2

I am attempting to write a cubemap shader that can be applied to any geometry, with the goal to create a Holodeck-like effect. This shader would be applied to the walls/floor/ceiling of a room, and give the appearance that the room is much bigger than it is. I am using Unity 2022 with the built-in pipeline.

enter image description here

After much trial and error, I was able to recreate the simple parallax cubemap effect, however, only certain aspects of geometry behind it will still be rendered. Perhaps fog, ambient occlusion, global illumination, my "computer vision" shader which relies on the Z-buffer seem to be particularly capable of rendering "through" the parallax cubemap surface shader.

Filtered

Left side shows normal geometry that is not occluded by the parallax cubemap surface. This is a normal ol' Standard shader material using yellow as the albedo color; nothing special.

Right side shows the same object, occluded by the parallax cubemap surface. I am using a simple starfield as my cubemap. The parallax cubemap surface shader doing its job by rendering the stars... except for not blocking SOME aspects of the geometry behind it.

This is one screenshot by the way, I just positioned a parallax cubemap surface to partially obstruct the yellow geometry.

I have proven that this strange "partial blocking" applies to any surfaces that are behind the parallax cubemap surface, regardless of shader, and render order.

Here is the complete parallax cubemap shader:

Shader "Custom/ParallaxCubemap" 
{
    Properties 
    {
        _FrontTex ("FrontTex", 2D) = "white" {}
        _BackTex ("BackTex", 2D) = "white" {}
        _LeftTex ("LeftTex", 2D) = "white" {}
        _RightTex ("RightTex", 2D) = "white" {}
        _UpTex ("UpTex", 2D) = "white" {}
        _DownTex ("DownTex", 2D) = "white" {}
    }

    SubShader 
    {
        Tags {"Queue"="Geometry" "RenderType"="Opaque" "LightMode"="Always"}
        ZWrite On
        Lighting Off
        LOD 100

        CGPROGRAM
        #pragma surface surf Unlit noambient noshadow novertexlights nolightmap nodynlightmap nodirlightmap nofog nometa nolppv noshadowmask noforwardadd
        #pragma target 3.0

        sampler2D _FrontTex;
        sampler2D _BackTex;
        sampler2D _LeftTex;
        sampler2D _RightTex;
        sampler2D _UpTex;
        sampler2D _DownTex;

        struct Input 
        {
            float3 worldPos;
            float3 worldNormal;
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            float3 dir = normalize(IN.viewDir);
            float2 uv;

            fixed4 texcolor;
            float3 absDir = abs(dir);
            if (absDir.x >= absDir.y && absDir.x >= absDir.z) 
            {
                uv = dir.yz / absDir.x;
                if (dir.x < 0)
                {
                    uv.y *= -1;
                    texcolor = tex2D(_RightTex, uv * 0.5f + 0.5f);
                }
                else
                {
                    texcolor = tex2D(_LeftTex, uv * 0.5f + 0.5f);
                }
            } 
            else if (absDir.y >= absDir.x && absDir.y >= absDir.z) 
            {
                uv = dir.xz / absDir.y;

                if (dir.y < 0)
                {
                    texcolor = tex2D(_UpTex, uv * 0.5f + 0.5f);
                }
                else
                {
                    texcolor = tex2D(_DownTex, uv * 0.5f + 0.5f);
                }
            } 
            else 
            {
                uv = dir.xy / absDir.z;

                if (dir.z < 0)
                {
                    texcolor = tex2D(_FrontTex, uv * -0.5f + 0.5f);
                }
                else
                {
                    uv.x *= -1;
                    texcolor = tex2D(_BackTex, uv * -0.5f + 0.5f);
                }
            }

            o.Albedo = texcolor.rgb;
            o.Normal = IN.worldNormal;
            o.Emission = fixed3(0,0,0);
            o.Specular = 0;
            o.Gloss = 0;
            o.Alpha = 1.0f;
        }

        half4 LightingUnlit(SurfaceOutput s, half3 lightDir, half atten)
        {
            return half4(s.Albedo, 1.0f);
        }

        ENDCG
    }
}

EDIT: Switching to Lambert lighting model does fix the "partial obstruction" issues, but then fog impacts the ParallaxCubemap surfaces, which is not ideal, but much better than seeing through walls!

Any ideas would be deeply appreciated!

Zoop
  • 965
  • 1
  • 13
  • 24
  • So you want the yellow object to be completely (rather than only partially) visible through the starfield? – CrazyChucky May 12 '23 at 16:32
  • Actually, the opposite. The ParallaxCubeMap material, which is using starfield textures, and applied to normal geometry like a cube, should overwrite any objects that are behind it, just like it was a normal standard shader. – Zoop May 13 '23 at 18:09

0 Answers0