用点积、叉积搞点事情
2019-01-04 本文已影响12人
万里_aa3f
用点积、叉积实现剖面图效果
什么是剖面图,一把无形的刀,将模型一分为二,将其中一半隐藏掉,单看一半用来观察内部结构。几年前出现Zorro的工具,能将剖切的墙体截面涂成纯色。
为了方便与算法联系,我将刀的所在的平面分解为三个点,毕竟三点成面嘛。上效果
1.实现方法:①界面表现:两个pass 一个剔除正面输出截面颜色 第二个pass剔除反面+光照 ②discard 剖切掉的模型:点积、叉积
2.点积、叉积相关算法
3.shader
点积、叉积
使用脚本得到世界坐标系下三个点的坐标P1,P2,P3,这三个点确定一个平面。
用P1、P2、P3先求出Dir1与Dir2 . 用向量Dir1叉乘向量Dir2,如在Unity里世界坐标系为左手坐标系,得到的Dir3指向如图方向。
取该片元在世界坐标系下的worldPos减去P1得出Dir4 ,因点成公式为a·b=|a||b|cos@ 判断Dir4点成Dir3的正负即可,负的discard掉
Shader
Shader"LuZheng/ZorroKnife"{
Properties{
_LeftPoint("LeftPoint",Vector)=(0,0,0,1)
_RightPoint("RightPoint",Vector)=(0,1,0,1)
_UpPoint("UpPoint",Vector)=(1,0,0,1)
_Color("InterColor",Color)=(1,0,0,1)
}
SubShader{
Tags{"RenderType"="Transparent""IgnoreProjector"="True""Queue"="Transparent"}
pass{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
float4 _LeftPoint;
float4 _RightPoint;
float4 _UpPoint;
struct a2v{
float4 vertex:POSITION;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldPos:TEXCOORD0;
};
void isVisiable(float3 WorldPos){
float3 Dir1=(_RightPoint-_LeftPoint).xyz;
float3 Dir2=(_UpPoint-_LeftPoint).xyz;
float3 Dir3=cross(Dir2,Dir1);
float3 Dir4=WorldPos-_LeftPoint.xyz;
if(dot(Dir3,Dir4)<0){
discard;
}
}
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
return o;
}
fixed4 frag(v2f i):SV_TARGET{
isVisiable(i.worldPos);
return (_Color);
}
ENDCG
}
pass{
Tags{"LightMode"="ForwardBase"}
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
#include"Lighting.cginc"
fixed4 _Color;
float4 _LeftPoint;
float4 _RightPoint;
float4 _UpPoint;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldPos:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
};
void isVisiable(float3 WorldPos){
float3 Dir1=(_RightPoint-_LeftPoint).xyz;
float3 Dir2=(_UpPoint-_LeftPoint).xyz;
float3 Dir3=cross(Dir2,Dir1);
float3 Dir4=WorldPos-_LeftPoint.xyz;
if(dot(Dir3,Dir4)<0){
discard;
}
}
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag(v2f i):SV_TARGET{
isVisiable(i.worldPos);
float3 worldNormal=normalize(i.worldNormal);
float3 LightDir=UnityWorldSpaceLightDir(i.worldPos);
fixed3 color=saturate(dot(worldNormal,LightDir))*_LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;;
return fixed4(color,1);
}
ENDCG
}
}
}