OpenGL立方体贴图:写入到mipmap

3

[目标] 我需要在OpenGL 4+中写入CubeMap的特定mipmap级别。每个mipmap级别越深,图像越模糊。

[问题] 问题是如果我只在级别0上写入,所有mipmap级别都有相同的图像,如果我尝试只在其他mipmap级别上写入,则什么也没有。

[更新] 我非常确定问题在于textureLod始终将其截止到基本LOD 0。无论我尝试通过它获取哪个mipmap级别,它都返回基本LOD。

这是我的cubemap生成(我正在尝试拥有6个mipmap级别,包括基本级别):

GLuint PreFilteredEnvTex;
glGenTextures(1, &PreFilteredEnvTex);
glBindTexture(GL_TEXTURE_CUBE_MAP, PreFilteredEnvTex);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 5);
for (int i = 0; i < 6; ++i)
{
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, 0);
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);

Utils::checkGlError("Generate PreFilteredEnvMap");

以下是我尝试向每个mipmap级别写入的示例:

//Compute pre filtered environnement maps
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBindFramebuffer(GL_FRAMEBUFFER, fboManager["fx"]);
glViewport(0, 0, screenWidth, screenHeight);
glClear(GL_COLOR_BUFFER_BIT);

const int MIPMAPLEVELS = 6;
const int MIPMAPBASELEVELSIZE = 512;
int MipMapTextureSize;
glBindVertexArray(vaoManager["cube"]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->texture_id);
Shader* PreEnvFilter = shaderManager["PreEnvFilter"];
PreEnvFilter->use();

glm::vec3 EyePosition = glm::vec3(0.f);
// Light space matrices
glm::mat4 CubeMapProjection = glm::perspective(glm::radians(90.f), 1.f, 1.f, 100.f);
std::vector<glm::mat4> worldToLight;
worldToLight.push_back(CubeMapProjection * glm::lookAt(EyePosition, EyePosition + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
worldToLight.push_back(CubeMapProjection * glm::lookAt(EyePosition, EyePosition + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
worldToLight.push_back(CubeMapProjection * glm::lookAt(EyePosition, EyePosition + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)));
worldToLight.push_back(CubeMapProjection * glm::lookAt(EyePosition, EyePosition + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)));
worldToLight.push_back(CubeMapProjection * glm::lookAt(EyePosition, EyePosition + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)));
worldToLight.push_back(CubeMapProjection * glm::lookAt(EyePosition, EyePosition + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)));
for (GLuint i = 0; i < 6; ++i)
    PreEnvFilter->SetMatrix4(("ViewMatrix[" + to_string(i) + "]").c_str(), worldToLight[i]);
PreEnvFilter->SetInt("EnvMapSampler", 0);
PreEnvFilter->SetMatrix4("Model", glm::mat4());
//For each faces compute all mipmaps levels
for (unsigned int j = 0; j < MIPMAPLEVELS; ++j)
{
    //For each mipmap level, render the filtered environnement in it
    MipMapTextureSize = std::max(1, MIPMAPBASELEVELSIZE / (1 << j));
    glViewport(0, 0, MipMapTextureSize, MipMapTextureSize);
    //glViewport(0, 0, MIPMAPBASELEVELSIZE, MIPMAPBASELEVELSIZE);
    float roughness = (j + 0.5f) / MIPMAPLEVELS;
    PreEnvFilter->SetFloat("Roughness", roughness);
    //Bind to the current buffer
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, PreFilteredEnvTex, j);
    glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_INT, (void*)0);
}

PreEnvFilter->unuse();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);

Utils::checkGlError("Initialize PreFilteredEnvMap");

我相信我的着色器正在工作,因为如果我循环所有mipmap级别并且只绘制到基本级别,我会得到一个好看的结果: 如果我只对所有mipmap级别写入级别0的结果 以下是用于打印立方体贴图的片段着色器(TexCoords根据我想要绘制的面进行修改):
#version 430

uniform int MipMapLevel;
uniform samplerCube CubeMap;
in vec3 TexCoords;
out vec4 Color;

void main()
{
    Color = textureLod(CubeMap, TexCoords, MipMapLevel);
}

如果我写入所有mipmap级别,那么所有mipmap级别上的图像都是相同的(实际上,如果我只写入0级,所有mipmap级别上的结果也是相同的)。 相同的结果,不同的mipmap级别 我的结论如下:
- 我的mipmap生成不好,但我已经阅读了规格,glGenerateMipmap应该完成了工作。 - 当我尝试通过glFramebufferTexture绑定mipmap级别时,我遇到了问题,但在我看来这似乎并没有错。 - 我用于绘制立方体贴图的着色器似乎不起作用?我以前从未使用过textureLod,但据我所知,我在这里使用得很正确,对吗? - 如果有人已经做过类似的事情,我会非常感激一些帮助!毕竟,我花了很多时间在这上面,在DX11中没有问题地完成了这个简单的OpenGL任务:(
P.S:OpenGL没有报告任何错误。

抱歉,第二个问题应该被编辑过了,实际上我正在传递j,我之前用5进行测试是为了看看是否在mipmap级别5中写入了某些内容,但事实并非如此。至于第一个问题,也许我表达得不太清楚,但你所提到的着色器只是生成问题图像的着色器(即我的“调试绘制”),程序中使用的着色器更加复杂,但正如我所说,我百分之百确定它能够正常工作。 - Toffanim
好的,我认为你需要使用glFrameBufferTexture2D,它允许你指定要绘制到的立方体贴图面。这意味着你应该有两个嵌套循环:对于所有6个面,对于所有mipmap级别;结果是6 * #mipmap_levels次绘制调用。 - user2693780
实际上,我正在使用几何着色器一次性渲染所有面(这就是为什么我有6个视图矩阵并渲染一个单位立方体)。我可以尝试渲染到一个面的mipmap并查看是否有效,但我认为这只是mipmap问题,而不是渲染到cubemap的问题(因为您可以看到图片实际上是有效的,如果我只使用mipmap的基本级别)。 - Toffanim
我在所有mipmap级别上都有相同的图像。"相同的图像"是什么意思?你不可能有完全相同的图像;因为mipmap级别较小,所以它们不同。 - Nicol Bolas
@NicolBolas 嗯,这就是问题所在!如果我在mipmap级别0上写入,当我在另一个mipmap级别上调用textureLod时,我会得到完全相同的纹理。嗯,我不确定glGenerateMipmaps是否生成了我的mipmaps(我怎么知道呢?),而且似乎当我想要渲染到mipmap级别时它不起作用,但是当我使用没有mipmaps的立方体贴图时,我可以在基本级别0上无任何问题地写入。 - Toffanim
显示剩余4条评论
1个回答

2

经过尝试几乎所有的方法,我最终通过以下方式生成我的立方体贴图:

GLuint PreFilteredEnvTex;
glGenTextures(1, &PreFilteredEnvTex);
glBindTexture(GL_TEXTURE_CUBE_MAP, PreFilteredEnvTex);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 5);

for (int i = 0; i < 6; ++i)
{
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, 0);
}   
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
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);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);

我已经将最小过滤器更改为GL_LINEAR_MIPMAP_LINEAR,并在末尾调用glGenerateMipmap,而不是像这个链接中所做的那样。感谢您的关注 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接