0

I've been having some trouble with randomly perturbing the surface of a sphere with a bump map in Unity (v2021.3.18f1) for a VR application. Here are the steps I've taken so far:

  • created a sphere with radius of 30
  • created a material with maximum opacity (albedo=255) and assigned it to the sphere; the color of the material is green
  • written a custom shader (template=Standard Surface Shader) which does the following things:
    • creates a visible interior surface for the sphere by:
      • duplicating the mesh on the exterior face
      • flipping the normals
      • turning off backface culling
    • applies a bump map to the exterior surface
  • created a bump map in GIMP (100x100 noisy grayscale .png image)
  • imported the bump map as an asset and linked it to the abovementioned material; set the texture type of the bump map to "normal map"
  • set the bump scale to 1.0 to maximize its effect

ChatGPT suggests that the mesh geometry may not be detailed enough to render the bumps. The mesh has over 700 polygons and seems detailed enough but not totally sure, this is my first time using Unity or doing anything with graphics. A screenshot of the wireframe rendering is below. Also, there is a screenshot of the bump map itself.

The environment has a directional light pointing at the sphere at somewhat of an angle. I've tried to create shadows on the surface of the sphere to accentuate any tiny bumps to no avail.

Below the images is the shader code.

Wireframe Rendering of Sphere Mesh

Bump map

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

        // START MODS
        _BumpMap ("Bump Map", 2D) = "bump" {}
        _BumpScale ("Bump Scale", Range(0, 1)) = 1.0
        // END MODS
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        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;
        
        // START MODS
        sampler2D _BumpMap;
        //END MODS

        struct Input
        {
            float2 uv_MainTex;
            
            // START MODS
            float3 worldNormal;
            float3 worldPos;
            INTERNAL_DATA
            // END MODS
        };

        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 assume uniform scaling
        UNITY_INSTANCING_BUFFER_START(Props)
        // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)
        
        // START MODS
        // function to perturb surface normal
        inline float3 perturb_normal(float3 normal, float3 pos, float3 worldNormal, float3 worldTangent)
        {
            float3 map = UnpackNormal(tex2D(_BumpMap, pos.xy));
            map = 2.0 * map - 1.0;
            map.xy *= 1.0; // adjust the bump map strength here
            map = normalize(map);

            // calculate tangent space basis
            float3 worldBinormal = cross(worldNormal, worldTangent);
            float3x3 tangentSpace = float3x3(worldTangent, worldBinormal, worldNormal);

            // perturb normal
            return normalize(mul(tangentSpace, map));
        }

        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;

            // apply bump map to surface normal
            float3 worldNormal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex) * 2.0 - 1.0);
            worldNormal = normalize(worldNormal);
            // use the worldNormal to perturb the surface normal
            o.Normal = perturb_normal(o.Normal, IN.worldPos, worldNormal, IN.worldNormal);
        }
        // END MODS

        ENDCG
        
        // START MODS
        // turn off backface culling
        Cull Off

        // make the mesh double-sided
        Pass
        {
            Name "FORWARD"
            Tags { "LIGHTMODE" = "ForwardBase" }
            ZWrite On
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f {
                float4 pos : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float NORMALIZING_CONST = 255.0;
                float R = 30.0 / NORMALIZING_CONST;
                float G = 245.0 / NORMALIZING_CONST;
                float B = 90.0 / NORMALIZING_CONST;

                return fixed4(R, G, B, 1);
            }
            // END MODS

            ENDCG
        }
    
    }
    FallBack "Diffuse"
}

Why aren't there any bumps on the sphere's surface? What can I do to move towards that goal?

Ender
  • 229
  • 2
  • 8
  • Please view https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned?cb=1 – Razvan S. Mar 12 '23 at 19:00
  • You are right, the link I provided is irrelevant for this case. I also undid the downvote, but I still think that there is an issue with your question. You should try to understand shaders, try writing the whole code yourself and then come with questions here. Pasting generated code is like not providing code at all from my point of view. Suppose I want an answer on this website but I don't want to try anything (not saying that you did that), I just slap some AI generated code to my question and wait for people to do my "homework" for me. – Razvan S. Mar 13 '23 at 12:20
  • Ok, I understand your position. At the same time, integrating and modifying pre-existing code is an accepted practice. As we've established, the fact that it is from ChatGPT isn't relevant in this case. If an engineer is working to modify and integrate pre-existing code into his project, he shouldn't be required to rewrite everything before posting a question on it. As you mentioned, though, he should have a decent grasp of it (continued...) – Ender Mar 14 '23 at 02:52
  • I have taken some time to understand the relevant parts of the code, specifically ```perturb_normal``` and ```surf```. It seems like the code itself is correct. ```perturb_normal``` extracts a vector from the bump map by reading RGB channel information and then projects it onto the tangent plane at that point. This becomes the modified surface normal that is used in ```surf``` for lighting and shading. Even if there is some subtle error in the implementation, it's clear that the surface normal is being changed and yet, there are no discernible changes in the Unity rendering (continued...) – Ender Mar 14 '23 at 02:53
  • The question then is, why are these changes to the normals not propagating? I hope this meets a reasonable bar of expectation for familiarity with the code. Just to be clear, I'm not expecting anyone to write everything for me, just a few thoughts and a productive discussion. Note: I've edited the question to reflect my level of understanding of the code. – Ender Mar 14 '23 at 02:53
  • I'm not an expert on shaders, I'm still learning. I can't run your code, I don't know which render pipeline and settings you are using but to me your normal map texture doesn't look like a normal map at all. Then you unpack the normal and change the domain from [0, 1] to [-1, 1] after that you multiply map.xy by 1 ( multiplying anything by 1 has no effect) and after that you normalize the result which will bring the result back from the [-1, 1] domain to [0, 1]. So after unpacking the normals all those lines of code have no effect. – Razvan S. Mar 19 '23 at 18:26

0 Answers0