Unity Shader着色器学习(一)

Shader介绍

一个模型渲染所需的组成

1. Mesh Filter
存储一个Mesh(网格,模型的网格,就是模型由哪些三角面组成,组成一个什么样子的模型,三角面的一些顶点信息)
2. Mesh Renderer
根据Mesh的顶点信息,渲染一个模型的外观,就是样子,按照Mesh给它皮肤,给它颜色,通过Material(材质)控制模型渲染的样子
3. Material
渲染的样子,包括贴图和Shader,贴图可以没有,可以是一个单纯的颜色
4. Shader

相关资料推荐

书籍
unity shader 入门精要(乐乐程序猿)
unity 3d shaderlab开发实战详解(第二版)
unity 5.x shaders and effects cookbook(中文版 unity着色器和屏幕特效开发秘籍)

CG语言教程官网
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_frontmatter.html

一些网站
www.shadertoy.com
http://blog.csdn.net/poem_qianmo?viewmode=contents

数学函数在线演示
http://zh.numberempire.com/graphingcalculator.php

什么是光照模型

光照模型就是一个公式,使用这个公式来计算在某个点的光照效果

标准光照模型
在标准光照模型里面,我们把进入摄像机的光分为下面四个部分
1. 自发光(emissive)
这个部分用于描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。需要注意的是,如果没有使用全局光照(global illumination)技术,这些自发光的表面并不会真的照亮周围的物体,而是它本身看起来更亮了而已。
2. 高光反射(specular)
这个部分用于描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。(高光是指光源照射到物体反射到人的眼镜里时,物体上最亮的那个点就是高光)
3. 漫反射(diffuse)
这个部分用于描述当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。(漫反射是投射在粗糙表面上的光向各个方向反射的现象)
4. 环境光(ambient)
它用于描述其他所有的间接光照

逐顶点漫反射计算

漫反射光照模型

Diffuse = 直射光颜色 * max(0, cosθ)
注:θ为光和法线的夹角

cosθ怎么算
当矢量a与b的模都为1的时候,a与b的点乘结果即为cosθ,所以如果我们可以通过光的单位矢量与法线的单位矢量求得cosθ

定义LightMode
只有定义了正确的LightMode才能得到一些Unity的内置光照变量

Pass
{
	Tags{ "LightMode" = "ForwardBase"}
}

包含Unity内置文件
包含unity的内置的Lighting.cginc文件,才可以使用unity内置的变量

shader	#include "Lighting.cginc"


逐顶点光照(加入环境光的影响)

Shader "Shader Learning Siki/Lighting/Diffuse PerVertex"
{
	Properties
	{
		_Diffuse("Diffuse Color", Color) = (1, 1, 1, 1)
	}
	SubShader
	{
		Pass
		{
			Tags{ "LightMode" = "ForwardBase"}
			
			CGPROGRAM
			
			//用于取得第一个直射光的颜色 _LightColor0
			//用于取得第一个直射光的位置 _WorldSpaceLightPos0
			#include "Lighting.cginc" 
			#pragma vertex vert
			#pragma fragment frag
			
			fixed4 _Diffuse;
			
			struct a2v
			{
				float4 vertex : POSITION;  //告诉Unity把模型空间下的顶点坐标填充给vertex
				float3 normal : NORMAL;
			};
			
			struct v2f
			{
				float4 position : SV_POSITION;
				fixed3 color : COLOR;
			};
			
			v2f vert(a2v v)
			{
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;  //获取环境光
				
				fixed3 normalDir = normalize( mul(v.normal, (float3x3)_World2Object));
				
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  //对于每个顶点来说 光源的位置就是光源的方向,因为光是平行光
				fixed3 diffuse = _LightColor0.rgb * max(dot( normalDir, lightDir), 0) * _Diffuse.rgb;  //取得漫反射的颜色
				f.color = diffuse + ambient;  //漫反射光部分和环境光两种光叠加,得到最终的光照结果
			
				return f;
			}
			
			fixed4 frag(v2f f) : SV_Target
			{
				return fixed(f.color, 1.0);
			}
			
			ENDCG
		}
	}
	
	Fallback "Diffuse"
}

注:
环境光在这里设置
在这里插入图片描述

逐像素漫反射计算

逐像素光照可以得到更加平滑的光照效果
逐像素漫反射计算只需要将 在逐顶点漫反射计算中的部分计算挪到片元着色器中计算即可。

Shader "Shader Learning Siki/Lighting/Diffuse PerFragment"
{
	Properties
	{
		_Diffuse("Diffuse Color", Color) = (1, 1, 1, 1)
	}
	SubShader
	{
		Pass
		{
			Tags{ "LightMode" = "ForwardBase"}
			
			CGPROGRAM
			
			//用于取得第一个直射光的颜色 _LightColor0
			//用于取得第一个直射光的位置 _WorldSpaceLightPos0
			#include "Lighting.cginc" 
			#pragma vertex vert
			#pragma fragment frag
			
			fixed4 _Diffuse;
			
			struct a2v
			{
				float4 vertex : POSITION;  //告诉Unity把模型空间下的顶点坐标填充给vertex
				float3 normal : NORMAL;
			};
			
			struct v2f
			{
				float4 position : SV_POSITION;
				fixed3 worldNormalDir : COLOR0;
			};
			
			v2f vert(a2v v)
			{
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);
				f.worldNormalDir = mul(v.normal, (float3x3)_World2Object);
			
				return f;
			}
			
			fixed4 frag(v2f f) : SV_Target
			{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;  //获取环境光
				
				fixed3 normalDir = normalize(f.worldNormalDir);
				
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  //对于每个顶点来说 光源的位置就是光源的方向,因为光是平行光
				fixed3 diffuse = _LightColor0.rgb * max(dot( normalDir, lightDir), 0) * _Diffuse.rgb;  //取得漫反射的颜色
				fixed3 tempColor = diffuse + ambient;  //漫反射光部分和环境光两种光叠加,得到最终的光照结果
			
				return fixed(tempColor , 1.0);
			}
			
			ENDCG
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的第一个问题是关于Unity Shader学习笔记,具体是在表面着色器中控制顶点变换。那么我可以回答您的问题。 在Unity中,表面着色器是一种用于控制物体表面外观的程序。它们可以控制颜色、纹理和光照等方面。而在表面着色器中,我们可以使用顶点变换来控制物体表面的外观。 顶点变换是一个将物体的顶点坐标从局部空间转换为世界空间或者相机空间的过程。在表面着色器中,我们可以通过在CG程序中编写代码来实现顶点变换。以下是一个简单的例子: ```CG // 定义变换矩阵 float4x4 worldMatrix; float4x4 viewMatrix; float4x4 projectionMatrix; // 定义输入结构体 struct appdata { float4 vertex : POSITION; }; // 定义输出结构体 struct v2f { float4 vertex : SV_POSITION; }; // 顶点变换函数 v2f vert (appdata v) { v2f o; o.vertex = mul(mul(mul(v.vertex, worldMatrix), viewMatrix), projectionMatrix); return o; } ``` 在这个例子中,我们定义了三个变换矩阵:世界矩阵、视图矩阵和投影矩阵。然后定义了一个输入结构体appdata,其中包含了顶点的位置信息。输出结构体v2f则只包含了顶点的位置信息,用于传递给像素着色器。 在vert函数中,我们首先将顶点从局部空间转换到世界空间,然后再从世界空间转换到相机空间,最后再从相机空间转换到屏幕空间。这个过程中使用了mul函数来进行矩阵乘法运算。 通过这样的方式,我们可以在表面着色器中控制顶点变换,从而实现对物体表面外观的控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值