【发布时间】:2012-02-14 22:49:34
【问题描述】:
(编辑:我尝试了一个示例,该示例仅绘制了一个没有任何纹理或着色器的三角形,并且我的设备上只有 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) 并且与背景渐变相反。我制作这张图片只是为了测试纹理的准确性,在那里我发现了它不是很精确的问题。您必须放大才能找出差异,这也是我发布放大图像的原因。注意:坐标与上面发布的代码不同,但问题是一样的(我尝试了不同的屏幕坐标,问题仍然存在)。
【问题讨论】:
-
截屏可以很好地显示问题,但从您写的内容来看,我怀疑它是dithering。这是一个后处理,所以它不会影响您的像素着色器。
-
您好,感谢您的回复,我添加了一张图片以更好地显示问题。我也不认为这仅仅是一个后处理错误,因为我在着色器中进行了一些计算并且预期值是关闭的,并指出这是问题所在。
-
我作为一个 Android 笨蛋问:有没有什么方法可以使用 PenTile 显示器并读取从实际显示元素计算出来的颜色?
-
它是具有普通 tft 的索尼设备(可以是 ips、mva 甚至是超级 tft,因为它具有相对较好的视角并且不会像普通 tn 面板那样反转颜色)我不不认为它是一个带有 pentile 矩阵的显示器。我使用我认为直接在内存缓冲区上工作的 eclipse DDMS 截取屏幕截图。我认为如果有任何与 pentile 相关的更改,它们不应该处于那个级别。但我不确定。
-
不仅线条附近有“抗锯齿”效果,整个背景也是一个水平渐变(从37 -> 44)。在源纹理中应该是这样的吗?
标签: java android opengl-es textures