Unity Shader 入门(三)颜色和贴图Shader

颜色

一样先看代码:

Shader "Demo/Diffuse Color"{
    Properties{
        _Color("Color", Color) = (1,1,1,1)
    }
    SubShader{
        Tags{"RenderType"="Opaque"}
        LOD 200
        CGPROGRAM
            #pragma surface surf Lambert
            float4 _Color;
            struct Input{
                float4 uv_Tex;
            };
            void surf(Input IN, inout SurfaceOutput o){
                o.Albedo = _Color.xyz;
                o.Alpha = _Color.w;
            }
        ENDCG
    }
    FallBack "Diffuse"
}

前一篇文章介绍过的不再重复,还是逐行说明:
_Color("Color", Color) = (0,0,0)
属性定义的一个关于Color(颜色)的属性,每条属性的定义语法如下:
_Name("Display Name", type) = defaultvalue{options}
_Name 属性的名字,代码调用的属性名。
Display Name 显示在unity的材质编辑器中作为可读的属性名(一般规范为可读属性名前加下划线即代码调用参数名)
type表示属性类型,可能表示的内容有以下几种:
1.Color 一种颜色,由RGBA(红绿蓝和透明度)四个量表示。
2.2D 一张2的阶数大小的贴图,在被采样后转为基于模型UV的每个像素的颜色,最终被显示出来。
3.Rect 一张非2的阶数大小的贴图。
4.Cube Cube Map Texture(立方体贴图),6张有联系的2D贴图组合,主要用于制作反射效果(天空盒和动态反射),也会被转换为对应点采样。
5.Range(min, max) 介于最小值和最大值的浮点数。
6.Float 浮点数
7.Vector 四维数
defaultvalue定义默认属性值,{options}只对2D,Rect,Cube贴图有关,输入时如果是贴图至少后边要跟一对什么都不含的{},需要打开特定选项时可以填入{}中,可能的选择有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一个,这些都是OpenGL中TexGen(纹理坐标生成)的模式,以后再研究。

Tags{"RenderType"="Opaque"}
该标签向系统声明,渲染非透明物体时调用,相反的是Tags{"RenderType"="Transparent"},表示渲染透明物体时调用。
常用的标签还有如下:
1."IgnoreProjector"="True",不被Projectors(投影)影响
2."ForceNoShadowCasting"="True",从不产生阴影
3."Queue"="xxx",指定渲染顺序队列。

Queue指定了物体的渲染顺序,预定义的Queue有:
1.Background - 最早被调用的渲染,用来渲染天空盒或者背景
2.Geometry - 这是默认值,用来渲染非透明物体(普通情况下,场景中的绝大多数物体应该是非透明的)
3.AlphaTest - 用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑
4.Transparent - 以从后往前的顺序渲染透明物体
5.Overlay - 用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效)
这些预定义的值本质上是一组整数,Background = 1000,Geometry = 2000,AlphaTest = 2450,Transparent = 3000,Overlay = 4000。在我们实际设置Queue值时,不仅能使用上面的几个预定义值,我们也可以指定自己的Queue值,写成类似这样:"Queue"="Transparent+100",表示一个在Transparent之后100的Queue上进行调用。通过调整Queue值,我们可以确保某些物体一定在另一些物体之前或者之后渲染,这个技巧有时候很有用处。

LOD 200
LOD是Level of Detail的缩写,在这里我们指定其为200(Unity的内建Diffuse着色器的设定值)。在Unity的Quality Settings中我们可以设定允许的最大LOD,当设定的LOD小于SubShader所指定的LOD时,这个SubShader将不可用。Unity内建Shader定义了一组LOD的数值,我们在实现自己的Shader的时候可以将其作为参考来设定自己的LOD数值,这样在之后调整根据设备图形性能来调整画质时可以进行比较精确的控制。
VertexLit及其系列 = 100
Decal, Reflective VertexLit = 150
Diffuse = 200
Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
Bumped, Specular = 300
Bumped Specular = 400
Parallax = 500
Parallax Specular = 600

float4 _Color;
对Properties里的_Color再次声明。因为shader是由两个相对独立的块组成的,外层的属性声明,回滚等等是Unity可以直接使用和编译的ShaderLab;而对于CGPROGRAM...ENDCG 中的CG程序,要想访问在Properties中定义的变量,必须使用和之前变量相同的名字进行声明。声明完毕后,surf方法中可以直接使用Properties中定义的_Color参数。

void surf(Input IN, inout SurfaceOutput o) {
    o.Albedo = _Color.xyz;
    o.Alpha = _Color.w;
}

下面解析Input和SurfaceOutput的结构:

struct Input {
    float2 uv_MainTex; //纹理坐标
    float3 viewDir; //入视角(计算视差、边缘光照等效果)
    float4 screenPos; //裁剪空间位置(为了获得反射效果,需要包含屏幕坐标)
    float3 worldPos; //世界空间位置
    float3 worldRefl; //世界中的反射向量。如果表面着色写入o.Normal, 将包含世界反射向量。
    float3 worldNormal; //世界中的法线向量。如果表面着色器写入法线(o.Normal)参数,将包含这个参数。
} ;

//默认的几种输出结构,可以自定义
struct SurfaceOutput {
    fixed3 Albedo; // 像素颜色
    fixed3 Normal; // 像素法向量值
    fixed3 Emission; // 像素自发光颜色
    half Specular; // 像素镜面高光强度,范围是0-1
    fixed Gloss; // 镜面光滑程度
    fixed Alpha; // 像素透明度
};
struct SurfaceOutputStandard {
    fixed3 Albedo;
    fixed3 Normal;
    half3 Emission;
    half Metallic;      // 金属光泽度,0=非金属, 1=金属
    half Smoothness;    //光滑度 0=粗糙, 1=光滑
    half Occlusion;     // 遮挡(默认1)
    fixed Alpha;
};
struct SurfaceOutputStandardSpecular {
    fixed3 Albedo;
    fixed3 Specular;    // 镜面反射颜色
    fixed3 Normal;
    half3 Emission;
    half Smoothness;
    half Occlusion;
    fixed Alpha;
};

看完上边的结构定义说明,应该明白surf中的方法所表达的意义了吧。

效果图

图3-1

贴图

上代码:

Shader "Demo/Diffuse Texture"{
    Properties{
        _MainTex("MainTex",2D) = ""{}
    }
    SubShader{
        Tags{"RenderType"="Opaque"}
        LOD 200
        CGPROGRAM
            #pragma surface surf Lambert
            sampler2D _MainTex;
            struct Input{
                float2 uv_MainTex;
            };
            void surf (Input IN, inout SurfaceOutput o){
                half4 c = tex2D(_MainTex, IN.uv_MainTex);
                o.Albedo = c.rgb;
                o.Alpha = c.a;
            }
        ENDCG
    }
    FallBack "Diffuse"
}

sampler2D _MainTex;
sampler2D是一个数据容器接口。简单地理解,sampler2D就是GLSL中的2D贴图的类型,相应的,还有sampler1D,sampler3D,samplerCube等等格式。
half4 c = tex2D(_MainTex, IN.uv_MainTex);
tex2d函数是CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。这里对_MainTex在输入点上进行了采样,将其颜色的RGBA值赋予了输出。于是,着色器就明白了应当怎样工作:即找到贴图上对应的uv点,直接使用颜色信息来进行着色。half和float与double类似,表示浮点数,只是精度不一样。这里half指的是半精度浮点数,精度最低,运算性能相对比高精度浮点数高一些,因此被大量使用。
注:可能会有人发现照着例子调整透明度,并没有什么效果。这就对了,因为没有开启Alpha混合,最简单的实现是在编译定义后加alpha(要小写!),即:#pragma surface surf Lambert alpha,但其实最后渲染效果还是会有问题,例如被不透明物体遮挡(渲染方式和顺序导致),过于透明效果的实现以后文章说明。

效果图:

图3-2
图3-2
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 动机自己使用Unity3D也有一段时间了,但是很多时候是流于表面,更多地是把这个引擎简单地用作脚本控制,而对更深入...
    JumboWu阅读 2,109评论 0 24
  • 转载注明出处:点击打开链接 Shader(着色器)是一段能够针对3D对象进行操作、并被GPU所执行的程序。Shad...
    游戏开发小Y阅读 3,323评论 0 4
  • <转>我也忘了转自哪里,抱歉,感谢原作者 什么是Shader Shader(着色器)是一段能够针对3D对象进行操作...
    星易乾川阅读 5,575评论 1 16
  • 文章转自:https://onevcat.com/2013/07/shader-tutorial-1/ Shade...
    Lamzz阅读 3,525评论 1 7
  • “本文参加#乡忆.乡思.乡情.乡恋#活动,本人承诺,文章内容为原创,且未在其它平台发表过 ” 01. “霜打残...
    一诺先生阅读 306评论 0 0