I have zero experience in shaders aside from using a forum post to modify the Standard Shader to make it double sided.
However, the “back side” that now shows is very shiny, much more than the front side. Is there a way to modify this or otherwise fix this visual effect?
The problem is the normals for the back side are still pointing the same way, which is away from you. Most PBR calculations (Unity’s Standard shader included) don’t really handle this case because in the real world it’s not possible for a surface to not be pointing toward the viewer and still be seen.
The fix is testing if the normals are facing towards the camera or not and flip the Z if they’re facing away. There’s some examples on the forum if you search for them. The correct way to do this is using the VFACE semantic, but most people just use a dot product of the normal and the view direction.
Thanks! Per a unity doc, I found the following code. I have about 99% no idea what’s going on, but best I can tell, the last line is basically saying “if it’s front, show this, if it’s back ,show that”
float4 vert (float4 vertex : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertex);
}
fixed4 _ColorFront;
fixed4 _ColorBack;
fixed4 frag (fixed facing : VFACE) : SV_Target
{
// VFACE input positive for frontbaces,
// negative for backfaces. Output one
// of the two colors depending on that.
return facing > 0 ? _ColorFront : _ColorBack;
}
However, _ColorFront & _ColorBack are black – I replace that with _Color, which is part of the shader, and sure enough that color shows up. I think I need it to display _MainTex, though, which throws an error when I try to use it.
" cannot implicitly convert from ‘const sampler2D’ to ‘half4’ at line 99 (on glcore)"
Any ideas how to get the main texture to be used instead?
Huh. Ok – thanks! I’m sure that’s helpful, but I’m looking at the nvidia and unity docs for “tex2D”, and while the concept roughly makes sense, I’m not at all sure how to go about getting any other aspect of what’s required to fill that function. Unfortunately I can’t see any similar code in the Unity standard shader script either to jump off from.
Im not sure if this would help you, but, i had a problem with double sided normals and i added the code
SubShader {
Tags { "RenderType" = "Opaque" }
Cull off
// Cull off supports double sided normals
Adding Cull off made the toon lit shader support double sided normals without a hitch, maybe it will work with your shader too?
Im noob, so not sure if this would work.
He’s already done this. The problem is that this doesn’t do double sided normals, this does double sided surfaces with single sided normals.
Imagine you have an opaque ball with light coming from above. The top of the ball will naturally be lit. Now let’s turn on front face culling so we’re only seeing back faces. The result will look about the same as the “top” faces are lit even though we’re now seeing the inside of the ball and it’s the bottom faces that should now be lit because the back faces’ normals are still pointing the same way as the front faces.
Yep. Unfortunately I can’t figure out how to get the back sides to render properly. I have no idea where to even start looking – I went through the standard shader and it’s includes, but nothing made sense to me.
I’m guessing it’s the last bit from the unity doc examples?
This throws an error, as I didn’t declare “o” variable. All of the shader stuff is really really new to me – as in I’ve never looked at it before
Below is part of my code – I’m attaching the current shader I have – the “working” one, that’s 2-sided but looks funky, and the one I’m working on. Where (And how?) do I declare the o variable? And is that last function where I should put the code? (the “surf” function?)
float4 vert (float4 vertex : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertex);
}
struct Input {
fixed facing : VFACE;
};
fixed4 _ColorFront;
fixed4 _ColorBack;
fixed4 frag (fixed facing : VFACE) : SV_Target
{
o.Normal.z *= saturate(IN.facing) * 2.0 - 1.0;
// VFACE input positive for frontbaces,
// negative for backfaces. Output one
// of the two colors depending on that.
// fixed4 col = tex2D(_MainTex, uv_MainTex); // need to pass uvs through from vert function
//return facing > 0 ? col : _ColorBack;
}
Here’s a basic example shader. The naming for the normal flip mode isn’t great, but one acts like the surface is a peice of plastic or metal that’s been stamped / molded so when you see the backside it’s the inverted surface normals, and the other makes both sides look the same.
Shader "Custom/Two Sided SurfaceShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
[NoScaleOffset] _MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
[Gamma] _Metallic ("Metallic", Range(0,1)) = 0.0
[NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
[Enum(Flip,0,Invert,1)] _BumpFlipMode("Normal Flip Mode", Float) = 0
}
SubShader {
Tags { "RenderType"="Opaque" }
Cull Off
LOD 200
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;
sampler2D _BumpMap;
struct Input {
float2 uv_MainTex;
fixed facing : VFACE;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
bool _BumpFlipMode;
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;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
// Test if looking at the backface.
if (IN.facing < 0.5)
{
if (_BumpFlipMode)
o.Normal *= -1.0;
else
o.Normal.z *= -1.0;
}
}
ENDCG
}
FallBack "Diffuse"
}
We have our specular in the alpha of the map, so it’s currently in the MetalRough standard shader.
Below is what it looks like now – using two materials, the top one being “Fade” (shown) and the bottom being a Cutout one with the same maps. That’s the best look I’ve been able to get so far. Using the double-sided version from before makes the hair look a bit more thick and normal (esp. from certain angles), but of course is shiny.
The male head is from the modelers application, and is how he intended it to look, using the standard shader in 3ds Max.
I’m running into a small problem, and i’m not sure where in the shader this is coming from. In some lighting, the transparent parts of the hair give a light visible film to the image. Like in the shot attached. Any idea where this is coming from?