Commit 77684cb8 authored by Johannes Braun's avatar Johannes Braun
Browse files

Finally a decent looking and structurized and... well... working gbuffer fragment shader.

parent b097d0b9
......@@ -28,64 +28,27 @@ uniform struct {
layout(location = 0) out vec4 out_final_color;
const vec2 poissonDisk[5] = vec2[](
vec2(0),
vec2(-0.94201624, -0.39906216),
vec2(0.94558609, -0.76890725),
vec2(-0.094184101, -0.92938870),
vec2(0.34495938, 0.29387760)
);
float calculateShadowMapDarkening(const in vec4 position, const in vec3 to_light, const in vec4 normal, const in LightWithShadowmap light) {
float darkening = 1.f;
if (light.shadow_map.available == 1) {
vec4 shadow_coord = light.shadow_map.matrix * vec4(position.xyz, 1); // clip coordinates, light space
vec3 shadow_coord_normalized = shadow_coord.xyz / shadow_coord.w; // normalized device coordinates, light space
//shadow_coord_normalized.xy = clamp(shadow_coord_normalized.xy, 0, 1);
float dst = pow(clamp(distance(camera_position, position.xyz) / 250.f, 0, 1), 3);
float cos_theta = dot(normal.xyz, to_light);
if (dst==0 || !(shadow_coord_normalized.x <= 1.f && shadow_coord_normalized.x > 0.f && shadow_coord_normalized.y <= 1.f && shadow_coord_normalized.y > 0.f)) {
return max(cos_theta, 0);
}
float bias = 0.005 * tan(acos(cos_theta));
bias = clamp(bias, 0, 0.001f);
const vec2 size = vec2(light.shadow_map.map.textureSize(0));
const int num_samples = 5;
float shadow_value = 0.f;
for (int i = 0; i<num_samples; i++) {
shadow_value += texture(light.shadow_map.map, vec3(shadow_coord_normalized.xy + (poissonDisk[i] / size.x), shadow_coord_normalized.z - bias));
}
shadow_value /= num_samples;
darkening = mix(shadow_value * max(cos_theta, 0), max(cos_theta, 0), dst);
}
return darkening;
}
void main()
{
out_final_color = vec4(0,0,0,0);
vec2 screen_dimensions = vec2(textureSize(u_gbuffer.diffuse));
vec2 texcoord = out_texcoord;
ivec2 pixel = ivec2(gl_FragCoord.xy);
for(int s=0; s<int(u_samples); ++s)
{
vec4 final_color_part = vec4(0,0,0,0);
//Emission, just put the color in and continue
vec4 lighting = texelFetch(u_gbuffer.lighting, pixel, s);
if(lighting.rgb != vec3(0))
{
final_color_part += lighting;
continue;
}
vec4 diffuse = vec4(texelFetch(u_gbuffer.diffuse, pixel, s).rgb, 1);
final_color_part = diffuse;
vec4 normal = texelFetch(u_gbuffer.normals, pixel, s);
vec4 final_color_part = vec4(0,0,0,0);
int mode = int(round(normal.w));
if(mode == 0){
......@@ -99,95 +62,34 @@ void main()
vec4 view = texelFetch(u_gbuffer.position, pixel, s);
vec4 position = texelFetch(u_gbuffer.position_raw, pixel, s);
vec4 lighting = texelFetch(u_gbuffer.lighting, pixel, s);
vec3 reflection;
if(is_transparent)
{
reflection = refract(normalize(position.xyz - camera_position), normalize(normal.xyz), 1 / 1.56f);
}
else
{
else
reflection = reflect(normalize(position.xyz - camera_position), normalize(normal.xyz));
}
// TODO: Quite not that optimal.
float fresnel = clamp(schlickFresnel(-normalize(position.xyz - camera_position), normalize(normal.xyz), 1, 1.56), 0, 1);
float shininess = specular.a * fresnel;
shininess = clamp(mix(specular.a/2.f, specular.a, fresnel), 0, 1);
shininess = mix(specular.a/2.f, specular.a, fresnel);
// environment reflection. Use the shininess value (which is the specular exponent divided by 100) as an interpolation value between the cubemap LODs.
float environment_factor = smoothstep(0.f, 1.f, 1 - shininess);
vec4 environment_reflect = textureLod(environment, reflection, environment_factor * 8.f);
vec4 environment_reflect = textureLod(environment, reflection, 2);//pow(1-shininess/100.f, 5));
final_color_part = vec4(0);
for(int i=0; i<b_lights.length() && !is_transparent; i++){
LightWithShadowmap light_and_map = b_lights[i];
BufferLight light = light_and_map.light;
vec3 pos_to_light;
float dist = length(light.position.xyz - position.xyz);
float attenuation;
switch(light.data.light_type){
case 0: //POINT
pos_to_light = normalize(light.position.xyz - position.xyz);
attenuation = 1/(light.attenuation.constant + light.attenuation.linear*dist + light.attenuation.quadratic*dist*dist);
break;
case 1: //SPOT
pos_to_light = normalize(light.position.xyz - position.xyz);
attenuation = 1/(light.attenuation.constant + light.attenuation.linear*dist + light.attenuation.quadratic*dist*dist);
float angle_dot = max(dot(normalize(-pos_to_light), normalize(light.direction.xyz)), 0.0);
attenuation *= 1-smoothstep(cos(light.data.params[0]), cos(light.data.params[1]), angle_dot);
break;
case 2: //DIR
pos_to_light = normalize(-light.direction.xyz);
attenuation = 1;
break;
case 3: //Ambient
//final_color_part += diffuse * light.color;
attenuation = 0;
break;
}
vec4 light_color = vec4(light.color.rgb * attenuation, 1);
float darkening = calculateShadowMapDarkening(position, pos_to_light, normal, light_and_map);
/*
final_color_part += vec4(darkening, darkening, darkening, 1) / b_lights.length();
attenuation = 0;*/
if(attenuation > 0.01) {
//DIFFUSE
float cos_phi = max(dot(normalize(normal.xyz), pos_to_light), 0.0f);
//SPECULAR
vec3 eye = normalize(camera_position-position.xyz);
vec3 reflection_vec = normalize(reflect(-pos_to_light, normalize(normal.xyz)));
float cos_phi_n = pow(max(dot(reflection_vec, eye), 0.0f), shininess *100);
final_color_part += (diffuse * darkening * cos_phi * light_color + vec4(diffuse.rgb * darkening, 1) * vec4(specular.rgb, 1) * cos_phi_n * light_color)/ b_lights.length();
}
final_color_part += phong(light_and_map, position.xyz, normal.xyz, camera_position, diffuse, specular, shininess) / b_lights.length();
}
if(is_transparent)
{
final_color_part = vec4(diffuse.rgb, 1) * environment_reflect;
}
else
{
final_color_part = mix(final_color_part, vec4(diffuse.rgb, 1) * vec4(specular.rgb, 1) * environment_reflect, shininess);
}
if(lighting.rgb != vec3(0))
{
final_color_part = lighting;
}
} else {
final_color_part = diffuse;
// Now we can add the previously calculated environment reflection or refraction
vec4 reflection_tint = is_transparent ? diffuse : specular;
final_color_part = mix(final_color_part, reflection_tint * environment_reflect, shininess);
}
out_final_color += final_color_part;
// Add resulting color to the finished image, and compensate for multisampling
out_final_color += final_color_part / u_samples;
}
out_final_color /= u_samples;
}
\ No newline at end of file
}
......@@ -44,4 +44,122 @@ STD_BUFFER_R lightsBuffer
LightWithShadowmap b_lights[];
};
const vec2 poissonDisk[5] = vec2[](
vec2(0),
vec2(-0.94201624, -0.39906216),
vec2(0.94558609, -0.76890725),
vec2(-0.094184101, -0.92938870),
vec2(0.34495938, 0.29387760)
);
float calculateShadowMapDarkening(const in vec3 position, const in vec3 to_light, const in vec3 normal, const in vec3 camera, const in LightWithShadowmap light) {
float darkening = 1.f;
if (light.shadow_map.available == 1) {
vec4 shadow_coord = light.shadow_map.matrix * vec4(position.xyz, 1); // clip coordinates, light space
vec3 shadow_coord_normalized = shadow_coord.xyz / shadow_coord.w; // normalized device coordinates, light space
//shadow_coord_normalized.xy = clamp(shadow_coord_normalized.xy, 0, 1);
float dst = pow(clamp(distance(camera, position.xyz) / 250.f, 0, 1), 3);
float cos_theta = dot(normal.xyz, to_light);
if (dst==0 || !(shadow_coord_normalized.x <= 1.f && shadow_coord_normalized.x > 0.f && shadow_coord_normalized.y <= 1.f && shadow_coord_normalized.y > 0.f)) {
return max(cos_theta, 0);
}
float bias = 0.005 * tan(acos(cos_theta));
bias = clamp(bias, 0, 0.001f);
const vec2 size = vec2(light.shadow_map.map.textureSize(0));
const int num_samples = 5;
float shadow_value = 0.f;
for (int i = 0; i<num_samples; i++) {
shadow_value += texture(light.shadow_map.map, vec3(shadow_coord_normalized.xy + (poissonDisk[i] / size.x), shadow_coord_normalized.z - bias));
}
shadow_value /= num_samples;
darkening = mix(shadow_value * max(cos_theta, 0), max(cos_theta, 0), dst);
}
return darkening;
}
float fullAttenuation(const in BufferLight light, float distance_to_point)
{
return 1/(light.attenuation.constant + light.attenuation.linear*distance_to_point + light.attenuation.quadratic*distance_to_point*distance_to_point);
}
bool evaluateColor(const in vec4 color)
{
return length(color.rgb) > 0.0001f;
}
bool sampleLight(const in LightWithShadowmap light_and_map, const in vec3 position, const in vec3 normal, const in vec3 camera, out vec3 point_to_light, out vec4 color)
{
const BufferLight light = light_and_map.light;
float attenuation;
float dist;
switch(light.data.light_type)
{
case 0:
//point light
point_to_light = light.position.xyz - position.xyz;
color = vec4(light.fullAttenuation(length(point_to_light))*light.color.rgb, 1);
return evaluateColor(color);
case 1:
//spot light
point_to_light = light.position.xyz - position.xyz;
float angle_dot = max(dot(normalize(-point_to_light), normalize(light.direction.xyz)), 0.0);
float attenuation = (1-smoothstep(cos(light.data.params[0]), cos(light.data.params[1]), angle_dot)) * light.fullAttenuation(length(point_to_light));
color = vec4(attenuation * light.color.rgb, 1);
return evaluateColor(color);
case 2:
//directional light
point_to_light = normalize(-light.direction.xyz);
float darkening = calculateShadowMapDarkening(position, normalize(point_to_light), normal, camera, light_and_map);
color = vec4(darkening * light.color.rgb, 1);
return evaluateColor(color);
case 3:
//ambient light
color = light.color;
return false;
default:
break;
}
return false;
}
vec4 phong(const in LightWithShadowmap light_and_map, const in vec3 position, const in vec3 normal, const in vec3 camera, const in vec4 diffuse, const in vec4 specular, float shininess, bool metallic = false)
{
vec4 color = vec4(0, 0, 0, 1);
vec3 point_to_light;
if(light_and_map.sampleLight(position, normal, camera, point_to_light, color)) {
//DIFFUSE
float cos_phi = max(dot(normalize(normal.xyz), normalize(point_to_light)), 0.0f);
//SPECULAR
vec3 eye = normalize(camera-position.xyz);
vec3 reflection_vec = normalize(reflect(-point_to_light, normalize(normal.xyz)));
float cos_phi_n = pow(max(dot(reflection_vec, eye), 0.0f), 5+shininess*95);
vec4 phong_diffuse = (diffuse * cos_phi * color);
//If the material is metallic, tint the specular color with the diffuse color.
vec4 phong_specular = ((metallic ? diffuse : vec4(1)) * specular * cos_phi_n * color);
return phong_diffuse + phong_specular;
}
else
{
//color may still be set e.g. by ambient
//if this else is triggered by a low attenuation (example), it shall be assured that the color will be set to a near-zero value.
return color;
}
}
#endif // !__GBUFFER_LIGHTS_GLH
......@@ -115,11 +115,11 @@ namespace glare
//quitPromptDefault(0);
//initializeScene(m_current_scene_root / "artifact_suzanne_x2_glass_0r.dae", 1.f);
initializeScene(m_current_scene_root / "glass.dae", 1.f);
//initializeScene(m_current_scene_root / "glass.dae", 1.f);
//initializeScene(m_current_scene_root / "artifact_suzanne_x2_mirror_0r.dae", 1.f);
//initializeScene(m_current_scene_root / "artifact_suzanne_x2_transparent.dae", 1.f);
//initializeScene(m_current_scene_root / "benchmark_stfd_bunny_diff.dae", 1.f);
//initializeScene(m_current_scene_root / "difficult.dae", 1.f);
initializeScene(m_current_scene_root / "some_spheres.dae", 1.f);
initializeRenderRequirements();
initializeAdvanced();
......
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