什么是渲染精灵在DirectX 11最初步实践? [英] What is the best pratice to render sprites in DirectX 11?
问题描述
我目前正在习惯了DirectX API和我想知道什么是常用的方法来呈现一个精灵在DirectX 11(例如,一个俄罗斯方块克隆)。
有没有simmilar接口 ID3DX10Sprite
,如果不是,这将是通常的方法来绘制精灵在DirectX 11?
编辑:这是为我工作(投影的坐标计算可以做的更好)的HLSL code:
结构SpriteData
{
FLOAT2位置;
FLOAT2大小;
的float4颜色;
};
结构VSOUT
{
的float4位置:SV_POSITION;
的float4颜色:颜色;
};
cbuffer屏幕尺寸:寄存器(B0)
{
FLOAT2屏幕尺寸;
FLOAT2填充; // cbuffer必须至少有16个字节
}
StructuredBuffer< SpriteData> spriteData:寄存器(T0);
FLOAT2 GetVertexPosition(UINT VID)
{
[分支]开关(VID)
{
情况下0:
返回FLOAT2(0,0);
情况1:
返回FLOAT2(1,0);
案例2:
返回FLOAT2(0,1);
默认:
返回FLOAT2(1,1);
}
}
的float4 ComputePosition(FLOAT2 positionInScreenSpace,FLOAT2大小,FLOAT2 vertexPosition)
{
FLOAT2原点= FLOAT2(-1,1);
FLOAT2 vertexPositionInScreenSpace = positionInScreenSpace +(尺寸* vertexPosition);
返回的float4(origin.x +(vertexPositionInScreenSpace.x /(screenSize.x / 2)),origin.y - (vertexPositionInScreenSpace.y /(screenSize.y / 2)),1,1);
}
VSOUT VShader(UINT VID:SV_VertexID,UINT SIID:SV_InstanceID)
{
VSOUT输出;
output.color = spriteData [SIID]。颜色;
output.position = ComputePosition(spriteData [SIID] .position,spriteData [SIID] .size,GetVertexPosition(VID));
返回输出;
}
的float4 PShader(个float4位置:SV_POSITION,float4变量颜色:彩色):SV_TARGET
{
返回的颜色;
}
没有没有等效的。通常的方法是画一个三角形带形成四。
您可以利用实例化的,所以你只需要更新与精灵数据的缓冲器(X,以像素为单位的y屏幕位置,纹理的ID来获取在纹理阵列,缩放,旋转,层等),使用着色渲染所有的精灵在一个单一的绘制调用。
下面是一些HLSL花絮了我的头顶部:
// ------------------------------------ --------------------------------------------------
//着色器code雪碧渲染
// ------------------------------------------------ --------------------------------------
结构雪碧{
FLOAT2位置; // X,Y世界上的地位
浮旋转;
浮动缩放;
浮层; //如果你有精灵的多层(如背景精灵)
UINT textureId;
};
StructuredBuffer<雪碧> SpritesRO:寄存器(T0);
Texture2DArray<的float4> TextureSlices:注册(T1);
cbuffer cbRenderConstants:注册(B0)
{
矩阵g_mViewProjection;
//其他常量
};
结构VSSpriteOut
{
FLOAT3位置:SV_Position;
UINT textureId;
};
// ------------------------------------------------ -------------------------------------
//雪碧顶点着色器
// ------------------------------------------------ -------------------------------------
VSSpriteOut SpriteVS(UINT VID:SV_VertexID,UINT SIID:SV_InstanceID)
{
VSSpriteOut时间=(VSSpriteOut)0;
// VID是0,1,2或3个
//我们可以映射0到位置(0,0),1(0,1),2〜(1,0),3至(1,1)
//我们获取精灵实例数据的协议SIID
雪碧SDATA = SpritesRO [SIID]
//函数f计算屏幕空间的顶点位置
FLOAT3 POS = F(g_mViewProjection,VID,位置,旋转,缩放,层等)
Out.position = POS机;
Out.textureId = sdata.textureId;
返回输出;
}
// ------------------------------------------------ -------------------------------------
//雪碧像素着色器
// ------------------------------------------------ -------------------------------------
的float4 SpritePS(VSSpriteOut中):SV_Target
{
//使用In.textureId获取正确的纹理切片纹理数组
返回的颜色;
}
I am currently trying to get used to the DirectX API and I am wondering what is the usual approach to render a sprite in DirectX 11 (e.g. for a tetris clone).
Is there a simmilar interface as ID3DX10Sprite
, and if not, which would be the usual method to draw sprites in DirectX 11?
Edit: Here is the HLSL code that worked for me (the computation of the projection coordinate could be done better):
struct SpriteData
{
float2 position;
float2 size;
float4 color;
};
struct VSOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
cbuffer ScreenSize : register(b0)
{
float2 screenSize;
float2 padding; // cbuffer must have at least 16 bytes
}
StructuredBuffer<SpriteData> spriteData : register(t0);
float2 GetVertexPosition(uint VID)
{
[branch] switch(VID)
{
case 0:
return float2(0, 0);
case 1:
return float2(1, 0);
case 2:
return float2(0, 1);
default:
return float2(1, 1);
}
}
float4 ComputePosition(float2 positionInScreenSpace, float2 size, float2 vertexPosition)
{
float2 origin = float2(-1, 1);
float2 vertexPositionInScreenSpace = positionInScreenSpace + (size * vertexPosition);
return float4(origin.x + (vertexPositionInScreenSpace.x / (screenSize.x / 2)), origin.y - (vertexPositionInScreenSpace.y / (screenSize.y / 2)), 1, 1);
}
VSOut VShader(uint VID : SV_VertexID, uint SIID : SV_InstanceID)
{
VSOut output;
output.color = spriteData[SIID].color;
output.position = ComputePosition(spriteData[SIID].position, spriteData[SIID].size, GetVertexPosition(VID));
return output;
}
float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
No there isn't an equivalent. Usual method would be to draw a triangle strip forming a quad.
You could make use of instancing, so you just have to update a buffer with sprite data (x, y screen position in pixels, id of the texture to fetch in a texture array, scaling, rotation, layer, etc) and use shaders for rendering all sprites in one single draw call.
Here's some HLSL tidbits off the top of my head:
//--------------------------------------------------------------------------------------
// Shader code for Sprite Rendering
//--------------------------------------------------------------------------------------
struct Sprite {
float2 position; // x, y world position
float rotation;
float scaling;
float layer; // if you have multiple layers of sprites (e.g. background sprites)
uint textureId;
};
StructuredBuffer<Sprite> SpritesRO : register( t0 );
Texture2DArray<float4> TextureSlices : register (t1);
cbuffer cbRenderConstants : register( b0 )
{
matrix g_mViewProjection;
// other constants
};
struct VSSpriteOut
{
float3 position : SV_Position;
uint textureId;
};
//-------------------------------------------------------------------------------------
// Sprite Vertex Shader
//-------------------------------------------------------------------------------------
VSSpriteOut SpriteVS(uint VID : SV_VertexID, uint SIID : SV_InstanceID)
{
VSSpriteOut Out = (VSSpriteOut)0;
// VID is either 0, 1, 2 or 3
// We can map 0 to position (0,0), 1 to (0,1), 2 to (1,0), 3 to (1,1)
// We fetch the sprite instance data accord SIID
Sprite sdata = SpritesRO[SIID];
// function f computes screen space vertex position
float3 pos = f (g_mViewProjection, VID, position, rotation, scaling, layer etc)
Out.position = pos;
Out.textureId = sdata.textureId;
return Out;
}
//-------------------------------------------------------------------------------------
// Sprite Pixel Shader
//-------------------------------------------------------------------------------------
float4 SpritePS(VSSpriteOut In) : SV_Target
{
// use In.textureId to fetch the right texture slice in texture array
return color;
}
这篇关于什么是渲染精灵在DirectX 11最初步实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!