关闭

Unity3d shader编程 VertexLit渲染路径

标签: shaderunity3d管线编程
1120人阅读 评论(0) 收藏 举报

此文仅供参考使用。this is reference not a manual!
所以知识点比较零碎,如果有时间我会整理一下概念,组织一下逻辑,让弱基础的读者理解。


老生重提,学过shader编程的同学应该知道,一个特效的形成是由3部分组成(像魔戒三部曲一样)。物体材质+光源+视摄像机共同渲染的结果。物体材质是我们可以编程的如何接收光,反射,折射等,这一部分涉及物理光学(突然好高大上),计算机靠数学函数模拟光照的特征,计算出光照强度颜色等,最终反映到屏幕上被肉眼接收。那摄像机有vertexlit,forward,deferred三种模式干嘛? 其实摄像机就是统一规定屏幕内的物体都是以什么方式被渲染的,VertexLit顶点方式则全部用物体材质中的vertex path渲染路径去刻画每一个物体,如果(当前显示)摄像机用forward模式,则查找物体材质shader程序中forward base/forward add path去刻画物体,如果找不到则还是用vertex path去刻画。如果(当前显示)摄像机用deferred模式,则查找物体材质shader程序中PrepassBase/PrepassFinal path(这里不是deferred开头额。)方法去刻画物体,找不到则寻找forward base/forward add path去刻画物体,再找不到则使用最低级的vertex path去渲染,再找不到?有个FallBack “Diffuse”就是最终使用unity系统默认渲染方法来渲染..您就甭管了…

所以摄像机的渲染模式就像一个总开关… 而材质的渲染路径path就是总开关下的各种串并联电路,决定哪种渲染方式合适,而光源有两种光照vertex/pixel和材质渲染路径共同决定如何显示,总不能光源是vertex顶点的,而要求材质渲染用deferred的逐像素点渲染吧?这时候就会自动调整到适合光源的vertex path路径下渲染。。 而vertex顶点渲染硬件开销小..废话么,都不是每个像素点运算的,只是顶点插值出来的均值,所以游戏中主要光源应该用pixel逐像素点刻画,而次要光源(啥叫次要,比如太阳下的小星星,你就自己琢磨吧)就可直接设置成vertex模式的,强制材质物体在使用该光源时使用vertex path渲染来减少运算开销,增加帧率!有舍必有得嘛。


物体材质+光源+视摄像机的关系全部说完,接下来是正文..序言很长,但必须理清!如果不理解可看完正文回头来看这段解释,深度理解三者关系,才能在写代码时心中有丘壑。

VertexLit渲染路径

顶点照明就是通过计算顶点颜色和光照插值放入fragment shader中进行渲染,因为是线性插值,不涉及每个像素点的编程,所以vertex lit是最基础的渲染模式(路径)。广泛适用于硬件设施有限,或者性能低下的设备,比如手机…

在unity的shader lab编程环境中,目前已经知道的存取光源的变量有如下几个。
(1)float4 _WorldSpaceLightPos0矢量,和它相对应的是一个 float4 _LightColor0。这是一个世界坐标中的光源的位置或者光照射方向矢量。取决于变量最后一个参数例如: _WorldSpaceLightPos0.w
如果w值为0则说明向量是光照方向(平行光),否则为世界坐标系下的灯光位置,球形点光源(w为光照距离?)

<\version=1.1>测试结果:该光源信息变量在shader pass 中LightMode = Vertex并且camera渲染模式是vertexlit时不起作用,虽然拿得到数据,不过是无效的上次光照遗留数据!camera渲染模式是Forward,Deferred模式时正常工作 <\version=1.1>

(2)float4 unity_4LightPosX0, float4 unity_4LightPosY0, float4 unity_4LightPosZ0,根据UnityCG.cginc中的说明,这三个4元变量代表4个光源的x,y,z的坐标(结构组织为下)
float4 float4 float4
4元素 4元素 4元素
x y z x y z x y z x y z
和它对应的是float4 unity_4LightAtten0,表示的是4个光源的衰减,float4 unity_LightColor[4]是对应光源的颜色。

<\version=1.1>测试结果:该光源信息变量在shader pass 中LightMode = Vertex并且camera渲染模式是vertexlit时不起作用,虽然拿得到数据,不过是无效的上次光照遗留数据!camera渲染模式是Forward,Deferred模式时正常工作 <\version=1.1>

(3)float4 unity_LightPosition[4],表示4个点光源的光源位置或者平行光的方向矢量。如果unity_LightPosition[index].w为0,则表明这是个平行光。和它对应的是float4 unity_LightColor[4],存储了光源的颜色; float4 unity_LightAtten[4],存储了光源的衰减

<\version=1.1>测试结果:该光源信息变量在shader pass 中LightMode = Vertex时任意camera渲染模式,VertexLit,ForWard,Deferred都会及时跟新这个光源信息变量,并且平行光在该变量内存中靠前,比点光源优先处理,意思就是平行光比点光源要重要!) <\version=1.1>

<\version=1.1>上述情况都是shader pass 中LightMode = Vertex并且,光源的光照特性也为Vertex(光源一共有两个选项,一个是顶点,一个是像素Pixel),如果修改光照特性为Pixel,上述情况不变,因为Pixel是Vertex的高级版本光源,向下兼容vertex光照的特性 <\version=1.1>

注意上述的变量都是unity3d shader lab的内置环境变量,全局都可获取!不用申明
例如

Shader "Lighting/VertexLit/Lab1/unity_4LightPosX0.x0"{
    Properties{
        _Color ("Base Color",Color)=(1,1,1,1)   //这里没有分号;是因为这是给Unity解析用的就像xml解析一样?unity自动帮你设置变量和界面。
    }
    SubShader{
        Pass{ //整个感觉就像xml一样....直到真正的cg语言代码处
        Tags{ "LightMode"="Vertex" }
        CGPROGRAM   //声明开始cg代码
        #progma vertex vert  //指定vertex shader入口函数(main)为vert
        #progma fragment frag //指定fragment shader入口函数(main)为frag
        #include "UnityCG.cginc" //包含unity环境文件,内置函数,变量等,与unity外部程序交互
        #include "Lighting.cginc" //包含灯光环境文件,获取程序内放置的光源和光源相关函数等
        uniform float4 _Color;
        struct vertOut{
            float4 pos:SV_POSITION; //定义vertex shader输出变量 :POSITION一样,如果不懂请   学完cg语言在反过来看此文,概念不清就如雾里探花。
            float4 color:COLOR; //cg语言定义vertex shader输出变量如上
        }
        vertOut vert(appdata_base v) //跟一般cg语言不同的是 我们这里用appdata_base来代替通常使用的 in float4 vertexIn:POSITION或者 float4 texCord1:TEXCORD0等外部输入变量
        {
            vertOut o;
            o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
            o.color = unity_4LightPosX0[0];
            return o; //vertex shader的main函数返回 (cg语言的语义绑定,return也好,显示声明out也好都是表示输出)
        }
        float4 frag(verOut i):COLOR //语义绑定可放在函数后面表输出类型反馈
        {
            return i.color;
        }
        ENDCG  //声明结束cg代码
        }
    }
}

上述代码中 o.color = unity_4LightPosX0[0]; 语句中unity_4LightPosX0[0]是环境变量,这就是为什么我们要#include “UnityCG.cginc”这样环境中就包含了unity内置的变量了


<\version=1.1> 后续对文章的修改 2015/7/8

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:26213次
    • 积分:477
    • 等级:
    • 排名:千里之外
    • 原创:19篇
    • 转载:5篇
    • 译文:1篇
    • 评论:9条
    最新评论