Simple double sided custom shader looks strange - unity3d

I'm very new to Shaders programming, I was trying to create a shader which:
Allows to change 2 textures with 2 corresponding normal maps (fade in/fade out)
Doublesided (show mesh from both sides of the surface)
Here is what I end up with:
Shader "Custom/TextureBlend" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_Blend ("Texture Blend", Range(0,1)) = 0.0
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_MainTex2 ("Albedo 2 (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_BumpMap ("Bumpmap", 2D) = "bump" {}
_BumpMap2 ("Bumpmap", 2D) = "bump" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Cull Off
ZTest LEqual
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;
sampler2D _MainTex2;
sampler2D _BumpMap;
sampler2D _BumpMap2;
struct Input {
float2 uv_MainTex;
float2 uv_MainTex2;
float2 uv_BumpMap;
float2 uv_BumpMap2;
};
half _Blend;
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = lerp (tex2D (_MainTex, IN.uv_MainTex), tex2D (_MainTex2, IN.uv_MainTex2), _Blend) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
fixed4 n = lerp (tex2D (_BumpMap, IN.uv_BumpMap), tex2D (_BumpMap2, IN.uv_BumpMap2), _Blend) * _Color;
o.Normal = n.rgb;
}
ENDCG
}
FallBack "Diffuse"
}
It works but for some reason the texture on the surface looks dim (on the other side of the mesh which usually invisible it's even darker), and normal map reflections barely visible.
Here, on the left you can see the plane with my shader, on the right - standard shader:
Also the reflection looks really strange, if I will move Metallic slider to the right you will see it:

Normal maps store vector information while regular textures are unsigned, so you need to use the UnpackNormal() helper method as shown in the samples. You also don't need to multiply by Color.
final code would then be along the lines of:
fixed4 n0 = tex2D(_BumpMap, IN.uv_BumpMap);
fixed4 n1 = tex2D(_BumpMap2, IN.uv_BumpMap2);
o.Normal = UnpackNormal(lerp(n0, n1, _Blend)).xyz;

Related

Custom shader casts shadows but cannot receive them

I have two shaders for my 2d sprites to cast shadows when they are "stood up" 10 degrees off a flat plane.
This one casts and receives shadows, but I cannot use the alpha channel, transparency is entirely ignored
Shader "Custom/SpriteShadow"
{
Properties {
_Color ("Color", Color) = (1,1,1,1)
[PerRendererData]_MainTex ("Sprite Texture", 2D) = "white" {}
_Cutoff("Shadow alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags
{
"Queue"="Geometry"
"RenderType"="TransparentCutout"
}
LOD 200
Cull Off
CGPROGRAM
// Lambert lighting model, and enable shadows on all light types
#pragma surface surf Lambert addshadow fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
fixed4 _Color;
fixed _Cutoff;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
clip(o.Alpha - _Cutoff);
}
ENDCG
}
FallBack "Diffuse"
}
The second shader can cast shadows and works with alpha/transparency, but cannot receive shadows.
Shader "Custom/SpriteShadowWithAlpha"{
Properties
{
[PerRendererData] _MainTex("Texture", 2D) = "white" {}
_EffectColor1("Effect Color", Color) = (1,1,1,1)
_Crossfade("Fade", float) = 0
_FlashColor("Flash Color", Color) = (1,1,1,1)
_FlashAmount("Flash Amount",Range(0.0,1.0)) = 0
_Cutoff("Alpha Cutoff", Range(0,1)) = 0.9
_Color ("Color", Color) = (1,1,1,1)
[Toggle(_ALPHABLEND_ON)] ALPHABLEND_ON("Enable Dithered Shadows", Float) = 0.0
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "TransparentCutOut"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Cull Off
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf Lambert alpha:blend fullforwardshadows alphatest:_Cutoff
#pragma target 3.0
struct Input {
fixed2 uv_MainTex;
fixed4 color : COLOR;
};
sampler2D _MainTex;
fixed4 _EffectColor1;
fixed _Crossfade;
fixed4 _FlashColor;
float _FlashAmount;
void surf(Input IN, inout SurfaceOutput o)
{
fixed4 col = tex2D(_MainTex, IN.uv_MainTex);
fixed4 returnColor = lerp(col, col * _EffectColor1, _Crossfade) * _EffectColor1.a + col * (1.0 - _EffectColor1.a);
o.Albedo = returnColor.rgb * IN.color.rgb;
o.Alpha = col.a * IN.color.a;
o.Albedo = lerp(o.Albedo,_FlashColor.rgb,_FlashAmount);
}
ENDCG
}
Fallback "Standard"
}
I have tried mixing and matching different parts of the two but can never get shadows to cast and receive and work with the alpha channel.
This may not be the answer anyone in the future wants to see, but it is the one I went with. Originally I was unable to figure out a URP shader to do what I wanted. I was however able to find one that suited my needs later on.
So my solution was to upgrade to URP and ditch the standard shader. Using the following video as a guide and shader source
https://www.youtube.com/watch?v=d_OBjV7c1CY

Masking 3D object with custom shader in Unity

I'm making a 2D mobile game but I want to use 3D objects in shop section. So, in the shop section, I have a scroll rect and a viewport. I can scroll and the mask component works as expected with 2D objects. But when I add 3D objects, the objects getting out of the mask. I researched the forums and I find a custom shader. When I apply the shader to the objects materials, it partially works. But the depth or shadows are not working properly. I know not much about shaders. You can take a look at this Image. Box on the right is the original one, box on the left is the one with custom shader.
My shader code is here;
Shader "Custom/NewSurfaceShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_StencilComp("Stencil Comparison", Float) = 8
_Stencil("Stencil ID", Float) = 0
_StencilOp("Stencil Operation", Float) = 0
_StencilWriteMask("Stencil Write Mask", Float) = 255
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags { "RenderType"="UI""Queue"="Transparent" }
LOD 200
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask[_ColorMask]
Stencil
{
Ref 1
Comp LEqual
Pass Keep
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
CGPROGRAM
#pragma surface surf Standard vertex:vert fullforwardshadows
#pragma target 3.0
#include "UnityUI.cginc"
struct Input
{
float2 uv_MainTex;
float4 worldPosition;
};
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
o.worldPosition = v.vertex;
}
sampler2D _MainTex;
half _Glossiness;
half _Metallic;
fixed4 _Color;
float4 _ClipRect;
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;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
o.Alpha *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#ifdef UNITY_UI_ALPHACLIP
clip(o.Alpha - 0.001);
#endif
}
ENDCG
}
FallBack "Diffuse"
}

Optimizing spherical mask shader for mobile

I have used a shader that is very heavy for mobile performance. Can someone help me to improve it in order to get better performance?
I have noticed that my FPS with this shader goes from 60 to 30.
Shader "Custom/Sphered2"
{Properties
{
[HDR] _Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_ColorStrength("Color Strenth", Range(1,4)) = 1
_EmissionColor ("_EmissionColor Color", Color) = (1,1,1,1)
_EmissionTex ("_EmissionColor (RGB)", 2D) = "white" {}
_EmissionStrength("_EmissionColor Strenth", Range(0,4)) = 1
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
// _position ("World Position", Vector) = (0,0,0,0)
// _Radius ("Sphere Radius", Range(0,100)) = 0
//_Softness("Sphere Softness", Range(0,100)) = 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,_EmissionTex;
struct Input
{
float2 uv_MainTex;
float2 uv_EmissionTex;
float3 worldPos;
};
half _Glossiness;
half _Metallic;
fixed4 _Color,_EmissionColor;
half _ColorStrength,_EmissionStrength;
uniform float4 GLOBALmask_position2;
uniform half GLOBALmask_Radius2;
uniform half GLOBALmask_Softness;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
half grayscale = (c.r + c.g + c.b) * 0.333;
fixed3 cgg = fixed3(grayscale,grayscale,grayscale);
fixed4 e = tex2D (_EmissionTex, IN.uv_EmissionTex) * _EmissionColor *_EmissionStrength;
half d = distance(GLOBALmask_position2,IN.worldPos);
half sum = saturate((d - GLOBALmask_Radius2)/ -GLOBALmask_Softness);
fixed4 lerpColor = lerp(fixed4(cgg,1),c * _ColorStrength,sum);
fixed4 lerpEmission = lerp(fixed4(0,0,0,0),e,sum);
o.Albedo =c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Emission = lerpEmission.rgb;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
I have used it like this :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayCastMovePos : MonoBehaviour
{
public Transform playerTransform;
public float radius2,sm;
public Vector4 myPos2;
void Update()
{
myPos2= new Vector4 ( playerTransform.position.x ,
playerTransform.position.y, playerTransform.position.z, 0);
//radius =Mathf .Clamp ( ( myVisualizer.allRythem
[0]+myVisualizer.allRythem [1]+myVisualizer.allRythem [2]) * 170,2,1000);
// radius2 =Mathf .Clamp ( ( myVisualizer.allRythem
[3]+myVisualizer.allRythem [4]+myVisualizer.allRythem [5]) * 150,2,1000);
Shader.SetGlobalVector ("GLOBALmask_position2", myPos2);
Shader.SetGlobalFloat ("GLOBALmask_Radius2", radius2);
Shader.SetGlobalFloat ("GLOBALmask_Softness", sm );
}
}
I am new to shaders, but if there are any suggestions for glowing a sprite, I would be glad to hear it.
If this is for a sprite, then do you really need to use a surface shader? These include tons of overhead, like lightmapping support, shadow casting/receiving, forward light support, etc. I'm sure a vertex/fragment shader would work fine for your purposes. You get emission by simply adding extra color to the final output.
Here is how the body of Unity's sprite shader looks:
https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/UnitySprites.cginc

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"
}

Unity Shader: Need help creating texture layers that don't affect other layers

I'm trying to learn how to write shaders in Unity and am having trouble separating the color and alphas values from affecting the other textures(or layers).
In my shader I have 3 textures of letters (The backgrounds are made transparent in the unity texture settings for each).
I want to have a background color then I need 3 texture/layers on top of the background and be able to change the tint and alpha of each layer without affecting the background or any other layer.
also...
When I multiply the Color by the texture in the surf function, The texture tint changes but also does the transparent background. Why is the transparent backgrounds tint changing when it is transparent?
Properties{
_Background("BackroundColor", Color) = (1,1,1,1)
_Color("c1", Color) = (1,1,1,1)
_Color2("c2", Color) = (1,1,1,1)
_Color3("c3", Color) = (1,1,1,1)
_MainTex ("layer1", 2D) = "white" {}
_MainTex2 ("layer2", 2D) = "white" {}
_MainTex3 ("layer3", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque"}
CGPROGRAM
#pragma surface surf Lambert alpha
#pragma target 3.0
struct Input {
float2 uv_MainTex;
float2 uv2_MainTex2;
float2 uv3_MainTex3;
};
sampler2D _MainTex;
sampler2D _MainTex2;
sampler2D _MainTex3;
float4 _Background;
float4 _Color;
float4 _Color2;
float4 _Color3;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _Background * (tex2D (_MainTex, IN.uv_MainTex).rgb*_Color) * (tex2D (_MainTex2, IN.uv2_MainTex2).rgb*_Color2) * (tex2D (_MainTex3, IN.uv3_MainTex3).rgb*_Color3);
o.Alpha = _Color.a * _Color2.a * _Color3.a;
}
ENDCG
}
Fallback "Diffuse"
Nice thing to begin the shaders with unity ;)
So here is my solution to your problem, you have 2 exposed textures. One is the background (MainTex) and one is one of your letter (overlay) and you can mix the alpha of the overlay with the variable Ratio_
Shader "Custom/Overlay" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Main Texture", 2D) = "white" {}
_Overlay ("Overlay Texture", 2D) = "white" {} // One texture of letter
_Ratio("Ratio", Range(0,1)) = 1
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Blend SrcAlpha OneMinusSrcAlpha
Lighting On
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Overlay;
float _Ratio;
struct Input {
float2 uv_MainTex;
float2 uv_Overlay;
};
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 background = tex2D (_MainTex, IN.uv_MainTex) * _Color;
fixed4 finalFragment = tex2D (_Overlay, IN.uv_Overlay) * _Color;
o.Albedo = background.rgb * (1 -finalFragment.a*_Ratio) + finalFragment.rgb * _Ratio;
o.Alpha = background.a;
}
ENDCG
}FallBack "Diffuse"
}
Hope this will help :D