Updated env map prefiltering shader (requires less samples)
This commit is contained in:
parent
486a6a94c0
commit
b672bee4e5
3 changed files with 22 additions and 9 deletions
|
|
@ -8,7 +8,7 @@ layout (binding = 0) uniform samplerCube samplerEnv;
|
||||||
layout(push_constant) uniform PushConsts {
|
layout(push_constant) uniform PushConsts {
|
||||||
layout (offset = 64) float roughness;
|
layout (offset = 64) float roughness;
|
||||||
layout (offset = 68) uint numSamples;
|
layout (offset = 68) uint numSamples;
|
||||||
} pushConsts;
|
} consts;
|
||||||
|
|
||||||
const float PI = 3.1415926536;
|
const float PI = 3.1415926536;
|
||||||
|
|
||||||
|
|
@ -69,14 +69,29 @@ vec3 prefilterEnvMap(vec3 R, float roughness)
|
||||||
vec3 V = R;
|
vec3 V = R;
|
||||||
vec3 color = vec3(0.0);
|
vec3 color = vec3(0.0);
|
||||||
float totalWeight = 0.0;
|
float totalWeight = 0.0;
|
||||||
for(uint i = 0u; i < pushConsts.numSamples; i++) {
|
float envMapDim = float(textureSize(samplerEnv, 0).s);
|
||||||
vec2 Xi = hammersley2d(i, pushConsts.numSamples);
|
for(uint i = 0u; i < consts.numSamples; i++) {
|
||||||
|
vec2 Xi = hammersley2d(i, consts.numSamples);
|
||||||
vec3 H = importanceSample_GGX(Xi, roughness, N);
|
vec3 H = importanceSample_GGX(Xi, roughness, N);
|
||||||
vec3 L = 2.0 * dot(V, H) * H - V;
|
vec3 L = 2.0 * dot(V, H) * H - V;
|
||||||
float dotNL = clamp(dot(N, L), 0.0, 1.0);
|
float dotNL = clamp(dot(N, L), 0.0, 1.0);
|
||||||
if(dotNL > 0.0) {
|
if(dotNL > 0.0) {
|
||||||
color += texture(samplerEnv, L).rgb * dotNL;
|
// Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
|
||||||
|
|
||||||
|
float dotNH = clamp(dot(N, H), 0.0, 1.0);
|
||||||
|
float dotVH = clamp(dot(V, H), 0.0, 1.0);
|
||||||
|
|
||||||
|
// Probability Distribution Function
|
||||||
|
float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001;
|
||||||
|
// Slid angle of current smple
|
||||||
|
float omegaS = 1.0 / (float(consts.numSamples) * pdf);
|
||||||
|
// Solid angle of 1 pixel across all cube faces
|
||||||
|
float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
|
||||||
|
// Biased (+1.0) mip level for better result
|
||||||
|
float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
|
||||||
|
color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL;
|
||||||
totalWeight += dotNL;
|
totalWeight += dotNL;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (color / totalWeight);
|
return (color / totalWeight);
|
||||||
|
|
@ -86,5 +101,5 @@ vec3 prefilterEnvMap(vec3 R, float roughness)
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 N = normalize(inPos);
|
vec3 N = normalize(inPos);
|
||||||
outColor = vec4(prefilterEnvMap(N, pushConsts.roughness), 1.0);
|
outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -260,8 +260,6 @@ public:
|
||||||
models.objects.push_back(model);
|
models.objects.push_back(model);
|
||||||
}
|
}
|
||||||
textures.environmentCube.loadFromFile(ASSET_PATH "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue);
|
textures.environmentCube.loadFromFile(ASSET_PATH "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue);
|
||||||
// Irradiance map generated offline with https://github.com/dariomanesku/cmft
|
|
||||||
// textures.irradianceCube.loadFromFile(ASSET_PATH "textures/hdr/pisa_cube_irradiance.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDescriptors()
|
void setupDescriptors()
|
||||||
|
|
@ -1199,7 +1197,7 @@ public:
|
||||||
struct PushBlock {
|
struct PushBlock {
|
||||||
glm::mat4 mvp;
|
glm::mat4 mvp;
|
||||||
float roughness;
|
float roughness;
|
||||||
uint32_t numSamples = 1024u;
|
uint32_t numSamples = 32u;
|
||||||
} pushBlock;
|
} pushBlock;
|
||||||
|
|
||||||
VkPipelineLayout pipelinelayout;
|
VkPipelineLayout pipelinelayout;
|
||||||
|
|
@ -1439,7 +1437,7 @@ public:
|
||||||
// 3D object
|
// 3D object
|
||||||
uboMatrices.projection = camera.matrices.perspective;
|
uboMatrices.projection = camera.matrices.perspective;
|
||||||
uboMatrices.view = camera.matrices.view;
|
uboMatrices.view = camera.matrices.view;
|
||||||
uboMatrices.model = glm::rotate(glm::mat4(), glm::radians(-90.0f + (models.objectIndex == 1 ? 45.0f : 0.0f)), glm::vec3(0.0f, 1.0f, 0.0f));
|
uboMatrices.model = glm::rotate(glm::mat4(), glm::radians(90.0f + (models.objectIndex == 1 ? -45.0f : 0.0f)), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
uboMatrices.camPos = camera.position * -1.0f;
|
uboMatrices.camPos = camera.position * -1.0f;
|
||||||
memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices));
|
memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue