Commit 1ae903ea authored by Johannes Braun's avatar Johannes Braun
Browse files

Kind of working a little bit better now

parent 109699ab
......@@ -132,7 +132,8 @@ bool shade(int id, inout vec3 radiance, uint bounce, out uint bsdf_id)
{
// Treat as emissive material.
//writeColorStore(ray, radiance * bsdf_result.irradiance, clamp_color_max);
writeColorStore(ray, bsdf_result.radiance, clamp_color_max);
//if(length(bsdf_result.generated_ray.direction) > 0)
writeColorStore(ray, normalize(bsdf_result.radiance), clamp_color_max);
b_traces[id].hit.invalidate();
return false;
}
......@@ -160,21 +161,21 @@ bool shade(int id, inout vec3 radiance, uint bounce, out uint bsdf_id)
if (success && !shadow_test.intersectsAny(light_distance, use_bvh))
{
writeColorStore(ray, light_color * bsdf_result.irradiance * radiance, clamp_color_max);
writeColorStore(ray, light_color * bsdf_result.evaluation * radiance, clamp_color_max);
}
}
//Quit if bounces won't be of any use due to low contributions
if (bsdf_result.radiance == vec3(0) || bsdf_result.distribution <= 1e-5f)
if (bsdf_result.radiance == vec3(0) || bsdf_result.probability_density <= 1e-5f)
{
b_traces[id].hit.invalidate();
return false;
}
b_traces[id].properties.accuracy_importance *= bsdf_result.distribution;
b_traces[id].properties.shadow_importance *= bsdf_result.distribution;
b_traces[id].properties.accuracy_importance *= bsdf_result.probability_density;
b_traces[id].properties.shadow_importance *= bsdf_result.probability_density;
b_traces[id].ray = bsdf_result.generated_ray;
radiance *= bsdf_result.radiance * angle(bsdf_result.generated_ray, vertex) / bsdf_result.distribution;//
radiance *= bsdf_result.radiance * angle(bsdf_result.generated_ray, vertex) / bsdf_result.probability_density;//
return true;
}
......
......@@ -8,23 +8,21 @@
#include <raytracer/properties/fresnel.glsl>
#include <screenshader/gbuffer/cook_torrance.glsl>
#include <raytracer/properties/ggx.glsl>
struct BSDFResult
{
// A newly generated ray for shading
Ray generated_ray;
// An environment lighting ray
Ray diffuse_ray;
// How the color coming from the generated ray direction will be tinted
vec3 radiance;
// How the incoming light will be tinted
vec3 irradiance;
vec3 evaluation;
// The probability of the generated ray (result of the probability distribution function)
float distribution;
float probability_density;
// For effect purposes: set a dedicated id for the type of effect achieved
uint bsdf_id;
......@@ -48,7 +46,7 @@ vec3 reflectedDirection(vec3 local_hemi_sample, vec3 normal, vec3 reflected, flo
return normalize(localToWorld(local_hemi_sample, normal, reflected));
}
BSDFResult computeBSDFaaaaa(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in)
SampledMaterial getMaterialParameters(const in Material material, const in Vertex vertex)
{
SampledMaterial sampled_material;
sampled_material.diffuse = material.getDiffuse(vertex.texcoord);
......@@ -60,106 +58,65 @@ BSDFResult computeBSDFaaaaa(const in Material material, const in vec2 random, co
sampled_material.roughness = material.getRoughness();
sampled_material.metallic = clamp((sampled_material.specular.r + sampled_material.specular.g + sampled_material.specular.b )/3, 0, 1);
sampled_material.ior = 1.56f;//material.ior;
return sampled_material;
}
vec3 backwards_direction = normalize(-ray_in.direction);
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);
const vec3 hemisphere = ggxImportantHemisphereSample(random, sampled_material.roughness);
bool entering = dot(backwards_direction, vertex.normal.xyz) > 0.f;
vec3 hemi = randCosineHemisphere(random.x, random.y) * (entering ? 1 : -1);
vec3 reflected = reflect(-backwards_direction, faceforward(vertex.normal.xyz, -backwards_direction, vertex.normal.xyz));
vec3 incoming = normalize(-ray_in.direction);
BSDFResult result;
result.generated_ray = ray_in;
result.generated_ray.direction = reflectedDirection(hemi, vertex.normal.xyz, reflected, sampled_material.roughness);
result.generated_ray.origin = vertex.position.xyz + 1e-5f * result.generated_ray.direction;
bool entering = dot(incoming, vertex.normal.xyz) > 0.f;
vec3 micro_normal = normalize(toWorld(hemisphere, vertex.normal.xyz));
vec3 outgoing = normalize(2 * clamp(dot(incoming, micro_normal), 0, 1) * micro_normal - incoming);
result.diffuse_ray.direction = localToWorldNormal(hemi, vertex.normal.xyz).xyz;
result.diffuse_ray.origin = vertex.position.xyz + 1e-5f*result.diffuse_ray.direction;
vec3 half_vector = normalize(sign(dot(incoming, vertex.normal.xyz)) * (incoming + outgoing));
float jacobian = 1 / (4 * clamp(dot(outgoing, half_vector), 0, 1));
float dist_m = ggxDist(vertex.normal.xyz, micro_normal, sampled_material.roughness);
vec3 normal_response = normalResponse(sampled_material.diffuse.rgb, sampled_material.ior, sampled_material.metallic);
vec3 half_vector = normalize(result.generated_ray.direction.xyz + backwards_direction);
float cosT = clamp(dot(result.generated_ray.direction.xyz, vertex.normal.xyz), 0, 1);
float sinT = sqrt(1 - cosT * cosT);
vec3 fresnel = fresnelSchlick(clamp(dot(backwards_direction, half_vector), 0, 1), normal_response);
float geometry = ggxPartialGeometry(backwards_direction, vertex.normal.xyz, half_vector, sampled_material.roughness)
* ggxPartialGeometry(result.generated_ray.direction, vertex.normal.xyz, half_vector, sampled_material.roughness);
float denominator = clamp(4 * (clamp(dot(vertex.normal.xyz, backwards_direction), 0, 1) * clamp(dot(half_vector, vertex.normal.xyz), 0, 1)) + 0.05f, 0, 1);
float distribution = ggxDistribution(vertex.normal.xyz, half_vector, sampled_material.roughness);
vec3 k_specular = fresnel;
vec3 one_minus_kspec = (1-k_specular);
result.radiance = fresnel * geometry;
result.distribution = denominator;//cosT * geometry * sinT / denominator;
result.irradiance = (1-k_specular)*(1-sampled_material.metallic)*sampled_material.diffuse.rgb * ONE_OVER_PI;
result.bsdf_id = 0;
float geom_in = ggxGeom(vertex.normal.xyz, incoming, micro_normal, sampled_material.roughness);
float geom_out = ggxGeom(vertex.normal.xyz, outgoing, micro_normal, sampled_material.roughness);
return result;
}
//Approx. by Smith
float geometry = clamp(geom_in * geom_out, 0, 1);
vec3 normal_response = normalResponse(sampled_material.diffuse.rgb, sampled_material.ior, sampled_material.metallic);
vec3 fresnel = fresnelSchlick(clamp(dot(incoming, micro_normal), 0, 1), normal_response);
BSDFResult computeBSDF(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in)
{
SampledMaterial sampled_material;
sampled_material.diffuse = material.getDiffuse(vertex.texcoord);
sampled_material.specular = material.getSpecular(vertex.texcoord);
sampled_material.transparent = material.getTransparent(vertex.texcoord);
sampled_material.emissive = material.getEmissive(vertex.texcoord);
sampled_material.ambient = material.getAmbient(vertex.texcoord);
float n_dot_in = clamp(dot(vertex.normal.xyz, incoming), 0, 1);
float n_dot_out = clamp(dot(vertex.normal.xyz, outgoing), 0, 1);
float m_dot_out = clamp(dot(micro_normal, outgoing), 0, 1);
sampled_material.roughness = material.getRoughness();
sampled_material.metallic = clamp((sampled_material.specular.r + sampled_material.specular.g + sampled_material.specular.b )/3, 0, 1);
sampled_material.ior = 1.56f;//material.ior;
float cos_theta = clamp(dot(vertex.normal.xyz, micro_normal), 0, 1);// * dist_m
float sin_theta = sqrt(1-(cos_theta*cos_theta));
float sin_aa = sqrt(1-(m_dot_out*m_dot_out));
vec3 incoming = normalize(-ray_in.direction);
float prop_m = dist_m * m_dot_out;
float prop_o = m_dot_out;//prop_m * jacobian;
vec3 normal_response = normalResponse(sampled_material.diffuse.rgb, sampled_material.ior, sampled_material.metallic);
bool entering = dot(incoming, vertex.normal.xyz) > 0.f;
vec3 hemi = randUniformSphere(random.x, random.y);
hemi.z = abs(hemi.z);
hemi *= (entering ? 1 : -1);
float distribution = ggxDistribution(vec3(0,0,1), hemi, sampled_material.roughness);
hemi.xy *= distribution;
vec3 microsurface_normal = reflectedDirection(hemi, incoming, vertex.normal.xyz, 1);
vec3 outgoing = reflect(-incoming, microsurface_normal);
vec3 fresnel = fresnelSchlick(clamp(dot(incoming, microsurface_normal), 0, 1), normal_response);
// m is h
float n_dot_m = clamp(dot(vertex.normal.xyz, microsurface_normal), 0, 1);
float n_dot_i = clamp(dot(vertex.normal.xyz, incoming), 0, 1);
float n_dot_o = clamp(dot(vertex.normal.xyz, outgoing), 0, 1);
float i_dot_m = clamp(dot(incoming, microsurface_normal), 0, 1);
float o_dot_m = clamp(dot(outgoing, microsurface_normal), 0, 1);
float roughness2 = sampled_material.roughness * sampled_material.roughness;
float sin_theta = sqrt(1 - n_dot_o*n_dot_o);
float sin_theta_in = sqrt(1 - n_dot_i*n_dot_i);
float geometric_in = ggxPartialGeometry(incoming, vertex.normal.xyz, microsurface_normal, sampled_material.roughness);
float geometric_out = ggxPartialGeometry(incoming, vertex.normal.xyz, microsurface_normal, sampled_material.roughness);
float geometric = clamp(min(geometric_in, geometric_out), 0, 1);
// float n_dot_m2 = 2.0f * n_dot_m;
// float geom1 = (n_dot_m2 * n_dot_i) / o_dot_m;
// float geom2 = (n_dot_m2 * n_dot_o) / o_dot_m;
// float geometric = min(1.0f, min(geom1, geom2));
float denom_part = (roughness2 - 1) * (n_dot_m*n_dot_m) + 1;
float distribution_part = roughness2 / (denom_part * denom_part);
//float distribution = distribution_part * ONE_OVER_PI;
float probability_half_theta = distribution * 2 * n_dot_m;
// float distribution = ggxDistribution(vertex.normal.xyz, microsurface_normal, sampled_material.roughness);
float denominator = clamp(4 * (n_dot_i * n_dot_o), 0.05f, 1);
vec3 specular = (fresnel * geometric * distribution) / denominator;
vec3 brdf = clamp(fresnel * geometry / clamp((4 * n_dot_in * n_dot_out), 0.05f, 1.f), 0, 1);
BSDFResult result;
result.generated_ray = ray_in;
result.generated_ray.direction = outgoing;
result.generated_ray.origin = vertex.position.xyz + 1e-5 * outgoing;
// result.diffuse_ray.direction = localToWorldNormal(hemi, vertex.normal.xyz).xyz;
//result.diffuse_ray.origin = vertex.position.xyz + 1e-5f*result.diffuse_ray.direction;
result.radiance = specular;// * distribution;
result.distribution = probability_half_theta / denominator;// * mix(1, 0.5f, sampled_material.roughness);//sin_theta * ONE_OVER_PI * n_dot_o;
result.irradiance = vec3(0);//(1-fresnel)*(1-sampled_material.metallic)*sampled_material.diffuse.rgb;
result.evaluation = (1-fresnel)*(1-sampled_material.metallic)*sampled_material.diffuse.rgb * ONE_OVER_PI;
if(sampled_material.metallic == 1 || (fresnel.x + fresnel.y + fresnel.z)/3 > random.x*random.y)
{
result.generated_ray.direction = outgoing;
result.radiance = brdf;
result.probability_density = prop_o;
}
else
{
result.generated_ray.direction = normalize(toWorld(randCosineHemisphere(random.x, random.y), vertex.normal.xyz));
result.probability_density = abs(dot(vec4(result.generated_ray.direction, 0), vertex.normal)) * ONE_OVER_PI;
result.radiance = result.evaluation;
}
result.generated_ray.origin = vertex.position.xyz + 1e-5f * result.generated_ray.direction;
result.bsdf_id = 0;
return result;
}
......@@ -168,9 +125,127 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
//
//
//
//
// BSDFResult computeBSDFaaaaa(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in)
// {
// const SampledMaterial sampled_material = getMaterialParameters(material, vertex);
// //const vec2 importance_sample = ggxImportanceSample(random);
//
// vec3 backwards_direction = normalize(-ray_in.direction);
//
// bool entering = dot(backwards_direction, vertex.normal.xyz) > 0.f;
// vec3 hemi = randCosineHemisphere(random.x, random.y) * (entering ? 1 : -1);
// vec3 reflected = reflect(-backwards_direction, faceforward(vertex.normal.xyz, -backwards_direction, vertex.normal.xyz));
//
// BSDFResult result;
// result.generated_ray = ray_in;
// result.generated_ray.direction = reflectedDirection(hemi, vertex.normal.xyz, reflected, sampled_material.roughness);
// result.generated_ray.origin = vertex.position.xyz + 1e-5f * result.generated_ray.direction;
//
// result.diffuse_ray.direction = localToWorldNormal(hemi, vertex.normal.xyz).xyz;
// result.diffuse_ray.origin = vertex.position.xyz + 1e-5f*result.diffuse_ray.direction;
//
// vec3 normal_response = normalResponse(sampled_material.diffuse.rgb, sampled_material.ior, sampled_material.metallic);
// vec3 half_vector = normalize(result.generated_ray.direction.xyz + backwards_direction);
//
// float cosT = clamp(dot(result.generated_ray.direction.xyz, vertex.normal.xyz), 0, 1);
// float sinT = sqrt(1 - cosT * cosT);
// vec3 fresnel = fresnelSchlick(clamp(dot(backwards_direction, half_vector), 0, 1), normal_response);
// float geometry = ggxPartialGeometry(backwards_direction, vertex.normal.xyz, half_vector, sampled_material.roughness)
// * ggxPartialGeometry(result.generated_ray.direction, vertex.normal.xyz, half_vector, sampled_material.roughness);
// float denominator = clamp(4 * (clamp(dot(vertex.normal.xyz, backwards_direction), 0, 1) * clamp(dot(half_vector, vertex.normal.xyz), 0, 1)) + 0.05f, 0, 1);
// float distribution = ggxDistribution(vertex.normal.xyz, half_vector, sampled_material.roughness);
//
// vec3 k_specular = fresnel;
// vec3 one_minus_kspec = (1-k_specular);
//
// result.radiance = fresnel * geometry;
// result.distribution = denominator;//cosT * geometry * sinT / denominator;
// result.irradiance = (1-k_specular)*(1-sampled_material.metallic)*sampled_material.diffuse.rgb * ONE_OVER_PI;
// result.bsdf_id = 0;
//
// return result;
// }
//
//
//
//
// BSDFResult computeBSDFabcdefg(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in)
// {
// SampledMaterial sampled_material;
// sampled_material.diffuse = material.getDiffuse(vertex.texcoord);
// sampled_material.specular = material.getSpecular(vertex.texcoord);
// sampled_material.transparent = material.getTransparent(vertex.texcoord);
// sampled_material.emissive = material.getEmissive(vertex.texcoord);
// sampled_material.ambient = material.getAmbient(vertex.texcoord);
//
// sampled_material.roughness = material.getRoughness();
// sampled_material.metallic = clamp((sampled_material.specular.r + sampled_material.specular.g + sampled_material.specular.b )/3, 0, 1);
// sampled_material.ior = 1.56f;//material.ior;
//
// vec3 incoming = normalize(-ray_in.direction);
//
// vec3 normal_response = normalResponse(sampled_material.diffuse.rgb, sampled_material.ior, sampled_material.metallic);
// bool entering = dot(incoming, vertex.normal.xyz) > 0.f;
// vec3 hemi = randUniformSphere(random.x, random.y);
// hemi.z = abs(hemi.z);
// hemi *= (entering ? 1 : -1);
// float distribution = ggxDistribution(vec3(0,0,1), hemi, sampled_material.roughness);
// hemi.xy *= distribution;
// vec3 microsurface_normal = reflectedDirection(hemi, incoming, vertex.normal.xyz, 1);
// vec3 outgoing = reflect(-incoming, microsurface_normal);
// vec3 fresnel = fresnelSchlick(clamp(dot(incoming, microsurface_normal), 0, 1), normal_response);
//
// // m is h
// float n_dot_m = clamp(dot(vertex.normal.xyz, microsurface_normal), 0, 1);
// float n_dot_i = clamp(dot(vertex.normal.xyz, incoming), 0, 1);
// float n_dot_o = clamp(dot(vertex.normal.xyz, outgoing), 0, 1);
// float i_dot_m = clamp(dot(incoming, microsurface_normal), 0, 1);
// float o_dot_m = clamp(dot(outgoing, microsurface_normal), 0, 1);
// float roughness2 = sampled_material.roughness * sampled_material.roughness;
// float sin_theta = sqrt(1 - n_dot_o*n_dot_o);
// float sin_theta_in = sqrt(1 - n_dot_i*n_dot_i);
//
// float geometric_in = ggxPartialGeometry(incoming, vertex.normal.xyz, microsurface_normal, sampled_material.roughness);
// float geometric_out = ggxPartialGeometry(incoming, vertex.normal.xyz, microsurface_normal, sampled_material.roughness);
// float geometric = clamp(min(geometric_in, geometric_out), 0, 1);
// // float n_dot_m2 = 2.0f * n_dot_m;
// // float geom1 = (n_dot_m2 * n_dot_i) / o_dot_m;
// // float geom2 = (n_dot_m2 * n_dot_o) / o_dot_m;
// // float geometric = min(1.0f, min(geom1, geom2));
//
// float denom_part = (roughness2 - 1) * (n_dot_m*n_dot_m) + 1;
// float distribution_part = roughness2 / (denom_part * denom_part);
// //float distribution = distribution_part * ONE_OVER_PI;
// float probability_half_theta = distribution * 2 * n_dot_m;
// // float distribution = ggxDistribution(vertex.normal.xyz, microsurface_normal, sampled_material.roughness);
// float denominator = clamp(4 * (n_dot_i * n_dot_o), 0.05f, 1);
// vec3 specular = (fresnel * geometric * distribution) / denominator;
//
//
// BSDFResult result;
// result.generated_ray = ray_in;
// result.generated_ray.direction = outgoing;
// result.generated_ray.origin = vertex.position.xyz + 1e-5 * outgoing;
// // result.diffuse_ray.direction = localToWorldNormal(hemi, vertex.normal.xyz).xyz;
// //result.diffuse_ray.origin = vertex.position.xyz + 1e-5f*result.diffuse_ray.direction;
// result.radiance = specular;// * distribution;
// result.distribution = probability_half_theta / denominator;// * mix(1, 0.5f, sampled_material.roughness);//sin_theta * ONE_OVER_PI * n_dot_o;
// result.irradiance = vec3(0);//(1-fresnel)*(1-sampled_material.metallic)*sampled_material.diffuse.rgb;
// result.bsdf_id = 0;
// return result;
// }
//
//
//
//
//
//
//
//
......
#ifndef INCLUDE_GGX_GLSL
#define INCLUDE_GGX_GLSL
#include <raytracer/random.glsl>
#define GGX_PI 3.14159265359f
vec2 ggxImportanceSample(const in vec2 random_sample, const in float roughness)
{
// float phi = 2.f * GGX_PI * random_sample.x;
// float theta = acos(sqrt((1.f - random_sample.y) / ((roughness * roughness - 1.f) * random_sample.y + 1.f)));
// return vec2(phi, theta);
float phi = random_sample.y;
// float theta = acos(sqrt((1.f - random_sample.y) / ((roughness * roughness - 1.f) * random_sample.y + 1.f)));
float rough2 = roughness*roughness;
float theta = sqrt(rough2 * random_sample.x / (1 - random_sample.x));
return vec2(phi, theta);
}
vec3 ggxImportantHemisphereSample(const in vec2 random_sample, const in float roughness)
{
vec2 important = ggxImportanceSample(random_sample, roughness);
float phi = important.x * 2.f * PI;
float cosTheta = cos(important.y);
float sinTheta = sqrt(max(0, 1 - cosTheta * cosTheta));
return vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
}
float ggxDist(const in vec3 normal, const in vec3 vector, float roughness)
{
float normal_dot_half = dot(normal, vector);
float roughness2 = roughness * roughness;
float normal_dot_half2 = normal_dot_half * normal_dot_half;
float denominator = normal_dot_half2 * roughness2 + (1-normal_dot_half2);
return (ggxChi(normal_dot_half) * roughness2) / (GGX_PI * denominator * denominator);
}
float ggxGeom(const in vec3 normal, const in vec3 vector, const in vec3 micro_normal, float roughness)
{
float eye_dot_half2 = clamp(dot(vector, micro_normal), 0, 1);
float chi = ggxChi(eye_dot_half2 / clamp(dot(vector, normal), 0, 1));
eye_dot_half2 = eye_dot_half2 * eye_dot_half2;
float tan2 = (1 - eye_dot_half2) / eye_dot_half2;
return (chi*2) / (1 + sqrt(1 + roughness * roughness * tan2));
}
#endif //!INCLUDE_GGX_GLSL
......@@ -34,4 +34,31 @@ vec3 localToWorldNormal(const in vec3 v, const in vec3 normal) {
return localToWorld(v, perpendicular, secondary_perpendicular, normal); // bring vectors to local shading space
}
vec3 toWorld(const in vec3 vector, const in vec3 normal) {
// Find an axis that is not parallel to normal
vec3 majorAxis;
if(vector == vec3(0, 0, 1))
{
return normal;
}
else
{
majorAxis = cross(vector, normal);
}
// Use majorAxis to create a coordinate system relative to world space
vec3 u = normalize(cross(normal, majorAxis));
vec3 v = cross(normal, u);
vec3 w = normal;
// return vector;// u+v+w;
// Transform from local coordinates to world coordinates
return normalize(u * vector.x +
v * vector.y +
w * vector.z
);
}
#endif // !__RAY_TRANSFORM_GLH
......@@ -63,6 +63,14 @@ vec3 randUniformSphere(float u, float v)
return vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
}
vec3 randUniformHemisphere(float u, float v)
{
float phi = v * 2.f * PI;
float cosTheta = abs(2 * u - 1);
float sinTheta = sqrt(max(0, 1 - cosTheta * cosTheta));
return vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
}
vec3 randUniformSphere(vec2 rand)
{
return randUniformSphere(rand.x, rand.y);
......
......@@ -82,5 +82,6 @@ vec3 ggxSpecular(samplerCube environment, const in vec3 normal, const in vec3 to
return radiance / sample_count;
}
#undef GGX_PI
#endif //!INCLUDE_COOK_TORRANCE_GLSL
Markdown is supported
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