Created
March 29, 2025 12:42
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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