Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Replace shaders + Single pass stereo + scene mesh using screen coords

Discussion in 'AR/VR (XR) Discussion' started by DavidMiranda, Feb 24, 2017.

  1. DavidMiranda

    DavidMiranda

    Joined:
    Nov 30, 2012
    Posts:
    611
    I have to do some offscreen render textures. These render textures are then used by scene objects later. Everything was fun until I looked to the HMD screen :)

    For simplicity, I have built a refractive shader with shaderforge to test my generated RTs. Then, I made some modifications to sample _GrabTexture with correct uvs in SPSR.

    This is the result (its looking correct in vr and editor):
    Code (CSharp):
    1.  
    2. Shader "Shader Forge/refract stereo single pass test" {
    3.     Properties {
    4.         _Color ("Color", Color) = (0.07843138,0.3921569,0.7843137,1)
    5.         _node_9734 ("node_9734", 2D) = "bump" {}
    6.         _node_8661 ("node_8661", Range(0, 1)) = 0
    7.         [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    8.     }
    9.     SubShader {
    10.         Tags {
    11.             "IgnoreProjector"="True"
    12.             "Queue"="Transparent"
    13.             "RenderType"="Transparent"
    14.         }
    15.         GrabPass{ }
    16.         Pass {
    17.             Name "FORWARD"
    18.             Tags {
    19.                 "LightMode"="ForwardBase"
    20.             }
    21.             Blend SrcAlpha OneMinusSrcAlpha
    22.             ZWrite Off
    23.        
    24.             CGPROGRAM
    25.             #pragma vertex vert
    26.             #pragma fragment frag
    27.             #define UNITY_PASS_FORWARDBASE
    28.             #include "UnityCG.cginc"
    29.             #pragma multi_compile_fwdbase
    30.             #pragma only_renderers d3d9 d3d11 glcore gles gles3 metal
    31.             #pragma target 3.0
    32.             uniform sampler2D _GrabTexture;
    33.             uniform float4 _Color;
    34.             uniform sampler2D _node_9734; uniform float4 _node_9734_ST;
    35.             uniform float _node_8661;
    36.             struct VertexInput {
    37.                 float4 vertex : POSITION;
    38.                 float2 texcoord0 : TEXCOORD0;
    39.             };
    40.             struct VertexOutput {
    41.                 float4 pos : SV_POSITION;
    42.                 float2 uv0 : TEXCOORD0;
    43.                 float4 uvgrab : TEXCOORD1;
    44.             };
    45.             VertexOutput vert (VertexInput v) {
    46.                 VertexOutput o = (VertexOutput)0;
    47.                 o.uv0 = v.texcoord0;
    48.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
    49.                 o.uvgrab = ComputeScreenPos(o.pos);
    50.                 return o;
    51.             }
    52.             float4 frag(VertexOutput i) : COLOR {
    53.                 #if UNITY_UV_STARTS_AT_TOP
    54.                     float grabSign = -_ProjectionParams.x;
    55.                 #else
    56.                     float grabSign = _ProjectionParams.x;
    57.                 #endif
    58.  
    59.                 float3 _node_9734_var = UnpackNormal(tex2D(_node_9734,TRANSFORM_TEX(i.uv0, _node_9734)));
    60.                float2 dist =(_node_9734_var.rgb.rg*_node_8661);
    61.                i.uvgrab.xy += dist;
    62.                 float4 sceneColor = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
    63. ////// Lighting:
    64. ////// Emissive:
    65.                 float3 emissive = _Color.rgb;
    66.                 float3 finalColor = emissive;
    67.                 return fixed4(lerp(sceneColor.rgb, finalColor,_Color.a),1);
    68.             }
    69.             ENDCG
    70.         }
    71.     }
    72.     FallBack "Diffuse"
    73.    // CustomEditor "ShaderForgeMaterialInspector"
    74. }
    75.  
    Next step was to substitute _GrabTexture with my RT, which was generated using a copy of the main camera and performing RenderWithShader. But nope, it is not that simple. Seems like I have to so something else in the RT camera. But what? I don't know.
    The internal method to generate _GrabTexture does some secret magic that I need to replicate, I think.

    Let's compare my custom depth with the generated _CameraDepthTexture:

    2017-02-24_17-54-00.jpg 2017-02-24_17-54-55.jpg

    There is some black magic in _CameraDepthTexture generation process to pack both eyes in the same RT. I bet each half is rendered separately with a different Camera.rect.

    Ideas?
     
    Last edited: Feb 24, 2017
    rod-lopez likes this.
  2. scottb

    scottb

    Unity Technologies

    Joined:
    Jan 26, 2016
    Posts:
    13
    You should use ComputeNonStereoScreenPos() to access textures that aren't in stereo.
     
  3. DanielDickinson

    DanielDickinson

    Joined:
    Aug 4, 2013
    Posts:
    277
    Is it possible to perform shader replacement with single pass stereo?

    I'm trying to setup shader replacement to render high-precision normal's into a render texture. And later using a command buffer to render "masked objects" into another render texture.

    After using CustomCamera.CopyFrom(SourceCamera), polling the CustomCamera.stereoEnabled property returns false, and it's not settable, so there appears no way to enable it on the custom camera. Currently it appears as if the left eye is simply stretched over the entire texture.

    The next idea was to split the render texture in two and render each eye separately into there perspective half of the texture, not ideal, but it would at least work. But setting the stereoTargetEye appears to have no effect, so I'm left with a render containing 2 copies of the left eyes perspective, instead of one the left and the right combined, as I'd hoped.

    So what is the correct way to perform single pass stereo shader replacement? I believe you guys use a similar method internally to render your depthtexturemodes?

    The same issue appears to be occurring with command buffers (left eye perspective stretched over entire sceen), so what is the correct way to render single pass stereo objects using command buffers?

    Rendering the texture as a non-stereo render-texture and accessing it doesn't make a lot of sense when each eye has a different view and projection matrix and essentially sees different normal's / masking.

    Any help would be appreciated, cheers
    Dan
     
  4. scottb

    scottb

    Unity Technologies

    Joined:
    Jan 26, 2016
    Posts:
    13
    We're working on fixes for the command buffer and stereoTargetEye issues. They should be fixed in 5.6 and 2017.1 within the next couple of weeks.
     
    Kronnect likes this.
  5. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    I am still observing the broken behavior in 5.6. Did it not make it in?
     
  6. scheichs

    scheichs

    Joined:
    Sep 7, 2013
    Posts:
    73
    Is there any Unity version > 5.6 that doesn't have unity_StereoEyeIndex always being 0?
     
  7. Epic_Cube_

    Epic_Cube_

    Joined:
    Jul 3, 2012
    Posts:
    97
    @scottb

    Hi all,
    I'm trying to use posto processing with Single-Pass Stereo Rendering on GearVR and DayDream.
    Now using Windows 10 + Unity 2017.2. My mobile device is a Samsung S6.
    My post effect consists of two steps:
    RenderWithShader renders the scene with my very-simple shader that draws everything is visible with White color
    Blit operations to perform more complex operations.
    Now I'm trying to make work the RenderWithShader operation. First of all: is it allowed to use RenderWithShader with single pass stereo rendering, or is there any issue related to its usage? Here it's the script code I use:
    Code (CSharp):
    1. RenderTexture tempRT1 = new RenderTexture( width, height, depth, format );
    2. [...]
    3. MyCamera.targetTexture = tempRT1;
    4. MyCamera.RenderWithShader( drawSimpleShader, "" );
    5. Graphics.Blit( tempRT1, destination );
    6.  
    I added to my shader all the additional instruction described in https://docs.unity3d.com/Manual/Android-SinglePassStereoRendering.html . Here it is the code (anything wrong?):


    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2. Shader "ShaderTest/DrawSimple SPSR"
    3. {
    4.     Properties {
    5.         _MainTex ("Base (RGB)", 2D) = "" {}
    6.     }
    7.     CGINCLUDE
    8.    
    9.     #include "UnityCG.cginc"
    10.     // FOR SINGLE PASS STEREO RENDERING
    11.     //sampler2D _MainTex;
    12.     UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex);
    13.     half4 _MainTex_ST;
    14.     struct appdata
    15.     {
    16.         float4 vertex : POSITION;
    17.         float2 uv : TEXCOORD0;
    18.     };
    19.     struct v2f {
    20.         float2 uv : TEXCOORD0;
    21.         float4 vertex : SV_POSITION;
    22.         UNITY_VERTEX_OUTPUT_STEREO
    23.     };
    24.    
    25.    
    26.    
    27.     v2f vert( appdata v )
    28.     {
    29.         v2f o;
    30.         // FOR SINGLE PASS STEREO RENDERING
    31.         UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    32.         o.vertex = UnityObjectToClipPos(v.vertex);
    33.         o.uv = TRANSFORM_TEX(v.uv, _MainTex); // v.texcoord.xy;
    34.         return o;
    35.     }
    36.    
    37.     fixed4 frag(v2f i) : SV_Target
    38.     {
    39.         //        return 1-tex2D(_MainTex, i.uv);
    40.         // FOR SINGLE PASS STEREO RENDERING
    41.         UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
    42.         half4 col = tex2D(_MainTex, i.uv);
    43.         half val = col.r + col.g + col.b;
    44.         return (val > 0) ? 1 : 0;
    45.     }
    46.     ENDCG
    47.     Subshader
    48.     {
    49.         Pass
    50.         {
    51.               ZTest Always Cull Off ZWrite Off
    52.               CGPROGRAM
    53.               #pragma vertex vert
    54.               #pragma fragment frag
    55.               ENDCG
    56.         }
    57.     }
    58. }
    When I try to play it in my GearVR, I can see only a dark screen with a lighter blinking screen in the upper right corner of my FOV. I expect to see a full-white moving cube, but it is not visible at all.
    Any project/graphics/camera/anything-else setting missing or wrong?
    Please help.
    Thanks