Directx11教程十六之ClipPlane(裁剪面)

看看本节的教程,本节介绍有关裁剪面的使用,先看看本节教程的结架吧,跟DiffuseLight那节教程的结架差不多




第一,ClipPlane的简介和公式。


裁剪面既然说了“面”,本节的教程涉及的面为平面,而非曲面,3D空间一个平面可以将空间分为两半,熟知的有X平面,Y平面,Z平面等等。

3D空间平面的方程式为 ax+by+cz+d=0;
(a,b,c)为平面的法向量,d为一个参数,具体推导参照3D平面的通用公式
随便提一下,XNAMATH库的平面用XMVECTOR(a,b,c,d)来表示。

假设一个点为(x1,y1,z1)

(1)当a*x1+b*y1+c*z1+d=0时 代表这个点在这个平面上。
(2)当a*x1+b*y1+c*z1+d<0时,代表这个点在这个平面的后面(面法向量的反向)。
(3)a*x1+b*y1+c*z1+d>0时,代表这个点在这个平面的前面(面法向量的正向)。

那么平面的前面和后面怎么区别呢?这得根据法向量的方向,在法向量方向那一边的为前面,反之为后面,看下面图就知道了:







假设裁剪面为(ClipP lane)为 ax+by+cz+d=0;,用float4表示为(a,b,c,d),  将3D几何体上位于   a*x1+b*y1+c*z1+d<0 空间的点剔除

Texture2D ShaderTexture:register(t0);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
	matrix World;
	matrix View;
	matrix Proj;
	matrix WorldInvTranspose;
};

cbuffer CBLight:register(b1)
{
	float4 DiffuseColor;
	float3 LightDirection;
	float pad;
};

cbuffer CBClipPlane:register(b2)
{
	float4 ClipPlane;
};

struct VertexIn
{
	float3 Pos:POSITION;
	float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
	float3 Normal:NORMAL;
};


struct VertexOut
{
	float4 Pos:SV_POSITION;
	float ClipValue : SV_ClipDistance0;//裁剪值关键字
	float2 Tex:TEXCOORD0;
	float3 W_Normal:NORMAL;  //世界空间的法线

};


VertexOut VS(VertexIn ina)
{
	VertexOut outa;
	//将顶点变换到齐次裁剪空间
	outa.Pos = mul(float4(ina.Pos,1.0f), World);
	outa.Pos = mul(outa.Pos, View);
	outa.Pos = mul(outa.Pos, Proj);

	//将顶点法线量变换到世界空间
	outa.W_Normal = mul(ina.Normal, (float3x3)WorldInvTranspose);  //此事世界逆转置矩阵的第四行本来就没啥用
	outa.W_Normal = normalize(outa.W_Normal);

	outa.Tex= ina.Tex;

	//在世界空间,对于乘以裁剪面小于零的进行裁剪,裁剪不满足条件的几何体部分
	outa.ClipValue = dot(mul(float4(ina.Pos, 1.0f), World), ClipPlane);
	return outa;
}


float4 PS(VertexOut outa) : SV_Target
{
	float4 TexColor; //采集的纹理颜色
    float LightFactor; //灯光因子
	float4 color = {0.0f,0.0f,0.0f,0.0f}; //最终输出的颜色


	//第一,获取采样颜色
    TexColor = ShaderTexture.Sample(SampleType, outa.Tex);

	//第二,求出灯光因子
	float3 InvLightDir = -LightDirection;
	 LightFactor = saturate(dot(InvLightDir,outa.W_Normal));
	 
	//第三,求出灯光照射颜色
	 if (LightFactor>0)
	 {
		 color += LightFactor*DiffuseColor;  //saturate(float1*float4)
	 }
	 
	 color = saturate(color);
		
	//第四,用灯光颜色调节纹理颜色
	color = color*TexColor;

	return color;
}

    //在世界空间,对于乘以裁剪面小于零的进行裁剪,裁剪不满足条件的几何体部分
   outa.ClipValue = dot(mul(float4(ina.Pos, 1.0f), World), ClipPlane);

注意关键字:
float ClipValue : SV_ClipDistance0;其中“ SV_ClipDistance0”代表裁剪值,在VertexShader进行计算得到的值小于0的被裁剪,跟PixelShader的函数Clip(Clip用于在PixelShader裁剪像素)有相似的功能。

我设定的裁剪面为:(0.0f,-1.0f,0.0f,0.0f),即在Y面以上的空间元素被裁剪。

最后我设定光栅化状态为不进行背面剔除,并且将相机位置往上平移
rasterDesc.CullMode = D3D11_CULL_NONE; //背面剔除

程序运行结果如下:




没裁剪面的时候程序运行如下:




最后我的源代码链接如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值