#include "../Common.hlsli" #include "../Normals.hlsli" /// Constants at Constant Buffer View (CBV) register 0 cbuffer RootConstants : register(b0) { /// Render node ID uint ID; } /// Constant buffer at Constant Buffer View (CBV) register 1 cbuffer CameraBuffer : register(b1) { /// Camera view matrix (world space->view space) float4x4 ViewMatrix; /// Camera projection matrix (view space->clip space) float4x4 ProjectionMatrix; /// Padding float4 pad[8]; }; /// Render nodes buffer StructuredBuffer RenderNodes : register(t0); /// Materials buffer (bindless) StructuredBuffer Materials: register(t1); /// Textures buffer (bindless) Texture2D Textures[]: register(t2); /// Anisotropic texture sampler SamplerState AnisoSampler : register(s0); /// Structure holding data passed from vertex shader struct VSOut { /// Clip space position float4 position : SV_POSITION; /// Texture coordinates for maps float2 texCoord : TEXCOORD0; /// View space vertex normals float3 normal : TEXCOORD1; /// View space S-tangent vector float3 tangent : TEXCOORD2; /// View space T-tangent vector float3 bitangent : TEXCOORD3; /// Clip space position passed to fragment shader float4 clipPos : TEXCOORD4; }; /// Vertex shader entry point /// Vertex position (object space) /// Vertex normal /// Vertex texture coordinates /// Vertex S-tangent vector /// Vertex T-tangent vector /// Filled structure VSOut VSOut VS(float3 position : POSITION, float3 normal : NORMAL, float2 texCoord : TEXCOORD0, float3 tangent : TEXCOORD2, float3 bitangent : TEXCOORD3) { VSOut result; // Transform vertex positions into world space float4 positionWS = mul(float4(position, 1.0f), RenderNodes[ID].WorldMatrix); // Transform vertex positions into clip space and set into output result.position = mul(ProjectionMatrix, mul(ViewMatrix, positionWS)); // Set vertex texture coordinates into output result.texCoord = texCoord; // Transform vertex normal into view space normals result.normal = mul(ViewMatrix, float4(mul(float4(normal.xyz, 1.0f), RenderNodes[ID].WorldMatrixInverseTranspose).xyz, 0.0f)).xyz; // Transform S-tangent vector into view space normals result.tangent = mul(ViewMatrix, float4(mul(float4(tangent.xyz, 1.0f), RenderNodes[ID].WorldMatrixInverseTranspose).xyz, 0.0f)).xyz; // Transform T-tangent vector into view space normals result.bitangent = mul(ViewMatrix, float4(mul(float4(bitangent.xyz, 1.0f), RenderNodes[ID].WorldMatrixInverseTranspose).xyz, 0.0f)).xyz; // Calculate depth result.clipPos = result.position; return result; } /// Structure holding data output from pixel shader (i.e. Multiple Render Targets data) struct PSOut { /// Color stored in first render target float4 color : SV_TARGET0; /// Normal - encoded to 2 channels (along with metallic and roughness) stored in second render target float4 normal : SV_TARGET1; /// Depth stored in third render target float depth : SV_TARGET2; }; /// Pixel shader entry point /// VSOut structure holding data passed from vertex shader /// Filled structure PSOut (Multiple Render Targets) PSOut PS(VSOut input) { PSOut result; // Read diffuse texture (based on MaterialID for current render node), and set into color output result.color = pow(Textures[Materials[RenderNodes[ID].MaterialID].DiffuseMap].Sample(AnisoSampler, input.texCoord.xy), 2.2); // Calculate tangent frame for applying normal map to vertex normals float3x3 tangentFrame = float3x3(input.tangent, -input.bitangent, input.normal); // Read normal map texture (based on MaterialID for current render node), apply it to vertex normals (through tangent frame) float3 normal = normalize(mul(Textures[Materials[RenderNodes[ID].MaterialID].NormalsMap].Sample(AnisoSampler, input.texCoord.xy).xyz * 2.0f - 1.0f, tangentFrame)); // Read metallic texture (based on MaterialID for current render node) float metallicMap = Textures[Materials[RenderNodes[ID].MaterialID].MetallicMap].Sample(AnisoSampler, input.texCoord.xy).x; // Read roughness texture (based on MaterialID for current render node) float roughnessMap = Textures[Materials[RenderNodes[ID].MaterialID].RoughnessMap].Sample(AnisoSampler, input.texCoord.xy).x; // Set normal output to contain encoded normal (first 2 channels - see Normals.hlsli for details), metallic (1 channel) and roughness (1 channel) result.normal = float4(EncodeNormal(normal), metallicMap, roughnessMap); // Write depth result.depth = input.clipPos.z / input.clipPos.w; return result; }