简体   繁体   English

在 Unity 中将纹理映射到点云

[英]Mapping a texture to a Pointcloud in Unity

I have a proprietary point cloud file that is then converted into a mesh that is displayed in Unity.我有一个专有的点云文件,然后将其转换为在 Unity 中显示的网格。 The mesh consists of vertices where each point of the point cloud is.网格由点云的每个点所在的顶点组成。 I'm trying to map the texture to the point cloud in a way that the texture aligns with the points 100%.我正在尝试以纹理与点 100% 对齐的方式将纹理 map 到点云。 I'm trying to accomplish this with a shader, but it seems that I don't have enough knowledge to do this.我正在尝试使用着色器来完成此操作,但似乎我没有足够的知识来做到这一点。 I've never worked with point clouds and shaders before, so I'm really struggling to do this.我以前从未使用过点云和着色器,所以我真的很难做到这一点。

The texture and the point cloud are the same x and y size and the ratio is 16:10 (1920x1200)纹理和点云的 x 和 y 大小相同,比例为 16:10 (1920x1200)

I've taken inspiration from an asset I found on the assetStore for the shader.我从在assetStore 上找到的着色器资产中获得了灵感。 To my knowledge, the shader creates a small quad on every vertex in the mesh and then takes the UV map information and maps the texture to the points.据我所知,着色器在网格中的每个顶点上创建一个小四边形,然后获取 UV map 信息并将纹理映射到点。 I downloaded the UV map from the internet, it should be neutral with no modifications when mapping the texture:我从互联网上下载了 UV map,它应该是中性的,在映射纹理时没有修改:

UV Map that I use我使用的UV Map

My current result is not good.我目前的结果并不好。 By default, the texture is zoomed-in roughly 2x on both the x and y-axis.默认情况下,纹理在 x 和 y 轴上都放大大约 2 倍。 When manually adjusting the scale and the offset for both of the axes, I can get a somewhat correct result but only on one part of the image.当手动调整两个轴的比例和偏移量时,我可以获得一些正确的结果,但只能在图像的一部分上。 The other parts then need a different offset/scale combination.然后其他部分需要不同的偏移/比例组合。 I tried a lot of things with no success, but I'm pretty sure that the solution lies in the shader code since other modifications have no effect on the texture mapping process.我尝试了很多事情都没有成功,但我很确定解决方案在于着色器代码,因为其他修改对纹理映射过程没有影响。

Since I can't show you all the details of the project because it is confidential, the question is probably hard to answer.由于我不能向您展示该项目的所有细节,因为它是机密的,所以这个问题可能很难回答。 Fortunately I can show you the shader code:幸运的是,我可以向您展示着色器代码:

    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
        }
    }
}

There is not a lot of information on shader coding in Unity on the web, neither is there about point clouds so I'm kind of lost right now.在 web 上的 Unity 中没有很多关于着色器编码的信息,也没有关于点云的信息,所以我现在有点迷路了。

Let me know your thoughts down below on what things can I change in order to fix the issue.请在下面告诉我您对我可以更改哪些内容来解决问题的想法。

Well I found a way to do it, but the result is not 100% what I need.好吧,我找到了一种方法,但结果并不是我需要的 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
    }
}

} }

Now every point is correctly aligned to the texture.现在每个点都与纹理正确对齐。 Now I need to combine this functionality with my other one, and that is to enlarge every vertex of the mesh.现在我需要将此功能与我的另一个功能结合起来,即放大网格的每个顶点。 Variable _PointSize should determine how large each vertex should be.变量 _PointSize 应该确定每个顶点应该有多大。 I tried to use the code shown earlier that creates the small quads on the vertex positions.我尝试使用前面显示的代码在顶点位置创建小四边形。 Does anyone know how to combine these two functionalities?有谁知道如何结合这两个功能?

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);
}

This is the geometry part of the shader which should create small quads for each vertex.这是着色器的几何部分,它应该为每个顶点创建小四边形。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM