Point lights shadows via GL_TEXTURE_CUBE_MAP_ARRAY: mess with cube faces

Hi, All.

After success reworking CSM from separated textures to texture array, I want to do similar refactoring with shadow cube of point lights.
So, I try to use GL_TEXTURE_CUBE_MAP_ARRAY instead several GL_TEXTURE_CUBE_MAP.

When I use one point light it is looks fine, but when I try to it with two there is some mess with cube faces:

one:
[ATTACH=CONFIG]1626[/ATTACH]

two:
[ATTACH=CONFIG]1627[/ATTACH]

I,m using OpenGl 4.0, lwjgl (java opengl library)

CubeShadowBuffer:


    depthMapFBO = glGenFramebuffers();

    depthMap = new CubeTexture(shadowMapWidth, shadowMapHeight, GL_DEPTH_COMPONENT, lightsNumber);

    glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthMap.getId(), 0, 0);

    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);

    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
      // number of problem from enum
      throw new IllegalStateException("Could not create FrameBuffer: " + (status - GL_FRAMEBUFFER_COMPLETE));
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

CubeTexture:


    id = glGenTextures();

    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, id);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_DEPTH_COMPONENT, width, height, 6 * lightsNumber, 0, GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer) null);

    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);

Cycle of rendering:


  public void render(Display display, Camera camera, Scene scene, Transformation transformation, IHud hud) {


    glViewport(0, 0, SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT);

    for (int cnt = 0; cnt < MAX_POINT_LIGHTS; cnt++) {
      Matrix4f viewMatrix = camera.updateViewMatrix();
      update(display, viewMatrix, scene, cnt);

      depthShaderProgram.bind();


      glDrawBuffer(GL_NONE);
      glReadBuffer(GL_NONE);
      glCullFace(GL_BACK);

      glClearColor(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);

      renderCubeFace(shadowBuffer, pointLightShadowBox.getRightMap(), 0 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getLeftMap(), 1 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getTopMap(), 2 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getBottomMap(), 3 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getRearMap(), 4 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getFrontMap(), 5 + cnt, scene, transformation);

      depthShaderProgram.unbind();
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
      glDrawBuffer(GL_BACK);
      glReadBuffer(GL_BACK);
    }

  }

  private void renderCubeFace(CubeShadowBuffer shadowBuffer, ShadowMap shadowMap, int face, Scene scene, Transformation transformation) {
    depthShaderProgram.setUniform("projectionMatrix", shadowMap.getProjectionMatrix());
    depthShaderProgram.setUniform("lightViewMatrix", shadowMap.getLightViewMatrix());

    glBindFramebuffer(GL_FRAMEBUFFER, shadowBuffer.getDepthMapFBO());
    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowBuffer.getDepthMapTexture().getId(), 0, face);
    glDrawBuffer(GL_DEPTH_ATTACHMENT);
    glClear(GL_DEPTH_BUFFER_BIT);

    renderMeshes(scene, transformation);
  }

Thank you for help! :slight_smile:

I would try checking for GL errors. For instance, glDrawBuffer() specifies the color buffer to write to. GL_DEPTH_ATTACHMENT is not a color buffer.

Also, where’s your shader that reads from the cubemap array?

Added validation, and there is no any errors:


    glBindFramebuffer(GL_FRAMEBUFFER, shadowBuffer.getDepthMapFBO());
    glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowBuffer.getDepthMapTexture().getId(), 0, face);
    glDrawBuffer(GL_DEPTH_ATTACHMENT);
    glClear(GL_DEPTH_BUFFER_BIT);

    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
      // number of problem from enum
      throw new IllegalStateException("Could not create FrameBuffer: " + (status - GL_FRAMEBUFFER_COMPLETE));
    }

There is the shader:


#version 400
...
uniform samplerCubeArray plShadowMap;
uniform int plNumber;
...

float calcPlShadow(vec3 position, PointLight light, int idx) {


  mat4 plLightViewMatrix = mat4(1,0,0,0,
                    0,1,0,0,
                    0,0,1,0,
                    -light.position.x,-light.position.y,-light.position.z,1);

  vec4 position_ls = plLightViewMatrix * wPosition;
  vec4 abs_position = abs(position_ls);
  float fs_z = -max(abs_position.x, max(abs_position.y, abs_position.z));
  vec4 clip = plProjectionMatrix * vec4(0.0, 0.0, fs_z, 1.0);
  float depth = (clip.z / clip.w) * 0.5 + 0.5;
  float result = 0.0;
  result = texture(plShadowMap, vec4(position_ls.xyz, idx)).r;
  if (result >= depth - 0.0002) {
    return 1.0;
  } else {
    return 0.0;
  }
}

void main() {
  ...
  vec4 aroundLight = vec4(0,0,0,0);

  for (int i=0; i < plNumber; i++) {
    if ( pointLights[i].intensity > 0 ) {

      float shadow = 1;
      vec4 currPointLight = calcPointLight(pointLights[i], mvVertexPos, currNomal);
      shadow = calcPlShadow(mvVertexPos, pointLights[i], i);
      aroundLight += (currPointLight * shadow);
    }
  }
...
}

I have found the problem.

It was so stupid bug!
was:


    for (int cnt = 0; cnt < MAX_POINT_LIGHTS; cnt++) {
      ......
      renderCubeFace(shadowBuffer, pointLightShadowBox.getRightMap(), 0 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getLeftMap(), 1 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getTopMap(), 2 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getBottomMap(), 3 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getRearMap(), 4 + cnt, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getFrontMap(), 5 + cnt, scene, transformation);
      ......
    }

fixed as:


    for (int cnt = 0; cnt < MAX_POINT_LIGHTS; cnt++) {
      ......
      int idx = cnt * 6;
      renderCubeFace(shadowBuffer, pointLightShadowBox.getRightMap(), 0 + idx, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getLeftMap(), 1 + idx, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getTopMap(), 2 + idx, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getBottomMap(), 3 + idx, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getRearMap(), 4 + idx, scene, transformation);
      renderCubeFace(shadowBuffer, pointLightShadowBox.getFrontMap(), 5 + idx, scene, transformation);
      ......
    }

Also i removed string “glDrawBuffer(GL_DEPTH_ATTACHMENT);”.
It was redundant there.
Now it working fine!

Thank you, Photon!