Merge revisions r5455:r5474 from trunk to ogl-es

Add color-mask fixes to ogles2 and webgl drivers.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@5475 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2017-06-07 15:20:59 +00:00
parent c3ed02c8d0
commit 56e72da4a7
15 changed files with 176 additions and 209 deletions

View File

@ -10,6 +10,8 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point)
--------------------------
Changes in 1.9 (not yet released)
- Lets the BSP loader find textures inserted with relative paths. Thx@ curaga for patch
- Slightly simplified ALLOC_STRATEGY_DOUBLE in arrays
- Add alternavive BoundingBox calculation for BillboardSceneNode which can take in a camera node. Thx @Seven and @JacKDuRdEn for bugreports.
- FPS camera now supports keyboard rotation.
- Base FPS-camera movement on last position of mouse instead of always center (works better on platforms where cursor-placement is not allowed)

View File

@ -220,7 +220,9 @@ void loadModel(const c8* fn)
return;
}
u32 then = Device->getTimer()->getRealTime();
scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() );
Device->getLogger()->log("Loading time (ms): ", core::stringc(Device->getTimer()->getRealTime() - then).c_str());
if (!m)
{
@ -323,7 +325,7 @@ void createToolBox()
}
/*
Function updateToolBox() is called each frame to update dynamic information in
Function updateToolBox() is called each frame to update dynamic information in
the toolbox.
*/
void updateToolBox()
@ -354,8 +356,8 @@ void updateToolBox()
void onKillFocus()
{
// Avoid that the FPS-camera continues moving when the user presses alt-tab while
// moving the camera.
// Avoid that the FPS-camera continues moving when the user presses alt-tab while
// moving the camera.
const core::list<scene::ISceneNodeAnimator*>& animators = Camera[1]->getAnimators();
core::list<irr::scene::ISceneNodeAnimator*>::ConstIterator iter = animators.begin();
while ( iter != animators.end() )
@ -524,11 +526,11 @@ public:
*/
bool OnKeyUp(irr::EKEY_CODE keyCode)
{
// Don't handle keys if we have a modal dialog open as it would lead
// Don't handle keys if we have a modal dialog open as it would lead
// to unexpected application behaviour for the user.
if ( hasModalDialog() )
return false;
if (keyCode == irr::KEY_ESCAPE)
{
if (Device)

View File

@ -856,6 +856,10 @@ namespace quake3
loadFile.append ( extension[g] );
}
texture = driver->findTexture( loadFile );
if ( texture )
break;
if ( fileSystem->existFile ( loadFile ) )
{
texture = driver->getTexture( loadFile );

View File

@ -1081,10 +1081,10 @@ namespace scene
//! Get scene nodes by type.
/** \param type: Type of scene node to find (ESNT_ANY will return all child nodes).
\param outNodes: array to be filled with results.
\param start: Scene node to start from. All children of this scene
node are searched. If null is specified, the root scene node is
taken. */
\param outNodes: results will be added to this array (outNodes is not cleared).
\param start: Scene node to start from. This node and all children of this scene
node are checked (recursively, so also children of children, etc). If null is specified,
the root scene node is taken as start-node. */
virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type,
core::array<scene::ISceneNode*>& outNodes,
ISceneNode* start=0) = 0;

View File

@ -22,12 +22,12 @@ class ITriangleSelector;
class IMeshBuffer;
//! Additional information about the triangle arrays returned by ITriangleSelector::getTriangles
/** ITriangleSelector are free to fill out this information fully, partly or ignore it.
/** ITriangleSelector are free to fill out this information fully, partly or ignore it.
Usually they will try to fill it when they can and set values to 0 otherwise.
*/
struct SCollisionTriangleRange
{
SCollisionTriangleRange()
SCollisionTriangleRange()
: RangeStart(0), RangeSize(0)
, Selector(0), SceneNode(0)
, MeshBuffer(0), MaterialIndex(0)
@ -42,10 +42,10 @@ struct SCollisionTriangleRange
return triangleIndex >= RangeStart && triangleIndex < RangeStart+RangeSize;
}
//! First index in the array for which this struct is valid
//! First index in the returned triangle array for which this struct is valid
irr::u32 RangeStart;
//! Number of elements in the array for which this struct is valid (starting with RangeStart)
//! Number of elements in the returned triangle array for which this struct is valid (starting with RangeStart)
irr::u32 RangeSize;
//! Real selector which contained those triangles (useful when working with MetaTriangleSelector)
@ -89,17 +89,17 @@ public:
into the array.
\param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer.
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer.
*/
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::matrix4* transform=0,
bool useNodeTransform=true,
s32& outTriangleCount, const core::matrix4* transform=0,
bool useNodeTransform=true,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo=0) const = 0;
//! Gets the triangles for one associated node which may lie within a specific bounding box.
@ -120,12 +120,12 @@ public:
will be written into the array.
\param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::aabbox3d<f32>& box,
@ -150,12 +150,12 @@ public:
will be written into the array.
\param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that
\param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which
One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line,
@ -179,7 +179,7 @@ public:
//! Get scene node associated with a given triangle.
/** With CMetaTriangleSelector-selectors it's possible to find out a node
belonging to a certain triangle index.
belonging to a certain triangle index.
NOTE: triangleIndex has nothing to do with the order of triangles returned by getTriangles functions!
So you can _not_ use this function to find out anything about to which node returned triangles belong.
Use STriangleCollisionInfo struct for that.

View File

@ -108,12 +108,12 @@ public:
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#endif
//! defines an allocation strategy
//! defines an allocation strategy (used only by irr::array so far)
enum eAllocStrategy
{
ALLOC_STRATEGY_SAFE = 0,
ALLOC_STRATEGY_DOUBLE = 1,
ALLOC_STRATEGY_SQRT = 2
ALLOC_STRATEGY_SAFE = 0, // increase size by 1
ALLOC_STRATEGY_DOUBLE = 1, // double size when under 500 elements, beyond that increase by 1/4th size. Plus a small constant.
ALLOC_STRATEGY_SQRT = 2 // not implemented
};

View File

@ -126,9 +126,7 @@ public:
//! Insert item into array at specified position.
/** Please use this only if you know what you are doing (possible
performance loss). The preferred method of adding elements should be
push_back().
/**
\param element: Element to be inserted
\param index: Where position to insert the new element. */
void insert(const T& element, u32 index=0)
@ -147,8 +145,7 @@ public:
switch ( strategy )
{
case ALLOC_STRATEGY_DOUBLE:
newAlloc = used + 1 + (allocated < 500 ?
(allocated < 5 ? 5 : used) : used >> 2);
newAlloc = used + 5 + (allocated < 500 ? used : used >> 2);
break;
default:
case ALLOC_STRATEGY_SAFE:

View File

@ -243,7 +243,7 @@ namespace core
//! returns if a equals b, taking possible rounding errors into account
template <class T>
inline T equals(const T a, const T b, const T tolerance = roundingError<T>())
inline bool equals(const T a, const T b, const T tolerance = roundingError<T>())
{
return (a + tolerance >= b) && (a - tolerance <= b);
}

View File

@ -580,12 +580,14 @@ void CGUITabControl::draw()
core::rect<s32> frameRect(AbsoluteRect);
// some empty background as placeholder when there are no tabs
if (Tabs.empty())
driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
if (!font)
return;
// tab button bar can be above or below the tabs
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
frameRect.UpperLeftCorner.Y += 2;
@ -610,6 +612,7 @@ void CGUITabControl::draw()
//const wchar_t* activetext = 0;
CGUITab *activeTab = 0;
// Draw all tab-buttons except the active one
for (u32 i=CurrentScrollTabIndex; i<Tabs.size(); ++i)
{
// get Text
@ -636,6 +639,7 @@ void CGUITabControl::draw()
if ((s32)i == ActiveTab)
{
// for active button just remember values
left = frameRect.UpperLeftCorner.X;
right = frameRect.LowerRightCorner.X;
//activetext = text;
@ -653,7 +657,8 @@ void CGUITabControl::draw()
}
}
// draw active tab
// Draw active tab button
// Drawn later than other buttons because it draw over the buttons before/after it.
if (left != 0 && right != 0 && activeTab != 0)
{
// draw upper highlight frame
@ -683,7 +688,6 @@ void CGUITabControl::draw()
}
else
{
frameRect.UpperLeftCorner.X = left-2;
frameRect.LowerRightCorner.X = right+2;
frameRect.LowerRightCorner.Y += 2;
@ -707,24 +711,26 @@ void CGUITabControl::draw()
}
else
{
// No active tab
// Draw a line separating button bar from tab area
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
if ( VerticalAlignment == EGUIA_UPPERLEFT )
{
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
}
else
{
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = 1000;
tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
}
}
// drawing some border and background for the tab-area.
skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment);
// enable scrollcontrols on need

View File

@ -78,9 +78,9 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
const u32 WORD_BUFFER_LENGTH = 512;
core::array<core::vector3df> vertexBuffer;
core::array<core::vector3df> normalsBuffer;
core::array<core::vector2df> textureCoordBuffer;
core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > vertexBuffer(1000);
core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000);
core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000);
SObjMtl * currMtl = new SObjMtl();
Materials.push_back(currMtl);
@ -101,6 +101,10 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS);
bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES);
irr::u32 lineNr = 1; // only counts non-empty lines, still useful in debugging to locate errors
core::array<int> faceCorners;
faceCorners.reallocate(32); // should be large enough
const core::stringc TAG_OFF = "off";
while(bufPtr != bufEnd)
{
switch(bufPtr[0])
@ -173,7 +177,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
#ifdef _IRR_DEBUG_OBJ_LOADER_
os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG);
#endif
if (core::stringc("off")==smooth)
if (TAG_OFF==smooth)
smoothingGroup=0;
else
smoothingGroup=core::strtoul10(smooth);
@ -215,8 +219,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
const c8* linePtr = wordBuffer.c_str();
const c8* const endPtr = linePtr+wordBuffer.size();
core::array<int> faceCorners;
faceCorners.reallocate(32); // should be large enough
faceCorners.set_used(0); // fast clear
// read in all vertices
linePtr = goNextWord(linePtr, endPtr);
@ -279,8 +282,6 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
currMtl->Meshbuffer->Indices.push_back( faceCorners[i] );
currMtl->Meshbuffer->Indices.push_back( faceCorners[0] );
}
faceCorners.set_used(0); // fast clear
faceCorners.reallocate(32);
}
break;

View File

@ -1798,11 +1798,7 @@ COGLES2Driver::~COGLES2Driver()
}
// Color Mask
CacheHandler->setColorMask(
(material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE);
CacheHandler->setColorMask(material.ColorMask);
// Blend Equation
if (material.BlendOperation == EBO_NONE)
@ -2122,7 +2118,7 @@ COGLES2Driver::~COGLES2Driver()
if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY)))
{
CacheHandler->setColorMask(false, false, false, false);
CacheHandler->setColorMask(ECP_NONE);
glEnable(GL_STENCIL_TEST);
}
@ -2191,7 +2187,7 @@ COGLES2Driver::~COGLES2Driver()
setRenderStates2DMode(true, false, false);
CacheHandler->setDepthMask(false);
CacheHandler->setColorMask(true, true, true, true);
CacheHandler->setColorMask(ECP_ALL);
CacheHandler->setBlend(true);
CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -2447,10 +2443,15 @@ COGLES2Driver::~COGLES2Driver()
void COGLES2Driver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
{
GLbitfield mask = 0;
u8 colorMask = 0;
bool depthMask = false;
CacheHandler->getColorMask(colorMask);
CacheHandler->getDepthMask(depthMask);
if (flag & ECBF_COLOR)
{
CacheHandler->setColorMask(true, true, true, true);
CacheHandler->setColorMask(ECP_ALL);
const f32 inv = 1.0f / 255.0f;
glClearColor(color.getRed() * inv, color.getGreen() * inv,
@ -2474,6 +2475,9 @@ COGLES2Driver::~COGLES2Driver()
if (mask)
glClear(mask);
CacheHandler->setColorMask(colorMask);
CacheHandler->setDepthMask(depthMask);
}

View File

@ -170,10 +170,10 @@ class COpenGLCoreCacheHandler
public:
COpenGLCoreCacheHandler(TOpenGLDriver* driver) :
Driver(driver), TextureCache(STextureCache(this, Driver->getFeature().TextureUnit)), FrameBufferCount(0),
BlendEquation(0), BlendSourceRGB(0), BlendDestinationRGB(0), BlendSourceAlpha(0), BlendDestinationAlpha(0),
Blend(0), ColorMask(0), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true),
DepthTest(false), FrameBufferID(0), ProgramID(0), ActiveTexture(GL_TEXTURE0), ViewportX(0), ViewportY(0)
Driver(driver), TextureCache(STextureCache(this, Driver->getFeature().TextureUnit)), FrameBufferCount(0), BlendEquation(0), BlendSourceRGB(0),
BlendDestinationRGB(0), BlendSourceAlpha(0), BlendDestinationAlpha(0), Blend(0), BlendEquationInvalid(false), BlendFuncInvalid(false), BlendInvalid(false),
ColorMask(0), ColorMaskInvalid(false), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true), DepthTest(false), FrameBufferID(0),
ProgramID(0), ActiveTexture(GL_TEXTURE0), ViewportX(0), ViewportY(0)
{
const COpenGLCoreFeature& feature = Driver->getFeature();
@ -185,8 +185,7 @@ public:
BlendSourceAlpha = new GLenum[FrameBufferCount];
BlendDestinationAlpha = new GLenum[FrameBufferCount];
Blend = new bool[FrameBufferCount];
ColorMask = new bool[FrameBufferCount][4];
ColorMask = new u8[FrameBufferCount];
// Initial OpenGL values from specification.
@ -205,9 +204,7 @@ public:
BlendDestinationAlpha[i] = GL_ZERO;
Blend[i] = false;
for (u32 j = 0; j < 4; ++j)
ColorMask[i][j] = true;
ColorMask[i] = ECP_ALL;
}
glBlendFunc(GL_ONE, GL_ZERO);
@ -260,12 +257,14 @@ public:
void setBlendEquation(GLenum mode)
{
if (BlendEquation[0] != mode)
if (BlendEquation[0] != mode || BlendEquationInvalid)
{
Driver->irrGlBlendEquation(mode);
for (GLuint i = 0; i < FrameBufferCount; ++i)
BlendEquation[i] = mode;
BlendEquationInvalid = false;
}
}
@ -276,13 +275,15 @@ public:
Driver->irrGlBlendEquationIndexed(index, mode);
BlendEquation[index] = mode;
BlendEquationInvalid = true;
}
}
void setBlendFunc(GLenum source, GLenum destination)
{
if (BlendSourceRGB[0] != source || BlendDestinationRGB[0] != destination ||
BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination)
BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination ||
BlendFuncInvalid)
{
glBlendFunc(source, destination);
@ -293,6 +294,8 @@ public:
BlendSourceAlpha[i] = source;
BlendDestinationAlpha[i] = destination;
}
BlendFuncInvalid = false;
}
}
@ -301,7 +304,8 @@ public:
if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha)
{
if (BlendSourceRGB[0] != sourceRGB || BlendDestinationRGB[0] != destinationRGB ||
BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha)
BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha ||
BlendFuncInvalid)
{
Driver->irrGlBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha);
@ -312,6 +316,8 @@ public:
BlendSourceAlpha[i] = sourceAlpha;
BlendDestinationAlpha[i] = destinationAlpha;
}
BlendFuncInvalid = false;
}
}
else
@ -331,6 +337,7 @@ public:
BlendDestinationRGB[index] = destination;
BlendSourceAlpha[index] = source;
BlendDestinationAlpha[index] = destination;
BlendFuncInvalid = true;
}
}
@ -347,6 +354,7 @@ public:
BlendDestinationRGB[index] = destinationRGB;
BlendSourceAlpha[index] = sourceAlpha;
BlendDestinationAlpha[index] = destinationAlpha;
BlendFuncInvalid = true;
}
}
else
@ -357,7 +365,7 @@ public:
void setBlend(bool enable)
{
if (Blend[0] != enable)
if (Blend[0] != enable || BlendInvalid)
{
if (enable)
glEnable(GL_BLEND);
@ -366,6 +374,8 @@ public:
for (GLuint i = 0; i < FrameBufferCount; ++i)
Blend[i] = enable;
BlendInvalid = false;
}
}
@ -379,37 +389,38 @@ public:
Driver->irrGlDisableIndexed(GL_BLEND, index);
Blend[index] = enable;
BlendInvalid = true;
}
}
// Color Mask.
void setColorMask(bool red, bool green, bool blue, bool alpha)
void getColorMask(u8& mask)
{
if (ColorMask[0][0] != red || ColorMask[0][1] != green || ColorMask[0][2] != blue || ColorMask[0][3] != alpha)
mask = ColorMask[0];
}
void setColorMask(u8 mask)
{
if (ColorMask[0] != mask || ColorMaskInvalid)
{
glColorMask(red, green, blue, alpha);
glColorMask((mask & ECP_RED) ? GL_TRUE : GL_FALSE, (mask & ECP_GREEN) ? GL_TRUE : GL_FALSE, (mask & ECP_BLUE) ? GL_TRUE : GL_FALSE, (mask & ECP_ALPHA) ? GL_TRUE : GL_FALSE);
for (GLuint i = 0; i < FrameBufferCount; ++i)
{
ColorMask[i][0] = red;
ColorMask[i][1] = green;
ColorMask[i][2] = blue;
ColorMask[i][3] = alpha;
}
ColorMask[i] = mask;
ColorMaskInvalid = false;
}
}
void setColorMaskIndexed(GLuint index, bool red, bool green, bool blue, bool alpha)
void setColorMaskIndexed(GLuint index, u8 mask)
{
if (index < FrameBufferCount && (ColorMask[index][0] != red || ColorMask[index][1] != green || ColorMask[index][2] != blue || ColorMask[index][3] != alpha))
if (index < FrameBufferCount && ColorMask[index] != mask)
{
Driver->irrGlColorMaskIndexed(index, red, green, blue, alpha);
Driver->irrGlColorMaskIndexed(index, (mask & ECP_RED) ? GL_TRUE : GL_FALSE, (mask & ECP_GREEN) ? GL_TRUE : GL_FALSE, (mask & ECP_BLUE) ? GL_TRUE : GL_FALSE, (mask & ECP_ALPHA) ? GL_TRUE : GL_FALSE);
ColorMask[index][0] = red;
ColorMask[index][1] = green;
ColorMask[index][2] = blue;
ColorMask[index][3] = alpha;
ColorMask[index] = mask;
ColorMaskInvalid = true;
}
}
@ -432,6 +443,7 @@ public:
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
CullFace = enable;
}
}
@ -447,6 +459,11 @@ public:
}
}
void getDepthMask(bool& depth)
{
depth = DepthMask;
}
void setDepthMask(bool enable)
{
if (DepthMask != enable)
@ -455,6 +472,7 @@ public:
glDepthMask(GL_TRUE);
else
glDepthMask(GL_FALSE);
DepthMask = enable;
}
}
@ -467,6 +485,7 @@ public:
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
DepthTest = enable;
}
}
@ -554,8 +573,13 @@ protected:
GLenum* BlendSourceAlpha;
GLenum* BlendDestinationAlpha;
bool* Blend;
bool BlendEquationInvalid;
bool BlendFuncInvalid;
bool BlendInvalid;
bool(*ColorMask)[4];
u8* ColorMask;
bool ColorMaskInvalid;
GLenum CullFaceMode;
bool CullFace;

View File

@ -467,7 +467,7 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
extGlBindBuffer(GL_ARRAY_BUFFER, 0);
return (!testGLError());
return (!testGLError(__LINE__));
#else
return false;
#endif
@ -541,7 +541,7 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return (!testGLError());
return (!testGLError(__LINE__));
#else
return false;
#endif
@ -735,10 +735,7 @@ void COpenGLDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
#else
0);
#endif
if ( testGLError() )
{
os::Printer::log("Occlusion Query failed", ELL_ERROR);
}
testGLError(__LINE__);
}
}
@ -766,10 +763,7 @@ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
0,
#endif
&available);
if ( testGLError() )
{
os::Printer::log("extGlGetQueryObjectiv failed", ELL_ERROR);
}
testGLError(__LINE__);
}
if (available==GL_TRUE)
{
@ -785,10 +779,7 @@ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
if (queryFeature(EVDF_OCCLUSION_QUERY))
OcclusionQueries[index].Result = available;
}
if ( testGLError() )
{
os::Printer::log("extGlGetQueryObjectiv failed", ELL_ERROR);
}
testGLError(__LINE__);
}
}
@ -1295,87 +1286,24 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi
if (!sourceRect.isValid())
return;
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());
// clip these coordinates
core::rect<s32> targetRect(destPos, sourceRect.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 + 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 + 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)
targetRect.clipAgainst(*clipRect);
if ( targetRect.getWidth() < 0 || targetRect.getHeight() < 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)
targetRect.clipAgainst( core::rect<s32>(0,0, (s32)renderTargetSize.Width, (s32)renderTargetSize.Height) );
if ( targetRect.getWidth() < 0 || targetRect.getHeight() < 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.
const core::dimension2d<s32> sourceSize(targetRect.getSize());
const core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner + (targetRect.UpperLeftCorner-destPos));
const core::dimension2d<u32>& ss = texture->getOriginalSize();
const f32 invW = 1.f / static_cast<f32>(ss.Width);
@ -1386,8 +1314,6 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi
(sourcePos.X + sourceSize.Width) * invW,
(sourcePos.Y + sourceSize.Height) * invH);
const core::rect<s32> poss(targetPos, sourceSize);
disableTextures(1);
if (!CacheHandler->getTextureCache().set(0, texture))
return;
@ -1398,10 +1324,10 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi
Quad2DVertices[2].Color = color;
Quad2DVertices[3].Color = color;
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].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[1].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[2].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f);
Quad2DVertices[3].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.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);
@ -2111,7 +2037,7 @@ void COpenGLDriver::setMaterial(const SMaterial& material)
//! prints error if an error happened.
bool COpenGLDriver::testGLError()
bool COpenGLDriver::testGLError(int code)
{
#ifdef _DEBUG
GLenum g = glGetError();
@ -2120,22 +2046,22 @@ bool COpenGLDriver::testGLError()
case GL_NO_ERROR:
return false;
case GL_INVALID_ENUM:
os::Printer::log("GL_INVALID_ENUM", ELL_ERROR); break;
os::Printer::log("GL_INVALID_ENUM", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_INVALID_VALUE:
os::Printer::log("GL_INVALID_VALUE", ELL_ERROR); break;
os::Printer::log("GL_INVALID_VALUE", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_INVALID_OPERATION:
os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR); break;
os::Printer::log("GL_INVALID_OPERATION", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_STACK_OVERFLOW:
os::Printer::log("GL_STACK_OVERFLOW", ELL_ERROR); break;
os::Printer::log("GL_STACK_OVERFLOW", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_STACK_UNDERFLOW:
os::Printer::log("GL_STACK_UNDERFLOW", ELL_ERROR); break;
os::Printer::log("GL_STACK_UNDERFLOW", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_OUT_OF_MEMORY:
os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR); break;
os::Printer::log("GL_OUT_OF_MEMORY", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_TABLE_TOO_LARGE:
os::Printer::log("GL_TABLE_TOO_LARGE", ELL_ERROR); break;
os::Printer::log("GL_TABLE_TOO_LARGE", core::stringc(code).c_str(), ELL_ERROR); break;
#if defined(GL_EXT_framebuffer_object)
case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", ELL_ERROR); break;
os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", core::stringc(code).c_str(), ELL_ERROR); break;
#endif
};
// _IRR_DEBUG_BREAK_IF(true);
@ -2540,11 +2466,7 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
}
// Color Mask
CacheHandler->setColorMask(
(material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE);
CacheHandler->setColorMask(material.ColorMask);
// Blend Equation
if (material.BlendOperation == EBO_NONE)
@ -3903,10 +3825,15 @@ bool COpenGLDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SCol
void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
{
GLbitfield mask = 0;
u8 colorMask = 0;
bool depthMask = false;
CacheHandler->getColorMask(colorMask);
CacheHandler->getDepthMask(depthMask);
if (flag & ECBF_COLOR)
{
CacheHandler->setColorMask(true, true, true, true);
CacheHandler->setColorMask(ECP_ALL);
const f32 inv = 1.0f / 255.0f;
glClearColor(color.getRed() * inv, color.getGreen() * inv,
@ -3930,6 +3857,9 @@ void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
if (mask)
glClear(mask);
CacheHandler->setColorMask(colorMask);
CacheHandler->setDepthMask(depthMask);
}
@ -4004,10 +3934,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE
}
glReadBuffer(tgt);
glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels);
if ( testGLError() )
{
os::Printer::log("glReadPixels failed", ELL_ERROR);
}
testGLError(__LINE__);
glReadBuffer(GL_BACK);
}
@ -4043,7 +3970,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE
if (newImage)
{
if (testGLError() || !pixels)
if (testGLError(__LINE__) || !pixels)
{
os::Printer::log("createScreenShot failed", ELL_ERROR);
newImage->drop();

View File

@ -345,9 +345,9 @@ namespace video
//! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) _IRR_OVERRIDE_;
//! checks if an OpenGL error has happend and prints it
//! checks if an OpenGL error has happened and prints it (+ some internal code which is usually the line number)
//! for performance reasons only available in debug mode
bool testGLError();
bool testGLError(int code=0);
//! Set/unset a clipping plane.
//! There are at least 6 clipping planes available for the user to set at will.

View File

@ -696,7 +696,7 @@ void CWebGL1Driver::drawStencilShadow(bool clearStencilBuffer,
lockRenderStateMode();
CacheHandler->setDepthMask(false);
CacheHandler->setColorMask(true, true, true, true);
CacheHandler->setColorMask(ECP_ALL);
CacheHandler->setBlend(true);
CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);