scripting custom render texture creation, assignment, shaders
I got a little fed up of dragging the (wrong) custom render texture swatches onto materials in the inspector (slightly down to my crap naming conventions & Unity's project window only showing the first 8 letters of each name- can this be changed?!), so I decided to figure out a C# script that could make this easier. The entire script is way below - I'm just going to highlight a few important lines.
Shader shader = Shader.Find("custom/createdTextureShader");
This finds a shader that you've created externally. You could have a public shader variable at the top instead, so you could drop stuff into the Inspector.
_init_mat = new Material(init_shader);
Here we make a new material, using a specified shader type.
_init_mat.SetTexture("_initTex", init_texture);
Then we give it a texture file. _initTex is a property I've specified for the init_shader. Typically there is a _MainTex by default. I just wanted to see if you could specify arbitrary property names - you can! Another method of doing this is by using id values. I've commented out some lines where I tried to get this working (it didn't haha)
_tex = new CustomRenderTexture(512, 512);
_tex.name = GetType().Name;
_tex.depth = 0;
_tex.Create();
Next we make _tex, a new custom render texture with specified 512 resolution. I'm not entirely sure what the name part is for...I stole this part of the code from a Unity forum post. The _tex.depth setting to 0 is "necessary" for the double buffered switching to work. I prefer setting it to zero here instead of using the ZTest always in the shader. Maybe there'll come a time where I'll see why this isn't great. Lastly we create the tex with _tex.Create();
_tex.initializationSource = CustomRenderTextureInitializationSource.Material;
_double.updateMode = CustomRenderTextureUpdateMode.OnDemand;
These lines really annoyed me. Pretty much noone on the internet has written about them, or how to set them. I guess it is "basic" knowledge for those in the know! Anyway this is how to set the initialisation source/updatemode or any other enumerated drop down option, I guess.
void OnDisable()
{
_tex.Release();
Destroy(_intermediate_mat);
Destroy(_tex);
Destroy(_update_mat);
Destroy(_CRTmat);
Destroy(_init_mat);
Destroy(_real_final_mat);
_double.Release();
Destroy(_double);
}
Finally - we should do some housekeeping and destroy all the textures and materials we've created.
Final code below -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class create_custom_RT : MonoBehaviour
{
Material _update_mat;
Material _CRTmat;
Material _init_mat;
Material _real_final_mat;
Material _intermediate_mat;
public Texture2D init_texture;
public RenderTexture update_texture;
CustomRenderTexture _tex;
CustomRenderTexture _double;
void OnEnable()
{
Shader shader = Shader.Find("custom/createdTextureShader");
Shader init_shader = Shader.Find("custom/create_shader_init");
Shader finalshader = Shader.Find("custom/standardShader");
_init_mat = new Material(init_shader);
// int init_texture_id=init_shader.FindPropertyIndex("_initTex");//not using this method of id
// int init_texture_main_id = init_shader.FindPropertyIndex("_MainTex");//not using this method of id
_init_mat.SetTexture("_initTex", init_texture);
_update_mat = new Material(shader);
_update_mat.SetTexture("_MainTex", update_texture);
_tex = new CustomRenderTexture(512, 512);
_tex.name = GetType().Name;
_tex.depth = 0;
_tex.Create();
_tex.material = _update_mat;
_tex.initializationSource = CustomRenderTextureInitializationSource.Material;
_tex.initializationMaterial = _init_mat;
_tex.doubleBuffered = true;
_tex.initializationMode = CustomRenderTextureUpdateMode.OnLoad;
_tex.updateMode = CustomRenderTextureUpdateMode.OnDemand;
_tex.updatePeriod = 0.0333f;
_CRTmat = new Material(finalshader);
_CRTmat.mainTexture = _tex;
_intermediate_mat = new Material(shader);
_intermediate_mat.SetTexture("_MainTex", _tex);
_double = new CustomRenderTexture(512, 512);
_double.name = GetType().Name;
_double.depth = 0;
_double.Create();
_double.material = _intermediate_mat;
_double.initializationSource = CustomRenderTextureInitializationSource.Material;
_double.initializationMaterial = _CRTmat;
_double.doubleBuffered = true;
_double.initializationMode = CustomRenderTextureUpdateMode.OnLoad;
_double.updateMode = CustomRenderTextureUpdateMode.OnDemand;
_double.updatePeriod = 0.333f;
_real_final_mat = new Material(finalshader);
_real_final_mat.mainTexture = _double;
GetComponent<Renderer>().material = _real_final_mat;
}
private void Update()
{
_tex.Update();
_double.Update();
}
void OnDisable()
{
_tex.Release();
Destroy(_intermediate_mat);
Destroy(_tex);
Destroy(_update_mat);
Destroy(_CRTmat);
Destroy(_init_mat);
Destroy(_real_final_mat);
_double.Release();
Destroy(_double);
}
}
Comments
Post a Comment