"...Irrlicht/svn:/svn.code.sf.net/p/irrlicht/code/trunk@4507" did not exist on "5f619ddfde3cafb82ec50598361428fb219c781a"
Commit 881bb195 authored by monstrobishi's avatar monstrobishi

- Added sprite bank draw batching. (Performance improvement is negligible...

 - Added sprite bank draw batching. (Performance improvement is negligible unfortunately, wait for sprite bank VBOs)

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2544 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 494e1a91
......@@ -8,6 +8,7 @@
#include "IReferenceCounted.h"
#include "SColor.h"
#include "rect.h"
#include "irrString.h"
namespace irr
{
......@@ -47,7 +48,7 @@ public:
\param vcenter: Specifies if the text should be centered vertically into the rectangle.
\param clip: Optional pointer to a rectangle against which the text will be clipped.
If the pointer is null, no clipping will be done. */
virtual void draw(const wchar_t* text, const core::rect<s32>& position,
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter=false, bool vcenter=false,
const core::rect<s32>* clip=0) = 0;
......
......@@ -67,6 +67,13 @@ public:
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0,
bool loop=true, bool center=false) = 0;
//! Draws a sprite batch in 2d using an array of positions and a color
virtual void draw2DSpriteBatch(const core::array<u32>& indices, const core::array<core::position2di>& pos,
const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0,
bool loop=true, bool center=false) = 0;
};
......
......@@ -670,7 +670,7 @@ namespace video
255, the image will be transparent.
\param useAlphaChannelOfTexture: If true, the alpha channel of
the texture is used to draw the image. */
virtual void draw2DImage(const video::ITexture* texture,
virtual void draw2DImageBatch(const video::ITexture* texture,
const core::position2d<s32>& pos,
const core::array<core::rect<s32> >& sourceRects,
const core::array<s32>& indices,
......@@ -679,6 +679,29 @@ namespace video
SColor color=SColor(255,255,255,255),
bool useAlphaChannelOfTexture=false) =0;
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
/** All drawings are clipped against clipRect (if != 0).
The subtextures are defined by the array of sourceRects and are
positioned using the array of positions.
\param texture Texture to be drawn.
\param pos Array of upper left 2d destinations where the images
will be drawn.
\param sourceRects Source rectangles of the image.
\param clipRect Pointer to rectangle on the screen where the
images are clipped to.
If this pointer is 0 then the image is not clipped.
\param color Color with which the image is drawn.
Note that the alpha component is used. If alpha is other than
255, the image will be transparent.
\param useAlphaChannelOfTexture: If true, the alpha channel of
the texture is used to draw the image. */
virtual void draw2DImageBatch(const video::ITexture* texture,
const core::array<core::position2d<s32> >& positions,
const core::array<core::rect<s32> >& sourceRects,
const core::rect<s32>* clipRect=0,
SColor color=SColor(255,255,255,255),
bool useAlphaChannelOfTexture=false) =0;
//! Draws a part of the texture into the rectangle. Note that colors must be an array of 4 colors if used.
/** Suggested and first implemented by zola.
\param texture The texture to draw from
......
......@@ -33,7 +33,8 @@ CD3D9Driver::CD3D9Driver(const core::dimension2d<u32>& screenSize, HWND window,
WindowId(0), SceneSourceRect(0),
LastVertexType((video::E_VERTEX_TYPE)-1), MaxTextureUnits(0), MaxUserClipPlanes(0),
MaxLightDistance(0.f), LastSetLight(-1), ColorFormat(ECF_A8R8G8B8), DeviceLost(false),
Fullscreen(fullscreen), DriverWasReset(true), AlphaToCoverageSupport(false)
Fullscreen(fullscreen), DriverWasReset(true), AlphaToCoverageSupport(false),
Cached2DModeSignature(0)
{
#ifdef _DEBUG
setDebugName("CD3D9Driver");
......@@ -1307,6 +1308,148 @@ void CD3D9Driver::draw2DImage(const video::ITexture* texture,
}
void CD3D9Driver::draw2DImageBatch(const video::ITexture* texture,
const core::array<core::position2d<s32> >& positions,
const core::array<core::rect<s32> >& sourceRects,
const core::rect<s32>* clipRect,
SColor color,
bool useAlphaChannelOfTexture)
{
if (!texture)
return;
if (!setActiveTexture(0, const_cast<video::ITexture*>(texture)))
return;
const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
core::array<S3DVertex> vtx(drawCount * 4);
core::array<u16> indices(drawCount * 6);
for(u32 i = 0;i < drawCount;i++)
{
core::position2d<s32> targetPos = positions[i];
core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;
// This needs to be signed as it may go negative.
core::dimension2d<s32> sourceSize(sourceRects[i].getSize());
if (clipRect)
{
if (targetPos.X < clipRect->UpperLeftCorner.X)
{
sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
if (sourceSize.Width <= 0)
return;
sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
targetPos.X = clipRect->UpperLeftCorner.X;
}
if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
if (sourceSize.Width <= 0)
return;
}
if (targetPos.Y < clipRect->UpperLeftCorner.Y)
{
sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
if (sourceSize.Height <= 0)
return;
sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
targetPos.Y = clipRect->UpperLeftCorner.Y;
}
if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
if (sourceSize.Height <= 0)
return;
}
}
// clip these coordinates
if (targetPos.X<0)
{
sourceSize.Width += targetPos.X;
if (sourceSize.Width <= 0)
return;
sourcePos.X -= targetPos.X;
targetPos.X = 0;
}
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
if (sourceSize.Width <= 0)
return;
}
if (targetPos.Y<0)
{
sourceSize.Height += targetPos.Y;
if (sourceSize.Height <= 0)
return;
sourcePos.Y -= targetPos.Y;
targetPos.Y = 0;
}
if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
if (sourceSize.Height <= 0)
return;
}
// ok, we've clipped everything.
// now draw it.
core::rect<f32> tcoords;
tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
const core::rect<s32> poss(targetPos, sourceSize);
setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));
vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));
vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));
vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
0.0f, 0.0f, 0.0f, color,
tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));
indices.push_back(0+i*4);
indices.push_back(1+i*4);
indices.push_back(2+i*4);
indices.push_back(0+i*4);
indices.push_back(2+i*4);
indices.push_back(3+i*4);
}
setVertexShader(EVT_STANDARD);
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vtx.size(), indices.size() / 3, indices.pointer(),
D3DFMT_INDEX16,vtx.pointer(), sizeof(S3DVertex));
}
//! draws a 2d image, using a color and the alpha channel of the texture if
//! desired. The image is drawn at pos and clipped against clipRect (if != 0).
void CD3D9Driver::draw2DImage(const video::ITexture* texture,
......@@ -2062,6 +2205,13 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan
Transformation3DChanged = false;
}
u32 current2DSignature = 0;
current2DSignature |= alpha ? EC2D_ALPHA : 0;
current2DSignature |= texture ? EC2D_TEXTURE : 0;
current2DSignature |= alphaChannel ? EC2D_ALPHA_CHANNEL : 0;
if(CurrentRenderMode != ERM_2D || current2DSignature != Cached2DModeSignature)
{
if (texture)
{
if (alphaChannel)
......@@ -2123,8 +2273,10 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
}
}
CurrentRenderMode = ERM_2D;
Cached2DModeSignature = current2DSignature;
}
......
......@@ -124,6 +124,14 @@ namespace video
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false);
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
virtual void draw2DImageBatch(const video::ITexture* texture,
const core::array<core::position2d<s32> >& positions,
const core::array<core::rect<s32> >& sourceRects,
const core::rect<s32>* clipRect=0,
SColor color=SColor(255,255,255,255),
bool useAlphaChannelOfTexture=false);
//!Draws an 2d rectangle with a gradient.
virtual void draw2DRectangle(const core::rect<s32>& pos,
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
......@@ -380,6 +388,15 @@ namespace video
f32 MaxLightDistance;
s32 LastSetLight;
enum E_CACHE_2D_ATTRIBUTES
{
EC2D_ALPHA = 0x1,
EC2D_TEXTURE = 0x2,
EC2D_ALPHA_CHANNEL = 0x4
};
u32 Cached2DModeSignature;
ECOLOR_FORMAT ColorFormat;
D3DFORMAT D3DColorFormat;
bool DeviceLost;
......
......@@ -460,7 +460,7 @@ core::dimension2d<u32> CGUIFont::getDimension(const wchar_t* text) const
}
//! draws some text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position,
void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color,
bool hcenter, bool vcenter, const core::rect<s32>* clip
)
......@@ -472,7 +472,7 @@ void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position,
core::position2d<s32> offset = position.UpperLeftCorner;
if (hcenter || vcenter || clip)
textDimension = getDimension(text);
textDimension = getDimension(text.c_str());
if (hcenter)
offset.X += (position.getWidth() - textDimension.Width) >> 1;
......@@ -488,15 +488,19 @@ void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position,
return;
}
wchar_t c;
while (( c = *text++))
core::array<u32> indices(text.size());
core::array<core::position2di> offsets(text.size());
for(u32 i = 0;i < text.size();i++)
{
wchar_t c = text[i];
bool lineBreak=false;
if ( c == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if ( *text == L'\n') // Windows breaks
++text;
if ( text[i + 1] == L'\n') // Windows breaks
c = text[++i];
}
else if ( c == L'\n') // Unix breaks
{
......@@ -510,7 +514,7 @@ void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position,
if ( hcenter )
{
core::dimension2d<u32> lineDim = getDimension(text);
core::dimension2d<u32> lineDim = getDimension(text.c_str());
offset.X += (position.getWidth() - lineDim.Width) >> 1;
}
continue;
......@@ -520,10 +524,15 @@ void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position,
offset.X += area.underhang;
if ( Invisible.findFirst ( c ) < 0 )
SpriteBank->draw2DSprite(area.spriteno, offset, clip, color);
offset.X += area.width + area.overhang + GlobalKerningWidth;
{
indices.push_back(area.spriteno);
offsets.push_back(offset);
}
offset.X += area.width + area.overhang + GlobalKerningWidth;
}
SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color);
}
......
......@@ -49,7 +49,7 @@ public:
bool load(io::IXMLReader* xml);
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const wchar_t* text, const core::rect<s32>& position,
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter=false,
bool vcenter=false, const core::rect<s32>* clip=0);
......
......@@ -136,6 +136,81 @@ void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos,
}
void CGUISpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,
const core::array<core::position2di>& pos,
const core::rect<s32>* clip,
const video::SColor& color,
u32 starttime, u32 currenttime,
bool loop, bool center)
{
const irr::u32 drawCount = core::min_<u32>(indices.size(), pos.size());
struct SDrawBatch
{
core::array<core::position2di> positions;
core::array<core::recti> sourceRects;
u32 textureNumber;
};
core::array<SDrawBatch> drawBatches(Textures.size());
for(u32 i = 0;i < Textures.size();i++)
{
drawBatches.push_back(SDrawBatch());
drawBatches[i].positions.reallocate(drawCount);
drawBatches[i].sourceRects.reallocate(drawCount);
}
for(u32 i = 0;i < drawCount;i++)
{
const u32 index = indices[i];
if (index >= Sprites.size() || Sprites[index].Frames.empty() )
continue;
// work out frame number
u32 frame = 0;
if (Sprites[index].frameTime)
{
u32 f = ((currenttime - starttime) / Sprites[index].frameTime);
if (loop)
frame = f % Sprites[index].Frames.size();
else
frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;
}
const u32 texNum = Sprites[index].Frames[frame].textureNumber;
SDrawBatch& currentBatch = drawBatches[texNum];
const u32 rn = Sprites[index].Frames[frame].rectNumber;
if (rn >= Rectangles.size())
return;
const core::rect<s32>& r = Rectangles[rn];
if (center)
{
core::position2di p = pos[i];
p -= r.getSize() / 2;
currentBatch.positions.push_back(p);
currentBatch.sourceRects.push_back(r);
}
else
{
currentBatch.positions.push_back(pos[i]);
currentBatch.sourceRects.push_back(r);
}
}
for(u32 i = 0;i < drawBatches.size();i++)
{
if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty())
Driver->draw2DImageBatch(Textures[i], drawBatches[i].positions,
drawBatches[i].sourceRects, clip, color, true);
}
}
} // namespace gui
} // namespace irr
......
......@@ -40,11 +40,18 @@ public:
virtual void addTexture(video::ITexture* texture);
virtual void setTexture(u32 index, video::ITexture* texture);
//! draws a sprite in 2d with position and color
//! Draws a sprite in 2d with position and color
virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false);
//! Draws a sprite batch in 2d using an array of positions and a color
virtual void draw2DSpriteBatch(const core::array<u32>& indices, const core::array<core::position2di>& pos,
const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0,
bool loop=true, bool center=false);
protected:
core::array<SGUISprite> Sprites;
......
......@@ -24,7 +24,7 @@ namespace gui
//! constructor
CGUITable::CGUITable(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip,
s32 id, const core::rect<s32>& rectangle, bool clip,
bool drawBack, bool moveOverSelect)
: IGUITable(environment, parent, id, rectangle), Font(0),
VerticalScrollBar(0), HorizontalScrollBar(0),
......
......@@ -27,7 +27,7 @@ namespace gui
public:
//! constructor
CGUITable(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip=true,
s32 id, const core::rect<s32>& rectangle, bool clip=true,
bool drawBack=false, bool moveOverSelect=true);
//! destructor
......
......@@ -689,7 +689,7 @@ void CNullDriver::draw2DImage(const video::ITexture* texture, const core::positi
//! in one line. All drawings are clipped against clipRect (if != 0).
//! The subtextures are defined by the array of sourceRects and are chosen
//! by the indices given.
void CNullDriver::draw2DImage(const video::ITexture* texture,
void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
const core::position2d<s32>& pos,
const core::array<core::rect<s32> >& sourceRects,
const core::array<s32>& indices,
......@@ -708,6 +708,23 @@ void CNullDriver::draw2DImage(const video::ITexture* texture,
}
}
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired.
void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
const core::array<core::position2d<s32> >& positions,
const core::array<core::rect<s32> >& sourceRects,
const core::rect<s32>* clipRect,
SColor color,
bool useAlphaChannelOfTexture)
{
const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
for (u32 i=0; i<drawCount; ++i)
{
draw2DImage(texture, positions[i], sourceRects[i],
clipRect, color, useAlphaChannelOfTexture);
}
}
//! Draws a part of the texture into the rectangle.
......
......@@ -166,7 +166,7 @@ namespace video
Note that the alpha component is used: If alpha is other than 255, the image will be transparent.
\param useAlphaChannelOfTexture: If true, the alpha channel of the texture is
used to draw the image. */
virtual void draw2DImage(const video::ITexture* texture,
virtual void draw2DImageBatch(const video::ITexture* texture,
const core::position2d<s32>& pos,
const core::array<core::rect<s32> >& sourceRects,
const core::array<s32>& indices,
......@@ -175,6 +175,29 @@ namespace video
SColor color=SColor(255,255,255,255),
bool useAlphaChannelOfTexture=false);
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
/** All drawings are clipped against clipRect (if != 0).
The subtextures are defined by the array of sourceRects and are
positioned using the array of positions.
\param texture Texture to be drawn.
\param pos Array of upper left 2d destinations where the images
will be drawn.
\param sourceRects Source rectangles of the image.
\param clipRect Pointer to rectangle on the screen where the
images are clipped to.
If this pointer is 0 then the image is not clipped.
\param color Color with which the image is drawn.
Note that the alpha component is used. If alpha is other than
255, the image will be transparent.
\param useAlphaChannelOfTexture: If true, the alpha channel of
the texture is used to draw the image. */
virtual void draw2DImageBatch(const video::ITexture* texture,
const core::array<core::position2d<s32> >& positions,
const core::array<core::rect<s32> >& sourceRects,
const core::rect<s32>* clipRect=0,
SColor color=SColor(255,255,255,255),
bool useAlphaChannelOfTexture=false);
//! Draws a 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment