纹理单一颜色
English describe : android opengl textureview solid color
StackOverFlow推荐的错误排查
PS:(声明了属性,但没使用,debug时position为-1(测试时注意))
直接原因
纹理坐标赋值没有起效,实际上一直在重复纹理0,0坐标上的颜色
可能代码原因
- stackoverflow那个是属性赋值没有glEnableVertexAttribArray
- 对属性赋值时 VBO和FloatBuffer作为实参 两种方式不能混合使用
针对2的实验代码如下:
public class Triangle {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" v_TexCoordinate = a_TexCoordinate;" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision highp float;" +
"uniform vec4 vColor;" +
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate);" +
// " gl_FragColor = vColor;" +
"}";
private final int mProgram;
private int vbo_vertex_box;
private int vbo_coord_box;
private int mTextureDataHandle;
// Use to access and set the view transformation
private int mMVPMatrixHandle;
private FloatBuffer vertexBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = { // in counterclockwise order:
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};
final float[] cubeTextureCoordinateData = {
0f, 0f,
0f, 1f,
1f, 0f,
1f, 0f,
0f, 1f,
1f, 1f
};
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
/**
* Store our model data in a float buffer.
*/
private FloatBuffer mTextureBuffer;
private int mBytesPerFloat = 4;
private boolean useVbo = false;
public Triangle(Context context) {
// initialize vertex byte buffer for shape coordinates
int vertexShader = GlUtils.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = GlUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
mTextureDataHandle = GlUtils.loadTexture(context, R.drawable.real_solid);
if (useVbo) {
vbo_vertex_box = generateOneBuffer();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_vertex_box);
FloatBuffer cube_vertices_buffer = FloatBuffer.wrap(triangleCoords);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertices_buffer.limit() * 4,
cube_vertices_buffer, GLES20.GL_DYNAMIC_DRAW);
vbo_coord_box = generateOneBuffer();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_coord_box);
FloatBuffer coord_buffer = FloatBuffer.wrap(cubeTextureCoordinateData);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, coord_buffer.limit() * 4,
coord_buffer, GLES20.GL_DYNAMIC_DRAW);
} else {
vertexBuffer = (FloatBuffer) ByteBuffer.allocateDirect(triangleCoords.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer().put(triangleCoords).position(0);
mTextureBuffer = (FloatBuffer) ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer().put(cubeTextureCoordinateData).position(0);
}
}
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
GLES20.glUseProgram(mProgram);
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
int textureHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
if (useVbo) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_vertex_box);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT,
false, 3 * 4, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_coord_box);
GLES20.glEnableVertexAttribArray(textureHandle);
GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT,
false, 2 * 4, 0);
} else {
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
COORDS_PER_VERTEX * 4, vertexBuffer);
GLES20.glEnableVertexAttribArray(textureHandle);
GLES20.glVertexAttribPointer(textureHandle, 2,
GLES20.GL_FLOAT, false,
2 * 4, mTextureBuffer);
}
// get handle to fragment shader's vColor member
int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
private int generateOneBuffer() {
int[] buffer = {0};
GLES20.glGenBuffers(1, buffer, 0);
return buffer[0];
}
}
public class MyGlRenderer implements GLSurfaceView.Renderer {
private Triangle mTriangle;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
Context mContext;
public MyGlRenderer(Context context) {
mContext = context;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mTriangle = new Triangle(mContext);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f);
}
@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// mTriangle.draw();
mTriangle.draw(mMVPMatrix);
}
}
public class MyGlSurfaceView extends GLSurfaceView {
private MyGlRenderer mRender;
public MyGlSurfaceView(Context context) {
super(context);
init(context);
}
public MyGlSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
setEGLContextClientVersion(2);
mRender = new MyGlRenderer(context);
setRenderer(mRender);
setRenderMode(RENDERMODE_WHEN_DIRTY);
}
}
private GLSurfaceView mGlSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_surface_view);
initView();
}
private void initView() {
mGlSurfaceView = (GLSurfaceView) findViewById(R.id.surface_gl_view);
}