diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index 97f01b41c4..3faf7dc529 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -2564,6 +2564,14 @@ B68779051A8CA82E00643ABF /* CCParticleSystem3D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B68778F61A8CA82E00643ABF /* CCParticleSystem3D.cpp */; }; B68779061A8CA82E00643ABF /* CCParticleSystem3D.h in Headers */ = {isa = PBXBuildFile; fileRef = B68778F71A8CA82E00643ABF /* CCParticleSystem3D.h */; }; B68779071A8CA82E00643ABF /* CCParticleSystem3D.h in Headers */ = {isa = PBXBuildFile; fileRef = B68778F71A8CA82E00643ABF /* CCParticleSystem3D.h */; }; + B6D38B8A1AC3AFAC00043997 /* CCSkybox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6D38B861AC3AFAC00043997 /* CCSkybox.cpp */; }; + B6D38B8B1AC3AFAC00043997 /* CCSkybox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6D38B861AC3AFAC00043997 /* CCSkybox.cpp */; }; + B6D38B8C1AC3AFAC00043997 /* CCSkybox.h in Headers */ = {isa = PBXBuildFile; fileRef = B6D38B871AC3AFAC00043997 /* CCSkybox.h */; }; + B6D38B8D1AC3AFAC00043997 /* CCSkybox.h in Headers */ = {isa = PBXBuildFile; fileRef = B6D38B871AC3AFAC00043997 /* CCSkybox.h */; }; + B6D38B8E1AC3AFAC00043997 /* CCTextureCube.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6D38B881AC3AFAC00043997 /* CCTextureCube.cpp */; }; + B6D38B8F1AC3AFAC00043997 /* CCTextureCube.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6D38B881AC3AFAC00043997 /* CCTextureCube.cpp */; }; + B6D38B901AC3AFAC00043997 /* CCTextureCube.h in Headers */ = {isa = PBXBuildFile; fileRef = B6D38B891AC3AFAC00043997 /* CCTextureCube.h */; }; + B6D38B911AC3AFAC00043997 /* CCTextureCube.h in Headers */ = {isa = PBXBuildFile; fileRef = B6D38B891AC3AFAC00043997 /* CCTextureCube.h */; }; D0FD03491A3B51AA00825BB5 /* CCAllocatorBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FD033B1A3B51AA00825BB5 /* CCAllocatorBase.h */; }; D0FD034A1A3B51AA00825BB5 /* CCAllocatorBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FD033B1A3B51AA00825BB5 /* CCAllocatorBase.h */; }; D0FD034B1A3B51AA00825BB5 /* CCAllocatorDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0FD033C1A3B51AA00825BB5 /* CCAllocatorDiagnostics.cpp */; }; @@ -3973,6 +3981,14 @@ B68778F51A8CA82E00643ABF /* CCParticle3DRender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCParticle3DRender.h; path = Particle3D/CCParticle3DRender.h; sourceTree = ""; }; B68778F61A8CA82E00643ABF /* CCParticleSystem3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCParticleSystem3D.cpp; path = Particle3D/CCParticleSystem3D.cpp; sourceTree = ""; }; B68778F71A8CA82E00643ABF /* CCParticleSystem3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCParticleSystem3D.h; path = Particle3D/CCParticleSystem3D.h; sourceTree = ""; }; + B6D38B861AC3AFAC00043997 /* CCSkybox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCSkybox.cpp; sourceTree = ""; }; + B6D38B871AC3AFAC00043997 /* CCSkybox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSkybox.h; sourceTree = ""; }; + B6D38B881AC3AFAC00043997 /* CCTextureCube.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCTextureCube.cpp; sourceTree = ""; }; + B6D38B891AC3AFAC00043997 /* CCTextureCube.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTextureCube.h; sourceTree = ""; }; + B6D38B941AC3B45600043997 /* ccShader_3D_Particle.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_Particle.frag; sourceTree = ""; }; + B6D38B951AC3B45600043997 /* ccShader_3D_Particle.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_Particle.vert; sourceTree = ""; }; + B6D38B961AC3B45600043997 /* ccShader_3D_Skybox.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_Skybox.frag; sourceTree = ""; }; + B6D38B971AC3B45600043997 /* ccShader_3D_Skybox.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_Skybox.vert; sourceTree = ""; }; D0FD033B1A3B51AA00825BB5 /* CCAllocatorBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAllocatorBase.h; sourceTree = ""; }; D0FD033C1A3B51AA00825BB5 /* CCAllocatorDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCAllocatorDiagnostics.cpp; sourceTree = ""; }; D0FD033D1A3B51AA00825BB5 /* CCAllocatorDiagnostics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAllocatorDiagnostics.h; sourceTree = ""; }; @@ -5857,6 +5873,10 @@ 5034CA5D191D591900CE6051 /* shaders */ = { isa = PBXGroup; children = ( + B6D38B941AC3B45600043997 /* ccShader_3D_Particle.frag */, + B6D38B951AC3B45600043997 /* ccShader_3D_Particle.vert */, + B6D38B961AC3B45600043997 /* ccShader_3D_Skybox.frag */, + B6D38B971AC3B45600043997 /* ccShader_3D_Skybox.vert */, B20564AA1A6E5744001C1B6E /* ccShader_PositionColorTextureAsPointsize.vert */, B67C624319D4186F00F11FC6 /* ccShader_3D_ColorNormal.frag */, B67C624419D4186F00F11FC6 /* ccShader_3D_ColorNormalTex.frag */, @@ -6153,6 +6173,10 @@ B29594B81926D61F003EEF37 /* 3d */ = { isa = PBXGroup; children = ( + B6D38B861AC3AFAC00043997 /* CCSkybox.cpp */, + B6D38B871AC3AFAC00043997 /* CCSkybox.h */, + B6D38B881AC3AFAC00043997 /* CCTextureCube.cpp */, + B6D38B891AC3AFAC00043997 /* CCTextureCube.h */, 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */, 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */, 5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */, @@ -6548,6 +6572,7 @@ 15AE1A5319AAD40300C27E9E /* b2Draw.h in Headers */, B665E25C1AA80A6500DDB1C5 /* CCPUDoEnableComponentEventHandler.h in Headers */, 38B8E2E319E671D2002D7CE7 /* UILayoutComponent.h in Headers */, + B6D38B8C1AC3AFAC00043997 /* CCSkybox.h in Headers */, 5034CA39191D591100CE6051 /* ccShader_PositionColorLengthTexture.frag in Headers */, 292DB14B19B4574100A80320 /* UIEditBoxImpl-mac.h in Headers */, B29A7E3F19EE1B7700872B35 /* AnimationState.h in Headers */, @@ -7013,6 +7038,7 @@ 50ABBD621925AB0000A911A9 /* Vec4.h in Headers */, B60C5BD619AC68B10056FBDE /* CCBillBoard.h in Headers */, 15AE1BA419AADFDF00C27E9E /* UILayoutManager.h in Headers */, + B6D38B901AC3AFAC00043997 /* CCTextureCube.h in Headers */, 1A01C69418F57BE800EFE3A6 /* CCFloat.h in Headers */, 1A57034D180BD09B0088DEC7 /* tinyxml2.h in Headers */, 15AE18F519AAD35000C27E9E /* CCArmatureDefine.h in Headers */, @@ -7575,6 +7601,7 @@ 1A570224180BCC1A0088DEC7 /* CCParticleBatchNode.h in Headers */, 15AE1AC919AAD40300C27E9E /* b2Joint.h in Headers */, 382383EF1A258FA7002C4610 /* flatbuffers.h in Headers */, + B6D38B911AC3AFAC00043997 /* CCTextureCube.h in Headers */, B665E2811AA80A6500DDB1C5 /* CCPUDoScaleEventHandlerTranslator.h in Headers */, 15AE196819AAD35100C27E9E /* CCUtilMath.h in Headers */, B29A7E2019EE1B7700872B35 /* BoneData.h in Headers */, @@ -7770,6 +7797,7 @@ B665E2CD1AA80A6500DDB1C5 /* CCPUGravityAffectorTranslator.h in Headers */, 50ABBD4F1925AB0000A911A9 /* MathUtil.h in Headers */, 1A01C69718F57BE800EFE3A6 /* CCInteger.h in Headers */, + B6D38B8D1AC3AFAC00043997 /* CCSkybox.h in Headers */, 15AE1C0619AAE01E00C27E9E /* CCTableViewCell.h in Headers */, B665E4251AA80A6600DDB1C5 /* CCPUTranslateManager.h in Headers */, 15AE19AB19AAD39700C27E9E /* ListViewReader.h in Headers */, @@ -8021,6 +8049,7 @@ 50ABBDA71925AB4100A911A9 /* CCRenderCommand.cpp in Sources */, B665E35E1AA80A6500DDB1C5 /* CCPUOnRandomObserverTranslator.cpp in Sources */, B665E24E1AA80A6500DDB1C5 /* CCPUColorAffectorTranslator.cpp in Sources */, + B6D38B8E1AC3AFAC00043997 /* CCTextureCube.cpp in Sources */, 15AE1B9B19AADFDF00C27E9E /* UIRelativeBox.cpp in Sources */, B665E3E21AA80A6600DDB1C5 /* CCPUSineForceAffector.cpp in Sources */, 50ABBD501925AB0000A911A9 /* Quaternion.cpp in Sources */, @@ -8328,6 +8357,7 @@ 15AE182019AAD2F700C27E9E /* CCBundleReader.cpp in Sources */, B665E2421AA80A6500DDB1C5 /* CCPUCollisionAvoidanceAffector.cpp in Sources */, 15AE1AD819AAD41000C27E9E /* b2Rope.cpp in Sources */, + B6D38B8A1AC3AFAC00043997 /* CCSkybox.cpp in Sources */, B665E3521AA80A6500DDB1C5 /* CCPUOnQuotaObserver.cpp in Sources */, B29A7DC719EE1B7700872B35 /* SkeletonRenderer.cpp in Sources */, 15AE1A7C19AAD40300C27E9E /* b2MotorJoint.cpp in Sources */, @@ -8848,6 +8878,7 @@ 15AE1AA519AAD40300C27E9E /* b2Fixture.cpp in Sources */, B29A7DE219EE1B7700872B35 /* MeshAttachment.c in Sources */, 50ED2BE719BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp in Sources */, + B6D38B8F1AC3AFAC00043997 /* CCTextureCube.cpp in Sources */, 15AE1BAD19AADFDF00C27E9E /* UILayoutParameter.cpp in Sources */, 3823843E1A259140002C4610 /* SingleNodeReader.cpp in Sources */, B29A7DDE19EE1B7700872B35 /* BoneData.c in Sources */, @@ -8886,6 +8917,7 @@ 15AE1A9D19AAD40300C27E9E /* b2StackAllocator.cpp in Sources */, B665E34F1AA80A6500DDB1C5 /* CCPUOnPositionObserverTranslator.cpp in Sources */, 1A5701EF180BCB8C0088DEC7 /* CCTransitionProgress.cpp in Sources */, + B6D38B8B1AC3AFAC00043997 /* CCSkybox.cpp in Sources */, 1A5701F8180BCBAD0088DEC7 /* CCMenu.cpp in Sources */, 382384141A259092002C4610 /* NodeReaderProtocol.cpp in Sources */, 50ABBD511925AB0000A911A9 /* Quaternion.cpp in Sources */, diff --git a/cocos/2d/libcocos2d.vcxproj b/cocos/2d/libcocos2d.vcxproj index c2432f1adb..96f5083022 100755 --- a/cocos/2d/libcocos2d.vcxproj +++ b/cocos/2d/libcocos2d.vcxproj @@ -388,8 +388,10 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + + @@ -912,8 +914,10 @@ 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 6a5664a0b0..8cc70f8955 100755 --- a/cocos/2d/libcocos2d.vcxproj.filters +++ b/cocos/2d/libcocos2d.vcxproj.filters @@ -1333,6 +1333,12 @@ 3d + + 3d + + + 3d + extension\Particle3D\ParticleUniverse @@ -3040,6 +3046,12 @@ physics + + 3d + + + 3d + platform 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 430cb070f4..339ff0ab88 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 @@ -219,8 +219,10 @@ + + @@ -802,8 +804,10 @@ + + NotUsing 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 2295b95218..be937fc075 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 @@ -1,4 +1,4 @@ - + @@ -1737,6 +1737,12 @@ cocostudio\json + + 3d + + + 3d + @@ -3300,6 +3306,12 @@ cocostudio\json + + 3d + + + 3d + diff --git a/cocos/2d/libcocos2d_wp8.vcxproj b/cocos/2d/libcocos2d_wp8.vcxproj index 2bd3354056..6b862f370e 100644 --- a/cocos/2d/libcocos2d_wp8.vcxproj +++ b/cocos/2d/libcocos2d_wp8.vcxproj @@ -386,8 +386,10 @@ + + @@ -990,8 +992,10 @@ + + diff --git a/cocos/2d/libcocos2d_wp8.vcxproj.filters b/cocos/2d/libcocos2d_wp8.vcxproj.filters index 93d1161219..9e6d9e7b74 100644 --- a/cocos/2d/libcocos2d_wp8.vcxproj.filters +++ b/cocos/2d/libcocos2d_wp8.vcxproj.filters @@ -1809,6 +1809,12 @@ cocostudio\json + + 3d + + + 3d + @@ -3516,6 +3522,12 @@ cocostudio\json + + 3d + + + 3d + diff --git a/cocos/3d/Android.mk b/cocos/3d/Android.mk index 9710c56be0..da02ad5649 100644 --- a/cocos/3d/Android.mk +++ b/cocos/3d/Android.mk @@ -21,7 +21,9 @@ CCMeshVertexIndexData.cpp \ CCSprite3DMaterial.cpp \ CCObjLoader.cpp \ CCSkeleton3D.cpp \ -CCSprite3D.cpp +CCSprite3D.cpp \ +CCSkybox.cpp \ +CCTextureCube.cpp LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.. diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp new file mode 100644 index 0000000000..c9eb9705dc --- /dev/null +++ b/cocos/3d/CCSkybox.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** + 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 "3d/CCSkybox.h" +#include "3d/CCTextureCube.h" + +NS_CC_BEGIN + +Skybox::Skybox() + : _vao(0) + , _vertexBuffer(0) + , _indexBuffer(0) + ,_texture(nullptr) +{ +} + +Skybox::~Skybox() +{ + glDeleteBuffers(1, &_vertexBuffer); + glDeleteBuffers(1, &_indexBuffer); + + _vertexBuffer = 0; + _indexBuffer = 0; + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glDeleteVertexArrays(1, &_vao); + GL::bindVAO(0); + _vao = 0; + } + + _texture->release(); +} + +bool Skybox::init() +{ + // create and set our custom shader + auto shader = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKYBOX); + auto state = GLProgramState::create(shader); + state->setVertexAttribPointer(GLProgram::ATTRIBUTE_NAME_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); + setGLProgramState(state); + + initBuffers(); + + CHECK_GL_ERROR_DEBUG(); + + return true; +} + +void Skybox::initBuffers() +{ + 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); + getGLProgramState()->applyAttributes(false); + + GL::bindVAO(0); + } +} + +void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) +{ + _customCommand.init(_globalZOrder); + _customCommand.func = CC_CALLBACK_0(Skybox::onDraw, this, transform, flags); + renderer->addCommand(&_customCommand); +} + +void Skybox::onDraw(const Mat4& transform, uint32_t flags) +{ + auto state = getGLProgramState(); + state->apply(transform); + + GLboolean depthFlag = glIsEnabled(GL_DEPTH_TEST); + GLint depthFunc; + glGetIntegerv(GL_DEPTH_FUNC, &depthFunc); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + 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); + + glDepthFunc(depthFunc); + if (!depthFlag) + glDisable(GL_DEPTH_TEST); + + CHECK_GL_ERROR_DEBUG(); +} + +void Skybox::setTexture(TextureCube* texture) +{ + CCASSERT(texture != nullptr, __FUNCTION__); + + texture->retain(); + + if (_texture) + _texture->release(); + + _texture = texture; + + getGLProgramState()->setUniformTexture("u_Env", _texture); +} + +void Skybox::reload() +{ + auto glProgram = getGLProgramState()->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Shaders3D/Skybox.vert", "Shaders3D/Skybox.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + initBuffers(); +} + +NS_CC_END diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h new file mode 100644 index 0000000000..266e0eca86 --- /dev/null +++ b/cocos/3d/CCSkybox.h @@ -0,0 +1,89 @@ +/**************************************************************************** + 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 __SKYBOX_H__ +#define __SKYBOX_H__ + +#include "cocos2d.h" + +NS_CC_BEGIN + +class TextureCube; + +/** +* Sky box technology usually used to simulate infinity sky, mountains and other phenomena. +*/ +class CC_DLL Skybox : public Node +{ +public: + CREATE_FUNC(Skybox); + + /**texture getter and setter*/ + void setTexture(TextureCube*); + + /** draw Skybox object */ + virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + + /** reload sky box after GLESContext reconstructed.*/ + void reload(); + +CC_CONSTRUCTOR_ACCESS: + /** + * Constructor. + */ + Skybox(); + + /** + * Destructor. + */ + virtual ~Skybox(); + + /** + * init Skybox. + */ + virtual bool init(); + +protected: + + /** + * init internal buffers for Skybox. + */ + void initBuffers(); + + void onDraw(const Mat4& transform, uint32_t flags); + + GLuint _vao; + GLuint _vertexBuffer; + GLuint _indexBuffer; + + CustomCommand _customCommand; + + TextureCube* _texture; +private: + CC_DISALLOW_COPY_AND_ASSIGN(Skybox); +}; + +NS_CC_END + +#endif // __SKYBOX_H__ diff --git a/cocos/3d/CCTextureCube.cpp b/cocos/3d/CCTextureCube.cpp new file mode 100644 index 0000000000..f11c306040 --- /dev/null +++ b/cocos/3d/CCTextureCube.cpp @@ -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. + ****************************************************************************/ + +#include "3d/CCTextureCube.h" +#include "platform/CCImage.h" +#include "platform/CCFileUtils.h" + +NS_CC_BEGIN + +unsigned char* getImageData(Image* img, Texture2D::PixelFormat& ePixFmt) +{ + unsigned char* pTmpData = img->getData(); + unsigned int* inPixel32 = nullptr; + unsigned char* inPixel8 = nullptr; + unsigned short* outPixel16 = nullptr; + bool bHasAlpha = img->hasAlpha(); + size_t uBPP = img->getBitPerPixel(); + + int nWidth = img->getWidth(); + int nHeight = img->getHeight(); + + // compute pixel format + if (bHasAlpha) + { + ePixFmt = Texture2D::PixelFormat::DEFAULT; + } + else + { + if (uBPP >= 8) + { + ePixFmt = Texture2D::PixelFormat::RGB888; + } + else + { + ePixFmt = Texture2D::PixelFormat::RGB565; + } + } + + // Repack the pixel data into the right format + unsigned int uLen = nWidth * nHeight; + + if (ePixFmt == Texture2D::PixelFormat::RGB565) + { + if (bHasAlpha) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" + inPixel32 = (unsigned int*)img->getData(); + pTmpData = new unsigned char[nWidth * nHeight * 2]; + outPixel16 = (unsigned short*)pTmpData; + + for (unsigned int i = 0; i < uLen; ++i, ++inPixel32) + { + *outPixel16++ = + ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R + ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | // G + ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); // B + } + } + else + { + // Convert "RRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB" + pTmpData = new unsigned char[nWidth * nHeight * 2]; + outPixel16 = (unsigned short*)pTmpData; + inPixel8 = (unsigned char*)img->getData(); + + for (unsigned int i = 0; i < uLen; ++i) + { + unsigned char R = *inPixel8++; + unsigned char G = *inPixel8++; + unsigned char B = *inPixel8++; + + *outPixel16++ = + ((R >> 3) << 11) | // R + ((G >> 2) << 5) | // G + ((B >> 3) << 0); // B + } + } + } + + if (bHasAlpha && ePixFmt == Texture2D::PixelFormat::RGB888) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB" + inPixel32 = (unsigned int*)img->getData(); + + pTmpData = new unsigned char[nWidth * nHeight * 3]; + unsigned char* outPixel8 = pTmpData; + + for (unsigned int i = 0; i < uLen; ++i, ++inPixel32) + { + *outPixel8++ = (*inPixel32 >> 0) & 0xFF; // R + *outPixel8++ = (*inPixel32 >> 8) & 0xFF; // G + *outPixel8++ = (*inPixel32 >> 16) & 0xFF; // B + } + } + + return pTmpData; +} + +Image* createImage(const std::string& path) +{ + // Split up directory and filename + // MUTEX: + // Needed since addImageAsync calls this method from a different thread + + std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path); + if (fullpath.size() == 0) + { + return nullptr; + } + + // all images are handled by UIImage except PVR extension that is handled by our own handler + Image* image = nullptr; + do + { + image = new (std::nothrow) Image(); + CC_BREAK_IF(nullptr == image); + + bool bRet = image->initWithImageFile(fullpath); + CC_BREAK_IF(!bRet); + } + while (0); + + return image; +} + +TextureCube::TextureCube() +{ + _imgPath.resize(6); +} + +TextureCube::~TextureCube() +{ +} + +TextureCube* TextureCube::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 ret = new (std::nothrow) TextureCube(); + if (ret && ret->init(positive_x, negative_x, positive_y, negative_y, positive_z, negative_z)) + { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; +} + +bool TextureCube::init(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) +{ + _imgPath[0] = positive_x; + _imgPath[1] = negative_x; + _imgPath[2] = positive_y; + _imgPath[3] = negative_y; + _imgPath[4] = positive_z; + _imgPath[5] = negative_z; + + std::vector images(6); + + images[0] = createImage(positive_x); + images[1] = createImage(negative_x); + images[2] = createImage(positive_y); + images[3] = createImage(negative_y); + images[4] = createImage(positive_z); + images[5] = createImage(negative_z); + + GLuint handle; + glGenTextures(1, &handle); + glBindTexture(GL_TEXTURE_CUBE_MAP, handle); + + for (int i = 0; i < 6; i++) + { + Image* img = images[i]; + + Texture2D::PixelFormat ePixelFmt; + unsigned char* pData = getImageData(img, ePixelFmt); + if (ePixelFmt == Texture2D::PixelFormat::RGBA8888) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, // level + GL_RGBA, // internal format + img->getWidth(), // width + img->getHeight(), // height + 0, // border + GL_RGBA, // format + GL_UNSIGNED_BYTE, // type + pData); // pixel data + } + else if (ePixelFmt == Texture2D::PixelFormat::RGB888) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, // level + GL_RGB, // internal format + img->getWidth(), // width + img->getHeight(), // height + 0, // border + GL_RGB, // format + GL_UNSIGNED_BYTE, // type + pData); // pixel data + } + + if (pData != img->getData()) + delete[] pData; + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + _name = handle; + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + + for (auto img: images) + { + CC_SAFE_RELEASE(img); + } + + return true; +} + +void TextureCube::setTexParameters(const TexParams& texParams) +{ + CCASSERT(_name != 0, __FUNCTION__); + + glBindTexture(GL_TEXTURE_CUBE_MAP, _name); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, texParams.wrapS); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, texParams.wrapS); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, texParams.wrapS); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, texParams.wrapT); + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +bool TextureCube::reloadTexture() +{ + return init(_imgPath[0], _imgPath[1], _imgPath[2], _imgPath[3], _imgPath[4], _imgPath[5]); +} + +NS_CC_END diff --git a/cocos/3d/CCTextureCube.h b/cocos/3d/CCTextureCube.h new file mode 100644 index 0000000000..011c847191 --- /dev/null +++ b/cocos/3d/CCTextureCube.h @@ -0,0 +1,84 @@ +/**************************************************************************** + 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 __CCTEXTURECUBE_H__ +#define __CCTEXTURECUBE_H__ + +#include "renderer/CCTexture2D.h" + +#include +#include +#include "base/ccTypes.h" + +NS_CC_BEGIN + +/** + TextureCube is a collection of six separate square textures that are put + onto the faces of an imaginary cube. +*/ +class CC_DLL TextureCube: public Texture2D +{ +public: + /** create cube texture from 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 texture cube inited with given parameters. + */ + static TextureCube* 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); + + /** Sets the min filter, mag filter, wrap s and wrap t texture parameters. + If the texture size is NPOT (non power of 2), then in can only use GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}. + */ + void setTexParameters(const TexParams&); + + /** reload texture cube after GLESContext reconstructed.*/ + bool reloadTexture(); +CC_CONSTRUCTOR_ACCESS: + /** + * Constructor. + */ + TextureCube(); + + /** + * Destructor. + */ + virtual ~TextureCube(); +protected: + + bool init(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); +private: + std::vector _imgPath; +}; + +NS_CC_END + +#endif // __CCTEXTURECUBE_H__ diff --git a/cocos/3d/CMakeLists.txt b/cocos/3d/CMakeLists.txt index 3acd5a5254..682655a154 100644 --- a/cocos/3d/CMakeLists.txt +++ b/cocos/3d/CMakeLists.txt @@ -23,5 +23,7 @@ set(COCOS_3D_SRC 3d/CCSprite3D.cpp 3d/CCSprite3DMaterial.cpp 3d/CCBillBoard.cpp + 3d/CCSkybox.cpp + 3d/CCTextureCube.cpp ) diff --git a/cocos/cocos2d.h b/cocos/cocos2d.h index 1fd746d99c..13e50ffbcc 100644 --- a/cocos/cocos2d.h +++ b/cocos/cocos2d.h @@ -285,6 +285,8 @@ THE SOFTWARE. #include "3d/CCBillBoard.h" #include "3d/CCFrustum.h" #include "3d/CCPlane.h" +#include "3d/CCTextureCube.h" +#include "3d/CCSkybox.h" // Deprecated include #include "deprecated/CCDictionary.h" diff --git a/cocos/renderer/CCGLProgram.cpp b/cocos/renderer/CCGLProgram.cpp index e2bfb583b9..838450c7bb 100644 --- a/cocos/renderer/CCGLProgram.cpp +++ b/cocos/renderer/CCGLProgram.cpp @@ -72,6 +72,7 @@ const char* GLProgram::SHADER_3D_POSITION_NORMAL_TEXTURE = "Shader3DPositionNorm const char* GLProgram::SHADER_3D_SKINPOSITION_NORMAL_TEXTURE = "Shader3DSkinPositionNormalTexture"; const char* GLProgram::SHADER_3D_PARTICLE_COLOR = "Shader3DParticleColor"; const char* GLProgram::SHADER_3D_PARTICLE_TEXTURE = "Shader3DParticleTexture"; +const char* GLProgram::SHADER_3D_SKYBOX = "Shader3DSkybox"; // uniform names diff --git a/cocos/renderer/CCGLProgram.h b/cocos/renderer/CCGLProgram.h index 6aa423fd9c..577b219b5b 100644 --- a/cocos/renderer/CCGLProgram.h +++ b/cocos/renderer/CCGLProgram.h @@ -213,6 +213,11 @@ public: */ static const char* SHADER_3D_PARTICLE_COLOR; + /** + Built in shader for skybox + */ + static const char* SHADER_3D_SKYBOX; + /** end of built shader types. @} diff --git a/cocos/renderer/CCGLProgramCache.cpp b/cocos/renderer/CCGLProgramCache.cpp index 2fcfce9608..51d85ae171 100644 --- a/cocos/renderer/CCGLProgramCache.cpp +++ b/cocos/renderer/CCGLProgramCache.cpp @@ -63,6 +63,7 @@ enum { kShaderType_3DSkinPositionNormalTex, kShaderType_3DParticleTex, kShaderType_3DParticleColor, + kShaderType_3DSkyBox, #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || defined(WP8_SHADER_COMPILER) kShaderType_PositionColor_noMVP_GrayScale, #endif @@ -245,6 +246,10 @@ void GLProgramCache::loadDefaultGLPrograms() p = new GLProgram(); loadDefaultGLProgram(p, kShaderType_3DParticleTex); _programs.insert(std::make_pair(GLProgram::SHADER_3D_PARTICLE_TEXTURE, p)); + + p = new GLProgram(); + loadDefaultGLProgram(p, kShaderType_3DSkyBox); + _programs.insert(std::make_pair(GLProgram::SHADER_3D_SKYBOX, p)); } void GLProgramCache::reloadDefaultGLPrograms() @@ -372,6 +377,10 @@ void GLProgramCache::reloadDefaultGLPrograms() p = getGLProgram(GLProgram::SHADER_3D_PARTICLE_COLOR); p->reset(); loadDefaultGLProgram(p, kShaderType_3DParticleColor); + + p = getGLProgram(GLProgram::SHADER_3D_SKYBOX); + p->reset(); + loadDefaultGLProgram(p, kShaderType_3DSkyBox); } void GLProgramCache::loadDefaultGLProgram(GLProgram *p, int type) @@ -463,6 +472,9 @@ void GLProgramCache::loadDefaultGLProgram(GLProgram *p, int type) case kShaderType_3DParticleColor: p->initWithByteArrays(cc3D_Particle_vert, cc3D_Particle_color_frag); break; + case kShaderType_3DSkyBox: + p->initWithByteArrays(cc3D_Skybox_vert, cc3D_Skybox_frag); + break; #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || defined(WP8_SHADER_COMPILER) case kShaderType_PositionColor_noMVP_GrayScale: p->initWithByteArrays(ccPositionTextureColor_noMVP_vert, ccUIGrayScale_frag); diff --git a/cocos/renderer/CCGLProgramState.cpp b/cocos/renderer/CCGLProgramState.cpp index 0682cd47ef..34b94140d2 100644 --- a/cocos/renderer/CCGLProgramState.cpp +++ b/cocos/renderer/CCGLProgramState.cpp @@ -80,6 +80,11 @@ void UniformValue::apply() GL::bindTexture2DN(_value.tex.textureUnit, _value.tex.textureId); break; + case GL_SAMPLER_CUBE: + _glprogram->setUniformLocationWith1i(_uniform->location, _value.tex.textureUnit); + GL::bindTextureN(_value.tex.textureUnit, _value.tex.textureId, GL_TEXTURE_CUBE_MAP); + break; + case GL_INT: _glprogram->setUniformLocationWith1i(_uniform->location, _value.intValue); break; @@ -135,7 +140,7 @@ void UniformValue::setFloat(float value) void UniformValue::setTexture(GLuint textureId, GLuint textureUnit) { - CCASSERT(_uniform->type == GL_SAMPLER_2D, "Wrong type. expecting GL_SAMPLER_2D"); + //CCASSERT(_uniform->type == GL_SAMPLER_2D, "Wrong type. expecting GL_SAMPLER_2D"); _value.tex.textureId = textureId; _value.tex.textureUnit = textureUnit; _useCallback = false; diff --git a/cocos/renderer/ccGLStateCache.cpp b/cocos/renderer/ccGLStateCache.cpp index dc28a6870a..25eedc382f 100644 --- a/cocos/renderer/ccGLStateCache.cpp +++ b/cocos/renderer/ccGLStateCache.cpp @@ -148,17 +148,33 @@ void bindTexture2D(GLuint textureId) void bindTexture2DN(GLuint textureUnit, GLuint textureId) { +#if CC_ENABLE_GL_STATE_CACHE + CCASSERT(textureUnit < MAX_ACTIVE_TEXTURE, "textureUnit is too big"); + if (s_currentBoundTexture[textureUnit] != textureId) + { + s_currentBoundTexture[textureUnit] = textureId; + activeTexture(GL_TEXTURE0 + textureUnit); + glBindTexture(GL_TEXTURE_2D, textureId); + } +#else + glActiveTexture(GL_TEXTURE0 + textureUnit); + glBindTexture(GL_TEXTURE_2D, textureId); +#endif +} + +void bindTextureN(GLuint textureUnit, GLuint textureId, GLuint textureType/* = GL_TEXTURE_2D*/) +{ #if CC_ENABLE_GL_STATE_CACHE CCASSERT(textureUnit < MAX_ACTIVE_TEXTURE, "textureUnit is too big"); if (s_currentBoundTexture[textureUnit] != textureId) { s_currentBoundTexture[textureUnit] = textureId; activeTexture(GL_TEXTURE0 + textureUnit); - glBindTexture(GL_TEXTURE_2D, textureId); + glBindTexture(textureType, textureId); } #else glActiveTexture(GL_TEXTURE0 + textureUnit); - glBindTexture(GL_TEXTURE_2D, textureId); + glBindTexture(textureType, textureId); #endif } diff --git a/cocos/renderer/ccGLStateCache.h b/cocos/renderer/ccGLStateCache.h index fdb2effc2a..fb535ac1e4 100644 --- a/cocos/renderer/ccGLStateCache.h +++ b/cocos/renderer/ccGLStateCache.h @@ -126,7 +126,6 @@ void CC_DLL enableVertexAttribs(uint32_t flags); */ void CC_DLL bindTexture2D(GLuint textureId); - /** * If the texture is not already bound to a given unit, it binds it. * @@ -135,6 +134,12 @@ void CC_DLL bindTexture2D(GLuint textureId); */ void CC_DLL bindTexture2DN(GLuint textureUnit, GLuint textureId); +/** If the texture is not already bound to a given unit, it binds it. + * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. + * @since v3.6 + */ +void CC_DLL bindTextureN(GLuint textureUnit, GLuint textureId, GLuint textureType = GL_TEXTURE_2D); + /** * It will delete a given texture. If the texture was bound, it will invalidate the cached. * diff --git a/cocos/renderer/ccShader_3D_Skybox.frag b/cocos/renderer/ccShader_3D_Skybox.frag new file mode 100644 index 0000000000..1fe25805c5 --- /dev/null +++ b/cocos/renderer/ccShader_3D_Skybox.frag @@ -0,0 +1,13 @@ +const char* cc3D_Skybox_frag = STRINGIFY( +\n#ifdef GL_ES\n +varying mediump vec3 v_reflect; +\n#else\n +varying vec3 v_reflect; +\n#endif\n +uniform samplerCube u_Env; + +void main(void) +{ + gl_FragColor = textureCube(u_Env, v_reflect); +} +); \ No newline at end of file diff --git a/cocos/renderer/ccShader_3D_Skybox.vert b/cocos/renderer/ccShader_3D_Skybox.vert new file mode 100644 index 0000000000..005048153c --- /dev/null +++ b/cocos/renderer/ccShader_3D_Skybox.vert @@ -0,0 +1,18 @@ +const char* cc3D_Skybox_vert = STRINGIFY( + +attribute vec4 a_position; +varying vec3 v_reflect; + +void main(void) +{ + mat4 MVMatrixLimited = CC_MVMatrix; + MVMatrixLimited[0][3] = 0.0; + MVMatrixLimited[1][3] = 0.0; + MVMatrixLimited[2][3] = 0.0; + + vec4 position = MVMatrixLimited* a_position; + + v_reflect = a_position.xyz; + gl_Position = position.xyww; +} +); \ No newline at end of file diff --git a/cocos/renderer/ccShaders.cpp b/cocos/renderer/ccShaders.cpp index d5f36368f2..70fb421ad4 100644 --- a/cocos/renderer/ccShaders.cpp +++ b/cocos/renderer/ccShaders.cpp @@ -82,5 +82,7 @@ NS_CC_BEGIN #include "ccShader_3D_ColorNormalTex.frag" #include "ccShader_3D_Particle.vert" #include "ccShader_3D_Particle.frag" +#include "ccShader_3D_Skybox.vert" +#include "ccShader_3D_Skybox.frag" NS_CC_END diff --git a/cocos/renderer/ccShaders.h b/cocos/renderer/ccShaders.h index 74b11bb09b..108bdc3a44 100644 --- a/cocos/renderer/ccShaders.h +++ b/cocos/renderer/ccShaders.h @@ -84,6 +84,8 @@ extern CC_DLL const GLchar * cc3D_ColorNormal_frag; extern CC_DLL const GLchar * cc3D_Particle_vert; extern CC_DLL const GLchar * cc3D_Particle_tex_frag; extern CC_DLL const GLchar * cc3D_Particle_color_frag; +extern CC_DLL const GLchar * cc3D_Skybox_vert; +extern CC_DLL const GLchar * cc3D_Skybox_frag; // end of shaders group /// @} diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 6e629b3dc0..9feda1cc5c 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -30,6 +30,8 @@ #include "3d/CCAttachNode.h" #include "3d/CCRay.h" #include "3d/CCSprite3D.h" +#include "3d/CCTextureCube.h" +#include "3d/CCSkybox.h" #include "renderer/CCVertexIndexBuffer.h" #include "DrawNode3D.h" @@ -71,7 +73,8 @@ static std::function createFunctions[] = CL(QuaternionTest), CL(Sprite3DEmptyTest), CL(UseCaseSprite3D), - CL(Sprite3DForceDepthTest) + CL(Sprite3DForceDepthTest), + CL(Sprite3DCubeMapTest) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -2336,3 +2339,128 @@ void UseCaseSprite3D::update(float delta) circle->setPositionZ(z); } } + +Sprite3DCubeMapTest::Sprite3DCubeMapTest() : + _textureCube(nullptr), + _skyBox(nullptr), + _teapot(nullptr) +{ + auto s = Director::getInstance()->getWinSize(); + addNewSpriteWithCoords(Vec2(s.width / 2, s.height / 2)); +} + +Sprite3DCubeMapTest::~Sprite3DCubeMapTest() +{ +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener); +#endif + + _teapot->release(); + _skyBox->release(); + _textureCube->release(); +} + +std::string Sprite3DCubeMapTest::title() const +{ + return "CubeMap & Skybox Test"; +} + +std::string Sprite3DCubeMapTest::subtitle() const +{ + return ""; +} + +void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) +{ + Size visibleSize = Director::getInstance()->getVisibleSize(); + auto _camera = Camera::createPerspective(60, visibleSize.width / visibleSize.height, 0.1, 200); + _camera->setCameraFlag(CameraFlag::USER1); + + // create a teapot + _teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + _teapot->retain(); + + //create and set our custom shader + auto shader = GLProgram::createWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag"); + auto state = GLProgramState::create(shader); + + // create the second texture for cylinder + _textureCube = TextureCube::create("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg", + "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", + "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); + + _textureCube->retain(); + + //set texture parameters + Texture2D::TexParams tRepeatParams; + tRepeatParams.magFilter = GL_NEAREST; + tRepeatParams.minFilter = GL_NEAREST; + tRepeatParams.wrapS = GL_MIRRORED_REPEAT; + tRepeatParams.wrapT = GL_MIRRORED_REPEAT; + _textureCube->setTexParameters(tRepeatParams); + + // pass the texture sampler to our custom shader + state->setUniformTexture("u_cubeTex", _textureCube); + + _teapot->setGLProgramState(state); + _teapot->setPosition3D(Vec3(0, -5, -20)); + _teapot->setRotation3D(Vec3(-90, 180, 0)); + + auto rotate_action = RotateBy::create(1.5, Vec3(0, 30, 0)); + _teapot->runAction(RepeatForever::create(rotate_action)); + + //pass mesh's attribute to shader + long offset = 0; + auto attributeCount = _teapot->getMesh()->getMeshVertexAttribCount(); + for (auto i = 0; i < attributeCount; i++) + { + auto meshattribute = _teapot->getMesh()->getMeshVertexAttribute(i); + state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], + meshattribute.size, + meshattribute.type, + GL_FALSE, + _teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); + + offset += meshattribute.attribSizeBytes; + } + addChild(_teapot); + addChild(_camera); + setCameraMask(2); + + { + // config skybox + _skyBox = Skybox::create(); + _skyBox->retain(); + + _skyBox->setTexture(_textureCube); + addChild(_skyBox); + } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, + [this](EventCustom*) + { + auto state = _teapot->getGLProgramState(); + auto glProgram = state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + _textureCube->reloadTexture(); + + Texture2D::TexParams tRepeatParams; + tRepeatParams.magFilter = GL_NEAREST; + tRepeatParams.minFilter = GL_NEAREST; + tRepeatParams.wrapS = GL_MIRRORED_REPEAT; + tRepeatParams.wrapT = GL_MIRRORED_REPEAT; + _textureCube->setTexParameters(tRepeatParams); + state->setUniformTexture("u_cubeTex", _textureCube); + + _skyBox->reload(); + _skyBox->setTexture(_textureCube); + }); + Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); +#endif +} diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 1f2e0a97c0..3df3b5826b 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -498,4 +498,30 @@ public: virtual void runThisTest(); }; +namespace cocos2d +{ +class TextureCube; +class Skybox; +} +class Sprite3DCubeMapTest : public Sprite3DTestDemo +{ +public: + CREATE_FUNC(Sprite3DCubeMapTest); + Sprite3DCubeMapTest(); + ~Sprite3DCubeMapTest(); + virtual std::string title() const override; + virtual std::string subtitle() const override; + + void addNewSpriteWithCoords(Vec2); + +protected: + cocos2d::TextureCube* _textureCube; + Skybox* _skyBox; + Sprite3D* _teapot; + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + EventListenerCustom* _backToForegroundListener; +#endif +}; + #endif diff --git a/tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag new file mode 100644 index 0000000000..69f05b6cdb --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag @@ -0,0 +1,8 @@ + +varying vec3 v_reflect; +uniform samplerCube u_cubeTex; + +void main(void) +{ + gl_FragColor = textureCube(u_cubeTex, v_reflect); +} \ No newline at end of file diff --git a/tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert new file mode 100644 index 0000000000..500e9ffc9d --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert @@ -0,0 +1,16 @@ +attribute vec4 a_position; +attribute vec3 a_normal; + +varying vec3 v_reflect; + +void main(void) +{ + gl_Position = CC_MVPMatrix * a_position; + + // compute reflect + vec4 positionWorldViewSpace = CC_MVMatrix * a_position;; + vec3 vEyeVertex = normalize(positionWorldViewSpace.xyz / positionWorldViewSpace.w); + + vec3 v_normalVector = CC_NormalMatrix * a_normal; + v_reflect = normalize(reflect(vEyeVertex, v_normalVector)); +} diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/back.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/back.jpg new file mode 100644 index 0000000000..d91cbd3163 Binary files /dev/null and b/tests/cpp-tests/Resources/Sprite3DTest/skybox/back.jpg differ diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/bottom.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/bottom.jpg new file mode 100644 index 0000000000..47db53c695 Binary files /dev/null and b/tests/cpp-tests/Resources/Sprite3DTest/skybox/bottom.jpg differ diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/front.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/front.jpg new file mode 100644 index 0000000000..35b4796f89 Binary files /dev/null and b/tests/cpp-tests/Resources/Sprite3DTest/skybox/front.jpg differ diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/left.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/left.jpg new file mode 100644 index 0000000000..e500248c48 Binary files /dev/null and b/tests/cpp-tests/Resources/Sprite3DTest/skybox/left.jpg differ diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/right.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/right.jpg new file mode 100644 index 0000000000..68d235b79a Binary files /dev/null and b/tests/cpp-tests/Resources/Sprite3DTest/skybox/right.jpg differ diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/top.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/top.jpg new file mode 100644 index 0000000000..e15efede83 Binary files /dev/null and b/tests/cpp-tests/Resources/Sprite3DTest/skybox/top.jpg differ diff --git a/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua b/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua index 87916699d8..36f376e040 100644 --- a/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua +++ b/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua @@ -1026,12 +1026,75 @@ end function AsyncLoadSprite3DTest:onExit() +---------------------------------------- +----Sprite3DCubeTexture +---------------------------------------- +local Sprite3DCubeMap = {} +Sprite3DCubeMap.__index = Sprite3DCubeMap + +function Sprite3DCubeMap.create() +local layer = cc.Layer:create() +Helper.initWithLayer(layer) +Helper.titleLabel:setString("Sprite3D CubeMap/Skybox Test") + +local visSize = cc.Director:getInstance():getVisibleSize() +local camera = cc.Camera:createPerspective(68, visSize.width / visSize.height, 0.1, 200) +camera:setCameraFlag(2) +layer:addChild(camera) + +local fileName = "Sprite3DTest/teapot.c3b" +local teapot = cc.Sprite3D:create(fileName) +teapot:setPosition3D({x = 0, y = -5, z = -20}) +teapot:setRotation3D({x = -90, y = 180, z = 0}) + +local texCube = cc.TextureCube:create("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg", + "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", + "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); + +local program = cc.GLProgram:createWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag") +local state = cc.GLProgramState:create(program) + +attriNames = { + "a_position", "a_color", + "a_texCoord", "a_texCoord1", "a_texCoord2", "a_texCoord3", + "a_normal", "a_blendWeight", "a_blendIndex" + } + +--pass mesh's attribute to shader +local offset = 0 +local attributeCount = teapot:getMesh():getMeshVertexAttribCount() +for i = 0, attributeCount-1 do + local meshattribute = teapot:getMesh():getMeshVertexAttribute(i) + state:setVertexAttribPointer(attriNames[meshattribute.vertexAttrib+1], + meshattribute.size, + meshattribute.type, + false, + teapot:getMesh():getVertexSizeInBytes(), + offset); + offset = offset + meshattribute.attribSizeBytes +end + +state:setUniformTexture("u_cubeTex", texCube:getName()) + +teapot:setGLProgramState(state) +teapot:setCameraMask(2) + +local rotate_action = cc.RotateBy:create(1.5, { x = 0.0, y = 30.0, z = 0.0}) +teapot:runAction(cc.RepeatForever:create(rotate_action)); +layer:addChild(teapot) + +local skybox = cc.Skybox:create() +skybox:setTexture(texCube) +layer:addChild(skybox) + +return layer +>>>>>>> 4ea27173daf6b04cf0b917faa7911dde448cbdca end function Sprite3DTest() local scene = cc.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { Sprite3DBasicTest.create, Sprite3DHitTest.create, @@ -1041,7 +1104,8 @@ function Sprite3DTest() Sprite3DReskinTest.create, Sprite3DWithOBBPerfromanceTest.create, Sprite3DMirrorTest.create, - AsyncLoadSprite3DTest.create + AsyncLoadSprite3DTest.create, + Sprite3DCubeMap.create, } scene:addChild(Sprite3DBasicTest.create())