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的更多相关文章

  1. Creating Materials at runtime And Issue of Shader.Find()

    Creating Materials at runtimehttp://forum.unity3d.com/threads/create-materials-at-runtime.72952/ //通 ...

  2. surface shader相关参数,命令

    https://docs.unity3d.com/Manual/SL-SurfaceShaders.html 说明: 注意下surfaceshader相关开关选项,input结构体全部可用参数 goo ...

  3. OpenGL shader 中关于顶点坐标值的思考

    今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...

  4. 【Unity Shaders】Alpha Test和Alpha Blending

    写在前面 关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到半透明问题的时候,总是不知道为什么A就遮挡了B,而B明明在A前面.这篇文章就总结一下我现在的认识~ Alpha Test和A ...

  5. Unity Shader 基础(3) 获取深度纹理

    Unity提供了很多Image Effect效果,包含Global Fog.DOF.Boom.Blur.Edge Detection等等,这些效果里面都会使用到摄像机深度或者根据深度还原世界坐标实现各 ...

  6. (转)【Unity Shaders】Alpha Test和Alpha Blending

    转自:http://blog.csdn.net/candycat1992/article/details/41599167 写在前面 关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到 ...

  7. 雷达波Shader

    OSG版本: vert #version varying out vec3 v; void main() { gl_FrontColor = gl_Color; gl_Position = ftran ...

  8. Unity关闭shader中的光照模型以及如何自定义光照模型

    // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject' // Upgrade NOTE: replaced '_Wor ...

  9. unity, unlit surface shader (texColor only surface shader)

    要实现双面透明无光照只有纹理色的surface shader. 错误的写法:(导致带有曝光) Shader "Custom/doubleFaceTranspTexColor" { ...

随机推荐

  1. UPUPW PHP环境集成包

    UPUPW PHP环境集成包 http://www.upupw.net/

  2. altium6.x中自动删除重复走线的位置

    在protel 2004 DXP中,“自动删除走线”的位置就在"PCB Editor"的默认页面,非常好找. 但是升级到了altium 6.7,6.9之后,很多人就找不到这个了. ...

  3. Redisson使用起来很方便,但是需要redis环境支持eval命令

    Redisson使用起来很方便,但是需要redis环境支持eval命令,否则一切都是悲剧,比如me.结果还是要用RedisCommands去写一套.例子就如下,获得一个RLock锁对象,然后tryLo ...

  4. Keepalived+MySQL双主

    一.Keepalived+MySQL Replication的应用场景 MySQL的高可用方案有cluster,MMM,MHA等,这些高可用方案都要三台服务器以上,成本有点高,今天介绍一个低成本高可用 ...

  5. Android 常用UI控件之TabHost(3)在4.0不显示图标的解决方案

    1,自定义 TabWidget 上每个tab的view 2,用多个图片

  6. Hadoop源代码分析【IO专题】

    由于Hadoop的MapReduce和HDFS都有通信的需求,需要对通信的对象进行序列化.Hadoop并没有采用Java的序列化(因为Java序列化比较复杂,且不能深度控制),而是引入了它自己的系统. ...

  7. hadoop2.2原理:分析HDFS的文件读写

    File Read 程序举例: public class FileRead { public static void main(Sting[] args) throws Exception { Con ...

  8. bzoj2763

    首先是稀疏图,不难想到dij+heap 观察题目可以知道,0<=k<=10; 所以比较裸的想法就是,d[i,j]表示已经免费了i条线路后到达j的最短路 容易得到 d[i,j]:=min(d ...

  9. 教你如何通过ICCID找回丢失的的iPhone

    22日晚买了FACETIME,在某宝上买的.价格不贵,可以查到偷手机的人注册FT的号码,还可以查询手机被刷机和被维修的日期(这个很关键) 27日手机被刷机,遂买了某宝查询ICCID的服务,找到一串IC ...

  10. Apk修改利器:ApkToolkit v2.1

    作 者: Mzucore 时 间: 2013-05-10, 17:18:23 链 接: http://www.unpack.cn/thread-93058-1-1.html 下载地址:http://b ...