我正在使用openGL 2.0开发Android应用程序。我必须使用着色器将位图图像显示为纹理。 从很多Internet教程中,我创建了一个GlRenderer.java类。在那里,位图图像成功显示为纹理。但要检查着色器的工作情况,当我替换" gl_FragColor = texture2D(sTexture,vTextureCoord);"在片段着色器中,对于" gl_FragColor = vec4(0.0,1.0,0.0,0.0);",输出屏幕上没有发生任何变化。实际上" vec4(0.0,1.0,0.0,0.0)"我猜应该显示绿屏。 为什么会这样?
下面的代码是我的变量和着色器代码。
private Square square; // the square
private Context context;
private int mTextureUniformHandle ;
private int mTextureCoordinateHandle;
private int mTextureDataHandle;
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-1.0f, -1.0f, 1.0f, // V1 - bottom left
-1.0f, 1.0f, 1.0f, // V2 - top left
1.0f, -1.0f, 1.0f, // V3 - bottom right
1.0f, 1.0f, 1.0f // V4 - top right
};
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
/** The texture pointer */
private int[] textures = new int[1];
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix; " +
"uniform mat4 uSTMatrix; " +
"attribute vec4 aPosition; " +
"attribute vec4 aTextureCoord; " +
"varying vec2 vTextureCoord; " +
"void main() { " +
" gl_Position = uMVPMatrix * aPosition; " +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy; " +
"} ";
private final String fragmentShaderCode =
"#extension GL_OES_EGL_image_external : require \n" +
"precision mediump float; " +
"varying vec2 vTextureCoord; " +
"uniform samplerExternalOES sTexture; " +
"void main() {" +
" ivec2 uv = ivec2(gl_FragCoord.xy) / ivec2(20); "+
"vec4 bg; "+
"if(mod(float(uv.x + uv.y),2.0)>0.0) {"+
" bg = vec4(0.3,0.3,0.3,1.0);"+
" }else{"+
" bg = vec4(1.0,1.0,1.0,1.0);"+
" }"+
"gl_FragColor = bg;"+
"}";
private int mProgram;
private int maPositionHandle;
private int muMVPMatrixHandle;
private float[] mProjMatrix = new float[16];
private float[] mVMatrix = new float[16];
public float mAngle;
private float[] mMMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
以下是onSurfaceCreated():
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
System.out.println("inside onSurfaceCreated");
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
ThisAppGlobals.textureBuffer=textureBuffer;
// Load the texture for the square
mTextureDataHandle=loadGLTexture(gl);
gl.glEnable(GLES20.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background
// Load/Compile shaders from shader source
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
System.out.println("vertexShader value : " +vertexShader);
System.out.println("fragmentShader value : " +fragmentShader);
// Create shader program object
mProgram = GLES20.glCreateProgram();
System.out.println("mProgram value : " +mProgram);
// Attach vertex and fragment shader to program
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
// Link shaders to create shader program
GLES20.glLinkProgram(mProgram);
// Get vertex shader variable reference
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
loadGLTexture()函数是:
private int loadGLTexture(GL10 gl) {
// TODO Auto-generated method stub
Bitmap tempBitmap = null;
if(ThisAppGlobals.created3DImage!=null)
{
System.out.println("Created3Dimage not null");
}
else
{
System.out.println("Created3Dimage is null");
}
try{
tempBitmap=ImageResizetoPO2(ThisAppGlobals.created3DImage);
}catch(NullPointerException e){
e.printStackTrace();
}
// generate one texture pointer
gl.glGenTextures(1, textures, 0);
// ...and bind it to our array
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
// create nearest filtered texture
gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
try{
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0,tempBitmap, 0);
}catch(NullPointerException e){
e.printStackTrace();
}
return textures[0];
}
其他使用的功能是:
private Bitmap ImageResizetoPO2(Bitmap created3dImage) {
// TODO Auto-generated method stub
int powWidth = getNextHighestPO2( ThisAppGlobals.screenWidth );
int powHeight = getNextHighestPO2( ThisAppGlobals.screenHeight );
Bitmap tempBitmap2 = null;
try{
tempBitmap2=Bitmap.createScaledBitmap(created3dImage, powWidth, powHeight, true);
}catch(NullPointerException e){
e.printStackTrace();
}
return tempBitmap2;
}
private int getNextHighestPO2(int n) {
// TODO Auto-generated method stub
n -= 1;
n = n | (n >> 1);
n = n | (n >> 2);
n = n | (n >> 4);
n = n | (n >> 8);
n = n | (n >> 16);
n = n | (n >> 32);
return n + 1;
}
loadShader()函数是:
private int loadShader(int type, String shaderCode) {
// TODO Auto-generated method stub
// Create shader object of appropriate type
int shader = GLES20.glCreateShader(type);
System.out.println("shader value : " +shader);
// Compile shader source
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
In the above code shader= GLES20.glCreateShader(type) is always returning zero.
onSurfaceChanged funstion是:
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
// Set viewport to new extents
GLES20.glViewport(0, 0, width, height);
// Compute aspect ratio for proper scaling
float ratio = (float) width / height;
// Create perspective projection matrix
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
// Set camera modelview matrix
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
// Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);
}
onDraw()函数是:
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// Clear frame and depth buffers
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Select shader program
GLES20.glUseProgram(mProgram);
// Attaches vertex buffer to shader
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 12, ThisAppGlobals.textureBuffer);
GLES20.glEnableVertexAttribArray(maPositionHandle);
// Compute local transformation (rotation) matrix
Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f);
// Add local transformation into modelview matrix
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
// Add modelview matrix to projection matrix
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
// Pass modelview-projection matrix to shader
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
draw(gl);
}
private void draw(GL10 gl) {
// TODO Auto-generated method stub
// bind the previously generated texture
gl.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
// Point to our buffers
gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
// Set the face rotation
gl.glFrontFace(GLES20.GL_CW);
// Point to our vertex buffer
gl.glVertexPointer(3, GLES20.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GLES20.GL_FLOAT, 0, textureBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
}