Archived
1
Fork 0

Remove kD term, improve fresnel reflections and fix scene capture

This commit is contained in:
redstrate 2020-08-16 23:31:00 -04:00
parent 69eb4bea34
commit 92e04068fd
6 changed files with 58 additions and 57 deletions

View file

@ -292,6 +292,18 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
}\n"; }\n";
} }
if(use_ibl) {
src += "vec3 ibl(const int probe, const ComputedSurfaceInfo surface_info, const float intensity) {\n \
const vec3 R = get_reflect(probe, surface_info.N);\n \
const vec2 brdf = texture(brdfSampler, vec2(surface_info.NdotV, surface_info.roughness)).rg; \n \
const vec3 sampledIrradiance = texture(irrandianceSampler, vec4(surface_info.N, probe)).xyz;\n \
const vec3 prefilteredColor = textureLod(prefilterSampler, vec4(R, probe), surface_info.roughness * 4).xyz;\n \
const vec3 diffuse = sampledIrradiance * surface_info.diffuse_color;\n \
const vec3 specular = prefilteredColor * (surface_info.F0 * brdf.x + 1.0 * brdf.y);\n \
return (diffuse + specular) * intensity;\n \
}\n";
}
src += "void main() {\n"; src += "void main() {\n";
bool has_output = false; bool has_output = false;
@ -335,47 +347,33 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
light_info = calculate_sun(scene.lights[i]);\n \ light_info = calculate_sun(scene.lights[i]);\n \
break;\n \ break;\n \
}\n \ }\n \
ComputedLightSurfaceInfo light_surface_info = compute_light_surface(light_info.direction, surface_info);\n"; SurfaceBRDF surface_brdf = brdf(light_info.direction, surface_info);\n";
if(render_options.enable_normal_mapping && has_normal_mapping && render_options.enable_normal_shadowing) { if(render_options.enable_normal_mapping && has_normal_mapping && render_options.enable_normal_shadowing) {
src += std::string("light_info.radiance *= calculate_normal_lighting(") + normal_map_property_name + ", final_normal, light_info.direction);\n"; src += std::string("light_info.radiance *= calculate_normal_lighting(") + normal_map_property_name + ", final_normal, light_info.direction);\n";
} }
src += "Lo += (light_surface_info.kD * final_diffuse_color.rgb / PI + light_surface_info.specular) * light_surface_info.NdotL * scene.lights[i].colorSize.xyz * light_info.radiance;\n \ src += "Lo += ((surface_brdf.specular + surface_brdf.diffuse) * light_info.radiance * surface_brdf.NdotL) * scene.lights[i].colorSize.rgb;\n \
}\n"; }\n";
if(use_ibl) { if(use_ibl) {
src += src +=
"const vec3 F = fresnel_schlick_roughness(surface_info.NdotV, surface_info.F0, surface_info.roughness); \n \ "vec3 ambient = vec3(0.0); \
const vec3 kD = (1.0 - F) * (1.0 - surface_info.metallic); \n \
vec3 ambient = vec3(0.0); \
float sum = 0.0;\n \ float sum = 0.0;\n \
for(int i = 0; i < max_probes; i++) { \ for(int i = 0; i < max_probes; i++) { \
if(scene.probes[i].position.w == 1) {\n \ if(scene.probes[i].position.w == 1) {\n \
vec3 position = scene.probes[i].position.xyz; \ const vec3 position = scene.probes[i].position.xyz; \
vec3 probe_min = position - (scene.probes[i].size.xyz / 2.0); \ const vec3 probe_min = position - (scene.probes[i].size.xyz / 2.0); \
vec3 probe_max = position + (scene.probes[i].size.xyz / 2.0); \ const vec3 probe_max = position + (scene.probes[i].size.xyz / 2.0); \
if(all(greaterThan(in_frag_pos, probe_min)) && all(lessThan(in_frag_pos, probe_max)) && scene.probes[i].position.w == 1) { \ if(all(greaterThan(in_frag_pos, probe_min)) && all(lessThan(in_frag_pos, probe_max))) { \
float intensity = 1.0 - length(abs(in_frag_pos - position) / (scene.probes[i].size.xyz / 2.0));\n \ float intensity = 1.0 - length(abs(in_frag_pos - position) / (scene.probes[i].size.xyz / 2.0));\n \
intensity = clamp(intensity, 0.0, 1.0) * scene.probes[i].size.w;\n \ intensity = clamp(intensity, 0.0, 1.0) * scene.probes[i].size.w;\n \
const vec3 R = get_reflect(i, surface_info.N);\n \ ambient += ibl(i, surface_info, intensity);\n \
const vec2 brdf = texture(brdfSampler, vec2(surface_info.NdotV, surface_info.roughness)).rg; \n \
const vec3 sampledIrradiance = texture(irrandianceSampler, vec4(surface_info.N, i)).xyz;\n \
const vec3 prefilteredColor = textureLod(prefilterSampler, vec4(R, i), surface_info.roughness * 4).xyz;\n \
const vec3 diffuse = sampledIrradiance * final_diffuse_color.rgb;\n \
const vec3 specular = prefilteredColor * (F * brdf.x + brdf.y);\n \
ambient += (kD * diffuse + specular) * intensity;\n \
sum += intensity; \n \ sum += intensity; \n \
} \ } \
} else if(scene.probes[i].position.w == 2) {\n \ } else if(scene.probes[i].position.w == 2) {\n \
const vec3 R = reflect(-surface_info.V, surface_info.N);\n \ ambient += ibl(i, surface_info, scene.probes[i].size.w);\n \
const vec2 brdf = texture(brdfSampler, vec2(surface_info.NdotV, surface_info.roughness)).rg; \n \ sum += scene.probes[i].size.w; \n \
const vec3 sampledIrradiance = texture(irrandianceSampler, vec4(surface_info.N, i)).xyz;\n \
const vec3 prefilteredColor = textureLod(prefilterSampler, vec4(R, i), surface_info.roughness * 4).xyz;\n \
const vec3 diffuse = sampledIrradiance * final_diffuse_color.rgb;\n \
const vec3 specular = prefilteredColor * (F * brdf.x + brdf.y);\n \
ambient += (kD * diffuse + specular) * scene.probes[i].size.w;\n \
sum += 1.0; \n \
}\n \ }\n \
}\n \ }\n \
ambient /= sum;\n"; ambient /= sum;\n";

View file

@ -706,6 +706,8 @@ void Renderer::create_mesh_pipeline(Material& material) {
pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material, false); // scene capture does not use IBL pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material, false); // scene capture does not use IBL
pipelineInfo.rasterization.culling_mode = GFXCullingMode::Frontface;
material.capture_pipeline = material_compiler.create_static_pipeline(pipelineInfo, false, true); material.capture_pipeline = material_compiler.create_static_pipeline(pipelineInfo, false, true);
} }

View file

@ -47,8 +47,8 @@ const int mipLevels = 5;
const std::array<Matrix4x4, 6> sceneTransforms = { const std::array<Matrix4x4, 6> sceneTransforms = {
transform::look_at(Vector3(0), Vector3(1.0, 0.0, 0.0), Vector3(0.0, -1.0, 0.0)), transform::look_at(Vector3(0), Vector3(1.0, 0.0, 0.0), Vector3(0.0, -1.0, 0.0)),
transform::look_at(Vector3(0), Vector3(-1.0, 0.0, 0.0), Vector3(0.0, -1.0, 0.0)), transform::look_at(Vector3(0), Vector3(-1.0, 0.0, 0.0), Vector3(0.0, -1.0, 0.0)),
transform::look_at(Vector3(0), Vector3( 0.0, -1.0, 0.0), Vector3(0.0, 0.0,1.0)), transform::look_at(Vector3(0), Vector3( 0.0, -1.0, 0.0), Vector3(0.0, 0.0,-1.0)),
transform::look_at(Vector3(0), Vector3( 0.0, 1.0, 0.0), Vector3(0.0, 0.0,-1.0)), transform::look_at(Vector3(0), Vector3( 0.0, 1.0, 0.0), Vector3(0.0, 0.0,1.0)),
transform::look_at(Vector3(0), Vector3( 0.0, 0.0, 1.0), Vector3(0.0, -1.0, 0.0)), transform::look_at(Vector3(0), Vector3( 0.0, 0.0, 1.0), Vector3(0.0, -1.0, 0.0)),
transform::look_at(Vector3(0), Vector3( 0.0, 0.0, -1.0), Vector3(0.0, -1.0, 0.0)) transform::look_at(Vector3(0), Vector3( 0.0, 0.0, -1.0), Vector3(0.0, -1.0, 0.0))
}; };
@ -165,8 +165,8 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
Vector3 front = Vector3(0.0f, 0.0f, 1.0f) * scene->get<Transform>(obj).rotation; Vector3 front = Vector3(0.0f, 0.0f, 1.0f) * scene->get<Transform>(obj).rotation;
sl.directionPower = Vector4(-front, light.power); sl.directionPower = Vector4(-front, light.power);
sl.colorSize = Vector4(light.color, radians(light.size)); sl.colorSize = Vector4(light.color, radians(light.spot_size));
sl.shadowsEnable = Vector4(light.enable_shadows, 0, 0, 0); sl.shadowsEnable = Vector4(light.enable_shadows, radians(light.size), 0, 0);
sceneInfo.lights[sceneInfo.numLights++] = sl; sceneInfo.lights[sceneInfo.numLights++] = sl;
} }

View file

@ -21,7 +21,7 @@ vec2 IntegrateBRDF(float NdotV, float roughness) {
// preferred alignment direction (importance sampling). // preferred alignment direction (importance sampling).
const vec2 Xi = hammersley(i, SAMPLE_COUNT); const vec2 Xi = hammersley(i, SAMPLE_COUNT);
const vec3 H = importance_sample_ggx(Xi, N, roughness); const vec3 H = importance_sample_ggx(Xi, N, roughness);
const vec3 L = normalize(2.0 * dot(V, H) * H - V); const vec3 L = 2.0 * dot(V, H) * H - V;
const float NdotL = max(L.z, 0.0); const float NdotL = max(L.z, 0.0);
const float NdotH = max(H.z, 0.0); const float NdotH = max(H.z, 0.0);

View file

@ -88,10 +88,14 @@ float geometry_slick_direct(const vec3 N, const vec3 V, const float roughness) {
// GGX Smith Geometry, using GGX slick but combining both the view direction and the light direction // GGX Smith Geometry, using GGX slick but combining both the view direction and the light direction
float geometry_smith(const vec3 N, const vec3 V, const vec3 L, float roughness) { float geometry_smith(const vec3 N, const vec3 V, const vec3 L, float roughness) {
float ggx2 = geometry_slick_direct(N, V, roughness); const float dotNV = max(dot(N, V), 0.0);
float ggx1 = geometry_slick_direct(N, L, roughness); const float dotNL = max(dot(N, L), 0.0);
return ggx1 * ggx2; const float k = (roughness * roughness) / 2.0;
const float GL = dotNL / (dotNL * (1.0 - k) + k);
const float GV = dotNV / (dotNV * (1.0 - k) + k);
return GL * GV;
} }
// Fresnel Shlick // Fresnel Shlick

View file

@ -1,7 +1,7 @@
struct ComputedSurfaceInfo { struct ComputedSurfaceInfo {
vec3 N; vec3 N;
vec3 V; vec3 V;
vec3 F0; vec3 F0, diffuse_color;
float NdotV; float NdotV;
@ -16,47 +16,44 @@ ComputedSurfaceInfo compute_surface(const vec3 diffuse, const vec3 normal, const
info.NdotV = max(dot(info.N, info.V), 0.0); info.NdotV = max(dot(info.N, info.V), 0.0);
info.metallic = metallic; info.metallic = metallic;
info.roughness = max(0.0001, roughness * roughness); info.roughness = max(0.0001, roughness);
info.F0 = mix(vec3(0.04), diffuse, info.metallic); info.F0 = 0.16 * (1.0 - info.metallic) + diffuse * info.metallic;
info.diffuse_color = (1.0 - info.metallic) * diffuse;
return info; return info;
} }
struct ComputedLightSurfaceInfo { struct SurfaceBRDF {
vec3 kD; vec3 diffuse, specular;
vec3 specular;
float NdotL; float NdotL;
}; };
ComputedLightSurfaceInfo compute_light_surface(const vec3 L, const ComputedSurfaceInfo surface_info) { SurfaceBRDF brdf(const vec3 L, const ComputedSurfaceInfo surface_info) {
ComputedLightSurfaceInfo info; SurfaceBRDF info;
// half-vector // half-vector
const vec3 H = normalize(surface_info.V + L); const vec3 H = normalize(surface_info.V + L);
const float HdotV = clamp(dot(H, surface_info.V), 0.0, 1.0); const float HdotV = clamp(dot(H, surface_info.V), 0.0, 1.0);
const vec3 F = fresnel_schlick(HdotV, surface_info.F0); // fresnel reflectance function
const vec3 F = fresnel_schlick(surface_info.NdotV, surface_info.F0);
info.kD = (vec3(1.0) - F) * (1.0 - surface_info.metallic);
// geometry function
const float D = ggx_distribution(surface_info.N, H, surface_info.roughness); const float D = ggx_distribution(surface_info.N, H, surface_info.roughness);
// normal distribution function
const float G = geometry_smith(surface_info.N, surface_info.V, L, surface_info.roughness); const float G = geometry_smith(surface_info.N, surface_info.V, L, surface_info.roughness);
/*
F = fresnel reflectance function
G = geometry function
D = NDF (normal distribution function)
*/
const vec3 numerator = F * G * D; const vec3 numerator = F * G * D;
/*
Correction factor
*/
const float denominator = 4.0 * surface_info.NdotV * clamp(dot(surface_info.N, L), 0.0, 1.0); const float denominator = 4.0 * surface_info.NdotV * clamp(dot(surface_info.N, L), 0.0, 1.0);
// cook-torrance specular brdf
info.specular = numerator / (denominator + 0.001); info.specular = numerator / (denominator + 0.001);
// lambertian diffuse
info.diffuse = surface_info.diffuse_color * (1.0 / PI);
info.NdotL = clamp(dot(surface_info.N, L), 0.0, 1.0); info.NdotL = clamp(dot(surface_info.N, L), 0.0, 1.0);
return info; return info;