加载和使用HLSL着色器

Loading and using an HLSL shader?

本文关键字:HLSL 加载      更新时间:2023-10-16

我到处找,能找到的只有关于编写着色器的教程。他们都没有向我展示如何将他们融入我的场景。

所以本质上:

给定hlsl着色器,如果我有一个名为drawTexturedQuad()的函数,并且我希望着色器应用于结果,那么我该如何做到这一点呢?

感谢

ID3DXEffect提供了Begin()BeginPass()方法。在此期间,只需拨打drawQuad()即可。任何有关着色器的基本教程都应该显示这样的示例。

只是一个补充说明-如果有疑问,请咨询MSDN。

这个问题的答案令人惊讶地复杂,而且随着GPU硬件越来越强大,它变得越来越困难。D3DX-FX系统是所有需要完成的工作的一个例子,因此使用它是让事情在短期内正常工作的好步骤。

着色器是代码,但它们存在于CPU的另一台机器上,因此需要对它们的所有数据进行整理。固定部分:基本渲染状态,如深度状态、模具状态、混合模式、绘图命令;非常容易实现。最困难的部分是为可编程部分搭建桥梁:着色器、缓冲区、采样器和纹理。

索引缓冲区只起作用,因为在渲染未索引的几何体时只能有一个,或者没有。

顶点缓冲区或多或少相当容易处理,因为硬件可以编程为按程序读取顶点缓冲区。顶点缓冲区只需要提供至少与顶点着色器想要访问的信息一样多的信息。修改着色器的顶点输入,或需要同时编辑两侧的顶点格式,因此使用起来相当容易。

采样器和纹理是下一个"更容易"挂钩的困难部分:它们有一个可变的名称和一个相当刚性的类型。例如,在编译着色器"foo"时,纹理"myNormalMap"被指定为纹理槽3。您需要查找(通过反射API)分配纹理的插槽,并在运行时将引擎认为"myNormalMap"的纹理设置为插槽3,当然,还需要使用API来确定是否首先需要纹理。这就是开始为着色器变量制定命名约定开始变得重要的地方,因此可以使多个着色器与同一C++代码兼容。

常量缓冲区(或D3D9中的原始着色器常量)要复杂得多,尤其是使用可编程着色器框架,就像在Unreal等引擎中可以找到的那样。任何给定着色器使用的常量都是完整列表的一个子集,但C++端通常必须像需要所有常量一样编写。反射API不仅需要确定着色器中实际引用的变量,还需要确定它们的位置。这在D3D10中变得更易于管理,并且更新了,因为cbuffer是结构化的,并且比D3D9系统的流动性更小,后者受到寄存器计数的严重限制,但它也增加了还需要使用反射API来确定cbuffer绑定的顺序的步骤(以及还引用了哪些cbuffer本身)。

最后,有一个设计可以让它全部发挥作用:

创建一个驱动特定着色器原型的类。对于这个类暴露给着色器的每个变量(无论是纹理、常量缓冲区等),如果使用了反射信息,请查找它的位置并进行设置。保持这种快速、灵活和可扩展性是一项艰巨的挑战。