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.

Grayscale to Normal?

Discussion in 'Shaders' started by chingwa, Jan 14, 2011.

  1. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,784
    I am in need of a shader that will convert a grayscale image (bumpmap) into a normal map. It seems that this would be theoretically possible... at least... I can't think of any reasons with my limited shader knowledge why this wouldn't be possible in unity.

    Has anyone here done any work to this affect or have any ideas for accomplishing it? I tried a conversion method listed here:

    http://forum.unity3d.com/threads/5714-bumpmap-%28grayscale%29-to-normalmap-%28rgb%29?p=43006#post43006

    .. using javascript but it was slow enough to be impractical for what I'm looking for. the shader method listed at the same url is incomplete... unfortunately.
     
  2. ToreTank

    ToreTank

    Joined:
    Jun 23, 2008
    Posts:
    165
    It's been some time since I've tested this, but I seem to remember that it used to work. Feel free to clean it up :)

    Code (csharp):
    1.  
    2. Shader "Custom/BumpMap" {
    3.     Properties {
    4.         _MainTex ("Base (RGB)", 2D) = "white" {}
    5.         _HeightMap ("HeightMap (RGB)", 2D) = "black" {}
    6.         //_BumpStrength ("HeightMap strength", Range (0.03, 10)) = 1.0
    7.     }
    8.     SubShader {
    9.       Tags { "RenderType" = "Opaque" }
    10.       CGPROGRAM
    11.       #pragma surface surf BlinnPhong
    12.      
    13.       struct Input {
    14.           float2 uv_MainTex;
    15.       };
    16.       sampler2D _MainTex;
    17.      
    18.       sampler2D _HeightMap;
    19.       uniform float4 _HeightMap_TexelSize;
    20.      
    21.       //uniform float _BumpStrength;
    22.      
    23.       void surf (Input IN, inout SurfaceOutput o)
    24.       {
    25.             float3 normal = float3(0, 0, 1);
    26.        
    27.             float heightSampleCenter = tex2D (_HeightMap, IN.uv_MainTex).r;
    28.             float heightSampleRight = tex2D (_HeightMap, IN.uv_MainTex + float2(_HeightMap_TexelSize.x, 0)).r;
    29.             float heightSampleUp = tex2D (_HeightMap, IN.uv_MainTex + float2(0, _HeightMap_TexelSize.y)).r;
    30.      
    31.             float sampleDeltaRight = heightSampleRight - heightSampleCenter;
    32.             float sampleDeltaUp = heightSampleUp - heightSampleCenter;
    33.      
    34.             //TODO: Expose?
    35.             float _BumpStrength = 3.0f;
    36.      
    37.             normal = cross(
    38.             float3(1, 0, sampleDeltaRight * _BumpStrength),
    39.             float3(0, 1, sampleDeltaUp * _BumpStrength));
    40.      
    41.      
    42.             normal = normalize(normal);
    43.      
    44.             o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;//*0.001 + normal*0.5 + 0.5;
    45.             o.Gloss = 0.9;
    46.             o.Specular = 1;
    47.             o.Normal = normal;
    48.          
    49.       }
    50.       ENDCG
    51.     }
    52.    
    53. }
    54.  
    55.  
     
    zwcloud likes this.
  3. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,784
    Weeeellll... that is certainly a start! :D I'll have to go into the shader and play around a bit until it looks right, but it is certainly starting to approximate a normal map.

    Thanks for the help ToreTank!
     
  4. ToreTank

    ToreTank

    Joined:
    Jun 23, 2008
    Posts:
    165
    Just make sure your source image isn't DXT compressed, that will completely destroy the normal effect :) Also, you should get a better result if you get sample more points around the center instead of only right and up.
     
  5. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,784
    ToreTank, all I can say is that you are my hero of the month!

    Was able to incorporate your code into my existing shaders and get the exact functionality I was looking for. I actually didn't really notice much difference between compressed and uncompressed textures, which is a big plus. :D
     
  6. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,784
    Well now this shader seems to be broken in Unity 3.2 :( I'm glad I saved my old project before upgrading, but If I can't get this to work properly I may have to figure out a different method. ugh. 2 steps forward, one step back.
     
  7. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,784
  8. opponent019_unity

    opponent019_unity

    Joined:
    Feb 1, 2018
    Posts:
    2
    I know this is an old thread but I wanna ask just in case. Do you by any chance still have access to the shader you made with this @chingwa? Would you mind sharing it?
    Thanks!
     
  9. Remy_Unity

    Remy_Unity

    Unity Technologies

    Joined:
    Oct 3, 2017
    Posts:
    645
    An other answer for a zombie thread :) : If you need a normal map but only have a greyscale bump map, instead of creating a custom shader you can set your bump map to import as a normal map, and enable "Create from Grayscale", and tweek the bumpiness and filtering setting. You'll then have a normal map that suits to a lot of the shaders provided by Unity.
     
  10. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,784
    @Remy_Unity In most cases this is what you would want to do , but the original question was asking for a way to do this on-the-fly, rather than as an editor setting. I was using a generated grayscale texture and wanting to extract the normal info from grayscale directly in the shader.

    @opponent019_unity The solution from @ToreTank above still works. I've put it into a modern Unity PBR shader below. Do note that you do lose some quality in the normal rendering by doing it this way. If you need the best quality then you should do it in the editor if possible.

    Code (CSharp):
    1. Shader "Custom/CustomGrayscaleNormal" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _GrayTex ("GrayScale Normal", 2D) = "white" {}
    6.         _NormStrength ("Normal Strength", Range(0,3)) = 3.0
    7.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    8.         _Metallic ("Metallic", Range(0,1)) = 0.0
    9.     }
    10.     SubShader {
    11.         Tags { "RenderType"="Opaque" }
    12.         LOD 200
    13.      
    14.         CGPROGRAM
    15.         #pragma surface surf Standard fullforwardshadows
    16.         #pragma target 3.0
    17.  
    18.         struct Input {
    19.             float2 uv_MainTex;
    20.             float2 uv_GrayTex;
    21.         };
    22.  
    23.         sampler2D _MainTex;
    24.         sampler2D _GrayTex;
    25.         uniform float4 _GrayTex_TexelSize;
    26.         half _Glossiness;
    27.         half _Metallic;
    28.         fixed4 _Color;
    29.         half _NormStrength;
    30.  
    31.         void surf (Input IN, inout SurfaceOutputStandard o) {
    32.             //Albedo
    33.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    34.             o.Albedo = c.rgb;
    35.  
    36.             //Calculate Normal from Grayscale
    37.             float3 graynorm = float3(0, 0, 1);
    38.             float heightSampleCenter = tex2D (_GrayTex, IN.uv_GrayTex).r;
    39.             float heightSampleRight = tex2D (_GrayTex, IN.uv_GrayTex + float2(_GrayTex_TexelSize.x, 0)).r;
    40.             float heightSampleUp = tex2D (_GrayTex, IN.uv_GrayTex + float2(0, _GrayTex_TexelSize.y)).r;
    41.             float sampleDeltaRight = heightSampleRight - heightSampleCenter;
    42.             float sampleDeltaUp = heightSampleUp - heightSampleCenter;
    43.             graynorm = cross(
    44.             float3(1, 0, sampleDeltaRight * _NormStrength),
    45.             float3(0, 1, sampleDeltaUp * _NormStrength));
    46.  
    47.             o.Normal = normalize(graynorm);
    48.    
    49.             //PBR Settings
    50.             o.Metallic = _Metallic;
    51.             o.Smoothness = _Glossiness;
    52.             o.Alpha = c.a;
    53.         }
    54.         ENDCG
    55.     }
    56.     FallBack "Diffuse"
    57. }
    58.  
     
    Tyn3 likes this.
  11. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,600
    Is there any way to set this from code? I cant find it!..
     
  12. Remy_Unity

    Remy_Unity

    Unity Technologies

    Joined:
    Oct 3, 2017
    Posts:
    645
    theforgot3n1 likes this.