打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【浅墨Unity3D Shader编程】之六 暗黑城堡篇: 表面着色器(Surface Shader...

 

 



 

 

四、一些本次写Shader用到的CG函数讲解

 




本次Shader书写用到了四个CG着色器编程语言中的函数——UnpackNormal、saturate、dot、tex2D。下面将分别对其进行讲解。




4.1UnpackNormal( )函数


UnpackNormal接受一个fixed4的输入,并将其转换为所对应的法线值(fixed3),并将其赋给输出的Normal,就可以参与到光线运算中完成接下来的渲染工作了。

一个调用示例:

 

o.Normal = UnpackNormal (tex2D (_BumpMap,IN.uv_BumpMap));



4.2saturate( )函数


saturate的字面解释是浸湿,浸透。其作用其实也就是将取值转化为[0,1]之内的一个值。

 

其可选的原型如下:

 

float saturate(float x);float1 saturate(float1 x);float2 saturate(float2 x);float3 saturate(float3 x);float4 saturate(float4 x);half saturate(half x);half1 saturate(half1 x);half2 saturate(half2 x);half3 saturate(half3 x);half4 saturate(half4 x);fixed saturate(fixed x);fixed1 saturate(fixed1 x);fixed2 saturate(fixed2 x);fixed3 saturate(fixed3 x);fixed4 saturate(fixed4 x);


其唯一的一个参数x表示矢量或者标量的饱和值(Vector or scalar to saturate.),也就是将这个x转化为[0,1]之内的值。

 

其返回值:

  • 如果x取值小于0,则返回值为0.
  • 如果x取值大于1,则返回值为1.
  • 若x在0到1之间,则直接返回x的值。

 

其代码实现大致如下:


float saturate(float x){ return max(0,min(1, x));}


 

一个调用示例:

 

half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));


 

 

4.3 dot( )函数


dot函数顾名思义,是高等数学中的点积操作,用于返回两个向量的标量积。

 

可选原型如下:

 

float dot(float a, float b);float dot(float1 a, float1 b);float dot(float2 a, float2 b);float dot(float3 a, float3 b);float dot(float4 a, float4 b);half dot(half a, half b);half dot(half1 a, half1 b);half dot(half2 a, half2 b);half dot(half3 a, half3 b);half dot(half4 a, half4 b);fixed dot(fixed a, fixed b);fixed dot(fixed1 a, fixed1 b);fixed dot(fixed2 a, fixed2 b);fixed dot(fixed3 a, fixed3 b);fixed dot(fixed4 a, fixed4 b);


 

其代码实现大致是这样的:

 

float dot(float4 a, float4 b){ return a.x*b.x +a.y*b.y + a.z*b.z + a.w*b.w;}

 

一个调用示例:


float answer= dot (normalize(IN.viewDir),o.Normal);




 

4.4 tex2D( )函数

 

让我们看一看CG中用得比较多的用于2D纹理采样的tex2D函数的用法。其备选的原型也是非常之多:

 

float4 tex2D(sampler2D samp, float2 s)float4 tex2D(sampler2D samp, float2 s, inttexelOff)float4 tex2D(sampler2D samp, float3 s)float4 tex2D(sampler2D samp, float3 s, inttexelOff)float4 tex2D(sampler2D samp, float2 s,float2 dx, float2 dy)float4 tex2D(sampler2D samp, float2 s,float2 dx, float2 dy, int texelOff)float4 tex2D(sampler2D samp, float3 s,float2 dx, float2 dy)float4 tex2D(sampler2D samp, float3 s,float2 dx, float2 dy, int texelOff)int4 tex2D(isampler2D samp, float2 s)int4 tex2D(isampler2D samp, float2 s, inttexelOff)int4 tex2D(isampler2D samp, float2 s,float2 dx, float2 dy)int4 tex2D(isampler2D samp, float2 s,float2 dx, float2 dy, int texelOff)unsigned int4 tex2D(usampler2D samp, float2s)unsigned int4 tex2D(usampler2D samp, float2s, int texelOff)unsigned int4 tex2D(usampler2D samp, float2s, float2 dx, float2 dy)unsigned int4 tex2D(usampler2D samp, float2s, float2 dx, float2 dy,int texelOff)


 

参数简介:

samp-需要查找的采样对象,也就是填个纹理对象在这里。

s-需进行查找的纹理坐标。

dx-预计算的沿X轴方向的导数。

dy-预计算的沿Y轴方向的导数。

texelOff-添加给最终纹理的偏移量


而其返回值,自然是查找到的纹理。

 

最后,看一个综合了本次讲解的四个函数(UnpackNormal、saturate、tex2D、dot)的Surface Shader中surf函数的示例:

 

//【2】表面着色函数的编写void surf (Input IN, inout SurfaceOutput o){ //从主纹理获取rgb颜色值 o.Albedo= tex2D (_MainTex, IN.uv_MainTex).rgb; //从凹凸纹理获取法线值 o.Normal= UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); //从_RimColor参数获取自发光颜色 halfrim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); o.Emission= _RimColor.rgb * pow (rim, _RimPower);}


 

 

 

 

 

 

 

五、写Shdaer实战

 

 

 


上面都是些概念,下面我们将进行一些实战的Shader书写,将学到的这些概念用到实际当中去。

本次我们将讲解9个表面SurfaceShader的写法,从最基本的Surface Shader,循序渐进,一点一点加功能,到最后的稍微有点复杂的“凹凸纹理+颜色可调+边缘光照+细节纹理“表面Shader的写法。本期的全部Shader的合照如下:


 

在材质界面菜单中的显示:



OK,下面开始讲解,从最基本的开始。

 




 

1.最基本的Surface Shader



先看一个使用内建光照模式的最基本的Surface Shader应该怎么写:

Shader '浅墨Shader编程/Volume6/24.最基本的SurfaceShader'{ //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式 #pragma surface surf Lambert //【2】输入结构 struct Input { //四元素的颜色值(RGBA) float4 color : COLOR; }; //【3】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //反射率 o.Albedo = float3(0.5,0.8,0.3);//(0.5,0.8,0.3)分别对应于RGB分量 //而o.Albedo = 0.6;等效于写o.Albedo = float3(0.6,0.6,0.6); } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}



可以发现,一个最基本的Surface Shader,至少需要有光照模式的声明、输入结构和表面着色函数的编写这三部分。

 


另外,主要注意其中的surf函数的写法,就是把上文讲到的Surface Output结构体中需要用到的成员变量拿来赋值:

 

//【2】表面着色函数的编写void surf (Input IN, inout SurfaceOutput o){ //反射率 o.Albedo= float3(0.5,0.8,0.3);//(0.5,0.8,0.3)分别对应于RGB分量 //而o.Albedo = 0.6;等效于写o.Albedo =float3(0.6,0.6,0.6);}


注释中已经写得很明白,且之前也已经讲过,o.Albedo = 0.6;等效于写o.Albedo = float3(0.6,0.6,0.6);

来个举一反三,则o.Albedo =1;等效于写o.Albedo= float3(1,1,1);

 

我们将此Shader编译后赋给材质,得到如下效果:

 

 

 

而在场景中的实测效果为:

 

 

 

 

 

 

 

2.颜色可调

 


在最基本的Surface Shader的基础上,加上一点代码,就成了这里的可调颜色的Surface Shader:

 

Shader '浅墨Shader编程/Volume6/25.颜色可调的SurfaceShader'{ //--------------------------------【属性】--------------------------------------- Properties { _Color ('【主颜色】Main Color', Color) = (0.1,0.3,0.9,1) } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType'='Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式 #pragma surface surf Lambert //变量声明 float4 _Color; //【2】输入结构 struct Input { //四元素的颜色值(RGBA) float4 color : COLOR; }; //【3】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //反射率 o.Albedo = _Color.rgb; //透明值 o.Alpha = _Color.a; } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 FallBack 'Diffuse'}

 

我们将此Shader编译后赋给材质,得到如下效果,和之前的固定功能Shader一样,可以自由调节颜色:


 

其在场景中的实测效果为:



 

 

 

 

 

 

3.基本纹理载入




再来看看如何实现一个基本的纹理载入Surface Shader:

Shader '浅墨Shader编程/Volume6/26.基本纹理载入'{ //--------------------------------【属性】---------------------------------------- Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式 #pragma surface surf Lambert //【2】输入结构 struct Input { //纹理的uv值 float2 uv_MainTex; }; //变量声明 sampler2D _MainTex; //【3】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //从纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}


 

我们将此Shader编译后赋给材质,得到如下效果:



场景中的实测效果图为:


 

 

 

 

 

 

4.凹凸纹理载入

 



让我们慢慢添加特性,使得到的Surface Shader的效果与功能越来越强大。接着来看看Surface Shader的凹凸纹理如何实现:

Shader '浅墨Shader编程/Volume6/27.凹凸纹理载入'{ //--------------------------------【属性】---------------------------------------- Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} _BumpMap ('【凹凸纹理】Bumpmap', 2D) = 'bump' {} } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式 #pragma surface surf Lambert //【2】输入结构 struct Input { //主纹理的uv值 float2 uv_MainTex; //凹凸纹理的uv值 float2 uv_BumpMap; }; //变量声明 sampler2D _MainTex;//主纹理 sampler2D _BumpMap;//凹凸纹理 //【3】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //从主纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; //从凹凸纹理获取法线值 o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}


我们将此Shader编译后赋给材质,得到如下效果:


 

 

场景中的实测效果图为:




 

 

 

 

 

5.纹理载入+颜色可调


接着看一看纹理如何通过一个finalcolor关键字自定义函数,来达到调色的目的:

 

Shader '浅墨Shader编程/Volume6/28.纹理+颜色修改'{ //--------------------------------【属性】---------------------------------------- Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} _ColorTint ('【色泽】Tint', Color) = (0.6, 0.3, 0.6, 0.3) } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式+自定义颜色函数 #pragma surface surf Lambert finalcolor:setcolor //【2】输入结构 struct Input { //纹理的uv值 float2 uv_MainTex; }; //变量声明 fixed4 _ColorTint; sampler2D _MainTex; //【3】自定义颜色函数setcolor的编写 void setcolor (Input IN, SurfaceOutput o, inout fixed4 color) { //将自选的颜色值乘给color color *= _ColorTint; } //【4】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //从主纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}


我们将此Shader编译后赋给材质,得到如下效果:


 

调些颜色玩一玩:







场景中的实测效果图为:


 

 

 


 

6. 凹凸纹理+边缘光照

 

 

在之前凹凸纹理的基础上让我们加上喜闻乐见的边缘光照:

 

Shader '浅墨Shader编程/Volume6/29.凹凸纹理+边缘光照'{ //--------------------------------【属性】---------------------------------------- Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} _BumpMap ('【凹凸纹理】Bumpmap', 2D) = 'bump' {} _RimColor ('【边缘颜色】Rim Color', Color) = (0.26,0.19,0.16,0.0) _RimPower ('【边缘颜色强度】Rim Power', Range(0.5,8.0)) = 3.0 } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式+自定义颜色函数 #pragma surface surf Lambert //【2】输入结构 struct Input { //主纹理的uv值 float2 uv_MainTex; //凹凸纹理的uv值 float2 uv_BumpMap; //当前坐标的视角方向 float3 viewDir; }; //变量声明 sampler2D _MainTex;//主纹理 sampler2D _BumpMap;//凹凸纹理 float4 _RimColor;//边缘颜色 float _RimPower;//边缘颜色强度 //【3】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //从主纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; //从凹凸纹理获取法线值 o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); //从_RimColor参数获取自发光颜色 half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); o.Emission = _RimColor.rgb * pow (rim, _RimPower); } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}


其中的viewDir 意为WorldSpace View Direction,也就是当前坐标的视角方向:


                       

 

关于surf中的两句新加的代码在这里也讲一下。

上面已经提到过,Normalize函数,用于获取到的viewDir坐标转成一个单位向量且方向不变,外面再与点的法线做点积。最外层再用 saturate算出一[0,1]之间的最靠近的值。这样算出一个rim边界。原理可以这样解释:



                            


 

 

这里o.Normal就是单位向量。外加Normalize了viewDir。因此求得的点积就是夹角的cos值。因为cos值越大,夹角越小,所以,这时取反来。这样,夹角越大,所反射上的颜色就越多。于是就得到的两边发光的效果。哈哈这样明了吧。

这里再介绍一下这个half。CG里还有类似的float和fixed。half是一种低精度的float,但有时也会被选择成与float一样的精度。先就说这么多吧,后面还会遇到的,到时候再讲。

 

我们将此Shader编译后赋给材质,得到如下效果,除了凹凸纹理的选择之外,还有边缘发光颜色和强度可供自由定制:


 

依然是调一些颜色玩一玩:

  

  

 

场景中的实测截图为:


 

 

7.凹凸纹理+颜色可调

 



接下来我们看看凹凸纹理+颜色可调的Shader怎么写:

Shader '浅墨Shader编程/Volume6/30.凹凸纹理+颜色可调+边缘光照'{ //--------------------------------【属性】---------------------------------------- Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} _BumpMap ('【凹凸纹理】Bumpmap', 2D) = 'bump' {} _ColorTint ('【色泽】Tint', Color) = (0.6, 0.3, 0.6, 0.3) _RimColor ('【边缘颜色】Rim Color', Color) = (0.26,0.19,0.16,0.0) _RimPower ('【边缘颜色强度】Rim Power', Range(0.5,8.0)) = 3.0 } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式+自定义颜色函数 #pragma surface surf Lambert finalcolor:setcolor //【2】输入结构 struct Input { //主纹理的uv值 float2 uv_MainTex; //凹凸纹理的uv值 float2 uv_BumpMap; //当前坐标的视角方向 float3 viewDir; }; //变量声明 sampler2D _MainTex; sampler2D _BumpMap; fixed4 _ColorTint; float4 _RimColor; float _RimPower; //【3】自定义颜色函数setcolor的编写 void setcolor (Input IN, SurfaceOutput o, inout fixed4 color) { color *= _ColorTint; } //【4】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //从主纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; //从凹凸纹理获取法线值 o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); //从_RimColor参数获取自发光颜色 half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); o.Emission = _RimColor.rgb * pow (rim, _RimPower); } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}



我们将此Shader编译后赋给材质,得到如下非常赞的效果。除了载入纹理,还有色泽,边缘颜色和强度可供调节:



 

依然是调些效果玩一玩:

  

  

   

 

 

而在场景中的实测效果为:


 





8.细节纹理


接着我们来看一个在屏幕上显示纹理细节的Shader:

Shader '浅墨Shader编程/Volume6/31.细节纹理'{ //--------------------------------【属性】---------------------------------------- Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} _Detail ('【细节纹理】Detail', 2D) = 'gray' {} } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式 #pragma surface surf Lambert //【2】输入结构 struct Input { //主纹理的uv值 float2 uv_MainTex; //细节纹理的uv值 float2 uv_Detail; }; //变量声明 sampler2D _MainTex; sampler2D _Detail; //【3】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //先从主纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; //设置细节纹理 o.Albedo *= tex2D (_Detail, IN.uv_Detail).rgb * 2; } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}


我们将此Shader编译后赋给材质,不加细节纹理如下:


 

加纹理细节的效果图如下:



而在场景中的实测效果为:


 

 

 

 

 

 

9.凹凸纹理+颜色可调+边缘光照+细节纹理




结合上面的8个Shader,我们可以完成本期文章这个结合了凹凸纹理+颜色可调+边缘光照+细节纹理的稍微复杂一点的Surface Shader:

Shader '浅墨Shader编程/Volume6/32.凹凸纹理+颜色可调+边缘光照+细节纹理'{ Properties { _MainTex ('【主纹理】Texture', 2D) = 'white' {} _BumpMap ('【凹凸纹理】Bumpmap', 2D) = 'bump' {} _Detail ('【细节纹理】Detail', 2D) = 'gray' {} _ColorTint ('【色泽】Tint', Color) = (0.6, 0.3, 0.6, 0.3) _RimColor ('【边缘颜色】Rim Color', Color) = (0.26,0.19,0.16,0.0) _RimPower ('【边缘颜色强度】Rim Power', Range(0.5,8.0)) = 3.0 } //--------------------------------【子着色器】---------------------------------- SubShader { //-----------子着色器标签---------- Tags { 'RenderType' = 'Opaque' } //-------------------开始CG着色器编程语言段----------------- CGPROGRAM //【1】光照模式声明:使用兰伯特光照模式+自定义颜色函数 #pragma surface surf Lambert finalcolor:setcolor //【2】输入结构 struct Input { //主纹理的uv值 float2 uv_MainTex; //凹凸纹理的uv值 float2 uv_BumpMap; //细节纹理的uv值 float2 uv_Detail; //当前坐标的视角方向 float3 viewDir; }; //变量声明 sampler2D _MainTex; sampler2D _BumpMap; sampler2D _Detail; fixed4 _ColorTint; float4 _RimColor; float _RimPower; //【3】自定义颜色函数setcolor的编写 void setcolor (Input IN, SurfaceOutput o, inout fixed4 color) { color *= _ColorTint; } //【4】表面着色函数的编写 void surf (Input IN, inout SurfaceOutput o) { //先从主纹理获取rgb颜色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; //设置细节纹理 o.Albedo *= tex2D (_Detail, IN.uv_Detail).rgb * 2; //从凹凸纹理获取法线值 o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); //从_RimColor参数获取自发光颜色 half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); o.Emission = _RimColor.rgb * pow (rim, _RimPower); } //-------------------结束CG着色器编程语言段------------------ ENDCG } //“备胎”为普通漫反射 Fallback 'Diffuse'}


我们将此Shader编译后赋给材质,得到如下效果:

 



依然是调一些效果玩一玩:

  

  

 

而在场景中的实测效果为:




 

 

 

六、场景搭建

 

 



以大师级美工鬼斧神工的场景作品为基础,浅墨调整了场景布局,加入了音乐,并加入了更多高级特效,于是便得到了如此这次非常炫酷的暗黑城堡场景。

运行游戏,史诗级音乐渐渐响起,雨淅沥沥地下,我们来到了神秘的暗黑城堡:



集市:


 

 

在集市中逛荡1:


 

在集市中逛荡2:


 

 

在集市中逛荡3:

 

 

 

 

通向远方的桥梁:

 

 

壮观的瀑布:


 

感受瀑布溅起的水花:

 

 

 

在瀑布旁看远方,雾气氤氲:


 

 

成群的飞鸟飞过:


 

 

远方:

 


一片荒凉:


 

孤岛:



透过栅栏远眺:

 


画面太美,简直乱真:



海面上倒映出晚霞:


 

城堡概况:

 

 

 

最后一张本次的Shader全家福:

 

 

 

 

OK,美图就放这么多。游戏场景可运行的exe可以在文章开头中提供的链接下载。而以下是源工程的下载链接。



本篇文章的示例程序源工程请点击此处下载:

 

     【浅墨Unity3D Shader编程】之六 暗黑城堡篇配套Unity工程下载




好的,本篇文章到这里就全部结束了。

下周浅墨要出差,所以下周是否更新得看具体的行程安排。

OK,新的游戏编程之旅正在继续,我们下次再会~


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Shader之LimLighting
[原]【浅墨Unity3D Shader编程】之六 暗黑城堡篇: 表面着色器(Surface Shader)的写法(一)
【Unity Shader实战】利用凹凸纹理和边缘光模拟全息投影的效果
Unity shader 官网文档全方位学习(一)
【Unity Shaders】Shader学习资源和Surface Shader概述
Unity3D Shader入门指南(二)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服