|
bool slD3D11ShaderSprite::init(){
const char* text =
"Texture2D tex2d_1;\n"
"SamplerState tex2D_sampler_1;\n"
"struct VSIn{\n"
" float3 position : POSITION;\n"
" float2 uv : TEXCOORD;\n"
"};\n"
"cbuffer cbElement{\n"
" double4x4 W;\n"
" double4x4 V;\n"
" double4x4 P;\n"
" double4x4 Vi;\n"
" double4 Corners;\n"
" float4 Color1;\n"
" float4 UVs;\n"
" float alphaDiscard;\n"
" float padding[3];\n"
"};\n"
"struct VSOut{\n"
" float4 pos : SV_POSITION;\n"
" float2 uv : TEXCOORD0;\n"
" float4 color : COLOR0;\n"
"};\n"
"struct PSOut{\n"
" float4 color : SV_Target;\n"
"};\n"
"VSOut VSMain(VSIn input){\n"
" VSOut output;\n"
" output.pos.xyz = input.position.xyz;\n"
" output.pos.w = 1.f;\n"
" output.uv = input.uv;\n"
" return output;\n"
"}\n"
"PSOut PSMain(VSOut input){\n"
" PSOut output;\n"
" output.color = saturate(tex2d_1.Sample(tex2D_sampler_1, input.uv) * input.color);\n"
" if(output.color.w < alphaDiscard) discard;\n"
" return output;\n"
"}\n"
"[maxvertexcount(4)]\n"
"void GSMain(point VSOut input[1], inout TriangleStream<VSOut> TriStream ){\n"
" VSOut Out;\n"
" double4x4 V2 = Vi;\n"
" V2._41 = 0.0;\n"
" V2._42 = 0.0;\n"
" V2._43 = 0.0;\n"
" V2._44 = 1.0;\n"
" V2._14 = 0.0;\n"
" V2._24 = 0.0;\n"
" V2._34 = 0.0;\n"
" double4 v1 = double4(Corners.x, Corners.y, 0.0, 1.0);\n"
" double4 v2 = double4(Corners.z, Corners.w, 0.0, 1.0);\n"
" Out.pos = mul(W, mul(V2,double4(v2.x, v2.y, 0.0, 1.0)));\n"
" Out.pos = mul(V, Out.pos);\n"
" Out.pos = mul(P, Out.pos);\n"
" Out.uv = float2(UVs.x,UVs.y);\n" // 2
" Out.color = Color1;\n"
" TriStream.Append(Out);\n"
" Out.pos = mul(W, mul(V2,double4(v1.x, v2.y, 0.0,1.0)));\n"
" Out.pos = mul(V, Out.pos);\n"
" Out.pos = mul(P, Out.pos);\n"
" Out.uv = float2(UVs.z,UVs.y);\n" // 1
" Out.color = Color1;\n"
" TriStream.Append(Out);\n"
" Out.pos = mul(W, mul(V2,double4(v2.x, v1.y, 0.0, 1.0)));\n"
" Out.pos = mul(V, Out.pos);\n"
" Out.pos = mul(P, Out.pos);\n"
" Out.uv = float2(UVs.x,UVs.w);\n"// 4
" Out.color = Color1;\n"
" TriStream.Append(Out);\n"
" Out.pos = mul(W, mul(V2,double4(v1.x, v1.y, 0.0, 1.0)));\n"
" Out.pos = mul(V, Out.pos);\n"
" Out.pos = mul(P, Out.pos);\n"
" Out.uv = float2(UVs.z,UVs.w);\n" // 3
" Out.color = Color1;\n"
" TriStream.Append(Out);\n"
" TriStream.RestartStrip();\n"
"}\n";
if (!m_gs->createShaders(
"vs_5_0",
"ps_5_0",
text,
text,
"VSMain",
"PSMain",
slMeshVertexType::Null,
&this->m_vShader,
&this->m_pShader,
&this->m_vLayout))
return false;
if (!m_gs->createGeometryShaders("gs_5_0", text, "GSMain", &m_gShader))
return false;
if (!m_gs->createConstantBuffer(sizeof(cbElement), &m_cbElement))
return false;
return true;
}
Sprite
class slSpriteState;
// just rectangle with texture
// it can rotate using matrix
// this is not GUI element
class slSprite : public slSceneObject
{
slTexture* m_texture = 0;
slVec4f m_rect;
slArray<slSpriteState*> m_states;
slSpriteState* m_activeState = 0;
slColor m_color = ColorWhite;
public:
slSprite();
virtual ~slSprite();
slColor& GetColor() { return m_color; }
slTexture* GetTexture() { return m_texture; }
void SetTexture(slTexture* t) { m_texture = t; }
void SetSize(float x, float y);
enum class TransparentType
{
Discard,
Blending
}
m_transparentType = TransparentType::Discard;
float m_alphaDiscard = 0.5f;
slVec4f& GetRect() { return m_rect; }
slSpriteState* GetActiveState() { return m_activeState; }
void SetActiveState(slSpriteState* s) { m_activeState = s; }
slSpriteState* CreateNewState();
void AnimationUpdate(float dt);
};
class slSpriteState
{
friend class slSprite;
slSprite* m_sprite = 0;
public:
slSpriteState() {}
~slSpriteState(){}
slString m_name;
slArray<slVec4f> m_frames; // UVs
uint32_t m_frameCurrent = 0;
uint32_t m_frameNum = 0;
bool m_invertX = false;
bool m_invertY = false;
bool m_isAnimation = false;
float m_fps = 1.f;
float m_fpsTime = 1.f;
bool m_play = true;
bool m_loop = true;
float m_updateTimer = 0.f;
void SetFPS(float newFPS) {
if (newFPS < 1.f)
newFPS = 1.f;
m_fps = newFPS;
m_fpsTime = 1.f / newFPS;
}
void AddFrame(const slVec4f& rect);
void AnimationUpdate(float dt);
void CreateAnimation(uint32_t numFrames, const slVec2f& frameSize, const slVec2f& startPosition);
};
Implementation
slSprite::slSprite()
{
}
slSprite::~slSprite()
{
for (size_t i = 0; i < m_states.m_size; ++i)
{
slDestroy(m_states.m_data[i]);
}
}
void slSprite::SetSize(float x, float y)
{
float hx = x * 0.5f;
float hy = y * 0.5f;
m_rect.set(-hx, -hy, hx, hy);
}
slSpriteState* slSprite::CreateNewState()
{
slSpriteState* state = slCreate<slSpriteState>();
state->m_sprite = this;
m_states.push_back(state);
return state;
}
void slSprite::AnimationUpdate(float dt)
{
SL_ASSERT_ST(m_activeState);
m_activeState->AnimationUpdate(dt);
}
void slSpriteState::AddFrame(const slVec4f& rect)
{
slVec2f textureSize((float)m_sprite->GetTexture()->GetInfo().m_imageInfo.m_width,
(float)m_sprite->GetTexture()->GetInfo().m_imageInfo.m_height);
float xMulFactor = 1.f / (float)textureSize.x;
float yMulFactor = 1.f / (float)textureSize.y;
slVec4f newFrame;
newFrame.x = rect.x * xMulFactor;
newFrame.y = (rect.y * yMulFactor);
newFrame.z = (rect.z + 1.f) * xMulFactor;
newFrame.w = (rect.w + 1.f) * yMulFactor;
this->m_frames.push_back(newFrame);
m_frameNum = m_frames.size();
}
void slSpriteState::AnimationUpdate(float dt)
{
if (m_isAnimation && m_play)
{
m_updateTimer += dt;
if (m_updateTimer >= m_fpsTime)
{
m_updateTimer = 0.f;
++m_frameCurrent;
if (m_frameCurrent == m_frameNum)
{
if (m_loop)
{
m_frameCurrent = 0;
}
else
{
m_play = false;
}
}
}
}
}
void slSpriteState::CreateAnimation(uint32_t numFrames, const slVec2f& frameSize, const slVec2f& startPosition)
{
slVec2f textureSize((float)m_sprite->GetTexture()->GetInfo().m_imageInfo.m_width,
(float)m_sprite->GetTexture()->GetInfo().m_imageInfo.m_height);
slVec2f sp = startPosition;
for (uint32_t i = 0; i < numFrames; ++i)
{
slVec4f f;
f.x = sp.x;
f.y = sp.y;
f.z = f.x + frameSize.x - 1.f;
f.w = f.y + frameSize.y - 1.f;
if (f.z > textureSize.x)
{
sp.x = 0.f;
sp.y += frameSize.y;
f.x = sp.x;
f.y = sp.y;
f.z = f.x + frameSize.x - 1.f;
f.w = f.y + frameSize.y - 1.f;
}
AddFrame(f);
m_isAnimation = true;
sp.x += frameSize.x;
}
}
Draw it
void slGSD3D11::DrawSprite(slSprite* s)
{
SL_ASSERT_ST(s);
SL_ASSERT_ST(s->GetTexture());
SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::ViewInvert));
SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::World));
SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::View));
SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::Projection));
m_shaderSprite->m_cbDataElement.Color1 = s->GetColor();
m_shaderSprite->m_cbDataElement.Corners = s->GetRect();
auto state = s->GetActiveState();
if (state)
{
if (state->m_frames.m_size)
m_shaderSprite->m_cbDataElement.UVs = state->m_frames.m_data[state->m_frameCurrent];
else
goto default_uv;
}
else
{
default_uv:;
m_shaderSprite->m_cbDataElement.UVs.x = 0.f;
m_shaderSprite->m_cbDataElement.UVs.y = 0.f;
m_shaderSprite->m_cbDataElement.UVs.z = 1.f;
m_shaderSprite->m_cbDataElement.UVs.w = 1.f;
}
m_shaderSprite->m_cbDataElement.alphaDiscard = s->m_alphaDiscard;
m_shaderSprite->m_cbDataElement.Vi = *slFramework::GetMatrix(slMatrixType::ViewInvert);
m_shaderSprite->m_cbDataElement.W = *slFramework::GetMatrix(slMatrixType::World);
m_shaderSprite->m_cbDataElement.V = *slFramework::GetMatrix(slMatrixType::View);
m_shaderSprite->m_cbDataElement.P = *slFramework::GetMatrix(slMatrixType::Projection);
m_shaderSprite->SetOnElement(dynamic_cast<slGSD3D11Texture*>(s->GetTexture()));
m_d3d11DevCon->Draw(1, 0);
}
Download
|
|