• 在DirectX 12中使用tessellation


    DirectX 12支持tessellation,我们可以在vertex shader后加入hull shader和domain shader,来对顶点进行动态细分,以实现不同的效果。在CPU层面上,我们传入的顶点信息需要设置为patchlist,DirectX 12最多支持32个控制点的patchlist:

    object->mPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST;
    
    mCommandList->IASetPrimitiveTopology(object->mPrimitiveTopology);
    

    另外,在创建pipeline state object时,也需要进行一下调整:

    psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
    

    hull shader的定义如下:

    struct HullOut
    {
    	float3 PosL : POSITION;
    };
        
    [domain("quad")]
    [partitioning("integer")]
    [outputtopology("triangle_cw")]
    [outputcontrolpoints(4)]
    [patchconstantfunc("ConstantHS")]
    [maxtessfactor(64.0f)]
    HullOut HS(InputPatch<VertexOut, 4> p, 
               uint i : SV_OutputControlPointID,
               uint patchId : SV_PrimitiveID)
    {
    	HullOut hout;
    	
    	hout.PosL = p[i].PosL;
    	
    	return hout;
    }
    

    domain表示输入到hull shader的primitive格式,partitioning表示硬件tessellation的方式,outputtopology表示hull shader输出的primitive格式和绕序,outputcontrolpoints表示输出控制点的数量,这个数量决定了hull shader执行的次数。patchconstantfunc表示具体如何对一个primitive进行partition的函数,maxtessfactor表示最多tessellation的数量。

    patchconstantfunc的定义如下:

    struct PatchTess
    {
    	float EdgeTess[4]   : SV_TessFactor;
    	float InsideTess[2] : SV_InsideTessFactor;
    };
    
    PatchTess ConstantHS(InputPatch<VertexOut, 4> patch, uint patchID : SV_PrimitiveID)
    {
    	PatchTess pt;
    	
    	float3 centerL = 0.25f*(patch[0].PosL + patch[1].PosL + patch[2].PosL + patch[3].PosL);
    	float3 centerW = mul(float4(centerL, 1.0f), gWorld).xyz;
    	
    	float d = distance(centerW, gEyePosW);
    
    	// Tessellate the patch based on distance from the eye such that
    	// the tessellation is 0 if d >= d1 and 64 if d <= d0.  The interval
    	// [d0, d1] defines the range we tessellate in.
    	
    	const float d0 = 20.0f;
    	const float d1 = 100.0f;
    	float tess = 64.0f*saturate( (d1-d)/(d1-d0) );
    
    	// Uniformly tessellate the patch.
    
    	pt.EdgeTess[0] = tess;
    	pt.EdgeTess[1] = tess;
    	pt.EdgeTess[2] = tess;
    	pt.EdgeTess[3] = tess;
    	
    	pt.InsideTess[0] = tess;
    	pt.InsideTess[1] = tess;
    	
    	return pt;
    }
    

    EdgeTess控制边tessellation的数量,InsideTess控制primitive内部tessellation的数量。

    tessellation的结果会以uv的方式传递给domain shader。domain shader的定义如下:

    struct DomainOut
    {
    	float4 PosH : SV_POSITION;
    };
    
    // The domain shader is called for every vertex created by the tessellator.  
    // It is like the vertex shader after tessellation.
    [domain("quad")]
    DomainOut DS(PatchTess patchTess, 
                 float2 uv : SV_DomainLocation, 
                 const OutputPatch<HullOut, 4> quad)
    {
    	DomainOut dout;
    	
    	// Bilinear interpolation.
    	float3 v1 = lerp(quad[0].PosL, quad[1].PosL, uv.x); 
    	float3 v2 = lerp(quad[2].PosL, quad[3].PosL, uv.x); 
    	float3 p  = lerp(v1, v2, uv.y); 
    	
    	// Displacement mapping
    	p.y = 0.3f*( p.z*sin(p.x) + p.x*cos(p.z) );
    	
    	float4 posW = mul(float4(p, 1.0f), gWorld);
    	dout.PosH = mul(posW, gViewProj);
    	
    	return dout;
    }
    

    最后运行的结果如下:

    如果你觉得我的文章有帮助,欢迎关注我的微信公众号(大龄社畜的游戏开发之路-

  • 相关阅读:
    ASP.NET AJAX入门系列(7):使用客户端脚本对UpdateProgress编程
    ASP.NET AJAX入门系列(9):在母版页中使用UpdatePanel
    全面剖析C#正则表达式
    c# 正则表达式基础知识
    代理模式(Proxy Pattern)
    ASP.NET AJAX入门系列(8):自定义异常处理
    ASP.NET AJAX入门系列(2):使用ScriptManager控件
    ASP.NET AJAX入门系列(5):使用UpdatePanel控件(二)
    ASP.NET AJAX入门系列(6):UpdateProgress控件简单介绍
    ASP.NET AJAX入门系列(1):概述
  • 原文地址:https://www.cnblogs.com/back-to-the-past/p/15203334.html
Copyright © 2020-2023  润新知