Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

pixel color in frag from screen position.

Discussion in 'Shaders' started by Quatum1000, Nov 17, 2014.

  1. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    Hi everyone,
    I want to get the pixel color inside of a frag shader after the lightning and shadowing pass.

    + In the first pass the surf shader draws a simple diffuse map.
    + In the second pass I want to change the color based of the object that has already lighting and shadows on.

    Is there any chance to get the pixel color of the already rendered mesh from pass1 with light and shadows?
    Would that work with ComputeScreenPos() ? But I dont how to get the pix color from the o.screenPos in frag.


    Code (csharp):
    1.  
    2.  
    3. /// Pass 2nd ///
    4.  
    5. ...... snip snip .....
    6.  
    7. Pass{
    8.    
    9. CGPROGRAM
    10. #pragma vertex vert
    11. #pragma fragment frag
    12. #include "UnityCG.cginc"
    13.  
    14. struct v2f {
    15.        float4 pos  : SV_POSITION;
    16.        float4 screenPos  : TEXCOORD0;
    17. };
    18.  
    19. v2f vert(appdata_base v){
    20.    v2f o;
    21.    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    22.    o.screenPos = ComputeScreenPos(o.pos);
    23.    return o;
    24. }
    25.  
    26. half4 frag(v2f i) : COLOR{
    27.  
    28.     return ??
    29. }
    30.  
    31. ENDCG  
    32. }
    33.  
    34.  
     
  2. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    No. Shaders are a one way street in this particular case. You're probably best off rendering to a texture and sampling that.
     
  3. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    Thanks.
    >>> You're probably best off rendering to a texture and sampling that.
    Would you so kind and explain a little more in this case?
     
  4. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I'd need much more precise information about what you're actually trying to do.

    "I want to get the pixel color inside of a frag shader after the lightning and shadowing pass."

    Which pixel though? Frag runs for every single pixel that gets drawn by this shader on that mesh on screen.
     
  5. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    A mesh is rendered with a simple diffuse shader. (nothing special)

    * And in a second pass I want to tint this object. (Blend the original mesh slightly to the tinting color). Based on some attributes.
    * The tinting function should overwrite all lightning and shadow attributes on the mesh.

    From my understanding, the frag() function in the reder pipeline is executed after lightning and shadoing pass on the mesh. Because after
    Code (csharp):
    1.  
    2. half4 frag(v2f i) : COLOR{
    3.    return float4(1,0,0,0); // All RED
    4. }
    5.  
    none of the "red" vertextes receiveing lights or shadows. So I thought, The frag() part would be able to overwrite the lighting and shadowing.
     
  6. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    ... The effect can be described with fog on a single mesh. Fading the object from its original texture color to the tint color.
     
  7. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    If you're using a fragment shader in this manner you need to blend the shadow yourself.

    In any case:

    Code (CSharp):
    1. fixed4 frag(v2f i):COLOR
    2. {
    3.     fixed4 red = fixed4(1,0,0,1);
    4.     fixed4 green = fixed4(0,1,0,1);
    5.     fixed4 result = Lerp(red, green, amount);
    6.     return result;
    7. }
    Where amount is a variable or varying you pass in. This would fade the object from it's original texture color to the tint color. In this case green would be tint and red would be texture.
     
  8. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    It's not the point to lerp some colors. The point is to get the vertex colors from the already rendered mesh for fixed4 red. For sure I know to lerp some colors.

    What do you mean with:

     
    Last edited: Nov 17, 2014
  9. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Vertex colour is calculated in vertex shader, not fragment shader.

    As for rendering to a texture and sampling that, it's similar to how you store gpu particle data, you write 4 floats per pixel to a texture, then you can read that right back out again, either in code or in another shader.

    I'm still not clear on your desired end result, and you can't read from a shader other than how i've described above with texture, unless you're using compute shaders.
     
  10. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    "...how you store gpu particle data, you write 4 floats per pixel to a texture, then you can read that right back out again, either in code or in another shader."

    Sorry the is too theoretically to me, I require somthing to work with or an example that helps to understand what you have in mind.

    Should be the result:



    After the object is fully blended, it does not receive light or taken shadows into account.
    So my idea was to use a frag() shader to blend to the final color.
    But as hippocoder told, it doesn't work.

    My last idea was to reduce the albedo and raise the emisson in the surf shader.
    But that doesnt work too, because the emission is affected by light also.
    It overcast to white on any special scenery behavior.

    Any other idea that could work?

    Thank you..
     
  11. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    I think the stencil buffer would be the best way to to this. There would be a few ways, each with its pros and cons and complexity.

    The simplest (without the stencil buffer) would be to render the cubes twice. The first time using the normal surface shader and then the second time using a non-surface shader with transparency and out putting a flat color. You could then adjust the transparency to control the amount of blending. The issue with this is that you will likely have depth fighting unless your frustum is quite small.

    A better why would be to do the same as above but get the first pass to write into the stencil buffer. On the second transparent pass set the depth test to always pass and the stencil test to pass only where the previous had written to. You would have the same effect but there will never be depth fighting.

    Another way would be to render the first pass like above writing into the stencil buffer. This time however dont draw every object a second time which obviously is going to double your draw calls. Instead draw a single full screen quad using the same second pass shader as above that only passes where the stencil has been written to. This way every object that wrote to the stencil buffer will be covered but you will only have one extra draw call. The down side is every object will be treated the same which makes it harder to apply a unique color to each cube but the stencil buffer does have 8 bit which in theory could give the option to apply 8 different colors.
     
  12. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    Thanks scrawk,
    Is your answer in that direction what hippocoder tries to reply, or is your solution comletely different to?


     
  13. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Its quite a different method.

    I though it would be easier to give you a example scene that explaining it.

    You can download the scene from the attached zip file.

    It should look like this...



    The are two materials, just the default diffuse but one writes 1 to the stencil buffer the other writes 2.

    The overlay script then draws 2 full scene quads with the first only being drawn where the stencil is 1 and outputting red the other only where the stencil is 2 and outputting blue.

    The cubes have the diffuseStencil1 material and the plane has the difuseStencil2 material.

    You can adjust the color and transparency on the overlay materials or press keypad +/- to adjust the transparency fro a script.
     

    Attached Files:

    Last edited: Nov 23, 2014