Search Unity

Blitting Shader getting damaged results

Discussion in 'Shaders' started by Void24, Oct 9, 2015.

  1. Void24

    Void24

    Joined:
    Oct 15, 2013
    Posts:
    50
    I have a shader I wrote specifically for manual blit calls (procedural texturing). I am bypassing linear sampling, but no matter what I do, My results get darkened a bit each time I blit.

    I am just outputting exactly my read texture with no lighting operations at all.

    What is going on that is damaging data during the render process?

    I am out of ideas on what I am doing wrong.
     
  2. Void24

    Void24

    Joined:
    Oct 15, 2013
    Posts:
    50
    If anyone would like to test, Make a dynamic texture tex, RenderTexture texRender, and nolighting shader texBlit, then loop this:

    Graphics.Blit(tex, texRender, texBlit);
    tex.ReadPixels(new Rect(0, 0, 1024, 1024), 0, 0);
    tex.Apply(false);

    You are going to end up all black after a few dozen iterations. Where is the data getting degraded?
     
  3. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    What shader exactly are you using? I understand it's unlit, but it's still likely the shader causing this. Also note that ReadPixels is horribly slow, so avoid it at all costs in your end-product.
     
  4. Void24

    Void24

    Joined:
    Oct 15, 2013
    Posts:
    50
    Thanks for the response Gambit, My shader is not altering the inputs at all. Think "return tex2D(_MainTex, i.uvmain.xy);" in the frag shader. It still gets darker and darker with each iteration. It is not a linear light issue either, as using pow 2.2 and pow 1/2.2 both cause even worse degradation.

    As for ReadPixels, this is for procedurally generating textures by layering them at level load time. If you know of a way to do this without ReadPixels, I would be happy to switch to a new method!

    I found that multiplying the texture input by 1.02 reduces the problem a lot. This will work at the moment, but it is a pretty silly problem to have.
     
  5. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    This is a really strange issue... I've made a few games that call Graphics.Blit only when certain effects are going off (distortion and such). I see no change in the full-screen texture when I start/stop calling Graphics.Blit each frame. Inside what function are you calling Graphics.Blit? Is this a component on a camera?

    If you're just doing it at load time that's fine, it's just not something you'd want to do every frame. Normally when you give graphics commands, the GPU carries out those commands while the CPU continues (framerate = max(GPU, CPU)). When you call ReadPixels, the CPU must wait for the GPU to catch up, then the GPU must wait for the CPU to finish reading the pixels (thus, framerate = GPU + CPU).
     
  6. Void24

    Void24

    Joined:
    Oct 15, 2013
    Posts:
    50
    It is triggered during a Start() event, but I have moved it around a bit and had no change in results. I only have one camera. The component that does the blitting is not attached to the camera, and is blitting to an off screen render texture. The effect is only 0.02% though, so in a distortion shader you likely would not notice. I only started noticing when I started re-blitting my output many times (20-50 times). It is especially evident in procedural normal maps. If I put my blit in a coroutine, you can actually see the normals getting distorted very slowly.
     
  7. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Make sure you aren't blending (and if you need to blend, try it without blending to see if that helps). Make sure your render texture is using "no filtering".

    I'm running out of ideas, but I think the RenderTexture is what causes the problem. Maybe as a test, you could pass a solid color texture into the shader (like a solid red texture), then after your tex2D() call to sample, use the step() function to see if your color channels are any less than they should be. (so if you have a solid red texture, use something like step(color.r, 0.999) and output the result). This will clearly tell you if tex2D() returns your darkened values, or if the darkening happens after that.