安卓的OpenGL ES 2.0 - gl_FragCoord 和 gl_FragColor

3

经过几天的研究和测试,我终于成功实现了这本书中展示的片段着色器(一本非常好的书,我必须说):http://arcsynthesis.org/gltut/Basics/Tutorial%2002.html

它只是教你如何使用“gl_FragCoord.y”在片段着色器中渲染一个简单的三角形。

然而,在这些工作日里,我遇到了一些问题,我希望能更好地理解它们为什么会发生。

第一 - 在我的片段着色器中,如果我使用以下代码: gl_FragColor = vec4(gl_FragCoord.x/500.0, 0.0, 1.0, 1.0); 则三角形将被渲染。

但是如果我使用: gl_FragColor = vec4(gl_FragCoord.x/500, 0.0, 1.0, 1.0); 它就不会被渲染(我得到了一个黑屏,或者是在GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)中定义的任何颜色)。

这就引出了一个问题:在GLSL中,数字必须有小数点吗? 请注意,代码中唯一改变的是从500.0更改为500。

第二 - 我如何检索片段着色器代码中的变量值,以便例如在Toast中显示它们?让我解释一下这个问题。

使用以下三行代码:

float colorTwo[] = { 1.0f, 1.0f, 1.0f, 0.0f };

int mColorHandleTwo = GLES20.glGetUniformLocation(mProgram, "vColorTwo");

GLES20.glUniform4fv(mColorHandleTwo, 1, colorTwo, 0);

我能够获取这个“colorTwo”数组,并在片段着色器代码中使用它。 另一方面,如果我在片段着色器代码中有一个语句,例如:

float whatThisNumber = gl_FragCoord.y

我该如何获取这个浮点数并在Toast中显示它?

下面的代码实际上是我正在处理的代码:

public class TheShape {

    ByteBuffer myByteBuffer;
    FloatBuffer positionBufferObject;    

    int mProgram;   

    public TheShape() {

        float vertexPositions[] = { 

                 0.75f,  0.75f, 0.0f, 1.0f,
                 0.75f, -0.75f, 0.0f, 1.0f,
                -0.75f, -0.75f, 0.0f, 1.0f

        };

        myByteBuffer = ByteBuffer.allocateDirect(vertexPositions.length * 4);
        myByteBuffer.order(ByteOrder.nativeOrder());

        positionBufferObject = myByteBuffer.asFloatBuffer();
        positionBufferObject.put(vertexPositions);
        positionBufferObject.position(0);

        String vertexShaderCode =
                "attribute vec4 vPosition;" +
                "void main() {" +
                "  gl_Position = vPosition;" +
                "}";

        String fragmentShaderCode =
                "precision mediump float;" +
                "uniform vec4 vColor;" +
                "uniform vec4 vColorTwo;" +
                "void main() {" +
                "gl_FragColor = vec4(gl_FragCoord.x/500.0, 0.0, 1.0, 1.0);" +
         //ok   "gl_FragColor = mix(vColorTwo, vColor, (gl_FragCoord.y)/500.0);" +
         //ok   "gl_FragColor = vec4((gl_FragCoord.x)/500.0, (gl_FragCoord.y)/500.0, 0.0, 1.0);" + 
                "}";

        int myVertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(myVertexShader, vertexShaderCode);
        GLES20.glCompileShader(myVertexShader);

        int myFragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(myFragmentShader, fragmentShaderCode);
        GLES20.glCompileShader(myFragmentShader);

        mProgram = GLES20.glCreateProgram();

        GLES20.glAttachShader(mProgram, myVertexShader);        
        GLES20.glAttachShader(mProgram, myFragmentShader); 

        GLES20.glLinkProgram(mProgram);        

    }

    public void draw() {

        GLES20.glUseProgram(mProgram);

        GLES20.glEnableVertexAttribArray(0);
        GLES20.glVertexAttribPointer(0, 4, GLES20.GL_FLOAT, false, 0, positionBufferObject);



        float color[] = { 0.0f, 0.0f, 0.0f, 1.0f };  
        int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);


        float colorTwo[] = { 1.0f, 1.0f, 1.0f, 0.0f };  
        int mColorHandleTwo = GLES20.glGetUniformLocation(mProgram, "vColorTwo");
        GLES20.glUniform4fv(mColorHandleTwo, 1, colorTwo, 0);



        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

    }

}

我希望我的问题表达清楚了。

2个回答

2
  1. 在glsl语言中,整数不能自动转换为浮点数,因此代码行gl_FragColor = vec4(gl_FragCoord.x/500, 0.0, 1.0, 1.0);会导致编译错误。
  2. 您无法从Java代码(或C++代码)获取着色器变量的值。Java代码是由CPU执行的,而着色器是由GPU执行的。

希望对您有所帮助。


0

你的第一个问题是关于Java如何工作,与OpenGL本身无关。

如果你将一个整数除以另一个整数,你得到的结果也是一个整数。所以我猜测gl_FragCoord.x/500的结果是0.3之类的值,然后四舍五入为零。

如果你将一个整数除以一个浮点数(或双精度浮点数),你得到的结果就是一个浮点数(或双精度浮点数)。因此,当你除以500.0时,你会得到你期望的非零浮点数结果。你也可以通过使用500f来实现相同的效果。无论哪种方式,你都让编译器知道你正在使用一个浮点值,在这里显然非常重要。

至于你的第二个问题,我不认为你可以,尽管我很乐意被其他人纠正。


这与Java无关,实际上。GLSL由OpenGL实现(通常是显示驱动程序)编译,gl_FragCoord是一个浮点型的三分量向量。如果你从这个向量中取出一个分量(x),你会得到一个浮点型的标量。GLSL定义了整数类型到浮点型的隐式转换,当表达式中的一个操作数是浮点型时,整数类型会被自动转换为浮点型,所以这不应该是一个问题。我唯一能想到的是整数和浮点型之间精度的差异 - 如果整数大于尾数支持的范围,升级为浮点型时会发生精度损失。 - Andon M. Coleman
通常情况下,将整数500转换为浮点数不会成为主要问题,但OpenGL ES 2.0提供了三个浮点精度级别(片段着色器需要两个,一个是可选的)。例如,lowp浮点变量只能表示范围内的值:+/- 2.0。 - Andon M. Coleman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接