glDrawArrays throws GL_INVALID_OPERATION exception for specific shader - android

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

Related

Android/OpenGles drawing 2 external texture each taking half of the screen. Left and right half

I have successfully bind 2 external OES texture to my shader. Now I want each texture to take 1/2 of the screen(Left for one texture right for another). How do I go about doing it? Example:
http://vicceskep.hu/kepek/vicces_funny_007445.jpg
random image from google
Showing a full picture of each picture. It will be nice to have an efficient method to do it. The code that I am currently referencing from is the bikflake/ grafika code from github.
Visit http://bigflake.com/mediacodec/CameraToMpegTest.java.txt
To check the code out.
Okay I think i will really give in depth clarification for my question as I do not have much knowledge about 3d projections in open GL. Sorry for the numerous edits on the question.
This is my Vertex Shader code currently
private static final String VERTEX_SHADER =
// UMVPMATRIX IS AN IDENTITY MATRIX
"uniform mat4 uMVPMatrix;\n" +
//These are surfacetexture.getTransformationMatrix
"uniform mat4 uSTMatrixOne;\n" +
"uniform mat4 uSTMatrixTwo;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"varying vec2 vTextureCoordTwo;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
" vTextureCoordTwo = (uSTMatrixTwo* aTextureCoord).xy ;\n" +
"}\n";
This is my Fragment Shader code currently which does a overlay currently.
private static final String FRAGMENT_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" + // highp here doesn't seem to matter
"varying vec2 vTextureCoord;\n" +
"varying vec2 vTextureCoordTwo;\n" +
"uniform samplerExternalOES sTextureOne;\n" +
"uniform samplerExternalOES sTextureTwo;\n" +
"void main() {\n" +
" lowp vec4 pixelTop = texture2D(sTextureOne, vTextureCoord);\n" +
" lowp vec4 pixelBot = texture2D(sTextureTwo, vTextureCoordTwo);" +
" gl_FragColor = pixelTop + pixelBot;\n" +
"}\n";
As for the aPosition and the a texture coordinate it is currently referenced from. It would be nice if someone explained how mTraingleVerticesData works too.
private final float[] mTriangleVerticesData = {
// X, Y, Z, U, V
-1.0f, -1.0f, 0, 0.f, 0.f,
1.0f, -1.0f, 0, 1.f, 0.f,
-1.0f, 1.0f, 0, 0.f, 1.f,
1.0f, 1.0f, 0, 1.f, 1.f,
};
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, 2, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
My 2 external projection binding currently
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
//Cam Code
//Set texture to be active
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTwoTextureID);
You can do it the way #Sung suggested but conditional statements and loops in shaders, especialy fragment, are slow. It's better to render 2 different polygons.
Yea I finally got it.I used 2 different programs to draw and used mTriangleVerticesData to edit the image proportions and use gl_position to shift the image.

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

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;
}
}

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!

Not working OpenGL ES shader, call glLinkProgram every frame?

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);
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";
private int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
private int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
Code for rendering frame:
public void onDrawFrame(GL10 glUnused) {
//GLES20.glLinkProgram(mProgram);
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, 0, 1.0f);
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");
}
Without GLES20.glLinkProgram(mProgram); in the start of onDrawFrame() I get incorrect result (with incorrect transparency): http://imgur.com/kESeO
When I add GLES20.glLinkProgram(mProgram); in the start of onDrawFrame() it renders correctly, but the performance is bad, glLinkProgram() is time-consuming function. Here is screenshot of correct rendering: http://imgur.com/sw83z
Please explain what am I doing wrong, apparently I don't have to call glLinkProgram() on every frame redraw.
You don't need to link your program each frame, link it once and store its id somewhere. Then call GLES20.glUseProgram(_programId); before you issue drawing calls that correspond to that program.
Check this for an already implemented approach: https://github.com/TraxNet/ShadingZen/blob/master/library/src/main/java/org/traxnet/shadingzen/core/ShadersProgram.java (The bindProgram method is what you are after).
The cause of this misbehavior was not related to glLinkProgram(). I've modified some other GL init parameters (can't recall which at the moment) and now it works just fine.

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