加载并使用 HLSL 着色器?

发布于 2024-11-14 16:25:41 字数 159 浏览 5 评论 0原文

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

本质上来说:

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

谢谢

I've been looking everywhere and all I can find are tutorials on writing the shaders. None of them showed me how to incorporate them into my scene.

So essentially:

Given an hlsl shader, if I were to have a function called drawTexturedQuad() and I wanted the shader to be applied to the result, how exactly could I do this?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红衣飘飘貌似仙 2024-11-21 16:25:42

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

只是一个附加说明 - 如果有疑问,请询问 MSDN

ID3DXEffect provides Begin() and BeginPass() methods. Simply call drawQuad() during that time. Any basic tutorial on shaders should show such a sample.

Just an additional note- if in doubt, ask MSDN.

滴情不沾 2024-11-21 16:25:42

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

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

索引缓冲区可以正常工作,因为在渲染未索引几何体的情况下只能有一个,或者没有。

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

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

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

最后,有一种设计可以使其全部正常工作:

创建一个驱动特定着色器原型的类。对于此类向着色器公开的每个变量(无论是纹理、常量缓冲区等),请在反射信息中查找是否使用了该变量,并找出其位置并进行设置。保持快速、灵活和可扩展是一项艰巨的挑战。

The answer to this is surprisingly complex, and has been getting more difficult as the GPU hardware has been getting more and more powerful. The D3DX FX system is an example of all the work that needs to be done, so using that is a good step to just getting things working for short-term usage.

Shaders are code, but they live on another machine from the CPU, so need all of their data marshalled over. The fixed parts: basic render states like depth states, stencil states, blending modes, drawing commands; are extremely easy to implement. The hard part is making a bridge for the programmable parts: shaders, buffers, samplers, and textures.

Index buffers just work, since you can only have one, or none in the case of rendering un-indexed geometry.

Vertex buffers are more or less fairly easy to deal with, since the hardware can be programmed to read the vertex buffers procedurally. Your vertex buffers only needs to provide at least as much information as the vertex shader wants to access. Modifications to the shader's vertex input, or the vertex format requiring editing both sides at the same time, and so is reasonably easy to work with.

Samplers and Textures are the next 'easier' of the hard parts to hook: they have a variable name and a rather rigid type. For instance, When compiling shader 'foo', texture 'myNormalMap', is assigned texture slot 3. You need to look up (via the reflection APIs) which slot the texture was assigned, and set the texture your engine considers 'myNormalMap' to be to slot 3 at runtime, and of course also use the API to determine if the texture is even needed in the first place. This is where starting to have naming conventions for shader variables starts to matter, so multiple shaders can be made compatible with the same C++ code.

Constant buffers (or raw shader constants in D3D9) are a lot trickier, especially with a programmable shader framework like you can find in engines like Unreal. The constants any given shader uses is a subset of the full list, but the C++ side must generally be written as if all of them are needed. The reflection APIs again are needed to determine not only which variables are actually referenced in a shader, but where they are located. This became a bit more manageable in D3D10 and newer as the cbuffers are structs and less fluid than the D3D9 system which was heavily limited by register count, but it also adds the step of also needing to use the reflection APIs to determine the order of cbuffer bindings (and which cbuffers themselves are also referenced).

In the end there is one design to make it all work:

Make a class that drives a specific shader archetype. For each variable this class exposes to a shader (be it a texture, constant buffer, etc), look up in the reflection info if it is used, and find out its location, and set it. Keeping this fast, flexible, and extensible is all a difficult challenge.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文