GlGetTexImage возвращает 0 для текстуры, даже если текстура загружена и правильно заполнена в памяти графического процессора

Что я пытаюсь сделать

Считайте каждую отдельную грань текстуры кубической карты в массив с плавающей запятой на ЦП, чтобы я мог сохранить каждую грань на диск в виде файла изображения.

Проблема:

glGetTexImage возвращает данные, не соответствующие тому, что я наблюдаю на стороне графического процессора (подробнее позже).

Контекст: Я реализую зонды отражения для своего игрового движка OpenGL.

Вот краткий псевдокод, показывающий порядок работы:

entityList = LoadScene(); // Load entities along with their geometry, textures, shaders and other non-graphics components

bakedData.InitialiseReflectionProbes(std::vector<> positions); // Tell the bakedData class where the reflection probes are located

BakeReflectionProbes() { // Run the reflection probe baking system (more details later)
    // Render scene into cubemap from each probe position

    // Process cubemap render

    // Write textures to files
};

Теперь подробнее о самой проблеме.

Когда я вызываю glGetTexImage() с правильной привязкой текстуры, только первая грань кубической карты фактически возвращает правильные данные в массив с плавающей запятой, остальные грани — все 0 и полностью черные.

Это несовместимо с тем, что я вижу на стороне графического процессора. Я наблюдаю за кадром в RenderDoc при каждом вызове отрисовки. Я вижу каждый этап процесса запекания, он правильно захватывает сцену, и я прекрасно вижу каждую грань кубической карты. В вызовах API я вижу, что правильная текстура также привязана перед вызовом glGetTexImage.

Теперь я покажу, как я это делаю в коде, а затем покажу еще код, который приведет к этому моменту, например, как генерируются текстуры:

void BakedData::WriteReflectionProbesToFile()
{
    unsigned int numProbes = reflectionProbes.size();
    for (unsigned int i = 0; i < reflectionProbes.size(); i++) {
        ReflectionProbe* probe = reflectionProbes[i];
    ReflectionProbeEnvironmentMap envMap = probe->GetProbeEnvMap();
    unsigned int probeID = probe->GetFileID();

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

    faceWidth = probe->GetFaceWidth();
        faceHeight = probe->GetFaceHeight();

        GLfloat* floatData = new GLfloat[faceWidth * faceHeight * 3];

    glBindTexture(GL_TEXTURE_CUBE_MAP, envMap.cubemapID);
        glFinish();
    
        for (unsigned int j = 0; j < 6; j++) {

            glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 0, GL_RGB, GL_FLOAT, floatData);
        glFinish();

            // Debugging: Print the first pixel of each face
            std::cout << "Face " << j << " first pixel RGB: "
                << floatData[0] << ", "
        << floatData[1] << ", "
        << floatData[2] << std::endl;
    }
        delete[] floatData;
        
    }
}

Приведенный выше код для каждого датчика отражения будет правильно считывать только грань кубической карты GL_TEXTURE_CUBE_MAP_POSITIVE_X. Остальные все читаются как черные.

Ниже показано, как настраиваются текстуры отражающего зонда:

void ReflectionProbe::SetupTextureMaps()
{
    // ------ Set up base cubemap ------
    // ---------------------------------
    glGenTextures(1, &envMap.cubemapID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, envMap.cubemapID);

    for (unsigned int i = 0; i < 6; i++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, faceWidth, faceHeight, 0, GL_RGB, GL_FLOAT, nullptr);
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

    // ----- Set up irradiance map -----
    // ---------------------------------
    glGenTextures(1, &envMap.irradianceID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, envMap.irradianceID);
    for (unsigned int i = 0; i < 6; i++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 32, 32, 0, GL_RGB, GL_FLOAT, nullptr);
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // ----- Set up pre-filter map -----
    // ---------------------------------
    glGenTextures(1, &envMap.prefilterID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, envMap.prefilterID);
    for (unsigned int i = 0; i < 6; i++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 128 * 2, 128 * 2, 0, GL_RGB, GL_FLOAT, nullptr);
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
}

Интересно, что все текстуры кубической карты освещенности читаются совершенно нормально и выполняются точно так же, как текстуры кубической карты скайбокса:

void BakedData::WriteReflectionProbesToFile()
{
    ...
            // -  Write irradiance -
            // ---------------------
            std::cout << std::endl << "Writing irradiance map" << std::endl;
            std::cout <<              "----------------------" << std::endl;

            floatData = new GLfloat[32 * 32 * 3];

            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            glBindTexture(GL_TEXTURE_CUBE_MAP, envMap.irradianceID);
            glFinish();

            for (unsigned int j = 0; j < 6; j++) {
                //path = "Data/ReflectionProbe/" + probe->GetSceneName() + "/" + probeString + "/Irradiance/" += cubemapFaceToString[GL_TEXTURE_CUBE_MAP_POSITIVE_X + j] + ".hdr";

                glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 0, GL_RGB, GL_FLOAT, floatData);
                glFinish();

                // Debugging: Print the first pixel of each face
                std::cout << "Face " << j << " first pixel RGB: "
                    << floatData[0] << ", "
                    << floatData[1] << ", "
                    << floatData[2] << std::endl;

                //stbi_write_hdr(path.c_str(), 32, 32, 3, floatData);
            }

            delete[] floatData;
    ...
}

Я покажу немного больше деталей о системе запекания, о том, как датчики на самом деле захватывают сцену:

Я понимаю, что это много кода, я не ожидаю, что кто-нибудь сможет воспроизвести и исправить эту проблему напрямую, я просто хочу убедиться, что вы можете видеть полное время жизни текстур, то, как они визуализируются, генерируются и т. д. прочитать и т. д., чтобы иметь полную картину

for (int i = 0; i \< numProbes; i++) {
ReflectionProbe\* probe = probes\[i\];
std::cout \<\< "        - Baking probe " \<\< i + 1 \<\< " / " \<\< numProbes \<\< std::endl;

    // Capture scene
    width = probe->GetFaceWidth();
    height = probe->GetFaceHeight();
    
    glViewport(0, 0, width, height);
    glBindFramebuffer(GL_FRAMEBUFFER, reflectionFBO);
    
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, probe->GetProbeEnvMap().cubemapID, 0);
    
    // Resize depth texture buffer
    glBindTexture(GL_TEXTURE_CUBE_MAP, depthBuffer);
    for (unsigned int j = 0; j < 6; j++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
    }
    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthBuffer, 0);
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // error check
    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        std::cout << "ERROR::RENDERMANAGER::Cubemap FBO incomplete, status: 0x\%x\n" << status << std::endl;
    }
    
    reflectionShader->Use();
    
    glm::vec3 position = probe->GetWorldPosition();
    glm::mat4 projection = glm::perspective(glm::radians(90.0f), (float)width / (float)height, probe->GetNearClip(), probe->GetFarClip());
    
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    
    for (unsigned int i = 0; i < 6; ++i) {
        reflectionShader->setMat4("shadowMatrices[" + std::to_string(i) + "]", cubemapTransforms[i]); // Ignore the "shadowMatrices", this is just copied from a shadowmapping shader
    }
    
    reflectionShader->setVec3("viewPos", position);
    
    for (Entity* entity : entityList) {
        OnAction(entity); // This function just sets up shader uniforms from the geometry component of the entity, binds vertex data and material textures and draws the object
    }
    
    cubemapTransforms.clear();
    
    // Process capture
    glDisable(GL_CULL_FACE);

    // Convolute env map
    glBindFramebuffer(GL_FRAMEBUFFER, cubeCaptureFBO);
    glBindRenderbuffer(GL_RENDERBUFFER, cubeCaptureRBO);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 32, 32);

    // Set up projections for each cubemap face
    glm::mat4 captureProjection = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f);
    glm::mat4 captureViews[] = {
        glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
        glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
        glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
        glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)),
        glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
        glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f))
    };

    // Set up irradiance shader uniforms and bind env cupemap
    Shader* irradianceShader = resourceManager->CreateIrradianceShader();
    irradianceShader->Use();
    irradianceShader->setInt("environmentMap", 0);
    irradianceShader->setMat4("projection", captureProjection);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);

    glViewport(0, 0, 32, 32);
    glBindFramebuffer(GL_FRAMEBUFFER, cubeCaptureFBO);
    for (unsigned int j = 0; j < 6; ++j)
    {
        irradianceShader->setMat4("view", captureViews[j]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, irradianceMap, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        resourceManager->DefaultCube().DrawWithNoMaterial();
    }
    
    // Prefilter
    // Capture prefilter mipmap levels
    // -------------------------------
    Shader* prefilterShader = resourceManager->CreatePrefilterShader();
    prefilterShader->Use();
    prefilterShader->setInt("environmentMap", 0);
    prefilterShader->setMat4("projection", captureProjection);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);

    glBindFramebuffer(GL_FRAMEBUFFER, cubeCaptureFBO);
    unsigned int maxMipLevels = 5;
    for (unsigned int mip = 0; mip < maxMipLevels; mip++) {
        // resize framebuffer
    unsigned int mipWidth = (128 * 2) * std::pow(0.5, mip);
    unsigned int mipHeight = (128 * 2) * std::pow(0.5, mip);

    glBindRenderbuffer(GL_RENDERBUFFER, cubeCaptureRBO);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight);

    glViewport(0, 0, mipWidth, mipHeight);

    float roughness = (float)mip / (float)(maxMipLevels - 1);
    prefilterShader->setFloat("roughness", roughness);
    for (unsigned int j = 0; j < 6; j++) {
        prefilterShader->setMat4("view", captureViews[j]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, prefilterMap, mip);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        resourceManager->DefaultCube().DrawWithNoMaterial();
            }
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glEnable(GL_CULL_FACE);
    
}

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, renderManager->ScreenWidth(), renderManager->ScreenHeight());

// Write to file
// -------------
renderManager->GetBakedData().WriteReflectionProbesToFile();

Ниже приведены снимки экрана из RenderDoc, они взяты из вызова отрисовки на этапе захвата сцены в системе запекания зонда отражения, которая визуализирует текстуру кубической карты, из которой я пытаюсь прочитать. Как вы можете видеть, лицо положительного и отрицательногоX отображается правильно. Я также могу подтвердить, что другие лица также отображаются правильно:

Положительный X Скриншот RenderDoc, показывающий визуализированную текстуру текстуры с положительным X-гранью CubemapID

Отрицательный X Скриншот RenderDoc, показывающий отрендеренную текстуру текстуры CubemapID с отрицательным лицом X

Но при чтении их обратно в процессор только положительная сторона X дает мне правильные значения.

Я также хочу уточнить, что я пробовал вызывать glGetError до и после чтения текстуры в ЦП, никаких ошибок не возвращалось.

Я перепробовал все, что мог придумать:

  • Я попробовал использовать glGetTextureImage(), который не работает напрямую с гранями кубической карты, поэтому вместо этого я использовал glGetTextureSubImage() и указал каждую грань кубической карты как смещение по оси Z, это дало те же результаты, что и glGetTexImage().
  • Я попробовал привязать каждую грань текстуры к временному фреймбуферу, созданному специально для этого, установив буфер чтения в привязанный цвет и вызвав glReadPixels(). Это снова вернуло ту же проблему. Только положительный X кубической карты был правильным
  • Я даже пробовал создавать совершенно новые текстуры с помощью функции записи в файл. Сначала я сгенерировал новые текстуры в функции записи в файл (где я считываю их обратно в процессор). Я установил для них те же параметры, что и исходные текстуры. Затем я связал кубическую карту и рендерил каждую грань кубической карты в эти новые текстуры GL_TEXTURE_2D, которые я создал с помощью нового шейдера. Затем я подтвердил в RenderDoc, что результаты были правильными, в каждой 2D-текстуре была отображена правильная соответствующая грань кубической карты. Но, тем не менее, по какой-то странной причине вызов glGetTexImage() для каждой из 2D-текстур дал мне одну и ту же проблему, хотя теперь они были полностью отделены от исходной текстуры кубической карты. Я также попробовал выполнить glReadPixels() после рендеринга целевой текстуры, при этом текстура все еще была прикреплена к фреймбуферу, но опять же, та же проблема.
  • Я также попробовал создать уникальные массивы с плавающей запятой для каждой грани кубической карты, чтобы не было проблем с загрузкой разных данных в один буфер, но проблема осталась та же.
  • Также попробовал метод копирования исходной текстуры и чтения копии с помощью glCopyTexImage(), та же проблема.

Обновлено:

  • Я также пробовал напрямую нацеливаться на GL_TEXTURE_CUBE_MAP_NEGATIVE_X, без других вызовов glGetTexImage(), та же проблема.

@BDL да, я пробовал это. Сейчас добавлю это в пост. Но да, та же проблема и при прямом нацеливании на NEGATIVE_X. То же самое с любыми другими гранями, кроме положительного x.

Henry 29.07.2024 17:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решено:

Проблема возникла из-за того, как я изначально визуализировал текстуру кубической карты.

reflectionShader->Use();
    
    glm::vec3 position = probe->GetWorldPosition();
    glm::mat4 projection = glm::perspective(glm::radians(90.0f), (float)width / (float)height, probe->GetNearClip(), probe->GetFarClip());
    
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    cubemapTransforms.push_back(projection * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
    
    for (unsigned int i = 0; i < 6; ++i) {
        reflectionShader->setMat4("shadowMatrices[" + std::to_string(i) + "]", cubemapTransforms[i]); // Ignore the "shadowMatrices", this is just copied from a shadowmapping shader
    }
    
    reflectionShader->setVec3("viewPos", position);
    
    for (Entity* entity : entityList) {
        OnAction(entity); // This function just sets up shader uniforms from the geometry component of the entity, binds vertex data and material textures and draws the object
    }
    
    cubemapTransforms.clear();

Вышеупомянутый метод, используемый в исходном коде, работает за счет использования одного вызова отрисовки для каждой сетки для одновременного рендеринга всех 6 граней кубической карты. Это делается в геометрическом шейдере. По какой-то причине это вызывает проблемы, когда вы хотите прочитать текстуру обратно в процессор.

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

Решение:

Явно визуализируйте каждую грань кубической карты с помощью нового вызова отрисовки для каждой грани и сетки:

    glViewport(0, 0, width, height);
    for (unsigned int j = 0; j < 6; ++j)
    {
        reflectionShaderTest->setMat4("view", captureViews[j]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, probe->GetProbeEnvMap().cubemapID, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, depthBuffer, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        for (Entity* entity : entityList) {
            OnAction(entity);
        }
    }

Таким образом, каждая грань кубической карты теперь правильно визуализируется напрямую.

OpenGL определенно не так должен вести себя в этой ситуации. Я думаю, что это вызвано ошибкой драйвера. Мне было бы очень интересно услышать, является ли первоначальная проблема даже при выполнении на графическом процессоре другого производителя.

BDL 30.07.2024 00:19

Первоначально это было сделано на Nvidia 3080ti, попробовал еще раз на своем ноутбуке с картой AMD, проблема не исчезла. Это очень странная проблема, я действительно думал, что схожу с ума @BDL

Henry 30.07.2024 16:08

Другие вопросы по теме