/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Data/Base/Shaders/Common/BRDF.h
164 строки
5 KB
Sanakan8472
Area Lights (#1908)
20 апр 2026, 20:27
Не верифицирован
20 апр 2026, 20:27
bdf6e41
Код
Авторство
О чём код?
#pragma once #include <Shaders/Materials/MaterialData.h> // TODO: // check roughness^2 vs. roughness^4 // try different visibility function (SmithGGXCorrelated) struct AccumulatedLight { float3 diffuseLight; float3 specularLight; }; AccumulatedLight InitializeLight(float3 diff, float3 spec) { AccumulatedLight result; result.diffuseLight = diff; result.specularLight = spec; return result; } void AccumulateLight(inout AccumulatedLight result, AccumulatedLight light) { result.diffuseLight += light.diffuseLight; result.specularLight += light.specularLight; } void AccumulateLight(inout AccumulatedLight result, AccumulatedLight light, float3 color) { result.diffuseLight += light.diffuseLight * color; result.specularLight += light.specularLight * color; } void AccumulateLight(inout AccumulatedLight result, AccumulatedLight light, float3 color, float specularMultiplier) { result.diffuseLight += light.diffuseLight * color; result.specularLight += (light.specularLight * color) * specularMultiplier; } /////////////////////////////////////////////////////////////////////////////////// float RoughnessFromMipLevel(uint mipLevel, uint mipCount) { return pow(mipLevel / (float)(mipCount - 1), 2.0f); } float MipLevelFromRoughness(float roughness, uint mipCount) { return (mipCount - 1) * sqrt(roughness); } float RoughnessFromPerceptualRoughness(float perceptualRoughness) { return perceptualRoughness * perceptualRoughness; } float PerceptualRoughnessFromRoughness(float roughness) { return sqrt(roughness); } float3 DiffuseLambert(float3 diffuseColor) { return diffuseColor; } // divide by PI postponed float SpecularGGX(float roughness, float NdotH) { // mad friendly reformulation of: // // a^2 // -------------------------------- // PI * ((N.H)^2 * (a^2 - 1) + 1)^2 float a2 = roughness * roughness; float f = (NdotH * a2 - NdotH) * NdotH + 1.0f; return a2 / (f * f); } float VisibilitySmithCorrelated(float roughness, float NdotV, float NdotL) { float a2 = roughness * roughness; float lambdaV = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2); float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2); return 0.5f / (lambdaV + lambdaL); } float VisibilitySmithJointApprox(float roughness, float NdotV, float NdotL) { float a = roughness; float b = 1.0f - a; float lambdaV = NdotL * (NdotV * b + a); float lambdaL = NdotV * (NdotL * b + a); return 0.5f / (lambdaV + lambdaL); } float3 FresnelSchlick(float3 specularColor, float VdotH) { float f = 1.0f - VdotH; float ff = f * f; float f5 = ff * ff * f; // specularColor below 2% is considered to be shadowing return saturate(50.0 * GetLuminance(specularColor)) * f5 + (1 - f5) * specularColor; } // note that 1/PI is applied later AccumulatedLight DefaultShading(ezMaterialData matData, float3 lightDiffuseVector, float3 lightSpecVector, float3 V, float roughness) { float3 N = matData.worldNormal; float3 H = normalize(V + lightSpecVector); float NdotLSpec = saturate(dot(N, lightSpecVector)); float NdotL = saturate(dot(N, lightDiffuseVector)); float NdotV = max(dot(N, V), 1e-5f); float NdotH = saturate(dot(N, H)); float VdotH = saturate(dot(V, H)); // Cook-Torrance microfacet BRDF // // D * G * F G // ------------- = D * Vis * F with Vis = ------------- // 4 * N.L * N.V 4 * N.L * N.V float D = SpecularGGX(roughness, NdotH); float Vis = VisibilitySmithJointApprox(roughness, NdotV, NdotLSpec); float3 F = FresnelSchlick(matData.specularColor, VdotH); float3 diffuse = DiffuseLambert(matData.diffuseColor); return InitializeLight(diffuse * NdotL, F * (D * Vis * NdotLSpec)); } AccumulatedLight SubsurfaceShading(ezMaterialData matData, float3 L, float3 V) { float3 N = matData.worldNormal; float3 H = normalize(V + L); float3 distortedLightDir = L + N * 0.1; float inScatter = pow(saturate(dot(V, -distortedLightDir)), matData.subsurfaceScatterPower); float wrapFactor = 0.5; float wrappedNdotH = saturate((dot(N, H) * wrapFactor + 1 - wrapFactor)) / (PI * 2); return InitializeLight(matData.subsurfaceColor * lerp(wrappedNdotH, 1, inScatter), 0.0); } float3 EnvironmentBRDF(float3 specularColor, float roughness, float NoV) { // [ Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II" ] // Adaptation to fit our G term. const float4 c0 = {-1, -0.0275, -0.572, 0.022}; const float4 c1 = {1, 0.0425, 1.04, -0.04}; float4 r = roughness * c0 + c1; float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; float2 AB = float2(-1.04, 1.04) * a004 + r.zw; // specularColor below 2% is considered to be shadowing float F90 = saturate(50.0 * GetLuminance(specularColor)); return specularColor * AB.x + F90 * AB.y; }