Diffuse Shading——漫反射光照改善技巧

转: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,希望自己以后也可以有所创新,可以为游戏增光添彩。

时间: 2024-12-24 22:27:26

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

第六章:漫反射光照

原文链接: http://www.rastertek.com/gl40tut06.html Tutorial 6: Diffuse Lighting In this tutorial I will cover how to light 3D objects using diffuse lighting and OpenGL 4.0. We will start with the code from the previous tutorial and modify it. 本章将介绍如何使用Ope

使用RampTexture来控制diffuse shading

[RampTexture] RampTexture(渐变纹理),可以是1D/2D纹理. This allows you to accentuate the surface's colors to fake the effects of more bounce light or a more advanced lighting setup. You see this technique used a lot more for cartoony games, where you need a mor

【DirectX11】第八篇 光照模型——漫反射

本系列文章主要翻译和参考自<Real-Time 3D Rendering with DirectX and HLSL>一书(感谢原书作者),同时会加上一点个人理解和拓展,文章中如有错误,欢迎指正. 这里是书中的代码和资源. 本文所有的环境和工具使用都基于之前的文章,如有不明白的地方请先参考本系列之前的几篇文章. 本文索引: 关于灯光 Diffuse Lighting 漫反射光照 1 Directional Lights 平行光 2 Diffuse Lighting Effect Preambl

光照贴图烘焙

转载自CSDN雨蒙一,简书自由的天空等人,感谢分享: https://www.jianshu.com/p/3e1e002f5684 基础知识了解一下: 1,什么是贴图(Texture)? 贴图(texture)是一张不大的二维图像,它呈现了某个表面的最终信息.它被指定到线框多边形的表面,给予模型最终的外观.贴图的制作技巧是创建游戏真实度方面的关键因素. 2,贴图格式及大小 一般情况下,贴图的实现在图像处理软件中制作完成,纹理一般会包含很多信息和图层,也将随后被储存成PSD格式,当制作完成后,文件

【浅墨Unity3D Shader编程】之七 静谧之秋篇: 表面着色器的写法(二)——自定义光照模式

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://hpw123.net/plus/view.php?aid=183 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] QQ交流群:330595914 更多文章尽在:http://www.hpw123.net 本文主要讲解了Unity中SurfaceShader的自定义光照模式的写法. 上篇文章中我们已经说到,表面着色器将分为两次讲解,上

Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其他方向. 最后,摄像机吸收了一些光,产生了一张图像. 在光学中,我们使用辐照度来量化光.对于平行光来说,它的辐照度可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到.在计算光照模型时,我们需要知道一个物体表面的辐照度,而物体表面往往是和l不垂直的,我们可以

第五章 Unity中的基础光照(2)

目录 1. Unity中的环境光和自发光 2. 在UnityShader中实现漫反射光照模型 2.1 实践:逐顶点光照 2.2 实践:逐像素光照 2.3 半兰伯特模型 1. Unity中的环境光和自发光 在标准光照模型中,环境光和自发光的计算是最简单的. 在Unity中,场景中的环境光可以在Window->Lighting->Ambient Source/Ambient Intensity中控制,如下图所示.在Shader中,我们只需要通过Unity的内置变量UNITY_LIGHTMODEL_

【Unity Shaders】Shader中的光照

写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故,导致我们无法自如地处理很多常见的光照变量.这篇我们就来讨论下Unity内置的一些光照变量和函数到底怎么用. 以下内容均建立在Forward Rendering Path的基础上. 自己总结的,如果有硬伤一定要告诉我啊!感激不尽~ 主要参考: http://en.wikibooks.org/wiki/Cg_P

【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&amp;颜色、光照与材质

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] 本篇文章中,我们学习了Unity Shader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照.材质与颜色的具体写法.写了6个Shader作为本文S