ADD: IBL glsl cleaning
This commit is contained in:
@@ -1,21 +1,11 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_GOOGLE_include_directive : require
|
#extension GL_GOOGLE_include_directive : require
|
||||||
#include "input_structures.glsl"
|
#include "input_structures.glsl"
|
||||||
|
#include "ibl_common.glsl"
|
||||||
|
|
||||||
layout(location=0) in vec2 inUV;
|
layout(location=0) in vec2 inUV;
|
||||||
layout(location=0) out vec4 outColor;
|
layout(location=0) out vec4 outColor;
|
||||||
|
|
||||||
// IBL specular equirect 2D (LOD 0 for background)
|
|
||||||
layout(set=3, binding=0) uniform sampler2D iblSpec2D;
|
|
||||||
|
|
||||||
vec2 dir_to_equirect(vec3 d)
|
|
||||||
{
|
|
||||||
d = normalize(d);
|
|
||||||
float phi = atan(d.z, d.x);
|
|
||||||
float theta = acos(clamp(d.y, -1.0, 1.0));
|
|
||||||
return vec2(phi * (0.15915494309) + 0.5, theta * (0.31830988618));
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Reconstruct world-space direction from screen UV
|
// Reconstruct world-space direction from screen UV
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_GOOGLE_include_directive : require
|
#extension GL_GOOGLE_include_directive : require
|
||||||
#extension GL_EXT_ray_query : require
|
#extension GL_EXT_ray_query : require
|
||||||
#include "input_structures.glsl"
|
#include "input_structures.glsl"
|
||||||
|
#include "ibl_common.glsl"
|
||||||
|
|
||||||
layout(location=0) in vec2 inUV;
|
layout(location=0) in vec2 inUV;
|
||||||
layout(location=0) out vec4 outColor;
|
layout(location=0) out vec4 outColor;
|
||||||
@@ -10,33 +11,6 @@ layout(set=1, binding=0) uniform sampler2D posTex;
|
|||||||
layout(set=1, binding=1) uniform sampler2D normalTex;
|
layout(set=1, binding=1) uniform sampler2D normalTex;
|
||||||
layout(set=1, binding=2) uniform sampler2D albedoTex;
|
layout(set=1, binding=2) uniform sampler2D albedoTex;
|
||||||
layout(set=2, binding=0) uniform sampler2D shadowTex[4];
|
layout(set=2, binding=0) uniform sampler2D shadowTex[4];
|
||||||
// IBL (set=3): specular prefiltered cube, diffuse irradiance cube, BRDF LUT
|
|
||||||
layout(set=3, binding=0) uniform sampler2D iblSpec2D;
|
|
||||||
layout(set=3, binding=1) uniform sampler2D iblBRDF;
|
|
||||||
layout(std140, set=3, binding=2) uniform IBL_SH { vec4 sh[9]; } iblSH;
|
|
||||||
|
|
||||||
vec3 sh_eval_irradiance(vec3 n)
|
|
||||||
{
|
|
||||||
float x=n.x, y=n.y, z=n.z;
|
|
||||||
const float c0=0.2820947918;
|
|
||||||
const float c1=0.4886025119;
|
|
||||||
const float c2=1.0925484306;
|
|
||||||
const float c3=0.3153915653;
|
|
||||||
const float c4=0.5462742153;
|
|
||||||
float Y[9];
|
|
||||||
Y[0]=c0; Y[1]=c1*y; Y[2]=c1*z; Y[3]=c1*x; Y[4]=c2*x*y; Y[5]=c2*y*z; Y[6]=c3*(3.0*z*z-1.0); Y[7]=c2*x*z; Y[8]=c4*(x*x-y*y);
|
|
||||||
vec3 r=vec3(0.0);
|
|
||||||
for (int i=0;i<9;++i) r += iblSH.sh[i].rgb * Y[i];
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 dir_to_equirect(vec3 d)
|
|
||||||
{
|
|
||||||
d = normalize(d);
|
|
||||||
float phi = atan(d.z, d.x);
|
|
||||||
float theta = acos(clamp(d.y, -1.0, 1.0));
|
|
||||||
return vec2(phi * (0.15915494309) + 0.5, theta * (0.31830988618));
|
|
||||||
}
|
|
||||||
// TLAS for ray query (optional, guarded by sceneData.rtOptions.x)
|
// TLAS for ray query (optional, guarded by sceneData.rtOptions.x)
|
||||||
#ifdef GL_EXT_ray_query
|
#ifdef GL_EXT_ray_query
|
||||||
layout(set=0, binding=1) uniform accelerationStructureEXT topLevelAS;
|
layout(set=0, binding=1) uniform accelerationStructureEXT topLevelAS;
|
||||||
@@ -369,7 +343,7 @@ void main(){
|
|||||||
// Image-Based Lighting: split-sum approximation
|
// Image-Based Lighting: split-sum approximation
|
||||||
vec3 R = reflect(-V, N);
|
vec3 R = reflect(-V, N);
|
||||||
float levels = float(textureQueryLevels(iblSpec2D));
|
float levels = float(textureQueryLevels(iblSpec2D));
|
||||||
float lod = clamp(roughness * max(levels - 1.0, 0.0), 0.0, max(levels - 1.0, 0.0));
|
float lod = ibl_lod_from_roughness(roughness, levels);
|
||||||
vec2 uv = dir_to_equirect(R);
|
vec2 uv = dir_to_equirect(R);
|
||||||
vec3 prefiltered = textureLod(iblSpec2D, uv, lod).rgb;
|
vec3 prefiltered = textureLod(iblSpec2D, uv, lod).rgb;
|
||||||
vec2 brdf = texture(iblBRDF, vec2(max(dot(N, V), 0.0), roughness)).rg;
|
vec2 brdf = texture(iblBRDF, vec2(max(dot(N, V), 0.0), roughness)).rg;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_GOOGLE_include_directive : require
|
#extension GL_GOOGLE_include_directive : require
|
||||||
#include "input_structures.glsl"
|
#include "input_structures.glsl"
|
||||||
|
#include "ibl_common.glsl"
|
||||||
|
|
||||||
layout(location=0) in vec2 inUV;
|
layout(location=0) in vec2 inUV;
|
||||||
layout(location=0) out vec4 outColor;
|
layout(location=0) out vec4 outColor;
|
||||||
@@ -10,34 +11,6 @@ layout(set=1, binding=1) uniform sampler2D normalTex;
|
|||||||
layout(set=1, binding=2) uniform sampler2D albedoTex;
|
layout(set=1, binding=2) uniform sampler2D albedoTex;
|
||||||
layout(set=2, binding=0) uniform sampler2D shadowTex[4];
|
layout(set=2, binding=0) uniform sampler2D shadowTex[4];
|
||||||
|
|
||||||
// IBL (set=3): specular prefiltered cube, diffuse irradiance cube, BRDF LUT
|
|
||||||
layout(set=3, binding=0) uniform sampler2D iblSpec2D; // equirect 2D with prefiltered mips
|
|
||||||
layout(set=3, binding=1) uniform sampler2D iblBRDF; // RG LUT
|
|
||||||
layout(std140, set=3, binding=2) uniform IBL_SH { vec4 sh[9]; } iblSH;
|
|
||||||
|
|
||||||
vec3 sh_eval_irradiance(vec3 n)
|
|
||||||
{
|
|
||||||
float x=n.x, y=n.y, z=n.z;
|
|
||||||
const float c0=0.2820947918;
|
|
||||||
const float c1=0.4886025119;
|
|
||||||
const float c2=1.0925484306;
|
|
||||||
const float c3=0.3153915653;
|
|
||||||
const float c4=0.5462742153;
|
|
||||||
float Y[9];
|
|
||||||
Y[0]=c0; Y[1]=c1*y; Y[2]=c1*z; Y[3]=c1*x; Y[4]=c2*x*y; Y[5]=c2*y*z; Y[6]=c3*(3.0*z*z-1.0); Y[7]=c2*x*z; Y[8]=c4*(x*x-y*y);
|
|
||||||
vec3 r=vec3(0.0);
|
|
||||||
for (int i=0;i<9;++i) r += iblSH.sh[i].rgb * Y[i];
|
|
||||||
return r; // already convolved with Lambert in CPU bake
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 dir_to_equirect(vec3 d)
|
|
||||||
{
|
|
||||||
d = normalize(d);
|
|
||||||
float phi = atan(d.z, d.x);
|
|
||||||
float theta = acos(clamp(d.y, -1.0, 1.0));
|
|
||||||
return vec2(phi * (0.15915494309) + 0.5, theta * (0.31830988618));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tunables for shadow quality and blending
|
// Tunables for shadow quality and blending
|
||||||
// Border smoothing width in light-space NDC (0..1). Larger = wider cross-fade.
|
// Border smoothing width in light-space NDC (0..1). Larger = wider cross-fade.
|
||||||
const float SHADOW_BORDER_SMOOTH_NDC = 0.08;
|
const float SHADOW_BORDER_SMOOTH_NDC = 0.08;
|
||||||
@@ -299,7 +272,7 @@ void main(){
|
|||||||
// Image-Based Lighting: split-sum approximation
|
// Image-Based Lighting: split-sum approximation
|
||||||
vec3 R = reflect(-V, N);
|
vec3 R = reflect(-V, N);
|
||||||
float levels = float(textureQueryLevels(iblSpec2D));
|
float levels = float(textureQueryLevels(iblSpec2D));
|
||||||
float lod = clamp(roughness * max(levels - 1.0, 0.0), 0.0, max(levels - 1.0, 0.0));
|
float lod = ibl_lod_from_roughness(roughness, levels);
|
||||||
vec2 uv = dir_to_equirect(R);
|
vec2 uv = dir_to_equirect(R);
|
||||||
vec3 prefiltered = textureLod(iblSpec2D, uv, lod).rgb;
|
vec3 prefiltered = textureLod(iblSpec2D, uv, lod).rgb;
|
||||||
vec2 brdf = texture(iblBRDF, vec2(max(dot(N, V), 0.0), roughness)).rg;
|
vec2 brdf = texture(iblBRDF, vec2(max(dot(N, V), 0.0), roughness)).rg;
|
||||||
|
|||||||
57
shaders/ibl_common.glsl
Normal file
57
shaders/ibl_common.glsl
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#ifndef IBL_COMMON_GLSL
|
||||||
|
#define IBL_COMMON_GLSL
|
||||||
|
|
||||||
|
// IBL bindings (set=3): specular equirect 2D, BRDF LUT, SH UBO.
|
||||||
|
layout(set=3, binding=0) uniform sampler2D iblSpec2D;
|
||||||
|
layout(set=3, binding=1) uniform sampler2D iblBRDF;
|
||||||
|
layout(std140, set=3, binding=2) uniform IBL_SH { vec4 sh[9]; } iblSH;
|
||||||
|
|
||||||
|
// Evaluate diffuse irradiance from 2nd-order SH coefficients (9 coeffs).
|
||||||
|
// Coefficients are pre-convolved with the Lambert kernel on the CPU.
|
||||||
|
vec3 sh_eval_irradiance(vec3 n)
|
||||||
|
{
|
||||||
|
float x = n.x, y = n.y, z = n.z;
|
||||||
|
const float c0 = 0.2820947918;
|
||||||
|
const float c1 = 0.4886025119;
|
||||||
|
const float c2 = 1.0925484306;
|
||||||
|
const float c3 = 0.3153915653;
|
||||||
|
const float c4 = 0.5462742153;
|
||||||
|
float Y[9];
|
||||||
|
Y[0] = c0;
|
||||||
|
Y[1] = c1 * y;
|
||||||
|
Y[2] = c1 * z;
|
||||||
|
Y[3] = c1 * x;
|
||||||
|
Y[4] = c2 * x * y;
|
||||||
|
Y[5] = c2 * y * z;
|
||||||
|
Y[6] = c3 * (3.0 * z * z - 1.0);
|
||||||
|
Y[7] = c2 * x * z;
|
||||||
|
Y[8] = c4 * (x * x - y * y);
|
||||||
|
vec3 r = vec3(0.0);
|
||||||
|
for (int i = 0; i < 9; ++i)
|
||||||
|
{
|
||||||
|
r += iblSH.sh[i].rgb * Y[i];
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map direction to equirectangular UV (same convention across shaders).
|
||||||
|
vec2 dir_to_equirect(vec3 d)
|
||||||
|
{
|
||||||
|
d = normalize(d);
|
||||||
|
float phi = atan(d.z, d.x);
|
||||||
|
float theta = acos(clamp(d.y, -1.0, 1.0));
|
||||||
|
// 1/(2*pi) = 0.15915494309, 1/pi = 0.31830988618
|
||||||
|
return vec2(phi * 0.15915494309 + 0.5, theta * 0.31830988618);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper for selecting mip LOD from roughness and available levels.
|
||||||
|
// Uses roughness^2 to bias towards blurrier reflections at mid roughness.
|
||||||
|
float ibl_lod_from_roughness(float roughness, float levels)
|
||||||
|
{
|
||||||
|
float maxLevel = max(levels - 1.0, 0.0);
|
||||||
|
float r = clamp(roughness, 0.0, 1.0);
|
||||||
|
return r * r * maxLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IBL_COMMON_GLSL
|
||||||
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#extension GL_GOOGLE_include_directive : require
|
#extension GL_GOOGLE_include_directive : require
|
||||||
#include "input_structures.glsl"
|
#include "input_structures.glsl"
|
||||||
|
#include "ibl_common.glsl"
|
||||||
|
|
||||||
layout (location = 0) in vec3 inNormal;
|
layout (location = 0) in vec3 inNormal;
|
||||||
layout (location = 1) in vec3 inColor;
|
layout (location = 1) in vec3 inColor;
|
||||||
@@ -13,28 +14,6 @@ layout (location = 0) out vec4 outFragColor;
|
|||||||
|
|
||||||
const float PI = 3.14159265359;
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
// IBL bindings (set=3): specular equirect 2D + BRDF LUT + SH UBO
|
|
||||||
layout(set=3, binding=0) uniform sampler2D iblSpec2D;
|
|
||||||
layout(set=3, binding=1) uniform sampler2D iblBRDF;
|
|
||||||
layout(std140, set=3, binding=2) uniform IBL_SH { vec4 sh[9]; } iblSH;
|
|
||||||
|
|
||||||
vec3 sh_eval_irradiance(vec3 n)
|
|
||||||
{
|
|
||||||
float x=n.x, y=n.y, z=n.z;
|
|
||||||
const float c0=0.2820947918; const float c1=0.4886025119; const float c2=1.0925484306; const float c3=0.3153915653; const float c4=0.5462742153;
|
|
||||||
float Y[9];
|
|
||||||
Y[0]=c0; Y[1]=c1*y; Y[2]=c1*z; Y[3]=c1*x; Y[4]=c2*x*y; Y[5]=c2*y*z; Y[6]=c3*(3.0*z*z-1.0); Y[7]=c2*x*z; Y[8]=c4*(x*x-y*y);
|
|
||||||
vec3 r=vec3(0.0); for (int i=0;i<9;++i) r += iblSH.sh[i].rgb * Y[i]; return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 dir_to_equirect(vec3 d)
|
|
||||||
{
|
|
||||||
d = normalize(d);
|
|
||||||
float phi = atan(d.z, d.x);
|
|
||||||
float theta = acos(clamp(d.y, -1.0, 1.0));
|
|
||||||
return vec2(phi * (0.15915494309) + 0.5, theta * (0.31830988618));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
{
|
{
|
||||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
@@ -118,7 +97,7 @@ void main()
|
|||||||
// IBL: specular from equirect 2D mips; diffuse from SH
|
// IBL: specular from equirect 2D mips; diffuse from SH
|
||||||
vec3 R = reflect(-V, N);
|
vec3 R = reflect(-V, N);
|
||||||
float levels = float(textureQueryLevels(iblSpec2D));
|
float levels = float(textureQueryLevels(iblSpec2D));
|
||||||
float lod = clamp(roughness * max(levels - 1.0, 0.0), 0.0, max(levels - 1.0, 0.0));
|
float lod = ibl_lod_from_roughness(roughness, levels);
|
||||||
vec2 uv = dir_to_equirect(R);
|
vec2 uv = dir_to_equirect(R);
|
||||||
vec3 prefiltered = textureLod(iblSpec2D, uv, lod).rgb;
|
vec3 prefiltered = textureLod(iblSpec2D, uv, lod).rgb;
|
||||||
vec2 brdf = texture(iblBRDF, vec2(max(dot(N, V), 0.0), roughness)).rg;
|
vec2 brdf = texture(iblBRDF, vec2(max(dot(N, V), 0.0), roughness)).rg;
|
||||||
|
|||||||
Reference in New Issue
Block a user