笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
CSDN视频网址:http://edu.csdn.net/lecturer/144
网上很多开发者跟我咨询关于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
}
_Color ("Main Color", Color) = (1,1,1,1)
_Color 定义的是Shader内部的名字表示颜色,Main Color是指示器中显示的名字,Color表示的是属性类型,(1,1,1,1)表示的是颜色的默认值。再给读者看下图中对应的项:
下面把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的说明。