I am trying to render only point cloud data inside a 3d box with a shader.
However, a point cloud data shader uses geometry and a clip box shader uses surface, so I do not know how to combine these two together.
Point Cloud Data Shader
https://answers.unity.com/questions/1437520/implementing-a-geometry-shader-for-a-pointcloud.html
///////////////////////////////////////////
Shader "Custom/Pointcloud" {
Properties{
_Radius("Sphere Radius", float) = 1.0
}
SubShader{
LOD 200
Tags { "RenderType" = "Opaque" }
//if you want transparency
//Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
//Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
#pragma target 4.0 // Use shader model 3.0 target, to get nicer looking lighting
#include "UnityCG.cginc"
struct vertexIn {
float4 pos : POSITION;
float4 color : COLOR;
};
struct vertexOut {
float4 pos : SV_POSITION;
float4 color : COLOR0;
float3 normal : NORMAL;
float r : TEXCOORD0; // not sure if this is good to do lol
};
struct geomOut {
float4 pos : POSITION;
float4 color : COLO0R;
float3 normal : NORMAL;
};
float rand(float3 p) {
return frac(sin(dot(p.xyz, float3(12.9898, 78.233, 45.5432))) * 43758.5453);
}
float2x2 rotate2d(float a) {
float s = sin(a);
float c = cos(a);
return float2x2(c,-s,s,c);
}
//Vertex shader: computes normal wrt camera
vertexOut vert(vertexIn i) {
vertexOut o;
o.pos = UnityObjectToClipPos(i.pos);
o.color = i.color;
o.normal = ObjSpaceViewDir(o.pos);
o.r = rand(i.pos);// calc random value based on object space pos
// from world space instead (particles will spin when mesh moves, kinda funny lol)
//o.r = rand(mul(unity_ObjectToWorld,i.pos));
return o;
}
float _Radius;
//Geometry shaders: Creates an equilateral triangle with the original vertex in the orthocenter
[maxvertexcount(3)]
void geom(point vertexOut IN[1], inout TriangleStream<geomOut> OutputStream)
{
float2 dim = float2(_Radius,_Radius);
float2 p[3]; // equilateral tri
p[0] = float2(-dim.x, dim.y * .57735026919);
p[1] = float2(0., -dim.y * 1.15470053838);
p[2] = float2(dim.x, dim.y * .57735026919);
float2x2 r = rotate2d(IN[0].r * 3.14159);
geomOut OUT;
// OUT.color = IN[0].color;
OUT.color = IN[0].color;
OUT.normal = IN[0].normal;
for (int i = 0; i < 3; i++) {
p[i] = mul(r,p[i]); // apply rotation
p[i].x *= _ScreenParams.y / _ScreenParams.x; // make square
OUT.pos = IN[0].pos + float4(p[i],0,0) / 2.;
OutputStream.Append(OUT);
}
}
float4 frag(geomOut i) : COLOR
{
return i.color;
// could do some additional lighting calculation here based on normal
}
ENDCG
}
}
FallBack "Diffuse"
}
ClibBox shader
https://answers.unity.com/questions/1762908/render-only-whats-inside-a-box.html
Shader "Custom/ClipBox" {
Properties{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows addshadow
#pragma target 3.0
sampler2D _MainTex;
half _Glossiness;
half _Metallic;
float4x4 _WorldToBox;
struct Input {
float2 uv_MainTex;
float3 worldPos;
};
void surf(Input IN, inout SurfaceOutputStandard o) {
float3 boxPosition = mul(_WorldToBox, float4(IN.worldPos, 1));
clip(boxPosition + 0.5);
clip(0.5 - boxPosition);
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
o.Alpha = 0.0f;
}
ENDCG
}
FallBack "Diffuse"
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…