559 lines
18 KiB
GLSL
559 lines
18 KiB
GLSL
#version 450
|
|
#extension GL_EXT_samplerless_texture_functions : require
|
|
|
|
layout (constant_id = 0) const uint LIGHTS = 256;
|
|
|
|
layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedoMetallic;
|
|
layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormalRoughness;
|
|
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth;
|
|
|
|
layout (binding = 5) uniform sampler3D samplerNoise;
|
|
layout (binding = 6) uniform sampler2D samplerShadows[LIGHTS];
|
|
|
|
layout (location = 0) in vec2 inUv;
|
|
layout (location = 1) in flat uint inPushConstantPass;
|
|
|
|
layout (location = 0) out vec4 outFragColor;
|
|
|
|
/*
|
|
const vec2 poissonDisk[4] = vec2[](
|
|
vec2( -0.94201624, -0.39906216 ),
|
|
vec2( 0.94558609, -0.76890725 ),
|
|
vec2( -0.094184101, -0.92938870 ),
|
|
vec2( 0.34495938, 0.29387760 )
|
|
);
|
|
*/
|
|
vec2 poissonDisk[16] = vec2[](
|
|
vec2( -0.94201624, -0.39906216 ),
|
|
vec2( 0.94558609, -0.76890725 ),
|
|
vec2( -0.094184101, -0.92938870 ),
|
|
vec2( 0.34495938, 0.29387760 ),
|
|
vec2( -0.91588581, 0.45771432 ),
|
|
vec2( -0.81544232, -0.87912464 ),
|
|
vec2( -0.38277543, 0.27676845 ),
|
|
vec2( 0.97484398, 0.75648379 ),
|
|
vec2( 0.44323325, -0.97511554 ),
|
|
vec2( 0.53742981, -0.47373420 ),
|
|
vec2( -0.26496911, -0.41893023 ),
|
|
vec2( 0.79197514, 0.19090188 ),
|
|
vec2( -0.24188840, 0.99706507 ),
|
|
vec2( -0.81409955, 0.91437590 ),
|
|
vec2( 0.19984126, 0.78641367 ),
|
|
vec2( 0.14383161, -0.14100790 )
|
|
);
|
|
|
|
struct Light {
|
|
vec3 position;
|
|
float radius;
|
|
|
|
vec3 color;
|
|
float power;
|
|
|
|
int type;
|
|
float depthBias;
|
|
float padding1;
|
|
float padding2;
|
|
|
|
mat4 view;
|
|
mat4 projection;
|
|
};
|
|
|
|
struct Matrices {
|
|
mat4 view[2];
|
|
mat4 projection[2];
|
|
};
|
|
|
|
struct Space {
|
|
vec3 eye;
|
|
vec3 world;
|
|
} position, normal, view;
|
|
|
|
struct Fog {
|
|
vec3 color;
|
|
float stepScale;
|
|
|
|
vec3 offset;
|
|
float densityScale;
|
|
|
|
float densityThreshold;
|
|
float densityMultiplier;
|
|
float absorbtion;
|
|
float padding1;
|
|
|
|
vec2 range;
|
|
float padding2;
|
|
float padding3;
|
|
};
|
|
|
|
struct Mode {
|
|
uint type;
|
|
uint scalar;
|
|
vec2 padding;
|
|
vec4 parameters;
|
|
};
|
|
|
|
layout (binding = 0) uniform UBO {
|
|
Matrices matrices;
|
|
vec3 ambient;
|
|
float kexp;
|
|
Mode mode;
|
|
Fog fog;
|
|
Light lights[LIGHTS];
|
|
} ubo;
|
|
|
|
void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
|
|
vec3 Ls = vec3(1.0, 1.0, 1.0); // light specular
|
|
vec3 Ld = light.color; // light color
|
|
vec3 La = vec3(1.0, 1.0, 1.0);
|
|
|
|
vec3 Ks = vec3(albedoSpecular.a); // material specular
|
|
vec3 Kd = albedoSpecular.rgb; // material diffuse
|
|
vec3 Ka = vec3(1.0, 1.0, 1.0);
|
|
|
|
float Kexp = ubo.kexp;
|
|
|
|
vec3 V = position.eye;
|
|
vec3 N = normal.eye;
|
|
vec3 L = light.position.xyz - V;
|
|
float dist = length(L);
|
|
// if ( light.radius > 0.001 && light.radius < dist ) return;
|
|
|
|
vec3 D = normalize(L);
|
|
float d_dot = max(dot( D, N ), 0.0);
|
|
|
|
vec3 R = reflect( -D, N );
|
|
vec3 S = normalize(-V);
|
|
float s_factor = pow( max(dot( R, S ), 0.0), Kexp );
|
|
if ( Kexp < 0.0001 ) s_factor = 0;
|
|
|
|
float radiance = light.power / (dist * dist);
|
|
|
|
vec3 Ia = La * Ka;
|
|
vec3 Id = Ld * Kd * d_dot * radiance;
|
|
vec3 Is = Ls * Ks * s_factor * radiance;
|
|
|
|
i += Id + Is;
|
|
}
|
|
|
|
const float PI = 3.14159265359;
|
|
float DistributionGGX(vec3 N, vec3 H, float roughness) {
|
|
float a = roughness*roughness;
|
|
float a2 = a*a;
|
|
float NdotH = max(dot(N, H), 0.0);
|
|
float NdotH2 = NdotH*NdotH;
|
|
|
|
float num = a2;
|
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
|
denom = PI * denom * denom;
|
|
|
|
return num / denom;
|
|
}
|
|
|
|
float GeometrySchlickGGX(float NdotV, float roughness) {
|
|
float r = (roughness + 1.0);
|
|
float k = (r*r) / 8.0;
|
|
|
|
float num = NdotV;
|
|
float denom = NdotV * (1.0 - k) + k;
|
|
|
|
return num / denom;
|
|
}
|
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
|
|
float NdotV = max(dot(N, V), 0.0);
|
|
float NdotL = max(dot(N, L), 0.0);
|
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
|
|
|
return ggx1 * ggx2;
|
|
}
|
|
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
|
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
|
}
|
|
|
|
float random(vec3 seed, int i){
|
|
vec4 seed4 = vec4(seed,i);
|
|
float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
|
|
return fract(sin(dot_product) * 43758.5453);
|
|
}
|
|
|
|
float shadowFactor( Light light, uint shadowMap ) {
|
|
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
|
positionClip.xyz /= positionClip.w;
|
|
|
|
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
|
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
|
|
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0;
|
|
|
|
float factor = 1.0;
|
|
|
|
// spot light
|
|
if ( light.type == -2 || light.type == -3 ) {
|
|
float dist = length( positionClip.xy );
|
|
if ( dist > 0.5 ) return 0.0;
|
|
|
|
// spot light with attenuation
|
|
if ( light.type == -3 ) {
|
|
factor = 1.0 - (pow(dist * 2,2.0));
|
|
}
|
|
}
|
|
|
|
vec2 uv = positionClip.xy * 0.5 + 0.5;
|
|
float bias = light.depthBias;
|
|
if ( !true ) {
|
|
float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1);
|
|
bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01);
|
|
} else if ( true ) {
|
|
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
|
|
}
|
|
|
|
float eyeDepth = positionClip.z;
|
|
int samples = poissonDisk.length();
|
|
if ( samples <= 1 ) {
|
|
return eyeDepth < texture(samplerShadows[shadowMap], uv).r - bias ? 0.0 : factor;
|
|
}
|
|
for ( int i = 0; i < samples; ++i ) {
|
|
// int index = i;
|
|
// int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples;
|
|
int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples;
|
|
float lightDepth = texture(samplerShadows[shadowMap], uv + poissonDisk[index] / 700.0 ).r;
|
|
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
|
|
}
|
|
return factor;
|
|
}
|
|
vec3 hslToRgb(vec3 HSL) {
|
|
vec3 RGB; {
|
|
float H = HSL.x;
|
|
float R = abs(H * 6 - 3) - 1;
|
|
float G = 2 - abs(H * 6 - 2);
|
|
float B = 2 - abs(H * 6 - 4);
|
|
RGB = clamp(vec3(R,G,B), 0, 1);
|
|
}
|
|
float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
|
|
return (RGB - 0.5) * C + HSL.z;
|
|
}
|
|
vec3 rgbToHsl(vec3 RGB) {
|
|
float Epsilon = 1e-10;
|
|
vec3 HCV; {
|
|
vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
|
|
vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
|
|
float C = Q.x - min(Q.w, Q.y);
|
|
float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
|
|
HCV = vec3(H, C, Q.x);
|
|
}
|
|
float L = HCV.z - HCV.y * 0.5;
|
|
float S = HCV.y / (1 - abs(L * 2 - 1) + Epsilon);
|
|
return vec3(HCV.x, S, L);
|
|
}
|
|
|
|
float hueDistance(float h1, float h2) {
|
|
float diff = abs((h1 - h2));
|
|
return min(abs((1.0 - diff)), diff);
|
|
}
|
|
const float lightnessSteps = 4.0;
|
|
float lightnessStep(float l) {
|
|
return floor((0.5 + l * lightnessSteps)) / lightnessSteps;
|
|
}
|
|
const int indexMatrix16x16[256] = int[](0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255,
|
|
128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127,
|
|
32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223,
|
|
160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95,
|
|
8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247,
|
|
136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119,
|
|
40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215,
|
|
168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87,
|
|
2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253,
|
|
130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125,
|
|
34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221,
|
|
162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93,
|
|
10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245,
|
|
138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117,
|
|
42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213,
|
|
170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85);
|
|
float indexValue16x16( float scale ) {
|
|
int x = int(mod(gl_FragCoord.x * scale, 16));
|
|
int y = int(mod(gl_FragCoord.y * scale, 16));
|
|
return indexMatrix16x16[(x + y * 16)] / 256.0;
|
|
}
|
|
const int indexMatrix8x8[64] = int[](0, 32, 8, 40, 2, 34, 10, 42,
|
|
48, 16, 56, 24, 50, 18, 58, 26,
|
|
12, 44, 4, 36, 14, 46, 6, 38,
|
|
60, 28, 52, 20, 62, 30, 54, 22,
|
|
3, 35, 11, 43, 1, 33, 9, 41,
|
|
51, 19, 59, 27, 49, 17, 57, 25,
|
|
15, 47, 7, 39, 13, 45, 5, 37,
|
|
63, 31, 55, 23, 61, 29, 53, 21);
|
|
float indexValue8x8( float scale ) {
|
|
int x = int(mod(gl_FragCoord.x * scale, 8));
|
|
int y = int(mod(gl_FragCoord.y * scale, 8));
|
|
return indexMatrix8x8[(x + y * 8)] / 64.0;
|
|
}
|
|
const int indexMatrix4x4[16] = int[](0, 8, 2, 10,
|
|
12, 4, 14, 6,
|
|
3, 11, 1, 9,
|
|
15, 7, 13, 5);
|
|
float indexValue4x4( float scale ) {
|
|
int x = int(mod(gl_FragCoord.x * scale, 4));
|
|
int y = int(mod(gl_FragCoord.y * scale, 4));
|
|
return indexMatrix4x4[(x + y * 4)] / 16.0;
|
|
}
|
|
vec3[2] closestColors(float hue) {
|
|
vec3 ret[2];
|
|
vec3 closest = vec3(-2, 0, 0);
|
|
vec3 secondClosest = vec3(-2, 0, 0);
|
|
vec3 temp;
|
|
/*
|
|
for (int i = 0; i < palette.length(); ++i) {
|
|
temp = rgbToHsl(palette[i].rgb);
|
|
float tempDistance = hueDistance(temp.x, hue);
|
|
if (tempDistance < hueDistance(closest.x, hue)) {
|
|
secondClosest = closest;
|
|
closest = temp;
|
|
} else {
|
|
if (tempDistance < hueDistance(secondClosest.x, hue)) {
|
|
secondClosest = temp;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
ret[0] = closest;
|
|
ret[1] = secondClosest;
|
|
return ret;
|
|
}
|
|
float dither(float color) {
|
|
float closestColor = (color < 0.5) ? 0 : 1;
|
|
float secondClosestColor = 1 - closestColor;
|
|
float d = 1; // -0.5 - fract(ubo.mode.parameters.w / 8.0);
|
|
if ( ubo.mode.scalar == 16 ) {
|
|
d = indexValue16x16(1);
|
|
} else if ( ubo.mode.scalar == 8 ) {
|
|
d = indexValue8x8(1);
|
|
} else if ( ubo.mode.scalar == 4 ) {
|
|
d = indexValue4x4(1);
|
|
}
|
|
float distance = abs(closestColor - color);
|
|
return (distance < d) ? closestColor : secondClosestColor;
|
|
}
|
|
void dither(inout vec3 color) {
|
|
vec3 hsl = rgbToHsl(color);
|
|
hsl.x = dither(hsl.x);
|
|
color = hslToRgb(hsl);
|
|
}
|
|
void dither1(inout vec3 color) {
|
|
vec3 hsl = rgbToHsl(color);
|
|
|
|
float d = 0;
|
|
vec3 cs[2] = { hsl, hsl }; // closestColors(hsl.x);
|
|
float scale = 1;
|
|
if ( ubo.mode.scalar == 16 ) {
|
|
d = indexValue16x16(scale);
|
|
} else if ( ubo.mode.scalar == 8 ) {
|
|
d = indexValue8x8(scale);
|
|
} else if ( ubo.mode.scalar == 4 ) {
|
|
d = indexValue4x4(scale);
|
|
}
|
|
float hueDiff = hueDistance(hsl.x, cs[0].x) / hueDistance(cs[1].x, cs[0].x);
|
|
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
|
|
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
|
|
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
|
|
|
|
vec3 resultColor = (hueDiff < d) ? cs[0] : cs[1];
|
|
resultColor.z = (lightnessDiff < d) ? l1 : l2;
|
|
color = hslToRgb(resultColor);
|
|
}
|
|
vec3 dither2() {
|
|
vec3 vDither = dot( vec2( 171.0, 231.0 ), inUv.xy + ubo.mode.parameters.w ).xxx;
|
|
vDither.rgb = fract( vDither.rgb / vec3( 103.0, 71.0, 97.0 ) ) - vec3( 0.5, 0.5, 0.5 );
|
|
return ( vDither.rgb / 255.0 ) * 0.375;
|
|
}
|
|
|
|
float rand2(vec2 co){
|
|
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453);
|
|
}
|
|
float rand3(vec3 co){
|
|
return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453);
|
|
}
|
|
void whitenoise(inout vec3 color) {
|
|
float flicker = ubo.mode.parameters.x;
|
|
float pieces = ubo.mode.parameters.y;
|
|
float blend = ubo.mode.parameters.z;
|
|
float time = ubo.mode.parameters.w;
|
|
if ( blend < 0.0001 ) return;
|
|
float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
|
|
// float whiteNoise = rand3( floor(position.world / pieces) + floor(time * 2) );
|
|
float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
|
|
color = mix( color, vec3(whiteNoise), blend );
|
|
}
|
|
|
|
void pbr( Light light, vec3 albedo, float metallic, float roughness, vec3 lightPositionWorld, inout vec3 i ) {
|
|
vec3 F0 = vec3(0.04);
|
|
F0 = mix(F0, albedo, metallic);
|
|
|
|
vec3 N = normalize(normal.eye);
|
|
vec3 L = light.position.xyz - position.eye;
|
|
float dist = length(L);
|
|
// if ( light.radius > 0.001 && light.radius < dist ) return;
|
|
|
|
vec3 D = normalize(L);
|
|
vec3 V = normalize(-position.eye);
|
|
vec3 H = normalize(V + D);
|
|
|
|
float NdotD = max(dot(N, D), 0.0);
|
|
float NdotV = max(dot(N, V), 0.0);
|
|
|
|
vec3 radiance = light.color.rgb * light.power / (dist * dist);
|
|
/*
|
|
if ( light.radius > 0.0001 ) {
|
|
radiance *= clamp( light.radius / (pow(dist, 2.0) + 1.0), 0.0, 1.0 );
|
|
} else if ( false ) {
|
|
radiance /= dist * dist;
|
|
}
|
|
*/
|
|
|
|
// cook-torrance brdf
|
|
float NDF = DistributionGGX(N, H, roughness);
|
|
float G = GeometrySmith(N, V, D, roughness);
|
|
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
|
|
|
|
vec3 kS = F;
|
|
vec3 kD = vec3(1.0) - kS;
|
|
kD *= 1.0 - metallic;
|
|
|
|
vec3 numerator = NDF * G * F;
|
|
float denominator = 4.0 * NdotV * NdotD;
|
|
vec3 specular = numerator / max(denominator, 0.001);
|
|
|
|
// add to outgoing radiance Lo
|
|
i += (kD * albedo / PI + specular) * radiance * NdotD;
|
|
}
|
|
|
|
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir ) {
|
|
vec3 t0 = (boundsMin - rayOrigin) / rayDir;
|
|
vec3 t1 = (boundsMax - rayOrigin) / rayDir;
|
|
vec3 tmin = min(t0, t1);
|
|
vec3 tmax = max(t0, t1);
|
|
float dstA = max( max(tmin.x, tmin.y), tmin.z );
|
|
float dstB = min( tmax.x, min(tmax.y, tmax.z) );
|
|
float dstToBox = max(0, dstA);
|
|
float dstInsideBox = max(0, dstB - dstToBox);
|
|
return vec2(dstToBox, dstInsideBox);
|
|
}
|
|
|
|
float sampleDensity( vec3 position ) {
|
|
vec3 uvw = position * ubo.fog.densityScale * 0.001 + ubo.fog.offset * 0.01;
|
|
return max(0, texture(samplerNoise, uvw).r - ubo.fog.densityThreshold) * ubo.fog.densityMultiplier;
|
|
}
|
|
|
|
void fog( inout vec3 i, float scale ) {
|
|
if ( ubo.fog.stepScale <= 0 ) return;
|
|
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
|
|
|
|
mat4 iProjView = inverse( ubo.matrices.projection[inPushConstantPass] * ubo.matrices.view[inPushConstantPass] );
|
|
vec4 near4 = iProjView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
|
|
vec4 far4 = iProjView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
|
|
vec3 near3 = near4.xyz / near4.w;
|
|
vec3 far3 = far4.xyz / far4.w;
|
|
|
|
vec3 rayOrigin = near3;
|
|
vec3 rayDir = normalize( far3 - near3 );
|
|
|
|
float range = ubo.fog.range.y;
|
|
vec3 boundsMin = vec3(-range,-range,-range) + rayOrigin;
|
|
vec3 boundsMax = vec3(range,range,range) + rayOrigin;
|
|
int numSteps = int(length(boundsMax - boundsMin) * ubo.fog.stepScale );
|
|
|
|
vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayOrigin, rayDir );
|
|
float dstToBox = rayBoxInfo.x;
|
|
float dstInsideBox = rayBoxInfo.y;
|
|
float depth = position.eye.z;
|
|
|
|
float lightEnergy = 0;
|
|
// march
|
|
if ( 0 <= dstInsideBox && dstToBox <= depth ) {
|
|
float dstTravelled = 0;
|
|
float stepSize = dstInsideBox / numSteps;
|
|
float dstLimit = min( depth - dstToBox, dstInsideBox );
|
|
float totalDensity = 0;
|
|
float transmittance = 1;
|
|
while ( dstTravelled < dstLimit ) {
|
|
vec3 rayPos = rayOrigin + rayDir * (dstToBox + dstTravelled);
|
|
float density = sampleDensity(rayPos);
|
|
if ( density > 0 ) {
|
|
transmittance *= exp(-density * stepSize * ubo.fog.absorbtion);
|
|
if ( transmittance < 0.01 ) break;
|
|
}
|
|
dstTravelled += stepSize;
|
|
}
|
|
i.rgb = mix(ubo.fog.color.rgb, i.rgb, transmittance);
|
|
}
|
|
|
|
vec3 color = ubo.fog.color.rgb;
|
|
float inner = ubo.fog.range.x;
|
|
float outer = ubo.fog.range.y * scale;
|
|
float distance = length(-position.eye);
|
|
float factor = (distance - inner) / (outer - inner);
|
|
factor = clamp( factor, 0.0, 1.0 );
|
|
|
|
i.rgb = mix(i.rgb, color, factor);
|
|
}
|
|
|
|
void main() {
|
|
vec4 albedoMetallic = subpassLoad(samplerAlbedoMetallic);
|
|
vec4 normalRoughness = subpassLoad(samplerNormalRoughness);
|
|
// vec4 positionAO = subpassLoad(samplerPositionAO);
|
|
|
|
normal.eye = normalRoughness.rgb;
|
|
{
|
|
mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] );
|
|
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
|
|
float depth = subpassLoad(samplerDepth).r;
|
|
|
|
vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0);
|
|
vec4 positionEye = iProj * positionClip;
|
|
positionEye /= positionEye.w;
|
|
position.eye = positionEye.xyz;
|
|
|
|
vec4 positionWorld = iView * positionEye;
|
|
position.world = positionWorld.xyz;
|
|
}
|
|
|
|
bool usePbr = true;
|
|
bool gammaCorrect = false;
|
|
float litFactor = 1.0;
|
|
float ao = 1; // positionAO.a;
|
|
vec3 fragColor = albedoMetallic.rgb * ubo.ambient.rgb * ao;
|
|
for ( uint i = 0; i < LIGHTS; ++i ) {
|
|
Light light = ubo.lights[i];
|
|
|
|
if ( light.power <= 0.001 ) continue;
|
|
vec3 lightPositionWorld = light.position.xyz;
|
|
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
|
|
if ( light.type < 0 ) {
|
|
float factor = shadowFactor( light, i );
|
|
if ( factor <= 0.0001 ) continue;
|
|
light.power *= factor;
|
|
litFactor += light.power;
|
|
}
|
|
if ( usePbr ) {
|
|
pbr( light, albedoMetallic.rgb, albedoMetallic.a, normalRoughness.a, lightPositionWorld, fragColor );
|
|
} else
|
|
phong( light, albedoMetallic, fragColor );
|
|
}
|
|
|
|
if ( gammaCorrect ) {
|
|
fragColor = fragColor / (fragColor + vec3(1.0));
|
|
fragColor = pow(fragColor, vec3(1.0/2.2));
|
|
}
|
|
|
|
fog(fragColor, litFactor);
|
|
|
|
/*
|
|
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {
|
|
//dither1(fragColor);
|
|
fragColor += dither2();
|
|
}
|
|
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) {
|
|
whitenoise(fragColor);
|
|
}
|
|
*/
|
|
outFragColor = vec4(fragColor,1);
|
|
} |