【问题标题】:What vertex shader code should be used for a pixel shader used for simple 2D SpriteBatch drawing in XNA?在 XNA 中用于简单 2D SpriteBatch 绘图的像素着色器应该使用什么顶点着色器代码?
【发布时间】:2011-11-19 01:26:40
【问题描述】:

前言

首先,为什么 Silverlight 5 中的SilverlightEffect(.slfx 文件)需要顶点着色器?我正在尝试将一个简单的 2D XNA 游戏移植到 Silverlight 5 RC,并且我想使用一个基本的像素着色器。此着色器在 XNA for Windows 和 Xbox 中运行良好,但我无法将其与 Silverlight 一起编译为 SilverlightEffect。

Silverlight 工具包的MS blog 说“.slfx 和 .fx 之间没有区别”,但显然这不是真的——或者至少 SpriteBatch 在“常规 XNA”中为我们发挥了一些作用”,而且它不在“Silverlight XNA”中。

如果我尝试将像素着色器文件直接复制到 Silverlight 项目中(并将其更改为受支持的“Effect - Silverlight”导入器/处理器),当我尝试编译时,我会看到以下错误消息:

Invalid effect file. Unable to find vertex shader in pass "P0"

确实,我的像素着色器文件中没有顶点着色器。我不需要其他 2D XNA 应用程序,因为我只是在做基本的 SpriteBatch 绘图。

我尝试使用Remi Gillig's comment on this Shawn Hargreaves blog post 为我的着色器文件添加一个顶点着色器作为指导,但它并不完全奏效。着色器文件成功编译,我在屏幕上看到了我的游戏的一些相似之处,但它很小、扭曲、重复,而且全部混乱。很明显有些地方不太对劲。


真正的问题

这让我想到了我真正的问题:既然需要顶点着色器,是否有一个基本的顶点着色器函数适用于简单的 2D SpriteBatch 绘图?

如果顶点着色器需要世界/视图/项目矩阵作为参数,我应该为 2D 游戏使用什么值?

任何着色器专家可以提供帮助吗?谢谢!

【问题讨论】:

    标签: silverlight xna shader


    【解决方案1】:

    在 XNA 中,SpriteBatch 提供了自己的顶点着色器。因为 Silverlight 5 中没有 SpriteBatch,所以您必须提供自己的。

    您可能想查看the source code 以了解SpriteBatch 使用的着色器(位于SpriteEffect.fx 中)。这是它的顶点着色器,非常简单:

    void SpriteVertexShader(inout float4 color    : COLOR0,
                            inout float2 texCoord : TEXCOORD0,
                            inout float4 position : SV_Position)
    {
        position = mul(position, MatrixTransform);
    }
    

    所以现在您只需要输入位置和变换矩阵(以及纹理坐标,但这些都相当简单)。

    同样的blog post you linked,在最后告诉你如何设置矩阵(also here)。又来了:

    Matrix projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1);
    Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);
    Matrix transformation = halfPixelOffset * projection;
    

    (注意:我不确定 Silverlight 是否真的需要半像素偏移来保持纹理对齐 (ref)。它可能确实需要。)

    棘手的一点是精灵的定位是在着色器之外,在 CPU 上完成的。以下是SpriteBatch 的操作顺序:

    • 从矩形中的四个顶点开始,左上角为 (0,0),右下角为纹理的 (width,height)
    • 按原点向后平移
    • 规模
    • 旋转
    • 按位置翻译

    这会将精灵顶点放置在“客户空间”中,然后转换矩阵将这些顶点从客户空间转换到投影空间(用于绘图)。

    我在ExEnSpriteBatch.InternalDraw 中的SpriteBatchOpenGL.cs)中提供了这种转换的高度内联版本,您可以轻松适应您的使用。

    【讨论】:

    • 感谢您提供了这个令人难以置信的彻底答案。这正是我一直在寻找的。问题解决了!另外:ExEn 非常很有趣。我一定会检查出来的。谢谢。
    • 哦,我只想做一个小笔记。从 Silverlight 5 (Toolkit) 开始,Silverlight 实际上确实 有一个 SpriteBatch。显然它只是不提供自己的顶点着色器。 “Microsoft.Xna.Framework.Content.dll 程序集将向 Silverlight 5 添加以下类:ContentManager、Model、SpriteFont 和 SpriteBatch”,来自 blogs.msdn.com/b/eternalcoding/archive/2011/10/04/…
    • 啊 - 太好了,感谢您的提醒。我不知道工具包。似乎填补了 SL5 的 XNA 实现中的许多空白。
    【解决方案2】:

    我今天遇到了这个问题,我想补充一点,您可以在顶点着色器本身中进行所有计算:

    float2 Viewport; //Set to viewport size from application code
    
    void SpriteVertexShader(inout float4 color    : COLOR0,
                           inout float2 texCoord : TEXCOORD0,
                           inout float4 position : POSITION0)
    {
       // Half pixel offset for correct texel centering.
       position.xy -= 0.5;
       // Viewport adjustment.
       position.xy = position.xy / Viewport;
       position.xy *= float2(2, -2);
       position.xy -= float2(1, -1);
    }
    

    (我没有写这个,归功于上面提到的article 中的 cmets)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-21
      • 1970-01-01
      相关资源
      最近更新 更多