creating normals from alpha/heightmap inside a shader
http://www.polycount.com/forum/showthread.php?t=117185
I am making some custom terrain shaders with strumpy's editor and I want to be able to create normals based on my blend mask. Does anyone know how I can turn grayscale data into basic normal mapping info? I have seen someone do this in 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 are dFdx and dFdy.
DirectX11 has 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 the difference from those values. That should get you it in whatever space the base normal is in.
Nicked frm here; http://www.gamedev.net/topic/594781-...mal-algorithm/
- float me = tex2D(heightMapSampler,IN.tex).x;
- float n = tex2D(heightMapSampler,float2(IN.tex.x,IN.tex.y+1.0/heightMapSizeY)).x;
- float s = tex2D(heightMapSampler,float2(IN.tex.x,IN.tex.y-1.0/heightMapSizeY)).x;
- float e = tex2D(heightMapSampler,float2(IN.tex.x+1.0/heightMapSizeX,IN.tex.y)).x;
- float w = 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 is not parallel to norm
- if(norm.x==)
- temp.y+=0.5;
- else
- temp.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 its own space by the offset
- float3 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 change 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) = (,,,)
- _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) =
- _HeightmapDimY ("Heightmap Height", Float) =
- }
- SubShader{
- Tags { "RenderType" = "Opaque" }
- CGPROGRAM
- #pragma surface surf NormalsHeight
- #pragma target 3.0
- struct Input
- {
- float2 uv_MainTex;
- };
- sampler2D _MainTex, _BumpMap, _HeightMap;
- float _HeightmapStrength, _HeightmapDimX, _HeightmapDimY;
- void surf (Input IN, inout SurfaceOutput o)
- {
- o.Albedo = fixed3(0.5);
- float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
- float me = tex2D(_HeightMap,IN.uv_MainTex).x;
- float n = tex2D(_HeightMap,float2(IN.uv_MainTex.x,IN.uv_MainTex.y+1.0/_HeightmapDimY)).x;
- float s = tex2D(_HeightMap,float2(IN.uv_MainTex.x,IN.uv_MainTex.y-1.0/_HeightmapDimY)).x;
- float e = tex2D(_HeightMap,float2(IN.uv_MainTex.x-1.0/_HeightmapDimX,IN.uv_MainTex.y)).x;
- float w = 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 is not parallel to norm
- if(norm.x==)
- temp.y+=0.5;
- else
- temp.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 its own space by the offset
- float3 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, fixed atten)
- {
- viewDir = normalize(viewDir);
- lightDir = normalize(lightDir);
- s.Normal = normalize(s.Normal);
- float NdotL = dot(s.Normal, lightDir);
- _LightColor0.rgb = _LightColor0.rgb;
- fixed4 c;
- c.rgb = float3(0.5) * saturate ( NdotL ) * _LightColor0.rgb * atten;
- c.a = 1.0;
- return c;
- }
- 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.
creating normals from alpha/heightmap inside a shader的更多相关文章
- Creating Materials at runtime And Issue of Shader.Find()
Creating Materials at runtimehttp://forum.unity3d.com/threads/create-materials-at-runtime.72952/ //通 ...
- surface shader相关参数,命令
https://docs.unity3d.com/Manual/SL-SurfaceShaders.html 说明: 注意下surfaceshader相关开关选项,input结构体全部可用参数 goo ...
- OpenGL shader 中关于顶点坐标值的思考
今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...
- 【Unity Shaders】Alpha Test和Alpha Blending
写在前面 关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到半透明问题的时候,总是不知道为什么A就遮挡了B,而B明明在A前面.这篇文章就总结一下我现在的认识~ Alpha Test和A ...
- Unity Shader 基础(3) 获取深度纹理
Unity提供了很多Image Effect效果,包含Global Fog.DOF.Boom.Blur.Edge Detection等等,这些效果里面都会使用到摄像机深度或者根据深度还原世界坐标实现各 ...
- (转)【Unity Shaders】Alpha Test和Alpha Blending
转自:http://blog.csdn.net/candycat1992/article/details/41599167 写在前面 关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到 ...
- 雷达波Shader
OSG版本: vert #version varying out vec3 v; void main() { gl_FrontColor = gl_Color; gl_Position = ftran ...
- Unity关闭shader中的光照模型以及如何自定义光照模型
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject' // Upgrade NOTE: replaced '_Wor ...
- unity, unlit surface shader (texColor only surface shader)
要实现双面透明无光照只有纹理色的surface shader. 错误的写法:(导致带有曝光) Shader "Custom/doubleFaceTranspTexColor" { ...
随机推荐
- 周末“干活”之 Mesos Meetup
周末两天都是大雾霾天,作为运营也不能在家宅,告别了技术就得腿儿勤点儿. 非常感谢 Linker 的 Sam Chen 和 数人科技 的 CTO 共同组织的Mesos Meetup,OneAPM 最帅的 ...
- URAL1244. Gentlemen(背包)
链接 以前做的题 VJ太水了 数组里面的数可能会小于0 当时没判断 #include <iostream> #include<cstdio> #include<cstri ...
- write & read a sequence file(基于全新2.2.0API)
write & read a sequence file write & read a sequence file import java.io.IOException; import ...
- c# post文字图片至服务器
最近由于项目需要实现c#提交文字及数据至服务器,因此研究了一下c# php数据传送: 下面用一个示例来演示,c# post文字+图片 ,php端接收: post提交数据核心代码(post数据提交) ? ...
- App Store 加急审核方式
https://developer.apple.com/contact/app-store/?topic=expedite 1:理由一般是用户安全问题或者崩溃问题成功率会高一些. 如果是崩溃问题,你最 ...
- MVC中的扩展点(六)ActionResult
ActionResult是控制器方法执行后返回的结果类型,控制器方法可以返回一个直接或间接从ActionResult抽象类继承的类型,如果返回的是非ActionResult类型,控制器将会将结果转换为 ...
- sharepoint2010网站根据权限隐藏ribbon
转:http://www.it165.net/design/html/201302/1734.html 项目要求让普通用户看不到"网站操作",为了解决该问题,我找了好几篇博客,但都 ...
- MVC3中Action返回类型ActionResult类型
MVC3中Action返回类型ActionResult在System.Web.Mvc命名空间中.这些包含在控制器中的方法,我们称为控制器中的 Action,比如:HomeController 中的 I ...
- Epub2基础知识介绍
一.什么是epub epub是一个完全开放和免费的电子书标准.它可以“自动重新编排”的内容. Epub文件后缀名:.epub 二. epub组成 Epub内部使用XHTML(或者DTBook)来展现文 ...
- nginx错误汇总
一.Nginx出现413 Request Entity Too Large错误解决方法 Nginx出现的413 Request Entity Too Large错误,这个错误一般在上传文件的时候出现, ...