Writing a double-sided shader -- How to reverse the normal for back face?

I am trying create a paper page for books with a plane mesh;

The goal is the front page will be using a texture;
and the back side will be say in color white.

I am trying to write my own, simple, double-sided diffuse shader.
I started by basing on the standard Normal-Diffuse shader; but soon hits a wall – the back side does not have the proper normal for lighting, I need to flip the normal somehow, would someone know how to do it?

Thanks a bunch!!

Here’s a snippet

//…

	// Disalbe backface culling...
	Cull Off

//…

	void Surf (Input IN, inout SurfaceOutput o) 
	{
		if (dot(IN.worldNormal, IN.viewDir) > 0)
		{
			// Front side is facing the camera, render as normal
			fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		else
		{
			// back side is facing the camera
			// will just render a plain color as the back of a paper page
			fixed4 c = _Color;  
			o.Albedo = c.rgb;
			o.Alpha = c.a;

			// but the normal is facing away so the color is always dim!!
			// Looking a way to flip the normal somehow...

		}

	}

I’m using this to flip the normals:

float3 n = UnpackNormal(text2D(_Bump, IN.uv_Bump));
o.Normal = dot(IN.viewDir, float3(0, 0, 1)) > 0 ? n : -n;

I tried tossing in o.Normal=-1*IN.normal; and got yelled at for passing too many parms. What seems to work was adding an extra material for the backfaces. The front one can be a normal back-face culling diffuse shader. Have the the 2nd one cull front faces (so it draws only the back faces.) The model is drawn twice, which is about the same work as if you made an extra backplane:

Cull Front
...
// may as well flip in the vert shader, too save time:
#pragma surface surf Lambert vertex:vert

void vert (inout appdata_full v, out Input o) {
  o.Normal = v.Normal*-1;
}

// surf just draws tint color

It seems that shader just for one-side normal…

So maybe you should make a very thin box that makes two opposite normal…

You could get away with it using a multi-pass shader (i.e, one pass for each side), but this may not be the best idea for performance considerations. You can’t outright declare passes in surface shaders, although unity will create passes in order of placement. For correct backface normals, you can do the following:

Shader "Custom/2 Sided" {
	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" }
		LOD 200
		Cull Back

		CGPROGRAM
			// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows alpha

		#pragma target 3.0

		sampler2D _MainTex;

		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 (_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;
		}
		ENDCG

		Cull Front

		CGPROGRAM
			// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows alpha

		#pragma target 3.0
		#pragma vertex vert

		sampler2D _MainTex;

		struct Input {
			float2 uv_MainTex;
		};

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		void vert (inout appdata_full v) {
			v.normal *= -1;
		}

		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;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

This is an example with the built-in standard shader (plus accurate semi-transparency). The key thing to look out for is in the second pass, which renders the backfaces. In this pass, vertex modification is used to flip the normals. Hopefully this helps anyone looking for something similar,

Namey5

Note You should render the backface first for correct blending. I was in a rush at this point in time and forgot to flip that around.