GeometryShader shows an incorrect normals with using tessellation

Started by
1 comment, last by AndreyVK_D3D 2 years, 1 month ago

Hi All, I have a question. Why A Geometry Shader shows an incorrect Normals with using tessellation?

I see a line position for normals without Height, but height is reading from HeightMap's texture from DomainShader.

Vertex shader:

struct Output {
    float4 pos : SV_POSITION;
    location(1) float3 Normal : NORMAL;
};
struct Input {
    float4 pos: SV_POSITION;
    float3 Normal : NORMAL;
};
Output vsMain(in Input input) {
    Output output;
    output.pos = float4(input.pos.xyz, 1.0f);
    output.Normal = input.Normal;
    return output;
}

Hull Shader:

#define MAX_TF 20.0f
struct VSHSOutput {
    float4 pos: SV_POSITION;
    float3 Normal : NORMAL;
};
struct ConstantsHSOutput {
    float Edges[4] : SV_TessFactor;
    float Inside[2] : SV_InsideTessFactor;
};
cbuffer b0: register(b0) {
    row_major float4x4 view;
    row_major float4x4 proj;
    float4 cameraPosition;
    float LodDistance;
    float tessellationFactor;
    float tessellatedEdgeSize;
    uint numLods;
    float2 viewportDim;
};
float distSq(float3 p0, float3 p1) {
    float3 d = p0 - p1;
    return dot(d, d);
}
float screenSpaceTessFactor(float4 p0, float4 p1) {
    float4 midPoint = 0.5f * (p0 + p1);
    float radius = distance(p0, p1) * 0.5f;
    float4 v0 = mul(midPoint, view);
    float4 clip0 = mul(float4(v0.x - radius, v0.yzw), proj);
    float4 clip1 = mul(float4(v0.x + radius, v0.yzw), proj);
    clip0 /= clip0.w;
    clip1 /= clip1.w;
    clip0.xy *= viewportDim;
    clip1.xy *= viewportDim;
    return max(distance(clip0, clip1) / tessellatedEdgeSize * tessellationFactor, 1.0f);
}
float CalculateTessFactor(float4 p0, float4 p1) {
    return screenSpaceTessFactor(p0, p1);
}
ConstantsHSOutput ConstantsHS(InputPatch<VSHSOutput, 4> ip, uint PatchID : SV_PrimitiveID) {
    ConstantsHSOutput Output;
    Output.Edges[0] = CalculateTessFactor(ip[0].pos, ip[3].pos);
    Output.Edges[1] = CalculateTessFactor(ip[1].pos, ip[0].pos);
    Output.Edges[2] = CalculateTessFactor(ip[2].pos, ip[1].pos);
    Output.Edges[3] = CalculateTessFactor(ip[3].pos, ip[2].pos);
    Output.Inside[0] = lerp(Output.Edges[0], Output.Edges[3], 0.5f);
    Output.Inside[1] = lerp(Output.Edges[1], Output.Edges[2], 0.5f);
    return Output;
}
[domain("quad")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(4)]
[patchconstantfunc("ConstantsHS")]
[maxtessfactor(MAX_TF)]
VSHSOutput hMain(InputPatch<VSHSOutput, 4> ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID) {
    VSHSOutput Output;
    Output.pos = float4(ip[i].pos.xyz, 1.0f);
    Output.Normal = ip[i].Normal;
    return Output;
}

Domain Shader:

struct ConstantsHSOutput {
    float Edges[4] : SV_TessFactor;
    float Inside[2] : SV_InsideTessFactor;
};
struct InputOutput {
    float4 pos: SV_POSITION;
    float3 Normal : NORMAL;
};
cbuffer b0: register(b0) {
    row_major float4x4 ViewProjection;
    row_major float4x4 proj;
    float4 cameraPosition;
    float scaleHeight;
    float2 uvScale;
};
Texture2D HeightMap : register(t0);
SamplerState Sampler : register(s0);
[domain("quad")]
InputOutput dMain(in ConstantsHSOutput input, float2 domain : SV_DomainLocation, const     OutputPatch<InputOutput, 4> patch) {
    InputOutput Output;
    float4 pos = lerp(lerp(patch[0].pos, patch[1].pos, domain.x), lerp(patch[3].pos, patch[2].pos, domain.x), domain.y);
    float2 uv = pos.xz * uvScale;
    pos.y = HeightMap.SampleLevel(Sampler, uv, 0.0).r * scaleHeight;
    Output.pos = float4(pos.xyz, 1.0f);
    Output.Normal = lerp(lerp(patch[0].Normal, patch[1].Normal, domain.x), lerp(patch[3].Normal, patch[2].Normal, domain.x), domain.y);
    return Output;
}

Geometry Shader:

struct GSIn {
    float4 pos : POSITION;
    float3 normal : NORMAL;
};
struct GSOut {
    float4 pos : SV_POSITION;
    float4 color : COLOR;
};
cbuffer b0: register(b0) {
    row_major float4x4 ViewProjection;
};
[maxvertexcount(6)]
void gsMain(triangle GSIn Triangle[3], inout LineStream<GSOut> normal) {
    const float4 color = float4(1.0f, 0.0f, 0.0f, 1.0f);
    GSOut p;
    p.color = color;
    for (int i = 0; i < 3; ++i) {
        p.pos = mul(float4(Triangle[i].pos.xyz, 1.0f), ViewProjection);
        normal.Append(p);
        p.pos.xyz = Triangle[i].pos.xyz + 5.0f * Triangle[i].normal;
        p.pos = mul(float4(p.pos.xyz, 1.0f), ViewProjection);
        normal.Append(p);
        normal.RestartStrip();
    }
}

3DGraphics,Direct3D12,Vulkan,OpenCL,Algorithms

Advertisement

Problem has been fixed. uvScale had an invalid Value, so HeightMap.SampleLevel always was zero.

3DGraphics,Direct3D12,Vulkan,OpenCL,Algorithms

This topic is closed to new replies.

Advertisement