笔者介绍:姜雪伟


网上很多开发者跟我咨询关于GPU编程,其实GPU编程没有大家想象的那么难,它也是一种针对GPU显卡的编程脚本,在学习Shader编程之前,作为常识,我们要了解Shader编程开发语言有哪几种?

HLSL(High Level Shader Language)只能供微软的Direct3D以及XNA使用,微软提供的GPU编程不能跨平台使用,只能在Window平台上使用。

         CG(C for Graphics)由NVIDIA公司开发,CG程序可以根据运行时的需要或者事先编译成GPU汇编代码,CG语言也是最基本的语言,它的结构跟C语言类似,容易学习。读者可以学习《CG教程-可编程实时图形权威指南》。

        GLSL(OpenGL Shading Language)也称作Glslang语言,OpenGL和OpenGLES都是使用这种GPU编程语言实现跨平台的。

        ShaderLab语言是Unity配备了一个强大的着色器语言(ShaderLab),它的顶点和片段是CG/HLSL高级语言编写的。

介绍完语言,写过Shader的读者都知道,Shader不好调试,通常的做法都是在程序中通过注释代码的方式逐步排除Bug,在这里给读者推荐几个调试Shader的工具:FX Composer工具,Render Monkey工具,我调试Shader使用的是Render Monkey,当然也会使用排除法。下面给读者介绍ShaderLab的内容,先看一下事例代码:

Shader "SeparateSpecular" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
	_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
	_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
	_ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
	_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
	_Cube ("Reflection Cubemap", Cube) = "_Skybox" { TexGen CubeReflect }
	_GrayTex("Gray(RGB)", 2D) = "white"{}


	_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
	
	_RimFaceColor ("Rim Face Color", Color) = (0.26,0.19,0.16,0.0)
	_RimHairColor ("Rim Hair Color", Color) = (0.26,0.19,0.16,0.0)


	_RimFacePower ("Rim Face Power", Range(0.5,8.0)) = 3.0
	_RimHairPower ("Rim Hair Power", Range(0.5,8.0)) = 3.0


	_GrayFaceColor("Face Color", Color) = (0.5, 0.5, 0.5, 1)
	_GrayHairColor("Hair Color", Color) = (0.5, 0.5, 0.5, 1)
}
SubShader {
	LOD 300
	Tags { "RenderType"="Opaque" }


CGPROGRAM
#pragma surface surf BlinnPhong
sampler2D _MainTex;
samplerCUBE _Cube;
sampler2D _GrayTex;


fixed4 _Color;
fixed4 _ReflectColor;
half _Shininess;
float _RimFacePower;
float _RimHairPower;
float4 _RimFaceColor;
float4 _RimHairColor;


float4 _GrayFaceColor;
float4 _GrayHairColor;


struct Input {
	float2 uv_MainTex;
	float3 worldRefl;
	float3 viewDir;
	float2 uv_GrayTex;
};


void surf (Input IN, inout SurfaceOutput o) {
	fixed4 tex = tex2D(_MainTex, IN.uv_MainTex)* _Color;
	fixed4 graytex = tex2D(_GrayTex, IN.uv_GrayTex);


	fixed4 c = tex;
	
	fixed4 grayface = graytex * _GrayFaceColor;
	
	fixed4 grayhair = (1.0 - graytex.rgba) * _GrayHairColor;


	o.Albedo =c.rgb * grayhair.rgb;
	o.Albedo += c.rgb * grayface.rgb;


	o.Gloss = tex.a;
	o.Specular = _Shininess;
	
	fixed4 reflcol = texCUBE (_Cube, IN.worldRefl);
	reflcol *= tex.a;
	half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));


	o.Emission = reflcol.rgb * _ReflectColor.rgb + _RimHairColor.rgb * pow (rim, _RimHairPower) * grayhair.rgb;
	o.Emission += reflcol.rgb * _ReflectColor.rgb + _RimFaceColor.rgb * pow (rim, _RimFacePower) * grayface.rgb;


	o.Alpha = reflcol.a * _ReflectColor.a;
}
ENDCG
}



看上面的脚本中,Properties有很多项,以属性中的

_Color ("Main Color", Color) = (1,1,1,1)

_Color 定义的是Shader内部的名字表示颜色,Main Color是指示器中显示的名字,Color表示的是属性类型,(1,1,1,1)表示的是颜色的默认值。再给读者看下图中对应的项:

unity app开发框架 unity3d 开发框架_贴图

下面把Properties中对应的定义给读者一一展现如下:

Properties定义的属性块,其中可以包含多个属性,其定义如下:
name(“display name”,Range(min,max))=number
定义浮点数属性,在检视器中可通过一个标注最大最小的滑条来修改。
name(“display name”,Color)=(number,number,number,number)
定义颜色属性
name("display name",2D) = "name"{options}
定义2D纹理属性
name("display name",Rect)="name"{options}
定义长方形(非2次方)纹理属性
name("display name", Cube)="name"{options}
定义立方贴图纹理属性
name("display name",Float)=number
定义浮点数属性
name("display name",Vector)=(number, number,number,number)
定义一个四元数的容器(相当于Vector4)属性

注意:对于Range和Float类型的属性只能是单精度值,对于Color和Vector类型的属性将包含4个由括号围住的的数描述。对于纹理(2D,Rect,Cube)缺省既可以是一个空字符串也可以是某个内置的缺省纹理:“white”,"black","gray","bump"。


纹理后买年的大括号内为纹理属性选项,为可选项。可用选项是:TexGen texgenmode纹理生成模式为对应贴图的自动纹理坐标生成模式,为ObjectLinear,EyeLiner,SphereMap,CubeReflect,CubeNormal之一,这些模式和OpenGL纹理生成模式相对应。注意如果使用自定义顶点程序,那么纹理生成将被忽略。

比如:_MainTex("Base", 2D) = "white"{TexGen EyeLiner}

LightmapMode 光照贴图模式,如果给出这个选项,纹理将能被渲染器的光线贴图属性所影响。纹理不能被使用在材质中,而是取自渲染器的设定。

以上是关于Properties中的说明,后面会给出subShader的说明。