ingest more of brdf for bounces

This commit is contained in:
Ivan Avdeev 2021-09-01 11:01:40 -07:00 committed by Ivan Avdeev
parent 9c330e4118
commit e4aea1486f
2 changed files with 54 additions and 35 deletions

View File

@ -951,3 +951,23 @@ bool evalIndirectCombinedBRDF(vec2 u, vec3 shadingNormal, vec3 geometryNormal, v
return true;
}
// Calculates probability of selecting BRDF (specular or diffuse) using the approximate Fresnel term
float getBrdfProbability(MaterialProperties material, vec3 V, vec3 shadingNormal) {
// Evaluate Fresnel term using the shading normal
// Note: we use the shading normal instead of the microfacet normal (half-vector) for Fresnel term here. That's suboptimal for rough surfaces at grazing angles, but half-vector is yet unknown at this point
float specularF0 = luminance(baseColorToSpecularF0(material.baseColor, material.metalness));
float diffuseReflectance = luminance(baseColorToDiffuseReflectance(material.baseColor, material.metalness));
float Fresnel = saturate(luminance(evalFresnel(vec3(specularF0), shadowedF90(vec3(specularF0)), max(0.0f, dot(V, shadingNormal)))));
// Approximate relative contribution of BRDFs using the Fresnel term
float specular = Fresnel;
float diffuse = diffuseReflectance * (1.0f - Fresnel); //< If diffuse term is weighted by Fresnel, apply it here as well
// Return probability of selecting specular BRDF over diffuse BRDF
float p = (specular / max(0.0001f, (specular + diffuse)));
// Clamp probability to avoid undersampling of less prominent BRDF
return clamp(p, 0.1f, 0.9f);
}

View File

@ -151,7 +151,7 @@ vec3 computeLighting(vec3 view_dir, MaterialProperties material) {
if (emissive_kusok_index == uint(payload.kusok_index)) {
// TODO do we need to do this when we have textures?
//C += kc * vec3(hash(float(kusok_index)), hash(float(kusok_index)+15.43), hash(float(kusok_index)+34.));//kusok.emissive.rgb;
//C += throughput * vec3(hash(float(kusok_index)), hash(float(kusok_index)+15.43), hash(float(kusok_index)+34.));//kusok.emissive.rgb;
//C = vec3(1., 0., 1.);
continue;
}
@ -256,7 +256,7 @@ void main() {
vec4 target = ubo.inv_proj * vec4(uv.x, uv.y, 1, 1);
vec3 direction = (ubo.inv_view * vec4(normalize(target.xyz), 0)).xyz;
vec3 kc = vec3(1.);
vec3 throughput = vec3(1.);
vec3 C = vec3(0.);
payload.t_offset = .0;
@ -277,8 +277,9 @@ void main() {
origin, 0., direction, L,
ray_payload_loc);
// Sky/envmap
if (payload.hit_pos_t.w <= 0.) {
C += kc * payload.albedo;
C += throughput * payload.albedo;
break;
}
@ -286,49 +287,47 @@ void main() {
material.baseColor = payload.albedo;
material.metalness = 0.f;
material.emissive = payload.emissive;
material.roughness = .1f;// payload.roughness;
material.roughness = .1f; // FIXME payload.roughness;
C += kc * payload.emissive;
C += throughput * payload.emissive;
if ((payload.material_flags & kXVkMaterialFlagLighting) != 0) {
C += kc * computeLighting(-direction, material);
C += throughput * computeLighting(-direction, material);
}
#if 1
if (bounce == push_constants.bounces - 1)
break;
#else
float through_probablity = .0;
if ((payload.material_flags & kXVkMaterialFlagRefractive) != 0) {
through_probablity = .5; // .... FIXME
}
if ((payload.material_flags & kXVkMaterialFlagAdditive) != 0) {
through_probablity = 1.;
}
if (through_probablity > 0. && rand01() < through_probablity) {
// Refraction/additive
origin = payload.hit_pos_t.xyz - normal_offset_fudge * payload.normal;
if ((payload.material_flags & kXVkMaterialFlagAdditive) == 0) {
kc *= payload.albedo; // ... FIXME
}
vec3 shadingNormal = payload.normal;
vec3 geometryNormal = payload.normal;
vec3 V = -direction;
int brdfType;
if (material.metalness == 1.0f && material.roughness == 0.0f) {
// Fast path for mirrors
brdfType = SPECULAR_TYPE;
} else {
// Diffuse/specular bounce
origin = payload.hit_pos_t.xyz + normal_offset_fudge * payload.normal;
// TODO this is totally not correct
direction = normalize(mix(
reflect(direction, payload.normal),
//vec3(rand01(), rand01(), rand01())*2.-1.,
rand3_f01(uvec3(gl_LaunchIDEXT.xy, (bounce + 1) * push_constants.random_seed)) * 2. - 1.,
payload.roughness
));
direction *= dot(direction, payload.normal);
kc *= mix(vec3(1.), dot(direction, payload.normal) * payload.albedo, payload.roughness);
// Decide whether to sample diffuse or specular BRDF (based on Fresnel term)
float brdfProbability = getBrdfProbability(material, V, shadingNormal);
if (rand01() < brdfProbability) {
brdfType = SPECULAR_TYPE;
throughput /= brdfProbability;
} else {
brdfType = DIFFUSE_TYPE;
throughput /= (1.0f - brdfProbability);
}
}
#endif
vec2 u = vec2(rand01(), rand01());
vec3 brdfWeight;
if (!evalIndirectCombinedBRDF(u, shadingNormal, geometryNormal, V, material, brdfType, direction, brdfWeight)) {
break; // Ray was eaten by the surface :(
}
// FIXME better offset (see ray tracing gems, ch 6?)
origin = payload.hit_pos_t.xyz + normal_offset_fudge * payload.normal;
throughput *= brdfWeight;
} // for all bounces
{