2013-01-07 3 views
5

libgdx 및 SpriteBatch 클래스를 사용하여 Andoid 2D 라이브 벽지를 개발 중입니다. 이것은 시계이므로 모든 것이 필요합니다. libgdx에서 여러 개의 텍스처를 그려서 특정 각도로 회전시킵니다.libgdx : Samsung Android 장치의 조각 쉐이더가 올바르게 작동하지 않습니다.

SpriteBatch 클래스를 사용하여이 문제를 해결했으며 모두 괜찮 았습니다.

하지만 지금은 돋보기 렌즈 효과를 내 장면에 추가해야합니다. 작업은 특정 비율로 특정 영역을 확대하여 실제 렌즈를 시뮬레이션하는 것입니다.

FrameBuffer로 렌더링하고 FrameBuffer에서 텍스처 영역을 가져온 다음 SpriteBatch를 사용하여이 영역을 사용자 정의 셰이더로 그려서 해결했습니다.

문제 : 삼성 기기 (갤럭시 노트 N7000과 갤럭시 탭 10.1)에서 배율이 약간 증가하는 약 16x16 픽셀의 확대 영역 중앙에 작은 사각형이 있습니다. 죄송합니다. 삼성 기기가 없기 때문에 지금 스크린 샷을 게시 할 수 없습니다. 다른 기기에서는 HTC Vivid, Acer A500, Google Nexus One에서 모두 정상적으로 작동합니다.

내 생각에 문제는 말리 GPU에서 삼성 기기에 있지만 모르겠지만이를 수정하는 방법입니다.

다음
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() 방법 :

#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 소스의 기본입니다 : 내가 여기 Add Fisheye effect to images at runtime using OpenGL ES 을의 SpriteBatch이 질문에서 조각 쉐이더 코드를 적용했습니다

가 있습니다 :

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

' 이 문제를 해결할 수있었습니다. 문제는 Mali gpu입니다. Mali는 프래그먼트 셰이더에서 고정밀 부동 계산을 지원하지 않습니다. 중심에서 점까지의 거리가 0에 가까울 때 - 변수가 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를 설정하여 셰이더의 모든 유니폼 검사를 비활성화 할 수 있습니다. 또한 셰이더를 빌더가 아닌 SpriteBatch에 직접 설정하십시오. 참조 : https://code.google.com/p/libgdx/issues/detail?id=1114 https://code.google.com/p/libgdx/issues/detail?id=555 –

+0

확인 . 나는 나중에 그것을 시도 할 것이다. 그러나 때로는이 오류는 쉐이더에 문제가있을 때 발생합니다. – Nolesh