3
\$\begingroup\$

I want to write the information from my shader into a texture and save it in a png.

I found this:

http://forum-old.unity3d.com/threads/save-texture-generated-by-a-shader.326561/

and this

System.IO.File.WriteAllBytes(Application.dataPath + "/"+"picture5886.png", texture2.EncodeToPNG());    //app path n1! 

But currently it seems to be unsolved.

Lets say I do Graphics.Blit(src,temp,mat) into a "tempTexture". I would have the temp texture then somewhere in my world, right?. How can I save that into a png?

\$\endgroup\$
7
\$\begingroup\$

First you need to get your shader's output into a Texture2D, so create one of the appropriate size. You'll commonly want ARGB32 format and no mipmaps:

Texture2D outputTex = new Texture2D(width, height, TextureFormat.ARGB32, false)

If the content you want to save has already been rendered by a camera in the scene, you can skip ahead (although in this case Unity's screenshot features may be a shorter route to your goal if you don't need anything fancy)

If you want to use an off-screen buffer instead, we'll need to create a RenderTexture to write it into.

RenderTexture buffer = new RenderTexture(
                               width, 
                               height, 
                               0,                            // No depth/stencil buffer
                               RenderTextureFormat.ARGB32,   // Standard colour format
                               RenderTextureReadWrite.Linear // No sRGB conversions
                           );

(Assuming you don't need a depth/stencil buffer and don't want to work in sRGB - otherwise, use the parameters that are right for your use case)

Now we bind our RenderTexture and material/shader pass, and run our shader across every pixel.

Graphics.Blit(sourceTexture, buffer, material, passIndex);

If your shader doesn't require texture input, you might need to supply a dummy texture for sourceTexture - I haven't tested how it handles null there. ;)

Now we need to copy the data out of the current render target (whether it was the buffer we created above, or one used internally by a scene camera) and into our outputTex:

RenderTexture.active = buffer;           // If not using a scene camera
outputTex.ReadPixels(
          new Rect(0, 0, width, height), // Capture the whole texture
          0, 0,                          // Write starting at the top-left texel
          false                          // No mipmaps
);

Now you can use outputTex.EncodeToPNG() and write the results to a file as described in the question. You should use persistentDataPath rather than dataPath if this is something you're doing at runtime though - dataPath is not guaranteed to be a writeable location in a release build.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.