?
1.必须使用专用的着色器shader
2.使用时根据实限情况动态修改着色器shader的参数,MultipleTubesExample.cs必须挂载在要打孔的最上层节点上。
Shader "CrossSection/Unlit/Texture" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_SectionColor ("Section Color", Color) = (1,0,0,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 100
Cull off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
#pragma multi_compile __ CLIP_PLANE CLIP_TWO_PLANES CLIP_SPHERE CLIP_CUBE CLIP_TUBES CLIP_BOX
#include "CGIncludes/section_clipping_CS.cginc"
fixed4 _SectionColor;
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float4 wpos : TEXCOORD2;
UNITY_FOG_COORDS(1)
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 worldPos = mul (unity_ObjectToWorld, v.vertex).xyz;
float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
float dotProduct = dot(v.normal, viewDir);
//if(dotProduct<0) v.vertex.xyz -= v.normal * _BackfaceExtrusion;
o.wpos.w = dotProduct;
o.wpos.xyz = worldPos;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//PLANE_CLIP(i.wpos.xyz);
#if CLIP_BOX
PLANE_CLIPWITHCAPS(i.wpos.xyz);
#else
PLANE_CLIP(i.wpos.xyz);
#endif
//fixed4 col = (i.wpos.w>0)? tex2D(_MainTex, i.texcoord): _SectionColor;
//UNITY_APPLY_FOG(i.fogCoord, col);
//UNITY_OPAQUE_ALPHA(col.a);
return tex2D(_MainTex, i.texcoord);
}
ENDCG
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
public class MultipleTubesExample : MonoBehaviour {
private Vector4[] centerPoints;
private Vector4[] AxisDirs;
private float[] radiuses;
//最多64个
[Range(0, 64)]
//当前数量限制
public int n = 5;
private int i = 0;
void Start () {
centerPoints = new Vector4[64];
AxisDirs = new Vector4[64];
radiuses = new float[64];
Shader.SetGlobalInt("_centerCount", 0);
Renderer[] allrenderers = gameObject.GetComponentsInChildren<Renderer>();
foreach (Renderer r in allrenderers)
{
Material[] mats = r.sharedMaterials;
foreach (Material m in mats) if (m.shader.name.Substring(0, 13) == "CrossSection/") m.DisableKeyword("CLIP_PLANE");
}
}
void Update () {
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform.IsChildOf(transform))
{
Shader.EnableKeyword("CLIP_TUBES");
int k = i % n;
Debug.Log(k);
//圆柱中心点
centerPoints[k] = hit.point;
//圆柱方向
AxisDirs[k] = (hit.point - Camera.main.transform.position).normalized;
//半径
radiuses[k] = 50.0f;
Shader.SetGlobalVectorArray("_centerPoints", centerPoints);
Shader.SetGlobalVectorArray("_AxisDirs", AxisDirs);
Shader.SetGlobalFloatArray("_Radiuses", radiuses);
i++;
Shader.SetGlobalInt("_centerCount", (int)Mathf.Min(i, n));
Shader.SetGlobalInt("_tubeCount", (int)Mathf.Min(i, n));
}
}
}
}
void OnEnable()
{
Shader.EnableKeyword("CLIP_TUBES");
}
void OnDisable()
{
Shader.DisableKeyword("CLIP_TUBES");
Shader.SetGlobalInt("_hitCount", 0);
}
void OnApplicationQuit()
{
//disable clipping so we could see the materials and objects in editor properly
Shader.DisableKeyword("CLIP_TUBES");
}
}
|