[英]Mapping a texture to a Pointcloud in Unity
我有一个专有的点云文件,然后将其转换为在 Unity 中显示的网格。 网格由点云的每个点所在的顶点组成。 我正在尝试以纹理与点 100% 对齐的方式将纹理 map 到点云。 我正在尝试使用着色器来完成此操作,但似乎我没有足够的知识来做到这一点。 我以前从未使用过点云和着色器,所以我真的很难做到这一点。
纹理和点云的 x 和 y 大小相同,比例为 16:10 (1920x1200)
我从在assetStore 上找到的着色器资产中获得了灵感。 据我所知,着色器在网格中的每个顶点上创建一个小四边形,然后获取 UV map 信息并将纹理映射到点。 我从互联网上下载了 UV map,它应该是中性的,在映射纹理时没有修改:
我目前的结果并不好。 默认情况下,纹理在 x 和 y 轴上都放大大约 2 倍。 当手动调整两个轴的比例和偏移量时,我可以获得一些正确的结果,但只能在图像的一部分上。 然后其他部分需要不同的偏移/比例组合。 我尝试了很多事情都没有成功,但我很确定解决方案在于着色器代码,因为其他修改对纹理映射过程没有影响。
由于我不能向您展示该项目的所有细节,因为它是机密的,所以这个问题可能很难回答。 幸运的是,我可以向您展示着色器代码:
Properties {
[NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
[NoScaleOffset]_UVMap ("UV", 2D) = "white" {}
_TexScaleH("Uv texture scaler H", Float) = 1.0
_TexScaleV("Uv texture scaler V", Float) = 1.0
_PointSize("Point Size", Float) = 4.0
_Color("PointCloud Color", Color) = (1, 1, 1, 1)
_OffsetH("Horizontal offset", Float) = 0.0
_OffsetV("Vertical offset", Float) = 0.0
}
SubShader
{
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#pragma shader_feature USE_DISTANCE
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
float _PointSize;
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float _OffsetH;
float _OffsetV;
sampler2D _UVMap;
float4 _UVMap_TexelSize;
float _TexScaleH;
float _TexScaleV;
struct g2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
[maxvertexcount(4)]
void geom(point v2f i[1], inout TriangleStream<g2f> triStream)
{
g2f o;
float4 v = i[0].vertex;
float2 uv = v.xy;
uv.x = -uv.x;
uv.y = -uv.y;
float2 p = _PointSize * 0.001;
p.y *= _ScreenParams.x / _ScreenParams.y;
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(-p.x, p.y, 0, 0) * o.vertex.w;
o.uv = uv * float3(_TexScaleH,_TexScaleV,0) + float3(_OffsetH,_OffsetV,0);
triStream.Append(o);
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(-p.x, -p.y, 0, 0) * o.vertex.w;
o.uv = uv * float3(_TexScaleH, _TexScaleV, 0) + float3(_OffsetH, _OffsetV, 0);
triStream.Append(o);
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(p.x, p.y, 0, 0) * o.vertex.w;
o.uv = uv * float3(_TexScaleH, _TexScaleV, 0) + float3(_OffsetH, _OffsetV, 0);
triStream.Append(o);
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(p.x, -p.y, 0, 0) * o.vertex.w;
o.uv = uv * float3(_TexScaleH, _TexScaleV, 0) + float3(_OffsetH, _OffsetV, 0);
triStream.Append(o);
}
v2f vert (appdata v)
{
v2f o;
o.vertex = v.vertex;
o.uv = v.uv;
return o;
}
fixed4 frag (g2f i) : SV_Target
{
float2 uv = tex2D(_UVMap, i.uv);
if(any(uv <= 0 || uv >= 1))
discard;
return tex2D(_MainTex, uv) * _Color;
}
ENDCG
}
}
}
在 web 上的 Unity 中没有很多关于着色器编码的信息,也没有关于点云的信息,所以我现在有点迷路了。
请在下面告诉我您对我可以更改哪些内容来解决问题的想法。
好吧,我找到了一种方法,但结果并不是我需要的 100%。
Shader "shaderexample"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_PointSize("Point size", Float) = 1.0
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float _PointSize;
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
struct g2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_full v)
{
v2f o;
float4 vertex = mul(unity_ObjectToWorld, v.vertex);
o.vertex = mul(UNITY_MATRIX_VP, vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag(g2f i) : SV_Target
{
fixed4 color = tex2D(_MainTex, i.texcoord);
return color;
}
ENDCG
}
}
}
现在每个点都与纹理正确对齐。 现在我需要将此功能与我的另一个功能结合起来,即放大网格的每个顶点。 变量 _PointSize 应该确定每个顶点应该有多大。 我尝试使用前面显示的代码在顶点位置创建小四边形。 有谁知道如何结合这两个功能?
maxvertexcount(4)]
void geom(point v2f i[1], inout TriangleStream<g2f> triStream)
{
g2f o;
float4 v = i[0].vertex;
float2 p = _PointSize * 0.001;
p.y *= _ScreenParams.x / _ScreenParams.y;
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(p.x, p.y, 0, 0) * o.vertex.w;
triStream.Append(o);
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(p.x, -p.y, 0, 0) * o.vertex.w;
triStream.Append(o);
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(-p.x, p.y, 0, 0) * o.vertex.w;
triStream.Append(o);
o.vertex = UnityObjectToClipPos(v);
o.vertex += float4(-p.x, -p.y, 0, 0) * o.vertex.w;
triStream.Append(o);
}
这是着色器的几何部分,它应该为每个顶点创建小四边形。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.