Commit a847a258 authored by Johannes Braun's avatar Johannes Braun
Browse files

Fixed lines showing up when using transmissive materials.

parent 801909fe
......@@ -60,6 +60,12 @@ SampledMaterial getMaterialParameters(const in Material material, const in Verte
return sampled_material;
}
bool isTotalReflection(float ior_in, float ior_out, vec3 incoming, vec3 micro_normal)
{
float c = abs(dot(incoming, micro_normal));
return c * c < -(ior_out / ior_in) + 1;
}
BSDFResult computeBSDF(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in)
{
const SampledMaterial sampled_material = material.getMaterialParameters(vertex);
......@@ -82,7 +88,8 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
// Importance sampling: compute an importance sample {phi, theta} and generate a local (z-up) microsurface normal, as well as an according normal distribution
HemisphereSample hemisphere_sample = ggxSample(random, sampled_material.roughness);
vec3 base_micro_normal = localToWorld(hemisphere_sample.micro_normal, normal);
vec3 microfacet_normal = localToWorld(hemisphere_sample.micro_normal, normal);
microfacet_normal = dot(microfacet_normal, incoming) < 0 ? reflect(-microfacet_normal, normal) : microfacet_normal;
// Schlick's fresnel approximation with the material's normal response
float normal_response = normalResponse(sampled_material.ior, sampled_material.metallic);
......@@ -98,14 +105,15 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
float rnd = rand(int(12301 * random.x + 99373 * random.y));
vec3 mfntes = dot(base_micro_normal, incoming) < 0 ? reflect(-base_micro_normal, normal) : base_micro_normal;
BSDFResult brdf_result;
if(rnd < k_s){
// Compute BRDF
vec3 microfacet_normal = dot(base_micro_normal, incoming) < 0 ? reflect(-base_micro_normal, normal) : base_micro_normal;
// Compute needed refraction values
bool enters = dot(incoming, vertex.normal.xyz) > 0;
float ior_in = enters ? 1 : sampled_material.ior;
float ior_out = enters ? sampled_material.ior : 1;
float eta = ior_in / ior_out;
if(rnd < k_s || (k_t > 0 && rnd < k_s + k_t && isTotalReflection(ior_in, ior_out, incoming, microfacet_normal))){
// Compute BRDF
vec3 reflected = normalize(2 * abs(dot(microfacet_normal, incoming)) * microfacet_normal - incoming);
vec3 outgoing = dot(reflected, normal) >= 0 ? reflected : reflect(reflected, normal);
microfacet_normal = normalize(outgoing + incoming);
......@@ -123,6 +131,7 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
float jacobian = 1 / max(abs(4 * m_dot_out), 0.00001f);
float probability_m = distribution * cos_theta;
BSDFResult brdf_result;
brdf_result.evaluation = vec3(0); // No diffuse if reflecting
brdf_result.bsdf_id = eReflect;
brdf_result.probability_density = probability_m * jacobian;
......@@ -130,35 +139,13 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
brdf_result.generated_ray = ray_in;
brdf_result.generated_ray.direction = outgoing;
brdf_result.generated_ray.origin = vertex.position.xyz + 1e-3f * brdf_result.generated_ray.direction;
return brdf_result;
}
else if(rnd < k_s + k_t)
// Compute BTDF
{
// Compute needed refraction values
bool enters = dot(incoming, vertex.normal.xyz) > 0;
float ior_in = enters ? 1 : sampled_material.ior;
float ior_out = enters ? sampled_material.ior : 1;
float eta = ior_in / ior_out;
vec3 microfacet_normal = base_micro_normal;
float c = dot(incoming, microfacet_normal);
vec3 transmitted = (eta * c - sign(dot(incoming, normal)) * sqrt(1 + eta*(c * c - 1))) * microfacet_normal - eta * incoming;
vec3 outgoing = transmitted;//dot(transmitted, normal) < 0 ? transmitted : reflect(transmitted, normal);
// microfacet_normal = -normalize(ior_in * incoming + ior_out * outgoing);
//
// BSDFResult result;
// //Use the pixel coordinates of the incoming ray.
// result.generated_ray = ray_in;
// result.radiance =outgoing;
// result.bsdf_id = eEmit;
// return result;
// if(isnan(outgoing.x))
// {
// }
// Compute BTDF
float c = abs(dot(incoming, microfacet_normal));
vec3 outgoing = (eta * c - sign(dot(incoming, normal)) * sqrt(1 + eta*(c * c - 1))) * microfacet_normal - eta * incoming;
float m_dot_in = abs(dot(microfacet_normal, incoming));
float cos_theta = abs(dot(microfacet_normal, normal));
......@@ -200,68 +187,6 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
lambert_result.generated_ray.origin = vertex.position.xyz + 1e-3f * lambert_result.generated_ray.direction;
return lambert_result;
}
#ifdef BLABAL
// Compute geometric attenuation via GGX
// float geometry = ggxGeometry(incoming, outgoing_reflected, normal, micro_normal, sampled_material.roughness);
// float geometry_refracted = ggxGeometry(incoming, outgoing_refracted, normal, micro_normal, sampled_material.roughness);
//
// float m_dot_in = abs(dot(micro_normal, incoming));
// float m_dot_out = abs(dot(micro_normal, outgoing_reflected));
// float m_dot_out_refract = abs(dot(micro_normal, outgoing_refracted));
//float cos_theta = abs(dot(micro_normal, normal));
// // Compute the microsurface normal probability and with that the final probability density function
// // Clamp up denominator to not divide by zero.
// float jacobian_reflect = 1 / max(abs(4 * m_dot_out), 0.00001f);
// float probability_m = distribution * cos_theta;
// float pdf = probability_m * jacobian_reflect;
// Same as above but for refractions
float ior_out_2 = ior_out * ior_out;
float jacobian_refract_denominator = ior_in * m_dot_in + ior_out * abs(m_dot_out_refract);
jacobian_refract_denominator *= jacobian_refract_denominator;
jacobian_refract_denominator = max(jacobian_refract_denominator, 0.00001f);
//Take the absolute value as m_dot_out_refract is negative
float jacobian_refract = abs(ior_out_2 * m_dot_out_refract / jacobian_refract_denominator);
float pdf_refract = probability_m * jacobian_refract;
// Same here... clamp up denominator to not divide by zero
// float brdf_denominator = 4 * abs(m_dot_in) * abs(m_dot_out);
float btdf_denominator = jacobian_refract_denominator;
// Finally, build the brdf. As we do russian roulette, we can just tint the brdf instead of multiplying with the fresnel value.
// vec3 brdf = mix(vec3(1), sampled_material.base, sampled_material.metallic) * geometry * distribution / brdf_denominator;
// Same as above, we don't need the fresnel factor here either.
vec3 btdf = abs(m_dot_in * m_dot_out_refract / (m_dot_in * m_dot_out_refract)) * ior_out_2 * sampled_material.base * geometry_refracted * distribution / btdf_denominator;
// russian roulette Part 2
// Also check whether the refracted ray is valid, as we don't want to sample with NaN rays, just for safety.
if(roulette_border_specular >= random.x || isnan(outgoing_refracted.x))
{
// Use as brdf sample
result.generated_ray.direction = outgoing_reflected;
result.probability_density = pdf;
result.radiance = brdf;
result.evaluation = vec3(0); // No diffuse if reflecting
result.bsdf_id = eReflect;
}
else
{
// Use as btdf sample
result.generated_ray.direction = outgoing_refracted;
result.probability_density = pdf_refract;
result.radiance = btdf;
result.evaluation = vec3(0); // No diffuse if transmitting
result.bsdf_id = eTransmit;
}
// offset by newly generated direction
result.generated_ray.origin = vertex.position.xyz + 1e-3f * result.generated_ray.direction;
return result;
#endif
}
#endif //!INCLUDE_PATHTRACER_BSDF_GLSL
......@@ -117,10 +117,10 @@ bool shade(int id, inout vec3 radiance, uint bounce, out uint bsdf_id)
traces_data[id].properties.travelled_distance += traces_data[id].hit.valid() ? (distance(traces_data[id].ray.origin, vertex.position.xyz)) : FLT_MAX;
//As the px and py values of the ray are floats instead of integers,
//we can extract the random sample by extracting the subpixel offset.
//That means the random sample will always have a value between (0,0) and (1,1).
vec2 random_sample = vec2(ray.px, ray.py) - ivec2(floor(ray.px), floor(ray.py));
// generate a random sample on each bounce so there won't be any notifiable patterns
const vec2 base_random = vec2(ray.px, ray.py) - ivec2(floor(ray.px), floor(ray.py));
const ivec2 img_size = u_render_target.imageSize();
vec2 random_sample = rand2D(int(id + base_random.x * 60337 + base_random.y * 27487), img_size.x * img_size.y);
BSDFResult bsdf_result = material.computeBSDF(random_sample, vertex, ray);
......@@ -131,11 +131,6 @@ bool shade(int id, inout vec3 radiance, uint bounce, out uint bsdf_id)
return false;
}
// writeColorStore(ray, bsdf_result.radiance, clamp_color_max);
// traces_data[id].hit.invalidate();
// return false;
if(bsdf_result.bsdf_id == eEmit)
{
writeColorStore(ray, radiance * bsdf_result.radiance, clamp_color_max);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment