Search Unity

Returning per-pixel calculation results within the color values of a vertex/fragment shader

Discussion in 'Shaders' started by mcm2020, Jul 22, 2019.

  1. mcm2020

    mcm2020

    Joined:
    Jun 6, 2019
    Posts:
    1
    This is a problem I've been trying to attack for a while now, so any help would be appreciated.

    I need to do some per-pixel calculations between subsequent frames. I'm trying to do this calculation in a vertex/fragment shader since otherwise, I would need to use a double-for loop to iterate through all the pixels.

    I've gotten to the point where I can pass in the previous frame as a sampler2D object in cg/hlsl, and perform calculations between the current and previous frames for each same pixel location.

    However, I'd like to return the pixel coordinates back to the CPU (plus some other values). I was thinking of doing this by returning them as actual 'color' values at the end of the frag function. For example, setting the red value to be the x coordinate and the green value to be the y coordinate. This is not possible, however, since I can only return values between 0-1 in the frag function. Is there another way to accomplish what I'm trying to do? Thanks.
     
  2. Namey5

    Namey5

    Joined:
    Jul 5, 2013
    Posts:
    188
    It's absolutely possible to return those values in a regular shader pass. If you really need the raw values, you can use an HDR/floating-point texture format for the output, which includes values outside of that range.

    You could also format the values into a range of 0-1 and then unformat them when reading, i.e.

    Code (CSharp):
    1. //In your initial shader, where col is your output
    2. return 1.0 - exp (-col);
    3.  
    4. //Then, when you need to access those values
    5. value = -log (1.0 - col + 1e-6);
    6. //The '+ 1e-6' is an epsilon value to make sure we aren't taking the log of 0
    You will lose some precision in the second method, but you won't have to use a more memory consuming format.
     
    PrimalCoder likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Really it sounds like what you want to do is render to a floating point render texture using a replacement shader pass. Fragment shaders are unbounded in their output range (within IEEE 754 single precision floating point numerical limits), it's only the render target's format that limits the stored range. By default that's probably going to be an RGBA 32 bit render texture, which really means 8 bits or one byte per color channel, or a value range of 0.0 to 1.0 with 256 steps.

    If you render to an HDR render target, that defaults to an ARGBHalf render texture, which uses 16 bits per color channel, or a -65520.0 to +65520 floating point range (meaning the precision changes with how big or small the number is).
     
    PrimalCoder likes this.