Remove kD term, improve fresnel reflections and fix scene capture
This commit is contained in:
parent
69eb4bea34
commit
92e04068fd
6 changed files with 58 additions and 57 deletions
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Reference in a new issue