Skip to content

Instantly share code, notes, and snippets.

@Invertex
Created March 29, 2025 12:42
Show Gist options
  • Save Invertex/94e10b39f68b822735aeeb4ace098673 to your computer and use it in GitHub Desktop.
Save Invertex/94e10b39f68b822735aeeb4ace098673 to your computer and use it in GitHub Desktop.
Unity Standard Shader that renders with proper double-sided lighting, not just culling disabled. Also uses the proper Standard shader GUI.
Shader "Invertex/Standard Double Sided" {
Properties {
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_Glossiness("Roughness", Range(0.0, 1.0)) = 0.5
_GlossMapScale("Roughness Scale", Range(0.0, 1.0)) = 1.0
[Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
_MetallicGlossMap("Metallic", 2D) = "white" {}
[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
_BumpScale("Scale", Float) = 1.0
[Normal] _BumpMap("Normal Map", 2D) = "bump" {}
_Parallax ("Height Scale", Range(0.005, 0.08)) = 0.02
_ParallaxMap ("Height Map", 2D) = "black" {}
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
_DetailMask("Detail Mask", 2D) = "white" {}
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
_DetailNormalMapScale("Scale", Float) = 1.0
[Normal] _DetailNormalMap("Normal Map", 2D) = "bump" {}
[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
// Blending state
[HideInInspector] _Mode ("__mode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
[Enum(Off,0,Front,1,Back,2)] _Culling("Culling", Float) = 0
}
SubShader
{
Tags { "Queue"="Geometry" }
Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
Cull [_Culling]
LOD 300
CGPROGRAM
#include "UnityStandardInput.cginc"
struct Input {
float2 uv_DetailMask;
float2 uv2_BumpMap;
float facing : SV_IsFrontFace;
#if defined(_PARALLAXMAP) && (SHADER_TARGET >= 30)
float3 viewDir;
#endif
};
#pragma target 3.0
#pragma surface surf Standard fullforwardshadows dithercrossfade interpolateview keepalpha
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature_local _METALLICGLOSSMAP
#pragma shader_feature_local _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature_local _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature_local _ _DETAIL_MULX2
#pragma shader_feature_local _PARALLAXMAP
float2 TRANS_TEX(float2 uv, float4 samplerST)
{
return uv * samplerST.xy + samplerST.zw;
}
float4 GetTexCoords(Input v)
{
float4 texcoord;
texcoord.xy = TRANS_TEX(v.uv_DetailMask, _MainTex_ST); // Always source from uv0
texcoord.zw = (_UVSec == 0) ? texcoord.xy : TRANS_TEX(v.uv2_BumpMap, _DetailAlbedoMap_ST);
return texcoord;
}
half4 GetAlbedo(float4 texcoords)
{
half4 col = _Color * tex2D(_MainTex, texcoords.xy);
half3 albedo = col.rgb;
#if _DETAIL
#if (SHADER_TARGET < 30)
half mask = 1;
#else
half mask = DetailMask(texcoords.xy);
#endif
half3 detailAlbedo = tex2D(_DetailAlbedoMap, texcoords.zw).rgb;
#if _DETAIL_MULX2
albedo *= LerpWhiteTo(detailAlbedo * unity_ColorSpaceDouble.rgb, mask);
#elif _DETAIL_MUL
albedo *= LerpWhiteTo(detailAlbedo, mask);
#elif _DETAIL_ADD
albedo += detailAlbedo * mask;
#elif _DETAIL_LERP
albedo = lerp(albedo, detailAlbedo, mask);
#endif
#endif
return half4(albedo.rgb, col.a);
}
float GetAlpha(float texAlpha)
{
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
return _Color.a;
#else
return texAlpha * _Color.a;
#endif
}
void surf (Input IN, inout SurfaceOutputStandard o) {
float4 coords = GetTexCoords(IN);
#if defined(_PARALLAXMAP) && (SHADER_TARGET >= 30)
coords = Parallax(coords, IN.viewDir);
#endif
half4 albedo = GetAlbedo(coords);
float alpha = GetAlpha(albedo.a);
o.Alpha = alpha;
if (alpha < _Cutoff) { discard; }
o.Albedo = albedo.rgb;
#ifdef _NORMALMAP
o.Normal = NormalInTangentSpace(coords);
#endif
o.Emission = Emission(coords.xy);
half2 mg = MetallicRough(coords.xy);
o.Metallic = mg.r;
o.Smoothness = mg.g;
o.Occlusion = Occlusion(coords.xy);
if (IN.facing < 0.5) {
o.Normal *= -1;
}
}
ENDCG
}
FallBack "Standard"
CustomEditor "StandardShaderGUI"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment