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-e03cc46cb475master
parent
c3ed02c8d0
commit
56e72da4a7
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue