From be9b244779a6b4e34156a22d43004f2fde06d18d Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 30 Sep 2015 17:21:52 -0700 Subject: [PATCH] Fix the skybox color issue with background rendering when no texture is there --- libraries/model/src/model/Skybox.cpp | 113 +++++++++++++++------------ libraries/model/src/model/Skybox.slf | 10 ++- 2 files changed, 69 insertions(+), 54 deletions(-) diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index 944d16a6dd..4d49492c39 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -45,11 +45,18 @@ void Skybox::setCubemap(const gpu::TexturePointer& cubemap) { void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) { + const int VERTICES_SLOT = 0; + const int COLOR_SLOT = 1; + + // Create the static shared elements used to render the skybox static gpu::BufferPointer theBuffer; static gpu::Stream::FormatPointer theFormat; - - if (skybox.getCubemap()) { - if (!theBuffer) { + static gpu::BufferPointer theConstants; + static gpu::PipelinePointer thePipeline; + static int SKYBOX_CONSTANTS_SLOT = 0; // need to be defined by the compilation of the shader + static std::once_flag once; + std::call_once(once, [&] { + { const float CLIP = 1.0f; const glm::vec2 vertices[4] = { { -CLIP, -CLIP }, { CLIP, -CLIP }, { -CLIP, CLIP }, { CLIP, CLIP } }; theBuffer = std::make_shared(sizeof(vertices), (const gpu::Byte*) vertices); @@ -57,63 +64,65 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); } - glm::mat4 projMat; - viewFrustum.evalProjectionMatrix(projMat); + { + auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert))); + auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag))); + auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyVS, skyFS)); - Transform viewTransform; - viewFrustum.evalViewTransform(viewTransform); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewTransform); - batch.setModelTransform(Transform()); // only for Mac - batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); - batch.setInputFormat(theFormat); + gpu::Shader::BindingSet bindings; + bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0)); + if (!gpu::Shader::makeProgram(*skyShader, bindings)) { - if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { - static gpu::BufferPointer theConstants; - static gpu::PipelinePointer thePipeline; - static int SKYBOX_CONSTANTS_SLOT = 0; // need to be defined by the compilation of the shader - if (!thePipeline) { - auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert))); - auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag))); - auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyVS, skyFS)); - - gpu::Shader::BindingSet bindings; - bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0)); - if (!gpu::Shader::makeProgram(*skyShader, bindings)) { - - } - - SKYBOX_CONSTANTS_SLOT = skyShader->getBuffers().findLocation("skyboxBuffer"); - if (SKYBOX_CONSTANTS_SLOT == gpu::Shader::INVALID_LOCATION) { - SKYBOX_CONSTANTS_SLOT = skyShader->getUniforms().findLocation("skyboxBuffer"); - } - - auto skyState = std::make_shared(); - skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - - thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); - - auto color = glm::vec4(1.0f); - theConstants = std::make_shared(sizeof(color), (const gpu::Byte*) &color); } - if (glm::all(glm::equal(skybox.getColor(), glm::vec3(0.0f)))) { - auto color = glm::vec4(1.0f); - theConstants->setSubData(0, sizeof(color), (const gpu::Byte*) &color); - } else { - theConstants->setSubData(0, sizeof(Color), (const gpu::Byte*) &skybox.getColor()); + SKYBOX_CONSTANTS_SLOT = skyShader->getBuffers().findLocation("skyboxBuffer"); + if (SKYBOX_CONSTANTS_SLOT == gpu::Shader::INVALID_LOCATION) { + SKYBOX_CONSTANTS_SLOT = skyShader->getUniforms().findLocation("skyboxBuffer"); } - batch.setPipeline(thePipeline); - batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize()); - batch.setResourceTexture(0, skybox.getCubemap()); - batch.draw(gpu::TRIANGLE_STRIP, 4); + auto skyState = std::make_shared(); + skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + + thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); + + auto color = glm::vec4(1.0f); + theConstants = std::make_shared(sizeof(color), (const gpu::Byte*) &color); } + }); - } else { - // skybox has no cubemap, just clear the color buffer - auto color = skybox.getColor(); - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.0f, 0, true); + // Render + glm::mat4 projMat; + viewFrustum.evalProjectionMatrix(projMat); + + Transform viewTransform; + viewFrustum.evalViewTransform(viewTransform); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewTransform); + batch.setModelTransform(Transform()); // only for Mac + batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); + batch.setInputFormat(theFormat); + + gpu::TexturePointer skymap; + auto color = glm::vec4(skybox.getColor(), 0.0f); + if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { + skymap = skybox.getCubemap(); + + if (glm::all(glm::equal(skybox.getColor(), glm::vec3(0.0f)))) { + color = glm::vec4(1.0f); + } else { + color.w = 1.0f; + } } + // Update the constant color. + theConstants->setSubData(0, sizeof(glm::vec4), (const gpu::Byte*) &color); + + batch.setPipeline(thePipeline); + batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize()); + batch.setResourceTexture(0, skymap); + + batch.draw(gpu::TRIANGLE_STRIP, 4); + + batch.setResourceTexture(0, nullptr); + } diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf index 382801f52d..66abee8948 100755 --- a/libraries/model/src/model/Skybox.slf +++ b/libraries/model/src/model/Skybox.slf @@ -40,8 +40,14 @@ void main(void) { #else vec3 coord = normalize(_normal); - vec3 texel = texture(cubeMap, coord).rgb; - vec3 color = texel * _skybox._color.rgb; + + // Skybox color or blend with skymap + vec3 color = _skybox._color.rgb; + if (_skybox._color.a > 0.0) { + vec3 texel = texture(cubeMap, coord).rgb; + color *= texel; + } + vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction _fragColor = vec4(pixel, 0.0);