diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index a132121d99..08e37fa3b1 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -3603,6 +3603,10 @@ B6DD2FF61B04825B00E47F5F /* fastlz.c in Sources */ = {isa = PBXBuildFile; fileRef = B6DD2FA51B04825B00E47F5F /* fastlz.c */; }; B6DD2FF71B04825B00E47F5F /* fastlz.h in Headers */ = {isa = PBXBuildFile; fileRef = B6DD2FA61B04825B00E47F5F /* fastlz.h */; }; B6DD2FF81B04825B00E47F5F /* fastlz.h in Headers */ = {isa = PBXBuildFile; fileRef = B6DD2FA61B04825B00E47F5F /* fastlz.h */; }; + B6DD36D51B8564EC0044745A /* CCCameraBackGroundBrush.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DD36D31B8564EC0044745A /* CCCameraBackGroundBrush.cpp */; }; + B6DD36D61B8564EC0044745A /* CCCameraBackGroundBrush.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DD36D31B8564EC0044745A /* CCCameraBackGroundBrush.cpp */; }; + B6DD36D71B8564EC0044745A /* CCCameraBackGroundBrush.h in Headers */ = {isa = PBXBuildFile; fileRef = B6DD36D41B8564EC0044745A /* CCCameraBackGroundBrush.h */; }; + B6DD36D81B8564EC0044745A /* CCCameraBackGroundBrush.h in Headers */ = {isa = PBXBuildFile; fileRef = B6DD36D41B8564EC0044745A /* CCCameraBackGroundBrush.h */; }; C50306691B60B583001E6D43 /* CCBoneNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C50306631B60B583001E6D43 /* CCBoneNode.cpp */; }; C503066A1B60B583001E6D43 /* CCBoneNode.h in Headers */ = {isa = PBXBuildFile; fileRef = C50306641B60B583001E6D43 /* CCBoneNode.h */; }; C503066B1B60B583001E6D43 /* CCSkeletonNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C50306651B60B583001E6D43 /* CCSkeletonNode.cpp */; }; @@ -5546,6 +5550,8 @@ B6DD2FA31B04825B00E47F5F /* DetourTileCacheBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetourTileCacheBuilder.h; sourceTree = ""; }; B6DD2FA51B04825B00E47F5F /* fastlz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fastlz.c; sourceTree = ""; }; B6DD2FA61B04825B00E47F5F /* fastlz.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fastlz.h; sourceTree = ""; }; + B6DD36D31B8564EC0044745A /* CCCameraBackGroundBrush.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCCameraBackGroundBrush.cpp; sourceTree = ""; }; + B6DD36D41B8564EC0044745A /* CCCameraBackGroundBrush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCCameraBackGroundBrush.h; sourceTree = ""; }; C50306631B60B583001E6D43 /* CCBoneNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCBoneNode.cpp; sourceTree = ""; }; C50306641B60B583001E6D43 /* CCBoneNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCBoneNode.h; sourceTree = ""; }; C50306651B60B583001E6D43 /* CCSkeletonNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCSkeletonNode.cpp; sourceTree = ""; }; @@ -7327,6 +7333,8 @@ 46A169A11807B037005B8026 /* 2d */ = { isa = PBXGroup; children = ( + B6DD36D31B8564EC0044745A /* CCCameraBackGroundBrush.cpp */, + B6DD36D41B8564EC0044745A /* CCCameraBackGroundBrush.h */, 3EACC99C19F5014D00EB3C5E /* CCCamera.cpp */, 3EACC99D19F5014D00EB3C5E /* CCCamera.h */, 3EACC99E19F5014D00EB3C5E /* CCLight.cpp */, @@ -9330,6 +9338,7 @@ 15AE1BDD19AAE01E00C27E9E /* CCControlUtils.h in Headers */, B6CAB3271AF9AA1A00B9B856 /* btGImpactBvh.h in Headers */, 15AE198D19AAD36E00C27E9E /* CheckBoxReader.h in Headers */, + B6DD36D71B8564EC0044745A /* CCCameraBackGroundBrush.h in Headers */, B29A7E0919EE1B7700872B35 /* AttachmentLoader.h in Headers */, 1A01C68818F57BE800EFE3A6 /* CCBool.h in Headers */, B29A7E3319EE1B7700872B35 /* SlotData.h in Headers */, @@ -10810,6 +10819,7 @@ B29A7DDA19EE1B7700872B35 /* SkeletonRenderer.h in Headers */, 15AE194119AAD35100C27E9E /* CCBone.h in Headers */, D0FD035A1A3B51AA00825BB5 /* CCAllocatorStrategyDefault.h in Headers */, + B6DD36D81B8564EC0044745A /* CCCameraBackGroundBrush.h in Headers */, 50ABBD471925AB0000A911A9 /* CCVertex.h in Headers */, B6CAB4D81AF9AA1A00B9B856 /* SpuLocalSupport.h in Headers */, B6CAB2921AF9AA1A00B9B856 /* btCollisionShape.h in Headers */, @@ -11041,6 +11051,7 @@ B6CAB2811AF9AA1A00B9B856 /* btBoxShape.cpp in Sources */, 50ABBE311925AB6F00A911A9 /* CCConfiguration.cpp in Sources */, B665E3821AA80A6500DDB1C5 /* CCPUPathFollower.cpp in Sources */, + B6DD36D51B8564EC0044745A /* CCCameraBackGroundBrush.cpp in Sources */, 1A01C6A418F58F7500EFE3A6 /* CCNotificationCenter.cpp in Sources */, 15AE1A5D19AAD40300C27E9E /* b2Body.cpp in Sources */, 15AE1BDA19AAE01E00C27E9E /* CCControlSwitch.cpp in Sources */, @@ -12051,6 +12062,7 @@ 3EACC9A519F5014D00EB3C5E /* CCLight.cpp in Sources */, 15AE1B7A19AADA9A00C27E9E /* UIScrollView.cpp in Sources */, 1A570076180BC5A10088DEC7 /* CCActionGrid3D.cpp in Sources */, + B6DD36D61B8564EC0044745A /* CCCameraBackGroundBrush.cpp in Sources */, B6CAB38C1AF9AA1A00B9B856 /* btPolyhedralContactClipping.cpp in Sources */, B6CAB3A41AF9AA1A00B9B856 /* btConeTwistConstraint.cpp in Sources */, 15AE19B219AAD39700C27E9E /* SliderReader.cpp in Sources */, diff --git a/cocos/2d/CCCamera.cpp b/cocos/2d/CCCamera.cpp index 1df03955a9..32fdfd055e 100644 --- a/cocos/2d/CCCamera.cpp +++ b/cocos/2d/CCCamera.cpp @@ -25,6 +25,7 @@ ****************************************************************************/ #include "2d/CCCamera.h" +#include "2d/CCCameraBackGroundBrush.h" #include "base/CCDirector.h" #include "platform/CCGLView.h" #include "2d/CCScene.h" @@ -96,11 +97,14 @@ Camera::Camera() , _fbo(nullptr) { _frustum.setClipZ(true); + _clearBrush = CameraBackGroundBrush::createDepthBrush(1.f); + _clearBrush->retain(); } Camera::~Camera() { CC_SAFE_RELEASE_NULL(_fbo); + CC_SAFE_RELEASE(_clearBrush); } const Mat4& Camera::getProjectionMatrix() const @@ -398,86 +402,11 @@ void Camera::setScene(Scene* scene) } } -void Camera::clearBackground(float depth) +void Camera::clearBackground() { - GLboolean oldDepthTest; - GLint oldDepthFunc; - GLboolean oldDepthMask; + if (_clearBrush) { - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glStencilMask(0); - - oldDepthTest = glIsEnabled(GL_DEPTH_TEST); - glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc); - glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthMask); - - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - } - - //draw - static V3F_C4B_T2F_Quad quad; - quad.bl.vertices = Vec3(-1,-1,0); - quad.br.vertices = Vec3(1,-1,0); - quad.tl.vertices = Vec3(-1,1,0); - quad.tr.vertices = Vec3(1,1,0); - - quad.bl.colors = quad.br.colors = quad.tl.colors = quad.tr.colors = Color4B(0,0,0,1); - - quad.bl.texCoords = Tex2F(0,0); - quad.br.texCoords = Tex2F(1,0); - quad.tl.texCoords = Tex2F(0,1); - quad.tr.texCoords = Tex2F(1,1); - - auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_CAMERA_CLEAR); - auto programState = GLProgramState::getOrCreateWithGLProgram(shader); - programState->setUniformFloat("depth", 1.0); - programState->apply(Mat4()); - GLshort indices[6] = {0, 1, 2, 3, 2, 1}; - - { - GL::bindVAO(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); - - // vertices - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &quad.tl.vertices); - - // colors - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), &quad.tl.colors); - - // tex coords - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &quad.tl.texCoords); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); - } - - - { - if(GL_FALSE == oldDepthTest) - { - glDisable(GL_DEPTH_TEST); - } - glDepthFunc(oldDepthFunc); - - if(GL_FALSE == oldDepthMask) - { - glDepthMask(GL_FALSE); - } - - /* IMPORTANT: We only need to update the states that are not restored. - Since we don't know what was the previous value of the mask, we update the RenderState - after setting it. - The other values don't need to be updated since they were restored to their original values - */ - glStencilMask(0xFFFFF); -// RenderState::StateBlock::_defaultState->setStencilWrite(0xFFFFF); - - /* BUG: RenderState does not support glColorMask yet. */ - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + _clearBrush->drawBackGround(this); } } @@ -545,4 +474,11 @@ void Camera::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t par return Node::visit(renderer, parentTransform, parentFlags); } +void Camera::setBackGroundBrush(CameraBackGroundBrush* clearBrush) +{ + CC_SAFE_RETAIN(clearBrush); + CC_SAFE_RELEASE(_clearBrush); + _clearBrush = clearBrush; +} + NS_CC_END diff --git a/cocos/2d/CCCamera.h b/cocos/2d/CCCamera.h index 1b6d253dbe..cd1dd06452 100644 --- a/cocos/2d/CCCamera.h +++ b/cocos/2d/CCCamera.h @@ -36,6 +36,7 @@ THE SOFTWARE. NS_CC_BEGIN class Scene; +class CameraBackGroundBrush; /** * Note: @@ -236,9 +237,9 @@ public: */ static Camera* getDefaultCamera(); /** - Before rendering scene with this camera, the background need to be cleared. + Before rendering scene with this camera, the background need to be cleared. It clears the depth buffer with max depth by default. Use setBackGroundBrush to modify the default behavior */ - void clearBackground(float depth); + void clearBackground(); /** Apply the FBO, RenderTargets and viewport. */ @@ -258,6 +259,17 @@ public: */ bool isViewProjectionUpdated() const {return _viewProjectionUpdated;} + /** + * set the background brush. See CameraBackGroundBrush for more information. + * @param clearBrush Brush used to clear the background + */ + void setBackGroundBrush(CameraBackGroundBrush* clearBrush); + + /** + * Get clear brush + */ + CameraBackGroundBrush* getBackGroundBrush() const { return _clearBrush; } + virtual void visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags) override; CC_CONSTRUCTOR_ACCESS: @@ -300,6 +312,8 @@ protected: int8_t _depth; //camera depth, the depth of camera with CameraFlag::DEFAULT flag is 0 by default, a camera with larger depth is drawn on top of camera with smaller detph static Camera* _visitingCamera; + CameraBackGroundBrush* _clearBrush; //brush used to clear the back ground + experimental::Viewport _viewport; experimental::FrameBuffer* _fbo; diff --git a/cocos/2d/CCCameraBackGroundBrush.cpp b/cocos/2d/CCCameraBackGroundBrush.cpp new file mode 100644 index 0000000000..a9310460ab --- /dev/null +++ b/cocos/2d/CCCameraBackGroundBrush.cpp @@ -0,0 +1,418 @@ +/**************************************************************************** + Copyright (c) 2015 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + ****************************************************************************/ +#include "2d/CCCameraBackGroundBrush.h" +#include "2d/CCCamera.h" +#include "base/ccMacros.h" +#include "base/CCConfiguration.h" +#include "base/CCDirector.h" +#include "renderer/ccGLStateCache.h" +#include "renderer/CCGLProgram.h" +#include "renderer/CCGLProgramCache.h" +#include "renderer/CCGLProgramState.h" +#include "renderer/CCRenderer.h" +#include "renderer/CCRenderState.h" +#include "3d/CCTextureCube.h" + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) +#include "base/CCEventCustom.h" +#include "base/CCEventListenerCustom.h" +#include "base/CCEventType.h" +#include "base/CCEventDispatcher.h" +#endif + +NS_CC_BEGIN + +CameraBackGroundBrush::CameraBackGroundBrush() +: _glProgramState(nullptr) +{ + +} + +CameraBackGroundBrush::~CameraBackGroundBrush() +{ + CC_SAFE_RELEASE(_glProgramState); +} + +CameraBackGroundBrush* CameraBackGroundBrush::createNoneBrush() +{ + auto ret = new (std::nothrow) CameraBackGroundBrush(); + ret->init(); + + ret->autorelease(); + return ret; +} + +CameraBackGroundColorBrush* CameraBackGroundBrush::createColorBrush(const Color4F& color, float depth) +{ + return CameraBackGroundColorBrush::create(color, depth); +} + +CameraBackGroundDepthBrush* CameraBackGroundBrush::createDepthBrush(float depth) +{ + return CameraBackGroundDepthBrush::create(depth); +} + +CameraBackGroundSkyBoxBrush* CameraBackGroundBrush::createSkyboxBrush(const std::string& positive_x, const std::string& negative_x, const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z) +{ + return CameraBackGroundSkyBoxBrush::create(positive_x, negative_x, positive_y, negative_y, positive_z, negative_z); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +CameraBackGroundDepthBrush::CameraBackGroundDepthBrush() +: _depth(0.f) +, _clearColor(GL_FALSE) +{ + +} +CameraBackGroundDepthBrush::~CameraBackGroundDepthBrush() +{ + +} + +CameraBackGroundDepthBrush* CameraBackGroundDepthBrush::create(float depth) +{ + auto ret = new (std::nothrow) CameraBackGroundDepthBrush(); + ret->_depth = depth; + ret->init(); + ret->autorelease(); + return ret; +} + +bool CameraBackGroundDepthBrush::init() +{ + auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_CAMERA_CLEAR); + _glProgramState = GLProgramState::getOrCreateWithGLProgram(shader); + _glProgramState->retain(); + + _quad.bl.vertices = Vec3(-1,-1,0); + _quad.br.vertices = Vec3(1,-1,0); + _quad.tl.vertices = Vec3(-1,1,0); + _quad.tr.vertices = Vec3(1,1,0); + + _quad.bl.colors = _quad.br.colors = _quad.tl.colors = _quad.tr.colors = Color4B(0,0,0,1); + + _quad.bl.texCoords = Tex2F(0,0); + _quad.br.texCoords = Tex2F(1,0); + _quad.tl.texCoords = Tex2F(0,1); + _quad.tr.texCoords = Tex2F(1,1); + return true; +} + +void CameraBackGroundDepthBrush::drawBackGround(Camera* camera) +{ + GLboolean oldDepthTest; + GLint oldDepthFunc; + GLboolean oldDepthMask; + { + glColorMask(_clearColor, _clearColor, _clearColor, _clearColor); + glStencilMask(0); + + oldDepthTest = glIsEnabled(GL_DEPTH_TEST); + glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc); + glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthMask); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + } + + //draw + + _glProgramState->setUniformFloat("depth", _depth); + _glProgramState->apply(Mat4::IDENTITY); + GLshort indices[6] = {0, 1, 2, 3, 2, 1}; + + { + GL::bindVAO(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); + + // vertices + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &_quad.tl.vertices); + + // colors + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), &_quad.tl.colors); + + // tex coords + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &_quad.tl.texCoords); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + } + + + { + if(GL_FALSE == oldDepthTest) + { + glDisable(GL_DEPTH_TEST); + } + glDepthFunc(oldDepthFunc); + + if(GL_FALSE == oldDepthMask) + { + glDepthMask(GL_FALSE); + } + + /* IMPORTANT: We only need to update the states that are not restored. + Since we don't know what was the previous value of the mask, we update the RenderState + after setting it. + The other values don't need to be updated since they were restored to their original values + */ + glStencilMask(0xFFFFF); + // RenderState::StateBlock::_defaultState->setStencilWrite(0xFFFFF); + + /* BUG: RenderState does not support glColorMask yet. */ + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +CameraBackGroundColorBrush::CameraBackGroundColorBrush() +: _color(0.f, 0.f, 0.f, 0.f) +{ + +} + +CameraBackGroundColorBrush::~CameraBackGroundColorBrush() +{ + +} + +void CameraBackGroundColorBrush::setColor(const Color4F& color) +{ + _quad.bl.colors = _quad.br.colors = _quad.tl.colors = _quad.tr.colors = Color4B(color); +} + +CameraBackGroundColorBrush* CameraBackGroundColorBrush::create(const Color4F& color, float depth) +{ + auto ret = new (std::nothrow) CameraBackGroundColorBrush(); + ret->init(); + ret->_clearColor = GL_TRUE; + ret->setColor(color); + ret->setDepth(depth); + + ret->autorelease(); + return ret; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +CameraBackGroundSkyBoxBrush::CameraBackGroundSkyBoxBrush() +: _vao(0) +, _vertexBuffer(0) +, _indexBuffer(0) +, _texture(nullptr) +{ +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, + [this](EventCustom*) + { + initBuffer(); + } + ); + Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); +#endif +} + +CameraBackGroundSkyBoxBrush::~CameraBackGroundSkyBoxBrush() +{ + CC_SAFE_RELEASE(_texture); + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteBuffers(1, &_indexBuffer); + + _vertexBuffer = 0; + _indexBuffer = 0; + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glDeleteVertexArrays(1, &_vao); + GL::bindVAO(0); + _vao = 0; + } +} + +CameraBackGroundSkyBoxBrush* CameraBackGroundSkyBoxBrush::create(const std::string& positive_x, const std::string& negative_x, const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z) +{ + auto texture = TextureCube::create(positive_x, negative_x, positive_y, negative_y, positive_z, negative_z); + if (texture == nullptr) + return nullptr; + + Texture2D::TexParams tRepeatParams; + tRepeatParams.magFilter = GL_LINEAR; + tRepeatParams.minFilter = GL_LINEAR; + tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; + tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; + texture->setTexParameters(tRepeatParams); + + auto ret = new(std::nothrow)CameraBackGroundSkyBoxBrush(); + + ret->init(); + ret->setTexture(texture); + + ret->autorelease(); + return ret; +} + +CameraBackGroundSkyBoxBrush* CameraBackGroundSkyBoxBrush::create() +{ + auto ret = new(std::nothrow)CameraBackGroundSkyBoxBrush(); + + ret->init(); + + ret->autorelease(); + return ret; +} + +void CameraBackGroundSkyBoxBrush::drawBackGround(Camera* camera) +{ + Mat4 cameraModelMat = camera->getNodeToWorldTransform(); + + _glProgramState->apply(Mat4::IDENTITY); + + Vec4 color(1.f, 1.f, 1.f, 1.f); + _glProgramState->setUniformVec4("u_color", color); + cameraModelMat.m[12] = cameraModelMat.m[13] = cameraModelMat.m[14] = 0; + _glProgramState->setUniformMat4("u_cameraRot", cameraModelMat); + + glEnable(GL_DEPTH_TEST); + RenderState::StateBlock::_defaultState->setDepthTest(true); + + glDepthFunc(GL_LEQUAL); + RenderState::StateBlock::_defaultState->setDepthFunction(RenderState::DEPTH_LEQUAL); + + glEnable(GL_CULL_FACE); + RenderState::StateBlock::_defaultState->setCullFace(true); + + glCullFace(GL_BACK); + RenderState::StateBlock::_defaultState->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK); + + if (Configuration::getInstance()->supportsShareableVAO()) + { + GL::bindVAO(_vao); + } + else + { + GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION); + + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); + } + + glDrawElements(GL_TRIANGLES, (GLsizei)36, GL_UNSIGNED_BYTE, nullptr); + + if (Configuration::getInstance()->supportsShareableVAO()) + { + GL::bindVAO(0); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 8); + + CHECK_GL_ERROR_DEBUG(); +} + +bool CameraBackGroundSkyBoxBrush::init() +{ + auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKYBOX); + _glProgramState = GLProgramState::create(shader); + _glProgramState->setVertexAttribPointer(GLProgram::ATTRIBUTE_NAME_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); + _glProgramState->retain(); + + initBuffer(); + + return true; +} + +void CameraBackGroundSkyBoxBrush::initBuffer() +{ + if (_vertexBuffer) + glDeleteBuffers(1, &_vertexBuffer); + if (_indexBuffer) + glDeleteBuffers(1, &_indexBuffer); + + if (Configuration::getInstance()->supportsShareableVAO() && _vao) + { + glDeleteVertexArrays(1, &_vao); + GL::bindVAO(0); + _vao = 0; + } + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glGenVertexArrays(1, &_vao); + GL::bindVAO(_vao); + } + + // init vertex buffer object + Vec3 vexBuf[] = + { + Vec3(1, -1, 1), Vec3(1, 1, 1), Vec3(-1, 1, 1), Vec3(-1, -1, 1), + Vec3(1, -1, -1), Vec3(1, 1, -1), Vec3(-1, 1, -1), Vec3(-1, -1, -1) + }; + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STATIC_DRAW); + + // init index buffer object + const unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, // font + 1, 5, 4, 1, 4, 0, // right + 4, 5, 6, 4, 6, 7, // back + 7, 6, 2, 7, 2, 3, // left + 2, 6, 5, 2, 5, 1, // up + 3, 0, 4, 3, 4, 7 // down + }; + + glGenBuffers(1, &_indexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxBuf), idxBuf, GL_STATIC_DRAW); + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); + _glProgramState->applyAttributes(false); + + GL::bindVAO(0); + } +} + +void CameraBackGroundSkyBoxBrush::setTexture(TextureCube* texture) +{ + CC_SAFE_RETAIN(texture); + CC_SAFE_RELEASE(_texture); + _texture = texture; + _glProgramState->setUniformTexture("u_Env", _texture); +} + +NS_CC_END diff --git a/cocos/2d/CCCameraBackGroundBrush.h b/cocos/2d/CCCameraBackGroundBrush.h new file mode 100644 index 0000000000..152ea98c88 --- /dev/null +++ b/cocos/2d/CCCameraBackGroundBrush.h @@ -0,0 +1,263 @@ +/**************************************************************************** + Copyright (c) 2015 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + ****************************************************************************/ +#ifndef _CCCAMERA_BACKGROUND_BRUSH_H__ +#define _CCCAMERA_BACKGROUND_BRUSH_H__ + +#include "base/ccTypes.h" +#include "base/CCRef.h" +#include "3d/CCFrustum.h" +#include "renderer/CCQuadCommand.h" +#include "renderer/CCCustomCommand.h" +#include "renderer/CCFrameBuffer.h" + +NS_CC_BEGIN + +class CameraBackGroundColorBrush; +class CameraBackGroundDepthBrush; +class CameraBackGroundSkyBoxBrush; + +class GLProgramState; +class Camera; + +/** + * Defines a brush to clear the background of camera. + * There are 4 types of brush. None brush do nothing, Depth brush clear background with given depth, Color brush clear background with given color and depth, Skybox brush clear the background with a skybox. Camera uses depth brush by default. + */ +class CC_DLL CameraBackGroundBrush : public Ref +{ +public: + /** + * Brush types. There are 4 types of brush. See CameraBackGroundDepthBrush, CameraBackGroundColorBrush, CameraBackGroundSkyBoxBrush for more information. + */ + enum class BrushType + { + NONE, //none brush + DEPTH, // depth brush. See CameraBackGroundDepthBrush + COLOR, // color brush. See CameraBackGroundColorBrush + SKYBOX, // skybox brush. See CameraBackGroundSkyBoxBrush + }; + + /** + * get brush type + * @return BrushType + */ + virtual BrushType getBrushType() const { return BrushType::NONE; } + + /** + * Creates a none brush, it does nothing when clear the background + * @return Created brush. + */ + static CameraBackGroundBrush* createNoneBrush(); + + /** + * Creates a depth brush, which clears depth buffer with a given depth. + * @param depth Depth used to clear depth buffer + * @return Created brush + */ + static CameraBackGroundDepthBrush* createDepthBrush(float depth = 1.f); + + /** + * Creates a color brush + * @param color Color of brush + * @param depth Depth used to clear depth buffer + * @return Created brush + */ + static CameraBackGroundColorBrush* createColorBrush(const Color4F& color, float depth); + + + /** Creates a Skybox brush with 6 textures. + @param positive_x texture for the right side of the texture cube face. + @param negative_x texture for the up side of the texture cube face. + @param positive_y texture for the top side of the texture cube face + @param negative_y texture for the bottom side of the texture cube face + @param positive_z texture for the forward side of the texture cube face. + @param negative_z texture for the rear side of the texture cube face. + @return A new brush inited with given parameters. + */ + static CameraBackGroundSkyBoxBrush* createSkyboxBrush(const std::string& positive_x, const std::string& negative_x, + const std::string& positive_y, const std::string& negative_y, + const std::string& positive_z, const std::string& negative_z); + /** + * draw the background + */ + virtual void drawBackGround(Camera* camera) {} + +CC_CONSTRUCTOR_ACCESS: + CameraBackGroundBrush(); + virtual ~CameraBackGroundBrush(); + +protected: + virtual bool init() { return true; } + + GLProgramState* _glProgramState; +}; + +/** + * Depth brush clear depth buffer with given depth + */ +class CC_DLL CameraBackGroundDepthBrush : public CameraBackGroundBrush +{ +public: + /** + * Create a depth brush + * @param depth Depth used to clear the depth buffer + * @return Created brush + */ + static CameraBackGroundDepthBrush* create(float depth); + + /** + * Get brush type. Should be BrushType::DEPTH + * @return brush type + */ + virtual BrushType getBrushType() const override { return BrushType::DEPTH; } + + /** + * Draw background + */ + virtual void drawBackGround(Camera* camera) override; + + /** + * Set depth + * @param depth Depth used to clear depth buffer + */ + void setDepth(float depth) { _depth = depth; } + +CC_CONSTRUCTOR_ACCESS: + CameraBackGroundDepthBrush(); + virtual ~CameraBackGroundDepthBrush(); + +protected: + virtual bool init() override; + + float _depth; + + GLboolean _clearColor; + + V3F_C4B_T2F_Quad _quad; +}; + +/** + * Color brush clear buffer with given depth and color + */ +class CC_DLL CameraBackGroundColorBrush : public CameraBackGroundDepthBrush +{ +public: + /** + * Get brush type. Should be BrushType::COLOR + * @return brush type + */ + virtual BrushType getBrushType() const override { return BrushType::COLOR; } + + /** + * Create a color brush + * @param color Color used to clear the color buffer + * @param depth Depth used to clear the depth buffer + * @return Created brush + */ + static CameraBackGroundColorBrush* create(const Color4F& color, float depth); + + /** + * Set clear color + * @param color Color used to clear the color buffer + */ + void setColor(const Color4F& color); + +CC_CONSTRUCTOR_ACCESS: + CameraBackGroundColorBrush(); + virtual ~CameraBackGroundColorBrush(); + +protected: + + Color4F _color; +}; + +class TextureCube; +class GLProgramState; +class EventListenerCustom; + +/** + * Skybox brush clear buffer with a skybox + */ +class CC_DLL CameraBackGroundSkyBoxBrush : public CameraBackGroundBrush +{ +public: + /** + * Get brush type. Should be BrushType::SKYBOX + * @return brush type + */ + virtual BrushType getBrushType() const override { return BrushType::SKYBOX; } + + /** Creates a Skybox brush with 6 textures. + @param positive_x texture for the right side of the texture cube face. + @param negative_x texture for the up side of the texture cube face. + @param positive_y texture for the top side of the texture cube face + @param negative_y texture for the bottom side of the texture cube face + @param positive_z texture for the forward side of the texture cube face. + @param negative_z texture for the rear side of the texture cube face. + @return A new brush inited with given parameters. + */ + static CameraBackGroundSkyBoxBrush* create(const std::string& positive_x, const std::string& negative_x, + const std::string& positive_y, const std::string& negative_y, + const std::string& positive_z, const std::string& negative_z); + + /** Creates a Skybox brush with 6 textures. + */ + static CameraBackGroundSkyBoxBrush* create(); + /** + * Set skybox texutre + * @param texture Skybox texture + */ + void setTexture(TextureCube* texture); + + /** + * Draw background + */ + virtual void drawBackGround(Camera* camera) override; + +CC_CONSTRUCTOR_ACCESS: + CameraBackGroundSkyBoxBrush(); + virtual ~CameraBackGroundSkyBoxBrush(); + + /** + * init Skybox. + */ + virtual bool init() override; + + void initBuffer(); + + GLuint _vao; + GLuint _vertexBuffer; + GLuint _indexBuffer; + + TextureCube* _texture; + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + EventListenerCustom* _backToForegroundListener; +#endif +}; + +NS_CC_END + +#endif// _CCCAMERA_BACKGROUND_BRUSH_H__ diff --git a/cocos/2d/CCScene.cpp b/cocos/2d/CCScene.cpp index bd1a8ddab6..336433654d 100644 --- a/cocos/2d/CCScene.cpp +++ b/cocos/2d/CCScene.cpp @@ -194,7 +194,7 @@ void Scene::render(Renderer* renderer) director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, Camera::_visitingCamera->getViewProjectionMatrix()); camera->apply(); //clear background with max depth - camera->clearBackground(1.0); + camera->clearBackground(); //visit the scene visit(renderer, transform, 0); #if CC_USE_NAVMESH diff --git a/cocos/2d/CMakeLists.txt b/cocos/2d/CMakeLists.txt index dadb7100bb..d76096e7ce 100644 --- a/cocos/2d/CMakeLists.txt +++ b/cocos/2d/CMakeLists.txt @@ -24,6 +24,7 @@ set(COCOS_2D_SRC 2d/CCAnimation.cpp 2d/CCAtlasNode.cpp 2d/CCCamera.cpp + 2d/CCCameraBackGroundBrush.cpp 2d/CCClippingNode.cpp 2d/CCClippingRectangleNode.cpp 2d/CCComponentContainer.cpp diff --git a/cocos/2d/libcocos2d.vcxproj b/cocos/2d/libcocos2d.vcxproj index 35b3c43480..3c15cea25c 100644 --- a/cocos/2d/libcocos2d.vcxproj +++ b/cocos/2d/libcocos2d.vcxproj @@ -681,6 +681,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + @@ -1296,6 +1297,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + diff --git a/cocos/2d/libcocos2d.vcxproj.filters b/cocos/2d/libcocos2d.vcxproj.filters index bb2e25cb78..e0cd832b95 100644 --- a/cocos/2d/libcocos2d.vcxproj.filters +++ b/cocos/2d/libcocos2d.vcxproj.filters @@ -1931,6 +1931,9 @@ network\Source Files + + 2d + @@ -3765,6 +3768,9 @@ network\Header Files + + 2d + diff --git a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems index 9738344739..0871e51cb5 100644 --- a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems +++ b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems @@ -584,6 +584,7 @@ + @@ -1178,6 +1179,7 @@ + diff --git a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters index 5d90a435bc..31439fd209 100644 --- a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters +++ b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters @@ -1867,6 +1867,9 @@ cocostudio\reader\WidgetReader\GameNodeDReader + + 2d + @@ -3564,6 +3567,9 @@ cocostudio\reader\WidgetReader\GameNodeDReader + + 2d + diff --git a/cocos/Android.mk b/cocos/Android.mk index 608a575bc9..3635a8d21a 100644 --- a/cocos/Android.mk +++ b/cocos/Android.mk @@ -35,6 +35,7 @@ cocos2d.cpp \ 2d/CCAnimationCache.cpp \ 2d/CCAtlasNode.cpp \ 2d/CCCamera.cpp \ +2d/CCCameraBackGroundBrush.cpp \ 2d/CCClippingNode.cpp \ 2d/CCClippingRectangleNode.cpp \ 2d/CCComponent.cpp \ diff --git a/cocos/cocos2d.h b/cocos/cocos2d.h index c63d321809..d1dde6d6b0 100644 --- a/cocos/cocos2d.h +++ b/cocos/cocos2d.h @@ -138,6 +138,7 @@ THE SOFTWARE. // 2d utils #include "2d/CCCamera.h" +#include "2d/CCCameraBackGroundBrush.h" #include "2d/CCGrabber.h" #include "2d/CCGrid.h" #include "2d/CCLight.h" diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 3996b8587c..2f5a7cb257 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -25,6 +25,7 @@ #include "Sprite3DTest.h" #include "DrawNode3D.h" +#include "2d/CCCameraBackGroundBrush.h" #include "extensions/Particle3D/PU/CCPUParticleSystem3D.h" @@ -61,6 +62,7 @@ Sprite3DTests::Sprite3DTests() ADD_TEST_CASE(Sprite3DClippingTest); ADD_TEST_CASE(Sprite3DTestMeshLight); ADD_TEST_CASE(Animate3DCallbackTest); + ADD_TEST_CASE(CameraBackGroundClearTest); }; //------------------------------------------------------------------ @@ -2720,3 +2722,66 @@ std::string Sprite3DTestMeshLight::subtitle() const { return ""; } + +CameraBackGroundClearTest::CameraBackGroundClearTest() +{ + TTFConfig ttfConfig("fonts/arial.ttf", 20); + auto label1 = Label::createWithTTF(ttfConfig,"Clear Mode"); + auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(CameraBackGroundClearTest::switch_CameraClearMode,this) ); + + item1->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*4 ) ); + + auto pMenu1 = Menu::create(item1, nullptr); + pMenu1->setPosition(Vec2(0,0)); + this->addChild(pMenu1, 10); + + //setup camera + auto s = Director::getInstance()->getWinSize(); + _camera = Camera::createPerspective(40, s.width / s.height, 0.01f, 1000.f); + _camera->setCameraFlag(CameraFlag::USER1); + _camera->setPosition3D(Vec3(0.f, 30.f, 100.f)); + _camera->lookAt(Vec3(0.f, 0.f, 0.f)); + addChild(_camera); + + auto sprite = Sprite3D::create("Sprite3DTest/orc.c3b"); + addChild(sprite); + sprite->setCameraMask(2); + + _label = Label::createWithTTF(ttfConfig, "Depth Clear Brush"); + addChild(_label); + _label->setPosition(s.width / 2.f , VisibleRect::top().y * 0.8f); +} + +void CameraBackGroundClearTest::switch_CameraClearMode(cocos2d::Ref* sender) +{ + auto type = _camera->getBackGroundBrush()->getBrushType(); + if (type == CameraBackGroundBrush::BrushType::NONE) + { + _camera->setBackGroundBrush(CameraBackGroundBrush::createDepthBrush(1.f)); + _label->setString("Depth Clear Brush"); + } + else if (type == CameraBackGroundBrush::BrushType::DEPTH) + { + _camera->setBackGroundBrush(CameraBackGroundBrush::createColorBrush(Color4F(1.f, 0.f, 0.f, 1.f), 1.f)); + _label->setString("Color Clear Brush"); + } + else if (type == CameraBackGroundBrush::BrushType::COLOR) + { + _camera->setBackGroundBrush(CameraBackGroundBrush::createSkyboxBrush("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg","Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg","Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg")); + _label->setString("Skybox Clear Brush"); + } + else if (type == CameraBackGroundBrush::BrushType::SKYBOX) + { + _camera->setBackGroundBrush(CameraBackGroundBrush::createNoneBrush()); + _label->setString("None Clear Brush"); + } +} + +std::string CameraBackGroundClearTest::title() const +{ + return "Camera Background Clear Brush"; +} +std::string CameraBackGroundClearTest::subtitle() const +{ + return ""; +} diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 9a8cca3ef1..27044b98f8 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -592,4 +592,18 @@ protected: cocos2d::Sprite3D* _sprite; }; +class CameraBackGroundClearTest : public Sprite3DTestDemo +{ +public: + CREATE_FUNC(CameraBackGroundClearTest); + CameraBackGroundClearTest(); + virtual std::string title() const override; + virtual std::string subtitle() const override; + + void switch_CameraClearMode(cocos2d::Ref* sender); +protected: + cocos2d::Camera* _camera; + cocos2d::Label* _label; +}; + #endif