Shader入门学习手记

Shader程序的基本结构

在代码中学习吧,注释都写好了。

Shader "First Fantasy/Water/Water Diffuse"
{
	//定义着色器属性;
	Properties
	 {
	 	/*
	 		格式:_Name("Display Name", type) = defaultValue[{options}];
	 		{
	 			_Name - 属性的名字,变量名.
				Display Name - 这个字符串将显示在Unity的材质编辑器中作为Shader的使用者可读的内容
				type - 这个属性的类型,可能的type所表示的内容有以下几种:
					Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
					2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
					Rect - 一个非2阶数大小的贴图;
					Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样;
					Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等);
					Float - 任意一个浮点数;
					Vector - 一个四维数;
				defaultValue -定义了这个属性的默认值。
				Color - 以0~1定义的rgba颜色,比如(1,1,1,1);
				2D/Rect/Cube - 对于贴图来说,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者"white","black","gray","bump"中的一个
				Float,Range - 某个指定的浮点数
				Vector - 一个4维数,写为 (x,y,z,w)
				{option} - 它只对2D,Rect或者Cube贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{},当我们需要打开特定选项时可以把其写在这对花括号内。如果需要同时打开多个选项,可以使用空白分隔。可能的选择有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一个,这些都是OpenGL中TexGen的模式。
	 		}
	 	 */
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_MainTexColor ("Diffuse", Color) = (1,1,1,0.55)
		_MainTexMultiply ("Multiply", Range(0,5)) = 1
		_MainTexMoveSpeedU ("U Move Speed", Range(-6,6)) = 0.5
		_MainTexMoveSpeedV ("V Move Speed", Range(-6,6)) = 0.5
	}
	SubShader
	{
		//硬件将通过判定这些标签来决定什么时候调用该着色器。;
		/*
		"Queue"="xxx" --- 指定渲染顺序队列
		{
			Background (1000) - 最早被调用的渲染,用来渲染天空盒或者背景
			Geometry (2000)  - 这是默认值,用来渲染非透明物体(普通情况下,场景中的绝大多数物体应该是非透明的)
			AlphaTest (2450) - 用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑
			Transparent (3000) - 以从后往前的顺序渲染透明物体
			Overlay (4000) - 用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效)

			(PS:我们也可以指定自己的Queue值,写成类似这样:"Queue"="Transparent+100",表示一个在Transparent之后100的Queue上进行调用。
			通过调整Queue值,我们可以确保某些物体一定在另一些物体之前或者之后渲染,这个技巧有时候很有用处。)

		}
		"RenderType"="Opaque" -- 渲染非透明物体
		"RenderType" = "Transparent" -- 渲染含有透明效果的物体
		"IgnoreProjector"="True" -- 不被Projectors影响
		"ForceNoShadowCasting"="True" -- 从不产生阴影
		 */
		Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
		ZWrite Off
		Alphatest Greater 0
		Blend SrcAlpha OneMinusSrcAlpha 

		//Level of Detail的缩写;
		/*
			在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
			}
		 */
		LOD 200

		//一个开始标记,表明从这里开始是一段CG程序;
		CGPROGRAM

		/*
			声明了我们要写一个表面Shader,并指定了光照模型;
			格式:#pragma surface surfaceFunction lightModel [optionalparams]
				{
					surface - 声明的是一个表面着色器
					surfaceFunction - 着色器代码的方法的名字
					lightModel - 使用的光照模型。
				}
		 */
		#pragma surface surf Lambert

		//!!!对于这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字进行声明。;

		//sampler2D就是GLSL中的2D贴图的类型,相应的,还有sampler1D,sampler3D,samplerCube等等格式。;
		sampler2D _MainTex;
		fixed4 _MainTexColor;
		fixed _MainTexMultiply;
		fixed _MainTexMoveSpeedU;
		fixed _MainTexMoveSpeedV;

		struct Input
		{
			//声明了一个叫做uv_MainTex的包含两个浮点数的变量。;
			float2 uv_MainTex;
		};

		/*
			计算输出时Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出。
			第二个参数是一个可写的SurfaceOutput,SurfaceOutput是预定义的输出结构,我们的surf函数的目标就是根据输入把这个输出结构填上。
			SurfaceOutput结构体的定义如下:
			struct SurfaceOutput
			{
				    half3 Albedo;     //像素的颜色
				    half3 Normal;     //像素的法向值
				    half3 Emission;   //像素的发散颜色
				    half Specular;    //像素的镜面高光
				    half Gloss;       //像素的发光强度
				    half Alpha;       //像素的透明度
			};

			SurfaceOutput o - 这个就是经过表面计算函数surf处理后的输出

		 */
		void surf (Input IN, inout SurfaceOutput o)
		{
			fixed2 MainTexMoveScrolledUV = IN.uv_MainTex;

			fixed MainTexMoveU = _MainTexMoveSpeedU * _Time;
			fixed MainTexMoveV = _MainTexMoveSpeedV * _Time;

			MainTexMoveScrolledUV += fixed2(MainTexMoveU, MainTexMoveV);

			//tex2d函数,CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。;
			half4 c = tex2D (_MainTex, MainTexMoveScrolledUV);
			o.Albedo = c.rgb * _MainTexColor * _MainTexMultiply;
			o.Alpha = _MainTexColor.a;
		}
		ENDCG
	}
	FallBack "Diffuse"
}
时间: 2024-10-25 17:54:13

Shader入门学习手记的相关文章

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

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

Unity3D Shader入门指南(转)

猫都能学会的Unity3D Shader入门指南(一) Unity Shader教程 动机 自己使用Unity3D也有一段时间了,但是很多时候是流于表面,更多地是把这个引擎简单地用作脚本控制,而对更深入一些的层次几乎没有了解.虽然说Unity引擎设计的初衷就是创建简单的不需要开发者操心的谁都能用的3D引擎,但是只是肤浅的使用,可能是无法达到随心所欲的境地的,因此,这种状况必须改变!从哪里开始呢,貌似有句话叫做会写Shader的都是高手,于是,想大概看看从Shader开始能不能使自己到达的层次能再

Retrofit 入门学习

Retrofit 入门学习官方RetrofitAPI 官方的一个例子 public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } 这些注解都有一个参数 value,用来配置其路径,比如示例中的 users/{user}/repos, 我们还注意到在构造 Retrofit

JavaSE入门学习21:Java面向对象之接口(interface)(二)

一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.java源文件代码: public class Test{ public static void main(String[] args){ //实现接口Singer Singer s1 = new Student("Amy"); s1.sing(); s1.sleep(); s1.study

[Todo] Nodejs学习及Spider实验(包括php入门学习、React入门学习)

/Users/baidu/Documents/Data/Interview/Web-Server开发 深入浅出Node.js-f46c http://blog.csdn.net/u012273376/article/details/52736906 利用nodejs做爬虫 http://www.runoob.com/nodejs/nodejs-callback.html nodejs学习之路 http://www.runoob.com/php/php-tutorial.html php学习之路

JavaSE入门学习24:Java面向对象补充

一Java中的Object类 Object类是所有Java类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认 继承Object类. public class Person{ // } //等价于 public class Person extends Object{ // } Object类中的方法,适合所有子类. 1)toString()方法 在Object类中定义有public String toString()方法,其返回值是String类型,描述当前对

js入门学习

在HTML,CSS学习的最后,开始入门学习javascript, 首先就是去了解它的用途 作用:使web页面能够与用户交互,作为控制浏览器给网页增添活力的方法 定义:它是一种脚本语言,作用于浏览器.和java没有半毛钱关系,主要是当时Netscape公司为了增加影响力改了名,,(是不是感觉很无耻) ps:区分程序的一种方式:1.客户端程序(client-side),像javascript就是,我觉得HTML,CSS应该也是. 2.服务器端程序(server-side),java,perl,php

mybatis入门学习

一.mybaits简介 java程序中常用的数据库框架. 二.mybait入门学习 1.环境 创建一个java或者javaweb项目:我是创建了一个structs项目,helloworld 2.添加相应的jar包

angularjs入门学习【指令篇】

一.首先我们来了解下指令API 属性 含义 restrict 申明标识符在模版中作为元素,属性,类,注释或组合,如何使用 priority 设置模版中相对于其他标识符的执行顺序 Template 指定一个字符串式的内嵌模版,如果你指定了模版是一个URL,那么是不会使用的 tempateUrl 指定URL加载的模版,如果你已经指定了内嵌的模版字符串,那么它不会使用的 Replace 如果为真,替换当前元素,如果是假或未指定,拼接到当前元素 Transclude 移动一个标识符的原始字节带你到一个新