Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的着色器中的GLSL纹理坐标不是线性的?_Java_Android_Opengl Es_Glsl_Textures - Fatal编程技术网

Java 为什么我的着色器中的GLSL纹理坐标不是线性的?

Java 为什么我的着色器中的GLSL纹理坐标不是线性的?,java,android,opengl-es,glsl,textures,Java,Android,Opengl Es,Glsl,Textures,我的Android 2.3.4 Tegra 2设备上的glsl着色器有问题 我想做一些计算,在glsl着色器中的片段着色器中创建纹理坐标,并注意到一个问题,试图缩小范围,因此制作了一个测试程序。我在屏幕上渲染了一个宽度为256像素到256像素的纹理,保存帧缓冲区并逐像素检查(与源比较),它正确渲染。根据opengl规范,当我使用从0.0到1.0的纹理坐标时,它应该对中心的每个像素进行采样(0.5/256、1.5/256、2.5/256等),这似乎是正确的 然后,我将x纹理坐标自身写入纹理,并检查

我的Android 2.3.4 Tegra 2设备上的glsl着色器有问题

我想做一些计算,在glsl着色器中的片段着色器中创建纹理坐标,并注意到一个问题,试图缩小范围,因此制作了一个测试程序。我在屏幕上渲染了一个宽度为256像素到256像素的纹理,保存帧缓冲区并逐像素检查(与源比较),它正确渲染。根据opengl规范,当我使用从0.0到1.0的纹理坐标时,它应该对中心的每个像素进行采样(0.5/256、1.5/256、2.5/256等),这似乎是正确的

然后,我将x纹理坐标自身写入纹理,并检查它们。结果有点不对劲,我不知道为什么。我没有得到我期望的0..255的梯度,而是得到了1..128128..255。这意味着跳过值0,值128出现两次,这意味着它们不是完全线性的。如果该值以任何方式四舍五入,那么就不是以我显而易见的方式。我还检查了纹理坐标的亚像素值,它们是我所期望的。其值始终为0.5/256,应为半个像素,并确保纹理在像素内正确采样

同样,使用这些坐标渲染的纹理正是我想要的,但坐标本身并不是我所期望的。这对我来说是一个问题,因为我想用计算出的纹理坐标进行渲染,尽管我以正确的方式计算它们,但结果纹理是错误的。我需要这些坐标到像素级,我不知道为什么它们是关闭的

有人知道是什么导致了这种行为,以及我如何纠正它吗

这是正确渲染纹理的片段着色器:

precision mediump   float;
varying vec2        vtex;
uniform sampler2D   samp0;
void main()     {
            gl_FragColor = texture2D(samp0, vtex);
        };
这是一个片段着色器,它创建了一个纹理坐标为1..128128..255而不是我预期的0..255的渐变:

precision mediump   float;
varying vec2        vtex;
uniform sampler2D   samp0;
void main()     {
            gl_FragColor = vec4(vtex.x, 0, 0, 1.0);
        };
这是一个片段着色器,它为纹理坐标的子像素值创建颜色,并按照我的预期提供具有所有值127的纹理,该纹理应为像素的中心:

precision mediump   float;
varying vec2        vtex;
uniform sampler2D   samp0;
void main()     {
            gl_FragColor = vec4(fract(vtex.x * 256.0), 0, 0, 1.0);
        };
其余的测试程序完全相同。我只更改着色器。以下是一些重要的代码片段:

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


//  Initialization

    GLES20.glUseProgram(shader);
    //  Vertex
    vdata.position(0);
    GLES20.glVertexAttribPointer(handlepos, 2, GLES20.GL_FLOAT, false, 4*4, vdata);
    GLES20.glEnableVertexAttribArray(handlepos);
    vdata.position(2);
    GLES20.glVertexAttribPointer(handletex, 2, GLES20.GL_FLOAT, false, 4*4, vdata);
    GLES20.glEnableVertexAttribArray(handletex);
    //  Texture
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, maplookupid[1]);
    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_REPEAT );
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT );
    GLES20.glUniform1i(handlesampler0, 0);
    GLES20.glDisable(GLES20.GL_DITHER);

//  Rendering

    GLES20.glViewport(0, 0, screenx, screeny);
    //
    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/256.0f));
    vdata.put(0*4+3,   256.0f * (1.0f/256.0f));
    //  
    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/256.0f));
    vdata.put(1*4+3,     0.0f * (1.0f/256.0f));
    //  
    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/256.0f));
    vdata.put(2*4+3,   256.0f * (1.0f/256.0f));
    //  
    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/256.0f));
    vdata.put(3*4+3,     0.0f * (1.0f/256.0f));

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

看起来你遇到了取整问题。由于您显然使用的是8位颜色缓冲区,因此颜色将通过乘以255转换为像素值。因此,纹理值0.5/256将乘以255,生成像素值0.498,在理想情况下(GPU上的无限精度计算和四舍五入到最近值)将转换为0字节值

事实上,从得到1..128128..255(128是重复值)的事实来看,它看起来像是将转换向上舍入(因为(127.5/256)*255是127.002,(128.5/256)*255是127.998——这两个像素转换为128)。如果是这样的话,我希望您的第三个测试程序在每个像素中产生128个,而不是127个(因为0.5*255==127.5)


结果是,您不能期望GPU进行非常精确的计算——舍入误差的来源很多。

您可能需要更改以下代码行:

precision mediump float;
致:


在片段着色器代码中。

尝试更改最接近GL_线的GL_,以获得答复。当我的第三个测试程序只返回127,但这也可能是因为一些舍入错误(不确定)。我桌面上的同一个着色器正在工作,并返回预期值。我能做些什么来达到预期的行为吗?我想用(字节值->8位精度)计算的纹理坐标索引纹理,但不确定如何计算它们以考虑舍入。
precision highp float;