Need a quick way to turn a model into two-sided geometry without manually remodeling it.
That’s for the purposes of using the model with unity cloth system.
One would think it would be a fairly easy to slap a geometry shader but with surface shaders that’s not the case.
The question is valid till Monday 5:00 UTC+03.
Can’t you just duplicate the geometry, flip all normals, merge back into 1 mesh?
bgolus
December 11, 2016, 5:27pm
3
You can buy this asset.
Discover the best assets for game making. Choose from our massive catalog of 2D, 3D models, SDKs, templates, and tools to speed up your game development process.
Otherwise there are several examples on the forum already on how to do this. Search for two sided or double sided standard shader.
The main parts are, Cull Off, VFACE, and flipping the normal on back faces.
There are mentions that this messes up cloth due to duplicate normals. Not sure if this is true, and I’m still too busy with other stuff to investigate.
I don’t need “legacy”. I need standard PBR based built-in shader.
Already searched, didn’t find the sample I was looking for (with geometry shader + normal inversion).
bgolus
December 11, 2016, 7:11pm
5
That asset is actually “Double Sided Standard, Mobile, and Legacy Shaders”, but the title is missing the commas and the “and”, where the “Standard” is Unity’s PBR shader. It includes double sided versions of all of the various “sets” of shaders that come with Unity.
And the problem is you’re looking for a solution using geometry shaders when none is needed.
bgolus:
That asset is actually “Double Sided Standard, Mobile, and Legacy Shaders”, but the title is missing the commas and the “and”, where the “Standard” is Unity’s PBR shader. It includes double sided versions of all of the various “sets” of shaders that come with Unity.
And the problem is you’re looking for a solution using geometry shaders when none is needed.
Look, if you disable culling on standard shader, lighting on the other side will be, well, strange.
The cleanest way would be to emit extra faces, which is done in geometry shader. Without that you’ll need either hack standard shader (which will break after next update), or abandon idea with pbr and write both passes, shadowcasters and all that stuff.
bgolus
December 11, 2016, 7:27pm
7
neginfinity:
Look, if you disable culling on standard shader, lighting on the other side will be, well, strange
The lighting is strange because the surface normals are facing away from you when looking at the back faces. The solution is to flip the normal direction in the surface shader based on the facing, and VFACE is the semantic for knowing if a tri is facing towards or away.
Geometry shaders can be used to do the same thing, but at a greater cost.
Again, search the forums for VFACE and you’ll come across several examples of using it to flip the normal in a double sided surface shader. (Most probably written by me.)
1 Like
Found a solution.
Shader "Custom/CloakShader" {
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
}
SubShader {
Tags { "RenderType"="Opaque" "PreviewType"="Plane" }
LOD 200
Cull Off
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;
struct Input {
float2 uv_MainTex;
fixed facing: VFACE;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
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;
float tmp = IN.facing;
o.Normal = float3(0.0, 0.0, step(0.5f, IN.facing) * 2.0 - 1.0);
}
ENDCG
}
FallBack "Diffuse"
}
Requires “TwoSidedShadows” mode is shadowcasting is enabled.
Unsubscribing from the thread.
1 Like
bgolus
December 11, 2016, 8:35pm
9
neginfinity:
Found a solution.
Shader "Custom/CloakShader" {
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
}
SubShader {
Tags { "RenderType"="Opaque" "PreviewType"="Plane" }
LOD 200
Cull Off
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;
struct Input {
float2 uv_MainTex;
fixed facing: VFACE;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
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;
float tmp = IN.facing;
o.Normal = float3(0.0, 0.0, step(0.5f, IN.facing) * 2.0 - 1.0);
}
ENDCG
}
FallBack "Diffuse"
}
Requires “TwoSidedShadows” mode is shadowcasting is enabled.
Unsubscribing from the thread.
VFACE value is always a -1 or 1, the step() is unnecessary.
You can add to the shader a custom shadow caster pass with culling off as well to avoid the need for setting two sided shadows on the renderer. I don’t remember if just addshadow on the #pragma surface line is enough or if you need to add it manually.
bgolus:
VFACE value is always a -1 or 1, the step() is unnecessary.
You can add to the shader a custom shadow caster pass with culling off as well to avoid the need for setting two sided shadows on the renderer. I don’t remember if just addshadow on the #pragma surface line is enough or if you need to add it manually.
Apparently the solution I posted earlier refuses to play nice with directional shadows. Even if the mesh has “Dual shadows” enabled.
Grrr…
Don’t have the time to fix this right now. :-\
1 Like
bgolus
December 11, 2016, 9:56pm
11
The custom shadow caster pass fixes that. Or, again, that asset.
Quick and dirty fix:
Shader "Custom/CloakShader" {
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
}
SubShader {
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual
Cull Off
CGPROGRAM
#pragma target 3.0
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma multi_compile_shadowcaster
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#include "UnityStandardShadow.cginc"
ENDCG
}
Tags { "RenderType"="Opaque" "PreviewType"="Plane" }
LOD 200
Cull Off
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;
struct Input {
float2 uv_MainTex;
fixed facing: VFACE;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
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;
float tmp = IN.facing;
o.Normal = float3(0.0, 0.0, step(0.5f, IN.facing) * 2.0 - 1.0);
//o.Normal.z *= step(IN.facing, 0.5f) * 2.0 - 1.0;
//o.Normal = lerp(o.Normal, -o.Normal, step(IN.facing, 0.5f));
}
ENDCG
}
FallBack "Diffuse"
}
That seems to be working
1 Like
old thread but thanks for the shader! seems to be working quite well on my first google attempt to find a double sided cloth solution.