繁体   English   中英

为什么Android上的OpenGL ES 2.0中的像素颜色不正确?

[英]Why are the pixel colors not correct in OpenGL ES 2.0 on Android?

(编辑:我尝试了一个只绘制三角形的样本,没有任何纹理或着色器,只有我的设备上的OpenGL-ES 1.1,并且可以看到相同的工件。我在模拟器中尝试了相同的样本,并且根本没有任何工件。这可能是Tegra 2问题还是我需要设置特定的状态或模拟器中不需要的东西?)

我在屏幕上渲染一个像素正确的正方形但是当我制作一个屏幕抓取并查看像素时,它们中的一些稍微偏离了像防褪色或过滤或类似的东西。 您只能在放大它们时看到它,但这不是重点。 我想在像素着色器中做一些数学运算,如果像素略微偏离,那对我没有好处。 我需要它们就像我放入的位图一样。

这是一个问题的放大屏幕。 在白线周围,暗值比它们应该略微亮一些:

在此输入图像描述

我已经尝试过:

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

但它没有效果。 像素略微偏离。 它很容易在黑暗和白色像素之间看到,因为它旁边的暗像素略微更亮,并且用绘画程序检查r,g,b值也显示了我。

有人可以帮我这个吗?

更多信息:

我的设备的CPU是Tegra 2.0。 我将256x256正方形渲染为256x256像素(我通过使用eclipse DDMS获取屏幕来检查)。 透明度关闭,位图的每个像素的alpha值为255。 我使用alpha创建了表面为32位表面:

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

我简化了代码,但在使用以下着色器渲染时仍然可以看到问题:

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

和命令:

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:如果没有极端放大,那么轻微的颜色变化并不是真的可见,但我想用数值进行计算,这意味着它们必须精确。

编辑:我添加了全分辨率图像。 线条上的颜色应该从(0,0,0)到(255,255,255),并且与背景渐变相反。 我制作这个图像只是为了测试纹理的准确性,在那里我发现了它不是很精确的问题。 你必须放大,然后找出差异,这也是我发布放大图像的原因。 注意:坐标与上面发布的代码不同,但问题是相同的(我尝试了不同的屏幕坐标,问题仍然存在)。

在此输入图像描述

好的,我想我找到了解决方案。

正如我已经写过的那样,我使用eclipse DDMS制作了截图,这似乎导致了问题。 该屏幕截图不是确切的帧缓冲,但某种平滑/抗锯齿正在进行中。

这似乎不是DDMS本身的结果,但只是在我的实际设备上使用时才会出现。 当我尝试使用模拟器时,问题没有出现,所以可能是我的设备有一个pentile屏幕(它迄今为止仅在日本发布,我发现没有信息材料,所以确认或否认它,但它的索尼和索尼做了在设备中使用pentile显示器)或者它可能与tegra 2芯片有关,或者可能是在图像被传输时发生的某种压缩,或者可能是出于某种其他原因。

无论哪种方式,当我使用以下功能时,我可以保存绝对完美的截图,因为它需要OpenGL-ES 2.0 Framebuffer并将其保存到png文件中,然后我可以使用批处理文件轻松传输(“adb pull / mnt / sdcard / info / Testfile.txt“)并在我的计算机上查看:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM