From 5a11143a5d23bbec555c787b5f4f1582c3da1309 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 9 May 2015 11:40:46 -0700 Subject: [PATCH 1/9] Using the skybox cubemap for ambient lighting --- interface/src/Application.cpp | 4 +- libraries/gpu/src/gpu/Config.slh | 2 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 16 +++++- .../physics/src/PhysicalEntitySimulation.cpp | 2 +- .../render-utils/src/DeferredGlobalLight.slh | 25 ++++++++++ .../src/DeferredLightingEffect.cpp | 41 ++++++++++++++-- .../render-utils/src/DeferredLightingEffect.h | 7 +++ libraries/render-utils/src/TextureCache.cpp | 4 +- .../src/directional_skybox_light.slf | 43 ++++++++++++++++ ...ional_skybox_light_cascaded_shadow_map.slf | 48 ++++++++++++++++++ .../directional_skybox_light_shadow_map.slf | 49 +++++++++++++++++++ 11 files changed, 230 insertions(+), 11 deletions(-) create mode 100755 libraries/render-utils/src/directional_skybox_light.slf create mode 100755 libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf create mode 100755 libraries/render-utils/src/directional_skybox_light_shadow_map.slf diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9960e64bb4..42d08bcd9e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3190,6 +3190,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs // Background rendering decision auto skyStage = DependencyManager::get()->getSkyStage(); + auto skybox = model::SkyboxPointer(); if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) { } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) { if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { @@ -3237,7 +3238,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs } } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) { - auto skybox = skyStage->getSkybox(); + skybox = skyStage->getSkybox(); if (skybox) { gpu::Batch batch; model::Skybox::render(batch, _viewFrustum, *skybox); @@ -3316,6 +3317,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs auto skyStage = DependencyManager::get()->getSkyStage(); DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity()); DependencyManager::get()->setGlobalAtmosphere(skyStage->getAtmosphere()); + DependencyManager::get()->setGlobalSkybox(skybox); PROFILE_RANGE("DeferredLighting"); PerformanceTimer perfTimer("lighting"); diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index 7a51de594a..28f447a696 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -14,7 +14,7 @@ <@if GLPROFILE == PC_GL @> <@def GPU_FEATURE_PROFILE GPU_CORE@> <@def GPU_TRANSFORM_PROFILE GPU_CORE@> - <@def VERSION_HEADER #version 330 compatibility@> + <@def VERSION_HEADER #version 430 compatibility@> <@elif GLPROFILE == MAC_GL @> <@def GPU_FEATURE_PROFILE GPU_LEGACY@> <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 69f2b33d1b..fa4e4c93ea 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -370,9 +370,21 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture); const int NUM_FACES = 6; const GLenum FACE_LAYOUT[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, +/* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X }; + */ + GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + + /* GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; +*/ + /* GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };*/ if (needUpdate) { if (texture.isStoredMipAvailable(0)) { Texture::PixelsPointer mip = texture.accessStoredMip(0); diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index ed7b986800..442065cac2 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -167,7 +167,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() { _tempVector.push_back(motionState); entityItr = _pendingAdds.erase(entityItr); } else { - qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); + // qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); ++entityItr; } } else { diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index cbf7c31d1f..9583f8664b 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -13,6 +13,14 @@ <@include DeferredLighting.slh@> +uniform samplerCube skyboxMap; + +vec4 evalSkyboxLight(vec3 direction, float lod) { + +// vec4 skytexel = textureCube(skyboxMap, direction); + vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); + return skytexel; +} struct SphericalHarmonics { vec4 L00; @@ -92,6 +100,23 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no return color; } +vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { + // Need the light now + Light light = getLight(); + + vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0))); + vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); + vec3 fragEyeDir = normalize(fragEyeVector.xyz); + + vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light); + + vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); + + color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + + return color; +} + vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index bddb1815bf..ed24f089d6 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -41,6 +41,10 @@ #include "directional_ambient_light_shadow_map_frag.h" #include "directional_ambient_light_cascaded_shadow_map_frag.h" +#include "directional_skybox_light_frag.h" +#include "directional_skybox_light_shadow_map_frag.h" +#include "directional_skybox_light_cascaded_shadow_map_frag.h" + #include "point_light_frag.h" #include "spot_light_frag.h" @@ -66,6 +70,12 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { loadLightProgram(directional_ambient_light_cascaded_shadow_map_frag, false, _directionalAmbientSphereLightCascadedShadowMap, _directionalAmbientSphereLightCascadedShadowMapLocations); + loadLightProgram(directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations); + loadLightProgram(directional_skybox_light_shadow_map_frag, false, _directionalSkyboxLightShadowMap, + _directionalSkyboxLightShadowMapLocations); + loadLightProgram(directional_skybox_light_cascaded_shadow_map_frag, false, _directionalSkyboxLightCascadedShadowMap, + _directionalSkyboxLightCascadedShadowMapLocations); + loadLightProgram(point_light_frag, true, _pointLight, _pointLightLocations); loadLightProgram(spot_light_frag, true, _spotLight, _spotLightLocations); @@ -217,6 +227,7 @@ void DeferredLightingEffect::render() { float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height(); float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height(); + bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap()); // Fetch the ViewMatrix; glm::mat4 invViewMat; @@ -234,7 +245,10 @@ void DeferredLightingEffect::render() { if (_viewState->getCascadeShadowsEnabled()) { program = &_directionalLightCascadedShadowMap; locations = &_directionalLightCascadedShadowMapLocations; - if (_ambientLightMode > -1) { + if (useSkyboxCubemap) { + program = &_directionalSkyboxLightCascadedShadowMap; + locations = &_directionalSkyboxLightCascadedShadowMapLocations; + } else if (_ambientLightMode > -1) { program = &_directionalAmbientSphereLightCascadedShadowMap; locations = &_directionalAmbientSphereLightCascadedShadowMapLocations; } @@ -242,7 +256,10 @@ void DeferredLightingEffect::render() { program->setUniform(locations->shadowDistances, _viewState->getShadowDistances()); } else { - if (_ambientLightMode > -1) { + if (useSkyboxCubemap) { + program = &_directionalSkyboxLightShadowMap; + locations = &_directionalSkyboxLightShadowMapLocations; + } else if (_ambientLightMode > -1) { program = &_directionalAmbientSphereLightShadowMap; locations = &_directionalAmbientSphereLightShadowMapLocations; } @@ -252,7 +269,10 @@ void DeferredLightingEffect::render() { 1.0f / textureCache->getShadowFramebuffer()->getWidth()); } else { - if (_ambientLightMode > -1) { + if (useSkyboxCubemap) { + program = &_directionalSkyboxLight; + locations = &_directionalSkyboxLightLocations; + } else if (_ambientLightMode > -1) { program = &_directionalAmbientSphereLight; locations = &_directionalAmbientSphereLightLocations; } @@ -269,6 +289,11 @@ void DeferredLightingEffect::render() { } } + if (useSkyboxCubemap) { + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_CUBE_MAP, gpu::GLBackend::getTextureID(_skybox->getCubemap())); + } + if (locations->lightBufferUnit >= 0) { gpu::Batch batch; batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); @@ -300,7 +325,14 @@ void DeferredLightingEffect::render() { renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight); program->release(); - + + if (useSkyboxCubemap) { + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + if (!shadowsEnabled) { + glActiveTexture(GL_TEXTURE3); + } + } + if (shadowsEnabled) { glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE3); @@ -492,6 +524,7 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit program.setUniformValue("specularMap", 2); program.setUniformValue("depthMap", 3); program.setUniformValue("shadowMap", 4); + program.setUniformValue("skyboxMap", 5); locations.shadowDistances = program.uniformLocation("shadowDistances"); locations.shadowScale = program.uniformLocation("shadowScale"); locations.nearLocation = program.uniformLocation("near"); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index e64163b330..66cc6f59e9 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -101,6 +101,13 @@ private: ProgramObject _simpleProgram; int _glowIntensityLocation; + ProgramObject _directionalSkyboxLight; + LightLocations _directionalSkyboxLightLocations; + ProgramObject _directionalSkyboxLightShadowMap; + LightLocations _directionalSkyboxLightShadowMapLocations; + ProgramObject _directionalSkyboxLightCascadedShadowMap; + LightLocations _directionalSkyboxLightCascadedShadowMapLocations; + ProgramObject _directionalAmbientSphereLight; LightLocations _directionalAmbientSphereLightLocations; ProgramObject _directionalAmbientSphereLightShadowMap; diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index c88050f7fb..9a1b0da709 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -513,7 +513,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo imageLoaded(image); if ((_width > 0) && (_height > 0)) { - + bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); @@ -525,7 +525,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo if (_type == CUBE_TEXTURE) { if (_height >= (6 * _width)) { - _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP))); + _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); _gpuTexture->autoGenerateMips(-1); } diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf new file mode 100755 index 0000000000..38e3f9eb72 --- /dev/null +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -0,0 +1,43 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// directional_light.frag +// fragment shader +// +// Created by Sam Gateau on 5/8/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Everything about deferred buffer +<@include DeferredBuffer.slh@> + +<@include DeferredGlobalLight.slh@> + +void main(void) { + DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + + + // Light mapped or not ? + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + vec3 color = evalLightmappedColor( + 1.0, + frag.normal, + frag.diffuse, + frag.specularVal.xyz); + + gl_FragColor = vec4(color, 1.0); + } else { + vec3 color = evalSkyboxGlobalColor(1.0, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); + + gl_FragColor = vec4(color, frag.normalVal.a); + } +} diff --git a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf new file mode 100755 index 0000000000..d7d843855f --- /dev/null +++ b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf @@ -0,0 +1,48 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// directional_light.frag +// fragment shader +// +// Created by Sam Gateau on 5/8/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Everything about deferred buffer +<@include DeferredBuffer.slh@> + +<@include DeferredGlobalLight.slh@> + +// Everything about shadow +<@include Shadow.slh@> + +void main(void) { + DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + + // Eval shadow Texcoord and then Attenuation + vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); + float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); + + // Light mapped or not ? + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + gl_FragColor = vec4(evalLightmappedColor( + shadowAttenuation, + frag.normal, + frag.diffuse, + frag.specularVal.xyz), + 1.0); + } else { + vec3 color = evalSkyboxGlobalColor(shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); + + gl_FragColor = vec4(color, frag.normalVal.a); + } +} diff --git a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf new file mode 100755 index 0000000000..8c19cb959f --- /dev/null +++ b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf @@ -0,0 +1,49 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// directional_light.frag +// fragment shader +// +// Created by Sam Gateau on 5/8/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Everything about deferred buffer +<@include DeferredBuffer.slh@> + +<@include DeferredGlobalLight.slh@> + +// Everything about shadow +<@include Shadow.slh@> + + +void main(void) { + DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + + // Eval shadow Texcoord and then Attenuation + vec4 shadowTexcoord = evalShadowTexcoord(frag.position); + float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); + + // Light mapped or not ? + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + gl_FragColor = vec4(evalLightmappedColor( + shadowAttenuation, + frag.normal, + frag.diffuse, + frag.specularVal.xyz), + 1.0); + } else { + vec3 color = evalSkyboxGlobalColor(shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); + + gl_FragColor = vec4(color, frag.normalVal.a); + } +} From 23ef56826940b03a74d2e1b80b06f187a3dec580 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 9 May 2015 11:48:30 -0700 Subject: [PATCH 2/9] fixing file --- libraries/physics/src/PhysicalEntitySimulation.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 06099d19dc..50e81b4788 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -167,12 +167,8 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() { _tempVector.push_back(motionState); entityItr = _pendingAdds.erase(entityItr); } else { -<<<<<<< HEAD - // qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); -======= // TODO: Seth to look into why this case is hit. //qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); ->>>>>>> 72e1ea688adad9914d9994b81a96225ac411ba83 ++entityItr; } } else { From f1fcce3ea0b96df13d7338c6aee3c8b4e74b1f37 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 May 2015 10:47:45 -0700 Subject: [PATCH 3/9] refactoring th ecube texure loading to support 2 different layouts --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 123 ++++++++--------- libraries/gpu/src/gpu/Texture.cpp | 139 ++++++++++++++------ libraries/gpu/src/gpu/Texture.h | 77 +++++++---- libraries/model/src/model/Skybox.slv | 2 - libraries/render-utils/src/TextureCache.cpp | 35 ++++- 5 files changed, 235 insertions(+), 141 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index fa4e4c93ea..999173e5b7 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -295,8 +295,8 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { glBindTexture(GL_TEXTURE_2D, object->_texture); if (needUpdate) { - if (texture.isStoredMipAvailable(0)) { - Texture::PixelsPointer mip = texture.accessStoredMip(0); + if (texture.isStoredMipFaceAvailable(0)) { + Texture::PixelsPointer mip = texture.accessStoredMipFace(0); const GLvoid* bytes = mip->_sysmem.read(); Element srcFormat = mip->_format; @@ -318,15 +318,15 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { // At this point the mip piels have been loaded, we can notify - texture.notifyGPULoaded(0); + texture.notifyMipFaceGPULoaded(0, 0); object->_contentStamp = texture.getDataStamp(); } } else { const GLvoid* bytes = 0; Element srcFormat = texture.getTexelFormat(); - if (texture.isStoredMipAvailable(0)) { - Texture::PixelsPointer mip = texture.accessStoredMip(0); + if (texture.isStoredMipFaceAvailable(0)) { + Texture::PixelsPointer mip = texture.accessStoredMipFace(0); bytes = mip->_sysmem.read(); srcFormat = mip->_format; @@ -352,10 +352,11 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { syncSampler(texture.getSampler(), texture.getType(), object); - // At this point the mip piels have been loaded, we can notify - texture.notifyGPULoaded(0); + // At this point the mip pixels have been loaded, we can notify + texture.notifyMipFaceGPULoaded(0, 0); object->_storageStamp = texture.getStamp(); + object->_contentStamp = texture.getDataStamp(); object->_size = texture.getSize(); } @@ -370,75 +371,57 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture); const int NUM_FACES = 6; const GLenum FACE_LAYOUT[] = { -/* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X }; - */ GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; - - /* GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; -*/ - /* GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };*/ if (needUpdate) { - if (texture.isStoredMipAvailable(0)) { - Texture::PixelsPointer mip = texture.accessStoredMip(0); - Element srcFormat = mip->_format; - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); - - uint16 width = texture.getWidth(); - int faceSize = mip->_sysmem.getSize() / NUM_FACES; - - glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture); - for (int f = 0; f < NUM_FACES; f++) { - glTexSubImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, width, width, 0, - texelFormat.format, texelFormat.type, (GLvoid*) (mip->_sysmem.read() + f * faceSize)); - } - - if (texture.isAutogenerateMips()) { - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - - object->_target = GL_TEXTURE_CUBE_MAP; - - syncSampler(texture.getSampler(), texture.getType(), object); - - // At this point the mip piels have been loaded, we can notify - texture.notifyGPULoaded(0); - - object->_contentStamp = texture.getDataStamp(); - } - } else { - const gpu::Byte* bytes = 0; - Element srcFormat = texture.getTexelFormat(); - uint16 width = texture.getWidth(); - int faceSize = 0; - - if (texture.isStoredMipAvailable(0)) { - Texture::PixelsPointer mip = texture.accessStoredMip(0); - - bytes = mip->_sysmem.read(); - srcFormat = mip->_format; - faceSize = mip->_sysmem.getSize() / NUM_FACES; - - object->_contentStamp = texture.getDataStamp(); - } - - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); - glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture); + + // transfer pixels from each faces for (int f = 0; f < NUM_FACES; f++) { - glTexImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, width, width, 0, - texelFormat.format, texelFormat.type, (GLvoid*) (bytes + f * faceSize)); + if (texture.isStoredMipFaceAvailable(0, f)) { + Texture::PixelsPointer mipFace = texture.accessStoredMipFace(0, f); + Element srcFormat = mipFace->_format; + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); + + glTexSubImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, texture.getWidth(), texture.getWidth(), 0, + texelFormat.format, texelFormat.type, (GLvoid*) (mipFace->_sysmem.read())); + + // At this point the mip pixels have been loaded, we can notify + texture.notifyMipFaceGPULoaded(0, f); + } } - if (bytes && texture.isAutogenerateMips()) { + if (texture.isAutogenerateMips()) { + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + + object->_target = GL_TEXTURE_CUBE_MAP; + + syncSampler(texture.getSampler(), texture.getType(), object); + + object->_contentStamp = texture.getDataStamp(); + + } else { + glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture); + + // transfer pixels from each faces + for (int f = 0; f < NUM_FACES; f++) { + if (texture.isStoredMipFaceAvailable(0, f)) { + Texture::PixelsPointer mipFace = texture.accessStoredMipFace(0, f); + Element srcFormat = mipFace->_format; + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat); + + glTexImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, texture.getWidth(), texture.getWidth(), 0, + texelFormat.format, texelFormat.type, (GLvoid*) (mipFace->_sysmem.read())); + + // At this point the mip pixels have been loaded, we can notify + texture.notifyMipFaceGPULoaded(0, f); + } + } + + if (texture.isAutogenerateMips()) { glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { @@ -450,10 +433,8 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { syncSampler(texture.getSampler(), texture.getType(), object); - // At this point the mip piels have been loaded, we can notify - texture.notifyGPULoaded(0); - object->_storageStamp = texture.getStamp(); + object->_contentStamp = texture.getDataStamp(); object->_size = texture.getSize(); } diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index d4891fcf7c..07bb73a375 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -28,69 +28,103 @@ Texture::Pixels::~Pixels() { void Texture::Storage::assignTexture(Texture* texture) { _texture = texture; -} - -Stamp Texture::Storage::getStamp(uint16 level) const { - PixelsPointer mip = getMip(level); - if (mip) { - return mip->_sysmem.getStamp(); + if (_texture) { + _type = _texture->getType(); } - return 0; } void Texture::Storage::reset() { _mips.clear(); + bumpStamp(); } -Texture::PixelsPointer Texture::Storage::editMip(uint16 level) { +Texture::PixelsPointer Texture::Storage::editMipFace(uint16 level, uint8 face) { if (level < _mips.size()) { - return _mips[level]; + assert(face < _mips[level].size()); + bumpStamp(); + return _mips[level][face]; } return PixelsPointer(); } -const Texture::PixelsPointer Texture::Storage::getMip(uint16 level) const { +const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 face) const { if (level < _mips.size()) { - return _mips[level]; + assert(face < _mips[level].size()); + return _mips[level][face]; } return PixelsPointer(); } -void Texture::Storage::notifyGPULoaded(uint16 level) const { - PixelsPointer mip = getMip(level); - if (mip) { - mip->_isGPULoaded = true; - mip->_sysmem.resize(0); +void Texture::Storage::notifyMipFaceGPULoaded(uint16 level, uint8 face) const { + PixelsPointer mipFace = getMipFace(level, face); + if (mipFace) { + mipFace->_isGPULoaded = true; + mipFace->_sysmem.resize(0); } } -bool Texture::Storage::isMipAvailable(uint16 level) const { - PixelsPointer mip = getMip(level); - return (mip && mip->_sysmem.getSize()); +bool Texture::Storage::isMipAvailable(uint16 level, uint8 face) const { + PixelsPointer mipFace = getMipFace(level, face); + return (mipFace && mipFace->_sysmem.getSize()); } bool Texture::Storage::allocateMip(uint16 level) { bool changed = false; if (level >= _mips.size()) { - _mips.resize(level+1, PixelsPointer()); + _mips.resize(level+1, std::vector(Texture::NUM_FACES_PER_TYPE[getType()])); changed = true; } - if (!_mips[level]) { - _mips[level] = PixelsPointer(new Pixels()); - changed = true; + auto& mip = _mips[level]; + for (auto& face : mip) { + if (!face) { + face.reset(new Pixels()); + changed = true; + } } + bumpStamp(); + return changed; } bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) { - // Ok we should be able to do that... + + allocateMip(level); + auto& mip = _mips[level]; + + // here we grabbed an array of faces + // The bytes assigned here are supposed to contain all the faces bytes of the mip. + // For tex1D, 2D, 3D there is only one face + // For Cube, we expect the 6 faces in the order X+, X-, Y+, Y-, Z+, Z- + int sizePerFace = size / mip.size(); + auto faceBytes = bytes; + Size allocated = 0; + for (auto& face : mip) { + face->_format = format; + allocated += face->_sysmem.setData(sizePerFace, faceBytes); + face->_isGPULoaded = false; + faceBytes += sizePerFace; + } + + bumpStamp(); + + return allocated == size; +} + + +bool Texture::Storage::assignMipFaceData(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) { + allocateMip(level); auto mip = _mips[level]; - mip->_format = format; - Size allocated = mip->_sysmem.setData(size, bytes); - mip->_isGPULoaded = false; + Size allocated = 0; + if (face < mip.size()) { + auto mipFace = mip[face]; + mipFace->_format = format; + allocated += mipFace->_sysmem.setData(size, bytes); + mipFace->_isGPULoaded = false; + bumpStamp(); + } return allocated == size; } @@ -115,8 +149,8 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui { Texture* tex = new Texture(); tex->_storage.reset(new Storage()); - tex->_storage->_texture = tex; tex->_type = type; + tex->_storage->assignTexture(tex); tex->_maxMip = 0; tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices); @@ -275,6 +309,37 @@ bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, co return false; } + +bool Texture::assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) { + // Check that level accessed make sense + if (level != 0) { + if (_autoGenerateMips) { + return false; + } + if (level >= evalNumMips()) { + return false; + } + } + + // THen check that the mem buffer passed make sense with its format + Size expectedSize = evalStoredMipFaceSize(level, format); + if (size == expectedSize) { + _storage->assignMipFaceData(level, format, size, bytes, face); + _stamp++; + return true; + } else if (size > expectedSize) { + // NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images + // and alligning the line of pixels to 32 bits. + // We should probably consider something a bit more smart to get the correct result but for now (UI elements) + // it seems to work... + _storage->assignMipFaceData(level, format, size, bytes, face); + _stamp++; + return true; + } + + return false; +} + uint16 Texture::autoGenerateMips(uint16 maxMip) { _autoGenerateMips = true; _maxMip = std::min((uint16) (evalNumMips() - 1), maxMip); @@ -283,15 +348,15 @@ uint16 Texture::autoGenerateMips(uint16 maxMip) { } uint16 Texture::getStoredMipWidth(uint16 level) const { - PixelsPointer mip = accessStoredMip(level); - if (mip && mip->_sysmem.getSize()) { + PixelsPointer mipFace = accessStoredMipFace(level); + if (mipFace && mipFace->_sysmem.getSize()) { return evalMipWidth(level); } return 0; } uint16 Texture::getStoredMipHeight(uint16 level) const { - PixelsPointer mip = accessStoredMip(level); + PixelsPointer mip = accessStoredMipFace(level); if (mip && mip->_sysmem.getSize()) { return evalMipHeight(level); } @@ -299,24 +364,24 @@ uint16 Texture::getStoredMipHeight(uint16 level) const { } uint16 Texture::getStoredMipDepth(uint16 level) const { - PixelsPointer mip = accessStoredMip(level); - if (mip && mip->_sysmem.getSize()) { + PixelsPointer mipFace = accessStoredMipFace(level); + if (mipFace && mipFace->_sysmem.getSize()) { return evalMipDepth(level); } return 0; } uint32 Texture::getStoredMipNumTexels(uint16 level) const { - PixelsPointer mip = accessStoredMip(level); - if (mip && mip->_sysmem.getSize()) { + PixelsPointer mipFace = accessStoredMipFace(level); + if (mipFace && mipFace->_sysmem.getSize()) { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } return 0; } uint32 Texture::getStoredMipSize(uint16 level) const { - PixelsPointer mip = accessStoredMip(level); - if (mip && mip->_sysmem.getSize()) { + PixelsPointer mipFace = accessStoredMipFace(level); + if (mipFace && mipFace->_sysmem.getSize()) { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize(); } return 0; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 19add9a47e..35e7b9a4b7 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -112,28 +112,6 @@ public: }; typedef std::shared_ptr< Pixels > PixelsPointer; - class Storage { - public: - Storage() {} - virtual ~Storage() {} - virtual void reset(); - virtual PixelsPointer editMip(uint16 level); - virtual const PixelsPointer getMip(uint16 level) const; - virtual Stamp getStamp(uint16 level) const; - virtual bool allocateMip(uint16 level); - virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes); - virtual bool isMipAvailable(uint16 level) const; - virtual void notifyGPULoaded(uint16 level) const; - - protected: - Texture* _texture; - std::vector _mips; - - virtual void assignTexture(Texture* tex); - - friend class Texture; - }; - enum Type { TEX_1D = 0, TEX_2D, @@ -143,6 +121,39 @@ public: NUM_TYPES, }; + class Storage { + public: + Storage() {} + virtual ~Storage() {} + virtual void reset(); + virtual PixelsPointer editMipFace(uint16 level, uint8 face = 0); + virtual const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const; + virtual bool allocateMip(uint16 level); + virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes); + virtual bool assignMipFaceData(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face); + virtual bool isMipAvailable(uint16 level, uint8 face = 0) const; + + Texture::Type getType() const { return _type; } + + Stamp getStamp() const { return _stamp; } + Stamp bumpStamp() { return ++_stamp; } + protected: + Stamp _stamp = 0; + Texture* _texture = nullptr; + Texture::Type _type = Texture::TEX_2D; // The type of texture is needed to know the number of faces to expect + std::vector> _mips; // an array of mips, each mip is an array of faces + + virtual void assignTexture(Texture* tex); // Texture storage is pointing to ONE corrresponding Texture. + const Texture* getTexture() const { return _texture; } + + friend class Texture; + + // THis should be only called by the Texture from the Backend to notify the storage that the specified mip face pixels + // have been uploaded to the GPU memory. IT is possible for the storage to free the system memory then + virtual void notifyMipFaceGPULoaded(uint16 level, uint8 face) const; + }; + + static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler = Sampler()); static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler()); @@ -155,7 +166,7 @@ public: ~Texture(); Stamp getStamp() const { return _stamp; } - Stamp getDataStamp(uint16 level = 0) const { return _storage->getStamp(level); } + Stamp getDataStamp() const { return _storage->getStamp(); } // The size in bytes of data stored in the texture Size getSize() const { return _size; } @@ -214,8 +225,16 @@ public: uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); } uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); } uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); } - uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getNumFaces(); } + + // Size for each face of a mip at a particular level + uint32 evalMipFaceNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } + uint32 evalMipFaceSize(uint16 level) const { return evalMipFaceNumTexels(level) * getTexelFormat().getSize(); } + + // Total size for the mip + uint32 evalMipNumTexels(uint16 level) const { return evalMipFaceNumTexels(level) * getNumFaces(); } uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); } + + uint32 evalStoredMipFaceSize(uint16 level, const Element& format) const { return evalMipFaceNumTexels(level) * format.getSize(); } uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); } uint32 evalTotalSize() const { @@ -256,11 +275,11 @@ public: // Explicitely assign mip data for a certain level // If Bytes is NULL then simply allocate the space so mip sysmem can be accessed bool assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes); + bool assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face); // Access the the sub mips - bool isStoredMipAvailable(uint16 level) const { return _storage->isMipAvailable(level); } - const PixelsPointer accessStoredMip(uint16 level) const { return _storage->getMip(level); } - void notifyGPULoaded(uint16 level) const { return _storage->notifyGPULoaded(level); } + bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const { return _storage->isMipAvailable(level, face); } + const PixelsPointer accessStoredMipFace(uint16 level, uint8 face = 0) const { return _storage->getMipFace(level, face); } // access sizes for the stored mips uint16 getStoredMipWidth(uint16 level) const; @@ -277,6 +296,9 @@ public: const Sampler& getSampler() const { return _sampler; } Stamp getSamplerStamp() const { return _samplerStamp; } + // Only callable by the Backend + void notifyMipFaceGPULoaded(uint16 level, uint8 face) const { return _storage->notifyMipFaceGPULoaded(level, face); } + protected: std::unique_ptr< Storage > _storage; @@ -310,6 +332,7 @@ protected: mutable GPUObject* _gpuObject = NULL; void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } GPUObject* getGPUObject() const { return _gpuObject; } + friend class Backend; }; diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv index 3c7ffbce2d..1236e0d384 100755 --- a/libraries/model/src/model/Skybox.slv +++ b/libraries/model/src/model/Skybox.slv @@ -31,9 +31,7 @@ void main(void) { vec3 eyeDir; <$transformClipToEyeDir(cam, clipDir, eyeDir)$>; - normal = normalize(eyeDir); <$transformEyeToWorldDir(cam, eyeDir, normal)$>; - normal = normalize(normal); // Position is supposed to cmoe in clip space gl_Position = vec4(texcoord.xy, 0.0, 1.0); diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 9a1b0da709..803350629d 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -524,10 +524,37 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo } if (_type == CUBE_TEXTURE) { - if (_height >= (6 * _width)) { - _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); - _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - _gpuTexture->autoGenerateMips(-1); + _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); + _gpuTexture->autoGenerateMips(-1); + + std::vector faces; + if (_height == (6 * _width)) { + int faceWidth = _width; + + faces.push_back(image.copy(QRect(0, 0 * faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(0, 1 * faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(0, 2 * faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(0, 3 * faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(0, 4 * faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(0, 5 * faceWidth, faceWidth, faceWidth))); + } else if ((_height / 3) == (_width / 4)) { + int faceWidth = _height / 3; + faces.push_back(image.copy(QRect(2 * faceWidth, faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(0 * faceWidth, faceWidth, faceWidth, faceWidth))); + + faces.push_back(image.copy(QRect(1 * faceWidth, 0, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(1 * faceWidth, 0 * faceWidth, faceWidth, faceWidth))); + + faces.push_back(image.copy(QRect(3 * faceWidth, faceWidth, faceWidth, faceWidth))); + faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth))); + } + + if (faces.size() == _gpuTexture->getNumFaces()) { + int f = 0; + for (auto& face : faces) { + _gpuTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f); + f++; + } } } else { _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); From 45e70c98f809c79abf44976961d48026f35e02f7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 May 2015 13:43:15 -0700 Subject: [PATCH 4/9] Fixed the cube map loading issue --- libraries/gpu/src/gpu/Texture.h | 12 +++ .../render-utils/src/DeferredGlobalLight.slh | 7 +- libraries/render-utils/src/TextureCache.cpp | 91 +++++++++++++++---- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 4120f31659..e4f66c94e6 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -121,6 +121,18 @@ public: NUM_TYPES, }; + // Definition of the cube face name and layout + enum CubeFace { + CUBE_FACE_RIGHT_POS_X = 0, + CUBE_FACE_LEFT_NEG_X, + CUBE_FACE_TOP_POS_Y, + CUBE_FACE_BOTTOM_NEG_Y, + CUBE_FACE_BACK_POS_X, + CUBE_FACE_FRONT_NEG_Z, + + NUM_CUBE_FACES, // Not a valid vace index + }; + class Storage { public: Storage() {} diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 9583f8664b..c59c26894c 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -108,11 +108,12 @@ vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light); + // vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light); + vec3 color = /*diffuse.rgb * */evalSkyboxLight(fragNormal, getLightAmbientIntensity(light)).xyz; - vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); + // vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + // color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 803350629d..c1c8ec030f 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -524,32 +524,89 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo } if (_type == CUBE_TEXTURE) { - _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); - _gpuTexture->autoGenerateMips(-1); std::vector faces; if (_height == (6 * _width)) { int faceWidth = _width; - - faces.push_back(image.copy(QRect(0, 0 * faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(0, 1 * faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(0, 2 * faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(0, 3 * faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(0, 4 * faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(0, 5 * faceWidth, faceWidth, faceWidth))); + + // Here is the expected layout for the faces in an image with the 1/6 aspect ratio: + // + // WIDTH + // <------> + // ^ +------+ + // | | | + // | | +X | + // | | | + // H +------+ + // E | | + // I | -X | + // G | | + // H +------+ + // T | | + // | | +Y | + // | | | + // | +------+ + // | | | + // | | -Y | + // | | | + // H +------+ + // E | | + // I | +Z | + // G | | + // H +------+ + // T | | + // | | -Z | + // | | | + // V +------+ + // + // FaceWidth = width = height / 6 + + faces.push_back(image.copy(QRect(0, 0 * faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + faces.push_back(image.copy(QRect(0, 1 * faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + faces.push_back(image.copy(QRect(0, 2 * faceWidth, faceWidth, faceWidth)).mirrored(false, true)); + faces.push_back(image.copy(QRect(0, 3 * faceWidth, faceWidth, faceWidth)).mirrored(false, true)); + faces.push_back(image.copy(QRect(0, 4 * faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + faces.push_back(image.copy(QRect(0, 5 * faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + } else if ((_height / 3) == (_width / 4)) { int faceWidth = _height / 3; - faces.push_back(image.copy(QRect(2 * faceWidth, faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(0 * faceWidth, faceWidth, faceWidth, faceWidth))); - - faces.push_back(image.copy(QRect(1 * faceWidth, 0, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(1 * faceWidth, 0 * faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(3 * faceWidth, faceWidth, faceWidth, faceWidth))); - faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth))); + // Here is the expected layout for the faces in an image with the 3/4 aspect ratio: + // + // <-----------WIDTH-----------> + // ^ +------+------+------+------+ + // | | | | | | + // | | | +Y | | | + // | | | | | | + // H +------+------+------+------+ + // E | | | | | + // I | -X | -Z | +X | +Z | + // G | | | | | + // H +------+------+------+------+ + // T | | | | | + // | | | -Y | | | + // | | | | | | + // V +------+------+------+------+ + // + // FaceWidth = width / 4 = height / 3 + + // Right = +X + faces.push_back(image.copy(QRect(2 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + // Left = -X + faces.push_back(image.copy(QRect(0 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + // Top = +Y + faces.push_back(image.copy(QRect(1 * faceWidth, 0, faceWidth, faceWidth)).mirrored(false, true)); + // Bottom = -Y + faces.push_back(image.copy(QRect(1 * faceWidth, 2 * faceWidth, faceWidth, faceWidth)).mirrored(false, true)); + // Back = +Z + faces.push_back(image.copy(QRect(3 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false)); + // Front = -Z + faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false)); } - if (faces.size() == _gpuTexture->getNumFaces()) { + if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) { + _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); + _gpuTexture->autoGenerateMips(-1); int f = 0; for (auto& face : faces) { _gpuTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f); From f2c4e04a5a01eb89a166787cdada3c5ca9e65caa Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 May 2015 14:06:10 -0700 Subject: [PATCH 5/9] clean up for pr --- interface/src/Application.cpp | 2 +- .../render-utils/src/DeferredGlobalLight.slh | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d010119f23..dba4bd25f5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3330,7 +3330,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs auto skyStage = DependencyManager::get()->getSkyStage(); DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity()); DependencyManager::get()->setGlobalAtmosphere(skyStage->getAtmosphere()); - DependencyManager::get()->setGlobalSkybox(skybox); + // NOt yet DependencyManager::get()->setGlobalSkybox(skybox); PROFILE_RANGE("DeferredLighting"); PerformanceTimer perfTimer("lighting"); diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index c59c26894c..269827fbef 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -17,8 +17,12 @@ uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { -// vec4 skytexel = textureCube(skyboxMap, direction); +<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); +<@else@> + const int NUM_LEVELS = 10; + vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * NUM_LEVELS); +<@endif@> return skytexel; } @@ -108,12 +112,11 @@ vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - // vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light); - vec3 color = /*diffuse.rgb * */evalSkyboxLight(fragNormal, getLightAmbientIntensity(light)).xyz; + vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light); + + vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - // vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - - // color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } From 67b9dd248d7ff65a352869d29ad8428122539236 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 11 May 2015 14:25:05 -0700 Subject: [PATCH 6/9] Fix glsl failed compilation on Mac --- .../render-utils/src/DeferredGlobalLight.slh | 79 +++++++++---------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 269827fbef..d676a9c6b7 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -15,49 +15,48 @@ uniform samplerCube skyboxMap; -vec4 evalSkyboxLight(vec3 direction, float lod) { - -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> - vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); -<@else@> - const int NUM_LEVELS = 10; - vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * NUM_LEVELS); -<@endif@> - return skytexel; +vec4 evalSkyboxLight(vec3 direction, float lod) { + +<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> + vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); +<@else@> + vec4 skytexel = textureCube(skyboxMap, direction); +<@endif@> + return skytexel; } -struct SphericalHarmonics { - vec4 L00; - vec4 L1m1; - vec4 L10; - vec4 L11; - vec4 L2m2; - vec4 L2m1; - vec4 L20; - vec4 L21; - vec4 L22; +struct SphericalHarmonics { + vec4 L00; + vec4 L1m1; + vec4 L10; + vec4 L11; + vec4 L2m2; + vec4 L2m1; + vec4 L20; + vec4 L21; + vec4 L22; }; - -vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { - - vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis? - - const float C1 = 0.429043; - const float C2 = 0.511664; - const float C3 = 0.743125; - const float C4 = 0.886227; - const float C5 = 0.247708; - - vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) + - C3 * sh.L20 * dir.z * dir.z + - C4 * sh.L00 - C5 * sh.L20 + - 2.0 * C1 * ( sh.L2m2 * dir.x * dir.y + - sh.L21 * dir.x * dir.z + - sh.L2m1 * dir.y * dir.z ) + - 2.0 * C2 * ( sh.L11 * dir.x + - sh.L1m1 * dir.y + - sh.L10 * dir.z ) ; - return value; + +vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { + + vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis? + + const float C1 = 0.429043; + const float C2 = 0.511664; + const float C3 = 0.743125; + const float C4 = 0.886227; + const float C5 = 0.247708; + + vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) + + C3 * sh.L20 * dir.z * dir.z + + C4 * sh.L00 - C5 * sh.L20 + + 2.0 * C1 * ( sh.L2m2 * dir.x * dir.y + + sh.L21 * dir.x * dir.z + + sh.L2m1 * dir.y * dir.z ) + + 2.0 * C2 * ( sh.L11 * dir.x + + sh.L1m1 * dir.y + + sh.L10 * dir.z ) ; + return value; } // Need one SH From 6c606f630eaac320d9b5abb34b1a73c0e3c268ba Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 May 2015 15:22:13 -0700 Subject: [PATCH 7/9] adjust the alpha of the skybox to make it work with the glow effect --- libraries/model/src/model/Skybox.slf | 3 +-- libraries/model/src/model/Skybox.slv | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf index 03f7a5ef8a..5739cfda34 100755 --- a/libraries/model/src/model/Skybox.slf +++ b/libraries/model/src/model/Skybox.slf @@ -20,6 +20,5 @@ varying vec3 color; void main(void) { vec3 coord = normalize(normal); vec4 texel = textureCube(cubeMap, coord); - // gl_FragData[0] = vec4(texel.xyz * color, texel.w); - gl_FragData[0] = vec4(texel.xyz, 1.0); + gl_FragData[0] = vec4(texel.xyz * color, 0.0); } diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv index 1236e0d384..14c066905e 100755 --- a/libraries/model/src/model/Skybox.slv +++ b/libraries/model/src/model/Skybox.slv @@ -22,8 +22,7 @@ varying vec3 color; void main(void) { texcoord = gl_Vertex.xy; - // pass along the diffuse color - color = vec3(texcoord, 0.0); + color = vec3(1.0, 1.0, 1.0); // standard transform TransformCamera cam = getTransformCamera(); From e6bba04151b17c21dd693402363f38af3e0b330d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 May 2015 17:05:45 -0700 Subject: [PATCH 8/9] Enable the color blending for the skybox --- libraries/model/src/model/Skybox.cpp | 16 +++++++++++++++- libraries/model/src/model/Skybox.h | 1 + libraries/model/src/model/Skybox.slv | 24 +++++++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index 00a64c9606..08dcc491cf 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -52,6 +52,8 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky static gpu::PipelinePointer thePipeline; static gpu::BufferPointer theBuffer; static gpu::Stream::FormatPointer theFormat; + static gpu::BufferPointer theConstants; + const int SKYBOX_CONSTANTS_SLOT = 3; if (!thePipeline) { auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert))); auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag))); @@ -59,7 +61,8 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky gpu::Shader::BindingSet bindings; bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0)); - + bindings.insert(gpu::Shader::Binding(std::string("skyboxBuffer"), SKYBOX_CONSTANTS_SLOT)); + if (!gpu::Shader::makeProgram(*skyShader, bindings)) { } @@ -74,6 +77,9 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky theFormat.reset(new gpu::Stream::Format()); theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); + + auto color = glm::vec4(1.0f); + theConstants.reset(new gpu::Buffer(sizeof(color), (const gpu::Byte*) &color)); } glm::mat4 projMat; @@ -82,11 +88,19 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky Transform viewTransform; viewFrustum.evalViewTransform(viewTransform); + 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()); + } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewTransform); batch.setModelTransform(Transform()); // only for Mac batch.setPipeline(thePipeline); batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); + batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize()); batch.setInputFormat(theFormat); batch.setUniformTexture(0, skybox.getCubemap()); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/model/src/model/Skybox.h b/libraries/model/src/model/Skybox.h index de0ede8d90..b739032f39 100755 --- a/libraries/model/src/model/Skybox.h +++ b/libraries/model/src/model/Skybox.h @@ -38,6 +38,7 @@ public: protected: gpu::TexturePointer _cubemap; + Color _color{1.0f, 1.0f, 1.0f}; }; typedef std::shared_ptr< Skybox > SkyboxPointer; diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv index 14c066905e..c21863f9c7 100755 --- a/libraries/model/src/model/Skybox.slv +++ b/libraries/model/src/model/Skybox.slv @@ -15,6 +15,27 @@ <$declareStandardTransform()$> +struct Skybox { + vec4 _color; +}; + +<@if GPU_FEATURE_PROFILE == GPU_CORE @> +uniform skyboxBuffer { + Skybox _skybox; +}; +Skybox getSkybox() { + return _skybox; +} +<@else@> +uniform vec4 skyboxBuffer[1]; +Skybox getSkybox() { + Skybox _skybox; + _skybox._color = skyboxBuffer[0]; + + return _skybox; +} +<@endif@> + varying vec3 normal; varying vec2 texcoord; varying vec3 color; @@ -22,7 +43,8 @@ varying vec3 color; void main(void) { texcoord = gl_Vertex.xy; - color = vec3(1.0, 1.0, 1.0); + Skybox skybox = getSkybox(); + color = skybox._color.xyz; // standard transform TransformCamera cam = getTransformCamera(); From 449ca6df6d096e44b74224d1be2e422b334cc2a2 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 11 May 2015 17:27:22 -0700 Subject: [PATCH 9/9] fix the color blending on Mac --- libraries/model/src/model/Skybox.cpp | 9 ++++--- libraries/model/src/model/Skybox.slv | 37 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index 08dcc491cf..1a54ebd955 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -53,7 +53,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky static gpu::BufferPointer theBuffer; static gpu::Stream::FormatPointer theFormat; static gpu::BufferPointer theConstants; - const int SKYBOX_CONSTANTS_SLOT = 3; + 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))); @@ -61,12 +61,15 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky gpu::Shader::BindingSet bindings; bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0)); - bindings.insert(gpu::Shader::Binding(std::string("skyboxBuffer"), SKYBOX_CONSTANTS_SLOT)); - 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 = gpu::StatePointer(new gpu::State()); thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv index c21863f9c7..0ca64ffbf7 100755 --- a/libraries/model/src/model/Skybox.slv +++ b/libraries/model/src/model/Skybox.slv @@ -15,25 +15,24 @@ <$declareStandardTransform()$> -struct Skybox { - vec4 _color; -}; - -<@if GPU_FEATURE_PROFILE == GPU_CORE @> -uniform skyboxBuffer { - Skybox _skybox; -}; -Skybox getSkybox() { - return _skybox; -} -<@else@> -uniform vec4 skyboxBuffer[1]; -Skybox getSkybox() { - Skybox _skybox; - _skybox._color = skyboxBuffer[0]; - - return _skybox; -} +struct Skybox { + vec4 _color; +}; + +<@if GPU_FEATURE_PROFILE == GPU_CORE @> +uniform skyboxBuffer { + Skybox _skybox; +}; +Skybox getSkybox() { + return _skybox; +} +<@else@> +uniform vec4 skyboxBuffer[1]; +Skybox getSkybox() { + Skybox _skybox; + _skybox._color = skyboxBuffer[0]; + return _skybox; +} <@endif@> varying vec3 normal;