I'm looking to make a toon shader that has both the cell shading effect from one shader as well as an outline from another shader.
Is there a relatively straightforward way to combine these two?
The outline references a simple flat shader using "UsePass" is there a way I could reference the cell shaded shader instead?
This is the outline shader:
Shader "TSF/BaseOutline1"
{
Properties
{
[MaterialToggle(_TEX_ON)] _DetailTex ("Enable Detail texture", Float) = 0 //1
_MainTex ("Detail", 2D) = "white" {} //2
_ToonShade ("Shade", 2D) = "white" {} //3
[MaterialToggle(_COLOR_ON)] _TintColor ("Enable Color Tint", Float) = 0 //4
_Color ("Base Color", Color) = (1,1,1,1) //5
[MaterialToggle(_VCOLOR_ON)] _VertexColor ("Enable Vertex Color", Float) = 0//6
_Brightness ("Brightness 1 = neutral", Float) = 1.0 //7
_OutlineColor ("Outline Color", Color) = (0.5,0.5,0.5,1.0) //10
_Outline ("Outline width", Float) = 0.01 //11
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 250
Lighting Off
Fog { Mode Off }
UsePass "TSF/Base1/BASE"
Pass
{
Cull Front
ZWrite On
CGPROGRAM
#include "UnityCG.cginc"
#pragma fragmentoption ARB_precision_hint_fastest
#pragma glsl_no_auto_normalization
#pragma vertex vert
#pragma fragment frag
struct appdata_t
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
};
fixed _Outline;
v2f vert (appdata_t v)
{
v2f o;
o.pos = v.vertex;
o.pos.xyz += normalize(v.normal.xyz) *_Outline*0.01;
o.pos = UnityObjectToClipPos(o.pos);
return o;
}
fixed4 _OutlineColor;
fixed4 frag(v2f i) :COLOR
{
return _OutlineColor;
}
ENDCG
}
}
Fallback "Legacy Shaders/Diffuse"
}
And the cell shaded shader is here:
Shader "Toon/Cutoff"
{
Properties
{
_Color("Color(RGBA)", Color) = (1,1,1,1)
_MainTex("Texture", 2D) = "white" {}
_Shininess ("Shininess(0.0:)", Float) = 1.0
_ShadowThreshold ("Shadow Threshold(0.0:1.0)", Float) = 0.5
_ShadowColor ("Shadow Color(RGBA)", Color) = (0,0,0,0.5)
_ShadowSharpness ("Shadow Sharpness(0.0:)", Float) = 100
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.9
}
SubShader
{
// Settings
Tags {"Queue" = "Transparent" "IgnoreProjector"="False" "RenderType" = "TransparentCutout"}
// Surface Shader Pass ( Front )
Cull Back
ZWrite On
AlphaTest Greater 0.9
//AlphaTest Equal 1
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf Toon alphatest:_Cutoff vertex:vert
// Toon Surface Shader for Unity
// File : ToonSurface.cginc
// Title : Toon Surface Shader with Alpha
// Language : Cg Language
// Include : ToonSurface.cginc
/*
How To Use :
CGPROGRAM
#pragma surface surf Toon
#include "ToonSurface.cginc"
ENDCG
*/
float4 _Color;
sampler2D _MainTex;
float _ShadowThreshold;
float4 _ShadowColor;
float _ShadowSharpness;
float _Shininess;
struct ToonSurfaceOutput
{
half3 Albedo;
half3 Normal;
half3 Emission;
half3 Gloss;
half Specular;
half Alpha;
half4 Color;
};
inline half4 LightingToon (ToonSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
//Lighting paramater
float4 lightColor = _LightColor0 * atten;
float lightStrength = dot(lightDir, s.Normal) * 0.5 + 0.5;
//ToonMapping
half shadowRate = abs( max( -1, ( min( lightStrength, _ShadowThreshold ) -_ShadowThreshold)*_ShadowSharpness ) )*_ShadowColor.a;
float4 toon = float4(1,1,1,1) * (1-shadowRate) + _ShadowColor *shadowRate;
//Output
//float4 color = saturate( _Color * (lightColor*2) ) * s.Color;
float4 color = _Color * (lightColor) * s.Color * (atten*2) * _Shininess;
color *= toon;
color.a = s.Alpha;
return color;
}
struct Input
{
float2 uv_MainTex;
};
void vert (inout appdata_full v, out Input o) {
UNITY_INITIALIZE_OUTPUT(Input,o);
}
void surf (Input IN, inout ToonSurfaceOutput o)
{
// Defaults
o.Albedo = 0.0;
o.Emission = 0.0;
o.Gloss = 0.0;
o.Specular = 0.0;
half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
//o.Albedo = c;
o.Color = c;
o.Alpha = c.a;
}
ENDCG
// // Outline Pass
// Pass
// {
// Cull Off
// ZWrite On
// Lighting Off
// CGPROGRAM
// #pragma vertex vert
// #pragma fragment frag
// #include "UnityCG.cginc"
// #include "ToonOutlineVertFrag.cginc"
// ENDCG
// }
// Surface Shader Pass ( Back )
Cull Front
ZWrite On
//AlphaTest Equal 1
AlphaTest Greater 0.9
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf Toon alphatest:_Cutoff vertex:vert
// Toon Surface Shader for Unity
// File : ToonSurface.cginc
// Title : Toon Surface Shader with Alpha
// Language : Cg Language
// Include : ToonSurface.cginc
/*
How To Use :
CGPROGRAM
#pragma surface surf Toon
#include "ToonSurface.cginc"
ENDCG
*/
float4 _Color;
sampler2D _MainTex;
float _ShadowThreshold;
float4 _ShadowColor;
float _ShadowSharpness;
float _Shininess;
struct ToonSurfaceOutput
{
half3 Albedo;
half3 Normal;
half3 Emission;
half3 Gloss;
half Specular;
half Alpha;
half4 Color;
};
inline half4 LightingToon (ToonSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
//Lighting paramater
float4 lightColor = _LightColor0 * atten;
float lightStrength = dot(lightDir, s.Normal) * 0.5 + 0.5;
//ToonMapping
half shadowRate = abs( max( -1, ( min( lightStrength, _ShadowThreshold ) -_ShadowThreshold)*_ShadowSharpness ) )*_ShadowColor.a;
float4 toon = float4(1,1,1,1) * (1-shadowRate) + _ShadowColor *shadowRate;
//Output
//float4 color = saturate( _Color * (lightColor*2) ) * s.Color;
float4 color = _Color * (lightColor) * s.Color * (atten*2) * _Shininess;
color *= toon;
color.a = s.Alpha;
return color;
}
struct Input
{
float2 uv_MainTex;
};
void vert (inout appdata_full v, out Input o) {
UNITY_INITIALIZE_OUTPUT(Input,o);
}
void surf (Input IN, inout ToonSurfaceOutput o)
{
// Defaults
o.Albedo = 0.0;
o.Emission = 0.0;
o.Gloss = 0.0;
o.Specular = 0.0;
half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
//o.Albedo = c;
o.Color = c;
o.Alpha = c.a;
}
ENDCG
}
// Other Environment
Fallback "Diffuse"
}
Related
I found this shader online that mimics liquid movement in a container.
Here it is (https://pastebin.com/wRWnHQH2)
Shader "Unlit/SpecialFX/Liquid"
{
Properties
{
_Tint ("Tint", Color) = (1,1,1,1)
_MainTex ("Texture", 2D) = "white" {}
_FillAmount ("Fill Amount", Range(-10,10)) = 0.0
[HideInInspector] _WobbleX ("WobbleX", Range(-1,1)) = 0.0
[HideInInspector] _WobbleZ ("WobbleZ", Range(-1,1)) = 0.0
_TopColor ("Top Color", Color) = (1,1,1,1)
_FoamColor ("Foam Line Color", Color) = (1,1,1,1)
_Rim ("Foam Line Width", Range(0,0.1)) = 0.0
_RimColor ("Rim Color", Color) = (1,1,1,1)
_RimPower ("Rim Power", Range(0,10)) = 0.0
}
SubShader
{
Tags {"Queue"="Geometry" "DisableBatching" = "True" }
Pass
{
Zwrite On
Cull Off // we want the front and back faces
AlphaToMask On // transparency
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float3 viewDir : COLOR;
float3 normal : COLOR2;
float fillEdge : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _FillAmount, _WobbleX, _WobbleZ;
float4 _TopColor, _RimColor, _FoamColor, _Tint;
float _Rim, _RimPower;
float4 RotateAroundYInDegrees (float4 vertex, float degrees)
{
float alpha = degrees * UNITY_PI / 180;
float sina, cosa;
sincos(alpha, sina, cosa);
float2x2 m = float2x2(cosa, sina, -sina, cosa);
return float4(vertex.yz , mul(m, vertex.xz)).xzyw ;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
// get world position of the vertex
float3 worldPos = mul (unity_ObjectToWorld, v.vertex.xyz);
// rotate it around XY
float3 worldPosX= RotateAroundYInDegrees(float4(worldPos,0),360);
// rotate around XZ
float3 worldPosZ = float3 (worldPosX.y, worldPosX.z, worldPosX.x);
// combine rotations with worldPos, based on sine wave from script
float3 worldPosAdjusted = worldPos + (worldPosX * _WobbleX)+ (worldPosZ* _WobbleZ);
// how high up the liquid is
o.fillEdge = worldPosAdjusted.y + _FillAmount;
o.viewDir = normalize(ObjSpaceViewDir(v.vertex));
o.normal = v.normal;
return o;
}
fixed4 frag (v2f i, fixed facing : VFACE) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv) * _Tint;
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
// rim light
float dotProduct = 1 - pow(dot(i.normal, i.viewDir), _RimPower);
float4 RimResult = smoothstep(0.5, 1.0, dotProduct);
RimResult *= _RimColor;
// foam edge
float4 foam = ( step(i.fillEdge, 0.5) - step(i.fillEdge, (0.5 - _Rim))) ;
float4 foamColored = foam * (_FoamColor * 0.9);
// rest of the liquid
float4 result = step(i.fillEdge, 0.5) - foam;
float4 resultColored = result * col;
// both together, with the texture
float4 finalResult = resultColored + foamColored;
finalResult.rgb += RimResult;
// color of backfaces/ top
float4 topColor = _TopColor * (foam + result);
//VFACE returns positive for front facing, negative for backfacing
return facing > 0 ? finalResult: topColor;
}
ENDCG
}
}
}
it works nicely except that the AlphaToMask ON that works on desktop to mask out the fill part doesn't seem to work at all on mobile, showing black instead of transparency.
Any clue on what's going on or how I could solve this?
For those who want it works on mobile devices, just set AlphaToMask to off (optional), set Zwrite to off and add line Blend SrcAlpha OneMinusSrcAlpha below Zwrite off line,
also set "Queue"="Transparent" or "AlphaTest"
SubShader
{
Tags {"Queue"="Transparent" "DisableBatching" = "True" }
Pass
{
Zwrite off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off // we want the front and back faces
AlphaToMask off CGPROGRAM
#pragma vertex vert
#pragma fragment frag
(Full code)
(Demo image)
See also:
Unity Blend Documentation:https://docs.unity3d.com/Manual/SL-Blend.html
Unity Shader Transparent Tutorial:Making A Transparent Shader [6/8]
Unity Project, Want to combine these two shaders into one shader to get both of their functionality. One shader is for lighting, the other shader is for rendering better. How do I combine?
Shader "Transparent/Cutout/Lit3dSprite" {
Properties{
_MainCol("Main Tint", Color) = (1,1,1,1)
_MainTex("Main Texture", 2D) = "white" {}
_Cutoff("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader{
Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" "PreviewType" = "Plane"}
Cull Off
LOD 200
CGPROGRAM
#pragma surface surf SimpleLambert alphatest:_Cutoff addshadow fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
fixed4 _MainCol;
half4 LightingSimpleLambert(SurfaceOutput s, half3 lightDir, half atten)
{
half4 c;
c.rgb = s.Albedo * _MainCol.rgb * (atten)* _LightColor0.rgb;
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _MainCol;
o.Albedo = lerp(c.rgb, c.rgb, c.a);
o.Alpha = c.a;
}
ENDCG
}
Fallback "Transparent/Cutout/VertexLit"
}
Shader 2:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "RetroAA/Sprite"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,0,0,0)
}
SubShader
{
Tags {
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
LOD 100
Cull Off
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "RetroAA.cginc"
struct appdata {
float4 vertex : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _MainTex_TexelSize;
float4 _Color;
v2f vert(appdata v){
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.color = v.color * _Color;
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 color = RetroAA(_MainTex, i.uv, _MainTex_TexelSize);
return i.color*color*color.a;
}
ENDCG
}
}
}
The second shader isn't too complicated, and can be merged into the first one by just using the second shader's code to change how the first shader's surf calculates fixed4 c.
You'll also need to include the definition for RetroAA and include the Texel Size of the main texture in the shader variables.
However, the first shader assumes that there is no partial transparency, and the second shader requires it, so you have to accomodate that. You'll need to use Alpha blending, change the RenderType and Queue to Transparent, and indicate ZWrite Off.
Here is what that might all look together:
Shader "Transparent/Cutout/Lit3dSprite" {
Properties{
_MainCol("Main Tint", Color) = (1,1,1,1)
_MainTex("Main Texture", 2D) = "white" {}
_Cutoff("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader{
// change RenderType and Queue to Transparent
Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"}
Cull Off
ZWrite Off // Add this
LOD 200
// Enable Alpha blending here
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
// Enable Alpha blending here also
#pragma surface surf SimpleLambert alphatest:_Cutoff addshadow fullforwardshadows alpha:blend
#pragma target 3.0
sampler2D _MainTex;
float4 _MainTex_TexelSize; // Add this
fixed4 _MainCol;
// include this
fixed4 RetroAA(sampler2D tex, float2 uv, float4 texelSize)
{
float2 texelCoord = uv * texelSize.zw;
float2 hfw = 0.5*fwidth(texelCoord);
float2 fl = floor(texelCoord - 0.5) + 0.5;
float2 uvaa = (fl + smoothstep(0.5 - hfw, 0.5 + hfw, texelCoord - fl))*texelSize.xy;
return tex2D(tex, uvaa);
}
half4 LightingSimpleLambert(SurfaceOutput s, half3 lightDir, half atten)
{
half4 c;
// Fix the lambert lighting implementation here
half NdotL = dot(s.Normal, lightDir);
// We set the surface rgba in surf, so don't need to do it again here.
c.rgb = s.Albedo * (NdotL * atten) * _LightColor0.rgb;
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
float4 color: Color; // Add this to use SpriteRenderer color
};
void surf(Input IN, inout SurfaceOutput o) {
// replace this line:
// fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _MainCol;
// with this
fixed4 c = RetroAA(_MainTex, IN.uv_MainTex, _MainTex_TexelSize);
// factor in MainCol and SpriteRenderer color/tints
o.Albedo = c.rgb * _MainCol.rgb * IN.color.rgb;
o.Alpha = c.a * _MainCol.a * IN.color.a;
}
ENDCG
}
Fallback "Transparent/Cutout/VertexLit"
}
You might need to turn down the Alpha cutoff to zero or some other low number in order to make the AA work nicely.
I'm trying to add some Smoothness and Metallic to my custom shader in order to have dark texture for day/night cycle.
For the moment, i have a procedurale planet and my shader draw different textures based on height (distance between center of planet and vertex at surface).
Until there, it works !
Now I really need to add Smoothness and Metallic to material but with my shader the textures of my procedurale planet is black and dont know why ? I have a pass for frag and then a surf function for smoothness and metallic. Why this doesn't work please ?
However when I look at the material icon and I change value it looks nice but procedurale planet is always black no matter of value i change and the color i set.
Can't solve this problem since too long time. Please need some help.
Thanks in advance.
Here is my shader :
Shader "Custom/Planet" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Tex0 ("Tex 0", 2D) = "white" {}
_Tex1 ("Tex 1", 2D) = "white" {}
_Tex2 ("Tex 2", 2D) = "white" {}
_Tex3 ("Tex 3", 2D) = "white" {}
_Tex4 ("Tex 4", 2D) = "white" {}
_Blend0to1and1to2 ("Blend between 0 and 1, 1 and 2", Vector) = (0,1,2,3)
_Blend2to3and3to4 ("Blend between 2 and 3, 3 and 4", Vector) = (0,1,2,3)
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma target 3.0
sampler2D _Tex0;
sampler2D _Tex1;
sampler2D _Tex2;
sampler2D _Tex3;
sampler2D _Tex4;
float4 _Blend0to1and1to2;
float4 _Blend2to3and3to4;
uniform float4 _Tex0_ST;
uniform float4 _Tex1_ST;
uniform float4 _Tex2_ST;
uniform float4 _Tex3_ST;
struct appData {
float4 vertex : POSITION;
float2 uv1 : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float2 uv3 : TEXCOORD2;
float2 uv4 : TEXCOORD3;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv1 : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float2 uv3 : TEXCOORD2;
float2 uv4 : TEXCOORD3;
float4 col : COLOR;
};
#define PI 3.141592653589793
inline float2 RadialCoords(float3 a_coords)
{
float3 a_coords_n = normalize(a_coords);
float lon = atan2(a_coords_n.z, a_coords_n.x);
float lat = acos(a_coords_n.y);
float2 sphereCoords = float2(lon, lat) * (1.0 / PI);
return float2(sphereCoords.x * 0.5 + 0.5, 1 - sphereCoords.y);
}
v2f vert (appData vInput) {
v2f output;
output.pos = UnityObjectToClipPos (vInput.vertex);
output.uv1 = TRANSFORM_TEX(vInput.uv1, _Tex0);
output.uv2 = TRANSFORM_TEX(vInput.uv2, _Tex1);
output.uv3 = TRANSFORM_TEX(vInput.uv3, _Tex2);
output.uv4 = TRANSFORM_TEX(vInput.uv4, _Tex3);
output.col = length(vInput.vertex);
return output;
}
half4 frag (v2f fInput) : COLOR {
half4 c0 = tex2D (_Tex0, fInput.uv1);
half4 c1 = tex2D (_Tex1, fInput.uv2);
half4 c2 = tex2D (_Tex2, fInput.uv3);
half4 c3 = tex2D (_Tex3, fInput.uv4);
half4 c4 = tex2D (_Tex4, fInput.uv1);
if (fInput.col.x < _Blend0to1and1to2.x) {
return c0;
}
if (fInput.col.x > _Blend0to1and1to2.x && fInput.col.x < _Blend0to1and1to2.y) {
return lerp(c0,c1,((fInput.col.x - _Blend0to1and1to2.x)/(_Blend0to1and1to2.y-_Blend0to1and1to2.x)));
}
if (fInput.col.x > _Blend0to1and1to2.y && fInput.col.x < _Blend0to1and1to2.z) {
return c1;
}
if (fInput.col.x > _Blend0to1and1to2.z && fInput.col.x < _Blend0to1and1to2.w) {
return lerp(c1,c2,((fInput.col.x - _Blend0to1and1to2.z)/(_Blend0to1and1to2.w-_Blend0to1and1to2.z)));
}
if (fInput.col.x > _Blend0to1and1to2.w && fInput.col.x < _Blend2to3and3to4.x) {
return c2;
}
if (fInput.col.x > _Blend2to3and3to4.x && fInput.col.x < _Blend2to3and3to4.y) {
return lerp(c2,c3,((fInput.col.x - _Blend2to3and3to4.x)/(_Blend2to3and3to4.y-_Blend2to3and3to4.x)));
}
if (fInput.col.x > _Blend2to3and3to4.y && fInput.col.x < _Blend2to3and3to4.z) {
return c3;
}
if (fInput.col.x > _Blend2to3and3to4.z && fInput.col.x < _Blend2to3and3to4.w) {
return lerp(c3,c4,((fInput.col.x - _Blend2to3and3to4.z)/(_Blend2to3and3to4.w-_Blend2to3and3to4.z)));
}
return c4;
}
ENDCG
}
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 _Tex1;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_Tex1, 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;
}
ENDCG
}
FallBack "Diffuse"
}
I am trying to use a shader to prevent an object being rendered when it leaves a specific area. However, when using a surface shader to do this, to fix drawing issues I have to use a depth buffer. Currently I am doing this by
Pass {
ColorMask 0
}
However, this is causing an effect that doesn't render the parts of the mesh that are behind the drawn parts of the color mask.
To get round this I attempted to just complete the pass but discard the fragments, this however caused faces to render in the wrong order. This potentially could be due to Cull Off in the shader script below, however that is not the normal way my program handles the inside rendering, it was just a quick thing to provide reasonable results without lots of code. Also it happens with both Cull Back and Cull Off.
How can I make it so that either ColorMask 0 doesn't obscure what is behind it or what CG program could be used to prevent the issue with the faces rendering in the wrong order when all the fragments are discarded?
Shader Code - Lit.shader
Shader "Culling/Lit" {
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
//Properties normally assigned by script but can be done manually
_SHOWCULL("Show Cull", Int) = 0
_RADIUS("Radius", Float) = 0
_STARTX("Start X", Float) = 0
_STARTY("Start Y", Float) = 0
_STARTZ("Start Z", Float) = 0
_CENTREX("Centre X", Float) = 0
_CENTREY("Centre Y", Float) = 0
_CENTREZ("Centre Z", Float) = 0
_ENDX("End X", Float) = 0
_ENDY("End Y", Float) = 0
_ENDZ("End Z", Float) = 0
_MODE("Mode", Int) = 0
}
SubShader {
Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" }
LOD 200
Blend SrcAlpha OneMinusSrcAlpha
ZWrite On
Pass {
//Renders faces in wrong order
/*CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : POSITION;
};
v2f vert (appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : COLOR {
discard;
return _Color;
}
ENDCG*/
ColorMask 0
}
Cull Off //Not normally used as provides incorrect light but way to fix is not needed for this and it is here to show example inside
CGPROGRAM
#pragma surface surf Standard fullforwardshadows alpha
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
float3 worldPos;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
UNITY_INSTANCING_CBUFFER_START(Props)
UNITY_INSTANCING_CBUFFER_END
int _SHOWCULL;
float _RADIUS;
float _STARTX;
float _STARTY;
float _STARTZ;
float _CENTREX;
float _CENTREY;
float _CENTREZ;
float _ENDX;
float _ENDY;
float _ENDZ;
int _MODE;
void surf (Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
if (_MODE == 0) {
//For Cylinder
if (sqrt(((IN.worldPos.x - _CENTREX) * (IN.worldPos.x - _CENTREX)) +
((IN.worldPos.z - _CENTREZ) * (IN.worldPos.z - _CENTREZ))) < _RADIUS
&& IN.worldPos.y > _STARTY && IN.worldPos.y < _ENDY) {
}
else
{
discard; //ignores that pixel - doesnt render it
}
}
else if (_MODE == 1) {
//For Sphere
if (sqrt(((IN.worldPos.x - _CENTREX) * (IN.worldPos.x - _CENTREX)) +
((IN.worldPos.y - _CENTREY) * (IN.worldPos.y - _CENTREY)) +
((IN.worldPos.z - _CENTREZ) * (IN.worldPos.z - _CENTREZ))) < _RADIUS) {
}
else
{
discard; //ignores that pixel - doesnt render it
}
}
else if (_MODE == 2) {
// For Cuboid
if (IN.worldPos.x > _STARTX && IN.worldPos.x < _ENDX
&& IN.worldPos.y > _STARTY && IN.worldPos.y < _ENDY
&& IN.worldPos.z > _STARTZ && IN.worldPos.z < _ENDZ) {
}
else
{
discard; //ignores that pixel - doesnt render it
}
}
}
ENDCG
}
FallBack "Diffuse"
}
This can be solved by using the same math to clip the ColorMask as used with the mesh. This way, the depth buffer still is present so the faces are drawn in the right order and it does not occlude anything.
...
Pass {
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float _RADIUS;
float _STARTX;
float _STARTY;
float _STARTZ;
float _CENTREX;
float _CENTREY;
float _CENTREZ;
float _ENDX;
float _ENDY;
float _ENDZ;
float _MODE;
sampler2D _MainTex;
fixed4 _Color;
// vertex shader inputs
struct appdata
{
float4 vertex : POSITION; // vertex position
float2 uv : TEXCOORD0; // texture coordinate
};
// vertex shader outputs ("vertex to fragment")
struct v2f
{
float2 uv : TEXCOORD0; // texture coordinate
float4 vertex : SV_POSITION; // clip space position
float4 position_in_world_space : TEXCOORD1; //same as uv
};
float4 _MainTex_ST;
// vertex shader
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.position_in_world_space = mul(unity_ObjectToWorld, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv) * _Color;
if (_MODE == 0) {
//For Cylinder
if (sqrt(((i.position_in_world_space.x - _CENTREX) * (i.position_in_world_space.x - _CENTREX)) +
((i.position_in_world_space.z - _CENTREZ) * (i.position_in_world_space.z - _CENTREZ))) < _RADIUS
&& i.position_in_world_space.y > _STARTY && i.position_in_world_space.y < _ENDY) {}
else
{
discard; //ignores that pixel - doesnt render it
}
}
else if (_MODE == 1){
//For Sphere
if (sqrt(((i.position_in_world_space.x - _CENTREX) * (i.position_in_world_space.x - _CENTREX)) +
((i.position_in_world_space.y - _CENTREY) * (i.position_in_world_space.y - _CENTREY)) +
((i.position_in_world_space.z - _CENTREZ) * (i.position_in_world_space.z - _CENTREZ))) < _RADIUS) {}
else
{
discard; //ignores that pixel - doesnt render it
}
}
else if (_MODE == 2){
// For Cuboid
if (i.position_in_world_space.x > _STARTX && i.position_in_world_space.x < _ENDX
&& i.position_in_world_space.y > _STARTY && i.position_in_world_space.y < _ENDY
&& i.position_in_world_space.z > _STARTZ && i.position_in_world_space.z < _ENDZ) {}
else
{
discard; //ignores that pixel - doesnt render it
}
}
return col;
}
ENDCG
}
...
I need help in applying a specular shade in a 3D model after I deformed it in CG vertex shader. I don't know how to do it in Unity shader. I already searched in google and there are no hits of what I am looking for.
Below is my current solution. The 3D object is rendered twice.
Shader "myShader/DeformSpecular" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0.5)
_Shininess ("Shininess", Range (0.01, 1)) = 0.7
_MainTex ("Base (RGB)", 2D) = "white" { }
_BumpMap ("Normalmap", 2D) = "bump" {}
_cubeSize("Cube Size", Range (1, 10)) = 1
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 250
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "myShaderFuncs.cginc"
sampler2D _MainTex;
sampler2D _BumpMap;
half _Shininess;
float4 _Color;
float4x4 _localOrient; //local orientation
float4x4 _parentWOrient; //world orientation of parent node
float _deformParam;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
float4 _MainTex_ST;
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul(_localOrient, v.vertex); //apply local transformation
o.pos = deformShape(_deformParam); //apply deform
o.pos = mul(_parentWOrient, o.pos); //apply parents world orientation
o.pos = mul (UNITY_MATRIX_VP, o.pos);
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
return o;
}
half4 frag (v2f i) : COLOR
{
half4 texcol = tex2D (_MainTex, i.uv);
return texcol * _Color;
}
ENDCG
}//Pass
CGPROGRAM
#pragma surface surf MobileBlinnPhong exclude_path:prepass nolightmap noforwardadd halfasview
inline fixed4 LightingMobileBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 halfDir, fixed atten)
{
fixed diff = max (0, dot (s.Normal, lightDir));
fixed nh = max (0, dot (s.Normal, halfDir));
fixed spec = pow (nh, s.Specular*128) * s.Gloss;
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten*2);
c.a = 0.0;
return c;
}
sampler2D _MainTex;
sampler2D _BumpMap;
half _Shininess;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb;
o.Gloss = tex.a;
o.Alpha = tex.a;
o.Specular = _Shininess;
o.Normal = UnpackNormal (tex2D(_BumpMap, IN.uv_MainTex));
}
ENDCG
}//SubShader
FallBack "Mobile/VertexLit"
}
If I understood you correctly, you want to do specular lighting calculations inside your CG shader?
Unity gives you lighting info that you can access to do your own calculations if you wish:
http://docs.unity3d.com/Documentation/Components/SL-BuiltinValues.html
However, the Doc seems outdated and some variables are wrong as its point out here:
http://answers.unity3d.com/questions/411114/shaderlab-builtin-lighting-properties-are-not-corr.html
once you use these variables you can calculate the lighting as you want