forked from vixorien/AdvancedDX11Starter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPixelShaderPBR.hlsl
137 lines (111 loc) · 4.1 KB
/
PixelShaderPBR.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "Lighting.hlsli"
// How many lights could we handle?
#define MAX_LIGHTS 128
// Data that only changes once per frame
cbuffer perFrame : register(b0)
{
// An array of light data
Light Lights[MAX_LIGHTS];
// The amount of lights THIS FRAME
int LightCount;
// Needed for specular (reflection) calculation
float3 CameraPosition;
// mip levels in IBL cube map
int SpecIBLTotalMipLevels;
};
// Data that can change per material
cbuffer perMaterial : register(b1)
{
// Surface color
float4 Color;
};
// Defines the input to this pixel shader
// - Should match the output of our corresponding vertex shader
struct VertexToPixel
{
float4 screenPosition : SV_POSITION;
float2 uv : TEXCOORD;
float3 normal : NORMAL;
float3 tangent : TANGENT;
float3 worldPos : POSITION; // The world position of this PIXEL
};
struct PS_Output
{
float4 color : SV_TARGET0;
float4 normals : SV_TARGET1;
float4 depths : SV_TARGET2;
};
// Texture-related variables
Texture2D AlbedoTexture : register(t0);
Texture2D NormalTexture : register(t1);
Texture2D RoughnessTexture : register(t2);
Texture2D MetalTexture : register(t3);
// IBL (indirect PBR) textures
Texture2D BrdfLookUpMap : register(t4);
TextureCube IrradianceIBLMap : register(t5);
TextureCube SpecularIBLMap : register(t6);
// Samplers
SamplerState BasicSampler : register(s0);
SamplerState ClampSampler : register(s1);
// Entry point for this pixel shader
PS_Output main(VertexToPixel input)
{
// Always re-normalize interpolated direction vectors
input.normal = normalize(input.normal);
input.tangent = normalize(input.tangent);
// Sample various textures
input.normal = NormalMapping(NormalTexture, BasicSampler, input.uv, input.normal, input.tangent);
float roughness = RoughnessTexture.Sample(BasicSampler, input.uv).r;
float metal = MetalTexture.Sample(BasicSampler, input.uv).r;
// Gamma correct the texture back to linear space and apply the color tint
float4 surfaceColor = AlbedoTexture.Sample(BasicSampler, input.uv);
surfaceColor.rgb = pow(surfaceColor.rgb, 2.2) * Color.rgb;
// Specular color - Assuming albedo texture is actually holding specular color if metal == 1
// Note the use of lerp here - metal is generally 0 or 1, but might be in between
// because of linear texture sampling, so we want lerp the specular color to match
float3 specColor = lerp(F0_NON_METAL.rrr, surfaceColor.rgb, metal);
// Total color for this pixel
float3 totalColor = float3(0,0,0);
// Loop through all lights this frame
for(int i = 0; i < LightCount; i++)
{
// Which kind of light?
switch (Lights[i].Type)
{
case LIGHT_TYPE_DIRECTIONAL:
totalColor += DirLightPBR(Lights[i], input.normal, input.worldPos, CameraPosition, roughness, metal, surfaceColor.rgb, specColor);
break;
case LIGHT_TYPE_POINT:
totalColor += PointLightPBR(Lights[i], input.normal, input.worldPos, CameraPosition, roughness, metal, surfaceColor.rgb, specColor);
break;
case LIGHT_TYPE_SPOT:
totalColor += SpotLightPBR(Lights[i], input.normal, input.worldPos, CameraPosition, roughness, metal, surfaceColor.rgb, specColor);
break;
}
}
// Calculate requisite reflection vectors
float3 viewToCam = normalize(CameraPosition - input.worldPos);
float3 viewRefl = normalize(reflect(-viewToCam, input.normal));
float NdotV = saturate(dot(input.normal, viewToCam));
// Indirect lighting
float3 indirectDiffuse = IndirectDiffuse(IrradianceIBLMap, BasicSampler, input.normal);
float3 indirectSpecular = IndirectSpecular(
SpecularIBLMap,
SpecIBLTotalMipLevels,
BrdfLookUpMap,
ClampSampler, // MUST use the clamp sampler here!
viewRefl,
NdotV,
roughness,
specColor);
// Balance indirect diff/spec
float3 balancedDiff = DiffuseEnergyConserve(indirectDiffuse, indirectSpecular, metal);
float3 fullIndirect = indirectSpecular + balancedDiff * surfaceColor.rgb;
// Add the indirect to the direct
totalColor += fullIndirect;
PS_Output output;
output.color = float4(pow(totalColor, 1.0f / 2.2f), 1); // Gamma correction
output.normals = float4(input.normal * 0.5f + 0.5f, 1);
output.depths = input.screenPosition.z;
return output;
}