DX11 Geometry Shader – Terrain Sample

Overview

This sample demonstrates how to use a geometry shader to procedurally generate terrain geometry on the GPU with DirectX 11. It showcases tessellation, height‑map displacement, and dynamic LOD.

Prerequisites

Key Files

#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
using namespace DirectX;

// Vertex structure
struct Vertex
{
    XMFLOAT3 Pos;
    XMFLOAT3 Normal;
    XMFLOAT2 Tex;
};

// Constant buffer
cbuffer CBPerObject : register(b0)
{
    matrix World;
    matrix View;
    matrix Projection;
    float   TessFactor;
};

// Vertex shader (pass‑through)
VS_OUTPUT VSMain(VS_INPUT input)
{
    VS_OUTPUT output;
    output.Pos = mul(float4(input.Pos, 1.0f), World);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Normal = mul(input.Normal, (float3x3)World);
    output.Tex = input.Tex;
    return output;
}

// Geometry shader – generate terrain quads
[maxvertexcount(4)]
void GSMain(triangle VS_OUTPUT input[3], inout TriangleStream triStream)
{
    // Simple tri‑to‑quad conversion with tessellation factor
    for (int i = 0; i < 3; ++i)
    {
        VS_OUTPUT v = input[i];
        // Displace based on a height map (sampled in a real shader)
        v.Pos.y += sin(v.Pos.x * 0.1f) * 2.0f;
        triStream.Append(v);
    }
}

// Pixel shader – basic lighting
float4 PSMain(VS_OUTPUT input) : SV_TARGET
{
    float3 lightDir = normalize(float3(0.5f, -1.0f, 0.5f));
    float NdotL = saturate(dot(input.Normal, -lightDir));
    float4 color = float4(NdotL, NdotL, NdotL, 1.0f);
    return color;
}

// Compile shaders
ID3DBlob* CompileShader(const wchar_t* src, const char* entry, const char* target)
{
    ID3DBlob* shaderBlob = nullptr;
    ID3DBlob* errorBlob = nullptr;
    D3DCompileFromFile(src, nullptr, nullptr, entry, target, 0, 0, &shaderBlob, &errorBlob);
    if (errorBlob) { OutputDebugStringA((char*)errorBlob->GetBufferPointer()); }
    return shaderBlob;
}
Download Project ZIP

Run the Sample

  1. Open TerrainSample.sln in Visual Studio.
  2. Build the solution (Debug or Release).
  3. Run the executable – you’ll see a procedurally generated terrain rendered with a geometry shader.

Further Reading