PDA

View Full Version : Point lights shadows via GL_TEXTURE_CUBE_MAP_ARRAY: mess with cube faces



nimelord
11-30-2017, 02:46 PM
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:
2562


two:
2563


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! :)

Dark Photon
11-30-2017, 05:23 PM
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?

nimelord
11-30-2017, 11:24 PM
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.

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));
}



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

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);
}
}
...
}

nimelord
12-03-2017, 10:43 AM
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!