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 (offset = 64) float roughness;
|
||||
layout (offset = 68) uint numSamples;
|
||||
} pushConsts;
|
||||
} consts;
|
||||
|
||||
const float PI = 3.1415926536;
|
||||
|
||||
|
|
@ -69,14 +69,29 @@ vec3 prefilterEnvMap(vec3 R, float roughness)
|
|||
vec3 V = R;
|
||||
vec3 color = vec3(0.0);
|
||||
float totalWeight = 0.0;
|
||||
for(uint i = 0u; i < pushConsts.numSamples; i++) {
|
||||
vec2 Xi = hammersley2d(i, pushConsts.numSamples);
|
||||
float envMapDim = float(textureSize(samplerEnv, 0).s);
|
||||
for(uint i = 0u; i < consts.numSamples; i++) {
|
||||
vec2 Xi = hammersley2d(i, consts.numSamples);
|
||||
vec3 H = importanceSample_GGX(Xi, roughness, N);
|
||||
vec3 L = 2.0 * dot(V, H) * H - V;
|
||||
float dotNL = clamp(dot(N, L), 0.0, 1.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;
|
||||
|
||||
}
|
||||
}
|
||||
return (color / totalWeight);
|
||||
|
|
@ -86,5 +101,5 @@ vec3 prefilterEnvMap(vec3 R, float roughness)
|
|||
void main()
|
||||
{
|
||||
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);
|
||||
}
|
||||
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()
|
||||
|
|
@ -1199,7 +1197,7 @@ public:
|
|||
struct PushBlock {
|
||||
glm::mat4 mvp;
|
||||
float roughness;
|
||||
uint32_t numSamples = 1024u;
|
||||
uint32_t numSamples = 32u;
|
||||
} pushBlock;
|
||||
|
||||
VkPipelineLayout pipelinelayout;
|
||||
|
|
@ -1439,7 +1437,7 @@ public:
|
|||
// 3D object
|
||||
uboMatrices.projection = camera.matrices.perspective;
|
||||
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;
|
||||
memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue