今天讲解下最基本的如何通过一个shader来渲染一个物体,教程结束的时候将会看到一个纯色的立方体。如果代码部分有不清楚的地方,建议看一下上一篇讲解HLSL的教程。
result.pngShaderlab 的结构
在开始写shader之前,我们先要搞清楚shaderlab的结构。Shader文件第一行 以Shader开头,后面跟着的是shader文件的路径和名字,后面会在Inspector中选择shader的时候显示出来。接下来是Subshader.。一个shader可以包含多个Subshader,可以针对不同的情况使用不同的Subshader。
Shader "Tutorial/02_Simple"{
Subshader{
}
}
在subshader里面是 Pass, 同样可以有多个。当Subshader被渲染的时候,将会依次渲染里面的每个pass,这里我们只用了一个pass。在Pass里面我们通过Tag告诉unity如果去处理当前的Pass。比如下面的,我们希望物体被渲染为不透明,并且和其他不透明物体一起渲染。
Shader "Tutorial/02_Simple"{
Subshader{
Pass{
Tags{
"RenderType"="Opaque"
"Queue"="Geometry"
}
}
}
}
HLSL Code
上面的都准备好之后,我们可以开始写HLSL代码部分了。我们来看一下Shader中的数据流程是怎样的。首先 3D模型的数据信息给到vertex shader, 变换为相对于屏幕的一些信息。然后通过光栅化,把顶点及三角面转化为像素信息给到fragment shader,fragment shader通过一系列的差值及其他操作,讲最终颜色输出到屏幕上。
Shader Pipeline通过CGPROGRAM 开始 和 ENDCG 结束 告诉unity我们使用HLSL来书写代码。为了使用unity提供的一些工具函数,我们引入 “UnityCG.cginc“ 文件.
Shader "Tutorial/02_Simple"{
Subshader{
Pass{
Tags{
"RenderType"="Opaque"
"Queue"="Geometry"
}
CGPROGRAM
#include "unityCG.cginc"
ENDCG
}
}
}
通过一个结构体来引入输入数据,一般命名为appdata ,这里我们只获取物体的顶点位置,通过POSITION属性来标明为物体的局部空间位置信息。
struct appdata{
float4 vertex : POSITION;
}
我们再声明一个结构体,这个结构体是vertex shader的输出值。现在我们只需要顶点的屏幕坐标,我们通过SV_POSITION属性来标明。
struct v2f{
float4 position : SV_POSITION;
}
接下来是vertex shader,它接受appdata中的物体信息,输出v2f的结构体给到fragment shader。首先我们生成一个v2f的新实例,然后把顶点的屏幕坐标赋值给它。UnityObjectToClipPos函数定义在UnityCG.cginc 文件中,将顶点从局部空间坐标变化到屏幕坐标,我们直接使用就行了。
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
return o;
}
最后我们来写一下fragment shader。这里我们仅仅返回一个红色,在后续的教程里将会对它做更多其他的操作。我们将函数标明为SV_TARGET,这样unity就知道函数的返回值将被渲染到屏幕上。
fixed4 frag(v2f i) : SV_TARGET{
return fixed4(0.5, 0, 0, 1);
}
完成上面这些之后,我们还需要告诉unity,vertex shader对应的函数 以及 fragment shader 对应的函数。通过 #pragma vertex 函数名
#pragma fragment 函数名
来实现。
Shader "Tutorial/01_Basic"{
SubShader{
Tags{
"RenderType"="Opaque"
"Queue"="Geometry"
}
Pass{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
struct appdata{
float4 vertex : POSITION;
};
struct v2f{
float4 position : SV_POSITION;
};
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_TARGET{
return fixed4(0.5, 0, 0, 1);
}
ENDCG
}
}
}
现在我们可以把新创建的这个Shader赋给一个材质,将会看到立方体显示fragment shader返回的颜色。
Apply
from:https://www.ronja-tutorials.com/2018/03/21/simple-color.html
Unity技术交流 微信公众号 UnityAsk,QQ群:891920228
网友评论