
Added ability to hold shift and skip the terrain generation when loading Added ability for the perlin terrain to save a raw image of the terrain to use as a cache
174 lines
5.8 KiB
HLSL
174 lines
5.8 KiB
HLSL
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
|
|
|
|
// Vars to deal with the water, also padding because the cbuffer needs to be a multiple of 16
|
|
float waterHeight;
|
|
float waterShininess;
|
|
float4 waterColor;
|
|
|
|
// Padded with a float array, floats being 4 bytes each, the above just hits the multiple of 16 but added extra incase this was the issue, will remove later most likely
|
|
float padding[4];
|
|
}
|
|
|
|
Texture2D BlendMap : register(t0);
|
|
Texture2DArray TexturesArray : register(t1);
|
|
|
|
// Textures for the water normals and the snow
|
|
Texture2D WaterNormalMap : register(t2);
|
|
Texture2D snowTest : 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 PositionOG: TEXCOORD4;
|
|
float4 NormalWS : TEXCOORD3;
|
|
float2 TexCoord : TEXCOORD0;
|
|
float2 BlendMapTexCoord : TEXCOORD1;
|
|
};
|
|
|
|
// Function for rotating a UV around a point
|
|
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;
|
|
|
|
}
|
|
|
|
// Typical HLSL hasing function for psuedo random number generation
|
|
float4 hash4(float2 v)
|
|
{
|
|
float4 p = mul(float4x2(127.1f, 311.7f, 269.5f, 183.3f, 113.5f, 271.9f, 246.1f, 124.6f), v);
|
|
return frac(sin(p) * 43758.5453123);
|
|
}
|
|
|
|
PixelShaderInput VShader(VertexShaderInput vin)
|
|
{
|
|
PixelShaderInput output;
|
|
float3 position = vin.Position;
|
|
output.PositionOG = output.PositionWS = mul(worldTransformation, float4(position, 1.0f));
|
|
output.TexCoord = vin.TexCoord;
|
|
// Check if the y pos is lower than the water point
|
|
if (position.y < waterHeight)
|
|
{
|
|
// Change up the flat water height with some psuedo RNG height generation
|
|
float4 yOffset = hash4(float2(-position.y, position.y));
|
|
// the offset should return as a value between 0 and 1, i change this to be a value between -1 and 1, then add some height modifier so you can actually see the difference
|
|
position.y = waterHeight + (((yOffset.y * 2.0f) - 1.0f) * 3.0f);
|
|
}
|
|
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.BlendMapTexCoord = vin.BlendMapTexCoord;
|
|
return output;
|
|
}
|
|
|
|
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.PositionOG.y < waterHeight)
|
|
{
|
|
// Sample the normal from the water normal map and calculate it with the worldtransform
|
|
float4 n0 = WaterNormalMap.Sample(ss, input.TexCoord);
|
|
float4 n1 = float4((n0.xyz * 2.0f) - 1.0f, 1.0f);
|
|
//float4 n2 = float4(mul((float3x3)worldTransformation, n0), 1.0f);
|
|
adjustedNormal = n1; // normalize(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;
|
|
|
|
// Randomly rotate the UV coordinates using the noise map
|
|
float2 scaleCenter = float2(0.5f, 0.5f);
|
|
float2 scaledUV = frac(UVRotate(input.TexCoord, scaleCenter, input.BlendMapTexCoord.x)); // (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);
|
|
// Using the single snow texture because of the snow dds loading glitch
|
|
float4 c4 = snowTest.SampleGrad(ss, float2(scaledUV), 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, and check if this is water
|
|
if (input.PositionOG.y < waterHeight)
|
|
{
|
|
// Tint the water
|
|
color = saturate(color) * waterColor;
|
|
}
|
|
color = (ambientLight + diffuse) * color;
|
|
color = saturate(color + specular);
|
|
return color;
|
|
} |