Search Unity

pass world position to shader using Graphics.Blit.

Discussion in 'Shaders' started by AlexTemina, Feb 5, 2016.

  1. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    Hi!

    Is there a way to pass the world position to a Shader when using Graphics.Blitt?
    I cannot pass it a parameter because I want to know the world position of each pixel.
     
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Then use vertex-fragment shaders. If you write world position of vertex in vertex shader output, in fragment shader you will get world position of fragment as input. And in vertex shader world position is just local position multiplied by unity matrices.

    EDIT: just seen your other post.
    How exactly do you get where you want to render that texture? Because world position will depend heavily on that.
     
  3. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    I am using a vertex-fragment shader. How do I write the world position of the vertex in the shader output?
     
  4. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    For blit you can add model matrix to uniforms (in subshader section of shader "uniform float4x4 _matrix;"), set that matrix directly using Material.SetMatrix("_matrix",...) to set it from object's transform matrix you want and in shader mul(_matrix, v.vertex);

    And in general use case(not suitable for Graphics.Blit using a shader as it will always have positions of 0 and 1s)...
    Something like
    Code (CSharp):
    1. o.worldPos= mul(_Object2World, v.vertex);
    This should translate vertice from model coordinates that are usually input for shader into world coordinates.
    I recommend reading about model view projection matrices. _Object2World is model matrix; UNITY_MATRIX_MV is modelview matrix; and UNITY_MATRIX_MVP is model view projection matrix ( If I remember right multiplication is P*V*M)...
     
    Last edited: Feb 5, 2016
  5. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    Awesome! it works! now the only problem is that the position is not completely perfect... it goes some points offset, and I don't know why...
     
  6. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Blit uses quads with (0,0,0), (1,0,0), (1,1,0), (0,1,0) positions afaik while your objects might have its own points offsets(model-space-wise). If you know how to transform your object(quad/plane I assume?) into those coordinates using transformation matrix, you might want to include its inverse matrix into that _matrix.
     
  7. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    ok... that I didn't get. My object can be a lot of things (Always with a renderer, but It can be a plance, a sprite or a mesh so far), I'm blitting the "Fog" into all textures that are going to be fix in the game. My game is 2D lateral scroll.
    So basically I'm doing:



    Code (CSharp):
    1.  
    2. Matrix4x4 transform_matrix = rend.localToWorldMatrix;
    3.  
    4. Sprite cold_sprite = BakeFog( object_depth_, composer.baseColdSprite, composer.coldSprite, transform_matrix, true );
    5.  
    6.     private static Sprite BakeFog( float object_depth_, Sprite base_sprite, Sprite sprite, Matrix4x4 transform_matrix_, bool is_cold )
    7.     {
    8.         if( !base_sprite )
    9.         {
    10.             base_sprite = sprite;
    11.         }
    12.  
    13.         Texture2D warm_texture = base_sprite.texture;
    14.         Texture2D warm_texture_fogged = warm_texture;
    15.         if( _ShouldFog( object_depth_ ) )
    16.         {
    17.             warm_texture_fogged = BlitFog( object_depth_, warm_texture, transform_matrix_, is_cold );
    18.         }
    19.         warm_texture_fogged.name = warm_texture.name;
    20.         sprite = Sprite.Create( warm_texture_fogged, base_sprite.rect, base_sprite.pivot, base_sprite.pixelsPerUnit );
    21.         sprite.name = base_sprite.name;
    22.  
    23.         return sprite;
    24.     }
    25. ;
     
  8. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Blitting is just processing of texture that is loaded in GPU using a shader to get a rendertexture.
    It doesn't have positions of vertices in model space as it lacks model context. So when you transform it using transform's matrix, you only move, scale and rotate "unit quad"(like unit vector, but quad), not the real quad/object you have. So if your quad has model-space coordinates other than that "unit quad" as I call it you will get different result. That's what I'm saying.

    So if your object is quad or 2D collection of quads, it should give acceptable results, but if your object is 3D I doubt it will as it'll just "flatten" it and then blit.