主讲人:虚拟橙子什么是SHADER程序化着色器,最初的概念是采用一系列类似汇编语言的指令直接对GPU进行操作,改变3D显示中的顶点、像素,做到一些特殊的效果经过多年的发展,语言体系逐渐成熟,多家公司及机构开发了自己的语言标准,目前我们常见的有以下几种:语言应用平台开发商HLSLdirectXmircosoftCGdirectXNvidiaGLOpenGLSGIGLES手机等嵌入式设备KhronosUNITY3DSHADER分类语言适用平台阴影参考FixedFunctionShaderPC、Mac、移动设备无U3dReferenceVertex&FragmentShaderPC、Mac无CG、HLSLSurfaceShaderPC、Mac有CG、HLSL那些有可能是让你停下来的原因学习shader是否需要知道复杂的GPU指令?完全不需要,最初的shader确实是采用类似汇编的GPU语言来编写,但经过多年的进化,现在已经十分规范了。学习shader是否要有非常专业的图形学和数学知识?这个可以有,当然越专业越好!但意思并不是说不懂图形学就不能写shader了,即使做不到那么专业,你也可以学shader,就比方说你可能会C++,但是你不一定要用它来写一套windows系统,但你完全可以用它做个计算器,仍然很管用。HELLOSHADER这段程序做了最简单的事情:把一个物体的表面颜色赋值成了红色。当我们剔除shader当中的大部分,以最简单的结构去看它的时候,你会发现,其实shader就是一个函数,而这个函数所做的事情,不过就是指定输出的颜色而已HELLOSHADER稍微做下更改,这次我们把输出的自发光通道赋以绿色,结果中我们看到,自发光是不受环境光影响的至此,我们得出结论,shader其实只不过是让一个物体表面以什么颜色显示而已,就这么简单从哪里开始?到哪里结束?(SURFACESHADER)CG语言段起点CG语言段终点文件头:#pragmasurfacesurfSimpleLambert#pragmasurface:声明是surfaceshadersurf:surfaceshader的入口函数名称定义SimpleLambert:自定义的光照模式函数名称(实际的函数都要在此名称基础上加Lighting前缀)执行顺序(SURFACESHADER)12Shader程序的执行顺序:1.执行surfaceshader的入口函数,计算表面颜色,返回给SurfaceOutput结构体2.执行光照模式函数,用surf函数返回的SurfaceOutput参数计算高光颜色,最终输出到屏幕中的3D物体表面注意:可能你看过很多没有光照模式函数的代码段,但那并不意味着没有光照模式函数,打开Unity\Editor\Data\CGIncludes文件夹中的Lighting.cginc文件,你就会找到默认的Lambert和BlinnPhong两种光照模式函数了,当然,你也可以找到surf函数中形参中的SurfaceOutput结构体的定义,他是固定的,不可以自己定义形参(SURFACESHADER)Surfaceshader的形参结构体Input可以由以下参数构成:uv_TextureName–贴图坐标1(TextureName例如MainTex)uv2_TextureName–贴图坐标2float3viewDir–视点方向float4withCOLORsemantic–颜色float4screenPos–屏幕坐标系中的点坐标float3worldPos–世界坐标系中的点坐标float3worldRefl-世界坐标系下的反射向量float3worldNormal-世界坐标系下的法线float3worldRefl;INTERNAL_DATAfloat3worldNormal;INTERNAL_DATA通过简单的例子认识SHADER我们知道,在u3d的shader中,一般情况下,习惯把高光贴图放到_MainTex的Alpha通道内,如左图这样的确省了一张贴图,但并不是我们所习惯的,因此我们想把它提取出来,为这个shader增加一个高光通道的设置通过简单的例子认识SHADER1.为shader在u3d的属性面板中增加一个贴图通道2.增加一个变量与属性面板对应,以便能够在程序中使用3.在Input结构体中增加这个贴图通道的uv,但其实你可以直接用uv_MainTex,因为不论你定义成什么名字,只要以uv_开头,都是默认的第一套坐标4.将贴图解释成颜色信息,并代替原来的MainTex的alpha通道,赋值给高光属性1234从哪里开始?到哪里结束?(VERTEX&FRAGMENTSHADER)CG语言段起点CG语言段终点声明VertexShader的函数名称声明FragmentShader的函数名称执行顺序(VERTEX&FRAGMENTSHADER)Shader程序的执行顺序:1.执行vertexshader,执行结果输出到屏幕3D物体顶点,同时作为fragmentshader的形参输入(如果有)2.执行fragmentshader,最终输出到屏幕中的3D物体表面最终输出到画面12形参(VERTEX&FRAGMENTSHADER)形参定义以上图中所示的用于vertexshader的形参appdata结构体,可以有自己定义,但官方文档中有这样的解释仅能用以下参数构成:float4vertex顶点位置float3normal顶点法线float4texcoordUV1float4texcoord1UV2float4tangent正切(用于法线贴图计算)float4color顶点颜色不过我们也可以不用自己定义,打开unity3d安装目录下“Unity\Editor\Data\CGIncludes”文件夹中的UnityCG.cginc文件,会看到如右图的一些定义因此,我们只需要在程序中#include“UnityCG.cginc”就可以使用已经定义好的形参结构体注意:请完全不用去理会这些既定的参数是如何从模型文件中获得的,因为这是程序自动完成的,我们只需要关心,对他们进行什么样的处理就行了形参定义FragmentShader的形参结构体v2f,顾名思义就是vertextofragment的意思,当然这个名称是可以由你自己设定的v2f的变量都是从vertexshader函数输出的,并没有特定的格式,可完全由我们自己来定义,并不是所有定义的变量都有用,无论你如何定义,最终输出到屏幕上的仅有颜色而已试着写出你自己的第一个HELLOSHADER吧谢谢!