diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 19810be445..9a77cecefd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3116,6 +3116,14 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs } } } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) { + auto skybox = skyStage->getSkybox(); + if (skybox) { + gpu::Batch batch; + model::Skybox::render(batch, _viewFrustum, *skybox); + + gpu::GLBackend::renderBatch(batch); + glUseProgram(0); + } } if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 4b145b55a0..bff99e7ec3 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -91,6 +91,18 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, ui _params.push_back(nbInstances); } +void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil) { + ADD_COMMAND(clearFramebuffer); + + _params.push_back(stencil); + _params.push_back(depth); + _params.push_back(color.w); + _params.push_back(color.z); + _params.push_back(color.y); + _params.push_back(color.x); + _params.push_back(targets); +} + void Batch::setInputFormat(const Stream::FormatPointer& format) { ADD_COMMAND(setInputFormat); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index b6bc05ab40..b369c05646 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -81,6 +81,9 @@ public: void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0); void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0); + // Clear framebuffer layers + void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil); + // Input Stage // InputFormat // InputBuffers @@ -160,6 +163,8 @@ public: COMMAND_drawInstanced, COMMAND_drawIndexedInstanced, + COMMAND_clearFramebuffer, + COMMAND_setInputFormat, COMMAND_setInputBuffer, COMMAND_setIndexBuffer, diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 022ca02d6d..7ffb22f1c8 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -43,6 +43,7 @@ public: Mat4 _viewInverse; Mat4 _projectionViewUntranslated; Mat4 _projection; + Mat4 _projectionInverse; Vec4 _viewport; }; diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 69e507f824..50f42ed4fb 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -81,6 +81,7 @@ public: BUFFER_STENCIL = 0x80000000, BUFFER_DEPTHSTENCIL = 0xC0000000, }; + typedef uint32 Masks; ~Framebuffer(); @@ -111,7 +112,7 @@ public: // Properties - uint32 getBufferMask() const { return _bufferMask; } + Masks getBufferMask() const { return _bufferMask; } bool isEmpty() const { return (_bufferMask == 0); } bool hasColor() const { return (getBufferMask() & BUFFER_COLORS); } bool hasDepthStencil() const { return (getBufferMask() & BUFFER_DEPTHSTENCIL); } @@ -137,7 +138,7 @@ protected: TextureViews _renderBuffers; TextureView _depthStencilBuffer; - uint32 _bufferMask = 0; + Masks _bufferMask = 0; uint32 _frameCount = 0; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index a898c9042b..3c0ff4b309 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -17,7 +17,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_drawIndexed), (&::gpu::GLBackend::do_drawInstanced), (&::gpu::GLBackend::do_drawIndexedInstanced), - + (&::gpu::GLBackend::do_clearFramebuffer), + (&::gpu::GLBackend::do_setInputFormat), (&::gpu::GLBackend::do_setInputBuffer), (&::gpu::GLBackend::do_setIndexBuffer), @@ -170,6 +171,39 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { + + uint32 masks = batch._params[paramOffset + 6]._uint; + Vec4 color; + color.x = batch._params[paramOffset + 5]._float; + color.y = batch._params[paramOffset + 4]._float; + color.z = batch._params[paramOffset + 3]._float; + color.w = batch._params[paramOffset + 2]._float; + float depth = batch._params[paramOffset + 1]._float; + int stencil = batch._params[paramOffset + 0]._float; + + GLuint glmask = 0; + if (masks & Framebuffer::BUFFER_DEPTH) { + glClearStencil(stencil); + glmask |= GL_STENCIL_BUFFER_BIT; + } + + if (masks & Framebuffer::BUFFER_DEPTH) { + glClearDepth(depth); + glmask |= GL_DEPTH_BUFFER_BIT; + } + + if (masks & Framebuffer::BUFFER_COLORS) { + glClearColor(color.x, color.y, color.z, color.w); + glmask |= GL_COLOR_BUFFER_BIT; + } + + glClear(glmask); + + (void) CHECK_GL_ERROR(); +} + + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index b725fa46d0..9943af1679 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -191,6 +191,8 @@ protected: void do_drawInstanced(Batch& batch, uint32 paramOffset); void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset); + void do_clearFramebuffer(Batch& batch, uint32 paramOffset); + // Input Stage void do_setInputFormat(Batch& batch, uint32 paramOffset); void do_setInputBuffer(Batch& batch, uint32 paramOffset); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 48a45ce93f..938ed77730 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -171,10 +171,21 @@ void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 1]._uint; TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); - GLuint to = getTextureID(uniformTexture); - glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(GL_TEXTURE_2D, to); + if (!uniformTexture) { + return; + } - (void) CHECK_GL_ERROR(); + GLTexture* object = GLBackend::syncGPUObject(*uniformTexture); + if (object) { + GLuint to = object->_texture; + GLuint target = object->_target; + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(target, to); + + (void) CHECK_GL_ERROR(); + + } else { + return; + } } diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index da39ab16fa..97987a401a 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -363,6 +363,93 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { } break; } + case Texture::TEX_CUBE: { + if (texture.getNumSlices() == 1) { + GLint boundTex = -1; + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &boundTex); + 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_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::Resource::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); + 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 (bytes && texture.isAutogenerateMips()) { + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + 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->_storageStamp = texture.getStamp(); + object->_size = texture.getSize(); + } + + glBindTexture(GL_TEXTURE_CUBE_MAP, boundTex); + } + break; + } default: qCDebug(gpulogging) << "GLBackend::syncGPUObject(const Texture&) case for Texture Type " << texture.getType() << " not supported"; } @@ -449,6 +536,5 @@ void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, GLTextur glTexParameterf(object->_target, GL_TEXTURE_MIN_LOD, (float) sampler.getMinMip()); glTexParameterf(object->_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip())); glTexParameterf(object->_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy()); - (void) CHECK_GL_ERROR(); } diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 88c993985f..d619d0afee 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -59,6 +59,7 @@ void GLBackend::updateTransform() { // Check all the dirty flags and update the state accordingly if (_transform._invalidProj) { _transform._transformCamera._projection = _transform._projection; + _transform._transformCamera._projectionInverse = glm::inverse(_transform._projection); } if (_transform._invalidView) { diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index f73b24411b..d4891fcf7c 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -15,6 +15,8 @@ using namespace gpu; +uint8 Texture::NUM_FACES_PER_TYPE[NUM_TYPES] = {1, 1, 1, 6}; + Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) : _sysmem(size, bytes), _format(format), @@ -131,19 +133,7 @@ Texture* Texture::createFromStorage(Storage* storage) { } Texture::Texture(): - Resource(), - _storage(), - _stamp(0), - _size(0), - _width(1), - _height(1), - _depth(1), - _numSamples(1), - _numSlices(1), - _maxMip(0), - _type(TEX_1D), - _autoGenerateMips(false), - _defined(false) + Resource() { } @@ -186,10 +176,9 @@ Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 widt _depth = depth; changed = true; } - + // Evaluate the new size with the new format - const int DIM_SIZE[] = {1, 1, 1, 6}; - uint32_t size = DIM_SIZE[_type] *_width * _height * _depth * _numSamples * texelFormat.getSize(); + uint32_t size = NUM_FACES_PER_TYPE[_type] *_width * _height * _depth * _numSamples * texelFormat.getSize(); // If size change then we need to reset if (changed || (size != getSize())) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index c7f82839a0..5523f7f417 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -138,6 +138,8 @@ public: TEX_2D, TEX_3D, TEX_CUBE, + + NUM_TYPES, }; static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); @@ -180,11 +182,19 @@ public: uint16 getDepth() const { return _depth; } uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); } - uint32 getNumTexels() const { return _width * _height * _depth; } + + // The number of faces is mostly used for cube map, and maybe for stereo ? otherwise it's 1 + // For cube maps, this means the pixels of the different faces are supposed to bepacked back to back in a mip + // as if the height was NUM_FACES time bigger. + static uint8 NUM_FACES_PER_TYPE[NUM_TYPES]; + uint8 getNumFaces() const { return NUM_FACES_PER_TYPE[getType()]; } + + uint32 getNumTexels() const { return _width * _height * _depth * getNumFaces(); } uint16 getNumSlices() const { return _numSlices; } uint16 getNumSamples() const { return _numSamples; } + // NumSamples can only have certain values based on the hw static uint16 evalNumSamplesUsed(uint16 numSamplesTried); @@ -203,7 +213,7 @@ 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); } + uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getNumFaces(); } uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); } uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); } @@ -269,27 +279,26 @@ public: protected: std::unique_ptr< Storage > _storage; - Stamp _stamp; + Stamp _stamp = 0; Sampler _sampler; Stamp _samplerStamp; - - uint32 _size; + uint32 _size = 0; Element _texelFormat; - uint16 _width; - uint16 _height; - uint16 _depth; + uint16 _width = 1; + uint16 _height = 1; + uint16 _depth = 1; - uint16 _numSamples; - uint16 _numSlices; + uint16 _numSamples = 1; + uint16 _numSlices = 1; - uint16 _maxMip; + uint16 _maxMip = 0; - Type _type; - bool _autoGenerateMips; - bool _defined; + Type _type = TEX_1D; + bool _autoGenerateMips = false; + bool _defined = false; static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler); Texture(); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 042964f0f7..a65fc7e9bd 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -21,6 +21,7 @@ struct TransformCamera { mat4 _viewInverse; mat4 _projectionViewUntranslated; mat4 _projection; + mat4 _projectionInverse; vec4 _viewport; }; @@ -120,4 +121,22 @@ TransformCamera getTransformCamera() { <@endif@> <@endfunc@> +<@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@> +<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> + { // transformEyeToWorldDir + <$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); + } +<@else@> +<@endif@> +<@endfunc@> + +<@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> +<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> + { // transformClipToEyedDir + <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); + } +<@else@> +<@endif@> +<@endfunc@> + <@endif@> diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index 9a1addc9c7..c9b0d270fb 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -10,12 +10,73 @@ // #include "Skybox.h" +#include "gpu/Batch.h" +#include "gpu/Context.h" + +#include "ViewFrustum.h" +#include "skybox_vert.h" +#include "skybox_frag.h" + using namespace model; Skybox::Skybox() { + + _cubemap.reset( gpu::Texture::createCube(gpu::Element::COLOR_RGBA_32, 1)); + unsigned char texels[] = { + 255, 0, 0, 255, + 0, 255, 255, 255, + 0, 0, 255, 255, + 255, 255, 0, 255, + 0, 255, 0, 255, + 255, 0, 255, 255, + }; + _cubemap->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, sizeof(texels), texels); +} + +void Skybox::setColor(const Color& color) { + _color = color; } void Skybox::setCubemap(const gpu::TexturePointer& cubemap) { _cubemap = cubemap; } +void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) { + + if (skybox.getCubemap()) { + + static gpu::PipelinePointer thePipeline; + 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)) { + + } + + auto skyState = gpu::StatePointer(new gpu::State()); + + thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); + } + + glm::mat4 projMat; + viewFrustum.evalProjectionMatrix(projMat); + + Transform viewTransform; + viewFrustum.evalViewTransform(viewTransform); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewTransform); + batch.setPipeline(thePipeline); + batch.setUniformTexture(0, skybox.getCubemap()); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } else { + // skybox has no cubemap, just clear the color buffer + auto color = skybox.getColor(); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(skybox.getColor(),1.0f), 0.f, 0); + } +} diff --git a/libraries/model/src/model/Skybox.h b/libraries/model/src/model/Skybox.h index 8a04265129..8eb910a96e 100755 --- a/libraries/model/src/model/Skybox.h +++ b/libraries/model/src/model/Skybox.h @@ -13,6 +13,10 @@ #include "gpu/Texture.h" +class ViewFrustum; +//class Transform; +namespace gpu { class Batch; } + namespace model { typedef glm::vec3 Color; @@ -24,14 +28,16 @@ public: virtual ~Skybox() {}; void setColor(const Color& color); - const Color& getColor() { return _color; } + const Color& getColor() const { return _color; } void setCubemap(const gpu::TexturePointer& cubemap); const gpu::TexturePointer& getCubemap() const { return _cubemap; } + static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox); + protected: gpu::TexturePointer _cubemap; - Color _color; + Color _color{1.0f, 1.0f, 1.0f}; }; typedef std::shared_ptr< Skybox > SkyboxPointer; diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf new file mode 100755 index 0000000000..da9f9401bc --- /dev/null +++ b/libraries/model/src/model/Skybox.slf @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// skybox.frag +// +// Created by Sam Gateau on 5/5/2015. +// Copyright 2015 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 +// + +uniform samplerCube cubeMap; + +varying vec3 normal; +varying vec2 texcoord; +varying vec3 color; + + +void main(void) { + vec4 texel = texture(cubeMap, normalize(normal)); + gl_FragData[0] = texel; + // gl_FragData[0] = vec4(normal, 1.0); +} diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv new file mode 100755 index 0000000000..d4fe58959f --- /dev/null +++ b/libraries/model/src/model/Skybox.slv @@ -0,0 +1,42 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// skybox.vert +// vertex shader +// +// Created by Sam Gateau on 5/5/2015. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec3 normal; +varying vec2 texcoord; +varying vec3 color; + +void main(void) { + const float CLIP = 1.0; + const vec2 vertices[4] = vec2[4](vec2(-CLIP, -CLIP), vec2(CLIP, -CLIP), vec2(-CLIP, CLIP), vec2(CLIP, CLIP)); + texcoord = vertices[gl_VertexID]; + + // pass along the diffuse color + color = vec3(texcoord, 0.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + vec3 clipDir = vec3(texcoord.xy, 0.0); + 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/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 453bc0c154..2e579d3618 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -215,6 +215,10 @@ SunSkyStage::SunSkyStage() : _skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); + + _skybox.reset(new Skybox()); + _skybox->setColor(Color(1.0f, 0.0f, 0.0f)); + } SunSkyStage::~SunSkyStage() { diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index b28c20fc65..d22269bece 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -223,7 +223,7 @@ public: const SkyboxPointer& getSkybox() const { valid(); return _skybox; } protected: - BackgroundMode _backgroundMode = SKY_DOME; + BackgroundMode _backgroundMode = SKY_BOX; LightPointer _sunLight; AtmospherePointer _atmosphere; diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index b18b2fcb3e..11ed24799d 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -862,3 +862,7 @@ void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { } } +void ViewFrustum::evalViewTransform(Transform& view) const { + view.setTranslation(getPosition()); + view.setRotation(getOrientation()); +} diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 3c8639d215..dfb0dcb308 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -20,6 +20,7 @@ #include #include +#include "Transform.h" #include "AABox.h" #include "AACube.h" #include "Plane.h" @@ -121,6 +122,8 @@ public: float distanceToCamera(const glm::vec3& point) const; void evalProjectionMatrix(glm::mat4& proj) const; + void evalViewTransform(Transform& view) const; + private: // Used for keyhole calculations ViewFrustum::location pointInKeyhole(const glm::vec3& point) const;