2

I'm currently working on a Deferred shading project in DirectX. I noticed weird lighting when I create the final image;

enter image description here

With this light ray constantly shining from the top left. I looked at my gbuffers and noticed that my position only seems to take the UV coordinates of the screen (but flipped?) where objects are located.

Position, Normal, Diffuse and Render result

Uv coordinate map for reference

enter image description here

This becomes way more apparent when I try to apply shadow mapping.

enter image description here

The answer is probably really easy, but I am staring myself blind at my code to find what's wrong. I'm posting my shader codes below, sorry if its a lot, I have implemented a working tesselator as well, and I think the problem either lies in the domain or pixelshader.

Vertex shader

struct VertexShaderInput
{
    float4 position : POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;
};

struct VertexShaderOutput
{
    float4 position : POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;
};

VertexShaderOutput DeferredVertexShader(VertexShaderInput input)
{
    VertexShaderOutput output;

    output.position = input.position;
    output.texcoord = input.texcoord;
    output.normal = input.normal;

    return output;
}

Hull shader

cbuffer TessellationBuffer
{
    matrix world;
    float3 CamPos;
    float padding;
};

struct HullShaderInput
{
    float4 position : POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;
};

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

struct HullShaderOutput
{
    float4 position : POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;

};

// PATCH OUTPUT FUNCTION

ConstantOutput PatchConstantFunction(InputPatch<HullShaderInput, 3> inputPatch, uint patchId : SV_PrimitiveID)
{
    ConstantOutput output;
    float3 center = (inputPatch[0].position + inputPatch[1].position + inputPatch[2].position) / 3.0f;
    float3 centerW = mul(float4(center, 1.0f), world).xyz;

    const float d = distance(centerW, CamPos);
    const float d0 = 0.01f;
    const float d1 = 10.0f;

    float tessellationAmount = 12.0f * saturate((d1 - d) / (d1 - d0)) + 1;

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

    return output;
}

// Hull shader
[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("PatchConstantFunction")]

HullShaderOutput DeferredHullShader(InputPatch<HullShaderInput, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
{
    HullShaderOutput output;

    output.position = patch[pointId].position;
    output.texcoord = patch[pointId].texcoord;
    output.normal = patch[pointId].normal;

    return output;
}

Domain shader

cbuffer MatrixBuffer
{
    matrix world;
    matrix view;
    matrix proj;
};

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

struct DomainShaderInput
{
    float4 position : POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;
};

struct DomainShaderOutput
{
    float4 position : SV_POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;
};

// DOMAIN SHADER

[domain("tri")]

DomainShaderOutput DeferredDomainShader(ConstantOutput input, const OutputPatch<DomainShaderInput, 3> patch, float3 barycentric : SV_DomainLocation)
{
    float4 worldPos;
    float3 vertexPosition, flatPosition;
    DomainShaderOutput output;

    output.texcoord = barycentric.x * patch[0].texcoord + barycentric.y * patch[1].texcoord + barycentric.z * patch[2].texcoord;
    output.normal = barycentric.x * patch[0].normal + barycentric.y * patch[1].normal + barycentric.z * patch[2].normal;

    vertexPosition = barycentric.x * patch[0].position + barycentric.y * patch[1].position + barycentric.z * patch[2].position;

    float3 vecProj0 = dot(patch[0].position - vertexPosition, patch[0].normal) * patch[0].normal;
    float3 vecProj1 = dot(patch[1].position - vertexPosition, patch[1].normal) * patch[1].normal;
    float3 vecProj2 = dot(patch[2].position - vertexPosition, patch[2].normal) * patch[2].normal;

    float3 vecOffset = barycentric.x * vecProj0 + barycentric.y * vecProj1 + barycentric.z * vecProj2;

    vertexPosition += 0.5f * vecOffset;

    worldPos = mul(vertexPosition, world);

    output.position = mul(float4(vertexPosition, 1.0f), world);
    output.position = mul(output.position, view);
    output.position = mul(output.position, proj);

    output.normal = mul(output.normal, (float3x3)world);
    output.normal = normalize(output.normal);

    return output;
}

Pixel shader

Texture2D diffuseTexture : register(t0);
Texture2D specularTexture : register(t1);
Texture2D ambientTexture : register(t2);

SamplerState sampleTypeWrap : register(s0);

cbuffer MaterialBuffer
{
    float specularPower;
    float3 pad3;
};

struct PixelShaderInput
{
    float4 position : SV_POSITION;
    float2 texcoord : TEXCOORD0;
    float3 normal   : NORMAL;
};

struct PixelShaderOutput
{
    float4 position : SV_Target0;
    float4 normal   : SV_Target1;
    float4 diffuse  : SV_Target2;
    float4 specular : SV_Target3;
    float4 ambient  : SV_Target4;
};

PixelShaderOutput DeferredPixelShader(PixelShaderInput input) : SV_TARGET
{
    PixelShaderOutput output;
    output.position = input.position;
    output.position.w = 1.0f;

    input.normal = normalize(input.normal);

    output.normal = float4(input.normal, 1.0f);
    output.diffuse = diffuseTexture.Sample(sampleTypeWrap, input.texcoord);
    output.specular = specularTexture.Sample(sampleTypeWrap, input.texcoord);
    output.ambient = ambientTexture.Sample(sampleTypeWrap, input.texcoord);
    output.specular.w = specularPower;

    return output;
}
Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
Charlie.Q
  • 43
  • 6
  • Your gbuffer position is in screen space, to apply shading you want either view space or world space position, so either you add a channel for that from the domain shader to the pixel shader, or more commonly you can reconstruct world position from depth buffer. – mrvux Mar 12 '23 at 16:43
  • @mrvux Ok but I think I do that in my compute shader (which acts as the light pass):

    `float4x4 lightView = lBuffer[index].lightView; float4x4 lightProj = lBuffer[index].lightProj; float4 lightViewPos = mul(float4(pos, 1.0f), lightView); lightViewPos = mul(lightViewPos, lightProj); float2 projUV; projUV.x = lightViewPos.x / lightViewPos.w / 2.0f + 0.5f; projUV.y = -lightViewPos.y / lightViewPos.w / 2.0f + 0.5f;` lBuffer holds all the lights information, and pos is a float3 from the position gBuffer
    – Charlie.Q Mar 12 '23 at 16:53
  • @mrvux weird formatting for the code, but basically I take pos which is a float3 from the position gbuffer and multiplied it with the view and proj matrix from the lights that I loop through, or is this something completely else? – Charlie.Q Mar 12 '23 at 17:16
  • Well that's correct except your position from the gbuffer is in the wrong space (it needs to be in world space to work) – mrvux Mar 14 '23 at 10:58
  • @mrvux sorry for being completely dense, but I'm trying to wrap my head around the transformation... If I understand right, to get the position into world space, I would need to multiply it by the inverse of the view, then projection, lastly world matrix. But wouldn't that render the calculations I make in the domain shader (where I multiply the vertexPosition by world, view and proj) obsolete? – Charlie.Q Mar 15 '23 at 16:47
  • @mrvux so yeah, learnt a bit more in these two months and decided to tackle this again. My problem was that I didn't understand how SV_position changed the coordinates, so now I have a second position channel like you suggested and I send it before doing any matrix calculations so it is still in world coordinates. I still think it looks weird, and my shadowmapping calculations doesnt work. Position gBuffer now: https://imgur.com/a/zEaczyG – Charlie.Q May 20 '23 at 11:31

0 Answers0