如何解决仅渲染盒子内的点云数据
我正在尝试仅使用着色器渲染3d框内的点云数据。 但是,点云数据着色器使用几何图形,而剪辑盒着色器使用曲面,所以我不知道如何将这两个组合在一起。
点云数据着色器
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) / 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着色器
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",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"
}
解决方法
要获取像素在片段着色器中的世界位置,您必须将其通过顶点和几何着色器:
顶点=>几何
struct vertexOut {
float4 pos : SV_POSITION;
float4 color : COLOR0;
float3 normal : NORMAL;
float r : TEXCOORD0; // not sure if this is good to do lol
float3 worldPos : TEXCOORD1;
};
vertexOut vert(vertexIn i) {
vertexOut o;
...
// calculate world position
o.worldPos = mul(unity_ObjectToWorld,i.pos);
return o;
}
几何=>片段 (由于您只是在顶点周围创建了一个小三角形,因此可以用原始顶点中的一个来近似新顶点的世界位置。如果不希望这样做,则必须在循环内计算3个单独的世界位置。)
struct geomOut {
float4 pos : POSITION;
float4 color : COLO0R;
float3 normal : NORMAL;
float3 worldPos : TEXCOORD0;
};
void geom(point vertexOut IN[1],inout TriangleStream<geomOut> OutputStream) {
...
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) / 2.;
// Simply use the input vertex world position. This might result in unclear cube edges.
OUT.worldPos = IN[0].worldPos;
OutputStream.Append(OUT);
}
}
现在您可以添加剪贴代码
float3 boxPosition = mul(_WorldToBox,float4(IN.worldPos,1));
clip(boxPosition + 0.5);
clip(0.5 - boxPosition);
和片段着色器的_WorldToBox
属性。
您还需要c#scipt将矩阵传递给着色器。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。