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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How to use Graphics.Blit: Draw-Modify texture by GPU

Discussion in 'General Graphics' started by IsGreen, Apr 24, 2015.

  1. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    I'm trying to modify a texture, replace a color, change its alpha channel, ... by GPU, instead of using Texture2D SetPixel and GetPixel.

    In unity answer comment that can be done with Graphics.Blit, but not get it to work.

    This is the code:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class GraphicsBlit : MonoBehaviour {
    4.  
    5.     public Texture texture;
    6.     public Material material;
    7.     public RenderTexture renderTexture;
    8.  
    9.     private Rect rect = new Rect(0f,0f,200f,200f);
    10.  
    11.     void Start () {
    12.  
    13.         Graphics.Blit(this.texture,this.renderTexture,Instantiate<Material>(this.material));
    14.          
    15.     }
    16.  
    17.  
    18.     void OnGUI() {
    19.  
    20.         GUI.DrawTexture(this.rect,this.renderTexture);
    21.  
    22.     }
    23.  
    24. }
    25.  
    Attach project that I am using.
     

    Attached Files:

    Ben-BearFish likes this.
  2. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    @IsGreen Any luck using Graphics.Blit? I was hoping to implement something similar.
     
  3. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    Nothing.
     
  4. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,005
    Change your material to use an unlit shader and it should work.
     
  5. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    To be or not to be, that is the question.

    No poetry, please. Do not speculate.
     
  6. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,005
    Ok then, it did work for me, but since I don't know exactly what you are trying to do I didn't want to say it will work in all cases (e.g. I did not test every rendering path). Probably took you longer to post that reply than to have tested to confirm it works for you too.

    Would seem to make sense, since what would the lighting set up be when blitting? My guess is that lighting is simply ignored, thus if you use a shader that requires lighting you'll get a black result.
     
    jmunozar likes this.
  7. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    Whats exactly do you do with an unlit shader?

    The unlit shader doesn't apply a color.

    I'm looking to create an effect (color, brightness, contrast, bloom, blur, ...) to a texture, for use in the UI or GUI system.
     
    Last edited: May 27, 2015
  8. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,005
    Unlit Color Shader applies a color. But for any of those effects you mention you'll have to write a shader to apply that via the material that you are blitting. Point is don't use shaders that rely on lighting information as it would appear none is available ( since it doesn't make much sense in the context of a blit ), when you do you just get black.

    I'd recommend taking a look at the image effect code in the standard assets package as a good starting point.
     
    Last edited: May 27, 2015
  9. AlexBM

    AlexBM

    Joined:
    Mar 26, 2015
    Posts:
    16
    Clear depth buffer of render texture first. Or add in your shader ZTest Always flag and blend function One Zero.
    Also don't use Standard shader for such purposes. As Noisecrime noted, it's heavily dependent on lightning, which is obviously isn't used in Blit method. Create your own, use Unlit/Texture one, or just use Blit without any material at all

    So one of the ways to make your example work is to rewrite your start like this:

    Code (CSharp):
    1. RenderTexture.active = renderTexture;
    2. GL.Clear (true, true, Color.black);
    3. Graphics.Blit(this.texture,this.renderTexture);
     
    Last edited: May 27, 2015
    henners999, Oxygeniium and brokenm like this.
  10. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    Thank you for your interest. This was an issue that had left.

    But again, with unlit shader you can not change the texture.

    I tried, and can also use the Sprite shader. But there is only the option to change the color of the texture.

    Really, Graphics.Blit is not for this. Can`t apply normal maps, etc...

    Finally, I created an image capture using the targetTexture of a camera that use a quad to render the material.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. namespace Custom{
    5.  
    6.     public class Texture : MonoBehaviour {
    7.      
    8.         public Camera textureCamera;
    9.         public MeshRenderer quadRenderer;
    10.      
    11.         public static Custom.Texture Camera;
    12.      
    13.         void Awake(){
    14.          
    15.             Camera = this;
    16.          
    17.         }
    18.      
    19.         public RenderTexture Capture (int width, int height, Material material){
    20.          
    21.             this.quadRenderer.material = material;
    22.             RenderTexture temp = RenderTexture.GetTemporary(width, height);
    23.             this.textureCamera.targetTexture = temp;
    24.             this.textureCamera.Render();
    25.             return temp;
    26.          
    27.         }
    28.      
    29.     }
    30.  
    31. }
    With Capture function, you can obtain texture from any material.



    How to use:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GUIScript : MonoBehaviour {
    5.          
    6.     public Rect rect1 = new Rect(0f,0f,200f,200f);
    7.     public Rect rect2 = new Rect(0f,201f,200f,200f);
    8.  
    9.     public Material material1;
    10.     public Material material2;
    11.  
    12.     Texture tex1, tex2;
    13.  
    14.     void Start(){
    15.  
    16.         this.tex1 = Custom.Texture.Camera.Capture(512, 512, this.material1);
    17.         this.tex2 = Custom.Texture.Camera.Capture(512, 512, this.material2);
    18.  
    19.     }
    20.      
    21.     void OnGUI() {
    22.      
    23.         GUI.DrawTexture(this.rect1, this.tex1);
    24.         GUI.DrawTexture(this.rect2, this.tex2);
    25.      
    26.     }
    27.  
    28. }
     

    Attached Files:

    Last edited: May 28, 2015
    FEF2223 and WaylandGod like this.