Search Unity

Applying a shader effect to sourse texture

Discussion in 'Shaders' started by Andrey_M, Oct 15, 2020.

  1. Andrey_M

    Andrey_M

    Joined:
    Oct 17, 2015
    Posts:
    7
    I create a shader that changes the parameters of the texture (brightness, saturation, etc.).
    After manipulating the image, I need to upload it in .png format. But the original image is preserved unchanged.

    qwest.jpg


    How to apply shader settings to original texture?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    You want to save a .png file with the modifications, correct?

    Shaders only apply on the GPU, so you need some way to copy the data from the GPU back to the CPU. To do that you need to render your material to a RenderTexture using a Blit(), then create a Texture2D with the same dimensions and format as the render texture and use ReadPixels() to copy the render texture to the CPU memory. Then you can use EncodeToPNG() to convert the image to a png and save the resulting data to disk.
     
    ElasticSea and Andrey_M like this.
  3. Andrey_M

    Andrey_M

    Joined:
    Oct 17, 2015
    Posts:
    7
    Right!
    Thanks for the answer
    I try to do as you advise, it turns out something similar, but not quite right
    What am I doing wrong?

    Code (CSharp):
    1. Image img = IMG.GetComponent<Image>();
    2.  
    3.             img.material = Instantiate(Resources.Load("ImageEffect") as Material);
    4.             img.material.SetFloat("_Brightness", bright);
    5.  
    6.             RenderTexture rTex = new RenderTexture(img.sprite.texture.width, img.sprite.texture.height, 16, RenderTextureFormat.ARGB32);
    7.             Graphics.Blit(img.material.mainTexture, rTex);
    8.  
    9.             Texture2D TX = new Texture2D(rTex.width, rTex.height);
    10.  
    11.             img.sprite.texture.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0, false);
    12.             img.sprite.texture.Apply();

    Apparently I am grabbing the texture incorrectly.
     
    Last edited: Oct 17, 2020
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Because you’re trying to grab the texture from a material you’re using on a UI element, which has no texture assigned. The texture being used in your example is the sprite assigned to the image component, which is setting the texture to use at runtime when displaying that UI component.

    For a Blit you need a Texture2D, not a sprite. Also you need to assign a material to use with the Blit otherwise it’s just making a copy of the original image unmodified.
     
    Andrey_M likes this.
  5. Andrey_M

    Andrey_M

    Joined:
    Oct 17, 2015
    Posts:
    7
    Here is code that seems to work but is not correct.
    Code (CSharp):
    1. RenderTexture buffer = new RenderTexture(img.sprite.texture.width, img.sprite.texture.height, 32, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
    2.  
    3.             Graphics.Blit(img.sprite.texture, buffer, img.material);
    4.  
    5.             img.sprite.texture.ReadPixels(new Rect(0, 0, img.sprite.texture.width, img.sprite.texture.height), 0, 0, false);
    6.             img.sprite.texture.Apply();
    I don’t understand what material should be used. The texture changes, but becomes either light or dark
     

    Attached Files: