combine surface texture(external basically camera feed ) and ordinary texture - android

i am trying to combine surface texture(external basically camera feed ) and ordinary texture , when i run this the screen becomes black i tried in galaxy s5,s6 got the same results,searched online but couldn't find any resources for this,Any feedback is welcome.
shaders
private final String vertexShaderCodeCamera ="uniform mat4 uMVPMatrix;" +
"attribute vec4 position;" +
"attribute vec2 inputTextureCoordinate;" +
"varying vec2 textureCoordinate;" +
"attribute vec3 a_normal;"+ //new line
"varying vec3 v_normal;"+//new line
"uniform mat4 u_MVMatrix;" +
"void main()" +
"{" +
" gl_Position = uMVPMatrix * position;" +
"textureCoordinate = inputTextureCoordinate;" +
"v_normal = vec3(u_MVMatrix * vec4(a_normal, 0.0));"+
"}";
private final String fragmentShaderCodeCamera =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;" +
"varying vec2 textureCoordinate; \n" +
"uniform samplerExternalOES s_texture; \n" +
"uniform sampler2D Texture;" +
"void main(void) {" +
"gl_FragColor = texture2D(s_texture, textureCoordinate );\n" +
"gl_FragColor = texture2D(Texture, textureCoordinate);" +
"}";
camera draw method:
public void display_Camera(int texture){
GLES20.glUseProgram(cam_mProgram);
GLES20.glActiveTexture(GL_TEXTURE_EXTERNAL_OES);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
cam_mPositionHandle = GLES20.glGetAttribLocation(cam_mProgram, "position");
GLES20.glEnableVertexAttribArray(cam_mPositionHandle);
GLES20.glVertexAttribPointer(cam_mPositionHandle, CAM_COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStrideSquare, vertexBuffer);
cam_mTextureCoordHandle = GLES20.glGetAttribLocation(cam_mProgram, "inputTextureCoordinate");
GLES20.glEnableVertexAttribArray(cam_mTextureCoordHandle);
GLES20.glVertexAttribPointer(cam_mTextureCoordHandle, CAM_COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStrideSquare, textureVerticesBuffer);
cam_mColorHandle = 2;//GLES20.glGetAttribLocation(cam_mProgram, "s_texture");
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(cam_mPositionHandle);
GLES20.glDisableVertexAttribArray(cam_mTextureCoordHandle);
}
model draw method:
public void draw1(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(cam_mProgram);
// get handle to shape's transformation matrix
mPositionHandle = 0;//GLES20.glGetAttribLocation(cam_mProgram, "vPosition");
// get handle to vertex shader's vPosition member
mMVPMatrixHandle = GLES20.glGetUniformLocation(cam_mProgram, "uMVPMatrix");
MainActivity.checkGLError("glGetUniformLocation");
fsTexture = GLES20.glGetUniformLocation(cam_mProgram, "Texture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(fsTexture, 0);
vsTextureCoord = 1;//GLES20.glGetAttribLocation(cam_mProgram, "texCoord");
mNormalHandle = 3;//GLES20.glGetAttribLocation(cam_mProgram, "a_normal");//new line
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(vsTextureCoord, COORDS_PER_TEXTURE,
GLES20.GL_FLOAT, false,
TextureStride, texBuffer);
GLES20.glEnableVertexAttribArray(vsTextureCoord);
GLES20.glVertexAttribPointer(mNormalHandle, COORDS_PER_NORMAL, GLES20.GL_FLOAT, false,
12, normalbuffer);//new line
GLES20.glEnableVertexAttribArray(mNormalHandle);//new line
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
MainActivity.checkGLError("glUniformMatrix4fv");
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, tablelamp21NumVerts);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(vsTextureCoord);
GLES20.glDisableVertexAttribArray(mNormalHandle);
}
linking of shaders:
cam_mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
if (cam_mProgram != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(cam_mProgram, cameravertexShader);
// Bind the fragment shader to the program.
GLES20.glAttachShader(cam_mProgram, camerafragmentShader);
// Bind attributes
GLES20.glBindAttribLocation(cam_mProgram, 0, "position");
GLES20.glBindAttribLocation(cam_mProgram, 1, "inputTextureCoordinate");
GLES20.glBindAttribLocation(cam_mProgram, 2, "s_texture");//new line
GLES20.glBindAttribLocation(cam_mProgram, 3, "a_normal");//new line
// Link the two shaders together into a program.
GLES20.glLinkProgram(cam_mProgram);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(cam_mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(cam_mProgram);
cam_mProgram = 0;
}
}

Related

Overlay texture using GLES20 and apply rotation

I am working on a project in which I am using GLES20 to render a texture. I used GLUtils.texImage2D() to draw 2d texture image from the bitmap.
What do I need to implement to make these changes:
Place the texture to the right corner of the screen instead of stretching it to the full screen.
Provide incremental rotation frame by frame to the texture.
Shaders
private final static String FRAGMENT_SHADER =
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform lowp sampler2D sTexture;\n" +
"uniform lowp sampler2D oTexture;\n" +
"void main() {\n" +
" lowp vec4 textureColor = texture2D(sTexture, vTextureCoord);\n" +
" lowp vec4 textureColor2 = texture2D(oTexture, vTextureCoord);\n" +
" \n" +
" gl_FragColor = mix(textureColor, textureColor2, textureColor2.a);\n" +
"}\n";
protected static final String DEFAULT_VERTEX_SHADER =
"attribute highp vec4 aPosition;\n" +
"attribute highp vec4 aTextureCoord;\n" +
"varying highp vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_Position = aPosition;\n" +
"vTextureCoord = aTextureCoord.xy;\n" +
"}\n";
Texture Generation
int[] textures = new int[1];
#Override
public void setup() {
super.setup();// 1
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
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.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
}
#Override
public void onDraw() {
if (bitmap == null) {
return;
}
int offsetDepthMapTextureUniform = getHandle("oTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
if (bitmap != null && !bitmap.isRecycled()) {
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
}
GLES20.glUniform1i(offsetDepthMapTextureUniform, 3);
// Recycle the bitmap, since its data has been loaded into OpenGL.
releaseBitmap();
}
UPDATED
I added the mMVPMatrix for the texture transformation as suggested by alexrnov. Both, camera feed and overlay texture are rotating now.
protected static final String VERTEX_SHADER ="attribute highp vec4 aPosition;\n" +
"uniform mat4 uMVPMatrix;\n" +
"attribute highp vec4 aTextureCoord;\n" +
"varying highp vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_Position = uMVPMatrix * aPosition;\n" +
"vTextureCoord = aTextureCoord.xy;\n" +
"}\n";
#Override
public void onDraw() {
....
Matrix.setIdentityM(mvpMatrix, 0);
Matrix.rotateM(mvpMatrix, 0, rotation, 0.0f, 0.0f, 1.0f);
rotation++;
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMVPMatrixAsFloatBuffer(mvpMatrix));
...
}
The project structure is quite complicated. I can't write all the code here. Please refer the Github Project
Maybe there is another way, but you can overlay the texture on the rectangle, and apply transformations (movement/rotate) to this rectangle:
Vertex shader:
#version 100
uniform mat4 u_mvpMatrix; // MVP-matrix for moving and rotating texture
attribute vec4 a_position; // data of vertices rectangle
attribute vec2 a_textureCoordinates;
varying vec2 v_textureCoordinates;
void main() {
v_textureCoordinates = a_textureCoordinates;
gl_Position = u_mvpMatrix * a_position;
}
Fragment shader:
#version 100
varying vec2 v_textureCoordinates;
uniform sampler2D s_texture;
void main() {
gl_FragColor = texture2D(s_texture, v_textureCoordinates);
}
Approximate Java-code:
private final int textureID;
...
textureID = loadTexture(R.raw.texture);
...
#Override
public void draw() {
GLES20.glUseProgram(programObject);
GLES20.glEnableVertexAttribArray(positionLink);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO[0]);
GLES20.glVertexAttribPointer(positionLink, VERTEX_COMPONENT,
GLES20.GL_FLOAT, false, VERTEX_STRIDE, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glEnableVertexAttribArray(textureCoordinatesLink);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO[1]);
GLES20.glVertexAttribPointer(textureCoordinatesLink, TEXTURE_COMPONENT,
GLES20.GL_FLOAT, false, TEXTURE_STRIDE, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
GLES20.glUniform1i(samplerLink, 0);
GLES20.glUniformMatrix4fv(mvpMatrixLink, 1, false,
RectangleObject3D.getMVPMatrixAsFloatBuffer());
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, VBO[2]);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, NUMBER_INDICES,
GLES20.GL_UNSIGNED_INT, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glDisableVertexAttribArray(positionLink);
GLES20.glDisableVertexAttribArray(textureCoordinatesLink);
}
MVP-matrix:
import android.opengl.Matrix
protected val viewMatrix = FloatArray(16)
protected val projectionMatrix = FloatArray(16)
protected val modelMatrix = FloatArray(16)
protected val modelViewMatrix = FloatArray(16)
protected val mvpMatrix = FloatArray(16)
...
Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 0f,
0f, 0f, -4f, 0f, 1.0f, 0.0f) // camera
...
// parameters different for portrait and landscape orientation screen android
Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far)
...
fun spotPosition() { // invoke on every frame
Matrix.setIdentityM(modelMatrix, 0)
Matrix.translateM(modelMatrix, 0, x, y, z) // move object
Matrix.rotateM(modelMatrix, 0, angleX, 0.0f, 1.0f, 0.0f) // rotate object
Matrix.scaleM(modelMatrix, 0, 4f, 4f, 4f) // scale object
Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, modelMatrix, 0)
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, modelViewMatrix, 0)
}
fun getMVPMatrixAsFloatBuffer(): FloatBuffer = floatBuffer(mvpMatrix)
get FloatBuffer (essential in Java SDK):
public static FloatBuffer floatBuffer(float[] data) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4)
.order(ByteOrder.nativeOrder());
FloatBuffer returnBuffer = byteBuffer.asFloatBuffer();
returnBuffer.put(data).position(0);
return returnBuffer;
}

OPEN GL ES 2.0 - glGetAttribLocation returning -1 when using normals

My code:
public void draw1(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to shape's transformation matrix
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// get handle to vertex shader's vPosition member
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "a_normal");//new line
fsTexture = GLES20.glGetUniformLocation(mProgram, "Texture");
vsTextureCoord = GLES20.glGetAttribLocation(mProgram, "texCoord");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(fsTexture, 0);
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(vsTextureCoord, COORDS_PER_TEXTURE,
GLES20.GL_FLOAT, false,
TextureStride, texBuffer);
GLES20.glEnableVertexAttribArray(vsTextureCoord);
GLES20.glVertexAttribPointer(mNormalHandle, COORDS_PER_NORMAL, GLES20.GL_FLOAT, false,
12, normalbuffer);//new line
GLES20.glEnableVertexAttribArray(mNormalHandle);//new line
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, tablelamp21NumVerts);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(vsTextureCoord);
GLES20.glDisableVertexAttribArray(mNormalHandle);//new line
}
so i am getting a glGetUniformLocation: glError 1281 at MyGLRenderer.checkGlError("glGetUniformLocation"); code line
after debugging i found that my mNormalHandle is -1 i.e GLES20.glGetAttribLocation(mProgram, "a_normal"); is returning -1, even though i using it in the vertex shader and i am using GLES20.glBindAttribLocation(mProgram, 2, "a_normal"); before linking please help.
shaders code:
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"uniform mat4 u_MVMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec2 texCoord;" +
"attribute vec3 a_normal;"+ //new line
"varying vec3 v_normal;"+//new line
"varying vec2 texCoordOut;" +
"void main() {" +
" v_normal = vec3(u_MVMatrix * vec4(a_normal, 0.0));"+
" texCoordOut = texCoord;" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D Texture;" +
"varying vec2 texCoordOut;"+
"void main() {" +
" gl_FragColor = texture2D(Texture, texCoordOut);" +
"}";
Sorry to answer to an outdated question, but if that can help other developers: I think the GLSL compiler is pretty good to strip unused variables.
For example, with the follow vertex and fragment shader compiled with the OpenGL/ES driver of an Android emulator:
private val vertexShaderCode = """attribute vec4 in_position;
attribute vec2 in_texcoord;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
varying vec2 var_texcoord;
void main() {
var_texcoord = in_texcoord;
gl_Position = projection * view * model * in_position;
}
"""
private val fragmentShaderCode = """
precision mediump float;
varying vec2 var_texcoord;
uniform sampler2D texture;
uniform vec4 color;
void main() {
gl_FragColor = color;
}
"""
GLES20.glGetAttribLocation(program, "in_texcoord"); will return -1
Now if we use var_texcoord to compute the color in the fragment shader:
private val fragmentShaderCode = """
precision mediump float;
varying vec2 var_texcoord;
uniform sampler2D texture;
uniform vec4 color;
void main() {
gl_FragColor = texture2D(texture, var_texcoord);
}
"""
GLES20.glGetAttribLocation(program, "in_texcoord"); will return a valid id, > -1
Apparently the GLSL compiler can strip variable and varying variable, if they are not used, so it's seems possible that your a_normal variable is removed too.

glDrawArrays throws GL_INVALID_OPERATION exception for specific shader

I'm using open gl es on android to show video with black color substituted with transparent color. But when I use my specific shader GL_INVALID_OPERATION error code.
here is my shader:
protected final String mFragmentShader =
"#extension GL_OES_EGL_image_external : require\n" +
"uniform samplerExternalOES sTexture;\n" +
"varying vec2 vTextureCoord;\n" +
"vec4 color;\n" +
"\n" +
"void main(){\n" +
" color = texture2D(sTexture, vTextureCoord);\n" +
" if(color.r < 0.1 && color.g < 0.1 && color.b < 0.1){\n" +
" gl_FragColor = vec4(0.0,0.0,0.0,0.0);\n" +
" } else{\n" +
" gl_FragColor = color;\n" +
" }\n" +
"}";
When I use next shader - everything is being showed well(except transparency of course)
protected final String mFragmentShader =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
Here is my onDrawFrame code:
public void onDrawFrame(GL10 glUnused) {
if(!mMediaPlayer.isPlaying())
return;
synchronized (this) {
if (updateSurface) {
mSurface.updateTexImage();
mSurface.getTransformMatrix(mSTMatrix);
updateSurface = false;
}
}
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
GLES20.glFinish();
}
what can be the problem?
The problem was in float precision. When I set precision mediump float in first shader everything started working well
In your first shader you are using color.r when you should be using color.x and so on. The vec4 object is an object with members x,y,z,w

OpenGL ES 2.0 Not rendering correctly

This is supposed to render a cube. It looks like some parts of the rear faces are rendering in front of the ones closest to the camera. This happens even if I set it farther away. This is from my renderer:
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.setRotateM(mModelMatrix, 0, mAngle, 0f, 1f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
// Draw object
cube.draw(mMVPMatrix, context);
mAngle++;
}
and my object's draw method
public void draw(float[] mvpMatrix, Context context) {
GLES20.glUseProgram(mProgram);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(mTexHandle, 2,
GLES20.GL_FLOAT, false,
8, textureBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glEnableVertexAttribArray(mTexHandle);
GLES20.glActiveTexture ( GLES20.GL_TEXTURE0 );
GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, mTextureID);
GLES20.glUniform1i ( mSampler, 0 );
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexHandle);
}
and my shaders:
String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"uniform float u_offset; \n" +
"attribute vec4 a_position; \n" +
"attribute vec2 a_texCoord; \n" +
"varying vec2 v_texCoord; \n" +
"void main() \n" +
"{ \n" +
" gl_Position = uMVPMatrix * a_position; \n" +
" gl_Position.x += u_offset;\n" +
" v_texCoord = a_texCoord; \n" +
"} \n";
String fragmentShaderCode =
"precision mediump float; \n" +
"varying vec2 v_texCoord; \n" +
"uniform sampler2D s_texture; \n" +
"void main() \n" +
"{ \n" +
" gl_FragColor = texture2D(s_texture, v_texCoord); \n" +
"} \n";
and the result
Picture:
http://i.imgur.com/eWI2Uom.png
Thanks
Assuming you're using the depth buffer, you don't seem to be clearing it in your onDrawFrame function. Try:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
I'm not sure about Android-specific code as I program on iOS, but it's my understanding from reading "OpenGL ES 2.0 Programming Guide" (by Munshi et al.) that very little differs. Here's what my code looks like from a recent small project:
After setting up your framebuffer and color-renderbuffer, as you've already done, set up the depth buffer.
GLuint depthRenderbuffer;
GLint backingWidth, backingHeight;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
It's a good idea to include the part about setting the depthbuffer dimensions based off the color-renderbuffer, using glGetRenderbufferParameteriv(), because it ensures that no matter what, they're going to match.
One side note, on iOS it's recommended to setup the color-renderbuffer storage directly from the underlying iOS drawing layer, however in setting up the depth-renderbuffer it requires the call to glRenderbufferStorage() instead, as I've shown above.
You'll also want to include the following lines of code to your draw routine:
glClearDepthf(1.0);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
If you don't make the call to glEnable(GL_DEPTH_TEST), it seems to glitch at first and then work just fine, at least on my implementation in iOS. The glClearDepthf(1.0) clears it all the way to the far-plane, as opposed to a value of 0.0 which clears it to the front-plane.
It looks like you may have some Android-specific code, but hopefully this gets you off to the right start. Cheers!

Transparency shader fills transparent fragments with clear color

I'm trying to make transparent object in OpenGL ES 2.0.
It's a live wallpaper, I'm using GLWallpaperService as a base class for this.
I'm setting up OpenGL in this way:
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_GEQUAL);
GLES20.glClearDepthf(0.0f);
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
In Wallpaper initialization I set render mode:
setRenderMode(RENDERMODE_CONTINUOUSLY);
Shaders I use are taken from PowerVR sample OGLES2AlphaTest for alpha testing, which works fine on my HTC Desire device.
Here is the code for shaders:
private final String mVertexShader = "uniform highp mat4 uMVPMatrix;\n" +
"attribute highp vec4 aPosition;\n" +
"attribute highp vec2 aTextureCoord;\n" +
"varying mediump vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = aTextureCoord;\n" +
"}\n";
private final String mFragmentShader = "precision mediump float;\n" +
"varying mediump vec2 vTextureCoord;\n" +
"uniform sampler2D sTexture;\n" +
"void main() {\n" +
" vec4 base = texture2D(sTexture, vTextureCoord);\n" +
" if(base.a < 0.5){ discard; }\n" +
" gl_FragColor = base;\n" +
"}\n";
Code for rendering frame:
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
time = SystemClock.uptimeMillis();// % 4000L;
angle = 0.030f * ((int) time);
Matrix.setRotateM(mMMatrix, 0, angle, 0, 1.0f, 0);
Matrix.scaleM(mMMatrix, 0, 0.075f, 0.075f, 0.075f);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, numPolys);
checkGlError("glDrawArrays");
}
Resulting image of rendering: http://imgur.com/hNqm0.
But if I use
setRenderMode(RENDERMODE_WHEN_DIRTY);
for initializing wallpaper, I can get correct rendering, but only 1 still frame after I switch to some other activity and back to wallpaper. If I try to call requestRender() periodically I still get wrong transparency.
OK, I resolved it. It was caused by writing to depth buffer.

Categories

Resources