转:http://www.narkii.com/club/thread-355113-1.html

我们会列出两种方法:使用Half Lambert lighting model(半兰伯特光照模型)和使用一个ramp texture来控制diffuse shading。



准备工作



同样,我们需要你已经做好了上一篇文章中的内容,并得到了如下shader:

Shader “Custom/BasicDiffuse” {

Properties {

_EmissiveColor (“Emissive Color”, Color) = (1,1,1,1)

_AmbientColor(“Ambient Color”, Color) = (1,1,1,1)

_MySliderValue (“This is a Slider”, Range(0,10)) = 2.5

}

SubShader {

Tags { “RenderType”=”Opaque” }

LOD 200

CGPROGRAM

#pragma surface surf BasicDiffuse



//We need to declare the properties variable type inside of the

//CGPROGRAM so we can access its value from the properties block.

float4 _EmissiveColor;

float4 _AmbientColor;

float _MySliderValue;



struct Input

{

float2 uv_MainTex;

};



void surf (Input IN, inout SurfaceOutput o)

{

//We can then use the properties values in our shader

float4 c;

c =pow((_EmissiveColor + _AmbientColor), _MySliderValue);

o.Albedo = c.rgb;

o.Alpha = c.a;

}



inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)

{

float difLight = max(0, dot (s.Normal, lightDir));

float4 col;

col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);

col.a = s.Alpha;

return col;

}



ENDCG

}

FallBack “Diffuse”

}

创建一个Half Lambert lighting model(半兰伯特光照模型)



如果你看过之前的文章中,相信还记得Lambert这个名字。没错,它就是Unity默认的diffuse lighting model。简单来说,Lambert定律认为,在平面某点漫反射光的光强与该反射点的法向量和入射光角度的余弦值成正比(即我们之前使用dot函数得到的结果)。Half Lambert最初是由Valve(游戏半条命2使用的引擎即是其开发的)提出来,用于提高物体在一些光线无法照射到的区域的亮度的。简单说来,它提高了漫反射光照的亮度,使得漫反射光线可以看起来照射到一个物体的各个表面。而Half Lambert最初也是被用于游戏半条命的画面渲染,为了防止某个物体的背光面丢失形状并且显得太过平面化。这个技术是完全没有基于任何物理原理的,而仅仅是一种感性的视觉增强(参考这里)。

好啦,说了这么多还是要演示一下,代码非常简单!我们只需要稍微更改上述的LightingBasicDiffuse函数:

inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)

{

float difLight = max(0, dot (s.Normal, lightDir));

// Add this line

float hLambert = difLight * 0.5 + 0.5;



float4 col;

// Modify this line

col.rgb = s.Albedo * _LightColor0.rgb * (hLambert * atten * 2);

col.a = s.Alpha;

return col;

}

由代码可以看出,我们定义了一个新的变量hLambert来替换difLight用于计算某点的颜色值。difLight的范围是0.0-1.0,而通过hLambert,我们将结果由0.0-1.0映射到了0.5-1.0,从而达到了增加亮度的目的。下图显示了这一变化:



我们可以通过对比来看一下Lambert和Half Lambert的渲染区别(分别对应左图和右图):



创建一个ramp texture来控制diffuse shading



下面介绍另一种简单实用的方法——使用一张ramp texture(渐变图)来控制漫反射光照的颜色。这允许你着重强调surface的颜色而减弱漫反射光线或者其他更高级光线的影响。 可以在很多卡通风格的游戏中看到这种技术,通常在这些情况下你需要一个更加艺术而非写实风格的画面,并且不需要很多的真实物理模拟的光照模型。

这个技术在Team Fortress 2(军团要塞2)中流行起来,这个技术也是由Valve提出来用于渲染他们的游戏角色的。他们发表了一个非常有名的论文,强烈建议你应该读一下它!这篇论文讲解了军团要塞2中使用的光照和渲染技术。

上代码!

我们重新修改LightingBasicDiffuse函数,增加一个新的变量ramp:

inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)

{

float difLight = max(0, dot (s.Normal, lightDir));

float hLambert = difLight * 0.5 + 0.5;

float3 ramp = tex2D(_RampTex, float2(hLambert)).rgb;



float4 col;

col.rgb = s.Albedo * _LightColor0.rgb * (ramp);

col.a = s.Alpha;

return col;

}

其中,我们还需要一张texture,即_RampTex。即之前说到的渐变图。回忆一下,为了能够在Inspector中拖拽一个texture,并在shader中使用需要怎么做?首先,我们需要在Properties块中声明它,然后在SubShader中声明一个相同名字的变量,并制定它的类型,之后就可以在函数中访问它啦!忘记的请翻看之前的几篇文章。完整的代码如下:

Shader “Custom/RampDiffuse” {

Properties {

_EmissiveColor (“Emissive Color”, Color) = (1,1,1,1)

_AmbientColor(“Ambient Color”, Color) = (1,1,1,1)

_MySliderValue (“This is a Slider”, Range(0,10)) = 2.5

// Add this line

_RampTex (“Ramp Texture”, 2D) = “white”{}

}

SubShader {

Tags { “RenderType”=”Opaque” }

LOD 200



CGPROGRAM

#pragma surface surf BasicDiffuse



//We need to declare the properties variable type inside of the

//CGPROGRAM so we can access its value from the properties block.

float4 _EmissiveColor;

float4 _AmbientColor;

float _MySliderValue;

// Add this line

sampler2D _RampTex;



struct Input

{

float2 uv_MainTex;

};



void surf (Input IN, inout SurfaceOutput o)

{

//We can then use the properties values in our shader

float4 c;

c =pow((_EmissiveColor + _AmbientColor), _MySliderValue);

o.Albedo = c.rgb;

o.Alpha = c.a;

}



inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)

{

float difLight = max(0, dot (s.Normal, lightDir));

float hLambert = difLight * 0.5 + 0.5;

// Add this line

float3 ramp = tex2D(_RampTex, float2(hLambert)).rgb;



float4 col;

// Modify this line

col.rgb = s.Albedo * _LightColor0.rgb * (ramp);

col.a = s.Alpha;

return col;

}



ENDCG

}

FallBack “Diffuse”

}

使用的ramp texture(渐变图)如下:



其中最重要的代码只有一行:

float3 ramp = tex2D(_RampTex, float2(hLambert)).rgb;

这行代码返回一个rgb值。tex2D函数接受两个参数:第一个参数是操作的texture,第二个参数是需要采样的UV坐标。这里,我们并不像使用一个vertex来代表一个UV坐标进行采样,而仅仅想使用一个漫反射浮点值(即hLambert)来映射到渐变图上的某一个颜色值。最后得到的结果便是,我们将会根据计算得到的Half Lambert光照值来决定光线照射到一个物体表面的颜色变化。



我们再来对比看一下Half Lambert和添加了ramp texture控制后的渲染区别(分别对应左图和右图):

结束语



Diffuse Shader还有最后一篇文章就会阶段性结束了。通过这一些文章,相信已经对Unity Shaders有了一个大致的了解。呼,作为一个初学者,现在的渲染结果可能看起来还狠简陋,但是一口气吃个胖子是不现实的!呼呼,加油!相信学习这些对游戏渲染还是很有帮助的,毕竟每一个出色游戏几乎全部都使用了自己编写的shader,希望自己以后也可以有所创新,可以为游戏增光添彩。

Diffuse Shading——漫反射光照改善技巧的更多相关文章

  1. 【Unity Shaders】Diffuse Shading——漫反射光照改善技巧

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  2. 【Unity Shaders】Diffuse Shading——使用2D ramp texture来创建一个假的BRDF(双向反射分布函数)

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  3. 【Unity Shaders】概述及Diffuse Shading介绍

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  4. [Unity Shader] 逐顶点光照和逐片元漫反射光照

    书中的6.4节讲的是漫反射的逐顶点光照和逐片元光照. 前一种算法是根据漫反射公式计算顶点颜色(顶点着色器),对颜色插值(光栅化过程)返回每个像素的颜色值(片元着色器). 第二种算法是获得顶点的法线(顶 ...

  5. 【Unity Shader学习笔记】Unity光照基础-漫反射光照

    本代码只适用于平行光. 1.逐顶点漫反射光照 1.1漫反射光照原理 1.2代码实现 在Properties语义块中声明一个漫反射颜色属性 Properties { //漫反射参数,用于调整漫反射效果 ...

  6. 使用RampTexture来控制diffuse shading

    [RampTexture] RampTexture(渐变纹理),可以是1D/2D纹理. This allows you to accentuate the surface's colors to fa ...

  7. 【Unity Shaders】Diffuse Shading——创建一个自定义的diffuse lighting model(漫反射光照模型)

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  8. 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  9. 优化实现Mobile Diffuse动态直接光照shader

    项目中美术使用了Unity自带的Mobile/Diffuse这个shader制作了一部分场景素材,这个shader会依赖场景中的动态实时光源,比较耗费. 于是自己手动重写一份,简化shader的消耗, ...

随机推荐

  1. UDP中使用bind和connect的作用

    1:UDP中可以使用connect系统调用 2:UDP中connect操作与TCP中connect操作有着本质区别. TCP中调用connect会引起三次握手,client与server建立连结.UD ...

  2. AnguarJS中链式的一种更合理写法

    假设有这样的一个场景: 我们知道一个用户某次航班,抽象成一个departure,大致是: {userID : user.email,flightID : "UA_343223",d ...

  3. Chart-template

    ylbtech-Chart: 1.返回顶部 1-1. 2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   7.返回顶部   8.返回顶部   9.返回顶部   ...

  4. (转)Unity3D - 动作动画忽略timeScale

    转自:http://blog.csdn.net/ynnmnm/article/details/46866347 最近在调战斗时的动画与特效,Unity3D对加/减速提供了Time.timeScale支 ...

  5. vue Object.defineProperty Proxy 数据双向绑定

    Object.defineProperty 虽然已经能够实现双向绑定了,但是他还是有缺陷的. 只能对属性进行数据劫持,所以需要深度遍历整个对象 对于数组不能监听到数据的变化 虽然 Vue 中确实能检测 ...

  6. Eclipse 插件开发 -- 深入理解菜单(Menu)功能及其扩展点( FROM IBM)

    Eclipse 插件开发 -- 深入理解菜单(Menu)功能及其扩展点 菜单是各种软件及开发平台会提供的必备功能,Eclipse 也不例外,提供了丰富的菜单,包括主菜单(Main Menu),视图 / ...

  7. 【PMP】项目的定义和特点

    1.定义 项目是为创建独特的产品.服务和成果而进行的的临时性工作. 2.特点 2.1 独特的产品.服务或成果 实现项目目标可能产生一个或多个可交付成果.例如:即便采用相同的材料或者相同的施工单位来建设 ...

  8. 抓取epsg.io的内容

    简述 epsg.io是一个查询EPSG坐标系相关信息的好网站,内容很全.有各种格式的定义可以直接下载,也有坐标系的范围名称等相关信息,所以想抓取这些信息下来,方便对接各个系统. epsg.io本身是开 ...

  9. 查看修改添加环境变量的工具——Rapid Environment Editor

    工欲善其事,必先利其器! 特别是公司或者有其他限制的时候,更需要一个比较简单.实用.强大的工具了! 原来的公司都是小公司,给电脑安装系统.软件等都是自己直接上手,现在在一个大点的公司了,电脑运维有单独 ...

  10. AaronYang WCF教程目录

    ============================原创,讲究实践===================== 1. 那天有个小孩教我WCF[一][1/3]     基本搭建      阅读    ...