看很多人实现shader都用插件shader force,那我还学shader干X!!!???

好了,废话不多说,学习shader去。。。。


漫反射在shader里算是最基础的知识了。入手shader,你必须可以信手拈来一个漫反射吧??什么叫信手拈来,就是不查阅资料的前提下吧

那我就信手拈来一个半兰伯特漫反射效果吧(瞄了一眼资料,好像没人看见)。

正常的漫反射公式(Lambert)是这样的:

C(diffuse) = C(light) * M(diffuse)max(0,n*I)

C(light):入射光的颜色和强度

M(diffuse):材质的漫反射系数

n:世界坐标系下的表面法线

I:世界坐标系下的光源方向(反射点指向光源的矢量)

max函数:,将结果截取到0,防止法线与光源方向的点乘为负值,被背后的光源照亮的错误效果

而笔者会比较喜欢一个毫无依据的半兰伯特公式:

C(diffuse) = (C(light) * M(diffuse))(0.5(n*l)+0.5)

这个公式实现的漫反射效果看起来更真实一些(据说是让亮度更亮一点,特别是比较暗的地方)


好了,又要放代码了:

笔者是在顶点着色器中计算空间法线和空间灯光矢量,为的是让效果更佳精确点

但是同样笔者也有个疑问:我尝试在顶点着色器里面对贴图纹理进行采样,但是报错了,不知道为什么不能这样做?

Shader "CharmingShader/Wangzhe/Diffuse"
{
Properties
{
_MainTex("Main Tex",2D) = "white"{}
_DiffuseColor("Diffuse Color",Color) = (,,,)
}
SubShader
{
Tags{"Queque" = "Opaque"}
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc" sampler2D _MainTex;
float4 _MainTex_ST;
float4 _DiffuseColor; struct a2v
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float3 normal :NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
//float3 color : COLOR;
float halfLambert : TEXCOORD0;
float2 uv : TEXCOORD1;
}; v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
float3 worldPos = mul(unity_ObjectToWorld, o.pos);
float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
o.halfLambert = dot(worldNormal, worldLightDir)*0.5 + 0.5; return o;
} float4 frag(v2f f) : SV_Target
{
float3 col = tex2D(_MainTex, f.uv).rgb;
float3 diffuse = col * _DiffuseColor.rgb;
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * col;
float3 color = ambient + _LightColor0.rgb * diffuse * f.halfLambert;
return float4(color,);
} ENDCG
}
}
}

这里要注意一点,不管是在pass前面的tags还是pass里面的tags都是尤为重要的。

Tags标签是一个键值对,它们告诉Unity的渲染引擎如何及何时去渲染这个对象

这里用到的Tags{"LightMode" = "FarwordBase"},在官方文档是这样解释的:

Details

Tags are basically key-value pairs. Inside a Pass tags are used to control which role this pass has in the lighting pipeline (ambient, vertex lit, pixel lit etc.) and some other options. Note that the following tags recognized by Unity must be inside Pass section and not inside SubShader!

LightMode tag

LightMode tag defines Pass’ role in the lighting pipeline. See render pipeline for details. These tags are rarely used manually; most often shaders that need to interact with lighting are written as Surface Shaders and then all those details are taken care of.

Possible values for LightMode tag are:

  • Always: Always rendered; no lighting is applied.
  • ForwardBase: Used in Forward rendering, ambient, main directional light, vertex/SH lights and lightmaps are applied.
  • ForwardAdd: Used in Forward rendering; additive per-pixel lights are applied, one pass per light.
  • Deferred: Used in Deferred Shading; renders g-buffer.
  • ShadowCaster: Renders object depth into the shadowmap or a depth texture.
  • MotionVectors: Used to calculate per-object motion vectors.
  • PrepassBase: Used in legacy Deferred Lighting, renders normals and specular exponent.
  • PrepassFinal: Used in legacy Deferred Lighting, renders final color by combining textures, lighting and emission.
  • Vertex: Used in legacy Vertex Lit rendering when object is not lightmapped; all vertex lights are applied.
  • VertexLMRGBM: Used in legacy Vertex Lit rendering when object is lightmapped; on platforms where lightmap is RGBM encoded (PC & console).
  • VertexLM: Used in legacy Vertex Lit rendering when object is lightmapped; on platforms where lightmap is double-LDR encoded (mobile platforms).

意思是:LightMode标签是在Pass里面,管理处在光照管道中的pass和其它选项。注意LightMode标签必须处在Pass里面而不是SubShader里面。

由于时间的关系,我就只翻译一下ForwardBase:ForwardBase用在Forward渲染中,渲染时可以应用到环境光、主平行光、顶点光和球谐光照以及光照贴图。

之前一直忽视了这个标签的作用,导致如何调效果都灰常暗。

下面放两张对比图吧:

普通贴图效果------------------------------------------------->半兰伯特漫反射效果

虽然半兰伯特效果看起来更自然点,但是相对的亮度也比较暗了,反而没有图一看起来惊艳,而仅仅是更写实了点。

(有一位小萌同事也提出了这个问题:喵~~脸这么黑,哪里好看了!

我当时心里嘀咕到:想要怎样就怎样,哪有这么好的事情哦?)


(后来一次机缘巧合,得到了一块秘籍残片)咳咳,哪有这么神话。也就是我想装逼翻译文章遇到很多不会的名词,比如说SH Lights,

然后我就贴到Unity Shader群里问了问, 当时有个头衔为话痨id为落俗的小伙伴很热情的为我解答,并且贴出一段能让这个漫反射更好

看的代码。

SH Lights就是球谐光照,利用球谐光照技术可以实时重现面积光源下3D模型的全局光照效果(好吧,我也不懂,我就记住一个球)

代码是这样的(据说要有天空盒才会有效果):

在v2f结构体里定义sh

在顶点着色器里面计算sh,注意这里要对v2f o进行一次初始化

最后在片源着色器输出颜色里加上对sh的处理

Ctrl+S跳转界面,噔噔噔噔,有没被惊艳到= =


这里贴上完整的代码:

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "CharmingShader/Wangzhe/Diffuse"
{
Properties
{
_MainTex("Main Tex",2D) = "white"{}
_DiffuseColor("Diffuse Color",Color) = (,,,)
}
SubShader
{
Tags{"Queque" = "Opaque"}
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc" sampler2D _MainTex;
float4 _MainTex_ST;
float4 _DiffuseColor; struct a2v
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float3 normal :NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
//float3 color : COLOR;
float halfLambert : TEXCOORD0;
float2 uv : TEXCOORD1;
#if UNITY_SHOULD_SAMPLE_SH
float3 sh : TEXCOORD2;
#endif
}; v2f vert(a2v v)
{
v2f o = (v2f);
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
float3 worldPos = mul(unity_ObjectToWorld, o.pos);
float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
#ifndef LIGHTMAP_ON
#if UNITY_SHOULD_SAMPLE_SH
o.sh = ShadeSHPerVertex(worldNormal, o.sh);
#endif
#endif
o.halfLambert = dot(worldNormal, worldLightDir)*0.5 + 0.5; return o;
} float4 frag(v2f f) : SV_Target
{
float3 col = tex2D(_MainTex, f.uv).rgb;
float3 diffuse = col * _DiffuseColor.rgb;
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * col;
float3 color = ambient + _LightColor0.rgb * diffuse * f.halfLambert + diffuse * f.sh;
return float4(color,);
} ENDCG
}
}
}

shader之半兰伯特漫反射的更多相关文章

  1. 【Unity Shader学习笔记】Unity光照基础-半兰伯特光照

    在光照无法达到的区域,模型的外观通常是全黑的,没有任何明暗变化,这会使模型的背光区域看起来就像一个平面. 使用半兰伯特光照可以解决这个问题. 逐顶点光照技术也被称为兰伯特光照模型.因为它符合兰伯特定律 ...

  2. Unity shader学习之半兰伯特光照模型

    半兰伯特光照模型,为Valve公司在开发游戏<半条命>时提出的一种技术,用于解决漫反射光无法到达区域无任凭明暗变化,丢失模型细节表现的问题. 其公式如下: Cdiffuse = Cligh ...

  3. Unity3D Shader 半兰伯特光照模型

    //效果预览 //Shader代码 Shader "Unlit/HalfLambert" { Properties { _MainTex ("Texture", ...

  4. Lambert (兰伯特)光照模型

    Lambert (兰伯特)光照模型 是光源照射到物体表面后,向四面八方反射,产生的漫反射效果.这是一种理想的漫反射光照模型.如下图:这个是顶点函数处理后的该光照模型,因此看起来像素不够平滑. 漫反射 ...

  5. 兰伯特余弦定理(Lambert)

    兰伯特余弦定理(Lambert) 1.漫反射,是投射在粗糙表面上的光向各个方向反射的现象.当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向 ...

  6. 解读Unity中的CG编写Shader系列八(多光源漫反射)

    转自http://www.itnose.net/detail/6117338.html 前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下 ...

  7. 求解轨道力学二体意义下的Lambert方程(兰伯特方程)的Fortran程序

    轨道力学中二体问题下求解兰伯特方程. 老外写的Matlab程序,我把它转成了Fortran程序. !************************************************** ...

  8. Unity3D 开发之shader教程(浅谈光照之漫反射diffuse)

    在游戏开发过程中,光照应该是必不可少部分,当然,这是指大多数的稍微大型一些的3D游戏会需要,给模型或者山山水水加上光照,会看上去更加的真实,获得更好的体验.一个本身不发光物体显示什么颜色,在于本身反射 ...

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

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

随机推荐

  1. js的DOM操作

    ID选择器:document.getElementById("").innerHTML="" class选择器:var divc= document.getEl ...

  2. PHP xmapp 下面安装 Composer-Setup.exe

    1.打开PHP配置文件E:\xampp\php\php.ini确认以下模块已开启(移除前面的分号). extension=php_openssl.dll, (php.ini文档里面开启一次就OK了) ...

  3. vsftpd配置虚拟用户

    #安装vsftpd yum -y install vsftpd #创建本地ftp账户 groupadd ftpuser useradd -g ftpuser -s /sbin/nologin ftpu ...

  4. 打包可执行的jar

    #配置项目路径 *除程序文件以外,其他相关素材也可以打包进jar,但在内部访问时需以包名作为跟路径,如hello/xxx/yyy.zzz mkdir hello vi hello/HelloWorld ...

  5. 【Linux相识相知】bash的基础特性

    命令历史 shell进程会记录用户提交执行过的命令 可以是用history查看: [root@localhost dev]# history ss -tnl ifconfig vi /etc/sysc ...

  6. 移动端300ms的点击延迟以及解决方案

    [今天做在移动端的一些效果时,我选择使用动画而不是用过渡,这个300ms的点击延迟是我为什么使用动画而不使用过渡最主要的一个原因] 动画和过渡 共同点:都是css控制DOM运动, 不同点: 1.过渡: ...

  7. docker~使用阿里加速器安centos

    回到目录 上一篇说了hub.docker.com里拉个镜像太,而阿里云为我们做了不少本国镜像,这样下载的速度就很惊人了,下面看一下在centos7下配置阿里云加速器的方法 打开服务配置文件 vi /e ...

  8. 玩玩微信公众号Java版之准备

    微信自2013年流行起来,现在的发展已经超过了我们的想象,那么对应的公众平台,小程序等都是让人眼前一亮的东西,这里来学习一下微信工作号的对接,实现为Java,希望大家一起学习!   这里大概描述一下所 ...

  9. 基于android的语音质量评估

    最近研究如何通过android评估通话质量,希望获取的参数有:(1)接通时长 (2)掉话次数 (3)语音是否清晰,以下将给出接通时长和掉话次数的详细定义: 接通时长:通话一方开始拨号到另一方开始振铃的 ...

  10. cognos安装和配置即席报表流程

    安装前的配置: 1.  Cognos数据库的创建和用户的创建 注意:字符集需要设置为UTF-8:Cognos用户权限可以给dba: 2.系统上原有JDK的删除(因为Cognos已经自带JDK) 安装- ...