我正在使用OpenGL ES2.0 [ANdroid]在正方形上绘制纹理。纹理在垂直方向上无限滚动。
几帧后渲染质量下降非常快,纹理质量下降。
截图#1
屏幕截图#2
如何解决此问题?
代码:
package gamedev.soursugar.infinitescroll;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* Created by soursugar on 19/12/14.
*/
public class Background {
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec2 TexCoordIn;" +
"varying vec2 TexCoordOut;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
" TexCoordOut = TexCoordIn;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"uniform sampler2D TexCoordIn;" +
"uniform float scroll;" +
"varying vec2 TexCoordOut;" +
"void main() {" +
" gl_FragColor = texture2D(TexCoordIn, vec2(TexCoordOut.x, TexCoordOut.y + scroll));" +
"}";
private int[] textures = new int[1];
private byte[] indices = {
0, 1, 2,
0, 2, 3
};
private float[] texture = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
private float[] vertices = {
-1f, -1f, 0f,
-1f, 1f, 0f,
1f, 1f, 0f,
1f, -1f, 0f
};
private final FloatBuffer vertexBuffer;
private final ByteBuffer indexBuffer;
private final FloatBuffer textureBuffer;
private final int mProgram;
private int mPositionHandle;
private int mMVPMatrixHandle;
static final int COORDS_PER_VERTEX = 3;
static final int COORDS_PER_TEXTURE = 2;
private final int vertexStride = COORDS_PER_VERTEX * 4;
private final int textureStride = COORDS_PER_TEXTURE * 4;
private float scroll = 0.00f;
public Background() {
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.order(ByteOrder.nativeOrder());
indexBuffer.put(indices);
indexBuffer.position(0);
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexShader, vertexShaderCode);
GLES20.glCompileShader(vertexShader);
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, fragmentShaderCode);
GLES20.glCompileShader(fragmentShader);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
private void reloadVertexBuffer() {
vertexBuffer.put(vertices);
vertexBuffer.position(0);
}
public void loadTexture(int texture, Context context, int width, int height) {
Bitmap bitmap = null;
float w = 0.75f;
try{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled=false;
bitmap = BitmapFactory.decodeStream(context.getAssets().open("background.png"));
w = (1.0f/height)*width;
Log.d("Width", String.valueOf(w));
} catch (Exception e) {
Log.d("Exception from SourSugar", "Error in decoding stream");
}
vertices[0] = -w;
vertices[3] = -w;
vertices[6] = w;
vertices[9] = w;
reloadVertexBuffer();
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
public void draw(float[] mvpMatrix, int frameCount) {
//if(frameCount==25 || frameCount==50)
//scroll = 0f;
scroll -= 0.005f;
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
int vsTextureCoord = GLES20.glGetAttribLocation(mProgram, "TexCoordIn");
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(vsTextureCoord, COORDS_PER_TEXTURE, GLES20.GL_FLOAT, false, textureStride, textureBuffer);
GLES20.glEnableVertexAttribArray(vsTextureCoord);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
int fsTexture = GLES20.glGetUniformLocation(mProgram, "TexCoordOut");
int fsScroll = GLES20.glGetUniformLocation(mProgram, "scroll");
GLES20.glUniform1i(fsTexture, 0);
GLES20.glUniform1f(fsScroll, scroll);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_BYTE, indexBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
答案 0 :(得分:4)
问题与片段着色器中的这一行有关:
"gl_FragColor = texture2D(TexCoordIn, vec2(TexCoordOut.x, TexCoordOut.y + scroll));"
粗略地说,浮点数可以准确地表示小数字,也可以不准确地表示大数字。当您将两个浮点数加在一起时,结果通常会具有两者中较大幅度(不太准确)的精度。因此,当 scroll 的值过大时,纹理坐标(TexCoordOut.y + scroll)的精度会降低。
您可以通过更改Java代码来修复此问题,使您的滚动值环绕在0.0 - 1.0
的范围内scroll -= 0.005f;
if(scroll < 0.0f)
scroll += 1.0f;
由于你在T中进行纹理环绕,你可以丢弃整数部分,它不会有任何区别。