You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
Replace BRDF approximation with a DFG LUT
This commit is contained in:
@@ -723,6 +723,8 @@
|
|||||||
</constant>
|
</constant>
|
||||||
<constant name="SPECULAR_SCHLICK_GGX" value="0" enum="SpecularMode">
|
<constant name="SPECULAR_SCHLICK_GGX" value="0" enum="SpecularMode">
|
||||||
Default specular blob.
|
Default specular blob.
|
||||||
|
[b]Note:[/b] Forward+ uses multiscattering for more accurate reflections, although the impact of multiscattering is more noticeable on rough metallic surfaces than on smooth, non-metallic surfaces.
|
||||||
|
[b]Note:[/b] Mobile and Compatibility don't perform multiscattering for performance reasons. Instead, they perform single scattering, which means rough metallic surfaces may look slightly darker than intended.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="SPECULAR_TOON" value="1" enum="SpecularMode">
|
<constant name="SPECULAR_TOON" value="1" enum="SpecularMode">
|
||||||
Toon blob which changes size based on roughness.
|
Toon blob which changes size based on roughness.
|
||||||
|
|||||||
@@ -3205,6 +3205,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
|
|||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.binding = 16;
|
||||||
|
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||||
|
u.append_id(dfg_lut.texture);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET);
|
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4946,6 +4954,45 @@ RenderForwardClustered::RenderForwardClustered() {
|
|||||||
best_fit_normal.shader.version_free(best_fit_normal.shader_version);
|
best_fit_normal.shader.version_free(best_fit_normal.shader_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DFG LUT */
|
||||||
|
{
|
||||||
|
Vector<String> modes;
|
||||||
|
modes.push_back("\n");
|
||||||
|
dfg_lut.shader.initialize(modes);
|
||||||
|
dfg_lut.shader_version = dfg_lut.shader.version_create();
|
||||||
|
dfg_lut.pipeline = RD::get_singleton()->compute_pipeline_create(dfg_lut.shader.version_get_shader(dfg_lut.shader_version, 0));
|
||||||
|
|
||||||
|
RD::TextureFormat tformat;
|
||||||
|
tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
|
tformat.width = 128;
|
||||||
|
tformat.height = 128;
|
||||||
|
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||||
|
tformat.texture_type = RD::TEXTURE_TYPE_2D;
|
||||||
|
dfg_lut.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
|
||||||
|
|
||||||
|
RID shader = dfg_lut.shader.version_get_shader(dfg_lut.shader_version, 0);
|
||||||
|
ERR_FAIL_COND(shader.is_null());
|
||||||
|
|
||||||
|
Vector<RD::Uniform> uniforms;
|
||||||
|
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.binding = 0;
|
||||||
|
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||||
|
u.append_id(dfg_lut.texture);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0);
|
||||||
|
|
||||||
|
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||||
|
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, dfg_lut.pipeline);
|
||||||
|
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0);
|
||||||
|
RD::get_singleton()->compute_list_dispatch_threads(compute_list, tformat.width, tformat.height, 1);
|
||||||
|
RD::get_singleton()->compute_list_end();
|
||||||
|
|
||||||
|
dfg_lut.shader.version_free(dfg_lut.shader_version);
|
||||||
|
}
|
||||||
|
|
||||||
_update_shader_quality_settings();
|
_update_shader_quality_settings();
|
||||||
_update_global_pipeline_data_requirements_from_project();
|
_update_global_pipeline_data_requirements_from_project();
|
||||||
|
|
||||||
@@ -4995,6 +5042,7 @@ RenderForwardClustered::~RenderForwardClustered() {
|
|||||||
RD::get_singleton()->free(shadow_sampler);
|
RD::get_singleton()->free(shadow_sampler);
|
||||||
RSG::light_storage->directional_shadow_atlas_set_size(0);
|
RSG::light_storage->directional_shadow_atlas_set_size(0);
|
||||||
RD::get_singleton()->free(best_fit_normal.texture);
|
RD::get_singleton()->free(best_fit_normal.texture);
|
||||||
|
RD::get_singleton()->free(dfg_lut.texture);
|
||||||
|
|
||||||
{
|
{
|
||||||
for (const RID &rid : scene_state.uniform_buffers) {
|
for (const RID &rid : scene_state.uniform_buffers) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
|
#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
|
||||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||||
#include "servers/rendering/renderer_rd/shaders/forward_clustered/best_fit_normal.glsl.gen.h"
|
#include "servers/rendering/renderer_rd/shaders/forward_clustered/best_fit_normal.glsl.gen.h"
|
||||||
|
#include "servers/rendering/renderer_rd/shaders/forward_clustered/integrate_dfg.glsl.gen.h"
|
||||||
|
|
||||||
#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
|
#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
|
||||||
|
|
||||||
@@ -180,6 +181,13 @@ private:
|
|||||||
RID texture;
|
RID texture;
|
||||||
} best_fit_normal;
|
} best_fit_normal;
|
||||||
|
|
||||||
|
struct IntegrateDFG {
|
||||||
|
IntegrateDfgShaderRD shader;
|
||||||
|
RID shader_version;
|
||||||
|
RID pipeline;
|
||||||
|
RID texture;
|
||||||
|
} dfg_lut;
|
||||||
|
|
||||||
enum PassMode {
|
enum PassMode {
|
||||||
PASS_MODE_COLOR,
|
PASS_MODE_COLOR,
|
||||||
PASS_MODE_SHADOW,
|
PASS_MODE_SHADOW,
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
#[compute]
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
// References:
|
||||||
|
// https://www.gamedevs.org/uploads/real-shading-in-unreal-engine-4.pdf
|
||||||
|
// https://google.github.io/filament/Filament.html
|
||||||
|
// https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||||
|
|
||||||
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(rgba16f, set = 0, binding = 0) uniform restrict writeonly image2D current_image;
|
||||||
|
|
||||||
|
#define M_PI 3.14159265359
|
||||||
|
#define SAMPLE_COUNT 1024
|
||||||
|
#define SIZE 128
|
||||||
|
|
||||||
|
#define saturate(x) clamp(x, 0, 1)
|
||||||
|
|
||||||
|
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
||||||
|
// efficient VanDerCorpus calculation
|
||||||
|
float radical_inverse_vdc(uint bits) {
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 hammersley(uint i, float n) {
|
||||||
|
return vec2(float(i) / n, radical_inverse_vdc(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 importance_sample_ggx(vec2 Xi, vec3 N, float roughness) {
|
||||||
|
float a = roughness * roughness;
|
||||||
|
|
||||||
|
float phi = 2.0 * M_PI * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates - halfway vector
|
||||||
|
vec3 H;
|
||||||
|
H.x = cos(phi) * sinTheta;
|
||||||
|
H.y = sin(phi) * sinTheta;
|
||||||
|
H.z = cosTheta;
|
||||||
|
|
||||||
|
// from tangent-space H vector to world-space sample vector
|
||||||
|
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||||
|
vec3 tangent = normalize(cross(up, N));
|
||||||
|
vec3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
|
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return normalize(sampleVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
float geometry_schlick_ggx(float NdotV, float roughness) {
|
||||||
|
// note that we use a different k for IBL
|
||||||
|
float a = roughness;
|
||||||
|
float k = (a * a) / 2.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float geometry_smith(vec3 N, vec3 V, vec3 L, float roughness) {
|
||||||
|
float NdotV = saturate(dot(N, V));
|
||||||
|
float NdotL = saturate(dot(N, L));
|
||||||
|
float ggx2 = geometry_schlick_ggx(NdotV, roughness);
|
||||||
|
float ggx1 = geometry_schlick_ggx(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 importance_uniform_sample(vec2 u) {
|
||||||
|
float phi = 2.0f * M_PI * u.x;
|
||||||
|
float cosTheta = 1 - u.y;
|
||||||
|
float sinTheta = sqrt(1 - cosTheta * cosTheta);
|
||||||
|
return vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
|
||||||
|
}
|
||||||
|
|
||||||
|
float distribution_charlie(float NoH, float roughness) {
|
||||||
|
// Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF"
|
||||||
|
float a = roughness * roughness;
|
||||||
|
float invAlpha = 1 / a;
|
||||||
|
float cos2h = NoH * NoH;
|
||||||
|
float sin2h = 1 - cos2h;
|
||||||
|
return (2.0f + invAlpha) * pow(sin2h, invAlpha * 0.5f) / (2.0f * M_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
float visibility_ashikhmin(float NoV, float NoL) {
|
||||||
|
// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
|
||||||
|
return 1 / (4 * (NoL + NoV - NoL * NoV));
|
||||||
|
}
|
||||||
|
|
||||||
|
void integrate_brdfs(float n_dot_v, float roughness, out vec2 brdf, out float cloth_brdf) {
|
||||||
|
vec3 v = vec3(sqrt(1.0 - n_dot_v * n_dot_v), 0, n_dot_v);
|
||||||
|
vec3 n = vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
float A = 0.0f;
|
||||||
|
float B = 0.0f;
|
||||||
|
float C = 0.0f;
|
||||||
|
|
||||||
|
for (uint i = 0; i < SAMPLE_COUNT; ++i) {
|
||||||
|
vec2 Xi = hammersley(i, SAMPLE_COUNT);
|
||||||
|
vec3 h = importance_sample_ggx(Xi, n, roughness);
|
||||||
|
vec3 l = normalize(2.0 * dot(v, h) * h - v);
|
||||||
|
|
||||||
|
float n_dot_l = saturate(l.z);
|
||||||
|
float n_dot_h = saturate(h.z);
|
||||||
|
float v_dot_h = saturate(dot(v, h));
|
||||||
|
|
||||||
|
if (n_dot_l > 0.0) {
|
||||||
|
float G = geometry_smith(n, v, l, roughness);
|
||||||
|
float G_Vis = (G * v_dot_h) / (n_dot_h * n_dot_v);
|
||||||
|
float Fc = pow(1.0 - v_dot_h, 5.0);
|
||||||
|
|
||||||
|
// LDFG term for multiscattering
|
||||||
|
// https://google.github.io/filament/Filament.html#toc5.3.4.7
|
||||||
|
A += Fc * G_Vis;
|
||||||
|
B += G_Vis;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloth BRDF calculations
|
||||||
|
// https://github.com/google/filament/blob/main/libs/ibl/src/CubemapIBL.cpp#L856-L874
|
||||||
|
vec3 h_cloth = importance_uniform_sample(Xi);
|
||||||
|
vec3 l_cloth = normalize(2.0 * dot(v, h_cloth) * h_cloth - v);
|
||||||
|
float n_dot_l_cloth = saturate(l_cloth.z);
|
||||||
|
float n_dot_h_cloth = saturate(h_cloth.z);
|
||||||
|
float v_dot_h_cloth = saturate(dot(v, h_cloth));
|
||||||
|
|
||||||
|
if (n_dot_l_cloth > 0.0) {
|
||||||
|
float v_cloth = visibility_ashikhmin(n_dot_v, n_dot_l_cloth);
|
||||||
|
float d_cloth = distribution_charlie(n_dot_h_cloth, roughness);
|
||||||
|
C += v_cloth * d_cloth * n_dot_l_cloth * v_dot_h_cloth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
A /= float(SAMPLE_COUNT);
|
||||||
|
B /= float(SAMPLE_COUNT);
|
||||||
|
C *= (4.0 * 2.0 * M_PI / SAMPLE_COUNT);
|
||||||
|
|
||||||
|
brdf = vec2(A, B);
|
||||||
|
cloth_brdf = C;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
float roughness = float(pos.y + 0.5f) / SIZE;
|
||||||
|
float NdotV = float(pos.x + 0.5f) / SIZE;
|
||||||
|
vec2 brdf;
|
||||||
|
float cloth_brdf;
|
||||||
|
integrate_brdfs(NdotV, roughness, brdf, cloth_brdf);
|
||||||
|
ivec2 out_pos = ivec2(pos.x, (SIZE - 1) - pos.y);
|
||||||
|
imageStore(current_image, out_pos, vec4(brdf, cloth_brdf, 1.0));
|
||||||
|
}
|
||||||
@@ -1151,6 +1151,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||||||
float clearcoat_roughness = 0.0;
|
float clearcoat_roughness = 0.0;
|
||||||
float anisotropy = 0.0;
|
float anisotropy = 0.0;
|
||||||
vec2 anisotropy_flow = vec2(1.0, 0.0);
|
vec2 anisotropy_flow = vec2(1.0, 0.0);
|
||||||
|
vec3 energy_compensation = vec3(1.0);
|
||||||
#ifndef FOG_DISABLED
|
#ifndef FOG_DISABLED
|
||||||
vec4 fog = vec4(0.0);
|
vec4 fog = vec4(0.0);
|
||||||
#endif // !FOG_DISABLED
|
#endif // !FOG_DISABLED
|
||||||
@@ -1994,19 +1995,15 @@ void fragment_shader(in SceneData scene_data) {
|
|||||||
//simplify for toon, as
|
//simplify for toon, as
|
||||||
specular_light *= specular * metallic * albedo * 2.0;
|
specular_light *= specular * metallic * albedo * 2.0;
|
||||||
#else
|
#else
|
||||||
|
// Base Layer
|
||||||
|
float NdotV = clamp(dot(normal, view), 0.0001, 1.0);
|
||||||
|
vec2 envBRDF = prefiltered_dfg(roughness, NdotV).xy;
|
||||||
|
// Multiscattering
|
||||||
|
energy_compensation = get_energy_compensation(f0, envBRDF.y);
|
||||||
|
|
||||||
// scales the specular reflections, needs to be computed before lighting happens,
|
// cheap luminance approximation
|
||||||
// but after environment, GI, and reflection probes are added
|
float f90 = clamp(50.0 * f0.g, metallic, 1.0);
|
||||||
// Environment brdf approximation (Lazarov 2013)
|
specular_light *= energy_compensation * (f90 * envBRDF.x + f0 * envBRDF.y);
|
||||||
// see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
|
|
||||||
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
|
|
||||||
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
|
|
||||||
vec4 r = roughness * c0 + c1;
|
|
||||||
float ndotv = clamp(dot(normal, view), 0.0, 1.0);
|
|
||||||
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
|
|
||||||
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
|
|
||||||
|
|
||||||
specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2405,7 +2402,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||||||
#else
|
#else
|
||||||
directional_lights.data[i].color * directional_lights.data[i].energy * tint,
|
directional_lights.data[i].color * directional_lights.data[i].energy * tint,
|
||||||
#endif
|
#endif
|
||||||
true, shadow, f0, orms, directional_lights.data[i].specular, albedo, alpha, screen_uv,
|
true, shadow, f0, orms, directional_lights.data[i].specular, albedo, alpha, screen_uv, energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -2475,7 +2472,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||||||
continue; // Statically baked light and object uses lightmap, skip
|
continue; // Statically baked light and object uses lightmap, skip
|
||||||
}
|
}
|
||||||
|
|
||||||
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv, energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -2543,7 +2540,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||||||
continue; // Statically baked light and object uses lightmap, skip
|
continue; // Statically baked light and object uses lightmap, skip
|
||||||
}
|
}
|
||||||
|
|
||||||
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv, energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -280,6 +280,8 @@ layout(set = 0, binding = 14) uniform sampler DEFAULT_SAMPLER_LINEAR_WITH_MIPMAP
|
|||||||
|
|
||||||
layout(set = 0, binding = 15) uniform texture2D best_fit_normal_texture;
|
layout(set = 0, binding = 15) uniform texture2D best_fit_normal_texture;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 16) uniform texture2D dfg;
|
||||||
|
|
||||||
/* Set 1: Render Pass (changes per render pass) */
|
/* Set 1: Render Pass (changes per render pass) */
|
||||||
|
|
||||||
layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
|
layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
|
||||||
@@ -454,6 +456,18 @@ vec4 normal_roughness_compatibility(vec4 p_normal_roughness) {
|
|||||||
return vec4(normalize(p_normal_roughness.xyz * 2.0 - 1.0) * 0.5 + 0.5, roughness);
|
return vec4(normalize(p_normal_roughness.xyz * 2.0 - 1.0) * 0.5 + 0.5, roughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://google.github.io/filament/Filament.html#toc5.3.4.7
|
||||||
|
// Note: The roughness value is inverted
|
||||||
|
vec3 prefiltered_dfg(float lod, float NoV) {
|
||||||
|
return textureLod(sampler2D(dfg, SAMPLER_LINEAR_CLAMP), vec2(NoV, 1.0 - lod), 0.0).rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute multiscatter compensation
|
||||||
|
// https://google.github.io/filament/Filament.html#listing_energycompensationimpl
|
||||||
|
vec3 get_energy_compensation(vec3 f0, float env) {
|
||||||
|
return 1.0 + f0 * (1.0 / env - 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set 2 Skeleton & Instancing (can change per item) */
|
/* Set 2 Skeleton & Instancing (can change per item) */
|
||||||
|
|
||||||
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {
|
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {
|
||||||
|
|||||||
@@ -1705,7 +1705,8 @@ void main() {
|
|||||||
|
|
||||||
light_compute(normal, directional_lights.data[i].direction, view, size_A,
|
light_compute(normal, directional_lights.data[i].direction, view, size_A,
|
||||||
directional_lights.data[i].color * directional_lights.data[i].energy * tint,
|
directional_lights.data[i].color * directional_lights.data[i].energy * tint,
|
||||||
true, shadow, f0, orms, directional_lights.data[i].specular, albedo, alpha, screen_uv,
|
true, shadow, f0, orms, directional_lights.data[i].specular, albedo, alpha,
|
||||||
|
screen_uv, vec3(1.0),
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -1736,7 +1737,7 @@ void main() {
|
|||||||
uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
|
uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
|
||||||
for (uint i = 0; i < sc_omni_lights(); i++) {
|
for (uint i = 0; i < sc_omni_lights(); i++) {
|
||||||
uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
|
uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
|
||||||
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv, vec3(1.0),
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -1764,7 +1765,7 @@ void main() {
|
|||||||
uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
|
uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
|
||||||
for (uint i = 0; i < sc_spot_lights(); i++) {
|
for (uint i = 0; i < sc_spot_lights(); i++) {
|
||||||
uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
|
uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
|
||||||
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv, vec3(1.0),
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
|
|||||||
return mix(vec3(dielectric), albedo, vec3(metallic));
|
return mix(vec3(dielectric), albedo, vec3(metallic));
|
||||||
}
|
}
|
||||||
|
|
||||||
void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv,
|
void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
vec3 backlight,
|
vec3 backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -230,7 +230,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|||||||
// https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
|
// https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
|
||||||
float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0);
|
float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0);
|
||||||
vec3 F = f0 + (f90 - f0) * cLdotH5;
|
vec3 F = f0 + (f90 - f0) * cLdotH5;
|
||||||
vec3 specular_brdf_NL = cNdotL * D * F * G;
|
vec3 specular_brdf_NL = energy_compensation * (cNdotL * D * F * G);
|
||||||
specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;
|
specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
|
|||||||
return nd * pow(max(distance, 0.0001), -decay);
|
return nd * pow(max(distance, 0.0001), -decay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv,
|
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
vec3 backlight,
|
vec3 backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -667,7 +667,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec3 light_rel_vec_norm = light_rel_vec / light_length;
|
vec3 light_rel_vec_norm = light_rel_vec / light_length;
|
||||||
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, omni_attenuation * shadow, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, screen_uv,
|
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, omni_attenuation * shadow, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, screen_uv, energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -702,7 +702,7 @@ vec2 normal_to_panorama(vec3 n) {
|
|||||||
return panorama_coords;
|
return panorama_coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv,
|
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
vec3 backlight,
|
vec3 backlight,
|
||||||
#endif
|
#endif
|
||||||
@@ -871,7 +871,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, spot_attenuation * shadow, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, screen_uv,
|
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, spot_attenuation * shadow, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, screen_uv, energy_compensation,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user