Creating normals from Alpha/heightmap inside a shader

Source: Internet
Author: User

http://www.polycount.com/forum/showthread.php?t=117185

I am making some custom terrain shaders with Strumpy's editor and I want to being able to create normals based on my blend MA Sk. Does anyone know how do I can turn grayscale data into basic normal mapping info? I have the seen someone do the unreal but I can ' t remember where.

You probably want to get the difference of the values pixel-by-pixel using DDX, I think.

Off the top of my head ... for CG/HLSL;

Float Heightmap = your height map value;
FLOAT3 Normal;
normal.x = DDX (heightmap);
Normal.y = Ddy (heightmap);
Normal.z = sqrt (1-NORMAL.X*NORMAL.X-NORMAL.Y * normal.y); Reconstruct Z component to get a unit normal.

For OpenGL, I think the functions is DFDX and DFDY.

DirectX11 have Ddx_fine and Ddy_fine which I think give more accurate results.


That ' ll give you the normal in, EHR ... screen space I think?

Otherwise You can sample the heightmap multiple times, offsetting it by a pixel and working out of the difference from those Values. That's should get you it in whatever space the base normal are in.

nicked frm here; http://www.gamedev.net/topic/594781-... mal-algorithm/

floatme =tex2d (Heightmapsampler,in.tex). x;floatn = tex2d (HEIGHTMAPSAMPLER,FLOAT2 (in.tex.x,in.tex.y+1.0/Heightmapsizey)). x;floats = tex2d (Heightmapsampler,float2 (in.tex.x,in.tex.y-1.0/Heightmapsizey)). x;floatE = tex2d (HEIGHTMAPSAMPLER,FLOAT2 (in.tex.x+1.0/heightmapsizex,in.tex.y)). x;floatW = tex2d (Heightmapsampler,float2 (in.tex.x-1.0/heightmapsizex,in.tex.y)).                X //find perpendicular vector to norm:FLOAT3 temp = norm;//a temporary vector that's not parallel to normif(norm.x==1) Temp.y+=0.5;Elsetemp.x+=0.5;//form a basis with norm being one of the axes:FLOAT3 PERP1 =Normalize (Cross (norm,temp)); FLOAT3 Perp2=Normalize (Cross (NORM,PERP1));//Use the basis-to-move the normal in their own space by the offsetFLOAT3 Normaloffset =-bumpheightscale* (((n-me)-(s-me)) *perp1 + ((e-me)-(w-me)) *perp2); Norm+=Normaloffset;norm= normalize (norm);

Gave it a try out of curiosity.

Here's the Multi-sample method in a stripped-down surface shader.

I had to the handedness from the code above to match Unity (changing the sign of the operation when sampling the E and W values from + to-and vice versa).

Shader"debug/normal Map from Height"{Properties {_color ("Main Color", Color) = (1,1,1,1) _maintex ("Diffuse (RGB) Alpha (A)", 2D) =" White"{} _bumpmap ("Normal (normal)", 2D) ="Bump"{} _heightmap ("heightmap (R)", 2D) ="Grey"{} _heightmapstrength ("Heightmap Strength", Float) =1.0_heightmapdimx ("heightmap Width", Float) =2048_heightmapdimy ("heightmap Height", Float) =2048} subshader{Tags {"Rendertype"="Opaque"} cgprogram#pragmaSurface Surf Normalsheight#pragmaTarget 3.0structInput {float2 Uv_maintex;            };            Sampler2d _maintex, _bumpmap, _heightmap; float_heightmapstrength, _heightmapdimx, _heightmapdimy; voidSurf (Input in, InOut surfaceoutput o) {O.albedo= Fixed3 (0.5); FLOAT3 Normal=Unpacknormal (tex2d (_bumpmap, In.uv_maintex)); floatme =tex2d (_heightmap,in.uv_maintex). x; floatn = tex2d (_HEIGHTMAP,FLOAT2 (in.uv_maintex.x,in.uv_maintex.y+1.0/_heightmapdimy)).                X floats = tex2d (_heightmap,float2 (in.uv_maintex.x,in.uv_maintex.y-1.0/_heightmapdimy)).                X floatE = tex2d (_HEIGHTMAP,FLOAT2 (in.uv_maintex.x-1.0/_heightmapdimx,in.uv_maintex.y)).                X floatW = tex2d (_heightmap,float2 (in.uv_maintex.x+1.0/_heightmapdimx,in.uv_maintex.y)).                X FLOAT3 Norm=Normal; FLOAT3 Temp= Norm;//a temporary vector that's not parallel to norm                if(norm.x==1) Temp.y+=0.5; Elsetemp.x+=0.5; //form a basis with norm being one of the axes:FLOAT3 PERP1 =Normalize (Cross (norm,temp)); FLOAT3 Perp2=Normalize (Cross (NORM,PERP1)); //Use the basis-to-move the normal in their own space by the offsetFLOAT3 Normaloffset =-_heightmapstrength * (((n-me)-(s-me)) * PERP1 + ((e-me)-(w-me)) *PERP2); Norm+=Normaloffset; Norm=normalize (norm); O.normal=Norm; } inline Fixed4 lightingnormalsheight (surfaceoutput s, fixed3 Lightdir, Fixed3 Viewdir,fixedatten) {Viewdir=normalize (Viewdir); Lightdir=normalize (Lightdir); S.normal=normalize (s.normal); floatNdotl =dot (s.normal, lightdir); _lightcolor0.rgb=_lightcolor0.rgb;                Fixed4 C; C.rgb= FLOAT3 (0.5) * Saturate (NDOTL) * _lightcolor0.rgb *Atten; C.A=1.0; returnC; } ENDCG} FallBack"Vertexlit"}

Derivative method works, but it's fucking ugly ' cause it ' s in screen space-really noisy.

Ddx_fine might give better results in DX11, but it looks like crap in DX9.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.