Android 上的 openGL ES 2 中纹理渲染不正确
Texture not rendering properly in openGL ES 2 on Android
我在 Android 上的 openGL ES 2 中渲染纹理时遇到问题。正在绘制图像,但从外观上看纹理未正确环绕。
我已经尝试了所有常用的方法来解决这个问题,但没有任何效果。
下面是其中一张图片的外观:
但是他们在屏幕上的样子是这样的:
忽略作为纹理一部分的黑色边框。
这是我的纹理 class:
public class HFTexture {
private int width;
private int height;
private int textureId;
private HFGame game;
private String textureFile;
public HFTexture(HFGame game, String textureFile) {
this.game = game;
this.textureFile = textureFile;
//load();
}
public void load() {
int[] texIds = new int[1];
GLES20.glGenTextures(1, texIds, 0);
textureId = texIds[0];
InputStream in;
try {
in = game.getFileManager().getAsset(textureFile);
Bitmap bitmap = BitmapFactory.decodeStream(in);
width = bitmap.getWidth();
height = bitmap.getHeight();
bind();
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 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_LINEAR);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
bitmap.recycle();
} catch(IOException ex) {
}
}
public void bind() {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
}
public void activate(HFShader shader, int texture) {
GLES20.glActiveTexture(texture);
bind();
GLES20.glUniform1i(shader.getHandle("sampler0"), 0);
}
public void delete() {
bind();
int[] textureIds = {textureId};
GLES20.glDeleteTextures(1, textureIds, 0);
}
}
这是我的顶点 class:
public class Vertices {
private FloatBuffer vertexBuffer;
private FloatBuffer normalBuffer;
private FloatBuffer texCoordBuffer;
private ShortBuffer indexBuffer;
private final int VERTEX_COUNT;
private final int VERTEX_STRIDE;
private final int VERTEX_SIZE = 3;
private final int NORMAL_STRIDE;
private final int NORMAL_SIZE = 3;
private final int TEXTURE_COORD_STRIDE;
private final int TEXTURE_COORD_SIZE = 2;
private final int INDEX_COUNT;
public Vertices(float[] vertices, float[] normals, float[] texCoords, short[] indices) {
VERTEX_STRIDE = VERTEX_SIZE * 4;
NORMAL_STRIDE = NORMAL_SIZE * 4;
TEXTURE_COORD_STRIDE = TEXTURE_COORD_SIZE * 4;
VERTEX_COUNT = vertices.length;
INDEX_COUNT = indices.length;
ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_COUNT * VERTEX_STRIDE);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
bb = ByteBuffer.allocateDirect(normals.length * NORMAL_STRIDE);
bb.order(ByteOrder.nativeOrder());
normalBuffer = bb.asFloatBuffer();
normalBuffer.put(normals);
normalBuffer.position(0);
bb = ByteBuffer.allocateDirect(texCoords.length * TEXTURE_COORD_STRIDE);
bb.order(ByteOrder.nativeOrder());
texCoordBuffer = bb.asFloatBuffer();
texCoordBuffer.put(texCoords);
texCoordBuffer.position(0);
bb = ByteBuffer.allocateDirect(indices.length * 2);
bb.order(ByteOrder.nativeOrder());
indexBuffer = bb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
public void bind(HFShader shader) {
int positionHandle = shader.getHandle("position");
int normalHandle = shader.getHandle("normal");
int texCoordHandle = shader.getHandle("texCoord");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(
positionHandle, VERTEX_SIZE,
GLES20.GL_FLOAT, false,
VERTEX_STRIDE, vertexBuffer);
GLES20.glEnableVertexAttribArray(normalHandle);
GLES20.glVertexAttribPointer(
normalHandle, NORMAL_SIZE,
GLES20.GL_FLOAT, false,
NORMAL_STRIDE, normalBuffer);
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
texCoordHandle, TEXTURE_COORD_SIZE,
GLES20.GL_FLOAT, false,
TEXTURE_COORD_STRIDE, vertexBuffer);
}
public void unbind(HFShader shader) {
int positionHandle = shader.getHandle("position");
int normalHandle = shader.getHandle("normal");
int texCoordHandle = shader.getHandle("texCoord");
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(normalHandle);
GLES20.glDisableVertexAttribArray(texCoordHandle);
}
public void draw() {
if(indexBuffer != null) {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, INDEX_COUNT, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
} else {
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_COUNT);
}
}
}
这是我的顶点数据:
float[] verts = {
-(width / 2f), (height / 2f), 0f, // index 0
-(width / 2f), -(height / 2f), 0f, // index 1
(width / 2f), -(height / 2f), 0f, // index 2
(width / 2f), (height / 2f), 0f // index 3
};
float[] norms = {
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f
};
float[] texCoords = {
0f, 1f,
0f, 0f,
1f, 0f,
1f, 1f
};
short[] indices = {
0,1,2,2,3,0
};
我也尝试过将钳位添加到边缘纹理参数,但这似乎没有帮助。我只是把顶点和纹理坐标放在错误的顺序还是我完全遗漏了什么?
您正在为纹理坐标设置顶点缓冲区而不是纹理坐标缓冲区:
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
texCoordHandle, TEXTURE_COORD_SIZE,
GLES20.GL_FLOAT, false,
TEXTURE_COORD_STRIDE, vertexBuffer); // <-- here
应该是:
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
texCoordHandle, TEXTURE_COORD_SIZE,
GLES20.GL_FLOAT, false,
TEXTURE_COORD_STRIDE, texCoordBuffer);
我在 Android 上的 openGL ES 2 中渲染纹理时遇到问题。正在绘制图像,但从外观上看纹理未正确环绕。
我已经尝试了所有常用的方法来解决这个问题,但没有任何效果。
下面是其中一张图片的外观:
但是他们在屏幕上的样子是这样的:
忽略作为纹理一部分的黑色边框。
这是我的纹理 class:
public class HFTexture {
private int width;
private int height;
private int textureId;
private HFGame game;
private String textureFile;
public HFTexture(HFGame game, String textureFile) {
this.game = game;
this.textureFile = textureFile;
//load();
}
public void load() {
int[] texIds = new int[1];
GLES20.glGenTextures(1, texIds, 0);
textureId = texIds[0];
InputStream in;
try {
in = game.getFileManager().getAsset(textureFile);
Bitmap bitmap = BitmapFactory.decodeStream(in);
width = bitmap.getWidth();
height = bitmap.getHeight();
bind();
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 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_LINEAR);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
bitmap.recycle();
} catch(IOException ex) {
}
}
public void bind() {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
}
public void activate(HFShader shader, int texture) {
GLES20.glActiveTexture(texture);
bind();
GLES20.glUniform1i(shader.getHandle("sampler0"), 0);
}
public void delete() {
bind();
int[] textureIds = {textureId};
GLES20.glDeleteTextures(1, textureIds, 0);
}
}
这是我的顶点 class:
public class Vertices {
private FloatBuffer vertexBuffer;
private FloatBuffer normalBuffer;
private FloatBuffer texCoordBuffer;
private ShortBuffer indexBuffer;
private final int VERTEX_COUNT;
private final int VERTEX_STRIDE;
private final int VERTEX_SIZE = 3;
private final int NORMAL_STRIDE;
private final int NORMAL_SIZE = 3;
private final int TEXTURE_COORD_STRIDE;
private final int TEXTURE_COORD_SIZE = 2;
private final int INDEX_COUNT;
public Vertices(float[] vertices, float[] normals, float[] texCoords, short[] indices) {
VERTEX_STRIDE = VERTEX_SIZE * 4;
NORMAL_STRIDE = NORMAL_SIZE * 4;
TEXTURE_COORD_STRIDE = TEXTURE_COORD_SIZE * 4;
VERTEX_COUNT = vertices.length;
INDEX_COUNT = indices.length;
ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_COUNT * VERTEX_STRIDE);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
bb = ByteBuffer.allocateDirect(normals.length * NORMAL_STRIDE);
bb.order(ByteOrder.nativeOrder());
normalBuffer = bb.asFloatBuffer();
normalBuffer.put(normals);
normalBuffer.position(0);
bb = ByteBuffer.allocateDirect(texCoords.length * TEXTURE_COORD_STRIDE);
bb.order(ByteOrder.nativeOrder());
texCoordBuffer = bb.asFloatBuffer();
texCoordBuffer.put(texCoords);
texCoordBuffer.position(0);
bb = ByteBuffer.allocateDirect(indices.length * 2);
bb.order(ByteOrder.nativeOrder());
indexBuffer = bb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
public void bind(HFShader shader) {
int positionHandle = shader.getHandle("position");
int normalHandle = shader.getHandle("normal");
int texCoordHandle = shader.getHandle("texCoord");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(
positionHandle, VERTEX_SIZE,
GLES20.GL_FLOAT, false,
VERTEX_STRIDE, vertexBuffer);
GLES20.glEnableVertexAttribArray(normalHandle);
GLES20.glVertexAttribPointer(
normalHandle, NORMAL_SIZE,
GLES20.GL_FLOAT, false,
NORMAL_STRIDE, normalBuffer);
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
texCoordHandle, TEXTURE_COORD_SIZE,
GLES20.GL_FLOAT, false,
TEXTURE_COORD_STRIDE, vertexBuffer);
}
public void unbind(HFShader shader) {
int positionHandle = shader.getHandle("position");
int normalHandle = shader.getHandle("normal");
int texCoordHandle = shader.getHandle("texCoord");
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(normalHandle);
GLES20.glDisableVertexAttribArray(texCoordHandle);
}
public void draw() {
if(indexBuffer != null) {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, INDEX_COUNT, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
} else {
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_COUNT);
}
}
}
这是我的顶点数据:
float[] verts = {
-(width / 2f), (height / 2f), 0f, // index 0
-(width / 2f), -(height / 2f), 0f, // index 1
(width / 2f), -(height / 2f), 0f, // index 2
(width / 2f), (height / 2f), 0f // index 3
};
float[] norms = {
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f
};
float[] texCoords = {
0f, 1f,
0f, 0f,
1f, 0f,
1f, 1f
};
short[] indices = {
0,1,2,2,3,0
};
我也尝试过将钳位添加到边缘纹理参数,但这似乎没有帮助。我只是把顶点和纹理坐标放在错误的顺序还是我完全遗漏了什么?
您正在为纹理坐标设置顶点缓冲区而不是纹理坐标缓冲区:
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
texCoordHandle, TEXTURE_COORD_SIZE,
GLES20.GL_FLOAT, false,
TEXTURE_COORD_STRIDE, vertexBuffer); // <-- here
应该是:
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
texCoordHandle, TEXTURE_COORD_SIZE,
GLES20.GL_FLOAT, false,
TEXTURE_COORD_STRIDE, texCoordBuffer);