Невозможно скомпилировать фрагментный шейдер opengl в Android - ОШИБКА: 0: 7: 'gl_GlobalInvocationID': необъявленный идентификатор - PullRequest
1 голос
/ 31 марта 2019

Невозможно скомпилировать следующий код шейдера фрагмента opengl в Android. GLES31.glGetString(GL_VERSION) показывает версию opengl 3.2, и устройство также поддерживает эту версию.

Ошибка: -

Error compiling shader: ERROR: 0:7: 'gl_GlobalInvocationID' : undeclared identifier 
    ERROR: 0:7: 'xy' :  field selection requires structure, vector, or matrix on left hand side 
    ERROR: 2 compilation errors.  No code generated.
03-31 10:39:17.822 23849-23887/com.research.gltest E/AndroidRuntime: FATAL EXCEPTION: GLThread 1686
    Process: com.research.gltest, PID: 23849
    java.lang.RuntimeException: Error creating shader.
        at com.research.gltest.ShaderHelper.compileShader(ShaderHelper.java:45)
        at com.research.gltest.GLLayer.onDrawFrame(GLLayer.java:325)

Код шейдера: -

    #version 310 es
    precision mediump float;
    layout(binding = 0) uniform sampler2D u_Texture1;
    layout(std430) buffer;
    layout(binding = 1) buffer Output { float elements[]; } output_data;
    void main() {
    ivec2 gid = ivec2(gl_GlobalInvocationID.xy);
    if (gid.x >= 257 || gid.y >= 257) return;
    vec3 pixel = texelFetch(u_Texture1, gid, 0).xyz;
    int linear_index = 3 * (gid.y * 224 + gid.x);
    output_data.elements[linear_index + 0] = pixel.x; output_data.elements[linear_index + 1] = pixel.y;
    output_data.elements[linear_index + 2] = pixel.z;
    }

Ошибка возникает в следующей строке: -

final int fragmentShaderHandle = ShaderHelper.compileShader(
            GLES31.GL_FRAGMENT_SHADER, fragmentShader)

JavaCodehaderHelper.java): -

public class ShaderHelper
    {
        private static final String TAG = "ShaderHelper";

        /** 
         * Helper function to compile a shader.
         * 
         * @param shaderType The shader type.
         * @param shaderSource The shader source code.
         * @return An OpenGL handle to the shader.
         */
        public static int compileShader(final int shaderType, final        String shaderSource) 
        {
            int shaderHandle = GLES31.glCreateShader(shaderType);

            if (shaderHandle != 0) 
            {
                // Pass in the shader source.
                GLES31.glShaderSource(shaderHandle, shaderSource);

                // Compile the shader.
                GLES31.glCompileShader(shaderHandle);

                // Get the compilation status.
                final int[] compileStatus = new int[1];
                GLES31.glGetShaderiv(shaderHandle, GLES31.GL_COMPILE_STATUS, compileStatus, 0);

                // If the compilation failed, delete the shader.
                if (compileStatus[0] == 0) 
                {
                    Log.e(TAG, "Error compiling shader: " + GLES31.glGetShaderInfoLog(shaderHandle));
                    GLES31.glDeleteShader(shaderHandle);
                    shaderHandle = 0;
                }
            }

            if (shaderHandle == 0)
            {           
                throw new RuntimeException("Error creating shader.");
            }

            return shaderHandle;
        }

        /**
         * Helper function to compile and link a program.
         * 
         * @param vertexShaderHandle An OpenGL handle to an already-compiled vertex shader.
         * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
         * @param attributes Attributes that need to be bound to the program.
         * @return An OpenGL handle to the program.
         */
        public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) 
        {
            int programHandle = GLES31.glCreateProgram();

            if (programHandle != 0) 
            {
                // Bind the vertex shader to the program.
                GLES31.glAttachShader(programHandle, vertexShaderHandle);

                // Bind the fragment shader to the program.
                GLES31.glAttachShader(programHandle, fragmentShaderHandle);

                // Bind attributes
                if (attributes != null)
                {
                    final int size = attributes.length;
                    for (int i = 0; i < size; i++)
                    {
                        GLES31.glBindAttribLocation(programHandle, i, attributes[i]);
                    }                       
                }

                // Link the two shaders together into a program.
                GLES31.glLinkProgram(programHandle);

                // Get the link status.
                final int[] linkStatus = new int[1];
                GLES31.glGetProgramiv(programHandle, GLES31.GL_LINK_STATUS, linkStatus, 0);

                // If the link failed, delete the program.
                if (linkStatus[0] == 0) 
                {               
                    Log.e(TAG, "Error compiling program: " + GLES31.glGetProgramInfoLog(programHandle));
                    GLES31.glDeleteProgram(programHandle);
                    programHandle = 0;
                }
            }

            if (programHandle == 0)
            {
                throw new RuntimeException("Error creating program.");
            }

            return programHandle;
        }
    }

NB. Использование плагина glsl в Android и код хранятся в папке raw. В любом случае, я могу скомпилировать и запустить некоторые другие примеры кодов шейдеров glsl (<3.0) с помощью приложения @ (<a href="https://github.com/yulu/GLtext" rel="nofollow noreferrer">https://github.com/yulu/GLtext).

).

Редактировать: я изменил старые коды шейдеров на opengl v3; но теперь выдает новую ошибку Ошибка компиляции программы: Ошибка: вычислить шейдер связан с другими шейдерами

1 Ответ

2 голосов
/ 31 марта 2019

gl_GlobalInvocationID является Специальными переменными вычислительного шейдера и может использоваться только в вычислительных шейдерах:

С Язык затенения OpenGL ES 3.20 Спецификация

Встроенная переменная gl_GlobalInvocationID является входной переменной вычислительного шейдера, содержащей глобальный индекс текущего рабочего элемента. Это значение однозначно идентифицирует этот вызов из всех других вызовов во всех рабочих группах, инициированных текущим вызовом DispatchCompute. Это вычисляется как:

gl_GlobalInvocationID =
     gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;

В вершинном шейдере есть встроенные переменные gl_VertexID и gl_InstanceID, которые можно передать на этап фрагментного шейдера. См. Специальные переменные вершинного шейдера .

...