首先,为什么Silverlight 5中的SilverlightEffect
(。slfx文件)需要顶点着色器?我正在尝试将简单的2D XNA游戏移植到Silverlight 5 RC,我想使用基本的像素着色器。这个着色器在XNA for Windows和Xbox中运行良好,但我不能用Silverlight作为SilverlightEffect进行编译。
Silverlight Toolkit的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游戏?
任何着色器专业人员都可以帮忙吗?谢谢!
答案 0 :(得分:3)
在XNA中,SpriteBatch
提供了自己的顶点着色器。由于Silverlight 5中没有SpriteBatch
,因此您必须提供自己的。{/ p>
您可能希望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
所做的顺序:
这将精灵顶点放在“客户空间”中,然后变换矩阵将那些顶点从客户空间转换为投影空间(用于绘图)。
我在ExEn(SpriteBatch.InternalDraw
中的SpriteBatchOpenGL.cs
)中有一个高度内联的转换版本,您可以轻松调整以供您使用。
答案 1 :(得分:1)
我今天遇到了这个问题,我想补充说你可以在顶点着色器本身进行所有计算:
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中的评论