Setting Vertex Position From Texure

Hello,

I am trying to set some vertex coordinates form values that I get from a texture:

Shader "Custom/ParticleDisp" {
    Properties {
        _posTex("posTex", 2D) = "black" { }
    }
   
    SubShader {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
       
        Pass {
            LOD 200
            Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
           
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
               
                #include "UnityCG.cginc"
               
                sampler2D _posTex;
               
                struct vIn {
                    float4 pos : POSITION;
                    float4 col : COLOR;
                };
               
                struct v2f {
                    float4 pos : SV_POSITION;
                    float4 col : COLOR;
                };
               
                v2f vert(vIn v) {
                    v2f o;
                   
                    float4 uv = float4(v.pos.x, v.pos.y, 0.0, 0.0);
                    float3 pos = tex2Dlod(_posTex, uv).rgb;
                   
                    o.pos = mul(UNITY_MATRIX_MVP, pos);
                   
                    //o.pos = mul(UNITY_MATRIX_MVP, v.pos);
                    o.col = v.col;
                   
                    return o;
                }
               
                float4 frag(v2f i) : SV_Target {
                    return i.col;
                }
            ENDCG
        } 
    }
}

However, all I get is a single dot in the middle of my display, not even located at 0,0,0 in world-space.

Each vertex in the mesh is given x and y coordinates that correspond to the UV coordinates that they should use from the position texture.

I am just not sure how to send the vertex coordinates that I read from the texture down the pipeline.

Can anyone help me? (full project attached to this post if you want to tinker)

2128295–140003–Particles.zip (668 KB)

I am trying to replicate this project: One Million Particles by Robert Oram - Experiments with Google

So, perhaps I should provide a bit more info.

When using this vertex shader, I get a nice grid of the vertices as initially set up:

                v2f vert(vIn v) {
                    v2f o;
                 
                    o.pos = mul(UNITY_MATRIX_MVP, v.pos);
                    o.col = v.col;
                 
                    return o;
                }

I know the texture data is being read because I can change the vertex shader to display the colors from the position data texture:

                v2f vert(vIn v) {
                    v2f o;
                 
                    o.pos = mul(UNITY_MATRIX_MVP, v.pos);
                 
                    float4 uv = float4(v.pos.x, v.pos.y, 0.0, 0.0);
                    o.col = float4(tex2Dlod(_posTex, uv).rgb, 1.0);
                 
                    return o;
                }

However, when I try to set the vertex position to the color from the position texture, I see nothing:

                v2f vert(vIn v) {
                    v2f o;
                 
                    float4 uv = float4(v.pos.x, v.pos.y, 0.0, 0.0);
                    float3 pos = tex2Dlod(_posTex, uv).rgb;
                 
                    o.pos = mul(UNITY_MATRIX_MVP, pos);
                 
                    o.col = v.col;
                 
                    return o;
                }

So I must be setting the vertex position incorrectly. Any ideas? Google is being quite unhelpful today…

2129849--140135--Grid.png



2129849–140138–Particles Project.zip (751 KB)

               struct vIn {
                    float4 pos : POSITION;
                    float4 col : COLOR;
                    float2 uv : TEXCOORD0;
                };

I pass it down the pipeline from the input, the UV coordinate from the mesh ends up in TEXCOORD0, but I prefer to do my coloring from the texture in the fragment function because it applies on a per pixel rather than a per vertex.

But how to I move the vertices (or just provide new vertex positions) in the shader?

What do you mean how do you move the vertices? You mean like modify the position of the vertex during the vert function? If so you can just add things onto v.pos before you multiply it with the matrix

Ahhh, I think I figured it out. This version of the shader works:

Shader "Custom/ParticleDisp" {
    Properties {
        _posTex("posTex", 2D) = "black" { }
    }
   
    SubShader {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
       
        Pass {
            LOD 200
            Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
           
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
               
                #include "UnityCG.cginc"
               
                sampler2D _posTex;
               
                struct vIn {
                    float4 pos : POSITION;
                    float4 col : COLOR;
                    float2 uv : TEXCOORD0;
                };
               
                struct v2f {
                    float4 pos : SV_POSITION;
                    float4 col : COLOR;
                };
               
                v2f vert(vIn v) {
                    v2f o;
                   
                    o.pos = mul(UNITY_MATRIX_MVP, tex2Dlod(_posTex, float4(v.uv.xy, 0.0, 0.0)));
                    o.col = v.col;
                   
                    return o;
                }
               
                float4 frag(v2f i) : SV_Target {
                    return i.col;
                }
            ENDCG
        }
    }
}

Yes, the other alternative is to use the tex look up in the frag function because then if a color changes part way through it should update smoothly across all the pixels (at least from what I understand)

You could switch the frag to look like this:

                float4 frag(v2f i) : COLOR {
                    return tex2D(_posTex, i.uv);
                }

I set each vertex’s color separately when the mesh is created and each vertex shows up as a single pixel, so I just need it per-vertex.

By the way, this is what I am working on (make sure you enlarge it):

The particle system can handle 16777216 particles, all on the GPU. I think the session above was 1048576 particles cruising at a silky 1300 FPS. (not a typo)

My latest version is attached if you want to use it!

2130249--140180--Stars.png
2130249–140181–Particles.zip (1.13 MB)

1 Like

Now I just need to be rendering billboards instead of points and this will be golden! (then I can lose the reliance on OpenGl) When will point size (gl_pointSize) be supported on all platforms? :eyes:

I’ll have to initialize 4 times as many vertices (plus two triangles per point). I think I can use the secondary UV coordinates to assign corners to the vertices.

After that it is just a matter of reading in a particle texture for which I may need to do some more research.

If you have any suggestions on how this can be made better, please tell me.