5

libgdx とその SpriteBatch クラスを使用して、Andoid 用の 2D ライブ壁紙を開発しています。これは時計なので、必要なのは libgdx から複数のテクスチャを描画し、それらを特定の角度に回転させるだけです。

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

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

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

問題: Samsung デバイス (Galaxy Note N7000 と Galaxy Tab 10.1 で試しました) では、拡大領域の中央に約 16x16 ピクセルの小さな長方形があり、拡大率がわずかに増加します。申し訳ありませんが、Samsung デバイスを持っていないため、現在スクリーンショットを投稿できません。他のデバイスではすべて正常に動作し、HTC Vivid、Acer A500、Google Nexus One で試しました。

Samsung デバイスの 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();
    }
4

1 に答える 1

3

私はこの問題を解決することができました。問題はMali GPUにあります。Mali は、フラグメント シェーダーでの高精度 float 計算をサポートしていません。中心から点までの距離がゼロに近い場合、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);
}
于 2013-01-14T08:34:39.337 に答える