欢迎来真孝善网,为您提供真孝善正能量书籍故事!

深入浅出:学习Shader的初阶指南

时间:11-21 名人轶事 提交错误

大家好,如果您还对深入浅出:学习Shader的初阶指南不太了解,没有关系,今天就由本站为大家分享深入浅出:学习Shader的初阶指南的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

Unity Shader其实并不难。初学者常常会感到困惑,因为它有太多固定的命令和结构,而这些命令需要我们对3D渲染有一定的了解才能知道它们是做什么的。

Shader种类

OpenGL 和Direct3D 都提供三种类型的着色器:

顶点着色器:处理每个顶点,将顶点的空间位置投影到屏幕上,即计算顶点的二维坐标。同时,它还负责顶点的深度缓冲区(Z-Buffer)的计算。顶点着色器可以控制顶点的位置、颜色、纹理坐标等属性,但不能生成新的顶点。顶点着色器的输出被传递到管道中的下一步。如果后面定义了几何着色器,则几何着色器处理顶点着色器的输出数据,否则,光栅化器继续管线任务。

像素着色器(Direct3D),通常称为片段着色器(OpenGL):处理来自光栅器的数据。光栅化器填充了多边形并将其通过管道传输到像素着色器,像素着色器逐像素计算颜色。像素着色器通常用于处理场景照明和相关效果,例如凹凸纹理映射和颜色分级。片段着色器这个名字似乎更准确,因为对着色器的调用和屏幕上显示的像素之间没有一一对应的关系。例如,对于一个像素,片段着色器可能会被调用多次以确定其最终颜色,并且那些被遮挡的对象也会被计算,直到最终的深度缓冲区将对象依次排序。

几何着色器:可以在多边形网格中添加和删除顶点。它可以执行对于CPU 来说过于繁重的生成几何图形和添加模型细节的工作。 Direct3D 版本10 添加了对几何着色器的API 支持,并成为Shader Model 4.0 的组成部分。 OpenGL 只能通过其插件之一使用几何着色器。

Unity Shader分为Surface Shader和Vertex And Fragment Shader。

Surface Shader是Unity提出的概念。编写与灯光交互的着色器很复杂。有多种类型的灯光、不同的阴影选项和不同的渲染路径(前向渲染和延迟渲染)。表面着色器简化了这部分。 Unity建议使用表面着色器来编写与光照相关的Shader。

顶点和片段着色器(Vertex And Fragment Shader)与OpenGL和Direct3D中的顶点着色器和片段着色器没有区别。顶点片段着色器比表面着色器使用更自由,功能更强大,但当然光照需要自己处理。 Unity还允许在里面编写几何着色器,一般用得不多。

Shader程序结构

//着色器语法:

着色器“名称”{[属性]子着色器[后备][自定义编辑器]}

//属性语法

属性{ 属性[属性.] }

//子着色器语法

Subshader { [标签] [CommonState] Passdef [Passdef .] }

//传递语法

通过{ [名称和标签] [RenderSetup] }

//后备语法

后备“名称”

属性定义:定义Shader的输入。这些输入可以在材质编辑期间指定。

子着色器:一个着色器可以有多个子着色器。这些子着色器彼此独立,并且只有一个子着色器将在最终平台上运行。写多个的目的是为了解决兼容性问题。 Unity会选择一个与终端平台兼容的Shader来运行。

Fallback:如果子Shader无法在终端平台运行,则使用Fallback指定的备用Shader,俗称备胎。

通行证:通行证是一张图纸。对于表面着色器来说,只能有一个Pass,所以没有Pass部分。顶点片段着色器可以有多个通道。多次通过可以实现许多特殊效果。例如,当角色被环境遮挡时,仍然可以看到角色的轮廓,这可以通过使用多个通道来实现。

Cg代码:每个Pass可以包含自定义的Cg代码,从CGPROGRAM开始到ENDCG结束。

表面着色器和顶点着色器:

着色器“自定义/新着色器”{

特性{

_MainTex("基础(RGB)", 2D)="白色"{}

}

子着色器{

标签{ "RenderType"="不透明" }

详细程度200

CG程序

#pragma 表面冲浪兰伯特

采样器2D _MainTex;

结构输入{

float2 uv_MainTex;

};

void surf (输入IN, inout SurfaceOutput o) {

half4 c=tex2D (_MainTex, IN.uv_MainTex);

o.反照率=c.rgb;

o.Alpha=c.a;

}

ENDCG

}

回退“漫反射”

}

着色器“VertexInputSimple”{

子着色器{

经过{

CG程序

#pragma 顶点vert

#pragma 片段片段

#include "UnityCG.cginc"

结构体v2f {

float4 位置: SV_POSITION;

固定4色: COLOR;

};

v2f 垂直(appdata_base v)

{

v2f o;

o.pos=mul(UNITY_MATRIX_MVP, v.vertex);

o.颜色.xyz=v.法线* 0.5 + 0.5;

o.颜色.w=1.0;

返回o;

}

固定4碎片(v2f i): SV_Target {返回i.color; }

ENDCG

}

}

}

Shader 输入

Shader输入有两种来源,一种是通过属性定义,另一种是通过Shader.SetGlobalXXX方法进行全局设置。

属性定义变量:属性定义中的变量是设置Shader参数的主要方式。它随材料而变化。使用此Shader的每种材质都可以在Inspector或脚本中设置这些参数。这些参数除了在Shader的Properties部分定义外,还需要在Cg中声明后才能使用。例如,在上面的表面着色器示例中,我们将_MainTex定义为2D类型的属性,并且我们还需要在Cg中声明sampler2D _MainTex。

全局变量:Shader有一组SetGlobalXXX方法,可以设置Shader的统一变量,这些变量在Cg中定义,但在属性中不定义。此设置是全局的,所有定义此统一的着色器都会受到影响。例如,如果我们希望场景随着时间的推移而改变颜色,我们可以为场景中使用的Shader设置一个统一的全局颜色变量,然后通过在脚本中设置颜色来改变场景的颜色。当角色释放技能时场景变黑时也可以使用此方法。

Unity着色器中允许定义的属性类型有:

Unity着色器中允许定义的属性类型有:

Cg类型对应的关键字类型示例

float float_MyFloat(“我的浮动”, Float)=0.5Range float (指定范围内) float_MyRange(“我的范围”, Range(0.01, 0.5))=0.1Color floatquad float4_MyColor(“某些颜色”, Color)=( 1,1,1,1)向量浮点四元float4_MyVector("Some Vector",Vector)=纹理sampler2D_MyTexture("纹理", 2D)="白色" {}矩形非2阶大小纹理sampler2D_MyRect("我的矩形" ,矩形)=“白色”{}CUBECubeMapsamplerCUBE_MyCubemap(“立方体贴图”,CUBE)=“”{}

注:CubeMap是6个相关2D纹理的组合,主要用于反射效果(例如天空盒和动态反射)

SubShader

除了Pass之外,SubShader中还有两个标签值得关注:LOD和Tags

LOD

LOD是Level of Detail的缩写,或者准确的说是Shader Level of Detail的缩写,因为Unity中也有模型LOD的概念,这是两个不同的东西。这里我们只介绍Shader中的LOD。模型的LOD请参考这里。

Shader LOD允许我们设置一个值,它决定了我们可以使用什么样的Shader。允许的最大LOD可以通过Shader.maximumLOD或Shader.globalMaximumLOD设置。当设置的LOD小于SubShader指定的LOD时,该SubShader将不可用。通过LOD,我们可以为某种材质编写一组SubShader,并指定不同的LOD。 LOD越大,渲染效果越好。当然,硬件要求也可能更高,然后根据不同的终端硬件配置来设置globalMaximumLOD。兼顾性能的同时达到最佳的显示效果。

Unity的内置Shader定义了一组LOD值。我们在实现自己的Shader时可以将其作为参考来设置自己的LOD值。

VertexLit 及其系列=100

贴花,反射VertexLit=150

漫反射=200

漫反射细节、反射凹凸不亮、反射凹凸VertexLit=250

凹凸、镜面反射=300

凹凸镜面反射=400

视差=500

视差镜面=600

Tag

SubShader可以通过几个标签(tag)来修改,硬件会通过判断这些标签来决定何时调用shader。

比较常见的标签有:

队列

这个标签非常重要。它定义了一个整数,决定了Shader的渲染顺序。数字越小,渲染越早。早期渲染意味着它可能会被稍后渲染的内容覆盖并且不可见。

预定义的队列是:

名称值描述

Background1000是最早被称为的渲染,用于渲染天空盒或背景Geometry2000。这是默认值,用于渲染不透明的物体(正常情况下,场景中的大多数物体应该是不透明的)。 AlphaTest2450用于渲染Alpha Test像素,为AlphaTest单独设置一个Queue是出于效率考虑。 Transparent3000按照从后到前的顺序渲染透明对象。 Overlay4000用于渲染叠加效果,这是渲染的最后阶段(例如镜头光晕等特效)。

渲染类型

“不透明”或“透明”是两种常用的渲染类型。如果输出包含非透明对象,则将其写入Opaque;如果要渲染透明或半透明像素,则应将其写为Transparent。该标签主要用于

着色器替换

,一般情况下这个Tag似乎没有什么作用。

CommonState

SubShader中可以定义一组Render State,基本上就是一些渲染开关选项。它们对SubShader 的所有Pass 都有效,因此称为Common。这些Render State也可以在每个Pass中单独定义,将在Pass中详细介绍。

Pass

Render State

Render State主要控制渲染过程的一些开关选项,比如是否开启alpha混合、是否开启深度测试等。

常用的渲染状态包括:

剔除

用法:剔除|前|离开

多边形表面剔除开关。 Back表示背面剔除,Front表示正面剔除,Off表示关闭表面剔除,即双面渲染。有时候造型的时候会把裙子、飘带之类很薄的东西做成贴片。这就需要设置双面渲染的Cull Off,否则背面会是黑色的。

Z写入

用法:ZWrite On |离开

控制当前对象的像素是否写入深度缓冲区。默认情况下它是启用的。一般来说,绘制不透明物体时,ZWrite开启,绘制透明或半透明物体时,ZWrite关闭。

深度缓冲区:当图形处理卡渲染对象时,每个生成像素的深度(即z 坐标)存储在缓冲区中。该缓冲区称为z 缓冲区或深度缓冲区,通常组织成x-y 二维数组,用于保存每个屏幕像素的深度。如果场景中的另一个对象也在同一像素处渲染,则显卡会比较它们的深度并保留距离观看者较近的对象。然后将保留的对象点深度保存到深度缓冲区。最后,显卡可以根据深度缓冲区正确生成通常的深度感知效果:较近的物体遮挡较远的物体。

了解了深度缓冲区也就明白了为什么需要关闭ZWrite才能绘制透明或半透明的物体。如果不关闭的话,透明物体的深度也会被写入深度缓冲区,从而消除其后面的物体,而其后面的物体将不会被渲染,而其后面的物体则无法渲染看不见,还能叫透明吗?因此,我们在使用Alpha混合时需要设置ZWrite Off。

Z测试

用法:ZTest(小于| 大于| LEqual | GEqual | 等于| NotEqual | 始终)

控制如何进行深度测试,也就是上面提到的深度比较方法,用于比较两个图形处理卡的深度。默认值为LEqual。

值得一提的是,使用Alpha混合时,需要关闭ZWrite但必须打开ZTest,因为如果透明物体前面有不透明物体,透明物体仍然应该被遮挡和消除。

混合

混合。控制每个着色器的输出如何与屏幕上已有的颜色混合。

用法:

Blend Off:关闭混合

Blend SrcFactor DstFactor:最终颜色=Shader生成的颜色SrcFactor+屏幕原始颜色DstFactor

Blend SrcFactor DstFactor、SrcFactorA DstFactor:与上面相同,只是Alpha 通道是使用接下来的两个参数计算的。

常用的混合模式有:

Blend SrcAlpha OneMinusSrcAlpha //Alpha 混合

混合一一//添加剂

Blend OneMinusDstColor One //软添加剂

混合DstColor 零//乘法

混合DstColor SrcColor //2x 乘法

具体参考这里

自Unity5 起,以下固定功能Shader 命令已被标记为过时。这些命令的功能现在建议通过Shader(Cg)中的代码来实现。在这里列出它们是为了方便阅读以前编写的着色器:

灯光开启|离开

材质{ 材质块}

单独镜面反射离开

颜色颜色值

颜色材质环境和漫反射|排放

雾{雾块}

AlphaTest(小于| 大于| LEqual | GEqual | 等于| NotEqual | 始终)

SetTexturetextureProperty { 组合选项}

表面着色器

Surface Shader隐藏了光照处理的许多细节。它最初的设计目的是让用户只需要使用一些指令(#pragma)就能完成很多事情,并且封装了很多常用的光照模型和函数。与底层的Vertex And Fragment Shader相比,Surface Shader有更多的限制。它只能有一张通行证。如果需要执行一些常规功能并且需要光照,可以使用Surface Shader来编写,更快更方便。如果想写更高级的Shader,建议使用Vertex Shader和Fragment Shader。

Surface Shader主要由两部分组成,一是#pragma后面的指令,二是surf函数。

pragma 的语法是#pragma surface surfaceFunction lightModel [可选参数]

- surfaceFunction 通常是一个名为surf 的函数。您可以自己选择函数名称。

surf函数原型为:void surf(Input IN, inout SurfaceOutput o)

- lightModel是Unity内置的光照模型,可以是Lambert、Blinn-Phong等。

- 可选参数:包含许多命令详细参数,请参考这里

surf函数主要有Input结构体的输入和SurfaceOutput结构体的输出。

Input

需要在Shader 中定义输入结构。它可以包含以下字段。如果定义了这些字段,就可以在surf函数中使用它们(好神奇的黑科技)

对于多个纹理的uv坐标,名称必须符合uv + 纹理名称的格式。例如

float2 uv_MainTex

float3 viewDir - 视图方向值。为了计算视差效果、边缘照明等,需要包括视图方向值。

具有COLOR 语义的float4 - 每个顶点颜色插值。

float4 screenPos - 屏幕空间中的位置。对于反射效果,需要包括屏幕空间中的位置信息。例如,Dark Unity 中使用的WetStreet 着色器。

float3 worldPos - 在世界空间中的位置。

float3 worldRefl - 世界空间中的反射向量。如果表面着色器没有写入法线(o.Normal)参数,则将包含该参数。请参考这个例子:反射漫反射着色器。

float3 worldNormal - 世界空间中的法线向量。如果表面着色器没有写入法线(o.Normal)参数,则将包含该参数。

float3 worldRefl; INTERNAL_DATA - 世界空间中的反射向量。如果表面着色器没有写入法线(o.Normal)参数,则将包含该参数。

float3 世界法线; INTERNAL_DATA - 世界空间中的法线向量。如果表面着色器没有写入法线(o.Normal)参数,则将包含该参数。

SurfaceOutput

SurfaceOutput 描述表面的特性(光色反射率、法线、散射、镜面等)。这个结构是固定的,不需要在Shader中重新定义。

结构表面输出{

half3 反照率; //反射率,一般为光照前的原始颜色

half3 正常; //普通的

half3 排放; //自发光,用于增强物体本身的亮度,使其看起来像是可以自己发光

半镜面反射; //镜面

半光泽; //光泽度

半阿尔法; //透明的

};

由于引入了基于物理的光照模型,Unity5 添加了两个新的输出。

结构体SurfaceOutputStandard

{

固定3反照率; //基础(漫反射或镜面反射)颜色

固定3 正常; //切线空间法线,如果写成

half3 排放;

半金属; //0=非金属,1=金属

半平滑度; //0=粗糙,1=平滑

半闭塞; //遮挡(默认1)

固定阿尔法; //透明度透明度

};

结构SurfaceOutputStandardSpecular

{

固定3反照率; //漫反射颜色

固定3镜面反射; //镜面反射颜色

固定3 正常; //切线空间法线,如果写成

half3 排放;

半平滑度; //0=粗糙,1=平滑

半闭塞; //遮挡(默认1)

固定阿尔法; //透明度透明度

};

Unity提供了一些基本的SurfaceShader示例来帮助我们理解输入和输出是如何使用的。

顶点着色器

如果不想使用Surface Shader而直接在opengl和Direct3D中编写常见的顶点着色器和片段着色器,可以将它们嵌入到Pass through Cg代码片段中:

经过{

//.通常的通过状态设置.

CG程序

//此代码段的编译指令,例如:

#pragma 顶点vert

#pragma 片段片段

//Cg/HLSL c

ode itself       ENDCG       // ... the rest of pass setup ...   }

其中vert就是顶点着色器函数,frag就是片段着色器函数。一般来说,可以在顶点着色器中进行的计算就不应该放到片段着色器中去算,因为顶点着色器是逐顶点计算的而片段着色器是逐像素计算的,一个模型顶点总比表明像素少很多吧。 编写顶点和片段着色器一般需要包含Unity预定义的一个帮助文件UnityCG.cginc,里面预定义了一些常用的结构和方法。Windows版Unity这个文件位于({unity install path}/Data/CGIncludes/UnityCG.cginc。 Mac版位于/Applications/Unity/Unity.app/Contents/CGIncludes/UnityCG.cginc。 在代码中我们只需要添加 #include "UnityCG.cginc"就可以使用里面的结构和方法。

Input

顶点着色器的原型是 v2f vert (appdata v)  appdata 是输入,可以自己定义也可以使用Unity预定义的。Unity在UnityCG.cginc预定义了三种常用的输入结构:appdata_base,appdata_tan,appdata_full。 struct appdata_base {     float4 vertex : POSITION;     float3 normal : NORMAL;     float4 texcoord : TEXCOORD0; }; struct appdata_tan {     float4 vertex : POSITION;     float4 tangent : TANGENT;     float3 normal : NORMAL;     float4 texcoord : TEXCOORD0; }; struct appdata_full {     float4 vertex : POSITION;     float4 tangent : TANGENT;     float3 normal : NORMAL;     float4 texcoord : TEXCOORD0;     float4 texcoord1 : TEXCOORD1;     float4 texcoord2 : TEXCOORD2;     float4 texcoord3 : TEXCOORD3; #if defined(SHADER_API_XBOX360)     half4 texcoord4 : TEXCOORD4;     half4 texcoord5 : TEXCOORD5; #endif     fixed4 color : COLOR; }; 我们注意到这些结构的字段和表面着色器中的字段不同,后面多了一个冒号和一个标签。这是该字段的语义,用于告诉GPU这个字段的数据应该去哪里读写。GPU毕竟是为了图形计算而特别设计的东西,很多东西都是固定的,我们只要记得有这么几个名字可以用行了。 类型名字标签备注 float4vertexPOSITION顶点在模型坐标系下的位置float3normalNORMAL顶点的法向量float4tangentTANGENT顶点的切向量float4colorCOLOR顶点色float4texcoordTEXCOORD0顶点的第一个uv坐标float4texcoord1TEXCOORD1顶点的第二个uv坐标,最多可以到5

Output

顶点着色器的输出是也是一个可以自己定义的结构,但是结构内容也是比较固定的,一般包含了顶点投影后的位置,uv,顶点色等,也可以加一些后面片段着色器需要用到但是需要在顶点着色器中计算的值。这个输出就是后面片段着色器的输入。  struct v2f {     float4 pos : SV_POSITION;     half2 uv   : TEXCOORD0; }; 可以使用的字段有: 类型标签描述 float4SV_POSITION顶点在投影空间下的位置,注意和输入的模型坐标系下的位置不同,这个字段必必须设置,这个坐标转换是顶点着色器的重要工作float3NORMAL顶点在视图坐标系下的法向量float4TEXCOORD0第一张贴图的uv坐标float4TEXCOORD1第二张贴图的uv坐标float4TANGENT切向量,主要用来修正法线贴图Normal Mapsfixed4COLOR第一个定点色fixed4COLOR1第二个定点色AnyAny其他自定义的字段

坐标变换

顶点着色器有一项重要的工作就是进行坐标变换。顶点着色器的输入中的坐标是模型坐标系(ObjectSpace)下的坐标,而最终绘制到屏幕上的是投影坐标。  在我们Shader里面只需要一句话就可以完成坐标的转换,这也是最简单的顶点着色器: v2f vert(appdata v) {           v2f o;           o.pos = mul(UNITY_MATRIX_MVP, v.vertex);           return o; } 用UNITY_MATRIX_MVP矩阵乘以顶点在模型坐标系下的坐标就得到投影坐标。  UNITY_MATRIX_MVP是Unity内建的模型->视->投影矩阵, Unity内建矩阵如下: UNITY_MATRIX_MVP:当前模型->视图->投影矩阵。(注:模型矩阵为 本地->世界) UNITY_MATRIX_MV:当前模型->视图矩阵 UNITY_MATRIX_V:当前视图矩阵 UNITY_MATRIX_P:当前投影矩阵 UNITY_MATRIX_VP:当前视图->投影矩阵 UNITY_MATRIX_T_MV:转置模型->视图矩阵 UNITY_MATRIX_IT_MV:逆转置模型->视矩阵, 用于将法线从ObjectSpace旋转到WorldSpace。为什么法线变化不能和位置变换一样用UNITY_MATRIX_MV呢?一是因为法线是3维的向量而- UNITY_MATRIX_MV是一个4x4矩阵,二是因为法线是向量,我们只希望对它旋转,但是在进行空间变换的时候,如果发生非等比缩放,方向会发生偏移。 UNITY_MATRIX_TEXTURE0 to UNITY_MATRIX_TEXTURE3:纹理变换矩阵 下面简单介绍一下里面提到的几个坐标系:  模型坐标系:也叫物体坐标系,3D建模的时候每个模型都是在自己的坐标系下建立的,如果一个人物模型脚底是(0,0,0) 点的话它的身上其它点的坐标都是相对脚底这个原点的。  世界坐标系:我们场景是一个世界,有自己的原点,模型放置到场景中后模型上的每个顶点就有了一个新的世界坐标。这个坐标可以通过模型矩阵×模型上顶点的模型坐标得到。  视图坐标系:又叫观察坐标系,是以观察者(相机)为原点的坐标系。场景中的物体只有被相机观察到才会绘制到屏幕上,相机可以设置视口大小和裁剪平面来控制可视范围,这些都是相对相机来说的,所以需要把世界坐标转换到视图坐标系来方便处理。  投影坐标系:场景是3D的,但是最终绘制到屏幕上是2D,投影坐标系完成这个降维的工作,投影变换后3D的坐标就变成2D的坐标了。投影有平行投影和透视投影两种,可以在Unity的相机上设置。  屏幕坐标系 : 最终绘制到屏幕上的坐标。屏幕的左下角为原点。 除了内建矩阵,Unity还内建了一些辅助函数也可以在顶点着色器里面使用: float3 WorldSpaceViewDir (float4 v):根据给定的局部空间顶点位置到相机返回世界空间的方向(非规范化的) float3 ObjSpaceViewDir (float4 v):根据给定的局部空间顶点位置到相机返回局部空间的方向(非规范化的) float2 ParallaxOffset (half h, half height, half3 viewDir):为视差法线贴图计算UV偏移 fixed Luminance (fixed3 c):将颜色转换为亮度(灰度) fixed3 DecodeLightmap (fixed4 color):从Unity光照贴图解码颜色(基于平台为RGBM 或dLDR) float4 EncodeFloatRGBA (float v):为储存低精度的渲染目标,编码[0..1)范围的浮点数到RGBA颜色。 float DecodeFloatRGBA (float4 enc):解码RGBA颜色到float。 float2 EncodeViewNormalStereo (float3 n):编码视图空间法线到在0到1范围的两个数。 float3 DecodeViewNormalStereo (float4 enc4):从enc4.xy解码视图空间法线

用户评论

浮殇年华

想学做一些视觉效果酷炫的游戏画面吗?shader是个不错开始!

    有8位网友表示赞同!

坠入深海i

我以前一直不知道shader是什么,最近才发现原来它可以让游戏图片看起来更加逼真。

    有5位网友表示赞同!

涐们的幸福像流星丶

感觉学习shader挺有挑战性的,需要搞懂一些编程知识吧?

    有7位网友表示赞同!

tina

对这个新课程挺感兴趣的,想了解一下shader的基本原理。

    有13位网友表示赞同!

闲肆

有没有什么好的书或教程可以让我快速入门Shader?

    有7位网友表示赞同!

太难

我一直都觉得游戏画面太单调了,希望学习shader能够让我的作品更生动!

    有14位网友表示赞同!

蹂躏少女

听说学习shader能提高游戏制作的效率啊,真想试试。

    有19位网友表示赞同!

Hello爱情风

感觉这个视频讲解内容很实用,适合刚开始接触shader的人。

    有16位网友表示赞同!

孤自凉丶

期待学习shader之后能做出一些自己喜欢的特效!

    有12位网友表示赞同!

歆久

终于找到一个关于shader入门的好教程了,加油!

    有12位网友表示赞同!

铁树不曾开花

我已经开始玩转shader一段时间了,分享这个课程给我的朋友。

    有12位网友表示赞同!

强辩

Shader入门课程可以让我快速了解 shader 的基本概念?

    有10位网友表示赞同!

幸好是你

学习shader可以运用到其他领域吗?比如图片处理?

    有11位网友表示赞同!

怀念·最初

想问一下学好shader需要多长时间?

    有16位网友表示赞同!

Edinburgh°南空

这个视频的制作质量很高,讲解也很清晰易懂。

    有5位网友表示赞同!

娇眉恨

学习shader需要用到什么软 wares 软件工具呢?

    有9位网友表示赞同!

浅巷°

看到这个课程就想把以前学的编程知识运用到shader中!

    有14位网友表示赞同!

念初

我已经开始尝试编写的 shader 代码了,希望能做出像视频里那样炫酷的效果。

    有6位网友表示赞同!

疲倦了

学习shader让我对游戏开发有了更深的理解!

    有18位网友表示赞同!

我的黑色迷你裙

期待通过 shader 进一步提升我的游戏画面效果!

    有20位网友表示赞同!

【深入浅出:学习Shader的初阶指南】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活