Commit c6fd504c authored by nadro's avatar nadro

- Improved COGLCoreTexture::lock method.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5177 dfc29bdd-3216-0410-991c-e03cc46cb475
parent e5b6e6af
......@@ -429,6 +429,25 @@ void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* d
*dB++ = A8R8G8B8toA1R5G5B5(*sB++);
}
void CColorConverter::convert_A8R8G8B8toA1B5G5R5(const void* sP, s32 sN, void* dP)
{
u8 * sB = (u8 *)sP;
u16* dB = (u16*)dP;
for (s32 x = 0; x < sN; ++x)
{
s32 r = sB[0] >> 3;
s32 g = sB[1] >> 3;
s32 b = sB[2] >> 3;
s32 a = sB[3] >> 3;
dB[0] = (a << 15) | (r << 10) | (g << 5) | (b);
sB += 4;
dB += 1;
}
}
void CColorConverter::convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
{
u8 * sB = (u8 *)sP;
......@@ -534,6 +553,18 @@ void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* d
}
void CColorConverter::convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP)
{
const u32* sB = (const u32*)sP;
u32* dB = (u32*)dP;
for (s32 x = 0; x < sN; ++x)
{
*dB++ = (*sB & 0xff00ff00) | ((*sB & 0x00ff0000) >> 16) | ((*sB & 0x000000ff) << 16);
++sB;
}
}
void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
{
u8 * sB = (u8 *)sP;
......
......@@ -67,6 +67,7 @@ public:
static void convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA1B5G5R5(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP);
......@@ -76,6 +77,7 @@ public:
static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP);
static void convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP);
static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP);
static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP);
......
......@@ -458,7 +458,12 @@ public:
}
}
// Shaders
// Shaders calls.
void getProgram(GLuint& programID) const
{
programID = ProgramID;
}
void setProgram(GLuint programID)
{
......@@ -471,6 +476,11 @@ public:
// Texture calls.
void getActiveTexture(GLenum& texture) const
{
texture = ActiveTexture;
}
void setActiveTexture(GLenum texture)
{
if (ActiveTexture != texture)
......@@ -482,6 +492,14 @@ public:
// Viewport calls.
void getViewport(GLint& viewportX, GLint& viewportY, GLsizei& viewportWidth, GLsizei& viewportHeight) const
{
viewportX = ViewportX;
viewportY = ViewportY;
viewportWidth = ViewportWidth;
viewportHeight = ViewportHeight;
}
void setViewport(GLint viewportX, GLint viewportY, GLsizei viewportWidth, GLsizei viewportHeight)
{
if (ViewportX != viewportX || ViewportY != viewportY || ViewportWidth != viewportWidth || ViewportHeight != viewportHeight)
......
......@@ -14,6 +14,7 @@
#include "ITexture.h"
#include "EDriverFeatures.h"
#include "os.h"
#include "CColorConverter.h"
namespace irr
{
......@@ -44,7 +45,7 @@ public:
};
COGLCoreTexture(const io::path& name, const core::array<IImage*>& image, TOGLDriver* driver) : ITexture(name), Driver(driver), TextureType(GL_TEXTURE_2D),
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), LockReadOnly(false), LockImage(0), LockLevel(0), KeepImage(true),
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), LockReadOnly(false), LockImage(0), LockLevel(0), KeepImage(false),
AutoGenerateMipMaps(false)
{
_IRR_DEBUG_BREAK_IF(image.size() == 0)
......@@ -158,11 +159,11 @@ public:
if (TextureName)
glDeleteTextures(1, &TextureName);
for (u32 i = 0; i < Image.size(); ++i)
Image[i]->drop();
if (LockImage)
LockImage->drop();
for (u32 i = 0; i < Image.size(); ++i)
Image[i]->drop();
}
virtual void* lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel = 0) _IRR_OVERRIDE_
......@@ -175,9 +176,86 @@ public:
LockReadOnly |= (mode == ETLM_READ_ONLY);
LockLevel = mipmapLevel;
LockImage = Image[0];
if (LockImage)
return LockImage->getData();
return LockImage->getData();
if (KeepImage && mipmapLevel == 0)
{
LockImage = Image[0];
LockImage->grab();
}
else
{
const core::dimension2d<u32> lockImageSize(Size.Width >> mipmapLevel, Size.Height >> mipmapLevel);
LockImage = Driver->createImage(ColorFormat, lockImageSize);
if (LockImage && mode != ETLM_WRITE_ONLY)
{
COGLCoreTexture* tmpTexture = new COGLCoreTexture("OGL_CORE_LOCK_TEXTURE", lockImageSize, ColorFormat, Driver);
GLuint tmpFBO = 0;
Driver->irrGlGenFramebuffers(1, &tmpFBO);
GLint prevViewportX = 0;
GLint prevViewportY = 0;
GLsizei prevViewportWidth = 0;
GLsizei prevViewportHeight = 0;
Driver->getCacheHandler()->getViewport(prevViewportX, prevViewportY, prevViewportWidth, prevViewportHeight);
Driver->getCacheHandler()->setViewport(0, 0, lockImageSize.Width, lockImageSize.Height);
GLuint prevFBO = 0;
Driver->getCacheHandler()->getFBO(prevFBO);
Driver->getCacheHandler()->setFBO(tmpFBO);
Driver->irrGlFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmpTexture->getOpenGLTextureName(), 0);
Driver->draw2DImage(this, true);
IImage* tmpImage = Driver->createImage(ECF_A8R8G8B8, lockImageSize);
glReadPixels(0, 0, lockImageSize.Width, lockImageSize.Height, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->getData());
Driver->getCacheHandler()->setFBO(prevFBO);
Driver->getCacheHandler()->setViewport(prevViewportX, prevViewportY, prevViewportWidth, prevViewportHeight);
Driver->irrGlDeleteFramebuffers(1, &tmpFBO);
delete tmpTexture;
void* src = tmpImage->getData();
void* dest = LockImage->getData();
bool passed = true;
switch (ColorFormat)
{
case ECF_A1R5G5B5:
CColorConverter::convert_A8R8G8B8toA1B5G5R5(src, tmpImage->getDimension().getArea(), dest);
break;
case ECF_R5G6B5:
CColorConverter::convert_A8R8G8B8toR5G6B5(src, tmpImage->getDimension().getArea(), dest);
break;
case ECF_R8G8B8:
CColorConverter::convert_A8R8G8B8toB8G8R8(src, tmpImage->getDimension().getArea(), dest);
break;
case ECF_A8R8G8B8:
CColorConverter::convert_A8R8G8B8toA8B8G8R8(src, tmpImage->getDimension().getArea(), dest);
break;
default:
passed = false;
break;
}
tmpImage->drop();
if (!passed)
{
LockImage->drop();
LockImage = 0;
}
}
}
return (LockImage) ? LockImage->getData() : 0;
}
virtual void unlock() _IRR_OVERRIDE_
......@@ -198,8 +276,7 @@ public:
regenerateMipMapLevels(LockImage->getMipMapsData());
}
if (!KeepImage || LockLevel != 0)
LockImage->drop();
LockImage->drop();
LockReadOnly = false;
LockImage = 0;
......
......@@ -1826,172 +1826,9 @@ void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCo
}
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired.
void COpenGLDriver::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;
const u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
const core::dimension2d<u32>& ss = texture->getOriginalSize();
const f32 invW = 1.f / static_cast<f32>(ss.Width);
const f32 invH = 1.f / static_cast<f32>(ss.Height);
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
disableTextures(1);
if (!CacheHandler->getTextureCache().set(0, texture))
return;
setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
Quad2DVertices[0].Color = color;
Quad2DVertices[1].Color = color;
Quad2DVertices[2].Color = color;
Quad2DVertices[3].Color = color;
if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra])
getColorBuffer(Quad2DVertices, 4, EVT_STANDARD);
CacheHandler->setClientState(true, false, true, true);
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].TCoords);
glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Pos);
#ifdef GL_BGRA
const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4;
#else
const GLint colorSize=4;
#endif
if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Color);
else
{
_IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0);
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
}
for (u32 i=0; i<drawCount; ++i)
{
if (!sourceRects[i].isValid())
continue;
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)
continue;
sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
targetPos.X = clipRect->UpperLeftCorner.X;
}
if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
if (sourceSize.Width <= 0)
continue;
}
if (targetPos.Y < clipRect->UpperLeftCorner.Y)
{
sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
if (sourceSize.Height <= 0)
continue;
sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
targetPos.Y = clipRect->UpperLeftCorner.Y;
}
if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
if (sourceSize.Height <= 0)
continue;
}
}
// clip these coordinates
if (targetPos.X<0)
{
sourceSize.Width += targetPos.X;
if (sourceSize.Width <= 0)
continue;
sourcePos.X -= targetPos.X;
targetPos.X = 0;
}
if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
if (sourceSize.Width <= 0)
continue;
}
if (targetPos.Y<0)
{
sourceSize.Height += targetPos.Y;
if (sourceSize.Height <= 0)
continue;
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)
continue;
}
// ok, we've clipped everything.
// now draw it.
const core::rect<f32> tcoords(
sourcePos.X * invW,
sourcePos.Y * invH,
(sourcePos.X + sourceSize.Width) * invW,
(sourcePos.Y + sourceSize.Height) * invH);
const core::rect<s32> poss(targetPos, sourceSize);
Quad2DVertices[0].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[1].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[2].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f);
Quad2DVertices[3].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f);
Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
}
}
//! draws a 2d image, using a color and the alpha channel of the texture if
//! desired. The image is drawn at pos, clipped against clipRect (if != 0).
//! Only the subtexture defined by sourceRect is used.
void COpenGLDriver::draw2DImage(const video::ITexture* texture,
const core::position2d<s32>& pos,
const core::rect<s32>& sourceRect,
const core::rect<s32>* clipRect, SColor color,
bool useAlphaChannelOfTexture)
void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect, SColor color,
bool useAlphaChannelOfTexture)
{
if (!texture)
return;
......@@ -1999,7 +1836,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
if (!sourceRect.isValid())
return;
core::position2d<s32> targetPos(pos);
core::position2d<s32> targetPos(destPos);
core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner);
// This needs to be signed as it may go negative.
core::dimension2d<s32> sourceSize(sourceRect.getSize());
......@@ -2071,7 +1908,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
targetPos.Y = 0;
}
if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
if (targetPos.Y + sourceSize.Height >(s32)renderTargetSize.Height)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
if (sourceSize.Height <= 0)
......@@ -2085,10 +1922,10 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
const f32 invW = 1.f / static_cast<f32>(ss.Width);
const f32 invH = 1.f / static_cast<f32>(ss.Height);
const core::rect<f32> tcoords(
sourcePos.X * invW,
sourcePos.Y * invH,
(sourcePos.X + sourceSize.Width) * invW,
(sourcePos.Y + sourceSize.Height) * invH);
sourcePos.X * invW,
sourcePos.Y * invH,
(sourcePos.X + sourceSize.Width) * invW,
(sourcePos.Y + sourceSize.Height) * invH);
const core::rect<s32> poss(targetPos, sourceSize);
......@@ -2121,15 +1958,15 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Pos);
#ifdef GL_BGRA
const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4;
const GLint colorSize = (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) ? GL_BGRA : 4;
#else
const GLint colorSize=4;
const GLint colorSize = 4;
#endif
if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Color);
else
{
_IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0);
_IRR_DEBUG_BREAK_IF(ColorBuffer.size() == 0);
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
}
......@@ -2137,10 +1974,9 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture,
}
//! The same, but with a four element array of colors, one for each vertex
void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor* const colors, bool useAlphaChannelOfTexture)
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor* const colors, bool useAlphaChannelOfTexture)
{
if (!texture)
return;
......@@ -2149,10 +1985,10 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
const f32 invW = 1.f / static_cast<f32>(ss.Width);
const f32 invH = 1.f / static_cast<f32>(ss.Height);
const core::rect<f32> tcoords(
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
const video::SColor temp[4] =
{
......@@ -2168,8 +2004,8 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
if (!CacheHandler->getTextureCache().set(0, texture))
return;
setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 ||
useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255,
true, useAlphaChannelOfTexture);
useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255,
true, useAlphaChannelOfTexture);
if (clipRect)
{
......@@ -2178,7 +2014,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y,
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
......@@ -2206,15 +2042,15 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Pos);
#ifdef GL_BGRA
const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4;
const GLint colorSize = (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) ? GL_BGRA : 4;
#else
const GLint colorSize=4;
const GLint colorSize = 4;
#endif
if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Color);
else
{
_IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0);
_IRR_DEBUG_BREAK_IF(ColorBuffer.size() == 0);
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
}
......@@ -2225,6 +2061,201 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
}
void COpenGLDriver::draw2DImage(const video::ITexture* texture, bool flip)
{
if (!texture || !CacheHandler->getTextureCache().set(0, texture))
return;
disableTextures(1);
setRenderStates2DMode(false, true, true);
CacheHandler->setMatrixMode(GL_PROJECTION);
glLoadIdentity();
CacheHandler->setMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Transformation3DChanged = true;
Quad2DVertices[0].Pos = core::vector3df(-1.f, 1.f, 0.f);
Quad2DVertices[1].Pos = core::vector3df(1.f, 1.f, 0.f);
Quad2DVertices[2].Pos = core::vector3df(1.f, -1.f, 0.f);
Quad2DVertices[3].Pos = core::vector3df(-1.f, -1.f, 0.f);
f32 modificator = (flip) ? 1.f : 0.f;
Quad2DVertices[0].TCoords = core::vector2df(0.f, 0.f + modificator);
Quad2DVertices[1].TCoords = core::vector2df(1.f, 0.f + modificator);
Quad2DVertices[2].TCoords = core::vector2df(1.f, 1.f - modificator);
Quad2DVertices[3].TCoords = core::vector2df(0.f, 1.f - modificator);
CacheHandler->setClientState(true, false, false, true);
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].TCoords);
glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Pos);
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
}
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired.
void COpenGLDriver::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;
const u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
const core::dimension2d<u32>& ss = texture->getOriginalSize();
const f32 invW = 1.f / static_cast<f32>(ss.Width);
const f32 invH = 1.f / static_cast<f32>(ss.Height);
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
disableTextures(1);
if (!CacheHandler->getTextureCache().set(0, texture))
return;
setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
Quad2DVertices[0].Color = color;
Quad2DVertices[1].Color = color;
Quad2DVertices[2].Color = color;
Quad2DVertices[3].Color = color;
if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra])
getColorBuffer(Quad2DVertices, 4, EVT_STANDARD);
CacheHandler->setClientState(true, false, true, true);
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].TCoords);
glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Pos);
#ifdef GL_BGRA
const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4;
#else
const GLint colorSize=4;
#endif
if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(Quad2DVertices))[0].Color);
else
{
_IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0);
glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
}
for (u32 i=0; i<drawCount; ++i)
{
if (!sourceRects[i].isValid())
continue;
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)
continue;
sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
targetPos.X = clipRect->UpperLeftCorner.X;
}
if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
if (sourceSize.Width <= 0)
continue;
}
if (targetPos.Y < clipRect->UpperLeftCorner.Y)
{
sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
if (sourceSize.Height <= 0)
continue;
sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
targetPos.Y = clipRect->UpperLeftCorner.Y;
}
if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
if (sourceSize.Height <= 0)
continue;
}
}
// clip these coordinates
if (targetPos.X<0)
{
sourceSize.Width += targetPos.X;
if (sourceSize.Width <= 0)
continue;
sourcePos.X -= targetPos.X;
targetPos.X = 0;
}
if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
if (sourceSize.Width <= 0)
continue;
}
if (targetPos.Y<0)
{
sourceSize.Height += targetPos.Y;
if (sourceSize.Height <= 0)
continue;
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)
continue;
}
// ok, we've clipped everything.
// now draw it.
const core::rect<f32> tcoords(
sourcePos.X * invW,
sourcePos.Y * invH,
(sourcePos.X + sourceSize.Width) * invW,
(sourcePos.Y + sourceSize.Height) * invH);
const core::rect<s32> poss(targetPos, sourceSize);
Quad2DVertices[0].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[1].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[2].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f);
Quad2DVertices[3].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f);
Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, Quad2DIndices);
}
}
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired. The images are drawn beginning at pos and concatenated
//! in one line. All drawings are clipped against clipRect (if != 0).
......
......@@ -151,6 +151,16 @@ namespace video
//! \param material: Material to be used from now on.
virtual void setMaterial(const SMaterial& material) _IRR_OVERRIDE_;
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
SColor color = SColor(255, 255, 255, 255), bool useAlphaChannelOfTexture = false) _IRR_OVERRIDE_;
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) _IRR_OVERRIDE_;
virtual void draw2DImage(const video::ITexture* texture, bool flip);
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired.
void draw2DImageBatch(const video::ITexture* texture,
......@@ -160,11 +170,6 @@ namespace video
SColor color,
bool useAlphaChannelOfTexture) _IRR_OVERRIDE_;
//! draws an 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,
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_;
//! draws a set of 2d images, using a color and the alpha
/** channel of the texture if desired. The images are drawn
beginning at pos and concatenated in one line. All drawings
......@@ -190,11 +195,6 @@ namespace video
SColor color=SColor(255,255,255,255),
bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_;
//! Draws a part of the texture into the rectangle.
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_;
//! draw an 2d rectangle
virtual void draw2DRectangle(SColor color, const core::rect<s32>& pos,
const core::rect<s32>* clip = 0) _IRR_OVERRIDE_;
......
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