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
{
return _projection;

View File

@ -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

View File

@ -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

View File

@ -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 .

View File

@ -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();

View File

@ -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
{

View File

@ -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)

View File

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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -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;

View File

@ -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();

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);
layer->setPosition(s.width * 0.25f, s.height * 0.25f);
layer->setGlobalZOrder(-1);
addChild(layer);
std::string filename = "Sprite3DTest/girl.c3b";