Why are pixel colors not correct in OpenGL ES 2.0 on Android?

(Edit: I tried a sample that simply drew a triangle without texture or shaders and only OpenGL-ES 1.1 on my device and could see the same artifacts. I tried the same sample in the emulator and there were no artifacts at all. Maybe Is this a Tegra 2 problem or do I need to set a specific state or something that is not needed in the emulator?)

I draw the correct square of the pixel on the screen, but when I do a screengrab and look at the pixel, some of them turn off a bit, like anti-virus or filtered, or something like that. You see this only when approaching them, but this is not the main thing. I want to do some math in the pixel shader, and if the pixels are off a bit, and that is not good for me. I need them just like in the bitmap in which I put them.

Here is an enlarged screengrab problem. Around the white line, the dark values ​​are slightly brighter than they should be:

enter image description here

I already tried:

GLES20.glDisable(GLES20.GL_DITHER); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST ); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST ); 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 ); 

but it did not affect. Pixels turn off slightly. It is easy to see between the dark and white pixels, because the dark pixel next to it is slightly brighter, and checking the r, g, b values ​​with a paint program also shows me this.

Can someone help me with this?

Additional Information:

My device processor is Tegra 2.0. I render a 256x256 square exactly at 256x256 pixels (I checked this by taking a screen capture using Eclipse DDMS). Transparency is off, and the bitmap has an alpha value of 255 for each pixel. I created the surface as a 32-bit surface with alpha:

  glSurface.setEGLConfigChooser(8, 8, 8, 8, 0, 0); 

I simplified the code, but still see a problem when rendering with the following shaders:

  String vshaderquad = "attribute vec4 a_pos; \n" + // in position "attribute vec2 a_tex; \n" + // in Texture coordinates "varying vec2 vtex; \n" + // out Texture coordinates "void main(void) { \n" + " gl_Position = vec4(a_pos); \n" + " vtex = a_tex; \n" + "}"; String fshaderquad = "precision mediump float; \n" + "varying vec2 vtex; \n" + "uniform sampler2D samp0; \n" + "void main() { \n" + " gl_FragColor = texture2D(samp0, vtex); \n" + "}"; 

and commands:

 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mapid[0]); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST ); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST ); 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.glUniform1i(handlesampler0, 0); GLES20.glDisable(GLES20.GL_DITHER); GLES20.glViewport(0, 0, screenx, screeny); float screenx = (float)ddimx; float screeny = (float)ddimy; // vdata.put(0*4+0, 0.0f * (2.0f/screenx)); vdata.put(0*4+1, 256.0f * (2.0f/screeny)); vdata.put(0*4+2, 0.0f * (1.0f/256f)); vdata.put(0*4+3, 256.0f * (1.0f/256f)); // vdata.put(1*4+0, 0.0f * (2.0f/screenx)); vdata.put(1*4+1, 0.0f * (2.0f/screeny)); vdata.put(1*4+2, 0.0f * (1.0f/256f)); vdata.put(1*4+3, 0.0f * (1.0f/256f)); // vdata.put(2*4+0, 256.0f * (2.0f/screenx)); vdata.put(2*4+1, 256.0f * (2.0f/screeny)); vdata.put(2*4+2, 256.0f * (1.0f/256f)); vdata.put(2*4+3, 256.0f * (1.0f/256f)); // vdata.put(3*4+0, 256.0f * (2.0f/screenx)); vdata.put(3*4+1, 0.0f * (2.0f/screeny)); vdata.put(3*4+2, 256.0f * (1.0f/256f)); vdata.put(3*4+3, 0.0f * (1.0f/256f)); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 

PS: A slight color change is not really noticeable without extreme scaling, but I want to do calculations with values, which means that they just have to be accurate.

Edit: I added a full resolution image. The colors on the lines should go from (0,0,0) to (255,255,255) and are inverse to the background gradient. I made this image only to check the accuracy of the texture, and there I found that the problem is not very accurate. You must zoom in, though, to make out the differences, so I posted a larger image. Note. The coordinates are different from the code above, but the problem is the same (I tried different screen coordinates, and the problem persists).

enter image description here

+6
source share
1 answer

Ok, I think I found a solution.

As I already wrote, I took a screenshot with eclipse DDMS and the problem seems to be causing it. This screenshot is not an exact framebuffer, but there is smoothing / smoothing.

This does not seem to be the result of DDMS itself, but it seems to only happen when used on my real device. When I tried this with the emulator, the problem did not arise, so it may happen that my device has a pentlic screen (it has only been released in Japan so far, and I have not found any information materials confirming or denying it, but its sleepyheads and Sony use pentile displays in devices), or maybe it's due to the tegra 2 chip, or maybe some kind of compression that happens when transmitting the image, or maybe for some other reason.

In any case, when I use the following function, I can save screenshots that are absolutely perfect, since it uses the OpenGL-ES 2.0 framebuffer and saves it to a png file, which I can then easily transfer using a batch file ("adb pull / mnt / sdcard / info / Testfile.txt ") and view on my computer:

 public boolean SaveFrameBuffer(int x, int y) { try { IntBuffer pinbuffer = IntBuffer.allocate(x*y*4); IntBuffer poutbuffer = IntBuffer.allocate(x*y*4); int i,j,z; int [] pin = pinbuffer.array(); int [] pout = poutbuffer.array(); // GLES20.glReadPixels(0, 0, x, y, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pinbuffer); for(i=0;i<y;i++) { for(j=0;j<x;j++) { z = pin[(y-1-i)*x+j]; pout[i*x+j] = (z & 0xff000000) | ((z >> 16) & 0x000000ff) | ((z << 16) & 0x00ff0000) | (z & 0x0000ff00); } } Bitmap map = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888); map.setPixels(pout, 0, x, 0,0, x, y); OutputStream stream = new FileOutputStream("/sdcard/info/test.png"); map.compress(CompressFormat.PNG, 100, stream); stream.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } 
+3
source

Source: https://habr.com/ru/post/908476/


All Articles