Jump to content
  • Advertisement

Recommended Posts

I ran into a problem when testing a program on an AMD GPU. When tested on Nvidia and Intel HD Graphics, everything works fine. On AMD, the problem occurs precisely when trying to bind the texture. Because of this problem, the shader has no shadow maps and only a black screen is visible. Id textures and other parameters are successfully loaded. Below are the code snippets:

Here is the complete problem area of the rendering code:

#define cfgtex(texture, internalformat, format, width, height) glBindTexture(GL_TEXTURE_2D, texture); \
                                                               glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_FLOAT, NULL);
void render() {
    for (GLuint i = 0; i < count; i++) {
        // start id = 10
        glUniform1i(samplersLocations[i], startId + i);
        glActiveTexture(GL_TEXTURE0 + startId + i);
        glBindTexture(GL_TEXTURE_CUBE_MAP, texturesIds[i]);

    renderer.mainPass(displayFB, rbo);
    cfgtex(colorTex, GL_RGBA16F, GL_RGBA, params.scrW, params.scrH);
    cfgtex(dofTex, GL_R16F, GL_RED, params.scrW, params.scrH);
    cfgtex(normalTex, GL_RGB16F, GL_RGB, params.scrW, params.scrH);
    cfgtex(ssrValues, GL_RG16F, GL_RG, params.scrW, params.scrH);
    cfgtex(positionTex, GL_RGB16F, GL_RGB, params.scrW, params.scrH);
    glClearBufferfv(GL_COLOR, 1, ALGINE_RED); // dof buffer

    // view port to window size
    glViewport(0, 0, WIN_W, WIN_H);
    // updating view matrix (because camera position was changed)
    // sending lamps parameters to fragment shader

    // drawing
    //glUniform1f(ALGINE_CS_SWITCH_NORMAL_MAPPING, 1); // with mapping

    for (size_t i = 0; i < MODELS_COUNT; i++) drawModel(models[i]);

    for (size_t i = 0; i < LAMPS_COUNT; i++) drawModel(lamps[i]);



renderer.mainPass code:

void mainPass(GLuint displayFBO, GLuint rboBuffer) {
    glBindFramebuffer(GL_FRAMEBUFFER, displayFBO);
    glBindRenderbuffer(GL_RENDERBUFFER, rboBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, params->scrW, params->scrH);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboBuffer);


#version 400 core
uniform samplerCube shadowMaps[MAX_LAMPS_COUNT];

There are no errors during the compilation of shaders. As far as I understand, the texture for some reason does not bind. Depth maps themselves are drawn correctly.

I access the elements of the array as follows:

for (int i = 0; i < count; i++) {
    depth = texture(shadowMaps[i], fragToLight).r;


Also, it was found that a black screen occurs when the samplerCube array is larger than the bound textures. For example MAX_LAMPS_COUNT = 2 and count = 1, then

uniform samplerCube shadowMaps[2];

glUniform1i(samplersLocations[0], startId + 0);
glActiveTexture(GL_TEXTURE0 + startId + 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, texturesIds[0]);

In this case, there will be a black screen.

But if MAX_LAMPS_COUNT = 1 (uniform samplerCube shadowMaps[1]) then shadows appear, but a new problem also arises: 



Do not pay attention to the fact that everything is greenish, this is due to incorrect color correction settings for the video card.

Any ideas? I would be grateful for the help

Share this post

Link to post
Share on other sites

How do you find the value of startId / how do you discover the correct uniform location to bind?

General debugging advice: Have you enabled debug output? Have you inspected the draw call in Renderdoc?

Share this post

Link to post
Share on other sites
Posted (edited)

It was found that indeed the entire array of samplerCube must be filled with something, otherwise there will be a black screen. Therefore, in order to avoid a black screen, all unused slots have to be filled with textures with id 0 (Is this because of the use of open source driver?). But then another problem appears - strange highlights. It was determined that they appear with the included PCF (soft shadows). Here is the problem area of the shader code:

const vec3 sampleOffsetDirections[20] = vec3[] (
		vec3(1, 1, 1), vec3(1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
		vec3(1, 1, -1), vec3(1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
		vec3(1, 1, 0), vec3(1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
		vec3(1, 0, 1), vec3(-1, 0, 1), vec3(1, 0, -1), vec3(-1, 0, -1),
		vec3(0, 1, 1), vec3(0, -1, 1), vec3(0, -1, -1), vec3(0, 1, -1)

// get vector between fragment position and light position
vec3 fragToLight = fragWorldPos - lamps[index].lampPos;
// now get current linear depth as the length between the fragment and light position
float currentDepth = length(fragToLight);
// use the light to fragment vector to sample from the depth map
float closestDepth;

// PCF
float viewDistance = length(viewPos - fragWorldPos);
float diskRadius = (1.0 + (viewDistance / lamps[index].far)) * diskRadius_k + diskRadius_min;
for (int i = 0; i < 20; i++) {
	closestDepth = texture(shadowMaps[index], fragToLight + sampleOffsetDirections[i] * diskRadius).r;
                                                            ^^^^^^^^^^^^^problem here^^^^^^^^^^^^^^
	closestDepth *= lamps[index].far; // Undo mapping [0;1]
	// now test for shadows
	if(currentDepth - shadow_bias > closestDepth) shadow += 1.0;
return shadow /= 20;

Any ideas? Note: everything works fine on Intel HD Graphics and Nvidia

Edited by congard

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!