纹理android示例
我正在使用OpenGLES,并尝试在我的projet上添加纹理正方形。 我设计了一个简单的我有纹理的方形课,我试着展示它。我的三角形在渲染类中调用。现在TexturedSquare类只显示一个空位图。纹理android示例
package com.example.nativecpp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class TexturedSquare {
private static int[] textureHandle;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec2 aPosition;\n" +
"attribute vec2 aTexPos;\n" +
"varying vec2 vTexPos;\n" +
"void main() {\n" +
" vTexPos = aTexPos;\n" +
" gl_Position = uMVPMatrix * vec4(aPosition.xy, 0.0, 1.0);\n" +
"}";
private final String fragmentShaderCode =
"precision mediump float;\n"+
"uniform sampler2D uTexture;\n" +
"varying vec2 vTexPos;\n" +
"void main(void)\n" +
"{\n" +
" gl_FragColor = texture2D(uTexture, vTexPos);\n" +
"}";
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private final int mProgram;
private int mPositionHandle;
private int mTexturePosHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
final int COORDS_PER_VERTEX = 4;
float squareCoords[] = {
-1.0f,-1.0f, 0.0f, 0.0f, // vertex 3
-1.0f, 1.0f, 0.0f, 1.0f, // vertex 1
1.0f,-1.0f, 1.0f, 0.0f, // vertex 2
1.0f, 1.0f, 1.0f, 1.0f, // vertex 0
}; // top right
private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.2f, 0.709803922f, 0.898039216f, 1.0f };
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public TexturedSquare() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
// prepare shaders and OpenGL program
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
}
public int loadTexture()
{
textureHandle = new int[1];
if (textureHandle[0] != -1)
{
GLES20.glGenTextures(1, textureHandle, 0);
int uTexture = GLES20.glGetAttribLocation(mProgram, "uTexture");
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
Bitmap bitmap = Bitmap.createBitmap(640, 480, conf); // this creates a MUTABLE bitmap
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
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);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
GLES20.glUniform1i(uTexture, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == -1)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
mTexturePosHandle = GLES20.glGetAttribLocation(mProgram, "aTexPos");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
MyGLRenderer.checkGlError("glGetUniformLocation");
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, 2,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glEnableVertexAttribArray(mTexturePosHandle);
GLES20.glVertexAttribPointer(
mPositionHandle, 2,
GLES20.GL_FLOAT, false,
vertexStride, (vertexBuffer.position(2)));
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
// Draw the square
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
我的程序崩溃与错误:
FATAL EXCEPTION: GLThread 6633
Process: com.example.nativecpp, PID: 3281
java.lang.RuntimeException: glGetUniformLocation: glError 1282
at com.example.nativecpp.MyGLRenderer.checkGlError(MyGLRenderer.java:198)
at com.example.nativecpp.TexturedSquare.draw(TexturedSquare.java:179)
at com.example.nativecpp.MyGLRenderer.onDrawFrame(MyGLRenderer.java:118)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1553)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1253)
似乎有在我的索引顶点位置的错误,但我不解决这个问题。
编辑: 我仍然有相同的错误:出现
MyGLRenderer: glGetUniformLocation: glError 1282
错误之后:
GLES20.glVertexAttribPointer(
mPositionHandle, 2,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
MyGLRenderer.checkGlError("glGetUniformLocation"); ####ERROR!!!
编辑2: 在该行: uTexture = GLES20.glGetAttribLocation(mProgram ,“uTexture”); uTexture = -1我不认为这是正常的...所以我将其更改为
int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture");
现在uTexture等于1,但该计划仍然停留在GLES20.glUniform1i(uTexture, 0); //glGetUniformLocation: glError 1282
编辑3: 当我把这些线放在绘图函数中时:
int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glUniform1i(uTexture, 0);
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Draw the square
有没有错误...为什么? GPU没有足够的时间将数据放入内存中?
您意外地在位置属性中加载了纹理坐标。更改
GLES20.glVertexAttribPointer(
mPositionHandle, 2,
GLES20.GL_FLOAT, false,
vertexStride, (vertexBuffer.position(2)));
要
GLES20.glVertexAttribPointer(
mTexturePosHandle, 2,
GLES20.GL_FLOAT, false,
vertexStride, (vertexBuffer.position(2)));
几个显着的 “失误”:
你应该只得到属性位置一次,NIT每帧,因为它是一个costy功能。
如果纹理的编号为0
,那么您不会执行任何操作,但仍然有效,请检查编号为-1
的纹理。
链接着色器程序时可能会出现问题,ypu应检查它的链接状态是否有误,如果是,则记录输出glGetProgramInfoLog
。
谢谢我做了修改。 glGetProgramInfoLog向我发送一个空字符串:String LogInfo = GLES20.glGetProgramInfoLog(mProgram); –
@Xavier只有在链接失败时才使用。 –
好的抱歉,我认为错误来自loadTexture方法,因为当我删除它时,checkGlError不会向我发送错误。 –
'textureHandle [0]!= 0'具有id 0的纹理是完全有效的,您不应该检查此 –
您还将顶点数据加载到位置属性两次。 –