【DirectX 11 SDK 学习笔记】Shaders and Effect System



Summary

在之前的教程中,我们建立了vertex buffer,而且将一个三角形传递给了GPU。现在,我们要一步步探索graphics pipeline,弄明白每一个阶段都是怎么工作的,探讨一下shadereffect system这些概念。

 

The Graphics Pipeline

在之前的例子中,我们建立了vertex buffer,并将一个 vertex layout和它关联起来。现在,我们来解释一下shader是什么,以及他是怎么工作的。为了更全面深入的了解shader,我们先退一步,在更宏观的角度来俯瞰整个graphical pipeline

在例子二中,当我们调用VSSetShader()andPSSetShader()时,确实将我们的shader绑定到了pipeline。然后我们调用了Draw开始处理传递给graphics pipeline的顶点数据。下面的几节详细的分析了在Draw 命令之后发生的事情。

 

Shaders

 Direct3D 11中,不同的 shader工作在不同的graphics pipeline阶段。是被GPU执行的短小程序,获得有效的输入数据,然后处理这些数据,再将输出的结果传递给下一个 pipeline 阶段。Direct3D 11支持3个基本的shader类型:vertex shader, geometryshader, and pixel shader

Vertex shader将顶点作为输入,通过vertex buffer传递给GPU的每个顶点都会被执行一次。Geometry sharder的输入数据是 primitive,每一个传递给GPU primitive都会执行一次,primitive可以是一个点,线段,或者三角形。Pixel shaderpixel (有时候也称为fragment)作为输入,我们想要渲染的primitive中的每个像素都会执行一次 pixel shader 。总的来说,vertexgeometry,和pixel shader 是渲染动作的核心。当使用Direct3D 11渲染的时候,GPU必须有有效的vertex shaderpixel shaderGeometry shaderDirect3D 11中的可选的高级特性,在本例中不会深入的涉及geometry shader。当然,在Direct3D 11中还有支持tessellation特性的hull shaderdomain shader,支持计算特性的 compute shader,这些需要参考其他的例子。

 

Vertex Shaders

VertexGPU在顶点上执行的一小段代码,可以将vertex shader理解成将每一个vertex作为输入,然后处理输入数据,输出处理结果的C函数。在应用程序将顶点数据以vertexbuffer格式传递给GPU之后,GPU迭代遍历vertex buffer中的所有顶点数据,将顶点数据作为vertex shader的输入,每个顶点执行一次vertex shader定义的动作。

Vertex shader可以用来完成很多的任务,但是最核心和常用的功能是transformation .Transformation 将向量从一个坐标系变换到另一个坐标系的过程.例如,3D场景中的一个三角形的三个点分别是(0, 0, 0) (1, 0, 0) (0, 1, 0)当这个三角形绘制在 2D texture上时,GPU就需要知道buffer中的这些点对应的2D坐标,这种情况下就需要transformation 来完成.Transformation会在下一个例子中详细讨论。这个例子中,只是使用了一个简单的vertex shader,不对传入的顶点做任何处理,怎么传入就怎么传出去。我们使用High-LevelShading Language (HLSL) 来编写shader,回忆一下,我们的顶点数据有一个3D的位置元素,并且这个vertexshader根本不对输入数据做任何处理。Vertex shader的代码看起来是这样:

    float4 VS( float4 Pos : POSITION ) :SV_POSITION
    {
        return Pos;
    }

这个vertex shader看起来和C函数很相似,HLSL使用类C语法,这样便于C/C++程序员更容易学习。我们能够看到这个vertex shader,名字是VS,有一个float4类型的参数和float4类型的返回值。HLSL中,float4是一个思维向量,每个分量都是float类型。和前面提到的一致,HLSL中的semantics也是描述了数据的本质。我们上面的shader,我们选择POSITION作为Possemantics,因为这个参数表示定点的位置。选择SV_POSITION作为返回值的semantics ,是预先定义的有特殊含义的semantics,告诉graphics pipeline clip-space位置信息。GPU在屏幕上画点的时候需要clip-space位置(在下一节中讨论clip-space)

 

Pixel Shaders

现代的电脑显示器大多是光栅显示器,这就意味着屏幕事实上都是二维的像素点组成的网格,每个像素含有和其他像素独立的颜色。当我们要在屏幕上渲染一个三角形的时候,并不是真的渲染一个完整的三角形,而是点亮被三角形区域覆盖的像素。图2很好的图解了这点:左边的图是我们想要绘制的三角形,右图是实际绘制在屏幕上的像素。



将三个点定义的三角形转化成被三角形覆盖的一堆像素点的过程,称为rasterizationGPU首先会检测哪些像素是被渲染目标三角形覆盖的。然后对覆盖的像素唤起活动的pixel shader Pixel shader的首要目标就是计算每个像素点的颜色。Pixel shader将着色之前的像素作为输入,然后做相应的计算,然后将计算结果颜色返回给pipeline。输入数来自激活的geometryshader,如果像本例中没有geometry shader的情况下,输入来自vertexshader


之前创建的vertexshader输出一个 float4类型的SV_POSITION结果,这将作为pixel shader的输入。因为pixelshader输出的是颜色值,所以输出结果应该是float4类型,所以我们将输出结果的semantics设置为SV_TARGET,表明输出的格式。完整的pixel shader代码如下:


 


  float4 PS( float4 Pos : SV_POSITION ) :SV_Target
    {
        return float4( 1.0f, 1.0f, 0.0f,1.0f );   // Yellow, with Alpha =1
    }


Creating the Shaders


在程序代码中,我们需要创建一个vertexshader和一个 pixel sheder对象,这些对象表示我们的shader,通过调用D3DX11CompileFromFile()来创建。代码如下:


 
    // Create the vertexshader
    if( FAILED( D3DX11CompileFromFile("Tutorial03.fx", NULL, NULL, "VS", "vs_4_0",D3DCOMPILE_ENABLE_STRICTNESS, NULL, NULL, &pVSBlob, &pErrorBlob, NULL )) )
        return FALSE;


// Create the pixelshader
    if( FAILED( D3DX11CompileFromFile("Tutorial03.fx", NULL, NULL, "PS", "ps_4_0",D3DCOMPILE_ENABLE_STRICTNESS, NULL, NULL, &pPSBlob, &pErrorBlob, NULL )) )
        return FALSE;


 


Putting It Together


在了解了完整的graphics pipeline之后,我们可以开始理解我们在Tutorial 2中创建的三角形的渲染过程了。创建Direct3D应用程序需要连个明确的步骤。第一步在vertex data中创建资源数据,参考 tutorial 2。第二步:创建可以将数据转化为渲染的shader,就像这个例子中分析的一样。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值