|
最近发现了一个很好的Unity入门Shader教程,作者貌似Twitter折腾的很多,是个逗逼。管他呢,反正这教程我认为很适合我这种图形学白痴,干脆转过来自己看看,原版在这,传送门: Ronja的Shader入门教程
言归正传,先从HLSL 基础开始。
Summary 就不翻译了。。
Unity Shaders are written in a custom environment called “Shaderlab”. With it we can customize a lot about how the material that will use our shader will be used internally. Inside of the shaderlab file we will also declare most of the logic of the shader in HLSL. Because Shaderlab is just a way to set some parameters in the material it’s pretty easy to learn how to set which parameter when we need it. HLSL is a bit more complex though so I’ll explain some of it’s basics here. Even though I try to explain everything in this tutorials, I sadly can’t explain every basic programming principle so I recommend you learn a different programming language before coming back to shaders.
作者说他不会解释每一条代码编写的规范。。都能理解。。
Because this is the first tutorial in this series I tried to make it as simple as possible, if I failed to do that and assumed that you know things about shaders that you don’t, please contact me. In that case I’ll fix the tutorial to be more approachable. If the information in this tutorial is clear, but you have difficulties grasping the concepts because it’s all a bit theoretical, feel free to jump to the next tutorials where we will use the concepts in praxis which might make things clearer.
很用心的作者,要不也坚持更新了一年多到现在吧。。。
Variables 变量
HLSL 是静态的语言, 这意味着每个变量都有一个特定的数据类型,必须显式声明并且不能更改。我将在这里快速介绍一些类型,如果您需要更多信息,可以查看Unity文档的这个页面: https://docs.unity3d.com/Manual/SL-DataTypesAndPrecision.html
Scalar Types 标量类型
最简单的变量类型是标量,它们只有一个数值。HLSL中有多种类型的标量数。选择较低的精度值可以提高着色器的性能,但现代显卡速度很快,因此差异很小。float类型里,用half或者fixed一般就够了,所以请你有自己的判断,别想太多。
int integer = 3; //数字没有小数部分,省
fixed fixed_point = 0.5; //12位点定数,-2 到2
half low_precision = 3.14; //低精度浮点
float high_precision = 14.321; //高精度浮点Vector Types 向量类型
使用vector,我们可以表示在一个变量中有多个值的颜色、位置和方向。
要在HLSL中声明它们,我们只需在类型的末尾编写所需的维度数量,因此我们得到了诸如float2、int3、half4等类型。
(请注意,这里的最大值是vector4,如果需要更多,必须使用数组)可以通过x、y、z和w或rgba访问向量的不同分量。第一组用于表示向量的维度,第二组用于表示颜色的红、绿、蓝和alpha。
fixed4 color = fixed4(1, 0.67, 0.73, 1);
float3 position = float3(1, 1, 0);
float2 textureCoordinates = float2(0.5, 0.5);
position.xy = position.yx; //xy与yx的互换Matrix Types 矩阵类型
矩阵类型,通常用来旋转、移动和缩放向量,以特定的方式将向量与矩阵相乘。
可以通过在标量类型后面写入[Dimension 1]x[Dimension 2]来创建矩阵。
在3D图形中,我们需要一个3x3矩阵来旋转和缩放一个向量,或者需要一个4x4矩阵来平移。
float4x4 transformMatrix3d;
float2x2 rotationMatrix2d = {
0, 1,
-1, 0
};
//当做矩阵乘法时,我们必须使用4d向量,第四个组件只是用来通过矩阵乘法移动向量
float4 position;
//我们旋转、缩放和平移一个位置,然后将其与向量相乘。
position = transformMatrix3d * position;Samplers 采样器
用于读取纹理的采样器。从采样器读取时,纹理的坐标从[0,0]到[1,1],[0,0]是纹理的左下角,[1,1]是纹理的右上角。
sampler2d texture; //教程将主要使用2D纹理,但也可以将3D采样器提供给Shader。
//我们将主要通过tex2d函数从采样器读取数据。
//将采样的位置coordinates作为第二个参。
float4 color = tex2D(texture, coordinates);Structs 结构体
结构体,也就是可以容纳其他几种数据类型的自定义数据类型。我们可以用结构表示灯光、输入数据和其他复杂数据。要使用结构,我们首先必须定义它,然后才能在其他地方使用它。
//定义InputData结构
struct InputData{
float4 position;
fixed4 color;
half4 normal;
};
//创建实例和使用
InputData data;
data.position = float4(1, 0, 0, 1);Functions 函数
虽然我们可以在函数外部定义变量以向Shader提供信息,但我们只能在函数中运行逻辑运算。一些函数将被自动调用,并将返回值,这些值将操纵我们处理顶点或绘制颜色的方式。但是我们也可以自己调用函数并使用它们返回的值。我们将函数返回的变量类型写在名称前面,返回类型也可以是void,这意味着函数不返回值。在函数名后面放入参数,这些参数是函数接收的数据。在函数中,我们返回该值,然后将该值赋给调用此函数的函数。
float add(float arg1, float arg2){
float sum = arg1 + arg2;
return sum;
}
float function(){
return add(3.5, 0.7);
}Include “”
写过C/C++ 的不用介绍了,类型动态语言的import “”
#include “IncludeFile.cginc”
void function(){
functionDeclaredInIncludeFile(3, variableInIncludeFile);
}
作者Ronja本人信息:
You can also find me on twitter at@totallyRonja. If you liked my tutorial and want to support me you can do that on Patreon (patreon.com/RonjaTutorials) or Ko-Fi (ko-fi.com/RonjaTutorials). |
|