# sobel operator - height to normal map on GPU

Discussion in 'Shaders' started by apple_motion, Oct 30, 2009.

1. ### apple_motion

Joined:
Jul 2, 2009
Posts:
169
For some reason (mostly lazy), I don't want to make the normal map on the editor. so that, I made it on runtime That is based on the Sobel operator

sobel operation...
Code (csharp):
1. float3 height2normal_sobel(float3x3 c)
2. {
3.     float3x3 x = float3x3(   1.0, 0.0, -1.0,
4.                                     2.0, 0.0, -2.0,
5.                                     1.0, 0.0, -1.0  );
6.
7.     float3x3 y = float3x3(   1.0,  2.0,  1.0,
8.                                     0.0,  0.0,  0.0,
9.                                    -1.0, -2.0, -1.0 );
10.
11.     x = x * c;
12.     y = y * c;
13.
14.     float cx =  x[0][0] +x[0][2]
15.                    +x[1][0] +x[1][2]
16.                    +x[2][0] +x[2][2];
17.
18.     float cy =  y[0][0] +y[0][1] +y[0][2]
19.                   +y[2][0] +y[2][1] +y[2][2];
20.
21.     float cz =  sqrt(1-(cx*cx+cy*cy));
22.
23.     return float3(cx, cy, cz);
24. }
( Edit: almost forget the float3x3 could do multiply directly )

Code (csharp):
1. float3x3 img3x3(sampler2D color_map, float2 tc, float ts, int ch)
2. {
3.     float   d = 1.0/ts; // ts, texture sampling size
4.     float3x3 c;
5.     c[0][0] = tex2D(color_map,tc + float2(-d,-d))[ch];
6.     c[0][1] = tex2D(color_map,tc + float2( 0,-d))[ch];
7.     c[0][2] = tex2D(color_map,tc + float2( d,-d))[ch];
8.
9.     c[1][0] = tex2D(color_map,tc + float2(-d, 0))[ch];
10.     c[1][1] = tex2D(color_map,tc                )[ch];
11.     c[1][2] = tex2D(color_map,tc + float2( d, 0))[ch];
12.
13.     c[2][0] = tex2D(color_map,tc + float2(-d, d))[ch];
14.     c[2][1] = tex2D(color_map,tc + float2( 0, d))[ch];
15.     c[2][2] = tex2D(color_map,tc + float2( d, d))[ch];
16.
17.     return c;
18. }
19.
how to use ...
Code (csharp):
1. float3x3 c = img3x3(color_map, IN.texcoord, texture_size, 0 );// red only
2. float3 normal = height2normal_sobel(c);
3. normal = normalize(float3(normal.xy, normal.z *bump_level));
Hope that is useful for someone like me (lazy )

kristoof likes this.
2. ### MattFS

Joined:
Jul 14, 2009
Posts:
219
good one - this sort of thing could be very useful for web deployment, if all you wanted was some noisy normalmaps (well, you could make it generate stuff like crazybump does) then this would save having to upload (and having to consider compressing) normalmaps!
good work

3. ### kristoof

Joined:
Aug 26, 2013
Posts:
29
Thank you som much for this
I know this is kind of an old thread but i extended the default surface shader with this if anyone intrested.

Code (CSharp):
2. {
3.     Properties
4.     {
5.         _Color ("Color", Color) = (1,1,1,1)
6.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
7.         _heightNrm ("Height2nrm (R)", 2D) = "white" {}
8.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
9.         _Metallic ("Metallic", Range(0,1)) = 0.0
10.         _BumpLvl ("bumpscale", Range(-1,1)) = 0.0
11.     }
13.     {
14.         Tags { "RenderType"="Opaque" }
15.         LOD 200
16.
17.         CGPROGRAM
18.         // Physically based Standard lighting model, and enable shadows on all light types
19.         #pragma surface surf Standard fullforwardshadows
20.
21.         // Use shader model 3.0 target, to get nicer looking lighting
22.         #pragma target 3.0
23.
24.         sampler2D _MainTex, _heightNrm;
25.
26.         struct Input
27.         {
28.             float2 uv_MainTex;
29.         };
30.
31.         half _Glossiness;
32.         half _Metallic;
33.         fixed4 _Color;
34.         float4 _heightNrm_TexelSize;
35.         float _BumpLvl;
36.
37.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
39.         // #pragma instancing_options assumeuniformscaling
40.         UNITY_INSTANCING_BUFFER_START(Props)
41.             // put more per-instance properties here
42.         UNITY_INSTANCING_BUFFER_END(Props)
43.
44.
45.
46.
47. float3 height2normal_sobel(float3x3 c)
48. {
49.     float3x3 x = float3x3(   1.0, 0.0, -1.0,
50.                                     2.0, 0.0, -2.0,
51.                                     1.0, 0.0, -1.0  );
52.     float3x3 y = float3x3(   1.0,  2.0,  1.0,
53.                                     0.0,  0.0,  0.0,
54.                                    -1.0, -2.0, -1.0 );
55.
56.     x = x * c;
57.     y = y * c;
58.     float cx =  x[0][0] +x[0][2]
59.                    +x[1][0] +x[1][2]
60.                    +x[2][0] +x[2][2];
61.
62.     float cy =  y[0][0] +y[0][1] +y[0][2]
63.                   +y[2][0] +y[2][1] +y[2][2];
64.
65.     float cz =  sqrt(1-(cx*cx+cy*cy));
66.
67.     return float3(cx, cy, cz);
68. }
69.
70.
71.         float3x3 img3x3(sampler2D color_map, float2 tc, float ts, int ch)
72. {
73.     float   d = 1.0/ts; // ts, texture sampling size
74.     float3x3 c;
75.     c[0][0] = tex2D(color_map,tc + float2(-d,-d))[ch];
76.     c[0][1] = tex2D(color_map,tc + float2( 0,-d))[ch];
77.     c[0][2] = tex2D(color_map,tc + float2( d,-d))[ch];
78.
79.     c[1][0] = tex2D(color_map,tc + float2(-d, 0))[ch];
80.     c[1][1] = tex2D(color_map,tc                )[ch];
81.     c[1][2] = tex2D(color_map,tc + float2( d, 0))[ch];
82.
83.     c[2][0] = tex2D(color_map,tc + float2(-d, d))[ch];
84.     c[2][1] = tex2D(color_map,tc + float2( 0, d))[ch];
85.     c[2][2] = tex2D(color_map,tc + float2( d, d))[ch];
86.
87.     return c;
88. }
89.
90.
91.         void surf (Input IN, inout SurfaceOutputStandard o)
92.         {
93.
94.             float3x3 ce = img3x3(_heightNrm, IN.uv_MainTex, _heightNrm_TexelSize.w, 0 );// red only
95.             float3 normal = height2normal_sobel(ce);
96.             normal = normalize(float3(normal.xy, normal.z *_BumpLvl));
97.
98.
99.             // Albedo comes from a texture tinted by color
100.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
101.             o.Albedo = c.rgb;
102.             o.Normal = normal;
103.             // Metallic and smoothness come from slider variables
104.             o.Metallic = _Metallic;
105.             o.Smoothness = _Glossiness;
106.             o.Alpha = c.a;
107.
108.         }
109.         ENDCG
110.     }
111.     FallBack "Diffuse"
112. }
113.

bb8_1 likes this.
4. ### mouurusai

Joined:
Dec 2, 2011
Posts:
345
Why not just regular bump?

On top "sobel", on bottom regular bump like here, but with texel size multiplied with an value. For 2 cases from 3 regular one seems look better for me.

Last edited: Aug 31, 2019
kristoof likes this.
unityunity