Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 11

Thread: Is there some way to bind uniform with dynamic size to shader?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14

    Question Is there some way to bind uniform with dynamic size to shader?

    I have shader with constant size of uniform array looks like next:
    Code :
    #version 430  // maximum version that can be supported by my ATI card with open source mesa driver.
     
    const int MAX_POINT_LIGHTS = 5;
    ...
     
    uniform PointLight pointLights[MAX_POINT_LIGHTS];
     
    struct Attenuation {
      float constant;
      float linear;
      float exponent;
      float distance;
    };
     
     
    struct PointLight {
      vec3 colour;
      vec3 position;
      float intensity;
      Attenuation att;
    };
     
    ...


    May I use in some way dynamic size of uniform array with my own structs?
    I mean:
    1 - On the CPU side I calculate "point light" number as three items.
    2 - I bind them those three lights to the shader.
    3 - On the shader side I have array with 3 items with known size.

    That is so cool if it possible!

    Tank you for answer!
    Last edited by nimelord; 12-05-2017 at 12:53 PM.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,519
    The size of a uniform array must be known when the shader is linked. You can declare the array with the maximum required size then use a uniform int variable to indicate the number of valid elements in the array.

    An array which is the last element of a shader storage block can have a dynamic size, the size being determined by the size of the buffer associated with the block.

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    Quote Originally Posted by GClements View Post
    An array which is the last element of a shader storage block can have a dynamic size, the size being determined by the size of the buffer associated with the block.
    Do you mean this one? https://www.khronos.org/opengl/wiki/..._Buffer_Object

    If yes, how can I use my "struct PointLight" in the such way?
    I have found only using of primitives in examples, I mean int, float, e.t.c.

  4. #4
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    443
    Code glsl:
    layout (std430, binding = 1) buffer POINTLIGHTBLOCK {
        PointLight mypointlights[]; /* unsized array */
    };

    Code cpp:
    /* create your pointlight buffer "mypointlightbuffer" here */
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mypointlightbuffer);

    and read about the memory layout (std430 in case of shader storage blocks)
    https://www.khronos.org/opengl/wiki/...#Memory_layout

  5. #5
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    I did it using "Shader Storage Buffer".
    It basically works except one thing that confused me.

    In shader i have structure with substructure: Attenuation is part of PointLight. (see code with them in the topic body)

    When I fill buffer in correct order: colour, position, intensity, att.constant, att.linear, att.exponent, att.distance, I get mess with data on the shader side.
    But if I write Attenuation data before intensity, then all is ok.

    Could you explain such behavior?

  6. #6
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    I caught the problem!
    This was a packing of data in the buffer.

    I use two vec3 objects, one float, and substructure with four floats in the order.
    I read somewhere that for using vec3 it must be filled as vec4: vec3 + one empty float.
    So, I did it in such way.
    In fact I was wrong: after last vec3 and before other type empty float is redundant. (I think so. Anyway it works.)
    See comment in the code sample where was is redundant empty float:

    Thus I should use vec4 instead vec3.


    My shader:
    Code :
    #version 430
    ...
     
    struct Attenuation {
      float constant;
      float linear;
      float exponent;
      float distance;
    };
     
     
    struct PointLight {
      vec3 colour;
      vec3 position;
      float intensity;
      Attenuation att;
    };
     
    ...
     
    layout (shared, binding = 3) buffer NewPointLight {
      PointLight pls[];
    } newPointLights;
    ...


    And binding:
    Code :
     
        private int pointLights;
        ...
     
     
        pointLights = glGenBuffers();
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, pointLights);
        ByteBuffer pointLightsData = BufferUtils.createByteBuffer(52);  // in bytes
     
        for (PointLight pointLight : scene.getSceneLight().getPointLightList()) {
     
          pointLightsData.putFloat(pointLight.getColor().x);
          pointLightsData.putFloat(pointLight.getColor().y);
          pointLightsData.putFloat(pointLight.getColor().z);
          pointLightsData.putFloat(0);
     
          pointLightsData.putFloat(pointLight.getPosition().x);
          pointLightsData.putFloat(pointLight.getPosition().y);
          pointLightsData.putFloat(pointLight.getPosition().z);
          pointLightsData.putFloat(0); // this one is dedundant!
     
          pointLightsData.putFloat(pointLight.getIntensity());
     
          pointLightsData.putFloat(pointLight.getAttenuation().getConstant());
          pointLightsData.putFloat(pointLight.getAttenuation().getLinear());
          pointLightsData.putFloat(pointLight.getAttenuation().getExponent());
          pointLightsData.putFloat(pointLight.getAttenuation().getDistance());
        }
        pointLightsData.flip();
     
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, pointLights);
        glBufferData(GL_SHADER_STORAGE_BUFFER, pointLightsData, GL_STATIC_DRAW);
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);


    I have one more question: I must build and fill buffer per each rendered frame, or there is more correct way to use it?

    Thanks for answer.
    Last edited by nimelord; 12-07-2017 at 01:08 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •