Init commit

This commit is contained in:
2026-08-17 06:31:43 +09:00
commit 348d9275f6
428 changed files with 61806 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
#ifndef RENDER_IBL_HLSLI
#define RENDER_IBL_HLSLI
// 必须与 IBLResources in ibl_resources.h.的定义顺序相同
TextureCube<float4> gIblIrradianceMap : register(t9);
TextureCube<float4> gIblPrefilteredMap : register(t10);
Texture2D<float4> gIblBrdfLut : register(t11);
SamplerState gIblSampler : register(s3);
cbuffer CBIBL : register(b4) {
// x=intensity, y=prefilter max mip, z=Y rotation in radians, w=enabled
float4 gIblParams;
};
float3 IBL_RotateAroundY(float3 direction, float radians){
float sineValue;
float cosineValue;
sincos(radians, sineValue, cosineValue);
return float3( cosineValue * direction.x + sineValue * direction.z,
direction.y,
-sineValue * direction.x + cosineValue * direction.z);
}
float3 IBL_FresnelSchlickRoughness(float cosTheta, float3 f0, float roughness)
{
const float oneMinusRoughness = 1.0f - roughness;
const float3 grazing = max(float3(oneMinusRoughness, oneMinusRoughness,
oneMinusRoughness), f0);
const float factor = pow(1.0f - saturate(cosTheta), 5.0f);
return f0 + (grazing - f0) * factor;
}
// V 点从表面到相机。 N 是世界空间着色法线。返回的值是线性 HDR 辐射度,必须在色调映射之前添加。
float3 EvaluateIBL(float3 N, float3 V, float3 baseColor,
float metallic, float roughness, float ambientOcclusion)
{
float3 finalRet = float3(0.0f,0.0f,0.0f);
if (gIblParams.w < 0.5f){
finalRet=float3(0.0f, 0.0f, 0.0f);
} else {
N = normalize(N);
V = normalize(V);
metallic = saturate(metallic);
roughness = clamp(roughness, 0.045f, 1.0f);
ambientOcclusion = saturate(ambientOcclusion);
const float nDotV = saturate(dot(N, V));
const float3 dielectricF0 = float3(0.04f, 0.04f, 0.04f);
const float3 f0 = lerp(dielectricF0, baseColor, metallic);
const float3 F = IBL_FresnelSchlickRoughness(nDotV, f0, roughness);
const float3 kD = (float3(1.0f, 1.0f, 1.0f) - F) * (1.0f - metallic);
const float3 sampleN = IBL_RotateAroundY(N, gIblParams.z);
const float3 irradiance = gIblIrradianceMap.SampleLevel(gIblSampler, sampleN, 0.0f).rgb;
const float3 diffuse = irradiance * baseColor;
const float3 reflection = reflect(-V, N);
const float3 sampleR = IBL_RotateAroundY(reflection, gIblParams.z);
const float lod = roughness * max(gIblParams.y, 0.0f);
const float3 prefiltered = gIblPrefilteredMap.SampleLevel(gIblSampler, sampleR, lod).rgb;
const float2 brdf = gIblBrdfLut.SampleLevel(gIblSampler, float2(nDotV, roughness), 0.0f).rg;
const float3 specular = prefiltered * (F * brdf.x + brdf.y);
finalRet = (kD * diffuse + specular) * ambientOcclusion * gIblParams.x;
}
return finalRet;
}
#endif // RENDER_IBL_HLSLI
+64
View File
@@ -0,0 +1,64 @@
#ifndef PBR_BRDF_HLSLI
#define PBR_BRDF_HLSLI
// [PBR-ADD: NEW FILE]
static const float PBR_PI = 3.14159265359f;
static const float PBR_EPSILON = 1.0e-5f;
float3 SafeNormalize(float3 value, float3 fallbackValue) {
const float lengthSquared = dot(value, value);
return lengthSquared > PBR_EPSILON ?
value * rsqrt(lengthSquared) : fallbackValue;
}
float3 BuildFallbackTangent(float3 normal) {
const float3 referenceAxis = abs(normal.y) < 0.999f ?
float3(0.0f, 1.0f, 0.0f) : float3(1.0f, 0.0f, 0.0f);
return SafeNormalize(cross(referenceAxis, normal), float3(1.0f, 0.0f, 0.0f));
}
float3 FresnelSchlick(float cosTheta, float3 f0) {
const float x = 1.0f - saturate(cosTheta);
const float x2 = x * x;
const float x5 = x2 * x2 * x;
return f0 + (1.0f - f0) * x5;
}
float DistributionGGX(float3 n, float3 h, float roughness) {
const float alpha = roughness * roughness;
const float alpha2 = alpha * alpha;
const float nDotH = saturate(dot(n, h));
const float nDotH2 = nDotH * nDotH;
const float denominator = nDotH2 * (alpha2 - 1.0f) + 1.0f;
return alpha2 / max(PBR_PI * denominator * denominator, PBR_EPSILON);
}
float GeometrySchlickGGX(float nDotX, float roughness) {
// UE4 常用的直接光 Schlick-GGX k。
const float r = roughness + 1.0f;
const float k = (r * r) / 8.0f;
return nDotX / max(nDotX * (1.0f - k) + k, PBR_EPSILON);
}
float GeometrySmith(float3 n, float3 v, float3 l, float roughness) {
const float nDotV = saturate(dot(n, v));
const float nDotL = saturate(dot(n, l));
return GeometrySchlickGGX(nDotV, roughness) * GeometrySchlickGGX(nDotL, roughness);
}
float3 DecodeNormalMap(float3 encodedNormal, float normalScale) {
float3 normalTS = encodedNormal * 2.0f - 1.0f;
normalTS.xy *= normalScale;
return normalize(normalTS);
}
float3 ToneMapACES(float3 color) {
const float a = 2.51f;
const float b = 0.03f;
const float c = 2.43f;
const float d = 0.59f;
const float e = 0.14f;
return saturate((color * (a * color + b)) / max(color * (c * color + d) + e, PBR_EPSILON));
}
#endif // PBR_BRDF_HLSLI
@@ -0,0 +1,26 @@
#ifndef INCLUDE_SHADOW_COMMON
#define INCLUDE_SHADOW_COMMON
cbuffer CBScene : register(b0)
{
row_major float4x4 cbView;
row_major float4x4 cbProj;
float4 cbCameraPos;
float4 cbMainLightDirection;
float4 cbCameraColor;
}
cbuffer CBPerObj : register(b2) {
row_major float4x4 cbWorld;
};
cbuffer CBShadow : register(b3) {
row_major float4x4 cbLightViewProjection;
// xy:阴影贴图 texel UV 尺寸
// z :最小深度偏移 w :斜率深度偏移
float4 cbShadowParams;
};
#endif //INCLUDE_SHADOW_COMMON
@@ -0,0 +1,58 @@
#ifndef INCLUDE_SHADOW_MAINLIT
#define INCLUDE_SHADOW_MAINLIT
#include "include/shadow_common.hlsli"
Texture2D<float> gShadowMap : register(t8);
SamplerComparisonState gShadowSampler : register(s2);
float CalculateMainLightShadow(float4 shadowPosition,float3 worldNormal)
{
// 默认完全受光。
float shadowVisibility = 1.0f;
// 只处理位于光源相机前方的像素。
if (shadowPosition.w > 0.0f)
{
float3 projected = shadowPosition.xyz / shadowPosition.w;
float2 shadowUV = projected.xy * float2(0.5f, -0.5f) + 0.5f;
float currentDepth = projected.z;
bool insideShadowMap = all(shadowUV >= 0.0f) && all(shadowUV <= 1.0f) &&
currentDepth > 0.0f && currentDepth < 1.0f;
if (insideShadowMap)
{
// cbMainLightDirection 是光线传播方向,
// 因此表面指向光源的方向需要取反。
float3 lightToSurface = normalize(-cbMainLightDirection.xyz);
float normalDotLight = saturate(dot(normalize(worldNormal), lightToSurface));
float bias = max(cbShadowParams.z, cbShadowParams.w * (1.0f - normalDotLight));
float shadowSum = 0.0f;
[unroll] for (int y = -1; y <= 1; ++y)
{
[unroll] for (int x = -1; x <= 1; ++x)
{
float2 offset = float2((float)x, (float)y) * cbShadowParams.xy;
shadowSum += gShadowMap.SampleCmpLevelZero(gShadowSampler,
shadowUV + offset,
currentDepth - bias);
}
}
shadowVisibility = shadowSum / 9.0f;
}
}
return shadowVisibility;
}
#endif //INCLUDE_SHADOW_MAINLIT