UDK 的材质编辑器十分好用,毕竟是所见即所得的。虽然unity也有类似第三方插件,但易用性还是差很多,下面主要是,把一些常见表达式概念对应起来。

1. UDK CameraVector (相机位向量)表达式
  机位向量表达式使您能够在游戏运行时访问相机的指向向量。在要求材质于不同视角角度下呈现出不同效果时
 对应unity shader中Input结构附加变量: float3 viewDir。对于内建的viewDir, 它和CameraVector一样是切线空间中的变量。
 对于unity 如果不使用附加变量,计算过程如下:ObjSpaceViewDir() 函数求摄像机到顶点的方向。
 在顶点shander中还可以求反射方向

   float3 viewDir = ObjSpaceViewDir( v.vertex );
   //float3 I = reflect( -viewDir, v.normal );   求 ReflectionVector 反射向量
   计算到切线空间
   TANGENT_SPACE_ROTATION;
    viewDir = normalize(mul(rotation, normalize(ObjSpaceViewDir(v.vertex))));

这个是基于物体切线空间的位置。 相机的世界坐标向量是:
     float3 worldView = normalize(WorldSpaceViewDir(v.vertex));

2. UDK PixelDepth (像素深度)表达式
   在udk 中 float z = ScreenPosition.w.r 
  
   对应unity计算如下:
   float z = mul (UNITY_MATRIX_MVP, v.vertex).w;
   float z = - mul(UNITY_MATRIX_MV, v.vertex).z;
   如果是在surf 函数中,也可以从screenPos.w.r 获得。

3. UDK ScreenPosition (屏幕位置)表达式
  屏幕位置表达式用于输出当前指定像素在屏幕中的位置。像素处于屏幕空间中的位置,范围从[-1,-1],即屏幕左下角,到[1, 1],即右上角。它有一个参数,屏幕校准(ScreenAlign),用来将坐标范围改动为从[0, 0]到[1, 1]
   udk 当前像素ScreenPosition是由CalcMaterialParameters函数计算出来的。

  unity 有两种方法获得ScreenPos 
   1. unity中顶点经过投影变换后再使用ComputeScreenPos计算出来。
   o.pos = mul (UNITY_MATRIX_MVP, v.vertex); 
   o.ScreenPos = ComputeScreenPos (o.pos); //由[-1,1]范围映射到[0,1]范围.

2. unity 方法2 是surface shader中, 直接在surf Input 参数结构中声明screenPos变量 ,unity 会自动填入值.
     screenPos.xy和上面计算的 o.ScreenPos.xy 相同
     struct Input {
        float4 screenPos;

      };
      void surf (Input IN, inout EditorSurfaceOutput o) {
     
    btw: 做为uv使用前都要除w值:screenPos.w 或者 ScreenPos.w。
    ComputeGrabScreenPos 函数用来映射像素到graptexture上,从GrabTexture 上可以获得 DestColor (目标颜色) ,这个grabuv和screenPos是不同的,在我机器上是除w之后,grabuv.y 是 1-screenPos.y(可能和我的环境有关,需要grabuv时最好从顶点中计算)。
   
4. UDK SceneDepth (场景深度)表达式
   场 景深度表达式跟目标深度表达式(DestDepth)非常相似,但它可以针对整个关卡场景中对深度进行采样,改变输入的UV即可。
   LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD( IN.screenPos)).r);
   LinearEyeDepth 线性化函数,正交投影时是针对z值进行了1/z变换(让近处物件有更好的z值分辨率,如下公式),这样近处的东西有更大的分辨率
  

 (opengl)  求 -Pz 即eyeZ  对应公式:  -Pz = (2 * n * f) / (f + n - z' * (f - n))

-Pz 是顶点在3D空间中的z值, 这和计算出来的w值以及PixelDepth是相同的。z'是投影变换后的z值。也是_CameraDepthTexture记录的z值。所以进行z值差值,要求线性结果。例如:

//#define UNITY_SAMPLE_DEPTH(value)  (value).r

   half depthdiff = UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos)));   
   depthdiff = LinearEyeDepth(depth) - IN.screenPos.w;
   BlendFactors = saturate(Paremeter * depthdiff); 
 
   对于当前点求的SceneDepth 也就是 udk 的DestDepth表达式。

5. UDK BumpOffset (凹凸偏移)表达式
  用来创建虚拟位移贴图(Virtual Displacement Mapping)效果。在使用法线贴图来产生表面高度的物理差异假象时,此表达式能改善其效果。
   BumpOffset 表达式公式如下:
   BumpOffset = TexCoord + CameraVector.RG * (Height * HeightRatio - HeightRatio * RefPlane);

需要带Alpha高度图的法线贴图,用alpha通道作为Height节点输入。

unity 对应的函数是
   inline float2 ParallaxOffset( half h, half height, half3 viewDir )
   {
     h = h * height - height/2.0;
     float3 v = normalize(viewDir);
     v.z += 0.42;
     return h * (v.xy / v.z);
   }

half h = tex2D (_SpecMap, IN.uv_BumpMap).w;      //从法线贴图alpha通道读取高度

float2 offset = ParallaxOffset (h, _HeightRatio, IN.viewDir);  //计算uv bumpoffset, _HeightRatio 是输入参数
    IN.uv_MainTex += offset;

IN.uv_BumpMap += offset;

虽然者略有不同,但都是属于虚拟位移贴图

6. UDK ReflectionVector (反射向量)
 反射向量表达式用来表示CameraVector(相机向量)通过应用材质的物体表面的法线的方向发射。
  对应着unity 顶点附加变量 float3 worldRefl. 但ReflectionVector 是切向空间的, worldRefl 则是世界空间的。对于UDK可以使用Transfrom表达式进行空间变化。
 Unity 局部空间变换到切向空间使用 TANGENT_SPACE_ROTATION得到rotation; 计算过程参考 CameraVector条目

//一个unity环境反射的例子
   half4 tex = tex2D(_MainTex, IN.uv_MainTex);
   o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
   float3 worldRefl = WorldReflectionVector (IN, o.Normal);
   half4 reflclr = texCUBE (_Cube, worldRefl);
   reflclr *= tex.a;
   o.Emission = reflclr.rgb * _ReflectColor.rgb;

7. UDK Fresnel (菲涅尔)
  菲涅尔表达式是多种功能的复杂综合:读取像素的法线向量,并在向量指向镜头时输出值0,在法线方向与相机视角垂直时输出1
 如下计算过程。法线和CameraVector都是位于切线空间的矢量。 如果没有法线贴图提供法线,那么法线就是 (0, 0, 1.0), 参考切线空间定义
 计算过程  Fresnel = (1 - Max(Normal dot Camera, 0)) ^ Exponent
  F = pow(1- max(N*C, 0), E)
  UDK 对应 Shader
  float Local2 = dot(float3(0.00000000,0.00000000,1.00000000),Parameters.TangentCameraVector);  //切线空间viewDir
  float Local3 = max((0.00000000),Local2);
  float Local4 = ((1.00000000) - Local3);
  float Local5 = ClampedPow(Local4,(3.00000000));

转换到unity
  o.Normal = half3(0,0,1.0f);  //有法线贴图则: o.Normal = UnpackNormal(tex2D(_BumpMap, IN.BumpUV));
  half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
  o.Emission = float3(1.0f,0,0) * pow (rim, 3);
viewDir 基于切线空间, 法线也是。如果没有法线贴图, 可以使用 (0,0,1)

8. unity 变量_ ZBufferParams 的值. 主要用于 ComputeScreenPos 函数中。
  double zc0, zc1;
 //OPenGL would be this:
 zc0 = (1.0 - m_FarClip / m_NearClip) / 2.0;

zc1 = (1.0 + m_FarClip / m_NearClip) / 2.0;

//D3D is this: 
 zc0 = 1.0 - m_FarClip / m_NearClip;
 zc1 = m_FarClip / m_NearClip;

float4 _ZBufferParams = float4(zc0, zc1, zc0/m_FarClip, zc1/m_FarClip);

DX:   
 eyeZ 正交投影之前的z值。 z 是经过正交投影的值(即_CameraDepthTexture中的值)。
  eyeZ  = (n * f) / (f - z * (f - n))
  LinearZ = eyeZ / f = n / (f - z * (f - n))

GL:
  eyeZ  = (2 * n * f) / (f + n - z * (f - n))
  LinearZ = eyeZ / f = (2 * n) / (f + n - z * (f - n))

9. SceneTexture (场景贴图)
   UDK 拥有这个表达式,代表当前的场景颜色信息
   unity 没有当前的color bufrer。代替的方法如下:

Subshader
  {
    Tags {"RenderType"="Transparent" "Queue"="Transparent"}

GrabPass {}
    sampler2D _GrabTexture;     //捕获的纹理
   
    Pass {
      。。。。。
      CGPROGRAM   
      #pragma target 3.0    
      #pragma vertex vert
      #pragma fragment frag  
      #pragma glsl

。。。。。
     ENDCG
    }
  }

10. Desaturation (冲淡颜色)

Desaturation(冲淡颜色)表达式将抽出材质中的颜色量,也可用说  减饱和作用  。其整体效果会使材质中存在的颜色趋向于灰色

可用于冲淡漫反射图得到高光贴图
    
   下面是unity 的函数Luminance, 作用类似
   unity 点乘的常量是 fixed3(0.22, 0.707, 0.071),而UDK默认值是(0.3,0.59,0.11)
    inline fixed Luminance( fixed3 c )
    {
         return dot( c, fixed3(0.22, 0.707, 0.071) );
    }

11. DepthBiasedAlpha(深度偏移Alpha)
  DepthBiasedAlpha表达式是两个主要用来消除尖锐边缘的表达式之一,这些边缘通常是由平面粒子实例(sprite particle)与几何体交叉而产生的。
  表达式读取两个输入值:Alpha值和Bias值。Bias值对目的地缓冲器中的内容和材质进行实际混合。
  Bias值读取黑、白之间的值,值0(黑)表示完全显示目的地缓冲器中的内容,值1(白)表示完全显示材质的颜色。
  Alpha输入值则直接通过表达式,不需要进行任何运算。默认值为1
  如果没有输入Alpha值,则DepthBiasedAlpha(深度偏移Alpha)表达式的输出值为1。

默认属性: float Local2 = DepthBiasedAlpha(Parameters,float((1.00000000)),float((0.50000000)),float((1.0000000)));

也有两个参数,bNormalize和BiasScale。BiasScale用作与Bias输入值的乘数,从而允许在材质和目的地缓冲器内容之间更大程度地进行混合。

bNormalize属性将深度值由范围的近到远映射到0到1的范围(bNormalize 暂时没看到起作用)
  公式如下:
  float DepthBiasedAlpha( FMaterialPixelParameters Parameters, float InAlpha, float InBias, float InBiasScale )
  {
    float Result;
    half SceneDepth = PreviousDepth(Parameters.ScreenPosition);
    float DepthBias = (1.0 - InBias) * InBiasScale;
    float BlendAmt = saturate((SceneDepth - Parameters.ScreenPosition.w) / max(DepthBias,0.001));
    Result = InAlpha * BlendAmt;
    return Result;
  }

unity 在这方面有一个 Soft Particles 的控制选项。 Edit->Project Setting->Quality。 或者在像素shader中:
   Properties

{
     _Bias("_Bias", Range(0,1) ) = 0.5
   }

.......
  half ScreenDepthDiff = LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos)).r) - IN.screenPos.w;
  half Pow = pow(ScreenDepthDiff, _Bias);
  float Saturate = saturate(Pow);
  o.Alpha = Saturate;

12.  Distortion
  Distortion 扭曲在UDK中是整个材质节点的一个输入参数。在unity 可以如下实现:使用法线扰动uv,然后从grab纹理取得像素值
 Shader "Distortion"
{
 Properties
 {
  _Distortion("_Distortion", Range(0,1) ) = 0.1632124
  _BumpMap("_Offset", 2D) = "black" {}
 }
 
 SubShader
 {
  Tags
  {"Queue"="Transparent" "IgnoreProjector"="False" "RenderType"="Transparent"}
  
  GrabPass {}
  
  Cull Back
  ZWrite Off
  ZTest LEqual
  ColorMask RGBA
  Fog{}

CGPROGRAM
  #pragma surface surf BlinnPhong  vertex:vert
  #pragma target 2.0

float _Distortion;
  sampler2D _BumpMap;
  sampler2D _GrabTexture;
   
  struct Input
  {   
   float4 grabPos; 
   float2 uv_BumpMap;    
  };

void vert (inout appdata_full v, out Input o)
  {
    float4 pos = mul (UNITY_MATRIX_MVP, v.vertex);
      o.grabPos = ComputeGrabScreenPos(pos);
  }

void surf (Input IN, inout SurfaceOutput o)
  {
    o.Normal = float3(0.0,0.0,1.0);
    o.Alpha = 1.0;
    o.Albedo = 0.0;                        
    
    float3 Normal=UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    float2 Multiply1=Normal.xy * _Distortion.xx;
    float2 uvs = IN.grabPos.xy/IN.grabPos.w + Multiply1;        
    float4 Tex2D0 = tex2D(_GrabTexture,uvs);
    o.Emission = Tex2D0.rgb;        
   }
  ENDCG
 }
 Fallback "Diffuse"
}

13.  如果你的程序不会运行到手机设备上,可以禁止生成OpenGL ES 2.0 (Opengl 缩减版)的shader。
   #pragma exclude_renderers gles
  这样可以解决 shader 中 isnan 之类函数不能编译问题, 对于flash 可以用 #pragma exclude_renderers flash
 flash 能支持的寄存器太少了

附:

1. unity 中可以附加到Input结构的变量.

    • float3 viewDir - will contain view direction, for computing Parallax effects, rim lighting etc.
    • float4 with COLOR semantic - will contain interpolated per-vertex color.
    • float4 screenPos - will contain screen space position for reflection effects. Used by WetStreet shader in Dark Unity for example.
    • float3 worldPos - will contain world space position.
    • float3 worldRefl - will contain world reflection vector if surface shader does not write to o.Normal. See Reflect-Diffuse shader for example.
    • float3 worldNormal - will contain world normal vector if surface shader does not write to o.Normal.
    • float3 worldRefl; INTERNAL_DATA - will contain world reflection vector if surface shader writes to o.Normal. To get the reflection vector based on per-pixel normal map, use WorldReflectionVector (IN, o.Normal). See Reflect-Bumped shader for example.
    • float3 worldNormal; INTERNAL_DATA - will contain world normal vector if surface shader writes to o.Normal. To get the normal vector based on per-pixel normal map, use WorldNormalVector (IN, o.Normal).

【原】Unity Shader VS UDK Material Editor的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第10章 高级纹理

    转载自 冯乐乐的 <Unity Shader入门精要> 立方体纹理 在图形学中,立方体纹理是环境映射的一种实现方法.环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层 ...

  2. Unity Shader入门精要之 screen post-processing effect

    本篇记录了学习Unity Shader入门精要的屏幕后处理的一些知识点. OnRenderImage(RenderTexture src, RenderTexture dest) 以上函数是Unity ...

  3. 【Unity Shader】(三) ------ 光照模型原理及漫反射和高光反射的实现

    [Unity Shader](三) ---------------- 光照模型原理及漫反射和高光反射的实现 [Unity Shader](四) ------ 纹理之法线纹理.单张纹理及遮罩纹理的实现 ...

  4. Unity Shader入门精要学习笔记 - 第15章 使用噪声

    转载自 冯乐乐的 <Unity Shader 入门精要> 消融效果 消融效果常见于游戏中的角色死亡.地图烧毁等效果.这这些效果中,消融往往从不同的区域开始,并向看似随机的方向扩张,最后整个 ...

  5. Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果

    建立一个基本的屏幕后处理脚本系统 屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效.使用这种技术,可以为游戏画面添加更多艺术效果,例如景深. ...

  6. Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础

    来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达 ...

  7. 【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)

    写在前面 感谢全部点进来看的朋友.没错.我眼下打算写一本关于Unity Shader的书. 出书的目的有以下几个: 总结我接触Unity Shader以来的历程,给其它人一个借鉴.我非常明确学Shad ...

  8. Unity Shader入门教程(一)

    参考文献:http://www.360doc.com/content/13/0923/15/12282510_316492286.shtml Unity Shader是着色器,将纹理.网格信息输入,得 ...

  9. Unity Shader - 消融效果原理与变体

    基本原理与实现 主要使用噪声和透明度测试,从噪声图中读取某个通道的值,然后使用该值进行透明度测试. 主要代码如下: fixed cutout = tex2D(_NoiseTex, i.uvNoiseT ...

随机推荐

  1. 3522: [Poi2014]Hotel

    3522: [Poi2014]Hotel Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 253  Solved: 117[Submit][Status ...

  2. CSS限制字数,超出部份显示点点点...

    最近项目中需要用CSS实现限制字数,超出部份显示点点点...,只需要一下代码即可: width:400px;/*要显示文字的宽度*/ text-overflow :ellipsis; /*让截断的文字 ...

  3. HttpURLConnection实现两个服务端的对接

    在企业开发中,很多时候需要用到两个服务端的对接,在java类中进行连接并传递参数,其中的HttpURLConnection是一种轻量化,并且简单的方法! package httptest; impor ...

  4. (30)批处理文件.bat

    批处理文件(bat) 简单的说,批处理的作用就是自动的连续执行多条命令 .编写bat处理文件可以使用记事本的方式: 常见批处理文件的命令: echo 表示显示此命令后的字符 tiltle 设置窗口的标 ...

  5. 【SF】开源的.NET CORE 基础管理系统 -介绍篇

    [SF]开源的.NET CORE 基础管理系统 -系列导航 1.环境: .NET Core SDK (https://www.microsoft.com/net/core) SQL Server or ...

  6. javascript中构造StringBuffer实例

    function StringBuffer(){      this.strings = new Array;  }    StringBuffer.prototype.append=function ...

  7. pyqt样式表语法笔记(上) --原创

    pyqt样式表语法笔记(上) pyqt QSS python 样式表 因为软件课设的原因开始学习使用pyqt4,才发现原来它也有样式表,而且语法跟css基本相同,而且一些功能实现起来感觉比js要简单方 ...

  8. windows_keyboard shortcuts快捷键

    单独按Windows:显示或隐藏"开始"功能表 Windows+BREAK:显示"系统属性" 对话框 Windows+D:显示桌面 Windows+M:最小化所 ...

  9. iOS面试必看经典试题分析

    > **不用临时变量怎么实现两个数据的交换?** 方式一:加减法的运算方式求解new_b = a - b + b = a;new_a = a + b - a = b;一个简单的运算方式,最重要的 ...

  10. 五分钟秒懂Java日志组件

    Java中有许多种日志记录方式,有些API有占位符,有些API没占位符,初学的人可能会搞不清楚这些日志组件的由来.我一开始的时候也是很懵逼的,后来一点点弄懂了于是就又了这篇文章. 在Java中进行日志 ...