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

Unity's "new" input system and Keijiro's Minis midi stuff

compute shader with skinned mesh flocking instances

setting VFX graph properties using C#