I'm very new to Unity and at this point I don't even really know what questions to ask to move forward with what I want to do.
My end goal is the ability to switch between a standard color view, a White Hot thermal camera kind of view, and a Black Hot thermal view. If I can figure out how to do White Hot, I imagine it'll be trivial to do Black Hot as well.
Here is a real-world image of the effect I'm trying to come up with:
My guess right now is that I could achieve this with 3 different cameras. One for each view mode.
I figure I could create an object with a full color material and have a child object with a different material to show to a camera that only shows White Hot objects. I could filter on tags so only the main object or one of it's child objects is visible at a time but this would require 3 times as many objects in my game. I would hope there's a way to show a Color camera one material but show a WhiteHot camera a different material but I don't see any way to do that.
I found a forum thread about thermal vision but I don't know anything about shaders and the provided sample project won't run in the web player and doesn't gracefully upgrade to my version of Unity.
Where is square one when it comes to having different "camera modes" like this?
EDIT: A brief look into shaders has shown semi-fruitful. I've created the following ultra-simple shader:
Shader "Custom/WhiteHotUnlit"
{
Properties
{
_Temp("Temperature", Float) = 0.0
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float _Temp;
struct vertInput {
float4 pos : POSITION;
};
struct vertOutput {
float4 pos : SV_POSITION;
};
vertOutput vert(vertInput input) {
vertOutput o;
o.pos = mul(UNITY_MATRIX_MVP, input.pos);
return o;
}
half4 frag(vertOutput output) : COLOR {
return half4(1.0 * _Temp, 1.0 * _Temp, 1.0 * _Temp, 1.0);
}
ENDCG
}
}
}
This allows me to use the shader on an object and set that object's Temperature and it'll show as a shade of gray depending on that temp. This also lets me set it on a per-object basis. So far so good! However, I can't seem to figure out how to have two shaders on an object. I want my Color Camera to display all objects using the Standard shader and when I switch to the WhiteHot Camera then it should render everything with the WhiteHot shader WITH THE TEMP VALUE ASSIGNED TO THAT OBJECT. I set up the second camera with:
WhiteHot.SetReplacementShader(whShader, null);
And nothing gets drawn when I'm using that camera. I also can't seem to give one object two mesh renderers. I guess that makes sense, but I was hoping to do one renderer per camera. I feel like I'm getting much closer! But I'm not there quite yet...
EDIT 2: Since Vertex and Fragment shaders seem to override and remove shadows (please correct me if I'm wrong, PLEASE) then I've decided to try a surface shader. I've switched to a one camera, one shader approach.
Here's my surface shader right now:
Shader "Custom/WhiteHotLit" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.0
_Metallic ("Metallic", Range(0,1)) = 0.0
//_Mode ("Mode", Int) = 0
_Temp ("Temperature", Range(0, 1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
uniform int _Mode = 0;
float _Temp;
void surf(Input IN, inout SurfaceOutputStandard o) {
switch (_Mode) {
case 1:
// Here I don't want shadows or lighting
o.Albedo = fixed3(_Temp, _Temp, _Temp);
break;
case 2:
// Here I don't want shadows or lighting
o.Albedo = fixed3(1.0 - _Temp, 1.0 - _Temp, 1.0 - _Temp);
break;
default:
// Here I want shadows and lighting
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
break;
}
}
ENDCG
}
FallBack "Diffuse"
}
Now I can make a call to Shader.SetGlobalInt('_Mode', <int>);
and change it to 0 (Full Color), 1 (White Hot), or 2 (Black Hot). However, just like Vertex/Fragment Shaders seem to always exclude shadows, this Surface Shader always includes them. I'd like to find a way that for Mode's 1 and 2 I can turn off shadows.
I could turn off all the lights and adjust the ambient light but that sounds like a duct tape kind of solution to this. Could a multi-pass shader do what I want? On one pass could it be a surface shader and on another pass could it be a vertex/fragment shader?