cbuffer ConstantBuffer { float4x4 completeTransformation; float4x4 worldTransformation; float4 cameraPosition; float4 lightVector; // the light's vector float4 lightColor; // the light's color float4 ambientColor; // the ambient light's color float4 diffuseCoefficient; // The diffuse reflection cooefficient float4 specularCoefficient; // The specular reflection cooefficient float shininess; // The shininess factor float opacity; // The opacity (transparency) of the material. 0 = fully transparent, 1 = fully opaque float waterHeight; float waterShininess; float4 waterColor; float padding[4]; } Texture2D BlendMap : register(t0); Texture2DArray TexturesArray : register(t1); Texture2D WaterNormalMap : register(t2); Texture2D rngNoiseMap : register(t3); SamplerState ss { Filter = MIN_MAG_MIP_LINEAR; AddressU = WRAP; AddressV = WRAP; }; struct VertexShaderInput { float3 Position : POSITION; float3 Normal : NORMAL; float2 TexCoord : TEXCOORD0; float2 BlendMapTexCoord : TEXCOORD1; }; struct PixelShaderInput { float4 Position : SV_POSITION; float4 PositionWS: TEXCOORD2; float4 NormalWS : TEXCOORD3; float2 TexCoord : TEXCOORD0; float2 BlendMapTexCoord : TEXCOORD1; }; float2 UVRotate(float2 uvCoord, float2 pivotPoint, float rotation) { float2x2 rotateMatrix = float2x2(float2(sin(rotation), -cos(rotation)), float2(cos(rotation), sin(rotation))); uvCoord -= pivotPoint; uvCoord = mul(uvCoord, rotateMatrix); uvCoord += pivotPoint; return uvCoord; } PixelShaderInput VShader(VertexShaderInput vin) { PixelShaderInput output; float3 position = vin.Position; if (position.y < waterHeight) { position.y = waterHeight - 0.01f; } output.Position = mul(completeTransformation, float4(position, 1.0f)); output.PositionWS = mul(worldTransformation, float4(position, 1.0f)); output.NormalWS = float4(mul((float3x3)worldTransformation, vin.Normal), 1.0f); output.TexCoord = vin.TexCoord; output.BlendMapTexCoord = vin.BlendMapTexCoord; return output; } float4 hash4(float2 v) { float4 p = mul(float4x2(127.1, 311.7, 269.5, 183.3, 113.5, 271.9, 246.1, 124.6), v); return frac(sin(p) * 43758.5453123); } float4 PShader(PixelShaderInput input) : SV_TARGET { float4 directionToCamera = normalize(input.PositionWS - cameraPosition); float4 directionToLight = normalize(-lightVector); float surfaceShininess = shininess; float4 adjustedNormal = normalize(input.NormalWS); if (input.PositionWS.y < waterHeight) { float3 n0 = (float3)WaterNormalMap.Sample(ss, input.TexCoord); float4 n2 = float4(mul((float3x3)worldTransformation, n0), 1.0f); adjustedNormal = n2; surfaceShininess = waterShininess; } // Calculate diffuse lighting float NdotL = max(0, dot(adjustedNormal, directionToLight)); float4 diffuse = saturate(lightColor * NdotL * diffuseCoefficient); diffuse.a = 1.0f; // Calculate specular component float4 R = 2 * NdotL * adjustedNormal - directionToLight; float RdotV = max(0, dot(R, directionToCamera)); float4 specular = saturate(lightColor * pow(RdotV, surfaceShininess) * specularCoefficient); specular.a = 1.0f; // Calculate ambient lighting float4 ambientLight = ambientColor * diffuseCoefficient; float4 color; float4 randSamp = rngNoiseMap.Sample(ss, input.BlendMapTexCoord); float2 scaleCenter = float2(0.5f, 0.5f); float currentScale = randSamp.r; float2 scaledUV = frac(UVRotate(input.TexCoord, scaleCenter, currentScale)); // (input.TexCoord - scaleCenter) * currentScale + scaleCenter; float2 xChange = ddx(scaledUV); float2 yChange = ddy(scaledUV); /*if (xChange.x < 0) { xChange = float2(0, 0); } if (yChange.y < 0) { yChange = float2(0, 0); }*/ // Sample layers in texture array. float4 c0 = TexturesArray.SampleGrad(ss, float3(scaledUV, 0.0f), xChange, yChange); float4 c1 = TexturesArray.SampleGrad(ss, float3(scaledUV, 1.0f), xChange, yChange); float4 c2 = TexturesArray.SampleGrad(ss, float3(scaledUV, 2.0f), xChange, yChange); float4 c3 = TexturesArray.SampleGrad(ss, float3(scaledUV, 3.0f), xChange, yChange); float4 c4 = TexturesArray.SampleGrad(ss, float3(scaledUV, 4.0f), xChange, yChange); // Sample the blend map. float4 t = BlendMap.Sample(ss, input.BlendMapTexCoord); // Blend the layers on top of each other. color = c0; color = lerp(color, c1, t.r); color = lerp(color, c2, t.g); color = lerp(color, c3, t.b); color = lerp(color, c4, t.a); // Combine all components if (input.PositionWS.y < waterHeight) { color = color * waterColor; } color = (ambientLight + diffuse) * color; color = saturate(color + specular); return color; }