我有一个纹理,想用作间接辐射光。
存在一个问题,当我对该纹理的最低 mip 进行采样时,结果如下所示:
但实际上应该是这样的:
我使用计算着色器来生成辐射数据,但对于调试情况,您可以使用常规立方体贴图和硬件生成的 mipmap(glGenerateTextureMipmap
)或从文件中加载它。结果将是相同的 - 硬面转换。
顶点着色器:
#version 460 core
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_normal;
//per instance
layout(location = 2) in vec4 a_modelToWorld0;
layout(location = 3) in vec4 a_modelToWorld1;
layout(location = 4) in vec4 a_modelToWorld2;
layout(location = 5) in vec4 a_modelToWorld3;
layout(location = 0) out vec3 v_worldPosition;
layout(location = 1) out vec3 v_worldNormal;
layout(std140, binding = 0) uniform PerFrame
{
mat4 cameraModel;
mat4 viewProjection;
} u_frame;
void main()
{
mat4 model = mat4(a_modelToWorld0, a_modelToWorld1, a_modelToWorld2, a_modelToWorld3);
vec4 worldPosition = model * vec4(a_position, 1.0f);
v_worldPosition = worldPosition.xyz;
v_worldNormal = mat3(model) * a_normal;
gl_Position = u_frame.viewProjection * worldPosition;
}
像素着色器:
#version 460 core
layout(location = 0) out vec4 f_color;
layout(location = 0) in vec3 v_worldPosition;
layout(location = 1) in vec3 v_worldNormal;
layout(std140, binding = 0) uniform PerFrame
{
mat4 cameraModel;
mat4 viewProjection;
} u_frame;
layout(binding = 1) uniform samplerCube u_indirectRadiance;
void main()
{
vec3 normal = normalize(v_worldNormal);
vec3 viewDirection = normalize(u_frame.cameraModel[3].xyz - v_worldPosition);
vec3 reflectionDir = reflect(-viewDirection, normal);
vec3 color = textureLod(u_indirectRadiance, reflectionDir, 10.0f).rgb;
f_color = vec4(color, 1.0f);
}
我做了一些调试并检查了normal
,,这些向量看起来是正确的
viewDirection
:reflectionDir
我将这些值与我的 DX11 应用程序进行了比较,该应用程序为我提供了正确的间接辐射光,并且它们看起来都一样。
至于问题本身,它与立方体贴图数据无关,因为我已经检查过了。它有正确的值。
采样方式存在问题。
创建辐射立方体贴图和采样器的代码
GLuint sampler;
glCreateSamplers(1, &sampler);
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
GLuint texture;
glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &texture);
glTextureStorage2D(texture, 11, GL_RGBA32F, 1024, 1024);
//here you can load a texture from a file
//eg. dds
/*
DirectX::TexMetadata meta;
DirectX::ScratchImage image;
//assuming that radianceCubemap.dds is 1024x1024, cubemap and has mipmaps generated correctly
DirectX::LoadFromDDSFile("assets/radianceCubemap.dds", DirectX::DDS_FLAGS_NONE, &meta, image);
GLuint target = GL_TEXTURE_CUBE_MAP;
GLuint format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; //assuming format is DXGI_FORMAT_BC1_UNORM, but this is just an example
for (std::size_t level = 0; level < meta.mipLevels; ++level) {
for (std::size_t face = 0; face < meta.arraySize; ++face) {
const DirectX::Image* img = image.GetImage(level, face, 0);
if (img) {
glCompressedTextureSubImage3D(texture, level, 0, 0, face, img->width, img->height, 1, format, img->slicePitch, img->pixels);
}
}
}
*/
/*
or you can do whatever, it does not matter, just make sure it's a 1024x1024 cubemap with 11 mips
*/
我的立方体贴图:
正如你所见,这一切都是正确的
我的代码有什么问题?我该如何修复它?
在最后一个 mipmap 级别中,纹理的每一边都是 1x1。据我所知,默认情况下,跨立方体贴图纹理边进行过滤是禁用的。因此,即使使用线性过滤,也只有 1 个纹素,这就是无法获得渐变的原因。如果您调用,
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS)
则启用跨边过滤。