mirror of https://github.com/axmolengine/axmol.git
commit
2738745614
|
@ -91,13 +91,6 @@ Camera::~Camera()
|
|||
|
||||
}
|
||||
|
||||
void Camera::setPosition3D(const Vec3& position)
|
||||
{
|
||||
Node::setPosition3D(position);
|
||||
|
||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
}
|
||||
|
||||
const Mat4& Camera::getProjectionMatrix() const
|
||||
{
|
||||
return _projection;
|
||||
|
|
|
@ -102,10 +102,6 @@ public:
|
|||
/**get & set Camera flag*/
|
||||
CameraFlag getCameraFlag() const { return (CameraFlag)_cameraFlag; }
|
||||
void setCameraFlag(CameraFlag flag) { _cameraFlag = (unsigned short)flag; }
|
||||
/**
|
||||
* Sets the position (X, Y, and Z) in its parent's coordinate system
|
||||
*/
|
||||
virtual void setPosition3D(const Vec3& position) override;
|
||||
|
||||
/**
|
||||
* Make Camera looks at target
|
||||
|
|
|
@ -609,10 +609,6 @@ void Node::setPositionZ(float positionZ)
|
|||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
|
||||
_positionZ = positionZ;
|
||||
|
||||
// FIXME: BUG
|
||||
// Global Z Order should based on the modelViewTransform
|
||||
setGlobalZOrder(positionZ);
|
||||
}
|
||||
|
||||
/// position getter
|
||||
|
|
|
@ -1122,7 +1122,7 @@ public:
|
|||
*
|
||||
* @return An Action pointer
|
||||
*/
|
||||
Action* runAction(Action* action);
|
||||
virtual Action* runAction(Action* action);
|
||||
|
||||
/**
|
||||
* Stops and removes all actions from the running action list .
|
||||
|
|
|
@ -741,6 +741,10 @@ void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
|
|||
}
|
||||
//support tint and fade
|
||||
meshCommand.setDisplayColor(Vec4(color.r, color.g, color.b, color.a));
|
||||
if (_forceDepthWrite)
|
||||
{
|
||||
meshCommand.setDepthWriteEnabled(true);
|
||||
}
|
||||
meshCommand.setTransparent(isTransparent);
|
||||
renderer->addCommand(&meshCommand);
|
||||
}
|
||||
|
@ -801,6 +805,12 @@ const AABB& Sprite3D::getAABB() const
|
|||
return _aabb;
|
||||
}
|
||||
|
||||
Action* Sprite3D::runAction(Action *action)
|
||||
{
|
||||
setForceDepthWrite(true);
|
||||
return Node::runAction(action);
|
||||
}
|
||||
|
||||
Rect Sprite3D::getBoundingBox() const
|
||||
{
|
||||
AABB aabb = getAABB();
|
||||
|
|
|
@ -126,6 +126,22 @@ public:
|
|||
*/
|
||||
const AABB& getAABB() const;
|
||||
|
||||
/**
|
||||
* Executes an action, and returns the action that is executed. For Sprite3D special logic are needed to take care of Fading.
|
||||
*
|
||||
* This node becomes the action's target. Refer to Action::getTarget()
|
||||
* @warning Actions don't retain their target.
|
||||
*
|
||||
* @return An Action pointer
|
||||
*/
|
||||
virtual Action* runAction(Action* action) override;
|
||||
|
||||
/**
|
||||
* Force to write to depth buffer, this is useful if you want to achieve effects like fading.
|
||||
*/
|
||||
void setForceDepthWrite(bool value) { _forceDepthWrite = value; }
|
||||
bool isForceDepthWrite() const { return _forceDepthWrite;};
|
||||
|
||||
/**
|
||||
* Returns 2d bounding-box
|
||||
* Note: the bouding-box is just get from the AABB which as Z=0, so that is not very accurate.
|
||||
|
@ -200,6 +216,7 @@ protected:
|
|||
bool _aabbDirty;
|
||||
unsigned int _lightMask;
|
||||
bool _shaderUsingLight; // is current shader using light ?
|
||||
bool _forceDepthWrite; // Always write to depth buffer
|
||||
|
||||
struct AsyncLoadParam
|
||||
{
|
||||
|
|
|
@ -42,12 +42,6 @@
|
|||
|
||||
NS_CC_BEGIN
|
||||
|
||||
//render state
|
||||
static bool s_cullFaceEnabled = false;
|
||||
static GLenum s_cullFace = 0;
|
||||
static bool s_depthTestEnabled = false;
|
||||
static bool s_depthWriteEnabled = false;
|
||||
|
||||
static const char *s_dirLightUniformColorName = "u_DirLightSourceColor";
|
||||
static std::vector<Vec3> s_dirLightUniformColorValues;
|
||||
static const char *s_dirLightUniformDirName = "u_DirLightSourceDirection";
|
||||
|
@ -159,6 +153,7 @@ void MeshCommand::setDepthTestEnabled(bool enable)
|
|||
|
||||
void MeshCommand::setDepthWriteEnabled(bool enable)
|
||||
{
|
||||
_forceDepthWrite = enable;
|
||||
_depthWriteEnabled = enable;
|
||||
}
|
||||
|
||||
|
@ -172,7 +167,11 @@ void MeshCommand::setTransparent(bool value)
|
|||
_isTransparent = value;
|
||||
//Skip batching for transparent mesh
|
||||
_skipBatching = value;
|
||||
setDepthWriteEnabled(!_isTransparent);
|
||||
|
||||
if (!_forceDepthWrite)
|
||||
{
|
||||
_depthWriteEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
MeshCommand::~MeshCommand()
|
||||
|
@ -185,46 +184,48 @@ MeshCommand::~MeshCommand()
|
|||
|
||||
void MeshCommand::applyRenderState()
|
||||
{
|
||||
if (_cullFaceEnabled && !s_cullFaceEnabled)
|
||||
_renderStateCullFace = glIsEnabled(GL_CULL_FACE);
|
||||
_renderStateDepthTest = glIsEnabled(GL_DEPTH_TEST);
|
||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &_renderStateDepthWrite);
|
||||
|
||||
if (_cullFaceEnabled && !_renderStateCullFace)
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
s_cullFaceEnabled = true;
|
||||
}
|
||||
if (s_cullFace != _cullFace)
|
||||
{
|
||||
|
||||
glCullFace(_cullFace);
|
||||
s_cullFace = _cullFace;
|
||||
}
|
||||
if (_depthTestEnabled && !s_depthTestEnabled)
|
||||
|
||||
if (_depthTestEnabled && !_renderStateDepthTest)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
s_depthTestEnabled = true;
|
||||
}
|
||||
if (_depthWriteEnabled && !s_depthWriteEnabled)
|
||||
if (_depthWriteEnabled && !_renderStateDepthWrite)
|
||||
{
|
||||
glDepthMask(GL_TRUE);
|
||||
s_depthWriteEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshCommand::restoreRenderState()
|
||||
{
|
||||
if (s_cullFaceEnabled)
|
||||
if (_renderStateCullFace)
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CULL_FACE);
|
||||
s_cullFaceEnabled = false;
|
||||
}
|
||||
if (s_depthTestEnabled)
|
||||
|
||||
if (_renderStateDepthTest)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
s_depthTestEnabled = false;
|
||||
}
|
||||
if (s_depthWriteEnabled)
|
||||
{
|
||||
glDepthMask(GL_FALSE);
|
||||
s_depthWriteEnabled = false;
|
||||
}
|
||||
s_cullFace = 0;
|
||||
|
||||
glDepthMask(_renderStateDepthTest);
|
||||
}
|
||||
|
||||
void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, const BlendFunc& blend)
|
||||
|
|
|
@ -127,6 +127,11 @@ protected:
|
|||
GLenum _cullFace;
|
||||
bool _depthTestEnabled;
|
||||
bool _depthWriteEnabled;
|
||||
bool _forceDepthWrite;
|
||||
|
||||
bool _renderStateCullFace;
|
||||
bool _renderStateDepthTest;
|
||||
GLboolean _renderStateDepthWrite;
|
||||
|
||||
// ModelView transform
|
||||
Mat4 _mv;
|
||||
|
|
|
@ -35,6 +35,7 @@ RenderCommand::RenderCommand()
|
|||
, _isTransparent(true)
|
||||
, _skipBatching(false)
|
||||
, _is3D(false)
|
||||
, _depth(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -44,14 +45,16 @@ RenderCommand::~RenderCommand()
|
|||
|
||||
void RenderCommand::init(float globalZOrder, const cocos2d::Mat4 &transform, uint32_t flags)
|
||||
{
|
||||
_globalOrder = globalZOrder;
|
||||
if (flags & Node::FLAGS_RENDER_AS_3D)
|
||||
{
|
||||
_globalOrder = Camera::getVisitingCamera()->getDepthInView(transform);
|
||||
_depth = Camera::getVisitingCamera()->getDepthInView(transform);
|
||||
set3D(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_globalOrder = globalZOrder;
|
||||
set3D(false);
|
||||
_depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@ public:
|
|||
|
||||
inline void set3D(bool value) { _is3D = value; }
|
||||
|
||||
inline float getDepth() const { return _depth; }
|
||||
|
||||
protected:
|
||||
RenderCommand();
|
||||
virtual ~RenderCommand();
|
||||
|
@ -98,6 +100,9 @@ protected:
|
|||
|
||||
// is the command been rendered on 3D pass
|
||||
bool _is3D;
|
||||
|
||||
// depth
|
||||
float _depth;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -53,7 +53,7 @@ static bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
|
|||
|
||||
static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
|
||||
{
|
||||
return a->getGlobalOrder() > b->getGlobalOrder();
|
||||
return a->getDepth() > b->getDepth();
|
||||
}
|
||||
|
||||
// queue
|
||||
|
@ -61,74 +61,78 @@ static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
|
|||
void RenderQueue::push_back(RenderCommand* command)
|
||||
{
|
||||
float z = command->getGlobalOrder();
|
||||
if(z < 0)
|
||||
{
|
||||
_commands[QUEUE_GROUP::GLOBALZ_NEG].push_back(command);
|
||||
}
|
||||
else if(z > 0)
|
||||
{
|
||||
_commands[QUEUE_GROUP::GLOBALZ_POS].push_back(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(command->is3D())
|
||||
{
|
||||
if(command->isTransparent())
|
||||
{
|
||||
_queue3DTransparent.push_back(command);
|
||||
_commands[QUEUE_GROUP::TRANSPARENT_3D].push_back(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
_queue3DOpaque.push_back(command);
|
||||
_commands[QUEUE_GROUP::OPAQUE_3D].push_back(command);
|
||||
}
|
||||
}
|
||||
else if(z < 0)
|
||||
_queueNegZ.push_back(command);
|
||||
else if(z > 0)
|
||||
_queuePosZ.push_back(command);
|
||||
else
|
||||
_queue0.push_back(command);
|
||||
{
|
||||
_commands[QUEUE_GROUP::GLOBALZ_ZERO].push_back(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t RenderQueue::size() const
|
||||
{
|
||||
return _queue3DOpaque.size() + _queue3DTransparent.size() + _queueNegZ.size() + _queue0.size() + _queuePosZ.size();
|
||||
ssize_t result(0);
|
||||
for(int index = 0; index < QUEUE_GROUP::QUEUE_COUNT; ++index)
|
||||
{
|
||||
result += _commands[index].size();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void RenderQueue::sort()
|
||||
{
|
||||
// Don't sort _queue0, it already comes sorted
|
||||
std::sort(std::begin(_queue3DTransparent), std::end(_queue3DTransparent), compare3DCommand);
|
||||
std::sort(std::begin(_queueNegZ), std::end(_queueNegZ), compareRenderCommand);
|
||||
std::sort(std::begin(_queuePosZ), std::end(_queuePosZ), compareRenderCommand);
|
||||
std::sort(std::begin(_commands[QUEUE_GROUP::TRANSPARENT_3D]), std::end(_commands[QUEUE_GROUP::TRANSPARENT_3D]), compare3DCommand);
|
||||
std::sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_NEG]), std::end(_commands[QUEUE_GROUP::GLOBALZ_NEG]), compareRenderCommand);
|
||||
std::sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_POS]), std::end(_commands[QUEUE_GROUP::GLOBALZ_POS]), compareRenderCommand);
|
||||
}
|
||||
|
||||
RenderCommand* RenderQueue::operator[](ssize_t index) const
|
||||
{
|
||||
if(index < static_cast<ssize_t>(_queue3DOpaque.size()))
|
||||
return _queue3DOpaque[index];
|
||||
|
||||
index -= _queue3DOpaque.size();
|
||||
|
||||
if(index < static_cast<ssize_t>(_queue3DTransparent.size()))
|
||||
return _queue3DTransparent[index];
|
||||
|
||||
index -= _queue3DTransparent.size();
|
||||
|
||||
if(index < static_cast<ssize_t>(_queueNegZ.size()))
|
||||
return _queueNegZ[index];
|
||||
|
||||
index -= _queueNegZ.size();
|
||||
|
||||
if(index < static_cast<ssize_t>(_queue0.size()))
|
||||
return _queue0[index];
|
||||
|
||||
index -= _queue0.size();
|
||||
|
||||
if(index < static_cast<ssize_t>(_queuePosZ.size()))
|
||||
return _queuePosZ[index];
|
||||
for(int queIndex = 0; queIndex < QUEUE_GROUP::QUEUE_COUNT; ++queIndex)
|
||||
{
|
||||
if(index < static_cast<ssize_t>(_commands[queIndex].size()))
|
||||
return _commands[queIndex][index];
|
||||
else
|
||||
{
|
||||
index -= _commands[queIndex].size();
|
||||
}
|
||||
}
|
||||
|
||||
CCASSERT(false, "invalid index");
|
||||
return nullptr;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RenderQueue::clear()
|
||||
{
|
||||
_queue3DOpaque.clear();
|
||||
_queue3DTransparent.clear();
|
||||
_queueNegZ.clear();
|
||||
_queue0.clear();
|
||||
_queuePosZ.clear();
|
||||
_commands.clear();
|
||||
for(int index = 0; index < QUEUE_COUNT; ++index)
|
||||
{
|
||||
_commands.push_back(std::vector<RenderCommand*>());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderQueue::saveRenderState()
|
||||
|
@ -502,48 +506,104 @@ void Renderer::processRenderCommand(RenderCommand* command)
|
|||
|
||||
void Renderer::visitRenderQueue(RenderQueue& queue)
|
||||
{
|
||||
ssize_t size = queue.size();
|
||||
|
||||
queue.saveRenderState();
|
||||
|
||||
//Process Opaque Object
|
||||
const std::vector<RenderCommand*>& opaqueQueue = queue.getOpaqueCommands();
|
||||
if (opaqueQueue.size() > 0)
|
||||
//
|
||||
//Process Global-Z < 0 Objects
|
||||
//
|
||||
const auto& zNegQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_NEG);
|
||||
if (zNegQueue.size() > 0)
|
||||
{
|
||||
glDepthMask(true);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
for (auto it = opaqueQueue.cbegin(); it != opaqueQueue.cend(); ++it) {
|
||||
processRenderCommand(*it);
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
}
|
||||
flush();
|
||||
|
||||
//Setup Transparent rendering
|
||||
if (opaqueQueue.size() > 0)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if(_isDepthTestFor2D)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
}
|
||||
|
||||
//Process Transparent Object
|
||||
for (ssize_t index = queue.getOpaqueQueueSize(); index < size; ++index)
|
||||
else
|
||||
{
|
||||
processRenderCommand(queue[index]);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
}
|
||||
for (auto it = zNegQueue.cbegin(); it != zNegQueue.cend(); ++it)
|
||||
{
|
||||
processRenderCommand(*it);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
//
|
||||
//Process Opaque Object
|
||||
//
|
||||
const auto& opaqueQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::OPAQUE_3D);
|
||||
if (opaqueQueue.size() > 0)
|
||||
{
|
||||
//Clear depth to achieve layered rendering
|
||||
glDepthMask(true);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
for (auto it = opaqueQueue.cbegin(); it != opaqueQueue.cend(); ++it)
|
||||
{
|
||||
processRenderCommand(*it);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
//
|
||||
//Process 3D Transparent object
|
||||
//
|
||||
const auto& transQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::TRANSPARENT_3D);
|
||||
if (transQueue.size() > 0)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
|
||||
for (auto it = transQueue.cbegin(); it != transQueue.cend(); ++it)
|
||||
{
|
||||
processRenderCommand(*it);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
//
|
||||
//Process Global-Z = 0 Queue
|
||||
//
|
||||
const auto& zZeroQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_ZERO);
|
||||
if (zZeroQueue.size() > 0)
|
||||
{
|
||||
if(_isDepthTestFor2D)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
}
|
||||
for (auto it = zZeroQueue.cbegin(); it != zZeroQueue.cend(); ++it)
|
||||
{
|
||||
processRenderCommand(*it);
|
||||
}
|
||||
flush();
|
||||
|
||||
glDepthMask(true);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glDepthMask(false);
|
||||
}
|
||||
|
||||
//
|
||||
//Process Global-Z > 0 Queue
|
||||
//
|
||||
const auto& zPosQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_POS);
|
||||
if (zPosQueue.size() > 0)
|
||||
{
|
||||
for (auto it = zPosQueue.cbegin(); it != zPosQueue.cend(); ++it)
|
||||
{
|
||||
processRenderCommand(*it);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
queue.restoreRenderState();
|
||||
}
|
||||
|
|
|
@ -47,25 +47,36 @@ class MeshCommand;
|
|||
are the ones that have `z < 0` and `z > 0`.
|
||||
*/
|
||||
class RenderQueue {
|
||||
public:
|
||||
enum QUEUE_GROUP
|
||||
{
|
||||
GLOBALZ_NEG = 0,
|
||||
OPAQUE_3D = 1,
|
||||
TRANSPARENT_3D = 2,
|
||||
GLOBALZ_ZERO = 3,
|
||||
GLOBALZ_POS = 4,
|
||||
QUEUE_COUNT = 5,
|
||||
};
|
||||
|
||||
public:
|
||||
RenderQueue()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
void push_back(RenderCommand* command);
|
||||
ssize_t size() const;
|
||||
void sort();
|
||||
RenderCommand* operator[](ssize_t index) const;
|
||||
void clear();
|
||||
ssize_t getOpaqueQueueSize() const { return _queue3DOpaque.size(); }
|
||||
const std::vector<RenderCommand*>& getOpaqueCommands() const { return _queue3DOpaque; }
|
||||
inline std::vector<RenderCommand*>& getSubQueue(QUEUE_GROUP group) { return _commands[group]; }
|
||||
inline ssize_t getSubQueueSize(QUEUE_GROUP group) const { return _commands[group].size();}
|
||||
|
||||
void saveRenderState();
|
||||
void restoreRenderState();
|
||||
|
||||
protected:
|
||||
std::vector<RenderCommand*> _queue3DOpaque;
|
||||
std::vector<RenderCommand*> _queue3DTransparent;
|
||||
std::vector<RenderCommand*> _queueNegZ;
|
||||
std::vector<RenderCommand*> _queue0;
|
||||
std::vector<RenderCommand*> _queuePosZ;
|
||||
|
||||
std::vector<std::vector<RenderCommand*>> _commands;
|
||||
|
||||
//Render State related
|
||||
bool _isCullEnabled;
|
||||
|
|
|
@ -130,7 +130,6 @@ CameraRotationTest::CameraRotationTest()
|
|||
|
||||
auto sp3d = Sprite3D::create();
|
||||
sp3d->setPosition(s.width/2, s.height/2);
|
||||
sp3d->setRotation3D(Vec3(90,90,0));
|
||||
addChild(sp3d);
|
||||
|
||||
auto lship = Label::create();
|
||||
|
|
|
@ -2212,6 +2212,7 @@ void UseCaseSprite3D::switchCase()
|
|||
{
|
||||
auto layer = LayerColor::create(Color4B(0, 0, 100, 255), s.width / 2.f, s.height / 2.f);
|
||||
layer->setPosition(s.width * 0.25f, s.height * 0.25f);
|
||||
layer->setGlobalZOrder(-1);
|
||||
addChild(layer);
|
||||
|
||||
std::string filename = "Sprite3DTest/girl.c3b";
|
||||
|
|
Loading…
Reference in New Issue