forked from vixorien/AdvancedDX11Starter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPixelShader.hlsl
139 lines (109 loc) · 4.19 KB
/
PixelShader.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
138
139
#include "Lighting.hlsli"
// How many lights could we handle?
#define MAX_LIGHTS 128
// Data that can change per material
cbuffer perMaterial : register(b0)
{
// Surface color
float4 Color;
// Material information
float Shininess;
};
// Data that only changes once per frame
cbuffer perFrame : register(b1)
{
// An array of light data
Light Lights[MAX_LIGHTS];
// The amount of lights THIS FRAME
int LightCount;
// Needed for specular (reflection) calculation
float3 CameraPosition;
//Ambient Color for Environment
float3 AmbientNonPBR;
};
// 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
float4 posForShadow : SHADOWPOS;
};
//Output
struct PS_Output
{
float4 color : SV_TARGET0;
float4 normals : SV_TARGET1;
float4 ambient : SV_TARGET2;
float4 depth : SV_TARGET3;
};
// Texture-related variables
Texture2D AlbedoTexture : register(t0);
Texture2D NormalTexture : register(t1);
Texture2D RoughnessTexture : register(t2);
Texture2D ShadowMap : register(t3);
SamplerState BasicSampler : register(s0);
SamplerComparisonState ShadowSampler : register(s2);
// Entry point for this pixel shader
PS_Output main(VertexToPixel input) : SV_TARGET
{
// Always re-normalize interpolated direction vectors
input.normal = normalize(input.normal);
input.tangent = normalize(input.tangent);
// Normal mapping
input.normal = NormalMapping(NormalTexture, BasicSampler, input.uv, input.normal, input.tangent);
// Treating roughness as a pseduo-spec map here, so applying it as
// a modifier to the overall shininess value of the material
float roughness = RoughnessTexture.Sample(BasicSampler, input.uv).r;
float specPower = max(Shininess * (1.0f - roughness), 0.01f); // Ensure we never hit 0
// 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;
// SHADOW MAPPING --------------------------------
// Note: This is only for a SINGLE light! If you want multiple lights to cast shadows,
// you need to do all of this multiple times IN THIS SHADER.
float2 shadowUV = input.posForShadow.xy / input.posForShadow.w * 0.5f + 0.5f;
shadowUV.y = 1.0f - shadowUV.y;
// Calculate this pixel's depth from the light
float depthFromLight = input.posForShadow.z / input.posForShadow.w;
// Sample the shadow map using a comparison sampler, which
// will compare the depth from the light and the value in the shadow map
// Note: This is applied below, after we calc our DIRECTIONAL LIGHT
float shadowAmount = ShadowMap.SampleCmpLevelZero(ShadowSampler, shadowUV, depthFromLight);
// 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:
float3 dirLightResult = DirLight(Lights[i], input.normal, input.worldPos, CameraPosition, specPower, surfaceColor.rgb);
// Apply the directional light result, scaled by the shadow mapping
// Note: This demo really only has one shadow map, so this
// will only be correct for THE FIRST DIRECTIONAL LIGHT
totalColor += dirLightResult * (Lights[i].CastsShadows ? shadowAmount : 1.0f);
break;
case LIGHT_TYPE_POINT:
totalColor += PointLight(Lights[i], input.normal, input.worldPos, CameraPosition, specPower, surfaceColor.rgb);
break;
case LIGHT_TYPE_SPOT:
totalColor += SpotLight(Lights[i], input.normal, input.worldPos, CameraPosition, specPower, surfaceColor.rgb);
break;
}
}
// Handle ambient
float3 ambient = surfaceColor.rgb * AmbientNonPBR;
PS_Output output;
// Gamma correction
//output.color = float4(pow(totalColor, 1.0f / 2.2f), 1);
output.color = float4(totalColor, 1);
output.ambient = float4(ambient, 1);
output.normals = float4(input.normal * 0.5f + 0.5f, 1);
output.depth = input.screenPosition.z;
return output;
}