Displacement Map

来源:互联网 发布:尼尔机械纪元a卡优化 编辑:程序博客网 时间:2024/06/06 01:44

Normal Map仅仅提升了光照细节,并没有提升图元细节,Normal Map仅仅只是一种光照技巧。
Displacement Map可以用于提升图元的细节。位移贴图配合细分可以极大的提升效果。
Displacement Map通过将顶点沿着法线方向的反方向进行偏移。
p=p+s(h1)
s是缩放量,h(0,1) , 因此h1(1,0) , 因此可以将顶点向法线内部进行偏移。偏移范围是s(h1)(s,0)
我们可以根据视点与图像的距离,细分图元,并调整mipmap等级。

我们使用D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST代替D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST以应用图元细分。

我们可以根据三角形到眼睛的距离调整细分,越近细分越多,采样纹理的mipmap等级越小。

Displacement Map的每个像素的(x , y , z)是切线空间中法线的坐标 ,w是偏移量,即上面提到的h

Vertex Shader:将三角形各顶点的法线,切线,顶点坐标变换到世界空间中,并根据到视点的距离确定细分系数

cbuffer Transform{float4x4 World;float4x4 WorldViewProj;float4x4 WorldInvTranspose;float4x4 TexTransform;...};cbuffer Tessellation{// 距离越大,细分系数越小// 所以MinTessDistance > MaxTessDistancefloat MinTessDistance;float MaxTessDistance;float MinTess;float MaxTess;float3 EyePosW;};struct VertexIn{float3 PosL :   POSITION;float3 NormalL  :   NORMAL;float3 TangentL :   TANGENT;float2 Tex  :   TEXCOORD;};struct VertexOut{float3 PosW :   POSITION;float3 NormalW  :   NORMAL;float3 TangentW :   TANGENT;float2 Tex  :   TEXCOORD;float TessFactor    :   TESS;}VertexOut main(VertexIn input , out float4 PosH : SV_POSITION){    VertexOut output;    output.PosW = mul(float4(input.PosL , 1.0f) , World).xyz;    output.NormalW = mul(input.NormalL , (float3x3)WorldInvTranspose);    output.TangentW = mul(input.TangentL , (float3x3)World);    output.Tex = mul(float4(input.Tex , 0.0f , 1.0f) , TexTransform).xy;    // 根据距离生成细分因子    float dist = distance(output.PosW , EyePosW);    float tess = (MinTessDistance - d) / (MinTessDistance - MaxTessDistance);    output.TessFactor = MinTessFactor + tess * (MaxTessFactor - MinTessFactor);}

Hull Shader:确定图元的细分因子

struct PatchTess{float EdgeTessFactor[3] :   SV_TessFactor;float InsideTessFactor  :   SV_InsideTessFactor;};PatchTess CalcHSPatchConstants(InputPatch<VertexOut , NUM_CONTROL_POINTS> patch,    uint PatchID : SV_PrimitiveID){    PatchTess output;    output.EdgeTessFactor[0] = 0.5f*(patch[1].TessFactor + pathc[2].TessFactor);    output.EdgeTessFactor[1] = 0.5f*(patch[0].TessFactor + patch[2].TessFactor);    output.EdgeTessFactor[2] = 0.5f* (patch[0].TessFactor + patch[1].TessFactor);    output.InsideTessFactor = output.EdgeTessFactor[0];}// 每个控制点执行一次Hull main(...){    HullOutput output;    output.PosW = input[i].PosW;    output.NormalW = input[i].NormalW;    output.TangentW = input[i].TangentW;    output.Tex = input[i].Tex;}

Domain Shader

DomainOut main(...){...// // 根据视点到顶点的距离调整mipmap level //const float MipInterval = 20.0f;float miplevel = clamp((distance(output.PosW , EyePosW) - MipInterval) / MipInterval , 0.0f , 6.0f);// 采样得到偏移值float h = NormalMap.SampleLevel(SampleLinear , Output.Tex , miplevel).a;//偏移顶点Output.PosW += HeightScale * (h - 1.0f) * Ouput.NormalW;// 变换到齐次空间Output.PosH = mul(float4(Ouput.PosW , 1.0f) , ViewProj);}

Pixel Shader

float4 main(DomainOut in) : SV_TARGENT{......// 计算扰动后的法线值float3 NormalMapSample = NormalMap.Sample(SampleLinear , in.Tex).rgb;float3 BumpNormal = NormalSampleToWorldSpace(NormalMapSample , in.NormalW , in.TangentW);// 光照计算...}
0 0
原创粉丝点击