Search Unity

Setting Vertex Position From Texure

Discussion in 'Shaders' started by tbg10101_, May 26, 2015.

  1. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    Hello,

    I am trying to set some vertex coordinates form values that I get from a texture:
    Code (CSharp):
    1.  
    2. Shader "Custom/ParticleDisp" {
    3.     Properties {
    4.         _posTex("posTex", 2D) = "black" { }
    5.     }
    6.    
    7.     SubShader {
    8.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    9.        
    10.         Pass {
    11.             LOD 200
    12.             Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
    13.            
    14.             CGPROGRAM
    15.                 #pragma vertex vert
    16.                 #pragma fragment frag
    17.                
    18.                 #include "UnityCG.cginc"
    19.                
    20.                 sampler2D _posTex;
    21.                
    22.                 struct vIn {
    23.                     float4 pos : POSITION;
    24.                     float4 col : COLOR;
    25.                 };
    26.                
    27.                 struct v2f {
    28.                     float4 pos : SV_POSITION;
    29.                     float4 col : COLOR;
    30.                 };
    31.                
    32.                 v2f vert(vIn v) {
    33.                     v2f o;
    34.                    
    35.                     float4 uv = float4(v.pos.x, v.pos.y, 0.0, 0.0);
    36.                     float3 pos = tex2Dlod(_posTex, uv).rgb;
    37.                    
    38.                     o.pos = mul(UNITY_MATRIX_MVP, pos);
    39.                    
    40.                     //o.pos = mul(UNITY_MATRIX_MVP, v.pos);
    41.                     o.col = v.col;
    42.                    
    43.                     return o;
    44.                 }
    45.                
    46.                 float4 frag(v2f i) : SV_Target {
    47.                     return i.col;
    48.                 }
    49.             ENDCG
    50.         }
    51.     }
    52. }
    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)
     

    Attached Files:

    Last edited: May 27, 2015
  2. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
  3. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    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:
    Code (CSharp):
    1.                 v2f vert(vIn v) {
    2.                     v2f o;
    3.                  
    4.                     o.pos = mul(UNITY_MATRIX_MVP, v.pos);
    5.                     o.col = v.col;
    6.                  
    7.                     return o;
    8.                 }


    I know the texture data is being read because I can change the vertex shader to display the colors from the position data texture:
    Code (CSharp):
    1.                 v2f vert(vIn v) {
    2.                     v2f o;
    3.                  
    4.                     o.pos = mul(UNITY_MATRIX_MVP, v.pos);
    5.                  
    6.                     float4 uv = float4(v.pos.x, v.pos.y, 0.0, 0.0);
    7.                     o.col = float4(tex2Dlod(_posTex, uv).rgb, 1.0);
    8.                  
    9.                     return o;
    10.                 }


    However, when I try to set the vertex position to the color from the position texture, I see nothing:
    Code (CSharp):
    1.                 v2f vert(vIn v) {
    2.                     v2f o;
    3.                  
    4.                     float4 uv = float4(v.pos.x, v.pos.y, 0.0, 0.0);
    5.                     float3 pos = tex2Dlod(_posTex, uv).rgb;
    6.                  
    7.                     o.pos = mul(UNITY_MATRIX_MVP, pos);
    8.                  
    9.                     o.col = v.col;
    10.                  
    11.                     return o;
    12.                 }


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

    Attached Files:

    Last edited: May 27, 2015
  4. Sessional

    Sessional

    Joined:
    Apr 21, 2013
    Posts:
    45
    Code (CSharp):
    1.                struct vIn {
    2.                     float4 pos : POSITION;
    3.                     float4 col : COLOR;
    4.                     float2 uv : TEXCOORD0;
    5.                 };
    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.
     
  5. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    But how to I move the vertices (or just provide new vertex positions) in the shader?
     
  6. Sessional

    Sessional

    Joined:
    Apr 21, 2013
    Posts:
    45
    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
     
  7. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    Ahhh, I think I figured it out. This version of the shader works:
    Code (CSharp):
    1. Shader "Custom/ParticleDisp" {
    2.     Properties {
    3.         _posTex("posTex", 2D) = "black" { }
    4.     }
    5.    
    6.     SubShader {
    7.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    8.        
    9.         Pass {
    10.             LOD 200
    11.             Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
    12.            
    13.             CGPROGRAM
    14.                 #pragma vertex vert
    15.                 #pragma fragment frag
    16.                
    17.                 #include "UnityCG.cginc"
    18.                
    19.                 sampler2D _posTex;
    20.                
    21.                 struct vIn {
    22.                     float4 pos : POSITION;
    23.                     float4 col : COLOR;
    24.                     float2 uv : TEXCOORD0;
    25.                 };
    26.                
    27.                 struct v2f {
    28.                     float4 pos : SV_POSITION;
    29.                     float4 col : COLOR;
    30.                 };
    31.                
    32.                 v2f vert(vIn v) {
    33.                     v2f o;
    34.                    
    35.                     o.pos = mul(UNITY_MATRIX_MVP, tex2Dlod(_posTex, float4(v.uv.xy, 0.0, 0.0)));
    36.                     o.col = v.col;
    37.                    
    38.                     return o;
    39.                 }
    40.                
    41.                 float4 frag(v2f i) : SV_Target {
    42.                     return i.col;
    43.                 }
    44.             ENDCG
    45.         }
    46.     }
    47. }
     
  8. Sessional

    Sessional

    Joined:
    Apr 21, 2013
    Posts:
    45
    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:
    Code (CSharp):
    1.  
    2.                 float4 frag(v2f i) : COLOR {
    3.                     return tex2D(_posTex, i.uv);
    4.                 }
     
  9. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    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!
     

    Attached Files:

    Last edited: May 27, 2015
    Jose_Martinez likes this.
  10. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    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? o_O

    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.