2013-01-07 18 views
5

私はlibgdxとそのSpriteBatchクラスを使用してAndoidの2Dライブ壁紙を開発中です。これは腕時計なので、私が必要とするのは、libgdxから複数のテクスチャを描き、特定の角度に回転させるだけです。libgdx:Samsung Androidデバイスのフラグメントシェーダが正しく動作しない

SpriteBatchクラスを使用してこの問題を解決しましたが、すべて問題ありませんでした。

しかし、私は自分のシーンに拡大レンズ効果を追加する必要があります。特定の比率で特定の領域を拡大して、実際のレンズをシミュレートすることです。

私はFrameBufferにレンダリングし、FrameBufferからテクスチャ領域を取得し、SpriteBatchを使用してこの領域をカスタムシェーダで描画することで解決しました。

問題:サムスンのデバイス(私はギャラクシーノートN7000とギャラクシータブ10.1を試しました)では、倍率がわずかに増加する約16x16pxの拡大領域の中央に小さな矩形があります。申し訳ありませんが、私はサムスンのデバイスを持っていないので、今スクリーンショットを投稿できません。 他の端末ではすべて正常に動作し、HTC Vivid、Acer A500、Google Nexus Oneで試しました。

私はマリGPUのサムスンのデバイスに問題があるとは思いますが、それを修正する方法はわかりません。

私はここでAdd Fisheye effect to images at runtime using OpenGL ES をSpriteBatchするために、この質問からフラグメントシェーダコードを適応してきたが、それは次のようになります。

#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です。 マリはフラグメントシェーダで高精度の浮動小数点計算をサポートしていません。 中心から点までの距離が0に近いとき、変数はゼロになりました。

私は計算に一定の係数を追加しました。これがトリックでした。ここで

は、フラグメントシェーダを働いている:

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 'in shader'。私は何を取りこぼしたか? – Nolesh

+1

SpriteBatchがカスタムシェーダーに投影行列を一様に設定していない可能性があるためです。 ShaderProgram.pedantic = falseを設定して、シェーダー内のすべてのユニフォームのチェックを無効にすることができます。また、シェイダーをBuilderではなくSpriteBatchに直接設定してみてください。 参照: https://code.google.com/p/libgdx/issues/detail?id=1114 https://code.google.com/p/libgdx/issues/detail?id=555 –

+0

Ok 。私は後でそれを試してみる。しかし、時々このエラーは、あなたのシェーダに何か問題がある場合に発生します。 – Nolesh