开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2005

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 714|回复: 3

[哪来的胖子] ShaderLab 第三节 基本光照模型

[复制链接]  [移动端链接]
排名
1140
昨日变化
4

34

主题

105

帖子

1957

积分

Rank: 9Rank: 9Rank: 9

UID
35368
好友
19
蛮牛币
366
威望
0
注册时间
2014-7-20
在线时间
724 小时
最后登录
2017-12-12

专栏作家活力之星

QQ
发表于 2016-11-13 11:50:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 哪来的胖子 于 2016-12-5 21:31 编辑

内容说明:
         1间接光照和直接光照
         2光照模型
   说明:可以查看OpenGL3.0关于照明的说明http://www.unitybeginner.com/?p=160
   说明:unity内置着色器下载地址https://unity3d.com/cn/get-unity/download/archive
         06内置着色器下载地址.jpg

1 间接照明和直接照明
         间接照明是光在物体间传播后,最终有对物体形成照明。在实际应用中这种照明一般通过预先烘焙得到。
         直接照明不考虑光再物体间的传播,也不考虑光线在物体内的传播,光线直接对物件照明。我们把照明的结果分成漫反射和镜面反射两种,其中镜面反射会形成高光。直接照明是实时渲染的重点。

2 照明计算方式:光照模型
2.1 漫反射和Lambert表达式
         对于粗糙物体表面上面的一点,其亮度应该和入射的光线垂直程度有关,也就是入射角和发现的夹角。如果我们用L表示入射法线,用c表示光线的强度和颜色,用N表示次点的法线,那么物体这点的亮度Lum就可以用如下公式表示。
         Lum= c*max(0,cos<L,N>) (L,N都是单位矩阵) = c*max0dot(L,N)
这就是Lambert的漫反射模型。

下面是实现的Shader
[C#] 纯文本查看 复制代码
Shader "Lession03/Demo001"
{
        Properties {
                _MainTex("MainTex",2D)="white"{}
        }

        SubShader {
                pass{
                Tags{"LightMode"="ForwardBase"}
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"//下面找不到的方法或数据就在这里面

                float4 _LightColor0;//灯光数据
                sampler2D _MainTex;
                float4 _MainTex_ST;

                //片段着色器使用数据
                struct v2f {
                        float4 pos:SV_POSITION;
                        float2 uv:TEXCOORD0;
                        float3 lightDir:TEXCOORD1;
                        float3 normal:TEXCOORD2;
                };

                //顶点处理
                v2f vert (appdata_full v) {
                        v2f o;
                        o.pos=mul(UNITY_MATRIX_MVP,v.vertex);//屏幕渲染位置
                        o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);//取得UV
                        
                        o.lightDir=ObjSpaceLightDir(v.vertex);//入射向量
                        o.normal=v.normal;//法线
                        return o;//丢给片段着色器了
                }

                //片段着色器
                float4 frag(v2f i):COLOR
                {
                        i.lightDir=normalize(i.lightDir);//单位化向量
                        i.normal=normalize(i.normal);

                        float4 c=tex2D(_MainTex,i.uv);//纹理颜色

                        float diff=max(0,dot(i.normal,i.lightDir));//夹角cos值

                        c=c*_LightColor0*(diff);//运算结果
                        return c;
                }
                ENDCG
                }
        } 
        FallBack "Diffuse"
}

07漫反射效果.jpg
2.2 镜面高光和Phong
         镜面高光就是折射的问题,也就是反射向量射视线向量夹角有关,原理就是下面这张图:
08镜面高光原理.jpg
我们可以通过reflect(入射向量,法线)求出反射向量,那么高光的公式就可以用下面的方式表达:
         Spec= powmax0dotR,V)),gloss)(R反射向量,V视线向量,gloss 波瓣系数)
Shader代码如下:
[C#] 纯文本查看 复制代码
Shader "Lession03/Demo002"
{
        Properties {
                _MainTex("MainTex",2D)="white"{}
        }
        SubShader {
                pass{
                Tags{"LightMode"="ForwardBase"}
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"

                float4 _LightColor0;
                sampler2D _MainTex;
                float4 _MainTex_ST;
                struct v2f {
                        float4 pos:SV_POSITION;
                        float2 uv:TEXCOORD0;
                        float3 lightDir:TEXCOORD1;
                        float3 viewDir:TEXCOORD2;
                        float3 normal:TEXCOORD3;
                };

                v2f vert (appdata_full v) {
                        v2f o;
                        o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                        o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                        
                        o.lightDir=ObjSpaceLightDir(v.vertex);
                        o.viewDir=ObjSpaceViewDir(v.vertex);
                        o.normal=v.normal;
                        return o;
                }

                float4 frag(v2f i):COLOR
                {
                        i.lightDir=normalize(i.lightDir);
                        i.viewDir=normalize(i.viewDir);
                        i.normal=normalize(i.normal);

                        float4 c=tex2D(_MainTex,i.uv);
                        float3 r=  reflect(-i.lightDir,i.normal);
                        float spec=max(0,dot(r,i.viewDir));
                        spec=pow(spec,5)*4;
                        float diff=max(0,dot(i.normal,i.lightDir));

                        c=c*_LightColor0*(diff)+c*spec*_LightColor0;

                        return c*2;
                }
                ENDCG
                }
        } 
        FallBack "Diffuse"
}

09镜面高光效果.jpg
2.3使用SurfaceShader实现光照
[C#] 纯文本查看 复制代码
Shader "Lession03/Demo003"
{
        Properties {
                _MainTex ("Albedo (RGB)", 2D) = "white" {}
        }

        SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 200
                
                CGPROGRAM
                //#pragma sufrace surfaceFunction lightModel [optionalparams]
                //Lambert BlinnPhong 是自带的光照模型 可以直接使用
                #pragma surface surf BlinnPhong

                sampler2D _MainTex;
                struct Input {
                        float2 uv_MainTex;
                };

                void surf (Input IN, inout SurfaceOutput  o) 
                {
                        fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
                        o.Albedo = c.rgb;
                        o.Alpha = c.a;
                }
                ENDCG
        }
        FallBack "Diffuse"
}

10SurfaceShader实现.jpg


项目资源下载地址(代码是基于5.x版本的):http://pan.baidu.com/s/1sl4GKln

更多教程欢迎访问随风工作室博客:http://www.unitybeginner.com/blog/


回复

使用道具 举报

6蛮牛粉丝
1051/1500
排名
1975
昨日变化
9

0

主题

252

帖子

1051

积分

Rank: 6Rank: 6Rank: 6

UID
180505
好友
2
蛮牛币
869
威望
0
注册时间
2016-11-3
在线时间
231 小时
最后登录
2017-12-12
QQ
发表于 2016-11-13 16:24:46 | 显示全部楼层
嗯  看完了,再次感谢楼主分享,虽然看完后还是一脸蒙蔽

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1386/1500
排名
1413
昨日变化
2

7

主题

326

帖子

1386

积分

Rank: 6Rank: 6Rank: 6

UID
104110
好友
0
蛮牛币
306
威望
0
注册时间
2015-5-29
在线时间
337 小时
最后登录
2017-11-10
发表于 2016-11-14 09:57:59 | 显示全部楼层
unity的SurfaceShader在实际中用的多吗?我看很多文章都只介绍顶点和片段shader

回复 支持 反对

使用道具 举报

排名
1140
昨日变化
4

34

主题

105

帖子

1957

积分

Rank: 9Rank: 9Rank: 9

UID
35368
好友
19
蛮牛币
366
威望
0
注册时间
2014-7-20
在线时间
724 小时
最后登录
2017-12-12

专栏作家活力之星

QQ
 楼主| 发表于 2016-11-14 10:07:00 | 显示全部楼层
eagle1098 发表于 2016-11-14 09:57
unity的SurfaceShader在实际中用的多吗?我看很多文章都只介绍顶点和片段shader

不多,用起来不灵活

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表