I decided to write a program that gives the plane a relief using a height map and tessellation, only the lighting is very rough As I understand it, the normals should be considered as follows:
But I can not implement it.
In short, I need to smooth out the normals.
Here is the shader code.
struct VS_INPUT { float4 Pos : POSITION; }; struct HS_INPUT { float4 Pos : POSITION; float2 Tex : TEXTURE; }; struct DS_INPUT { float4 Pos : POSITION; float2 Tex : TEXTURE; }; struct HS_CONSTANT_DATA { float Edges[3] : SV_TessFactor; float Inside[1] : SV_InsideTessFactor; }; struct GS_INPUT { float4 Pos : SV_POSITION; float2 Tex : TEXTURE; }; struct PS_INPUT { float4 Pos : SV_POSITION; float3 Nrm : NORMAL; float2 Tex : TEXTURE; }; cbuffer data :register(b0) { float4x4 world; float4x4 viewProj; float4 factor; float2 lightPos; float relief; } Texture2D textureMap:register(t0); Texture2D<float4> heightMap:register(t1); SamplerState textureSampler { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; AddressW = Wrap; }; HS_INPUT VS( VS_INPUT input ) { HS_INPUT output = (HS_INPUT)0; output.Tex = (input.Pos + float4(12.5, -12.5, 0, 0)) / float4(25, -25, 0, 0); output.Pos = input.Pos; return output; } float4 PS( PS_INPUT input) : SV_Target { return textureMap.Sample(textureSampler, input.Tex) * saturate(dot(input.Nrm,normalize(float3(lightPos.x, lightPos.y, -1))) + 0.2); } HS_CONSTANT_DATA SampleHSFunction( InputPatch<HS_INPUT, 3> ip, uint PatchID : SV_PrimitiveID ) { HS_CONSTANT_DATA Output; float tessFactor=factor.x; float TessAmount = factor.y; Output.Edges[0] = Output.Edges[1] = Output.Edges[2] = tessFactor; Output.Inside[0] = TessAmount; return Output; } [domain("tri")] [partitioning("pow2")] [outputtopology("triangle_cw")] [outputcontrolpoints(3)] [patchconstantfunc("SampleHSFunction")] DS_INPUT HS( InputPatch<HS_INPUT, 3> p, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID ) { DS_INPUT Output; Output.Pos = p[i].Pos; Output.Tex = p[i].Tex; return Output; } [domain("tri")] GS_INPUT DS( HS_CONSTANT_DATA input, float3 UV : SV_DomainLocation, const OutputPatch<DS_INPUT,3> TrianglePatch ) { GS_INPUT outP; outP.Pos=UV.x * TrianglePatch[0].Pos + UV.y * TrianglePatch[1].Pos + UV.z * TrianglePatch[2].Pos; outP.Tex = UV.x * TrianglePatch[0].Tex + UV.y * TrianglePatch[1].Tex + UV.z * TrianglePatch[2].Tex; outP.Pos.z = heightMap.SampleLevel(textureSampler, outP.Tex, 0, 0).x * relief; outP.Pos = mul(world, outP.Pos); outP.Pos = mul(viewProj,outP.Pos); return outP; } [maxvertexcount(72)] void GS( triangle GS_INPUT input[3], inout TriangleStream<PS_INPUT> TriStream ) { float3 P1=input[0].Pos.xyz; float3 P2=input[1].Pos.xyz; float3 P3=input[2].Pos.xyz; float3 Nrm= normalize(cross(P2-P1,P3-P1)); PS_INPUT A; A.Pos=input[0].Pos; A.Tex=input[0].Tex; A.Nrm=Nrm; PS_INPUT B; B.Pos=input[1].Pos; B.Tex=input[1].Tex; B.Nrm=Nrm; PS_INPUT C; C.Pos=input[2].Pos; C.Tex=input[2].Tex; C.Nrm=Nrm; TriStream.Append(A); TriStream.Append(B); TriStream.Append(C); TriStream.RestartStrip(); }