Массив samplerCube - PullRequest
       75

Массив samplerCube

0 голосов
/ 14 марта 2019

Я столкнулся с проблемой при тестировании программы на AMD GPU.При тестировании на Nvidia и Intel HD Graphics все работает нормально.На AMD проблема возникает именно при попытке связать текстуру.Из-за этой проблемы у шейдера нет карт теней, и виден только черный экран.Идентификационные текстуры и другие параметры успешно загружены.Ниже приведены фрагменты кода:

c ++:

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

glsl:

#version 400 core
...
uniform samplerCube shadowMaps[MAX_LAMPS_COUNT];

Нет ошибок при компиляции шейдеров.Насколько я понимаю, текстура почему-то не связывает.Сами карты глубины нарисованы правильно.

РЕДАКТИРОВАТЬ: Я обращаюсь к элементам массива следующим образом:

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

РЕДАКТИРОВАТЬ: это былообнаружил, что черный экран появляется, когда массив samplerCube больше связанных текстур.Например, MAX_LAMPS_COUNT = 2 и count = 1, затем

uniform samplerCube shadowMaps[2];

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

В этом случае будет черный экран.

Но если MAX_LAMPS_COUNT = 1 (uniform samplerCube shadowMaps[1]) затем появляются тени, но также возникает новая проблема: Не обращайте внимания на то, что все зеленовато, это связано сневерные настройки цветовой коррекции для видеокарты.

Есть идеи?

РЕДАКТИРОВАТЬ: Вот полная проблемная область кода рендеринга:

#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);
    glClear(GL_COLOR_BUFFER_BIT);
    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)
    createViewMatrix();
    // sending lamps parameters to fragment shader
    sendLampsData();
    glEnableVertexAttribArray(cs.inPosition);
    glEnableVertexAttribArray(cs.inNormal);
    glEnableVertexAttribArray(cs.inTexCoord);

    // drawing
    //glUniform1f(ALGINE_CS_SWITCH_NORMAL_MAPPING, 1); // with mapping
    glEnableVertexAttribArray(cs.inTangent);
    glEnableVertexAttribArray(cs.inBitangent);

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

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

    glDisableVertexAttribArray(cs.inPosition);
    glDisableVertexAttribArray(cs.inNormal);
    glDisableVertexAttribArray(cs.inTexCoord);
    glDisableVertexAttribArray(cs.inTangent);
    glDisableVertexAttribArray(cs.inBitangent);

    ...
}

renderer.mainPass код:

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);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

РЕДАКТИРОВАТЬ: Было обнаружено, что действительно весь массив samplerCube должен быть заполнен чем-то, в противном случае будет черный экран.Поэтому, чтобы избежать черного экрана, все неиспользуемые слоты должны быть заполнены текстурами с идентификатором 0 (это из-за использования драйвера с открытым исходным кодом?).Но тогда возникает другая проблема - странные моменты.Было установлено, что они появляются с включенным PCF (мягкие тени).Вот проблемная область кода шейдера:

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;

Есть идеи?Примечание: все отлично работает на Intel HD Graphics и Nvidia

Ответы [ 2 ]

1 голос
/ 23 марта 2019

Год или два назад у меня была похожая проблема с каскадными теневыми картами, где она отлично работала на Intel и Nvidia, но на AMD я получил только первый каскад.Очевидно, если у вас есть простые массивы сэмплеров (например, sampler2D tex[5]), вам нужно установить каждый элемент на AMD, тогда как Nvidia и Intel предполагают, что он является последовательным в памяти, и автоматически связывают все текстуры, если вы связываете первый.Мое решение состояло в том, чтобы использовать массивы сэмплеров (например, sampler2DArray), которые отлично работали на каждом графическом процессоре.

1 голос
/ 22 марта 2019

Проблема решена.

  1. Для корректной работы мне пришлось заполнить весь массив samplerCube нулями.В противном случае будет черный экран.
  2. На счет бликов: видимо, проблема была в открытых драйверах.Тест проводился на Windows с официальными драйверами, и все отображалось правильно, включая коррекцию цвета.Но 1-й пункт не отменяется.
...