Sto sviluppando un live wallpaper 2D per Andoid usando libgdx e la sua classe SpriteBatch. Questo è un orologio, quindi tutto ciò di cui ho bisogno, da libgdx è solo disegnare più trame, ruotandole a un angolo specifico.libgdx: SpriteBatch, framment shader su dispositivi Android Samsung funzionano in modo errato
Ho risolto questo problema utilizzando la classe SpriteBatch e tutto andava bene.
Ma ora ho bisogno di aggiungere l'effetto lente d'ingrandimento alla mia scena. Il compito è di ingrandire un'area specifica con un rapporto specifico per simulare l'obiettivo reale.
Ho risolto questo rendendo a FrameBuffer, ottenendo texture regione da FrameBuffer e, infine, disegnando questa regione con shader personalizzato, utilizzando SpriteBatch.
IL PROBLEMA: su dispositivi Samsung (ho provato su Galaxy Note N7000 e Galaxy Tab 10.1) c'è un piccolo rettangolo al centro dell'area di ingrandimento di circa 16x16px, dove il rapporto di ingrandimento aumenta leggermente. Spiacente, non posso pubblicare uno screenshot ora, perché non ho un dispositivo Samsung. Su altri dispositivi funziona tutto bene, provato in HTC Vivid, Acer A500, Google Nexus One.
Penso, il problema se in Mali GPU su dispositivi Samsung, ma non so, come risolverlo.
Ho adattato frammento di codice dello shader da questa domanda a SpriteBatch Add Fisheye effect to images at runtime using OpenGL ES Qui è esso:
#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);
}
vertex shader è di default da fonti 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;
}
Ecco il mio metodo 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();
}
ho copiato e incollare il vertex e fragment shader e ottenuto un errore in 'metodo SpriteBatch.begin':' java.lang.IllegalArgumentException: non uniforme con il nome ' u_projTrans 'in shader'. Cosa mi sono perso? – Nolesh
Probabilmente il motivo è che SpriteBatch non ha impostato la matrice di proiezione uniforme sullo shader personalizzato. Puoi provare a impostare ShaderProgram.pedantic = false per disabilitare il controllo di tutte le uniformi nello shader. Prova anche a impostare lo shader direttamente su SpriteBatch, non sul builder. Vedi: https://code.google.com/p/libgdx/issues/detail?id=1114 https://code.google.com/p/libgdx/issues/detail?id=555 –
Ok . Ci proverò più tardi. Ma a volte questo errore si verifica se qualcosa di sbagliato nel tuo shader. – Nolesh