适用于Android的OpenGL ES 2.0 - gl_FragCoord和gl_FragColor

时间:2013-11-03 13:56:37

标签: android opengl-es android-fragments

经过几天的大量研究和测试后,我终于能够实现这本书中出现的片段着色器(这是一本很好的书,我可以说):http://arcsynthesis.org/gltut/Basics/Tutorial%2002.html

它只讲授如何使用片段着色器渲染一个使用“gl_FragCoord.y”的简单三角形。

在这些工作日里,我遇到了一些我想更好理解的问题。

1st - 在我的片段着色器中,如果我使用代码: 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”数组并在Fragment Shader Code中使用它。 另一方面,如果我让片段着色器代码中的一个声明如下:

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 个答案:

答案 0 :(得分:2)

  1. 在glsl语言中,没有从整数到浮点数的自动转换,因此代码行gl_FragColor = vec4(gl_FragCoord.x/500, 0.0, 1.0, 1.0);会导致编译器错误。
  2. 您无法从java代码(或c ++代码)获取着色器变量的值。 java代码从CPU执行,着色器从GPU执行。
  3. 希望它有所帮助。

答案 1 :(得分:0)

你的第一个问题是关于java如何工作而不是与OpenGL无关。

如果将整数除以整数,则得到一个整数。所以我的猜测是gl_FragCoord.x / 500会产生一个0.3等值然后舍入为零。

如果用float(或double)除整数,则得到一个float(或double)。因此,当您除以500.0时,您将获得预期的非零浮点结果。您也可以使用500f实现相同的目标。无论哪种方式,您都让编译器知道您正在使用浮点值,这在这里显然非常重要。

关于你的第二个问题,我不相信你可以,虽然我很高兴被其他人纠正。