I'm new to shaders and I'm trying to make a shader for some very simple low poly water. I have created this simple surface shader that changes the vertex heights.
The problem is that it doesn't receive shadows as you can see in the gif and there is a weird behavior on the edges.
What am I doing wrong?
Shader "Ramble/LowPolyWater" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Main Color", Color) = (1,1,1,1)
_Emission ("Emission", Color) = (1,1,1,1)
_ScrollYSpeed("Scroll y speed", Float) = 0.1
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Emission;
float _ScrollYSpeed;
void vert (inout appdata_full v)
{
v.vertex.z += frac(sin( dot(v.vertex.xyz ,float3(12.9898,78.233,45.5432) )) * 43758.5453) * sin(_Time.y) * _ScrollYSpeed;
}
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = (tex2D (_MainTex, IN.uv_MainTex) * _Color).rgb;
o.Emission = _Emission.rgb;
}
ENDCG
}
Fallback "VertexLit"
}
Figured it out!
I just need to add addshadow to this line #pragma surface surf Lambert vertex:vert addshadow
Related
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
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"
}
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
I'm trying to configure this shader I got from the net to have a white outline not a black one. but the "_OutlineColor ("Outline Color", Color) = (1,1,1,1)" doesnt work.
I'm new to unity and how things work in it so I hope you can help me.
here is the complete shader:
Shader "Outlined/Diffuse" {
Properties {
_Color ("Main Color", Color) = (0,0,0,0)
_OutlineColor ("Outline Color", Color) = (1,1,1,1)
_Outline ("Outline width", Range (.002, 0.03)) = 5
_MainTex ("Base (RGB)", 2D) = "white" { }
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : POSITION;
float4 color : COLOR;
};
uniform float _Outline;
uniform float4 _OutlineColor;
v2f vert(appdata v) {
// just make a copy of incoming vertex data but scaled according to normal direction
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
return o;
}
ENDCG
SubShader {
//Tags {"Queue" = "Geometry+100" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
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;
}
ENDCG
// note that a vertex shader is specified here but its using the one above
Pass {
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
//Offset 50,50
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
half4 frag(v2f i) :COLOR { return i.color; }
ENDCG
}
}
SubShader {
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
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;
}
ENDCG
Pass {
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma exclude_renderers gles xbox360 ps3
ENDCG
SetTexture [_MainTex] { combine primary }
}
}
Fallback "Diffuse"
}
The "(1,1,1,1)" you are assigning to "_OutlineColor" describes a default value. That value is taken into consideration when you create new material that utilises that shader (here "Outlined/Diffuse"). Just create new material and assign to it your shader. You will notice that the Outline color this time will be white. Also you can simply select your material in the Editor and change the outline colour via inspector window.
As for your problem - probably you've created a new material combined with the shader you describe, BEFORE you made a change in the shader's body from black (0,0,0,1) to white (1,1,1,1) colour (I recognize the body of the shader, so I assume the black color). And what that means is that the default black colour has already been assigned to the material. If you want to change the colour, as I wrote above, do it on the material through the Editor's inspector.
I have created an object that has the texture and an AO , they are on different UV sets in maya(with Layered Texture) and in maya the mash looks ok.
How do i achive the same effect in Unity3D?
I can not make unity use the 2nd UV set.
You'll need to write a shader that does this. Here's a very minimal example, but you'd probably need to have a more elaborate setup for things specular, etc.
Shader "Custom/twotex" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_AoTex ("AO (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
sampler2D _AoTex;
struct Input {
float2 uv_MainTex : TEXCOORD0;
float2 uv_AoTex : TEXCOORD1;
};
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex.xy);
half4 ao = tex2D (_AoTex, IN.uv_AoTex.xy);
o.Albedo = c.rgb * ao.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}