Unity custom render textures

 It seems like Unity's Custom Render Textures provides much of the functionality that I'd want to create strange glitchy/feedback effects.

The workflow is a little messy and nested, but we'll break it down here in text, cos I'm lazy to take screenshots.

Firstly you have a material, which has a shader (could be anything), but importantly, it uses a texture - our custom render texture.

The custom render texture itself takes a few different inputs - it needs a material to update it and "something" to initialise it with. The Initialisation could just be from a texture, but should you require something a bit more flexible, you can assign a material with a shader.

Both the update material and intialisation material shaders are a little different to the ones I've been covering here, in terms of structure. This is because they're specifically operating within the custom render texture workflow.

Firstly - the initialisation shader -

Shader "customRT/init_shader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }

        CGINCLUDE
        #include "UnityCustomRenderTexture.cginc"

        sampler2D _MainTex;
        float4 _MainTex_ST;

        half4 frag(v2f_init_customrendertexture i):SV_Target
        {
            fixed4 tex = tex2D(_MainTex,i.texcoord);
            return tex;
        }

        ENDCG
    SubShader
    {
        

        Pass
        {
            Name "Init"
            CGPROGRAM
            #pragma vertex InitCustomRenderTextureVertexShader
            #pragma fragment frag
                  

            ENDCG
        }
    }
}

As usual it has a name and some properties - however we have to use the InitCustomRenderTextureVertexShader for our vertex shader  - also note that the pragmas are all relegated to the lower pass. We also must include "UnityCustomRenderTexture.cginc".

The fragment shader part of this code is between a CGINCLUDE/ENDCG block and the rest of it is fairly business as usual.

The update shader is fairly similar -

Shader "customRT/update_shader"
{
    Properties
    {
        _MainTex("Main Texture", 2D) = "grey"{}
        mult("multiply",float) = 1.0
        rdrift("red drift",float)=0.0
        gdrift("green drift",float) = 0.0

    }

        CGINCLUDE
#include "UnityCustomRenderTexture.cginc"
        sampler2D _MainTex;
        float mult;
        float rdrift;
        float gdrift;

        float2 rotateuv(float2 uv, float angle) {
            float2x2 rot = float2x2(cos(angle), -sin(angle), sin(angle), cos(angle));
            uv = mul(rot, uv);
            return uv;
        }

    half4 frag(v2f_customrendertexture i) : SV_Target
    {
        float2 uv = i.globalTexcoord;
        
        fixed4 col=tex2D(_SelfTexture2D,uv);
        uv = rotateuv(uv, _Time.x);
        fixed red= tex2D(_SelfTexture2D, uv).r*mult;
        col.r += red*0.03;
        fixed green = tex2D(_SelfTexture2D, uv ).g*mult;
        col.g += green*0.04;
        if (col.r > 0.95)col.r *= 0.1;
        if (col.g > 0.9)col.g *= 0.05;
        return half4(col);

    }
    ENDCG
                       
        SubShader
    {
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            Name "Update"
            CGPROGRAM
            #pragma vertex CustomRenderTextureVertexShader
            #pragma fragment frag
           
            ENDCG
        }
    }
}
 

This time the vertex shader drops the "init" part of the name, but again, we must use this specific one & include the cginc file as well.
Some useful stuff from the Unity docs -

The _SelfTexture2D texture is very useful - it is basically the "last frame rendered". On the custom render texture, there is a "double buffered" checkbox. That must be enabled for it to work (i think). It is useful because we can do things in a "solver" like fashion. In the example code I posted, I keep taking the previous frame & rotate the UVs, then add a fraction of the new red and green channel to it.

Keijiro has a good reaction diffusion example online, which I intend to dissect. There's also a good firey noise example online somewhere too. I'm very curious to see what I can do if I use video-stream as an input here!!

Comments

Popular posts from this blog

setting VFX graph properties using C#

scripting custom render texture creation, assignment, shaders