+6

Support for Single Pass Stereo Rendering Method when using Refraction

CodeFlow 7 years ago updated by MartinMoon 7 years ago 7

When using refraction I manually need to modify the shader to work with Single Pass stereo renderering. It would be nice if this can be supported by shaderforge since manually editing my refraction shaders is messing up my workflow :)


See this link for an example on how to enable single pass stereo rendering when using refraction -> https://forum.unity3d.com/threads/single-pass-stereo-rendering-doesnt-work-with-glassrefraction-effect-of-effects-package.418239/

Can you show us the modification? I don't know how to apply the code from that post. The shader generated by shaderforge is too different from what I can read in GlassStainedBumpDistort.shader
Regards.

Edit:
Made this one, which is working well in single stereo without using that code. This is so confusing :)

Maybe they modified UNITY_PROJ_COORD or ComputeScreenPos to do the job by default?


Shader "Shader Forge/refract stereo single pass test" {
Properties {
_Color ("Color", Color) = (0.07843138,0.3921569,0.7843137,1)
_node_9734 ("node_9734", 2D) = "bump" {}
_node_8661 ("node_8661", Range(0, 1)) = 0
[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {
"IgnoreProjector"="True"
"Queue"="Transparent"
"RenderType"="Transparent"
}
GrabPass{ }
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase
#pragma only_renderers d3d9 d3d11 glcore gles gles3 metal
#pragma target 3.0
uniform sampler2D _GrabTexture;
uniform float4 _Color;
uniform sampler2D _node_9734; uniform float4 _node_9734_ST;
uniform float _node_8661;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
o.screenPos = ComputeScreenPos(o.pos);
return o;
}
float4 frag(VertexOutput i) : COLOR {
#if UNITY_UV_STARTS_AT_TOP
float grabSign = -_ProjectionParams.x;
#else
float grabSign = _ProjectionParams.x;
#endif



float3 _node_9734_var = UnpackNormal(tex2D(_node_9734,TRANSFORM_TEX(i.uv0, _node_9734)));
float2 dist =(_node_9734_var.rgb.rg*_node_8661);
i.screenPos.xy += dist;
float4 sceneColor = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.screenPos));
////// Lighting:
////// Emissive:
float3 emissive = _Color.rgb;
float3 finalColor = emissive;
return fixed4(lerp(sceneColor.rgb, finalColor,_Color.a),1);
}
ENDCG
}
}
FallBack "Diffuse"

}

Hmmm, I still have to do manual editing of my shader to work with singlepass. If it helps anyone out there I will post the original and modified version of my shaderforge shader below ...

So this is my shader in shaderforge,

It produces a simple ripple effect, like this


However , in VR Singlepass it looks like this



This is the original code generated by shaderforge :

Shader "Shader Forge/Refract" {
Properties {
_Amplitude ("Amplitude", Range(0, 1)) = 0
_Frequency ("Frequency", Range(0, 100)) = 0
[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {
"IgnoreProjector"="True"
"Queue"="Transparent"
"RenderType"="Transparent"
}
GrabPass{ }
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase
#pragma only_renderers d3d9 d3d11 glcore gles n3ds wiiu
#pragma target 3.0
uniform sampler2D _GrabTexture;
uniform float _Amplitude;
uniform float _Frequency;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.pos = UnityObjectToClipPos(v.vertex );
o.screenPos = o.pos;
return o;
}
float4 frag(VertexOutput i) : COLOR {
#if UNITY_UV_STARTS_AT_TOP
float grabSign = -_ProjectionParams.x;
#else
float grabSign = _ProjectionParams.x;
#endif
i.screenPos = float4( i.screenPos.xy / i.screenPos.w, 0, 0 );
i.screenPos.y *= _ProjectionParams.x;
float node_4241 = (_Frequency*i.uv0.r);
float node_2277 = cos((node_4241*2.0+-1.0));
float2 sceneUVs = float2(1,grabSign)*i.screenPos.xy*0.5+0.5 + float2(0.0,(node_2277*_Amplitude));
float4 sceneColor = tex2D(_GrabTexture, sceneUVs);
////// Lighting:
float3 finalColor = 0;
return fixed4(lerp(sceneColor.rgb, finalColor,0.0),1);
}
ENDCG
}
}
FallBack "Diffuse"
CustomEditor "ShaderForgeMaterialInspector"
}


And this is the modified version that works with singlepass stereo rendering :


Shader "Shader Forge/Refract" {
Properties {
_Amplitude ("Amplitude", Range(0, 1)) = 0
_Frequency ("Frequency", Range(0, 100)) = 0
[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {
"IgnoreProjector"="True"
"Queue"="Transparent"
"RenderType"="Transparent"
}
GrabPass{ }
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase
#pragma only_renderers d3d9 d3d11 glcore gles n3ds wiiu
#pragma target 3.0
uniform sampler2D _GrabTexture;
uniform float _Amplitude;
uniform float _Frequency;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.pos = UnityObjectToClipPos(v.vertex );

#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.screenPos.xy = (float2(o.pos.x, o.pos.y*scale) + o.pos.w) * 0.5;
o.screenPos.zw = o.pos.zw;
return o;
}
float4 frag(VertexOutput i) : COLOR {
#if UNITY_SINGLE_PASS_STEREO
i.screenPos.xy = TransformStereoScreenSpaceTex(i.screenPos.xy, i.screenPos.w);
#endif
float node_4241 = (_Frequency*i.uv0.r);
float node_2277 = cos((node_4241*2.0+-1.0));
float2 sceneUVs = UNITY_PROJ_COORD(i.screenPos.xy) + float2(0.0,(node_2277*_Amplitude));
i.screenPos.xy = sceneUVs.xy;
float4 sceneColor = tex2Dproj(_GrabTexture, i.screenPos);
////// Lighting:
float3 finalColor = 0;
return fixed4(lerp(sceneColor.rgb, finalColor,0.0),1);
}
ENDCG
}
}
FallBack "Diffuse"
CustomEditor "ShaderForgeMaterialInspector"
}




Can you bold the changes in the fixed version to easily point the changes?

as you wish, sir

This is the original code generated by shaderforge :

Shader "Shader Forge/Refract" {
Properties {
_Amplitude ("Amplitude", Range(0, 1)) = 0
_Frequency ("Frequency", Range(0, 100)) = 0
[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {
"IgnoreProjector"="True"
"Queue"="Transparent"
"RenderType"="Transparent"
}
GrabPass{ }
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase
#pragma only_renderers d3d9 d3d11 glcore gles n3ds wiiu
#pragma target 3.0
uniform sampler2D _GrabTexture;
uniform float _Amplitude;
uniform float _Frequency;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.pos = UnityObjectToClipPos(v.vertex );
o.screenPos = o.pos;
return o;
}
float4 frag(VertexOutput i) : COLOR {
#if UNITY_UV_STARTS_AT_TOP
float grabSign = -_ProjectionParams.x;
#else
float grabSign = _ProjectionParams.x;
#endif
i.screenPos = float4( i.screenPos.xy / i.screenPos.w, 0, 0 );
i.screenPos.y *= _ProjectionParams.x;
float node_4241 = (_Frequency*i.uv0.r);
float node_2277 = cos((node_4241*2.0+-1.0));
float2 sceneUVs = float2(1,grabSign)*i.screenPos.xy*0.5+0.5 + float2(0.0,(node_2277*_Amplitude));
float4 sceneColor = tex2D(_GrabTexture, sceneUVs);
////// Lighting:
float3 finalColor = 0;
return fixed4(lerp(sceneColor.rgb, finalColor,0.0),1);
}
ENDCG
}
}
FallBack "Diffuse"
CustomEditor "ShaderForgeMaterialInspector"
}

And this is the modified version that works with singlepass stereo rendering :

Shader "Shader Forge/Refract" {
Properties {
_Amplitude ("Amplitude", Range(0, 1)) = 0
_Frequency ("Frequency", Range(0, 100)) = 0
[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {
"IgnoreProjector"="True"
"Queue"="Transparent"
"RenderType"="Transparent"
}
GrabPass{ }
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase
#pragma only_renderers d3d9 d3d11 glcore gles n3ds wiiu
#pragma target 3.0
uniform sampler2D _GrabTexture;
uniform float _Amplitude;
uniform float _Frequency;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.pos = UnityObjectToClipPos(v.vertex );

#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.screenPos.xy = (float2(o.pos.x, o.pos.y*scale) + o.pos.w) * 0.5;
o.screenPos.zw = o.pos.zw;
return o;

}
float4 frag(VertexOutput i) : COLOR {
#if UNITY_SINGLE_PASS_STEREO
i.screenPos.xy = TransformStereoScreenSpaceTex(i.screenPos.xy, i.screenPos.w);
#endif

float node_4241 = (_Frequency*i.uv0.r);
float node_2277 = cos((node_4241*2.0+-1.0));
float2 sceneUVs = UNITY_PROJ_COORD(i.screenPos.xy) + float2(0.0,(node_2277*_Amplitude));
i.screenPos.xy = sceneUVs.xy;
float4 sceneColor = tex2Dproj(_GrabTexture, i.screenPos);

////// Lighting:
float3 finalColor = 0;
return fixed4(lerp(sceneColor.rgb, finalColor,0.0),1);
}
ENDCG
}
}
FallBack "Diffuse"
CustomEditor "ShaderForgeMaterialInspector"
}


+3

Posting this here as I was hitting my head on this as well and couldnt get these manual tweaks to work reliably. Here is how you can do it all in shaderforge!  I cannot claim any credit for this. A user by the name of cubedparadox showed me how.


The code block needs an input in float2 form named uv, and the output should also be set to float2.

Here is the code in the codeblock:

float2 uvs = uv;
#if UNITY_SINGLE_PASS_STEREO
uvs = (uv.xy + float2 (unity_StereoEyeIndex,0)) * float2 (.5f,1);
#endif

return uvs;

Awesome Ben, this is a much more elegant solution

When I view this on Rift, the shader only renders to the left eye. Can you post the Blending / Geometry settings?