您的位置:首页 > 其它

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

2016-10-13 19:18 253 查看
看看本节的教程,本节介绍有关裁剪面的使用,先看看本节教程的结架吧,跟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时,代表这个点在这个平面的前面(面法向量的正向)。

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



假设裁剪面为(ClipPlane)为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; //背面剔除

程序运行结果如下:



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



最后我的源代码链接如下:
http://download.csdn.net/detail/qq_29523119/9667258
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: