Unity Shader入门教程(二)最基本的Diffuse和Normal样例

本教程参考了《猫都能学会的Unity3dShaderLab教程.CHM》,

1.请上网搜索并下载此文件。

2.随后再下载里面提到的素材:

http://vdisk.weibo.com/s/y-NNpUsxhYhZI

第一组实验(复习课,实现最简单的漫反射 [该组实验参考了官网示例中的Normal-Diffuse.shader例子]):

第1.1步:创建一个名为“NormalDiffuse”的shader

第1.2步:看到其中有一些已有的内容,不妨全部删掉(除了第一行),这样更加容易锻炼你的代码能力和加深理解。

笔者将会一行一行地带领读者写这个示例。

详细解读:

▼代码开始
Shader "Custom/NormalDiffuse" {
    Properties{
        //调制色_Color和主要纹理_MainTex将会相乘,得到调制后的颜色
        _Color("The Main Color", Color) = (1,1,1,1)
        _MainTex("Base Picture", 2D) = "white"{}
        //两张图默认都是白色(前面的数据结构是颜色,后面的是二维图像)
    }

        //之前也说过,这是一个处理子程序(一个Pass)
        SubShader{
            //渲染类型是不透明
            Tags{"RenderType" = "Opaque"}
            //当机器的能力超过200时,会执行这个SubShader
            LOD 200

            CGPROGRAM
            //pragma surface 处理函数 光照模型
            /*其中这里的光照模型是Lambert模型,也就是环境光+散射光+反射高光+放射光*/
            #pragma surface surf Lambert

            //还记得吗?同名变量,注意对应关系:Color对应fixed4,2D对应sampler2D
            sampler2D _MainTex;
            fixed4 _Color;

            //输入结构体一定要命名为Input,自己规定其输入,注意纹理坐标的写法一定是纹理贴图变量名前面加uv
            struct Input {
                float2 uv_MainTex;
            };

            //surf函数的输入输出是定死的,即Input和inout SurfaceOutput,后者是输出
            void surf(Input IN, inout SurfaceOutput o)
            {
                //非常简单,就是用tex2D(贴图,纹理坐标)取出纹理上的一点,然后和Color相乘调制即可得到结果
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex)*_Color;
                //Albedo是主颜色的意思(本质是一个用来相乘的系数,当外界光线找到此表面上时,反射的光线 = 入射光线 * Albedo)
                o.Albedo = c.rgb;
                //获得其透明度Alpha
                o.Alpha = c.a;
/*追加说明:SurfaceOutput这个固定好的结构中,有以下几个值:
            struct SurfaceOutput {
                half3 Albedo;     //像素的颜色
                half3 Normal;     //像素的法向值
                half3 Emission;   //像素的发散颜色
                half Specular;    //像素的镜面高光
                half Gloss;       //像素的发光强度
                half Alpha;       //像素的透明度
            };
*/
            }
            ENDCG
    }
        //Fallback暗藏乾坤,表示将此回滚全部插入到本代码中!(我凭什么这么说:http://www.ceeger.com/forum/read.php?tid=31958)
                //也就是说"Legacy Shaders/VertexLit"会完全插入到这里
        Fallback "Legacy Shaders/VertexLit"
}
▲代码结束

注意事项:

Unity3d下方可能有报错提示,可以根据此提示修改代码。

第1.3步:新建一个Material,命名为MNormalDif,按照下图配置一下(注意此处用到了上面它提到的资源)。

总结:这个实验用到的算法和前面第一节入门课提到的一样,就是很简单的取出了纹理颜色,然后就结束了。

第二组内容:

第2.1步:

▼代码开始
Shader "Custom/NormalBumped" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Normal("Normal", 2D) = "bump"{}
        //什么是"bump"{},通过实验可以知道,它是指蓝色“bump” (RGBA: 0.5,0.5,1,0.5),参考:https://docs.unity3d.com/Manual/SL-Properties.html
/*简单说说我是如何知道的:我将下文中的surf函数的代码改为只有一句o.Albedo = tex2D(_Normal, IN.uv_Normal);并在inspector面板中设置Normal为none(于是采用默认值bump),得到下图

当然,这个不是本实验的最终效果,只是为了说明bump是指蓝色(0.5,0.5,1,0.5)罢了
*/
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 300

        CGPROGRAM
        #pragma surface surf Lambert
        fixed4 _Color;
        sampler2D _MainTex;
        sampler2D _Normal;
        struct Input {
            float2 uv_MainTex;
            float2 uv_Normal;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            //o.Albedo = (tex2D(_Normal, IN.uv_Normal)).rgb;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
            //利用UnpackNormal(tex2D(_Normal, IN.uv_Normal))方法获取解包后的法方向(什么是UnpackNormal,存疑)
            o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_Normal));
        }
        ENDCG
    }
    FallBack "Diffuse"
}
▲代码结束

第2.2步:仿照第一组实验的做法,新建一个材质,指定主纹理和法向量贴图。效果为:

第三组实验:本组实验介绍Properties类型

参考资料:http://blog.csdn.net/candycat1992/article/details/17152641

第3.1步:新建一个shader,命名为LearnPropertiesType,新建一个Material应用它。

第3.2步:仅仅在默认的LearnPropertiesType代码中加入几个变量,我们就看看它们的写法和在editor中的样子。

▼代码开始
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0

//新加入的部分:
        _MyRange1("RangedNumber", Range(0,100)) = 20
        _MyFloat2("MyFloat", Float) = 1.1
//其它的就不多说了,只说Cube和Rect的默认值是“”{}这样就可以了,以及Vector如果没有写4维度,默认是4维度的,缺省的通道为1
        _MyInt3("MyInt", Int) = 2
        _MyVec("MyVec", Vector) = (1,1,1,0.5)
        _MyVec3("MyVec3", Vector) = (1,2,3)
        _MyCube("MyCube", Cube) = ""{}
        _MyRec("MyRec", Rect) = ""{}
/*官网中关于默认值的介绍:
For Range and Float properties it’s just a single number, for example “13.37”.
For Color and Vector properties it’s four numbers in parentheses, for example “(1,0.5,0.2,1)”.
For 2D Textures, the default value is either an empty string, or one of the built-in default Textures: “white” (RGBA: 1,1,1,1), “black” (RGBA: 0,0,0,0), “gray” (RGBA: 0.5,0.5,0.5,0.5), “bump” (RGBA: 0.5,0.5,1,0.5) or “red” (RGBA: 1,0,0,0).
For non–2D Textures (Cube, 3D, 2DArray) the default value is an empty string. When a Material does not have a Cubemap/3D/Array Texture assigned, a gray one (RGBA: 0.5,0.5,0.5,0.5) is used.
*/

    }
▲代码结束

第3.3步:查看效果:

以下提供一些学习笔记。

关于着色器的性能的介绍:

http://www.ceeger.com/Components/shader-Performance.html

常规着色器的性能比较:

Unlit<顶点光照<漫反射<高光<视差;

漫反射:

光照强度只和物体、光源有关,即随着物体表面和光的夹角的变小而变小,镜头的移动和旋转不改变光照强度。

下面的两种模型是高光计算模型。

Phong光照模型:

Specular=Ks*lightColor*(dot(视点方向,反射光方向))的shininess次方

其中的反射光方向R的计算用到了巧算公式。

Blinn-Phong光照模型:

Specular=Ks*lightColor*(dot(法方向N,视点方向 - 光入射方向))的shininess次方

以上知识点参考:http://www.cnblogs.com/bluebean/p/5299358.html

高光着色需要的纹理要带有alpha通道,用作上述shininess。

Lambertian反射模型:

(参考http://blog.csdn.net/u010922186/article/details/40680913)

最终表面 = 放射光(发光色) + 环境光(环境光色的若干倍) + 漫反射光(光源颜色*max(dot(法向量N, 指向光源向量L), 0)的若干倍) + 镜面反射(上述高光模型)

正切空间:是指Z轴定义为表面指向外面的坐标系,法线贴图就是在正切空间中应用的。

法线贴图着色器应用了法线贴图和无alpha的基本纹理。法线贴图着色器仅仅改动了Diffuse着色器中的法方向。因此和摄像机的移动和旋转无关。

法线贴图高光着色器:

非常简单,仅仅是高光着色和法线贴图着色的融合,即需要一个基本纹理(带有alpha通道表示高光贴图)以及法。

视差漫反射着色器:

需要的资源有一个基本的纹理(无alpha),一个法线贴图,一个高度纹理(在alpha通道带有视差深度)

高度有什么用?参考:http://blog.chinaunix.net/uid-26651460-id-3198307.html

视差高光贴图着色器:

需要的资源有一个基本的纹理(有alpha表示高光贴图),一个法线贴图,一个高度纹理(在alpha通道带有视差深度)

贴花着色器:

就是在原有基础上贴上一层纹理。

——小江村儿的文杰 zouw[email protected]

时间: 2024-11-07 10:58:40

Unity Shader入门教程(二)最基本的Diffuse和Normal样例的相关文章

Unity Shader入门教程(一)

参考文献:http://www.360doc.com/content/13/0923/15/12282510_316492286.shtml Unity Shader是着色器,将纹理.网格信息输入,得到材质的一段程序,具体是个什么东西,还需要亲自实践才知道.一个Unity大神推荐我:如果要学计算机图形编程(游戏编程的基础),可以先学习UnityShader,往后再学习OpenGL和DX.不说废话,依我的风格,都是直接看实例,笔者的教程偏向于傻瓜式的,应该适合入门. 前提:安装了Unity和VS,

Unity Shader入门教程(四)反射光斑的实现

本节内容介绍PhongModel(也就是上文说的反射光的计算模型),采用的计算方法是BlinPhong(也即是用视线方向V+光源方向L的和,与N做点积,随后幂化得到高光反射系数)下图采用了csdn博文http://blog.csdn.net/u010133610/article/details/52206654中的一张插图. 第1.1步:新建shader和material,正如我前面的教程所说的那样. 第1.2步:代码如下: ▼代码开始 Shader "Custom/Learn2" {

Unity Shader入门精要读书笔记(一)序章

本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数学基础. 第五章:利用简单的顶点/片元着色器来实现辅助技巧. 第六章:基本光照模型. 第七章:法线纹理.遮罩纹理等基础纹理. 第八章:透明度测试和透明度混合. 第九章:复杂光照实现. 第十章:高级纹理(立方体纹理等). 第十一章:纹理动画.顶点动画. 第十二章:屏幕特效. 第十三章:深度纹理. 第十四章:非真

Unity Shader入门精要学习笔记 - 第4章 学习 Shader 所需的数学基础

摘录自 冯乐乐的<Unity Shader入门精要> 笛卡尔坐标系 1)二维笛卡尔坐标系 在游戏制作中,我们使用的数学绝大部分都是计算位置.距离.角度等变量.而这些计算大部分都是在笛卡尔坐标系下进行的. 一个二维的笛卡尔坐标系包含了两个部分的信息: 一个特殊的位置,即原点,它是整个坐标系的中心. 两条过原点的互相垂直的矢量,即X轴和Y轴.这些坐标轴也被称为是该坐标的矢量. OpenGL 和 DirectX 使用了不同的二维笛卡尔坐标系.如下图所示: 2)三维笛卡尔坐标系 在三维笛卡尔坐标系中,

C语言快速入门教程(二)

C语言快速入门教程(二) C语言的基本语法 本节学习路线图: 引言: C语言,顾名思义就是一门语言,可以类比一下英语; 你要说出一个英语的句子需要:  单词  +  语法!  将单词按照一定的语法拼凑起来就成了一个英语句子了; C语言同样是这样,只不过单词可以理解为一些固定的知识点,而语法可以理解为算法(可以理解为解决问题的方法) 在这一节中我们就对固定知识点中的语言描述与数据存储进行解析! 1.C语言的基本元素 1.1  标识符 什么是标识符? 答:在C语言中,符号常量,变量,数组,函数等都需

DataVeryLite入门教程(二) Entity篇

DataVeryLite 是基于.net 4.0的数据库持久化ORM框架. 目前支持的数据库有Sqlserver,Mysql,Oracle,Db2,PostgreSql,Sqlite和Access. 最好先阅读DataVeryLite入门教程(一) 配置篇,然后再阅读本篇.如果你觉得麻烦也可以跳过. Entity是ORM中的核心对象之一,一个继承Entity的对象对应于数据库中的一个表. Entity提供丰富的API对表中的单条数据进行操作. 比如根据id或其他条件,加载,删除,插入,更新和部分

Spring Cloud 入门教程(二): 配置管理

使用Config Server,您可以在所有环境中管理应用程序的外部属性.客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用.随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切.服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具.很容易添加

jQuery 入门教程(二): 基本语法

学习jQuery之前需要你有下面几个方面的基本知识 HTML CSS JavaScript jQuery 的基本语法 $(selector).action() $ 符合定义这是一个jQuery语句 (selector) 用来选择某个HTML元素,其语法和CSS的selector语法一样. action() 定义操作该HTML元素的方法. 比如: $(this).hide() – 隐藏当前元素. $("p").hide() – 隐藏所以 <p> 元素. $(".te

Git的入门教程&lt;二&gt;

Git 的入门教程<二> 4> git远程仓库的使用 我们在使用git进行代码管理的时候,协同办公,需要一个24小时不间断的隐形同事,此时,如果在局域网内,则直接开一台局域网内的24小时开机运行的机器就可以,但是如果在homework的时候就需要这个24小时运行的机器拥有独立的外网IP,这样消耗就比较大,幸好,网上有一个github,提供给我们一个免费的仓库,让我们可以在同事之前推送代码,下面介绍github的使用. 4.1 github的使用 首先 登录github的官网: https