纹理不绘制
Texture doesn't draw
我想在屏幕上绘制图像,但得到的是黑色方块,上面没有纹理。图像路径正确并已加载,因为矩形的大小正确。我有一个单独的 class 用于加载名为 Texture 的纹理,还有一个 class 用于绘制名为 Sprite 的纹理。这是代码:
// Class Texture
public void loadFromResources(final Context context, int id) {
GLES20.glGenTextures(1, mTextureID, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), id, options);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
mSize = new Size(bmp.getWidth(), bmp.getHeight());
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
// Sprite class
public void setTexture(Texture texture) {
mTexture = texture;
Log.d("Sprite", mTexture.getSize().getWidth() + " " + mTexture.getSize().getHeight());
vertices = new float[] {
0.0f, 0.0f,
texture.getSize().getWidth(), 0.0f,
texture.getSize().getWidth(), texture.getSize().getHeight(),
0.0f, texture.getSize().getHeight() };
// The vertex buffer.
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// Create our UV coordinates.
uvs = new float[] {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
// The texture buffer
bb = ByteBuffer.allocateDirect(uvs.length * 4);
bb.order(ByteOrder.nativeOrder());
uvBuffer = bb.asFloatBuffer();
uvBuffer.put(uvs);
uvBuffer.position(0);
}
public void draw(float[] projectionMatrix) {
float[] scratch = new float[16];
float[] move = new float[16];
Matrix.setIdentityM(move, 0);
Matrix.translateM(move, 0, 10, 10, 0);
Matrix.multiplyMM(scratch, 0, projectionMatrix, 0, move, 0);
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 2,
GLES20.GL_FLOAT, false,
2 * 4, vertexBuffer);
// Get handle to texture coordinates location
int mTexCoordLoc = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
MyGLRenderer.checkGlError("glGetAttribLocation");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mTexCoordLoc);
MyGLRenderer.checkGlError("glEnableVertexAttribArray");
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
MyGLRenderer.checkGlError("glVertexAttribPointer");
// Get handle to shape's transformation matrix
int mtrxhandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, scratch, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
mTexture.useTexture();
// Get handle to textures locations
int mSamplerLoc = GLES20.glGetUniformLocation(mProgram, "s_texture" );
MyGLRenderer.checkGlError("glGetUniformLocation");
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i( mSamplerLoc, 0);
MyGLRenderer.checkGlError("glUniform1i");
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
}
// MyGLRenderer class
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
mTexture = new Texture();
mTexture.loadFromResources(context, R.drawable.hex);
mSprite = new Sprite(context);
mSprite.setTexture(mTexture);
编辑:
这是着色器:
// vert
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main() {
gl_Position = uMVPMatrix * vPosition;
v_texCoord = a_texCoord;
}
// frag
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
gl_FragColor = texture2D( s_texture, v_texCoord );
}
这是完整的 class 纹理:
public class Texture {
private final int[] mTextureID = new int[1];
private Size mSize = new Size(0,0);
public Texture() {
}
public Size getSize() { return mSize; }
public void loadFromResources(final Context context, int id) {
GLES20.glGenTextures(1, mTextureID, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), id, options);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
mSize = new Size(bmp.getWidth(), bmp.getHeight());
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
public void useTexture() {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
}
}
我发现了问题:在构造纹理 class 之前将下一行发布到 MyGLRenderer 之前,但现在我已经将它们添加到纹理 class 中的 glBindTexture() 和 texImage2D 之间:
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
我在使用相同的 open gl 命令时遇到了类似的问题,即我的纹理未被绘制(黑屏)。
为了在屏幕上渲染纹理,我还添加了一些额外的 open gl 命令以使用顶点着色器绘制纹理。
查看此项目以了解如何使用开放式 gl 顶点着色器
只需使用纹理句柄和适当的宽度和高度调用 renderTexture 方法即可解决您的问题
https://github.com/rsri/Pic2Fro/blob/b4fe69b44343dab2515c3fd6e769f3370bf31312/app/src/main/java/com/pic2fro/pic2fro/util/Util.java
我想在屏幕上绘制图像,但得到的是黑色方块,上面没有纹理。图像路径正确并已加载,因为矩形的大小正确。我有一个单独的 class 用于加载名为 Texture 的纹理,还有一个 class 用于绘制名为 Sprite 的纹理。这是代码:
// Class Texture
public void loadFromResources(final Context context, int id) {
GLES20.glGenTextures(1, mTextureID, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), id, options);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
mSize = new Size(bmp.getWidth(), bmp.getHeight());
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
// Sprite class
public void setTexture(Texture texture) {
mTexture = texture;
Log.d("Sprite", mTexture.getSize().getWidth() + " " + mTexture.getSize().getHeight());
vertices = new float[] {
0.0f, 0.0f,
texture.getSize().getWidth(), 0.0f,
texture.getSize().getWidth(), texture.getSize().getHeight(),
0.0f, texture.getSize().getHeight() };
// The vertex buffer.
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// Create our UV coordinates.
uvs = new float[] {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
// The texture buffer
bb = ByteBuffer.allocateDirect(uvs.length * 4);
bb.order(ByteOrder.nativeOrder());
uvBuffer = bb.asFloatBuffer();
uvBuffer.put(uvs);
uvBuffer.position(0);
}
public void draw(float[] projectionMatrix) {
float[] scratch = new float[16];
float[] move = new float[16];
Matrix.setIdentityM(move, 0);
Matrix.translateM(move, 0, 10, 10, 0);
Matrix.multiplyMM(scratch, 0, projectionMatrix, 0, move, 0);
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 2,
GLES20.GL_FLOAT, false,
2 * 4, vertexBuffer);
// Get handle to texture coordinates location
int mTexCoordLoc = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
MyGLRenderer.checkGlError("glGetAttribLocation");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mTexCoordLoc);
MyGLRenderer.checkGlError("glEnableVertexAttribArray");
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
MyGLRenderer.checkGlError("glVertexAttribPointer");
// Get handle to shape's transformation matrix
int mtrxhandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, scratch, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
mTexture.useTexture();
// Get handle to textures locations
int mSamplerLoc = GLES20.glGetUniformLocation(mProgram, "s_texture" );
MyGLRenderer.checkGlError("glGetUniformLocation");
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i( mSamplerLoc, 0);
MyGLRenderer.checkGlError("glUniform1i");
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
}
// MyGLRenderer class
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
mTexture = new Texture();
mTexture.loadFromResources(context, R.drawable.hex);
mSprite = new Sprite(context);
mSprite.setTexture(mTexture);
编辑: 这是着色器:
// vert
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main() {
gl_Position = uMVPMatrix * vPosition;
v_texCoord = a_texCoord;
}
// frag
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
gl_FragColor = texture2D( s_texture, v_texCoord );
}
这是完整的 class 纹理:
public class Texture {
private final int[] mTextureID = new int[1];
private Size mSize = new Size(0,0);
public Texture() {
}
public Size getSize() { return mSize; }
public void loadFromResources(final Context context, int id) {
GLES20.glGenTextures(1, mTextureID, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), id, options);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
mSize = new Size(bmp.getWidth(), bmp.getHeight());
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
public void useTexture() {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
}
}
我发现了问题:在构造纹理 class 之前将下一行发布到 MyGLRenderer 之前,但现在我已经将它们添加到纹理 class 中的 glBindTexture() 和 texImage2D 之间:
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
我在使用相同的 open gl 命令时遇到了类似的问题,即我的纹理未被绘制(黑屏)。
为了在屏幕上渲染纹理,我还添加了一些额外的 open gl 命令以使用顶点着色器绘制纹理。
查看此项目以了解如何使用开放式 gl 顶点着色器 只需使用纹理句柄和适当的宽度和高度调用 renderTexture 方法即可解决您的问题 https://github.com/rsri/Pic2Fro/blob/b4fe69b44343dab2515c3fd6e769f3370bf31312/app/src/main/java/com/pic2fro/pic2fro/util/Util.java