Hi guys.
I've been trying to implement tessellation, and got it implemented, thanks to you.
My next goal is to implement terrain tessellation with displacement mapping
Questions: (Some I have attempted, shown in the shader code below)
- The vertices generated on the cpu, do they just represent a plane, or a pre generated grid?
- How do I decide the height of the displacement mapping, just a constant?
- How are the normals generated?
My attempt: (If you want to see...)
cbuffer ConstantObjectBuffer : register (b0)
{
matrix worldMatrix;
};
cbuffer ConstantFrameBuffer : register (b1)
{
matrix viewMatrix;
matrix projectionMatrix;
float3 eyepos;
float cppad;
float4 lightvec;
float4 lightcol;
float FogStart;
float FogEnd;
float2 __space;
float3 FogColor;
float shadows;
float SpecularIntensity;
float3 pad3;
float4 SpecularColor;
}
//***************************************************//
// VERTEX SHADER //
//***************************************************//
struct VOut
{
float4 position : POSITION;
float2 texcoord : TEXCOORD;
float access : ACCESS;
float tessAmount : TSSAM;
float3 NormalW : NORMWORLD;
float3 normal : NORM;
float4 depthPosition : TEXTURE0;
};
struct GlobalIn
{
float4 position : POSITION;
float4 normal : NORMAL;
float2 texcoord : TEXCOORD;
};
Texture2D t_map : register(t0);
SamplerState ss;
VOut VShader(GlobalIn input)
{
VOut output;
input.position.w = 1.0f;
output.texcoord = input.texcoord;
// Calculate the position of the vertex against the world, view, and projection matrices.
/*output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);*/
output.position = mul(input.position, viewMatrix);
// Get Tesselation amount
output.tessAmount = (1.0f / output.position.z) * 6.0f;
output.position = input.position;
output.NormalW = mul(float4(input.normal.xyz,0), mul(worldMatrix, viewMatrix));
// Store the position value in a second input value for depth value calculations.
output.depthPosition.xyz = mul(float4(input.position.xyz,1), mul(worldMatrix, viewMatrix)).xyz;
// Per Vertex lighting
float4 norm = normalize(input.normal);
output.access = saturate(dot(norm, lightvec));
output.normal = input.normal;
return output;
}
//***************************************************//
// HULL SHADER //
//***************************************************//
struct HOutput
{
float edges[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
#define tessellationAmount 12.0f
HOutput ColorPatchConstantFunction(InputPatch<VOut, 3> inputPatch, uint patchId : SV_PrimitiveID)
{
HOutput output;
float tA = inputPatch[0].tessAmount;
tA = 12.0f;
// Set the tessellation factors for the three edges of the triangle.
output.edges[0] = tA;
output.edges[1] = tA;
output.edges[2] = tA;
// Set the tessellation factor for tessallating inside the triangle.
output.inside = tA;
return output;
}
[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("ColorPatchConstantFunction")]
VOut HShader(InputPatch<VOut, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
{
VOut output;
// Set the x for this control point as the output x.
output.position = patch[pointId].position;
output.texcoord = patch[pointId].texcoord;
output.access = patch[pointId].access;
output.NormalW = patch[pointId].NormalW;
output.normal = patch[pointId].normal;
output.depthPosition = patch[pointId].depthPosition;
return output;
}
//***************************************************//
// DOMAIN SHADER //
//***************************************************//
struct DOut
{
float4 position : SV_Position;
float2 texcoord : TEXCOORD;
float access : ACCESS;
float3 NormalW : NORMWORLD;
float4 depthPosition : TEXTURE0;
};
[domain("tri")]
DOut DShader(HOutput input, float3 uvwCoord : SV_DomainLocation, const OutputPatch<VOut, 3> patch)
{
DOut output;
float3 vertexPosition;
float2 texCoords;
float3 normal;
float4 worldPosition;
vertexPosition = uvwCoord.x * patch[0].position + uvwCoord.y * patch[1].position + uvwCoord.z * patch[2].position;
texCoords = uvwCoord.x * patch[0].texcoord + uvwCoord.y * patch[1].texcoord + uvwCoord.z * patch[2].texcoord;
normal = uvwCoord.x * float3(0, 1, 0) + uvwCoord.y * float3(0, 1, 0) + uvwCoord.z * float3(0, 1, 0);
normal = normalize(normal);
float vHeight = t_map.SampleLevel(ss, texCoords, 0);
vertexPosition += float3(0, 1, 0) * (vHeight * 2.0f);
output.position = mul(float4(vertexPosition, 1.0f), worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
output.texcoord = texCoords;
output.NormalW = mul(normal,(float3x3)worldMatrix);
output.NormalW = normalize(output.NormalW);
return output;
}
//***************************************************//
// PIXEL SHADER //
//***************************************************//
struct POut
{
float4 Diffuse : SV_Target0;
float4 Depth : SV_Target1;
float4 Normals : SV_Target2;
float4 Lighting : SV_Target3;
};
POut PShader(VOut input)
{
POut output;
// Depth
output.Depth = float4(input.depthPosition.xyz, 1.0f);
// Normals
output.Normals = float4(normalize(input.NormalW), 1);
output.Diffuse = float4(1, 1, 1, 1);
output.Lighting = float4(lightcol.rgb * input.access, 1.0f);
output.Lighting = float4(1, 1, 1, 1);
return output;
}
I've attempted with the pre generated grid, but this came: (The terrain is repeated over and over again, why?)
Thank you, as always GameDev.