Merge pull request #10248 from dabingnn/v3_fixRenderer

V3 fix renderer
This commit is contained in:
minggo 2015-01-28 15:15:08 +08:00
commit 2738745614
14 changed files with 222 additions and 125 deletions

View File

@ -91,13 +91,6 @@ Camera::~Camera()
} }
void Camera::setPosition3D(const Vec3& position)
{
Node::setPosition3D(position);
_transformUpdated = _transformDirty = _inverseDirty = true;
}
const Mat4& Camera::getProjectionMatrix() const const Mat4& Camera::getProjectionMatrix() const
{ {
return _projection; return _projection;

View File

@ -102,10 +102,6 @@ public:
/**get & set Camera flag*/ /**get & set Camera flag*/
CameraFlag getCameraFlag() const { return (CameraFlag)_cameraFlag; } CameraFlag getCameraFlag() const { return (CameraFlag)_cameraFlag; }
void setCameraFlag(CameraFlag flag) { _cameraFlag = (unsigned short)flag; } 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 * Make Camera looks at target

View File

@ -609,10 +609,6 @@ void Node::setPositionZ(float positionZ)
_transformUpdated = _transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
_positionZ = positionZ; _positionZ = positionZ;
// FIXME: BUG
// Global Z Order should based on the modelViewTransform
setGlobalZOrder(positionZ);
} }
/// position getter /// position getter

View File

@ -1122,7 +1122,7 @@ public:
* *
* @return An Action pointer * @return An Action pointer
*/ */
Action* runAction(Action* action); virtual Action* runAction(Action* action);
/** /**
* Stops and removes all actions from the running action list . * Stops and removes all actions from the running action list .

View File

@ -741,6 +741,10 @@ void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
} }
//support tint and fade //support tint and fade
meshCommand.setDisplayColor(Vec4(color.r, color.g, color.b, color.a)); meshCommand.setDisplayColor(Vec4(color.r, color.g, color.b, color.a));
if (_forceDepthWrite)
{
meshCommand.setDepthWriteEnabled(true);
}
meshCommand.setTransparent(isTransparent); meshCommand.setTransparent(isTransparent);
renderer->addCommand(&meshCommand); renderer->addCommand(&meshCommand);
} }
@ -801,6 +805,12 @@ const AABB& Sprite3D::getAABB() const
return _aabb; return _aabb;
} }
Action* Sprite3D::runAction(Action *action)
{
setForceDepthWrite(true);
return Node::runAction(action);
}
Rect Sprite3D::getBoundingBox() const Rect Sprite3D::getBoundingBox() const
{ {
AABB aabb = getAABB(); AABB aabb = getAABB();

View File

@ -126,6 +126,22 @@ public:
*/ */
const AABB& getAABB() const; 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 * Returns 2d bounding-box
* Note: the bouding-box is just get from the AABB which as Z=0, so that is not very accurate. * 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; bool _aabbDirty;
unsigned int _lightMask; unsigned int _lightMask;
bool _shaderUsingLight; // is current shader using light ? bool _shaderUsingLight; // is current shader using light ?
bool _forceDepthWrite; // Always write to depth buffer
struct AsyncLoadParam struct AsyncLoadParam
{ {

View File

@ -42,12 +42,6 @@
NS_CC_BEGIN 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 const char *s_dirLightUniformColorName = "u_DirLightSourceColor";
static std::vector<Vec3> s_dirLightUniformColorValues; static std::vector<Vec3> s_dirLightUniformColorValues;
static const char *s_dirLightUniformDirName = "u_DirLightSourceDirection"; static const char *s_dirLightUniformDirName = "u_DirLightSourceDirection";
@ -159,6 +153,7 @@ void MeshCommand::setDepthTestEnabled(bool enable)
void MeshCommand::setDepthWriteEnabled(bool enable) void MeshCommand::setDepthWriteEnabled(bool enable)
{ {
_forceDepthWrite = enable;
_depthWriteEnabled = enable; _depthWriteEnabled = enable;
} }
@ -172,7 +167,11 @@ void MeshCommand::setTransparent(bool value)
_isTransparent = value; _isTransparent = value;
//Skip batching for transparent mesh //Skip batching for transparent mesh
_skipBatching = value; _skipBatching = value;
setDepthWriteEnabled(!_isTransparent);
if (!_forceDepthWrite)
{
_depthWriteEnabled = true;
}
} }
MeshCommand::~MeshCommand() MeshCommand::~MeshCommand()
@ -185,46 +184,48 @@ MeshCommand::~MeshCommand()
void MeshCommand::applyRenderState() 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); glEnable(GL_CULL_FACE);
s_cullFaceEnabled = true;
} }
if (s_cullFace != _cullFace)
{
glCullFace(_cullFace); glCullFace(_cullFace);
s_cullFace = _cullFace;
} if (_depthTestEnabled && !_renderStateDepthTest)
if (_depthTestEnabled && !s_depthTestEnabled)
{ {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
s_depthTestEnabled = true;
} }
if (_depthWriteEnabled && !s_depthWriteEnabled) if (_depthWriteEnabled && !_renderStateDepthWrite)
{ {
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
s_depthWriteEnabled = true;
} }
} }
void MeshCommand::restoreRenderState() void MeshCommand::restoreRenderState()
{ {
if (s_cullFaceEnabled) if (_renderStateCullFace)
{
glEnable(GL_CULL_FACE);
}
else
{ {
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
s_cullFaceEnabled = false;
} }
if (s_depthTestEnabled)
if (_renderStateDepthTest)
{
glEnable(GL_DEPTH_TEST);
}
else
{ {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
s_depthTestEnabled = false;
} }
if (s_depthWriteEnabled)
{ glDepthMask(_renderStateDepthTest);
glDepthMask(GL_FALSE);
s_depthWriteEnabled = false;
}
s_cullFace = 0;
} }
void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, const BlendFunc& blend) void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, const BlendFunc& blend)

View File

@ -127,6 +127,11 @@ protected:
GLenum _cullFace; GLenum _cullFace;
bool _depthTestEnabled; bool _depthTestEnabled;
bool _depthWriteEnabled; bool _depthWriteEnabled;
bool _forceDepthWrite;
bool _renderStateCullFace;
bool _renderStateDepthTest;
GLboolean _renderStateDepthWrite;
// ModelView transform // ModelView transform
Mat4 _mv; Mat4 _mv;

View File

@ -35,6 +35,7 @@ RenderCommand::RenderCommand()
, _isTransparent(true) , _isTransparent(true)
, _skipBatching(false) , _skipBatching(false)
, _is3D(false) , _is3D(false)
, _depth(0)
{ {
} }
@ -44,14 +45,16 @@ RenderCommand::~RenderCommand()
void RenderCommand::init(float globalZOrder, const cocos2d::Mat4 &transform, uint32_t flags) void RenderCommand::init(float globalZOrder, const cocos2d::Mat4 &transform, uint32_t flags)
{ {
_globalOrder = globalZOrder;
if (flags & Node::FLAGS_RENDER_AS_3D) if (flags & Node::FLAGS_RENDER_AS_3D)
{ {
_globalOrder = Camera::getVisitingCamera()->getDepthInView(transform); _depth = Camera::getVisitingCamera()->getDepthInView(transform);
set3D(true); set3D(true);
} }
else else
{ {
_globalOrder = globalZOrder; set3D(false);
_depth = 0;
} }
} }

View File

@ -78,6 +78,8 @@ public:
inline void set3D(bool value) { _is3D = value; } inline void set3D(bool value) { _is3D = value; }
inline float getDepth() const { return _depth; }
protected: protected:
RenderCommand(); RenderCommand();
virtual ~RenderCommand(); virtual ~RenderCommand();
@ -98,6 +100,9 @@ protected:
// is the command been rendered on 3D pass // is the command been rendered on 3D pass
bool _is3D; bool _is3D;
// depth
float _depth;
}; };
NS_CC_END NS_CC_END

View File

@ -53,7 +53,7 @@ static bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
static bool compare3DCommand(RenderCommand* a, RenderCommand* b) static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
{ {
return a->getGlobalOrder() > b->getGlobalOrder(); return a->getDepth() > b->getDepth();
} }
// queue // queue
@ -61,74 +61,78 @@ static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
void RenderQueue::push_back(RenderCommand* command) void RenderQueue::push_back(RenderCommand* command)
{ {
float z = command->getGlobalOrder(); 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->is3D())
{ {
if(command->isTransparent()) if(command->isTransparent())
{ {
_queue3DTransparent.push_back(command); _commands[QUEUE_GROUP::TRANSPARENT_3D].push_back(command);
} }
else 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 else
_queue0.push_back(command); {
_commands[QUEUE_GROUP::GLOBALZ_ZERO].push_back(command);
}
}
} }
ssize_t RenderQueue::size() const 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() void RenderQueue::sort()
{ {
// Don't sort _queue0, it already comes sorted // Don't sort _queue0, it already comes sorted
std::sort(std::begin(_queue3DTransparent), std::end(_queue3DTransparent), compare3DCommand); std::sort(std::begin(_commands[QUEUE_GROUP::TRANSPARENT_3D]), std::end(_commands[QUEUE_GROUP::TRANSPARENT_3D]), compare3DCommand);
std::sort(std::begin(_queueNegZ), std::end(_queueNegZ), compareRenderCommand); std::sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_NEG]), std::end(_commands[QUEUE_GROUP::GLOBALZ_NEG]), compareRenderCommand);
std::sort(std::begin(_queuePosZ), std::end(_queuePosZ), 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 RenderCommand* RenderQueue::operator[](ssize_t index) const
{ {
if(index < static_cast<ssize_t>(_queue3DOpaque.size())) for(int queIndex = 0; queIndex < QUEUE_GROUP::QUEUE_COUNT; ++queIndex)
return _queue3DOpaque[index]; {
if(index < static_cast<ssize_t>(_commands[queIndex].size()))
index -= _queue3DOpaque.size(); return _commands[queIndex][index];
else
if(index < static_cast<ssize_t>(_queue3DTransparent.size())) {
return _queue3DTransparent[index]; index -= _commands[queIndex].size();
}
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];
CCASSERT(false, "invalid index"); CCASSERT(false, "invalid index");
return nullptr; return nullptr;
} }
void RenderQueue::clear() void RenderQueue::clear()
{ {
_queue3DOpaque.clear(); _commands.clear();
_queue3DTransparent.clear(); for(int index = 0; index < QUEUE_COUNT; ++index)
_queueNegZ.clear(); {
_queue0.clear(); _commands.push_back(std::vector<RenderCommand*>());
_queuePosZ.clear(); }
} }
void RenderQueue::saveRenderState() void RenderQueue::saveRenderState()
@ -502,48 +506,104 @@ void Renderer::processRenderCommand(RenderCommand* command)
void Renderer::visitRenderQueue(RenderQueue& queue) void Renderer::visitRenderQueue(RenderQueue& queue)
{ {
ssize_t size = queue.size();
queue.saveRenderState(); queue.saveRenderState();
//Process Opaque Object //
const std::vector<RenderCommand*>& opaqueQueue = queue.getOpaqueCommands(); //Process Global-Z < 0 Objects
if (opaqueQueue.size() > 0) //
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) if(_isDepthTestFor2D)
{ {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(true); glDepthMask(true);
} }
else
//Process Transparent Object
for (ssize_t index = queue.getOpaqueQueueSize(); index < size; ++index)
{ {
processRenderCommand(queue[index]); glDisable(GL_DEPTH_TEST);
glDepthMask(false);
}
for (auto it = zNegQueue.cbegin(); it != zNegQueue.cend(); ++it)
{
processRenderCommand(*it);
} }
flush(); 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(); queue.restoreRenderState();
} }

View File

@ -47,25 +47,36 @@ class MeshCommand;
are the ones that have `z < 0` and `z > 0`. are the ones that have `z < 0` and `z > 0`.
*/ */
class RenderQueue { 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: public:
RenderQueue()
{
clear();
}
void push_back(RenderCommand* command); void push_back(RenderCommand* command);
ssize_t size() const; ssize_t size() const;
void sort(); void sort();
RenderCommand* operator[](ssize_t index) const; RenderCommand* operator[](ssize_t index) const;
void clear(); void clear();
ssize_t getOpaqueQueueSize() const { return _queue3DOpaque.size(); } inline std::vector<RenderCommand*>& getSubQueue(QUEUE_GROUP group) { return _commands[group]; }
const std::vector<RenderCommand*>& getOpaqueCommands() const { return _queue3DOpaque; } inline ssize_t getSubQueueSize(QUEUE_GROUP group) const { return _commands[group].size();}
void saveRenderState(); void saveRenderState();
void restoreRenderState(); void restoreRenderState();
protected: protected:
std::vector<RenderCommand*> _queue3DOpaque;
std::vector<RenderCommand*> _queue3DTransparent; std::vector<std::vector<RenderCommand*>> _commands;
std::vector<RenderCommand*> _queueNegZ;
std::vector<RenderCommand*> _queue0;
std::vector<RenderCommand*> _queuePosZ;
//Render State related //Render State related
bool _isCullEnabled; bool _isCullEnabled;

View File

@ -130,7 +130,6 @@ CameraRotationTest::CameraRotationTest()
auto sp3d = Sprite3D::create(); auto sp3d = Sprite3D::create();
sp3d->setPosition(s.width/2, s.height/2); sp3d->setPosition(s.width/2, s.height/2);
sp3d->setRotation3D(Vec3(90,90,0));
addChild(sp3d); addChild(sp3d);
auto lship = Label::create(); auto lship = Label::create();

View File

@ -2212,6 +2212,7 @@ void UseCaseSprite3D::switchCase()
{ {
auto layer = LayerColor::create(Color4B(0, 0, 100, 255), s.width / 2.f, s.height / 2.f); 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->setPosition(s.width * 0.25f, s.height * 0.25f);
layer->setGlobalZOrder(-1);
addChild(layer); addChild(layer);
std::string filename = "Sprite3DTest/girl.c3b"; std::string filename = "Sprite3DTest/girl.c3b";