1
\$\begingroup\$

I have a building, built in blender, that has been imported to Unity. And I flipped every necessary piece and calculated the normals inside in blender. However, since I made the rooms inside the building with just a single cube, it's only visible from one side like they're not visible until I go the way around. Is there a way to solve this?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You usually do not want your polygons to draw from both sides in a game.

If you're standing outside a building, you want to see the outside faces that point toward you. You don't want to waste time and GPU resources drawing the back side of the building.

Similarly when you're standing inside a building, you want to see the faces of the interior walls. You don't want to waste time drawing the outside of the building that's not visible from where you're standing.

This lets us cut down the GPU workload by almost a factor of 2 - a huge savings! (Imagine being able to take a game and double its fps rate without sacrificing visual quality on any visible surface)

If you configure your polygons to be drawn from both sides, you lose this optimization, so the GPU has to spend time drawing the inner faces of things only to draw over them with the outer face later.

Also, the mesh still has only one shading normal, so your shader needs to detect when it's drawing the "wrong" side of the polygon and flip the normal for lighting, slightly increasing the complexity of your shader.

For all of these reasons, I would strongly recommend that you keep your material single-sided. Interior rooms should have their own polygons, separate from the outer shell of the building (real walls have thickness, after all), that face inward. If you make these interiors a separate mesh, they can be culled entirely when not visible from the outside, if you set up your scene appropriately.

That said, if you want a dual-sided material, here's how you can modify the default new Surface Shader to accomplish it:

  1. Add Cull Off to the top of the shader, just before CGPROGRAM. This says not to cull triangles based on their facing direction, so both the fronts and backs of triangles will be draw.

  2. Add fixed facing : VFACE; to your Input structure. This is a special shader semantic that the GPU pipeline will populate with a negative value when drawing the back of a triangle, and a positive value for the front.

  3. Inside your surf function, add o.Normal = o.Normal * IN.facing; to flip the normal for back faces.

Here's the full shader:

Shader "Custom/DoubleSidedLit"
{
    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 Off

        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;

        struct Input
        {
            float2 uv_MainTex;
            fixed facing : VFACE;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            o.Normal = o.Normal * IN.facing;

            // 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"
}
\$\endgroup\$
1
  • \$\begingroup\$ You're the life savior! I don't know about Shaders or anything. I just made my school building. And oh, you're the one from yesterday, haha. I really am into modelling 3Ds and making my characters move. But since our school have something called "a final project" for year ending. I want to include a game login system on my little django server and I want to make the building my own school, so I could get more points for creativity or something. And I have been drag-and-drop'ing everything and copying every free assets and scripts. Thank you for your help, appreciate it!! \$\endgroup\$
    – Kyi Zin
    Aug 23, 2020 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .