XNAShader教程一
2014-01-23 17:08
162 查看
您好,欢迎来到XNA Shader教程1。我的名字叫Petri Wilhelmsen,是Dark Codex Studios的成员。我们经常会参加各种图形/游戏开发的竞赛,如Gathering,Assembly,Solskogen,Dream-Build-Play和NGA等。
本XNA Shaders编程教程将讨论XNA的不同方面的知识以及如何使用XNA和GPU编写HLSL。我将从一些基本理论开始,然后深入到shader编程的实际方法。理论部分不会面面俱到,但足以让你开始使用shader并自己实践。
它将涵盖HLSL的基础,HLSL语言如何工作和一些必须知道的关键字。
今天,我将介绍XNA和HLSL以及一个简单的环境光照算法。
先决条件
XNA的编程基础,因为我们将涉及到加载纹理,三维模型,矩阵和一些数学知识。Shader简史
在DirectX8之前,GPU使用固定方式变换像素和顶点,即所谓的“固定管道”。这使得开发者不可能改变像素和顶点转化和处理的进程,使大多数游戏的图像表现看起来非常相似。2001年,DirectX8提出了顶点和像素着色器,这让开发者可以在管道中决定如何处理顶点和像素,使他们获得了很强的灵活性。
一开始shader编程使用汇编语言程序使用的着色器,这对shader开发者来说相当困难,Shader Model 1.0是唯一支持的版本。但DirectX9发布后这一切改变了,开发者能够使用高级着色语言(HLSL)取代了汇编语言,HLSL语法类似C语言,这使shader更容易编写、阅读和学习。
DirectX 10.0提出了一个新的shader——Geometry Shader作为Shader Model 4.0的组成部分。但这需要一个最先进的显卡和Windows Vista才能支持。
DirectX的最新版本为DirectX 11,它包含了tesselator,用于并行编程的DirectCompute等新功能。
XNA支持Shader Model 1.0至3.0,可以在XP,Vista和XBox360!上运行。
Shader?
那么什么是shader?shader一组运行在GPU上的指令,使开发者能够创建小型的程序控制图形管线的三个阶段:像素着色器阶段,几何着色器阶段和像素着色器阶段。图1:可编程图形管道
如图1所示,你可以对绿色部分进行编程,而其他阶段是固定的,你无法控制它们。Xbox360和XNA不支持几何着色器,所以本教程不会涉及它。下面我们快速浏览一下顶点着色器和像素着色器(不理解代码也别急,我们会在后面的部分加以讨论)
Vertex shader
Vertex shaders用来逐顶点地处理顶点数据。例如可以通过将模型中的每个顶点沿着法线方向移动到一个新位置使一个模型变“胖”(这称之为deform shaders)。Vertex shaders从应用程序代码中定义的一个顶点结构获取数据,并从顶点缓冲区加载这个结构传递到shader。这个结构描述了每个顶点的属性:位置,颜色,法线,切线等。
接着Vertex shader将输出传递到pixel shader。可以通过在shader中定义一个结构包含你想要存储的数据,并让Vertex shader返回这个实例来决定传递什么数据,或通过在shader中定义参数,使用out关键字来实现。输出可以是位置,雾化,颜色,纹理坐标,切线,光线位置等。
将一个对象的坐标转换到屏幕空间的简单顶点着色器代码如下:
?
Pixel Shader
Pixel Shader对给定的模型/对象/一组顶点处理所有像素(逐像素)。这可能是一个金属盒,我们要自定义照明的算法,色彩等等。Pixel Shader从vertex shaders的输出值获取数据,包括位置,法线和纹理坐标:?
图1中所示的所有阶段整合在一起就是为了合成图像并显示在屏幕上。
HLSL
高级着色语言(High Level Shading Language,HLSL)是用来开发shader的一种类似于C的语言。在HLSL中,你可以声明变量,函数,数据类型,测试(if/else/for/do/while+)以及更多功能以建立一个顶点和像素的处理逻辑。下面是一些HLSL的关键字。这不是全部,但是最重要的。bool | true或false |
int | 32位整数 |
half | 16位整数 |
float | 32位浮点数 |
double | 64位高精度浮点数 |
float3 vectorTest | float x 3 |
float vectorTest[3] | float x 3 |
vector vectorTest | float x 3 |
float2 vectorTest | float x 2 |
bool3 vectorTest | bool x 3 |
float3x3 | 3x3矩阵,浮点类型 |
float2x2 | 2x2矩阵,浮点类型 |
cos(x) | 返回x的余弦值 |
sin(x) | 返回x的正弦值 |
cross(a, b) | 返回向量a和向量b的叉乘 |
dot(a,b) | 返回向量a和向量b的点乘 |
normalize(v) | 返回一个归一化的向量v(v / |v|) |
Effect文件
Effect文件(.fx)让开发shader变得更容易,你可以在.fx文件中存储几乎所有关于着色的东西,包括全局变量,函数,结构,vertex shader,pixel shader,不同的techniques/passes,纹理等等。我们前面已经讨论了在shader中声明变量和结构,但什么是technique/passes?这很简单。一个Shader可以有一个或一个以上的technique。每个technique都有一个唯一的名称,我们可以通过设置Effect类中的CurrentTechnique属性选择使用哪个technique。?
?
?
?
?
在XNA中实现Shader
在XNA中实现Shader很简单。事实上,只需几行代码就可以加载和使用shader。下面是步骤:1. 编写shader
2. 把shader文件(.fx)导入到“Contents”
3. 创建一个Effect类的实例
4. 初始化Effect类的实例。
5. 选择使用的technique
6. 传递不同的参数至shader
7. 绘制场景
更详细的步骤:
1.记事本和Visual Studio等都可以用来编写shader。也有一些shader的IDE可用,我个人喜欢使用nVidia的FX Composer:http://developer.nvidia.com/object/fx_composer_home.html。2.当shader建立后,将其拖放到“Content”目录,自动生成素材名称。素材名称与fx文件名称是相同的,你也可以修改为不同的名称。
3.XNA框架有一个Effect类用于加载和编译shader。要创建这个类的实例可用以下代码:
?
?
?
5.选择使用何种technique:
?
?
?
?
?
环境光照(Ambient light)
现在我们知道了什么是shader,现在就可以创建你的第一个shader了。这个shader非常简单,只是变换了顶点坐标并计算了模型上的环境光照。首先,什么是“Ambient light” ?
环境光是场景中的基本光源。如果你进入一个漆黑的屋子,环境光通常是零,但走到外面时,总是有光能让你看到。环境光没有方向(译者:所以也将其称为“全局光照模型”),在这里应确保每个对象都会受到一个光照,获得一个基本的颜色。
在图2中的场景只包含一个绿色的环境光,场景由一个黑色背景和一个没有纹理的僵尸组成,在下面的教程中我们会让这个僵尸的视觉效果变得更好。
图2 被环境光照射的场景
环境光的公式是: I = Aintensity* Acolor
其中I是光的实际颜色,Aintensity是光的强度(通常在0.0和1.0之间),Acolor环境光的颜色,这个颜色可以是硬编码的值,参数或纹理。
好吧,现在开始实现Shader。
首先,我们需要矩阵表示世界矩阵、视矩阵和投影矩阵:
?
在声明Vertex Shader方法VertexShaderFunction(类似于Vertex Shaders的main()函数)时,我们指定这个函数的返回值为VertexShaderOutput类型的对象(你可以自定义这个结构体的名称,例如VSOut等),参数为VertexShaderInput结构体。在VertexShaderFunction方法中必须创建一个VertexShaderOutput结构体的实例,设置它的成员并返回。
?
现在开始处理pixel shaders,在这里进行环境光照的计算。它将Vertex Shader的输出作为输入。我们声明为一个float4类型的函数,返回存储在GPU中的COLOR寄存器上的float4值。
?
?
相关文章推荐
- XNA Shader编程教程2-漫反射光照
- Shader教程系列XNA
- 【原】XNA Shader教程的Rendermonkey实现
- 【风宇冲】Unity3D教程宝典之Shader篇:特别讲 CG函数
- Stage3d 由浅到深理解AGAL的管线vertex shader和fragment shader || 简易教程 学习心得 AGAL 非常非常好的入门文章
- OpenGL ES2.0教程:编写自己的shader
- 【GLSL教程】(三)在OpenGL中向shader传递信息
- Unity3D Shader官方教程翻译(十二)----Shader语法:Pass的标记
- 【译】Unity3D Shader 新手教程(6/6) —— 更好的卡通Shader
- XNA之RPG游戏开发教程之五
- WP7平衡球游戏开发教程(三)--DebugDraw(XNA渲染)
- opengl 教程(4) shader(1)
- XNA 实用教程
- Unity3D Shader官方教程翻译(二)
- Unity3D Shader官方教程翻译(十四)----Shader语法:Pass的BindChannels 绑定通道
- MPC—Shader—傻瓜教程 Ver.1.0
- XNA入门教程----(一)
- Strumpy Shader Editor入门教程
- Unity3D Shader官方教程翻译(十五)----Shader语法 UsePass
- Unity shader教程-第五课:自定义光照模型之Half Lambert模型