6
\$\begingroup\$

Firstly some info - I'm using DirectX 11 , C++ and I'm a fairly good programmer but new to tessellation and not a master graphics programmer.

I'm currently implementing a tessellation system for a terrain model, but i have reached a snag. My current system produces a terrain model from a height map complete with multiple texture coordinates, normals, binormals and tangents for rendering. Now when i was using a simple vertex and pixel shader combination everything worked perfectly but since moving to include a hull and domain shader I'm slightly confused and getting strange results. My terrain is a high detail model but the textured results are very large patches of solid colour.

My current setup passes the model data into the vertex shader then through the hull into the domain and then finally into the pixel shader for use in rendering. My only thought is that in my hull shader i pass the information into the domain shader per patch and this is producing the large areas of solid colour because each patch has identical information. Lighting and normal data are also slightly off but not as visibly as texturing.

Below is a copy of my hull shader that does not work correctly because i think the way that i am passing the data through is incorrect. If anyone can help me out but suggesting an alternative way to get the required data into the pixel shader? or by showing me the correct way to handle the data in the hull shader id be very thankful!

cbuffer TessellationBuffer
{
    float tessellationAmount;
    float3 padding;
};

struct HullInputType
{
    float3 position : POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
    float3 binormal : BINORMAL;
    float2 tex2 : TEXCOORD1;
};

struct ConstantOutputType
{
    float edges[3] : SV_TessFactor;
    float inside : SV_InsideTessFactor;
};

struct HullOutputType
{
    float3 position : POSITION;
    float2 tex : TEXCOORD0;
float3 normal : NORMAL;
float3 tangent : TANGENT;
float3 binormal : BINORMAL;
    float2 tex2 : TEXCOORD1;
    float4 depthPosition : TEXCOORD2;
};

ConstantOutputType ColorPatchConstantFunction(InputPatch<HullInputType, 3>        inputPatch, uint patchId : SV_PrimitiveID)
{    
    ConstantOutputType output;

output.edges[0] = tessellationAmount;
output.edges[1] = tessellationAmount;
output.edges[2] = tessellationAmount;
output.inside = tessellationAmount;

return output;
}

[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("ColorPatchConstantFunction")]

HullOutputType ColorHullShader(InputPatch<HullInputType, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
{
   HullOutputType output;

output.position = patch[pointId].position;
output.tex = patch[pointId].tex;
output.tex2 = patch[pointId].tex2;
output.normal = patch[pointId].normal;
output.tangent = patch[pointId].tangent;
    output.binormal = patch[pointId].binormal;

    return output;
}

Edited to include the domain shader:-

[domain("tri")]

PixelInputType ColorDomainShader(ConstantOutputType input, float3 uvwCoord :    SV_DomainLocation, const OutputPatch<HullOutputType, 3> patch)
{
    float3 vertexPosition;
    PixelInputType output;

// Determine the position of the new vertex.
    vertexPosition = uvwCoord.x * patch[0].position + uvwCoord.y * patch[1].position + uvwCoord.z * patch[2].position;

    output.position = mul(float4(vertexPosition, 1.0f), worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);    

    output.depthPosition = output.position;

     output.tex = patch[0].tex;
     output.tex2 = patch[0].tex2;
     output.normal = patch[0].normal;
     output.tangent = patch[0].tangent;
     output.binormal = patch[0].binormal;

    return output;
}
\$\endgroup\$
2
  • \$\begingroup\$ Can you post your domain shader as well? At a first guess I wonder if your domain shader is just duplicating one control point's UVs across the whole patch. \$\endgroup\$ Dec 17, 2012 at 22:14
  • \$\begingroup\$ edited to include the domain shader and just from looking at it i can see im only using patch[0]. how can i edit this so im using all three elements? \$\endgroup\$ Dec 17, 2012 at 22:48

1 Answer 1

4
\$\begingroup\$

The domain shader needs to interpolate amongst the patch control points using the SV_DomainLocation input. The idea is that the GPU runs the domain shader for each generated vertex of the tessellated patch, and you have complete control over where these vertices go. That's how you can implement different algorithms such as bicubic patches, PN triangles, subdivision surfaces, displacement mapping, etc.

As a simple test case you could just linearly interpolate the control points. This will just generate a flat triangle for each patch, i.e. the tessellated mesh should come out visually indistinguishable from the original triangle mesh, just with more triangles. To do this you'd so something like

output.tex = patch[0].tex * uvwCoord.x + patch[1].tex * uvwCoord.y + patch[2].tex * uvwCoord.z;

and similarly for the other components. The next step would be to replace the linear interpolation with something that actually generates a curved surface based on the normals, such as Phong tessellation (simpler, faster) or PN triangles (slower, possibly better results). Or, for terrain you presumably want to do displacement mapping, so you might skip generating the curved surface and just set the position directly from the heightmap.

\$\endgroup\$
2
  • \$\begingroup\$ thank you thats what im looking for :)! The next stage is to use displacement mapping to improve terrain detail around the camera. I have effects such as bump mapping already implemented in my pixel shader by using the depth position of the pixel to adjust if it is effect or not. I was wondering if you could possible point me in the correct direction to limiting the tessellation in the same way? i plan to do a bit of research into tessellation as its clear i just dont understand the system well enough yet. Thanks again! \$\endgroup\$ Dec 18, 2012 at 12:46
  • \$\begingroup\$ @StuartMartin You should be able to use the depth of the vertex to fade out the displacement map when it's too far away from the camera. Pretty easy. Don't forget to also reduce the tessellation factors when the whole patch is far from the camera, to save triangles. \$\endgroup\$ Dec 18, 2012 at 17:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .