Have 3d text shader be non-emissive? - unity3d

In Unity, how can I stop my 3d texts from "glowing" in the dark?
I'm using below shader code, for instance, but the texts turn up much brighter/ self-emissive than other things. Changing to "Lighting On" gets rid of the glow, but will then also get rid of the material color, and turn up black.
How to solve this? Many thanks!
Shader "GUI/3D Text Shader - Cull Back" {
Properties {
_MainTex ("Font Texture", 2D) = "white" {}
_Color ("Text Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Lighting Off Cull Back ZWrite Off Fog { Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
Pass {
Color [_Color]
SetTexture [_MainTex] {
combine primary, texture * primary
}
}
}

Copied from comments, added for context:
I suspect the emissive glow is just the material's unlit color contrasting against a dark/variably lit scene? A lit shader could fix such an issue, however Unity's TextMesh component appears to not generate mesh normals and thus the shader's lighting calculations will corrupt (if at all be compiled). It explains why Lighting On outputs black. Without access to TextMesh internals and confined to the limitations of fixed-function shaders, a custom shader may be your only option.
The following is a basic Surface Shader using the Lambert lightning model. Under the hood it will compile to a standard vertex/fragment shader with Unity's lighting calculations automagically injected. It's been written as a drop-in replacement, so simply add it to your project and drag and drop it onto your material:
Shader "GUI/3D Text Shader - Lit"
{
Properties
{
_Color ("Text Color", Color) = (1,1,1,1)
_MainTex ("Font Texture", 2D) = "white" {}
}
SubShader
{
Tags {"RenderType"="Transparent" "Queue"="Transparent"}
Cull Back
CGPROGRAM
#pragma surface SS_Main Lambert vertex:VS_Main alpha:blend
#pragma target 3.0
uniform fixed4 _Color;
uniform sampler2D _MainTex;
struct Output
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
};
struct Input
{
float2 uv_MainTex;
};
void VS_Main (inout Output o)
{
// Generate normals for lighting.
o.normal = float3(0, 0, -1);
}
void SS_Main (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = _Color.rgb;
o.Alpha = c.a;
}
ENDCG
}
}

Related

How do I make the shader working for the standard pipeline work for the urp pipeline?

I have a shader that provides texture repeat. But it doesn't work in urp. How do I make it work for urp?
More precisely, the shader works, but the material turns pink. I made the option Rendering>Generate shader includes. I will be glad if you can help me how to do it.
My RepeatShader:
Shader "Custom/RepeatShader" {
Properties{
_Color("Main Color", Color) = (1,1,1,1)
_MainTex("Base (RGB)", 2D) = "white" {}
_Scale("Texture Scale", Float) = 1.0
}
SubShader{
Tags{ "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
float _Scale;
struct Input {
float3 worldNormal;
float3 worldPos;
};
void surf(Input IN, inout SurfaceOutput o) {
float2 UV;
fixed4 c;
if (abs(IN.worldNormal.x) > 0.5) {
UV = IN.worldPos.yz; // side
c = tex2D(_MainTex, UV* _Scale); // use WALLSIDE texture
}
else if (abs(IN.worldNormal.z) > 0.5) {
UV = IN.worldPos.xy; // front
c = tex2D(_MainTex, UV* _Scale); // use WALL texture
}
else {
UV = IN.worldPos.xz; // top
c = tex2D(_MainTex, UV* _Scale); // use FLR texture
}
o.Albedo = c.rgb * _Color;
}
ENDCG
}
Fallback "Legacy Shaders/VertexLit"
}
I don't know in which version of Unity and URP you are, but here's what I did:
First, right-click with your mouse and select Create > Shader Graph > URP > Lit Shader Graph (or Unlit if your shader should not react to light).
Inside your shader, create a Texture2D property called Main Tex, a float property called Scale and a color property called Color.
This is what your shader graph result should look like:
This should replicate exactly what you have in your shader. There are a few possible improvements, like using the Custom Function node to extract what you need without using all those nodes but this should help you start.

Outline shader with curves and transparency

I'm trying to create an outline shader, who has an edited outline.
At the moment it looks like this.
Shader "test/SimpleOutline" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline Width", Range (.002, 1.1)) = .005
}
SubShader {
Tags { "Queue"="Transparent" }
ZWrite off
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input {
float3 viewDir;
float2 uv_MainTex;
};
float _Outline;
float4 _OutlineColor;
void vert (inout appdata_full v) {
v.vertex.xyz += v.normal * _Outline;
}
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o)
{
o.Emission = float4(0, 1, 0,0);
}
ENDCG
ZWrite on
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
I want it like this.
It should be at a distance from the actual object
Transparent so you can see the background.
Completely circle each object and be arched.
Like this horn?
Does anyone have a suggestion on how best to implement this?
Hm, interesting question.
1. How to outline effect in distance from object?
I suggest stencil
Pass1: draw your mesh with no stencil
Pass2: draw mesh with MaskColor 0 with stencil writing some value
Pass3: draw outline mesh in solid color with stencil enabled with bigger "scale" than previous pass
somth like that.
Curving image. Feels like it should be done with techniques like in this video
https://www.youtube.com/watch?v=xH5uUfeB2Go try to apply it in Pass3.
P.S. I'm gonna try this effect myself in next couple of days if I would have time.

Unity3d mobile shader transparency issue

My 3D object is overlapping itself with alpha when using a custom shader in Unity3D (Unlit version):
It should look something like this instead:
Shader "Custom/Shader1" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
Pass {
ZWrite On
ColorMask 0
}
Pass {
ZWrite Off // don't write to depth buffer
Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float4 _Color; // define shader property for shaders
uniform sampler2D _MainTex;
uniform float _Cutoff;
struct vertexInput {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float2 tex : TEXCOORD0;
};
vertexOutput vert(vertexInput input) {
vertexOutput output;
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR {
float4 col = tex2D(_MainTex, input.tex) * _Color;
float newOpacity = 1.0;
if (col.a < _Cutoff) {
newOpacity = 0.0;
}
return float4(col.r, col.g, col.b, newOpacity);
}
ENDCG
}
}
}
Did I miss anything? It seems like the transparency alpha overlaps itself.
Edit 1
I removed the first pass, then enabled Zbuffer and removed the if (col.a < _Cutoff) and let it be dynamic according to its texture, but I still get the same result like the 1st image.
Shader "Custom/Shader1" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
Pass {
ZWrite On
Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float4 _Color; // define shader property for shaders
uniform sampler2D _MainTex;
uniform float _Cutoff;
struct vertexInput {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float2 tex : TEXCOORD0;
};
vertexOutput vert(vertexInput input) {
vertexOutput output;
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR {
float4 col = tex2D(_MainTex, input.tex) * _Color;
return col;
}
ENDCG
}
}
}
The shader is unlit because you use a regular CG shader instead of a Surface shader, whose purpose is to conveniently provide lighting behind the scene. Solution: start fresh from a surface shader template
Alpha blending is not taken advantage of since(col.a < _Cutoff) is always either true or false with no intermediate values, it's always fully shown or fully hidden. On top of that the way you write that condition probably generates some dynamic branching in the shader, try static branching instead float newOpacity = (col.a < _Cutoff) ? 0.0 : 1.0; (in that case the executed code is always the same, only the value changes which is usually much better for perfs).
The shader has 2 passes, which will prevent batching later on and that is pretty bad for performances. One is filling the Zbuffer and the other is doing alpha blending (2 operations that are not really compatible). The prepass is not working properly because it fills the buffer with the raw mesh, without having the information of transparency coming from the texture. Sure you could modify the first pass to do that, but the outcome you look for is essentially just a very straighforward Surface shader with alpha testing on.
You can read on the semantics exposed by Unity to control alpha testing in Surface shaders here: https://docs.unity3d.com/Manual/SL-SurfaceShaders.html , specifically that part :
alphatest:VariableName - Enable alpha cutout transparency. Cutoff
value is in a float variable with VariableName. You’ll likely also
want to use addshadow directive to generate proper shadow caster
pass.
alternatively you can use the clip() method in combination with addshadow, most likely along the lines of clip(col.a - 0.5);

In Unity Shaderlab, how can you animate towards a value using lerp and deltaTime

How can a Custom Standard Surface Shader be used to animate a value towards a target value?
For Example:
...
float targetAlpha; //Set by the property block, or a C# script
float currrentAlpha; //Used internally only.
void surf (Input IN, inout SurfaceOutputStandard o)
{
currrentAlpha = lerp(currrentAlpha, targetAlpha, unity_DeltaTime.x);
o.Alpha = currrentAlpha;
}
This code does not work but should demonstrate what the goal is: when targetAlpha is set, the shader will fade towards that value.
There are few ways this can be done. One of them is using built-in shader variables:
Shader "Custom/Test" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_TargetAlpha ("TargetAlpha", 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 alpha:fade
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Alpha;
fixed4 _Color;
half _TargetAlpha;
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = lerp(o.Alpha, _TargetAlpha, clamp(_SinTime.w, 0, 1));
}
ENDCG
}
FallBack "Diffuse"
}
The shader in the answer above still works in Unity 2018.2. However, _SinTime oscillates between -1 and 1, while we want the range to be between 0 and 1. The code clamp(_SinTime.w, 0, 1) clamps onto the desired values, however the alpha stays at zero too long. So we need the absolute value, like so: abs(_SinTime.w).
The modified shader:
Shader "Custom/Test" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_TargetAlpha ("TargetAlpha", 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 alpha:fade
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Alpha;
fixed4 _Color;
half _TargetAlpha;
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = lerp(o.Alpha, _TargetAlpha, abs(_SinTime.w));
}
ENDCG
}
FallBack "Diffuse"
}

Emissive Material in Unity

I am trying to make that a sphere emits light by using a material from the own unity, but no light is being created or emitted. What is wrong?
You can modify the emission in the material, without any special shader
You can then switch off all lights in the scene and you will be able to still see this GameObject
You can test it adding a script that make the ambient light to be dark grey
void Start () {
Color myColor = new Color32( 0x0B, 0x0A, 0x0A, 0xFF );
RenderSettings.ambientLight = myColor;
}
The result would be something like this, a cube which emit yellow light and a cube which is almost in darkness
Now if you want (which I am still not sure) to iluminate other elements in the scene. You should select the object as static in the right top corner.
And the result would be:
If this solution still does´t work for you. You can try with shaders:
Create a new Shader, name it Glow and replace its default code by this:
Script
Shader "Glow" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_Glow ("Intensity", Range(0, 3)) = 1
}
SubShader {
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
LOD 100
Cull Off
ZWrite On
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
half4 _MainTex_ST;
fixed4 _Color;
half _Glow;
struct vertIn {
float4 pos : POSITION;
half2 tex : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
half2 tex : TEXCOORD0;
};
v2f vert (vertIn v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.pos);
o.tex = v.tex * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag (v2f f) : SV_Target {
fixed4 col = tex2D(_MainTex, f.tex);
col *= _Color;
col *= _Glow;
return col;
}
ENDCG
}
}
}
Create a Material
Change its color to what you want and the Shader type select Glow
(the one you created in the fist step). Also choose the intensity you prefer.
The result would be:
With this version, you can not iluminate the nearby objects.
Finally, to make a better glomming effect you can add some effects to the camera.
Go to Assets -> Import Package -> Effects
Select the Main Camera and Add Component: Image Effects -> Bloom and
Glow -> Bloom Optimized
You will have the following component in your camera:
And the result of adding this effect to the camera would be:
The problem was solved only checking all objects in the scene as Static!