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 5 of 5

Thread: arrays of arrays as vertex output/fragment input

  1. #1
    Newbie Newbie
    Join Date
    May 2018
    Posts
    2

    arrays of arrays as vertex output/fragment input

    Hello,

    I want to use an array of arrays (vec4[3][1]) as vertex output and fragment input. If the array has the form vec4 a[2][1]my program works but if the first index is larger than 2, my program shows only the clear color.
    The array has no effect on the rest of the shaders, other than an identity matrix multiplication to avoid that that array gets optimized out. The full fragment and vertex shaders:
    vert:
    Code :
     #version 450
     
    #define MAX_NUM_LIGHTS 10
    #define NUM_CASCADES 2
     
    in layout(location = 0) vec4 vertPosition_ModelSpace;
    in layout(location = 1) vec3 vertNormal_ModelSpace;
    in layout(location = 2) vec3 vertTangent_ModelSpace;
    in layout(location = 3) vec2 textureCoordinate;
     
    uniform mat4 modelToWorld;
    uniform mat4 worldToProjection;
    uniform mat4 worldToLight[NUM_CASCADES][MAX_NUM_LIGHTS];
     
    uniform vec3 cameraPosition_WorldSpace;
    uniform vec3 lightPosition_WorldSpace[MAX_NUM_LIGHTS];
    uniform int numLights;
     
    out VsOut
    {
      vec3 fragPosition_TangentSpace;
      vec2 textureCoordinate;
      vec3 cameraPosition_TangentSpace;
      vec3 lightPosition_TangentSpace[MAX_NUM_LIGHTS];
      vec4 v[3][1];
      vec4 fragPosition_LightSpace[NUM_CASCADES][MAX_NUM_LIGHTS];
    } vsOut;
     
    void main()
    {
      vsOut.v[0][0] = vec4(1.0);
      vec3 vertNormal_WorldSpace = normalize(vec3(modelToWorld * vec4(vertNormal_ModelSpace, 0.0)));
      vec3 vertTangent_WorldSpace = normalize(vec3(modelToWorld * vec4(vertTangent_ModelSpace, 0.0)));
      vec3 vertBiTangent_WorldSpace = normalize(cross(vertNormal_WorldSpace, vertTangent_WorldSpace));
      mat3 worldToTangentSpace = transpose(mat3(
            vertTangent_WorldSpace,
            vertBiTangent_WorldSpace,
            vertNormal_WorldSpace
        ));
     
      vec3 vertPosition_WorldSpace = vec3(modelToWorld * vertPosition_ModelSpace);
      gl_Position = worldToProjection * vec4(vertPosition_WorldSpace, 1.0);
     
      vsOut.fragPosition_TangentSpace = worldToTangentSpace * vertPosition_WorldSpace;
      vsOut.cameraPosition_TangentSpace = worldToTangentSpace * cameraPosition_WorldSpace;
      for(int i = 0; i < numLights; i++)
      {
        vsOut.lightPosition_TangentSpace[i] = worldToTangentSpace * lightPosition_WorldSpace[i];
        for(int cascadeIndex = 0; cascadeIndex<NUM_CASCADES; cascadeIndex++)
        {
          vsOut.fragPosition_LightSpace[cascadeIndex][i] = worldToLight[cascadeIndex][i] * vec4(vertPosition_WorldSpace, 1.0);
        }
      }
      vsOut.textureCoordinate = textureCoordinate;
    }
    frag:
    Code :
    #version 450
     
    #define MAX_NUM_LIGHTS 10
    #define NUM_CASCADES 2
     
    in VsOut
    {
      vec3 fragPosition_TangentSpace;
      vec2 textureCoordinate;
      vec3 cameraPosition_TangentSpace;
      vec3 lightPosition_TangentSpace[MAX_NUM_LIGHTS];
      vec4 v[3][1];
      vec4 fragPosition_LightSpace[NUM_CASCADES][MAX_NUM_LIGHTS];
    } vsOut;
     
    layout(location = 0) out vec4 outColor;
     
    uniform float lightPower[MAX_NUM_LIGHTS];
    uniform vec3 lightColor[MAX_NUM_LIGHTS];
    uniform int numLights;
    uniform vec3 ambientColor;
    uniform vec3 diffuseColor;
    uniform vec3 specularColor;
    uniform float transparency;
    uniform float shininess;
    uniform sampler2D diffuseTexture;
    uniform sampler2D normalMap;
    uniform sampler2D depthMap[NUM_CASCADES][MAX_NUM_LIGHTS];
     
    uniform float cascadeDistances[NUM_CASCADES];
     
    float shadowCalculation(int lightIndex, int cascadeIndex)
    {
      vec3 projCoords = vsOut.fragPosition_LightSpace[cascadeIndex][lightIndex].xyz / vsOut.fragPosition_LightSpace[cascadeIndex][lightIndex].w;
      projCoords = projCoords * 0.5 + 0.5;
      float currentDepth = projCoords.z;
      float shadow = 0.0;
      vec2 texelSize = 1.0 / textureSize(depthMap[cascadeIndex][lightIndex], 0);
      float bias = 0.0;
      for(int x = -1; x <= 1; ++x)
      {
        for(int y = -1; y <= 1; ++y)
        {
          float pcfDepth = texture(depthMap[cascadeIndex][lightIndex], projCoords.xy + vec2(x, y) * texelSize).r;
          shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
        }
      }
      shadow /= 9.0;
     
      return clamp(shadow, 0.0, 1.0);
    }
     
    float calculateLocalLightPower(float lightDistance, float lightPower)
    {
      return clamp(lightPower/pow(lightDistance, 2.0), 0.0, 1.0);
    }
     
    vec3 ambientLight(vec3 ambientColor)
    {
      return ambientColor * vec3(0.0, 0.0, 0.0);
    }
     
    vec3 diffuseLight(
      vec3 diffuseColor,
      vec3 toLight[MAX_NUM_LIGHTS],
      vec3 lightColor[MAX_NUM_LIGHTS],
      float localLightPower[MAX_NUM_LIGHTS],
      vec3 normal
    )
    {
      vec3 diffuseLight = vec3(0.0, 0.0, 0.0);
      for(int i = 0; i < numLights; i++)
      {
        diffuseLight +=
          lightColor[i] * clamp(dot(toLight[i], normal), 0.0, 1.0) * localLightPower[i];
      }
      return diffuseColor * clamp(diffuseLight, 0.0, 1.0);
    }
     
    vec3 specularLight(
      vec3 specularColor,
      vec3 toLight[MAX_NUM_LIGHTS],
      vec3 lightColor[MAX_NUM_LIGHTS],
      float localLightPower[MAX_NUM_LIGHTS],
      vec3 toCamera,
      vec3 normal
    )
    {
      vec3 specularLight = vec3(0.0, 0.0, 0.0);
      for(int i = 0; i < numLights; i++)
      {
        vec3 halfDir = normalize(toLight[i] + toCamera);
        float specAngle = clamp(dot(halfDir, normal), 0.0, 1.0);
        specularLight += lightColor[i] * pow(specAngle, shininess) * localLightPower[i];
      }
      return specularColor * specularLight;
    }
     
    void main()
    {
      vec4 diffuseTextureColor = texture2D(diffuseTexture, vsOut.textureCoordinate);
     
      vec3 fragNormal_TangentSpace = normalize(texture2D(normalMap, vsOut.textureCoordinate).rgb * 2.0 - vec3(1.0, 1.0, 1.0));
     
      int cascadeIndex;
      float currentCascadeDistance = distance(vsOut.fragPosition_TangentSpace, vsOut.cameraPosition_TangentSpace);
      for(int i = 0; i<NUM_CASCADES; i++)
      {
        cascadeIndex = i;
        if(currentCascadeDistance<cascadeDistances[i])
        {
          break;
        }
      }
     
      vec3 toLight_TangentSpace[MAX_NUM_LIGHTS];
      float localLightPower[MAX_NUM_LIGHTS];
      for(int i = 0; i < numLights; i++)
      {
        toLight_TangentSpace[i] = normalize(vsOut.lightPosition_TangentSpace[i] - vsOut.fragPosition_TangentSpace);
        float lightDistance = distance(vsOut.lightPosition_TangentSpace[i], vsOut.fragPosition_TangentSpace);
        localLightPower[i] =
          calculateLocalLightPower(lightDistance, lightPower[i])*(1.0 - shadowCalculation(i, cascadeIndex));
      }
     
      vec3 toCamera = normalize(vsOut.cameraPosition_TangentSpace - vsOut.fragPosition_TangentSpace);
     
      vec3 ambientLight = ambientLight(ambientColor);
      vec3 diffuseLight = diffuseLight(diffuseColor, toLight_TangentSpace, lightColor, localLightPower, fragNormal_TangentSpace);
      vec3 specularLight = specularLight(specularColor, toLight_TangentSpace, lightColor, localLightPower, toCamera, fragNormal_TangentSpace);
     
      vec3 finalLight = clamp(ambientLight +
        (diffuseLight + specularLight)
        , 0.0, 1.0);
     
      outColor = diffuseTextureColor * vec4(finalLight,  transparency)*vsOut.v[0][0];
    }
    As they are these shaders do not work as I intended, they work when vec4 v[3][1] gets replaced with vec4 v[2][1].
    I am sorry that i can't provide a minimal example but it would be too much of a headache to rewrite the renderer.
    https://github.com/tsoj/spacesimulator

    system information:
    KAOS Linux, Intel Open Source Technology Center, 4.5 (Core Profile) Mesa 17.3.9, Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2)
    using C++, glew, glfw

  2. #2
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,031
    You can only output so much stuff, and you're shoving way too much between the VS and FS. You have 28 individual outputs/inputs. That's a huge amount.

  3. #3
    Newbie Newbie
    Join Date
    May 2018
    Posts
    2
    Where can I find information about the limits of the inputs and outputs of fragment/vertex shaders and what are possible solutions for that problem?

    Edit:

    Do the elements of a vertex output array get interpolated as if they were individual elements?
    Last edited by tsojtsoj; 05-17-2018 at 06:46 PM.

  4. #4
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,031
    Shaders have all kinds of resource limitations that you can query.

    what are possible solutions for that problem?
    Besides not passing quite so much stuff?

    I don't know much about cascading shadow maps, so I can't help you there (though I think 10 maps is probably seriously overdoing it). But when dealing with complex shadow casting algorithms, it's probably best to do each light in a separate pass rather than all at once. That alone would almost half the number of outputs.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,926
    Quote Originally Posted by tsojtsoj View Post
    Where can I find information about the limits of the inputs and outputs of fragment/vertex shaders
    glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS) retrieves the maximum value for the total number of components of vertex shader outputs. Your VsOut structure has 130 components (80 of those are in fragPosition_LightSpace), so the limit is presumably 128 on your system. The standard only requires that the limit is at least 64.

    Quote Originally Posted by tsojtsoj View Post
    and what are possible solutions for that problem?
    Splitting the shadow calculations across multiple passes would significantly reduce the number of outputs.

Posting Permissions

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