Why pixel colour is not accurate in OpenGL ES 2.0? - android

I am using EGLConfig with these specifications:
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_RENDERABLE_TYPE, 4,
EGL10.EGL_SAMPLE_BUFFERS, 1,
EGL10.EGL_SAMPLES, 4,
Shaders:
private final static String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final static String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
onSurfaceCreated:
GLES20.glClearColor(1f, 1f, 1f, 1f);
// Initialising shapes
onDrawFrame:
GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Drawing shapes
Actual problem is that shape colour is not solid and this happens for whole screen area (there are more brighter pixels):
Real colour is 0.55f, 0.8f, 0.3f.

OpenGL performs dithering on the rendering output by default. This is particularly noticeable when the output buffer has a relatively low color depth, like it is the case for RGB565 config your code requests.
To disable dithering, add this call while initializing your OpenGL state, e.g. in onSurfaceCreated():
GLES20.glDisable(GLES20.GL_DITHER);
The intention of dithering is of course to improve the visual quality. Unless you have a requirement for the output color to be completely accurate/uniform, leaving dithering enabled may give you better visual results.

Related

Opengles image skewed while rotate texture on Z axis

Hi I am developing an OpenGLES based android application, and I need rotate the texture on z-axis on real time. But the image skewed while I add a rotation to the model matrix.
The first image below is the original one, and the second one is the skewed image after rotation on z-axis.
Here are my shaders:
private final String mVertexShader = "" +
"attribute vec4 position;\n" +
"attribute vec2 textureCoordinate;\n" +
"varying vec2 textureCoordinateVarying;\n" +
"uniform mat4 modelMat;\n" +
"uniform mat4 viewMat;\n" +
"uniform mat4 projectionMat;\n" +
"" +
"void main() {\n" +
" gl_Position = projectionMat * viewMat * modelMat*position ;\n" +
" textureCoordinateVarying = textureCoordinate;\n" +
"}";
private final String mFragmentShader = "precision highp float;\n" +
"uniform sampler2D textureBackground;\n" +
"uniform sampler2D textureNumbers;" +
"varying highp vec2 textureCoordinateVarying;\n" +
"void main() {\n" +
" vec4 background = texture2D(textureBackground, textureCoordinateVarying);" +
" vec4 foreground = texture2D(textureNumbers, textureCoordinateVarying);" +
" gl_FragColor = mix(background, foreground, 0.2);\n" +
"}\n";
And with respect to projection, view and model matrix, here is their init function:
Matrix.setIdentityM(model, 0);
Matrix.setIdentityM(rotation, 0);
Matrix.setIdentityM(view, 0);
Matrix.setIdentityM(projection, 0);
Matrix.translateM(view, 0,0,0,-3.0f);
Matrix.perspectiveM(projection,0,45,(float)mBackground.getHeight()/(float)mBackground.getWidth(), 0.1f, 100f);
And in onDraw function, I will update the value of the model matrix;
public void onDrawFrame(GL10 gl) {
//some function
//update model matrix, and rotation is just a 4*4 identity matrix, and the degree is the z-axis rotation degree.
Matrix.setRotateM(rotation, 0, degree, 0, 0, 1);
Matrix.multiplyMM(model, 0, rotation, 0, model, 0);
Matrix.setIdentityM(rotation,0);
//draw my texture
}
I am pretty desperate now, any help will be highly appreciated.
It seems I have to kill this question on my own, actually I just made a stupid mistake, the ratio of projection matrix should be the width of surface view divided by the height of the same surface view, which should not be the ratio of your texture image width/height.

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.

Use Android 4x5 ColorMatrix in OpenGL ES 2 Shader

I am trying to use Android Color Matrix in OpenGL ES 2. I have been able to use a 4x4 Matrix using the following code in the Shader (this adds also an intensity parameter):
varying vec2 textureCoordinate;
uniform lowp mat4 colorMatrix;
uniform lowp float intensity;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 outputColor = textureColor * colorMatrix;
gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
}
But i am struggling on how i could convert Android 4x5 matrix to a vec4 matrix usable in the shader. I am not interested in Alpha channel.
The most direct approach is probably to split the ColorMatrix into a mat4 and a vec4, where the mat4 contains the multipliers for the input components, and the vec4 the constant offsets.
One detail to watch out for is the order of the matrix elements in memory. OpenGL uses column major storage, where the ColorMatrix appears to be in row major order. But it looks like you're already correcting for this discrepancy by multiplying the input vector from the right in the shader code.
The shader code will then look like this:
uniform lowp mat4 colorMatrix
uniform lowp vec4 colorOffset;
...
vec4 outputColor = textureColor * colorMatrix + colorOffset;
In the Java code, say you have a ColorMatrix named mat:
ColorMatrix mat = ...;
float[] matArr = mat.getArray();
float[] oglMat = {
matArr[0], matArr[1], matArr[2], matArr[3],
matArr[5], matArr[6], matArr[7], matArr[8],
matArr[10], matArr[11], matArr[12], matArr[13],
matArr[15], matArr[16], matArr[17], matArr[18]};
// Set value of colorMatrix uniform using oglMat.
float[] oglOffset = {matArr[4], matArr[9], matArr[14], matArr[19]};
// Set value of colorOffset uniform using oglOffset.

OpenGL ES 2.0 dynamic texture not working

I'm very new to Android, Eclipse, and OpenGL ES 2.0 (and object oriented programming in general), but I got a program (basically, based on a few examples I found on the Internet) working to show a cube with each face displaying a different 512 x 512 bitmap image (a PNG image loaded and converted once during the initialization phase) a few days ago.
My system is a 32-bit Vista PC, and I've been using Bluestacks as my emulator (version 0.8.11, released June 22, 2014, Android version 4.0.4). I believe its API level is 15. I have no physical Android devices to test my programs on at this time.
I now want to try a technique to use a dynamic texture.
I've looked for complete Android app examples using a dynamic texture (in Java), but I found only one and when I run it, it doesn't work on my Bluestacks.
Here's the page that has a link to the complete project containing the program:
http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/
When I run it on my Bluestacks, all I see is a black screen.
One thing I noticed is that the texture size is huge. I changed the size to 512 x 512 (which I know works because my cube program uses 512 x 512 textures), but I still see only a black screen.
(It would be nice if somebody could try to run this program on his/her physical Android device/s and/or Bluestacks and post the result.)
The following is the method in which a dynamic texture is created and prepared for its use:
/**
* Sets up the framebuffer and renderbuffer to render to texture
*/
private void setupRenderToTexture() {
fb = new int[1];
depthRb = new int[1];
renderTex = new int[1];
// generate
GLES20.glGenFramebuffers(1, fb, 0);
GLES20.glGenRenderbuffers(1, depthRb, 0);
GLES20.glGenTextures(1, renderTex, 0);
// generate color texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]);
// parameters
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);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_LINEAR);
// create it
// create an empty intbuffer first?
int[] buf = new int[texW * texH];
texBuffer = ByteBuffer.allocateDirect(buf.length
* FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asIntBuffer();;
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texW, texH, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_SHORT_5_6_5, texBuffer);
// create render buffer and bind 16-bit depth buffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, texW, texH);
/*** PART BELOW SHOULD BE DONE IN onDrawFrame ***/
// bind framebuffer
/*GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex[0], 0);
// attach render buffer as depth buffer
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRb[0]);
// check status
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);*/
}
Does the above piece of code seem sound?
Oh, one more thing:
I've been using the following as my vertex and fragment shaders. They've been working fine to show a cube with static textures. (Normal's data are read but I'm not using any lights now.)
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 a_Position;" +
"attribute vec4 a_Color;" +
"attribute vec3 a_Normal;" +
"attribute vec2 a_TexCoordinate;" + // Per-vertex texture coordinate information we will pass in.
"varying vec4 v_Color;" +
"varying vec2 v_TexCoordinate;" + // This will be passed into the fragment shader.
"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.
" gl_Position = uMVPMatrix * a_Position;" +
" v_Color = a_Color;" +
" vec3 difuse = a_Normal;" +
" v_TexCoordinate = a_TexCoordinate;" + // pass through
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D u_Texture;" + // The input texture.
"varying vec4 v_Color;" +
"varying vec2 v_TexCoordinate;" + // Interpolated texture coordinate per fragment.
"void main() {" +
" gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));" +
"}";
Should they work when I render to a texture? Or do I have to have separate vertex and fragment shaders when I'm rendering to a texture?
Thank you.

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!

Categories

Resources