2013-01-07 83 views
5

我正在使用libgdx及其SpriteBatch類爲Andoid開發2D動態壁紙。這是一塊手錶,所以我只需要從libgdx繪製多個紋理,並將它們旋轉到特定的角度。libgdx:SpriteBatch,三星Android設備上的片段着色器工作不正確

我已經使用SpriteBatch類解決了這個問題,一切都很好。

但現在我需要在我的場景中添加放大鏡效果。任務是放大特定比例的特定區域以模擬真實鏡頭。

我已經通過渲染到FrameBuffer,從FrameBuffer獲取紋理區域,最後使用SpriteBatch使用自定義着色器繪製此區域來解決此問題。

問題:在三星設備上(我嘗試過銀河注意N7000和Galaxy Tab 10.1),在放大區域的中心有一個約16x16px的小矩形,放大比略有增加。抱歉,我現在無法發佈屏幕截圖,因爲我沒有三星設備。 在其他設備上的所有工作正常,在HTC Vivid,宏碁A500,谷歌Nexus One嘗試。

我想,這個問題如果在三星設備上的Mali GPU上,但是不知道,該如何解決。

我已經適應從這個問題片段着色器代碼SpriteBatch Add Fisheye effect to images at runtime using OpenGL ES 這裏是:

#ifdef GL_ES 
#define LOWP lowp 
precision mediump float; 
#else 
#define LOWP 
#endif 

varying LOWP vec4 v_color; 
varying vec2 v_texCoords; 
uniform sampler2D u_texture; 

void main() { 
vec2 m = vec2(0.622 , 0.4985); // lens center point, note that in live wallpaper center of texture is (0.5,0.5) 
float lensSize = 0.045; //diameter of lens 
float lensCut = 0.0342; //length of cut lines 

vec2 d = v_texCoords - m; 
float r = sqrt(dot(d, d)); // distance of pixel from mouse 
float cuttop = m.y + lensCut; 
float cutbottom = m.y - lensCut; 

vec2 uv; 
if (r >= lensSize) { 
    uv = v_texCoords; 
} else if (v_texCoords.y >= cuttop) { 
    uv = v_texCoords; 
} else if (v_texCoords.y <= cutbottom) { 
    uv = v_texCoords; 
} else { 
    uv = m + normalize(d) * asin(r)/(3.14159 * 0.37); 
} 

gl_FragColor = texture2D(u_texture, uv); 
} 

頂點着色器是SpriteBatch來源默認:

attribute vec4 a_position; 
attribute vec4 a_color; 
attribute vec2 a_texCoord0; 

uniform mat4 u_projTrans; 

varying vec4 v_color; 
varying vec2 v_texCoords; 

void main() { 
    v_color = a_color; 
    v_texCoords = a_texCoord0; 
    gl_Position = u_projTrans * a_position; 
} 

這裏是我的render()方法:

GL20 gl = Gdx.graphics.getGL20(); 
    gl.glEnable(GL20.GL_TEXTURE_2D); 
    gl.glActiveTexture(GL20.GL_TEXTURE0); 

    gl.glClearColor(WallpaperService.bg_red, WallpaperService.bg_green, WallpaperService.bg_blue, 1f); 
    gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 


    // Creating framebuffer, if it has gone 
    if (mFrameBuffer == null) { 
     mFrameBuffer = new FrameBuffer(Format.RGBA4444, BG_WIDTH, BG_HEIGHT, true); 

     mFrameBufferRegion = new TextureRegion(mFrameBuffer.getColorBufferTexture()); 
     mFrameBufferRegion.flip(false, true); 

    } 

    //Camera setting according to background texture 
    camera = new OrthographicCamera(BG_WIDTH, BG_HEIGHT); 
    camera.position.set(BG_WIDTH/2, BG_WIDTH/2, 0); 
    camera.update(); 
    batch.setProjectionMatrix(camera.combined); 

    //Rendering scene to framebuffer 
    mFrameBuffer.begin(); 
    batch.begin(); 
    //main Drawing goes here 
    batch.end(); 

    //Drawing frame to screen with applying shaders for needed effects 
    if (mFrameBuffer != null) { 
     mFrameBuffer.end(); 

     camera = new OrthographicCamera(width, height); 
     camera.position.set(width/2, height/2, 0); 
     camera.update(); 
     batch.setProjectionMatrix(camera.combined); 

     batch.begin(); 
     batch.setShader(null); 

     batch.setShader(shader); 

     batch.draw(mFrameBufferRegion, width/2 - (BG_WIDTH/2) + (MARGIN_BG_LEFT * ratio), height/2 
       - (BG_HEIGHT/2) + (MARGIN_BG_TOP * ratio), (float) BG_WIDTH/2, (float) BG_HEIGHT/2, 
       (float) BG_WIDTH, (float) BG_HEIGHT, (float) ratio, (float) ratio, 0f); 

     batch.setShader(null); 
     batch.end(); 
    } 

回答

3

我'已經設法解決這個問題。問題在馬裏gpu。 Mali不支持片段着色器中的高精度浮點計算。 當從中心到點的距離接近零時,r變量變爲零。

所以我給我的計算添加了常數係數,並且這樣做了。

這裏工作片段着色器:

precision mediump float; 

varying lowp vec4 v_color; 
varying vec2 v_texCoords; 


uniform sampler2D u_texture; 

const float PI = 3.14159; 
const float koef = 10.0; 
void main() { 
    vec2 uv;  
    vec2 m = vec2(0.622 , 0.4985); // lens center point, note that in live wallpaper center of texture is (0.5,0.5) 
    float lensSize = 0.045; //radius of lens 
    float lensCut = 0.0342; //height of cut 

    float cuttop = m.y + lensCut; 
    float cutbottom = m.y - lensCut; 
    float cutleft = m.x-lensSize; 
    float cutright = m.x+lensSize; 

//don't transform pixels, that aren't in lens area 
    if (v_texCoords.y >= cuttop) { 
     uv = v_texCoords; 
    } else if (v_texCoords.y <= cutbottom) { 
     uv = v_texCoords; 
      } else if (v_texCoords.x <= cutleft) { 
     uv = v_texCoords; 
      } else if (v_texCoords.x >= cutright) { 
     uv = v_texCoords; 
     } else { 
    vec2 p = v_texCoords*koef; //current point 
    vec2 d = p - m*koef; //vector differnce between current point and center point 
    float r = distance(m*koef,p); // distance of pixel from center 

    if (r/koef >= lensSize) { 
     uv = v_texCoords; 
     } else { 
    uv =m + normalize(d) * asin(r)/(PI*0.37*koef); 
    } 
    } 

    gl_FragColor = texture2D(u_texture, uv); 
} 
+1

我沒有複製粘貼你的頂點和片段着色器,並得到了在'SpriteBatch.begin'方法的錯誤:'java.lang.IllegalArgumentException異常:與名稱沒有統一的「 u_projTrans'着色器'。我錯過了什麼? – Nolesh

+1

原因可能是SpriteBatch沒有將投影矩陣統一到您的自定義着色器。您可以嘗試設置ShaderProgram.pedantic = false以禁止檢查着色器中的所有制服。另外嘗試直接將着色器設置爲SpriteBatch,而不是在構建器中。 請參閱: https://code.google.com/p/libgdx/issues/detail?id=1114 https://code.google.com/p/libgdx/issues/detail?id=555 –

+0

好的。我會稍後再嘗試。但是,如果着色器中出現錯誤,有時會出現此錯誤。 – Nolesh

相關問題