用点积、叉积搞点事情

用点积、叉积实现剖面图效果
什么是剖面图,一把无形的刀,将模型一分为二,将其中一半隐藏掉,单看一半用来观察内部结构。几年前出现Zorro的工具,能将剖切的墙体截面涂成纯色。


用点积、叉积搞点事情_第1张图片

为了方便与算法联系,我将刀的所在的平面分解为三个点,毕竟三点成面嘛。上效果


用点积、叉积搞点事情_第2张图片

用点积、叉积搞点事情_第3张图片

1.实现方法:①界面表现:两个pass 一个剔除正面输出截面颜色 第二个pass剔除反面+光照 ②discard 剖切掉的模型:点积、叉积
2.点积、叉积相关算法
3.shader

点积、叉积

使用脚本得到世界坐标系下三个点的坐标P1,P2,P3,这三个点确定一个平面。


用点积、叉积搞点事情_第4张图片

用P1、P2、P3先求出Dir1与Dir2 . 用向量Dir1叉乘向量Dir2,如在Unity里世界坐标系为左手坐标系,得到的Dir3指向如图方向。


用点积、叉积搞点事情_第5张图片

取该片元在世界坐标系下的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
        }
    }
}

你可能感兴趣的:(用点积、叉积搞点事情)