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";
}
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";
bool has_output = false;
@ -335,47 +347,33 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
light_info = calculate_sun(scene.lights[i]);\n \
break;\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) {
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";
if(use_ibl) {
src +=
"const vec3 F = fresnel_schlick_roughness(surface_info.NdotV, surface_info.F0, surface_info.roughness); \n \
const vec3 kD = (1.0 - F) * (1.0 - surface_info.metallic); \n \
vec3 ambient = vec3(0.0); \
"vec3 ambient = vec3(0.0); \
float sum = 0.0;\n \
for(int i = 0; i < max_probes; i++) { \
if(scene.probes[i].position.w == 1) {\n \
vec3 position = scene.probes[i].position.xyz; \
vec3 probe_min = position - (scene.probes[i].size.xyz / 2.0); \
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) { \
const vec3 position = scene.probes[i].position.xyz; \
const vec3 probe_min = 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))) { \
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 \
const vec3 R = get_reflect(i, 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, 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 \
ambient += ibl(i, surface_info, intensity);\n \
sum += intensity; \n \
} \
} else if(scene.probes[i].position.w == 2) {\n \
const vec3 R = reflect(-surface_info.V, 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, 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 \
ambient += ibl(i, surface_info, scene.probes[i].size.w);\n \
sum += scene.probes[i].size.w; \n \
}\n \
}\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.rasterization.culling_mode = GFXCullingMode::Frontface;
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 = {
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))
};
@ -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;
sl.directionPower = Vector4(-front, light.power);
sl.colorSize = Vector4(light.color, radians(light.size));
sl.shadowsEnable = Vector4(light.enable_shadows, 0, 0, 0);
sl.colorSize = Vector4(light.color, radians(light.spot_size));
sl.shadowsEnable = Vector4(light.enable_shadows, radians(light.size), 0, 0);
sceneInfo.lights[sceneInfo.numLights++] = sl;
}

View file

@ -21,7 +21,7 @@ vec2 IntegrateBRDF(float NdotV, float roughness) {
// preferred alignment direction (importance sampling).
const vec2 Xi = hammersley(i, SAMPLE_COUNT);
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 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
float geometry_smith(const vec3 N, const vec3 V, const vec3 L, float roughness) {
float ggx2 = geometry_slick_direct(N, V, roughness);
float ggx1 = geometry_slick_direct(N, L, roughness);
const float dotNV = max(dot(N, V), 0.0);
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

View file

@ -1,7 +1,7 @@
struct ComputedSurfaceInfo {
vec3 N;
vec3 V;
vec3 F0;
vec3 F0, diffuse_color;
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.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;
}
struct ComputedLightSurfaceInfo {
vec3 kD;
vec3 specular;
struct SurfaceBRDF {
vec3 diffuse, specular;
float NdotL;
};
ComputedLightSurfaceInfo compute_light_surface(const vec3 L, const ComputedSurfaceInfo surface_info) {
ComputedLightSurfaceInfo info;
SurfaceBRDF brdf(const vec3 L, const ComputedSurfaceInfo surface_info) {
SurfaceBRDF info;
// half-vector
const vec3 H = normalize(surface_info.V + L);
const float HdotV = clamp(dot(H, surface_info.V), 0.0, 1.0);
const vec3 F = fresnel_schlick(HdotV, surface_info.F0);
info.kD = (vec3(1.0) - F) * (1.0 - surface_info.metallic);
// fresnel reflectance function
const vec3 F = fresnel_schlick(surface_info.NdotV, surface_info.F0);
// geometry function
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);
/*
F = fresnel reflectance function
G = geometry function
D = NDF (normal distribution function)
*/
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);
// cook-torrance specular brdf
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);
return info;