OpenGL uniform array of structures

前端 未结 1 1876
天涯浪人
天涯浪人 2020-12-17 07:43

So i have a custom structure in the fragment shader and an uniform variable that is an array of these structures. It is defined like this:

#version 130
#defi         


        
相关标签:
1条回答
  • 2020-12-17 08:10

    Since people often blindly fumble around trying to figure out what the cause of glGetUniformLocation (...) returning -1 is, I figured I would share some modified code that I use to enumerate all uniforms per-GLSL program. I actually use a map structure to do type enum to string name but that would be more complicated than necessary.

    Utility structure to print human-readable types (up to GLSL 430):

    struct glsl_type_set {
      GLenum      type;
      const char* name;
    }
    type_set [] = {
      GL_INVALID_ENUM,                              "invalid",
      GL_FLOAT,                                     "float",
      GL_FLOAT_VEC2,                                "vec2",
      GL_FLOAT_VEC3,                                "vec3",
      GL_FLOAT_VEC4,                                "vec4",
      GL_DOUBLE,                                    "double",
      GL_DOUBLE_VEC2,                               "dvec2",
      GL_DOUBLE_VEC3,                               "dvec3",
      GL_DOUBLE_VEC4,                               "dvec4",
      GL_INT,                                       "int",
      GL_INT_VEC2,                                  "ivec2",
      GL_INT_VEC3,                                  "ivec3",
      GL_INT_VEC4,                                  "ivec4",
      GL_UNSIGNED_INT,                              "unsigned int",
      GL_UNSIGNED_INT_VEC2,                         "uvec2",
      GL_UNSIGNED_INT_VEC3,                         "uvec3",
      GL_UNSIGNED_INT_VEC4,                         "uvec4",
      GL_BOOL,                                      "bool",
      GL_BOOL_VEC2,                                 "bvec2",
      GL_BOOL_VEC3,                                 "bvec3",
      GL_BOOL_VEC4,                                 "bvec4",
      GL_FLOAT_MAT2,                                "mat2",
      GL_FLOAT_MAT3,                                "mat3",
      GL_FLOAT_MAT4,                                "mat4",
      GL_FLOAT_MAT2x3,                              "mat2x3",
      GL_FLOAT_MAT2x4,                              "mat2x4",
      GL_FLOAT_MAT3x2,                              "mat3x2",
      GL_FLOAT_MAT3x4,                              "mat3x4",
      GL_FLOAT_MAT4x2,                              "mat4x2",
      GL_FLOAT_MAT4x3,                              "mat4x3",
      GL_DOUBLE_MAT2,                               "dmat2",
      GL_DOUBLE_MAT3,                               "dmat3",
      GL_DOUBLE_MAT4,                               "dmat4",
      GL_DOUBLE_MAT2x3,                             "dmat2x3",
      GL_DOUBLE_MAT2x4,                             "dmat2x4",
      GL_DOUBLE_MAT3x2,                             "dmat3x2",
      GL_DOUBLE_MAT3x4,                             "dmat3x4",
      GL_DOUBLE_MAT4x2,                             "dmat4x2",
      GL_DOUBLE_MAT4x3,                             "dmat4x3",
      GL_SAMPLER_1D,                                "sampler1D",
      GL_SAMPLER_2D,                                "sampler2D",
      GL_SAMPLER_3D,                                "sampler3D",
      GL_SAMPLER_CUBE,                              "samplerCube",
      GL_SAMPLER_1D_SHADOW,                         "sampler1DShadow",
      GL_SAMPLER_2D_SHADOW,                         "sampler2DShadow",
      GL_SAMPLER_1D_ARRAY,                          "sampler1DArray",
      GL_SAMPLER_2D_ARRAY,                          "sampler2DArray",
      GL_SAMPLER_1D_ARRAY_SHADOW,                   "sampler1DArrayShadow",
      GL_SAMPLER_2D_ARRAY_SHADOW,                   "sampler2DArrayShadow",
      GL_SAMPLER_2D_MULTISAMPLE,                    "sampler2DMS",
      GL_SAMPLER_2D_MULTISAMPLE_ARRAY,              "sampler2DMSArray",
      GL_SAMPLER_CUBE_SHADOW,                       "samplerCubeShadow",
      GL_SAMPLER_BUFFER,                            "samplerBuffer",
      GL_SAMPLER_2D_RECT,                           "sampler2DRect",
      GL_SAMPLER_2D_RECT_SHADOW,                    "sampler2DRectShadow",
      GL_INT_SAMPLER_1D,                            "isampler1D",
      GL_INT_SAMPLER_2D,                            "isampler2D",
      GL_INT_SAMPLER_3D,                            "isampler3D",
      GL_INT_SAMPLER_CUBE,                          "isamplerCube",
      GL_INT_SAMPLER_1D_ARRAY,                      "isampler1DArray",
      GL_INT_SAMPLER_2D_ARRAY,                      "isampler2DArray",
      GL_INT_SAMPLER_2D_MULTISAMPLE,                "isampler2DMS",
      GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,          "isampler2DMSArray",
      GL_INT_SAMPLER_BUFFER,                        "isamplerBuffer",
      GL_INT_SAMPLER_2D_RECT,                       "isampler2DRect",
      GL_UNSIGNED_INT_SAMPLER_1D,                   "usampler1D",
      GL_UNSIGNED_INT_SAMPLER_2D,                   "usampler2D",
      GL_UNSIGNED_INT_SAMPLER_3D,                   "usampler3D",
      GL_UNSIGNED_INT_SAMPLER_CUBE,                 "usamplerCube",
      GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,             "usampler2DArray",
      GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,             "usampler2DArray",
      GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE,       "usampler2DMS",
      GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "usampler2DMSArray",
      GL_UNSIGNED_INT_SAMPLER_BUFFER,               "usamplerBuffer",
      GL_UNSIGNED_INT_SAMPLER_2D_RECT,              "usampler2DRect",
      GL_IMAGE_1D,                                  "image1D",
      GL_IMAGE_2D,                                  "image2D",
      GL_IMAGE_3D,                                  "image3D",
      GL_IMAGE_2D_RECT,                             "image2DRect",
      GL_IMAGE_CUBE,                                "imageCube",
      GL_IMAGE_BUFFER,                              "imageBuffer",
      GL_IMAGE_1D_ARRAY,                            "image1DArray",
      GL_IMAGE_2D_ARRAY,                            "image2DArray",
      GL_IMAGE_2D_MULTISAMPLE,                      "image2DMS",
      GL_IMAGE_2D_MULTISAMPLE_ARRAY,                "image2DMSArray",
      GL_INT_IMAGE_1D,                              "iimage1D",
      GL_INT_IMAGE_2D,                              "iimage2D",
      GL_INT_IMAGE_3D,                              "iimage3D",
      GL_INT_IMAGE_2D_RECT,                         "iimage2DRect",
      GL_INT_IMAGE_CUBE,                            "iimageCube",
      GL_INT_IMAGE_BUFFER,                          "iimageBuffer",
      GL_INT_IMAGE_1D_ARRAY,                        "iimage1DArray",
      GL_INT_IMAGE_2D_ARRAY,                        "iimage2DArray",
      GL_INT_IMAGE_2D_MULTISAMPLE,                  "iimage2DMS",
      GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY,            "iimage2DMSArray",
      GL_UNSIGNED_INT_IMAGE_1D,                     "uimage1D",
      GL_UNSIGNED_INT_IMAGE_2D,                     "uimage2D",
      GL_UNSIGNED_INT_IMAGE_3D,                     "uimage3D",
      GL_UNSIGNED_INT_IMAGE_2D_RECT,                "uimage2DRect",
      GL_UNSIGNED_INT_IMAGE_CUBE,                   "uimageCube",
      GL_UNSIGNED_INT_IMAGE_BUFFER,                 "uimageBuffer",
      GL_UNSIGNED_INT_IMAGE_1D_ARRAY,               "uimage1DArray",
      GL_UNSIGNED_INT_IMAGE_2D_ARRAY,               "uimage2DArray",
      GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE,         "uimage2DMS",
      GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY,   "uimage2DMSArray",
      GL_UNSIGNED_INT_ATOMIC_COUNTER,               "atomic_uint"
    };
    

    Code to enumerate all ACTIVE uniforms in a program:

    void
    eTB_GLSL__print_uniforms (GLuint program)
    {
      GLint uniform_count;
      glGetProgramiv (program, GL_ACTIVE_UNIFORMS, &uniform_count);
    
      GLchar name [256];
    
      for (GLint i = 0; i < uniform_count; i++) {
        memset (name, '\0', 256);
        GLint  size;
        GLenum type;
    
        glGetActiveUniform (program, i, 255, NULL, &size, &type, name);
    
        GLint location = glGetUniformLocation (program, name);
    
        for (int j = 0; j < sizeof (type_set) / sizeof (glsl_type_set); j++) {
          if (type_set [j].type != type)
            continue;
    
          const char* type_name = type_set [j].name;
    
          if (size > 1)
            printf ( "Uniform %d (loc=%d):\t%20s %-20s <Size: %d>\n",
                       i, location, type_name, name, size );
          else
            printf ( "Uniform %d (loc=%d):\t%20s %-20s\n",
                       i, location, type_name, name );
    
          break;
        }
    
        if (i == (uniform_count - 1))
          printf ("\n");
      }
    }
    

    Sample Output (AMD):

    Uniform 0 (loc=0):                         float buffer_res_x        
    Uniform 1 (loc=1):                         float buffer_res_y        
    Uniform 2 (loc=2):                         float buffer_scale        
    Uniform 3 (loc=3):                          mat4 camera_matrix       
    Uniform 4 (loc=4):                          bool fxaa                
    Uniform 5 (loc=5):                          vec3 light_colors         <Size: 128>
    Uniform 6 (loc=133):                        vec3 light_pos            <Size: 128>
    Uniform 7 (loc=261):                        mat4 modelview_mat       
    Uniform 8 (loc=262):                         int num_lights          
    Uniform 9 (loc=263):                   sampler2D depth_buffer        
    Uniform 10 (loc=264):                  sampler2D diffuse_buffer      
    Uniform 11 (loc=265):                  sampler2D normal_buffer       
    Uniform 12 (loc=266):                samplerCube shadow_buffer        <Size: 10>
    

    Sample Output (NV):

    Uniform 0 (loc=0):                         float buffer_res_x        
    Uniform 1 (loc=1):                         float buffer_res_y        
    Uniform 2 (loc=2):                         float buffer_scale        
    Uniform 3 (loc=3):                          mat4 camera_matrix       
    Uniform 4 (loc=4):                          bool fxaa                
    Uniform 5 (loc=5):                          vec3 light_colors[0]      <Size: 128>
    Uniform 6 (loc=133):                        vec3 light_pos[0]         <Size: 128>
    Uniform 7 (loc=261):                        mat4 modelview_mat       
    Uniform 8 (loc=262):                         int num_lights          
    Uniform 9 (loc=263):                   sampler2D depth_buffer        
    Uniform 10 (loc=264):                  sampler2D diffuse_buffer      
    Uniform 11 (loc=265):                  sampler2D normal_buffer       
    Uniform 12 (loc=266):                samplerCube shadow_buffer[0]     <Size: 10>
    

    I chose this particular shader because it is the first one I could find that demonstrates how NV and AMD differ when reporting uniform names for arrays, there is nothing particularly special about it. NV always uses [0] notation and AMD does not (newer drivers tend to, however). You can still query individual uniform locations provided they are within the range indicated by <Size: X>. That is to say that while the driver will enumerate them as name[0] or name, it is technically valid to query the uniform location for name or name[0] in either implementation.

    I would be very interested in seeing three things:

    1. The output of this after linking on your AMD hardware
    2. The output of this after linking on your NV hardware
    3. Your full shader

    With these three things, an actual answer should be possible.

    UPDATE

    I believe the GLSL compiler is having a hard time determining usage because of the way the shader is written, to confirm this, try replacing:

    vec3 computeLight(int light_index){
      Light light = lights[light_index];
      if(light.position == vec4(0.0)) { return vec3(0.0);}
      if(light.position.w == 0.0 ) {return directionLight(light);}
      if(light.cutoff == 0) {return pointLight(light);}
      return reflectionLight(light);
    }
    
    [...]
    
    vec3 lighting = vec3(0.);
      for(int i = 0; i < lights_no; i++) {
        lighting += computeLight(i);
    }
    

    With something much uglier like:

    vec3 lighting = vec3(0.0);
      for(int i = 0; i < lights_no; i++) {
        Light light = lights [i];
        if (light.position != vec4 (0.0)) {
          if (light.position.w == 0.0)
            lighting += directionLight(light);
          else if (light.cutoff == 0.0)
            lighting += pointLight(light);
          else
            lighting += reflectionLight (light);
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题