forked from LeenkxTeam/LNXSDK
Okay, so we're re-doing the render pipeline...!
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
#include "std/math.glsl"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform samplerCube probeTex;
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0; // Normal, roughness
|
||||
@ -27,95 +28,106 @@ float depth;
|
||||
const int numBinarySearchSteps = 7;
|
||||
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
||||
|
||||
// Project a view-space hit coordinate into screen UVs
|
||||
vec2 getProjectedCoord(const vec3 hit) {
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
||||
#endif
|
||||
return projectedCoord.xy;
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
||||
#endif
|
||||
return projectedCoord.xy;
|
||||
}
|
||||
|
||||
// Compute depth difference between current ray hit and gbuffer depth
|
||||
float getDeltaDepth(const vec3 hit) {
|
||||
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
}
|
||||
|
||||
// Refine hit using binary search
|
||||
vec4 binarySearch(vec3 dir) {
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
}
|
||||
// Ugly discard of hits too far away
|
||||
#ifdef _CPostprocess
|
||||
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
|
||||
#else
|
||||
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
|
||||
#endif
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
}
|
||||
#ifdef _CPostprocess
|
||||
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
|
||||
#else
|
||||
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
|
||||
#endif
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Perform raymarching using view-space direction
|
||||
vec4 rayCast(vec3 dir) {
|
||||
#ifdef _CPostprocess
|
||||
dir *= PPComp9.x;
|
||||
#else
|
||||
dir *= ssrRayStep;
|
||||
#endif
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
||||
}
|
||||
return vec4(0.0);
|
||||
#ifdef _CPostprocess
|
||||
dir *= PPComp9.x;
|
||||
#else
|
||||
dir *= ssrRayStep;
|
||||
#endif
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
||||
}
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
if (roughness >= 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
// Decode octahedral normal
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
vec3 viewNormal = normalize(V3 * n);
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 reflected = reflect(viewPos, viewNormal);
|
||||
hitCoord = viewPos;
|
||||
// View-space position and reflection
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 viewDir = normalize(viewPos);
|
||||
vec3 reflected = normalize(reflect(viewDir, viewNormal));
|
||||
|
||||
#ifdef _CPostprocess
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
|
||||
#else
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
|
||||
#endif
|
||||
hitCoord = viewPos;
|
||||
|
||||
// * max(ssrMinRayStep, -viewPos.z)
|
||||
vec4 coords = rayCast(dir);
|
||||
// Importance sampling jitter based on roughness
|
||||
float jitterStrength = roughness * roughness;
|
||||
vec3 randVec = normalize(vec3(rand(texCoord), rand(texCoord * 1.3), rand(texCoord * 2.7)) * 2.0 - 1.0);
|
||||
vec3 dir = normalize(mix(reflected, randVec, jitterStrength));
|
||||
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
vec4 coords = rayCast(dir);
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
|
||||
float reflectivity = 1.0 - roughness;
|
||||
#ifdef _CPostprocess
|
||||
float intensity = pow(reflectivity, PPComp10.x) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((PPComp9.z - length(viewPos - hitCoord)) * (1.0 / PPComp9.z), 0.0, 1.0) * coords.w;
|
||||
#else
|
||||
float intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0) * coords.w;
|
||||
#endif
|
||||
float reflectivity = 1.0 - roughness;
|
||||
#ifdef _CPostprocess
|
||||
float distAtten = clamp((PPComp9.z - length(viewPos - hitCoord)) / PPComp9.z, 0.0, 1.0);
|
||||
float intensity = pow(reflectivity, PPComp10.x) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * distAtten * coords.w;
|
||||
#else
|
||||
float distAtten = clamp((ssrSearchDist - length(viewPos - hitCoord)) / ssrSearchDist, 0.0, 1.0);
|
||||
float intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * distAtten * coords.w;
|
||||
#endif
|
||||
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
|
||||
reflCol = clamp(reflCol, 0.0, 1.0);
|
||||
fragColor.rgb = reflCol * intensity * 0.5;
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
vec3 ssrColor = textureLod(tex, coords.xy, roughness * 4.0).rgb;
|
||||
ssrColor = clamp(ssrColor, 0.0, 1.0);
|
||||
|
||||
// Cubemap fallback with roughness-aware LOD sampling
|
||||
vec3 cubemapColor = textureLod(probeTex, reflected, roughness * 6.0).rgb;
|
||||
|
||||
// Additively blend SSR with cubemap fallback
|
||||
fragColor.rgb = mix(cubemapColor, ssrColor, intensity) * spec;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
#ifndef _BRDF_GLSL_
|
||||
#define _BRDF_GLSL_
|
||||
|
||||
// http://xlgames-inc.github.io/posts/improvedibl/
|
||||
// http://blog.selfshadow.com/publications/s2013-shading-course/
|
||||
// Constants
|
||||
//const float PI = 3.1415926535;
|
||||
|
||||
// Fresnel-Schlick with optimized exponential approximation
|
||||
vec3 f_schlick(const vec3 f0, const float vh) {
|
||||
return f0 + (1.0 - f0) * exp2((-5.55473 * vh - 6.98316) * vh);
|
||||
}
|
||||
@ -11,82 +13,11 @@ float v_smithschlick(const float nl, const float nv, const float a) {
|
||||
return 1.0 / ((nl * (1.0 - a) + a) * (nv * (1.0 - a) + a));
|
||||
}
|
||||
|
||||
//Uncorrelated masking/shadowing (info below) function
|
||||
//Because it is uncorrelated, G1(NdotL, a) gives us shadowing, and G1(NdotV, a) gives us masking function.
|
||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
||||
float g1_approx(const float NdotX, const float alpha)
|
||||
{
|
||||
return (2.0 * NdotX) * (1.0 / (NdotX * (2.0 - alpha) + alpha));
|
||||
}
|
||||
|
||||
//Uncorrelated masking-shadowing function
|
||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
||||
float g2_approx(const float NdotL, const float NdotV, const float alpha)
|
||||
{
|
||||
vec2 helper = (2.0 * vec2(NdotL, NdotV)) * (1.0 / (vec2(NdotL, NdotV) * (2.0 - alpha) + alpha));
|
||||
return max(helper.x * helper.y, 0.0); //This can go negative, let's fix that
|
||||
}
|
||||
|
||||
float d_ggx(const float nh, const float a) {
|
||||
float a2 = a * a;
|
||||
float denom = nh * nh * (a2 - 1.0) + 1.0;
|
||||
denom = max(denom * denom, 0.00006103515625 /* 2^-14 = smallest possible half float value, prevent div by zero */);
|
||||
return a2 * (1.0 / 3.1415926535) / denom;
|
||||
}
|
||||
|
||||
vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const float nh, const float nv, const float vh) {
|
||||
float a = roughness * roughness;
|
||||
return d_ggx(nh, a) * g2_approx(nl, nv, a) * f_schlick(f0, vh) / max(4.0 * nv, 1e-5); //NdotL cancels out later
|
||||
}
|
||||
|
||||
// John Hable - Optimizing GGX Shaders
|
||||
// http://filmicworlds.com/blog/optimizing-ggx-shaders-with-dotlh/
|
||||
vec3 specularBRDFb(const vec3 f0, const float roughness, const float dotNL, const float dotNH, const float dotLH) {
|
||||
// D
|
||||
const float pi = 3.1415926535;
|
||||
float alpha = roughness * roughness;
|
||||
float alphaSqr = alpha * alpha;
|
||||
float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
|
||||
float D = alphaSqr / (pi * denom * denom);
|
||||
// F
|
||||
const float F_a = 1.0;
|
||||
float F_b = pow(1.0 - dotLH, 5.0);
|
||||
// V
|
||||
float vis;
|
||||
float k = alpha / 2.0;
|
||||
float k2 = k * k;
|
||||
float invK2 = 1.0 - k2;
|
||||
vis = 1.0 / (dotLH * dotLH * invK2 + k2);
|
||||
vec2 FV_helper = vec2((F_a - F_b) * vis, F_b * vis);
|
||||
|
||||
vec3 FV = f0 * FV_helper.x + FV_helper.y;
|
||||
vec3 specular = clamp(dotNL, 0.0, 1.0) * D * FV;
|
||||
return specular / 4.0; // TODO: get rid of / 4.0
|
||||
}
|
||||
|
||||
vec3 orenNayarDiffuseBRDF(const vec3 albedo, const float roughness, const float nv, const float nl, const float vh) {
|
||||
float a = roughness * roughness;
|
||||
float s = a;
|
||||
float s2 = s * s;
|
||||
float vl = 2.0 * vh * vh - 1.0; // Double angle identity
|
||||
float Cosri = vl - nv * nl;
|
||||
float C1 = 1.0 - 0.5 * s2 / (s2 + 0.33);
|
||||
float test = 1.0;
|
||||
if (Cosri >= 0.0) test = (1.0 / (max(nl, nv)));
|
||||
float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * test;
|
||||
return albedo * max(0.0, nl) * (C1 + C2) * (1.0 + roughness * 0.5);
|
||||
}
|
||||
|
||||
vec3 lambertDiffuseBRDF(const vec3 albedo, const float nl) {
|
||||
return albedo * nl;
|
||||
}
|
||||
|
||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||
return mix(baseColor, vec3(0.0), metalness);
|
||||
}
|
||||
|
||||
vec3 surfaceF0(const vec3 baseColor, const float metalness) {
|
||||
return mix(vec3(0.04), baseColor, metalness);
|
||||
denom = max(denom * denom, 2e-6);
|
||||
return a2 / (PI * denom);
|
||||
}
|
||||
|
||||
float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
||||
@ -94,47 +25,64 @@ float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
||||
return roughness * numMipmaps;
|
||||
}
|
||||
|
||||
float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 fiberDirection, float shinyParallel, float shinyPerpendicular) {
|
||||
if(dotNL < 0.0 || dotNV < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
// fiberDirection - parse from rotation
|
||||
// shinyParallel - roughness
|
||||
// shinyPerpendicular - anisotropy
|
||||
vec3 specularBRDF(vec3 N, vec3 V, vec3 L, vec3 F0, float roughness)
|
||||
{
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
vec3 fiberParallel = normalize(fiberDirection);
|
||||
vec3 fiberPerpendicular = normalize(cross(N, fiberDirection));
|
||||
float dotXH = dot(fiberParallel, H);
|
||||
float dotYH = dot(fiberPerpendicular, H);
|
||||
const float PI = 3.1415926535;
|
||||
float coeff = sqrt(dotNL/dotNV) / (4.0 * PI * shinyParallel * shinyPerpendicular);
|
||||
float theta = (pow(dotXH/shinyParallel, 2.0) + pow(dotYH/shinyPerpendicular, 2.0)) / (1.0 + dotNH);
|
||||
return clamp(coeff * exp(-2.0 * theta), 0.0, 1.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float VdotH = max(dot(V, H), 0.0);
|
||||
|
||||
float alpha = roughness * roughness;
|
||||
|
||||
float D = d_ggx(NdotH, alpha);
|
||||
float k = alpha / 2.0;
|
||||
float G_V = NdotV / (NdotV * (1.0 - k) + k + 1e-5);
|
||||
float G_L = NdotL / (NdotL * (1.0 - k) + k + 1e-5);
|
||||
float G = G_V * G_L;
|
||||
|
||||
vec3 F = f_schlick(F0, VdotH);
|
||||
|
||||
return F * D * G / max(4.0 * NdotL * NdotV, 1e-5);
|
||||
}
|
||||
|
||||
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
|
||||
// vec3 EnvBRDFApprox(vec3 SpecularColor, float Roughness, float NoV) {
|
||||
// const vec4 c0 = { -1, -0.0275, -0.572, 0.022 };
|
||||
// const vec4 c1 = { 1, 0.0425, 1.04, -0.04 };
|
||||
// vec4 r = Roughness * c0 + c1;
|
||||
// float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
||||
// vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
|
||||
// return SpecularColor * AB.x + AB.y;
|
||||
// }
|
||||
// float EnvBRDFApproxNonmetal(float Roughness, float NoV) {
|
||||
// // Same as EnvBRDFApprox( 0.04, Roughness, NoV )
|
||||
// const vec2 c0 = { -1, -0.0275 };
|
||||
// const vec2 c1 = { 1, 0.0425 };
|
||||
// vec2 r = Roughness * c0 + c1;
|
||||
// return min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
||||
// }
|
||||
float D_Approx(const float Roughness, const float RoL) {
|
||||
float a = Roughness * Roughness;
|
||||
float a2 = a * a;
|
||||
float rcp_a2 = 1.0 / a2;//rcp(a2);
|
||||
// 0.5 / ln(2), 0.275 / ln(2)
|
||||
float c = 0.72134752 * rcp_a2 + 0.39674113;
|
||||
return rcp_a2 * exp2( c * RoL - c );
|
||||
vec3 burleyDiffuseBRDF(vec3 N, vec3 V, vec3 L, vec3 albedo, float roughness)
|
||||
{
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float LdotH = max(dot(L, normalize(L + V)), 0.0);
|
||||
|
||||
float FD90 = 0.5 + 2.0 * LdotH * LdotH * roughness;
|
||||
float FL = pow(1.0 - NdotL, 5.0);
|
||||
float FV = pow(1.0 - NdotV, 5.0);
|
||||
|
||||
float diffuse = (1.0 + (FD90 - 1.0) * FL) * (1.0 + (FD90 - 1.0) * FV);
|
||||
return albedo * (1.0 / PI) * diffuse * NdotL;
|
||||
}
|
||||
|
||||
// Energy-conserving material albedo (fades out for metals)
|
||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||
return baseColor * (1.0 - metalness);
|
||||
}
|
||||
|
||||
// Metal-aware F0 blending
|
||||
vec3 surfaceF0(vec3 baseColor, float metalness) {
|
||||
return mix(vec3(0.04), baseColor, metalness);
|
||||
}
|
||||
|
||||
// LUT-based approximation of IBL BRDF (Unreal-style)
|
||||
vec2 EnvBRDFApprox(float Roughness, float NoV) {
|
||||
const vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022);
|
||||
const vec4 c1 = vec4(1, 0.0425, 1.04, -0.04);
|
||||
vec4 r = Roughness * c0 + c1;
|
||||
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
|
||||
return vec2(-1.04, 1.04) * a004 + r.zw;
|
||||
}
|
||||
|
||||
vec3 IBLSpecularApprox(vec3 specColor, float roughness, float NoV) {
|
||||
vec2 brdf = EnvBRDFApprox(roughness, NoV);
|
||||
return specColor * brdf.x + brdf.y;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,12 +15,10 @@ vec3 getNor(const vec2 enc) {
|
||||
|
||||
vec3 getPosView(const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
float linearDepth = cameraProj.y / (cameraProj.x - depth);
|
||||
//float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
return viewRay * linearDepth;
|
||||
}
|
||||
|
||||
vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
// eyeLook, viewRay should be normalized
|
||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
float viewZDist = dot(eyeLook, viewRay);
|
||||
vec3 wposition = eye + viewRay * (linearDepth / viewZDist);
|
||||
@ -28,7 +26,6 @@ vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float
|
||||
}
|
||||
|
||||
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
// eyeLook, viewRay should be normalized
|
||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
float viewZDist = dot(eyeLook, viewRay);
|
||||
vec3 wposition = viewRay * (linearDepth / viewZDist);
|
||||
@ -71,6 +68,7 @@ vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, const vec
|
||||
return pos.xyz - eye;
|
||||
}
|
||||
|
||||
// Updated to support separate roughness/metalness storage
|
||||
float packFloat(const float f1, const float f2) {
|
||||
return floor(f1 * 100.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||
}
|
||||
@ -80,7 +78,6 @@ vec2 unpackFloat(const float f) {
|
||||
}
|
||||
|
||||
float packFloat2(const float f1, const float f2) {
|
||||
// Higher f1 = less precise f2
|
||||
return floor(f1 * 255.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||
}
|
||||
|
||||
@ -101,21 +98,16 @@ vec3 decodeRGBM(const vec4 rgbm) {
|
||||
return rgbm.rgb * rgbm.a * maxRange;
|
||||
}
|
||||
|
||||
vec2 signNotZero(vec2 v)
|
||||
{
|
||||
vec2 signNotZero(vec2 v) {
|
||||
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||
}
|
||||
|
||||
vec2 encode_oct(vec3 v)
|
||||
{
|
||||
// Project the sphere onto the octahedron, and then onto the xy plane
|
||||
vec2 encode_oct(vec3 v) {
|
||||
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
|
||||
// Reflect the folds of the lower hemisphere over the diagonals
|
||||
return (v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p;
|
||||
}
|
||||
|
||||
vec3 decode_oct(vec2 e)
|
||||
{
|
||||
vec3 decode_oct(vec2 e) {
|
||||
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||
if (v.z < 0) v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
|
||||
return normalize(v);
|
||||
@ -147,9 +139,6 @@ vec3 decNor(uint val) {
|
||||
return normal;
|
||||
}
|
||||
|
||||
/**
|
||||
Packs a float in [0, 1] and an integer in [0..15] into a single 16 bit float value.
|
||||
**/
|
||||
float packFloatInt16(const float f, const uint i) {
|
||||
const uint numBitFloat = 12;
|
||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||
@ -165,7 +154,6 @@ void unpackFloatInt16(const float val, out float f, out uint i) {
|
||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||
|
||||
const uint bitsValue = uint(val);
|
||||
|
||||
i = bitsValue >> numBitFloat;
|
||||
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
|
||||
}
|
||||
|
@ -130,8 +130,10 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
vec3 F0 = surfaceF0(albedo, spec); // spec used as the metalness value
|
||||
|
||||
vec3 direct = burleyDiffuseBRDF(n, v, l, albedo, rough) * (1.0 - spec) +
|
||||
specularBRDF(n, v, l, f0, rough) * spec;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
|
Reference in New Issue
Block a user