Unity Shader学习(二)---光照的问题

(一)基本的物理知识

光学中用辐照度来量化光。光线由光源发射出来以后会与一些物体相交,结果为散射或者吸收。散射分为折射和透射。

为了区分不同的散射方向,在光照模型中用不同的部分计算:高光反射和漫反射。

着色指的是根据材质属性(如漫反射属性等),光源信息(如光源方向、折射度),使用一个等式去计算沿某个观察方向的出射度的过程,我们也把这个等式称为光照模型。

(1).环境光:环境光模拟间接光照。

(2).自发光:材质的自发光颜色,自发光的表面不会照亮周围的表面。

(3).漫反射:漫反射中视角的位置不一样,反射是完全随机的。漫反射符合兰伯特定律,反射光的强度与表面法线和光源方向之间的夹角的余弦值成正比.

(4).高光反射:计算高光反射需要的信息比较多,如表面法线,视角方向,光源方向,反射方向等。常用的有Phong模型,Blinn模型

逐像素光照:在片元着色器中计算为逐像素光照,以每个像素为基础,得到它的法线(可以是对顶点法线插值得到的,也可以是从法线纹理中采样得到的),然后进行光照模型的计算,这种在面片之间对顶点法线进行查值得技术为Phong着色,PHONG插值或法线插值着色技术

逐像素光照:在顶点着色器中计算为逐顶点光照,也称为高洛得着色,我们会在每个顶点上计算光照,然后在渲染图元内部进行线性插值,最后输出像素颜色。

(二)在Unity实现简单的光照模型常用的函数

1.Unity环境光在window->lighting->Ambient Source/Ambient Color/Ambient Intensity中控制,在shader中通过UNITY_LIGHTMODEL_AMBIENT可以得到环境光的颜色和强度信息

2.saturate函数(Cg中提供的函数),防止一个标量或矢量为负值,转为[0,1]

saturate(x) x可以为float2 float3 float4

3 reflect(i,n)函数 法线方向n和入射方向i,计算反射方向的函数reflect(i,n)

4.UnityCG.cginc中有一些常用的帮助函数

_WorldSpaceLightPos0 获得当前世界空间的光照

光源方向 normalize(_WorldSpaceLightPos0.xyz);

视角方向 normalize(_WorldSpaceCameraPos.xyz-v.pos.xyz)


float3 WorldSpaceViewDir(float4 v) 输入一个模型空间中的顶点位置,返回世界空间中从该顶点到摄像机的观察方向,内部实现用UnityWorldSpaceViewDir

float3UnityWorldSpaceViewDir(float4 v) 输入一个世界空间中的顶点位置,返回世界空间中从该顶点到摄像机的观察方向

float3 UnityWorldSpaceViewDir(float4 v){

return _WorldCameraPos.xyz - worldPos;

}

float3 ObjSpaceViewDir(float4 v) 输入一个模型空间中的顶点位置,返回模型空间中从该顶点到摄像机的观察方向

float3 WorldSpaceLightDir(float4 v)输入一个模型空间的顶点位置,返回世界空间中该点到到光源的方向,内部实现用的UnityWorldSpaceLightDir,没有归一化

float3 UnityWorldSpaceLightDir(float4 v)输入一个世界空间的顶点位置,返回世界空间中该点到到光源的方向,没有归一化

float3 ObjSpaceLightDir(float4 v)输入一个模型空间的顶点位置,返回模型空间到光源的光照方向,没有归一化

float3 UnityObjectToWorldNormal(float3 normal)把法线从模型空间转换到世界空间

float3 UnityObjectToWorldDir(float3 dir)把方向矢量从模型空间转化到世界空间

float3 UnityWorldToObjectDir(float3 dir)把方向矢量从世界空间到模型空间

这些函数一般没有归一化

(三)漫反射光照模型的实现

1.逐顶点实现漫反射光照

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex-Level" {
    Properties {
        _Diffuse ("Diffuse"Color) = (1111)//控制材质的漫反射颜色
    }
    SubShader {
        Pass { 
            Tags { "LightMode"="ForwardBase" }     
            CGPROGRAM          
            #pragma vertex vert
            #pragma fragment frag           
            #include "Lighting.cginc"        
            fixed4 _Diffuse;       
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };            
            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR;
            };            
            v2f vert(a2v v) {
                v2f o;
                // Transform the vertex from object space to projection space
                o.pos = UnityObjectToClipPos(v.vertex);//mul(UNITY_MATRIX_MVP,v.vertex) 坐标转换 模型空间到                
                // Get ambient term
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;               
                // Transform the normal from object space to world space
                fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));//法线,转换到世界坐标,并且归一化
                // Get the light direction in world space
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                // Compute diffuse term
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));     
                o.color = ambient + diffuse;              
                return o;
            }         
            fixed4 frag(v2f i) : SV_Target {
                return fixed4(i.color1.0);
            }        
            ENDCG
        }
    }
    FallBack "Diffuse"
}

2.逐像素实现漫反射光照

Shader "Unity Shaders Book/Chapter 6/Diffuse Pixel-Level" {
    Properties {
        _Diffuse ("Diffuse"Color) = (1111)
    }
    SubShader {
        Pass { 
            Tags { "LightMode"="ForwardBase" }       
            CGPROGRAM            
            #pragma vertex vert
            #pragma fragment frag           
            #include "Lighting.cginc"           
            fixed4 _Diffuse;         
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };         
            struct v2f {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
            };           
            v2f vert(a2v v) {
                v2f o;
                // Transform the vertex from object space to projection space
                o.pos = UnityObjectToClipPos(v.vertex);
                // Transform the normal from object space to world space
                o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
                return o;
            }          
            fixed4 frag(v2f i) : SV_Target {
                // Get ambient term
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;              
                // Get the normal in world space
                fixed3 worldNormal = normalize(i.worldNormal);
                // Get the light direction in world space
                fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);             
                // Compute diffuse term
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));             
        

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值