diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index d570007b3e..ea650c6ad9 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -7,279 +7,279 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Framebuffer.h" -#include -#include - -using namespace gpu; - -Framebuffer::~Framebuffer() { -} - -Framebuffer* Framebuffer::create() { - auto framebuffer = new Framebuffer(); - framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS); - return framebuffer; -} - - -Framebuffer* Framebuffer::create( const Format& colorBufferFormat, uint16 width, uint16 height) { - auto framebuffer = Framebuffer::create(); - - auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); - - framebuffer->setRenderBuffer(0, colorTexture); - - return framebuffer; -} - -Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height) { - auto framebuffer = Framebuffer::create(); - - auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); - auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); - - framebuffer->setRenderBuffer(0, colorTexture); - framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat); - - return framebuffer; -} - -Framebuffer* Framebuffer::createShadowmap(uint16 width) { - auto framebuffer = Framebuffer::create(); - auto depthTexture = TexturePointer(Texture::create2D(Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH), width, width)); +// + +#include "Framebuffer.h" +#include +#include + +using namespace gpu; + +Framebuffer::~Framebuffer() { +} + +Framebuffer* Framebuffer::create() { + auto framebuffer = new Framebuffer(); + framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS); + return framebuffer; +} + + +Framebuffer* Framebuffer::create( const Format& colorBufferFormat, uint16 width, uint16 height) { + auto framebuffer = Framebuffer::create(); + + auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); + + framebuffer->setRenderBuffer(0, colorTexture); + + return framebuffer; +} + +Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height) { + auto framebuffer = Framebuffer::create(); + + auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); + auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); + + framebuffer->setRenderBuffer(0, colorTexture); + framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat); + + return framebuffer; +} + +Framebuffer* Framebuffer::createShadowmap(uint16 width) { + auto framebuffer = Framebuffer::create(); + auto depthTexture = TexturePointer(Texture::create2D(Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH), width, width)); Sampler::Desc samplerDesc; samplerDesc._borderColor = glm::vec4(1.0f); samplerDesc._wrapModeU = Sampler::WRAP_BORDER; samplerDesc._wrapModeV = Sampler::WRAP_BORDER; samplerDesc._filter = Sampler::FILTER_MIN_MAG_LINEAR; - samplerDesc._comparisonFunc = LESS_EQUAL; - - depthTexture->setSampler(Sampler(samplerDesc)); - - framebuffer->setDepthStencilBuffer(depthTexture, Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH)); - - return framebuffer; -} - -bool Framebuffer::isSwapchain() const { - return _swapchain != 0; -} - -uint32 Framebuffer::getFrameCount() const { - if (_swapchain) { - return _swapchain->getFrameCount(); - } else { - return _frameCount; - } -} - -bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const { - if (texture.getType() == Texture::TEX_1D) { - return false; - } - - if (isEmpty()) { - return true; - } else { - if ((texture.getWidth() == getWidth()) && - (texture.getHeight() == getHeight()) && - (texture.getNumSamples() == getNumSamples())) { - return true; - } else { - return false; - } - } -} - -void Framebuffer::updateSize(const TexturePointer& texture) { - if (!isEmpty()) { - return; - } - - if (texture) { - _width = texture->getWidth(); - _height = texture->getHeight(); - _numSamples = texture->getNumSamples(); - } else { - _width = _height = _numSamples = 0; - } -} - -void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) { - if (width && height && numSamples && !isEmpty() && !isSwapchain()) { - if ((width != _width) || (height != _height) || (numSamples != _numSamples)) { - for (uint32 i = 0; i < _renderBuffers.size(); ++i) { - if (_renderBuffers[i]) { - _renderBuffers[i]._texture->resize2D(width, height, numSamples); - _numSamples = _renderBuffers[i]._texture->getNumSamples(); - } - } - - if (_depthStencilBuffer) { - _depthStencilBuffer._texture->resize2D(width, height, numSamples); - _numSamples = _depthStencilBuffer._texture->getNumSamples(); - } - - _width = width; - _height = height; - // _numSamples = numSamples; - } - } -} - -uint16 Framebuffer::getWidth() const { - if (isSwapchain()) { - return getSwapchain()->getWidth(); - } else { - return _width; - } -} - -uint16 Framebuffer::getHeight() const { - if (isSwapchain()) { - return getSwapchain()->getHeight(); - } else { - return _height; - } -} - -uint16 Framebuffer::getNumSamples() const { - if (isSwapchain()) { - return getSwapchain()->getNumSamples(); - } else { - return _numSamples; - } -} - -// Render buffers -int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource) { - if (isSwapchain()) { - return -1; - } - - // Check for the slot - if (slot >= getMaxNumRenderBuffers()) { - return -1; - } - - // Check for the compatibility of size - if (texture) { - if (!validateTargetCompatibility(*texture, subresource)) { - return -1; - } - } - - updateSize(texture); - - // assign the new one - _renderBuffers[slot] = TextureView(texture, subresource); - - // update the mask - int mask = (1<getDepthStencilBufferFormat(); - return _depthStencilBuffer._element; - } else { - return _depthStencilBuffer._element; - } + samplerDesc._comparisonFunc = LESS_EQUAL; + + depthTexture->setSampler(Sampler(samplerDesc)); + + framebuffer->setDepthStencilBuffer(depthTexture, Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH)); + + return framebuffer; +} + +bool Framebuffer::isSwapchain() const { + return _swapchain != 0; +} + +uint32 Framebuffer::getFrameCount() const { + if (_swapchain) { + return _swapchain->getFrameCount(); + } else { + return _frameCount; + } +} + +bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const { + if (texture.getType() == Texture::TEX_1D) { + return false; + } + + if (isEmpty()) { + return true; + } else { + if ((texture.getWidth() == getWidth()) && + (texture.getHeight() == getHeight()) && + (texture.getNumSamples() == getNumSamples())) { + return true; + } else { + return false; + } + } +} + +void Framebuffer::updateSize(const TexturePointer& texture) { + if (!isEmpty()) { + return; + } + + if (texture) { + _width = texture->getWidth(); + _height = texture->getHeight(); + _numSamples = texture->getNumSamples(); + } else { + _width = _height = _numSamples = 0; + } +} + +void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) { + if (width && height && numSamples && !isEmpty() && !isSwapchain()) { + if ((width != _width) || (height != _height) || (numSamples != _numSamples)) { + for (uint32 i = 0; i < _renderBuffers.size(); ++i) { + if (_renderBuffers[i]) { + _renderBuffers[i]._texture->resize2D(width, height, numSamples); + _numSamples = _renderBuffers[i]._texture->getNumSamples(); + } + } + + if (_depthStencilBuffer) { + _depthStencilBuffer._texture->resize2D(width, height, numSamples); + _numSamples = _depthStencilBuffer._texture->getNumSamples(); + } + + _width = width; + _height = height; + // _numSamples = numSamples; + } + } +} + +uint16 Framebuffer::getWidth() const { + if (isSwapchain()) { + return getSwapchain()->getWidth(); + } else { + return _width; + } +} + +uint16 Framebuffer::getHeight() const { + if (isSwapchain()) { + return getSwapchain()->getHeight(); + } else { + return _height; + } +} + +uint16 Framebuffer::getNumSamples() const { + if (isSwapchain()) { + return getSwapchain()->getNumSamples(); + } else { + return _numSamples; + } +} + +// Render buffers +int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource) { + if (isSwapchain()) { + return -1; + } + + // Check for the slot + if (slot >= getMaxNumRenderBuffers()) { + return -1; + } + + // Check for the compatibility of size + if (texture) { + if (!validateTargetCompatibility(*texture, subresource)) { + return -1; + } + } + + updateSize(texture); + + // assign the new one + _renderBuffers[slot] = TextureView(texture, subresource); + + // update the mask + int mask = (1<getDepthStencilBufferFormat(); + return _depthStencilBuffer._element; + } else { + return _depthStencilBuffer._element; + } } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 83ff8fbb23..807047a56e 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -1,167 +1,167 @@ -// -// Framebuffer.h -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 4/12/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 -// -#ifndef hifi_gpu_Framebuffer_h -#define hifi_gpu_Framebuffer_h - -#include "Texture.h" -#include - -namespace gpu { - -typedef Element Format; - -class Swapchain { -public: - // Properties - uint16 getWidth() const { return _width; } - uint16 getHeight() const { return _height; } - uint16 getNumSamples() const { return _numSamples; } - - bool hasDepthStencil() const { return _hasDepthStencil; } - bool isFullscreen() const { return _isFullscreen; } - - uint32 getSwapInterval() const { return _swapInterval; } - - bool isStereo() const { return _isStereo; } - - uint32 getFrameCount() const { return _frameCount; } - - // Pure interface - void setSwapInterval(uint32 interval); - - void resize(uint16 width, uint16 height); - void setFullscreen(bool fullscreen); - - Swapchain() {} - Swapchain(const Swapchain& swapchain) {} - virtual ~Swapchain() {} - -protected: - mutable uint32 _frameCount = 0; - - Format _colorFormat; - uint16 _width = 1; - uint16 _height = 1; - uint16 _numSamples = 1; - uint16 _swapInterval = 0; - - bool _hasDepthStencil = false; - bool _isFullscreen = false; - bool _isStereo = false; - - // Non exposed - - friend class Framebuffer; -}; -typedef std::shared_ptr SwapchainPointer; - - -class Framebuffer { -public: - enum BufferMask { - BUFFER_COLOR0 = 1, - BUFFER_COLOR1 = 2, - BUFFER_COLOR2 = 4, - BUFFER_COLOR3 = 8, - BUFFER_COLOR4 = 16, - BUFFER_COLOR5 = 32, - BUFFER_COLOR6 = 64, - BUFFER_COLOR7 = 128, - BUFFER_COLORS = 0x000000FF, - - BUFFER_DEPTH = 0x40000000, - BUFFER_STENCIL = 0x80000000, - BUFFER_DEPTHSTENCIL = 0xC0000000, - }; - typedef uint32 Masks; - - ~Framebuffer(); - - static Framebuffer* create(const SwapchainPointer& swapchain); - static Framebuffer* create(); - static Framebuffer* create(const Format& colorBufferFormat, uint16 width, uint16 height); - static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height); - static Framebuffer* createShadowmap(uint16 width); - - bool isSwapchain() const; - SwapchainPointer getSwapchain() const { return _swapchain; } - - uint32 getFrameCount() const; - - // Render buffers - void removeRenderBuffers(); - uint32 getNumRenderBuffers() const; - const TextureViews& getRenderBuffers() const { return _renderBuffers; } - - int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); - TexturePointer getRenderBuffer(uint32 slot) const; - uint32 getRenderBufferSubresource(uint32 slot) const; - - bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); - TexturePointer getDepthStencilBuffer() const; - uint32 getDepthStencilBufferSubresource() const; - Format getDepthStencilBufferFormat() const; - - - // Properties - 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); } - bool hasDepth() const { return (getBufferMask() & BUFFER_DEPTH); } - bool hasStencil() const { return (getBufferMask() & BUFFER_STENCIL); } - - bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const; - - Vec2u getSize() const { return Vec2u(getWidth(), getHeight()); } - uint16 getWidth() const; - uint16 getHeight() const; - uint16 getNumSamples() const; - - float getAspectRatio() const { return getWidth() / (float) getHeight() ; } - - // If not a swapchain canvas, resize can resize all the render buffers and depth stencil attached in one call - void resize( uint16 width, uint16 height, uint16 samples = 1 ); - - static const uint32 MAX_NUM_RENDER_BUFFERS = 8; - static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } - -protected: - SwapchainPointer _swapchain; - - TextureViews _renderBuffers; - TextureView _depthStencilBuffer; - - Masks _bufferMask = 0; - - uint32 _frameCount = 0; - - uint16 _width = 0; - uint16 _height = 0; - uint16 _numSamples = 0; - - void updateSize(const TexturePointer& texture); - - // Non exposed - Framebuffer(const Framebuffer& framebuffer) = delete; - Framebuffer() {} - - // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = NULL; - void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } - GPUObject* getGPUObject() const { return _gpuObject; } - friend class Backend; -}; -typedef std::shared_ptr FramebufferPointer; - -} - -#endif +// +// Framebuffer.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 4/12/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 +// +#ifndef hifi_gpu_Framebuffer_h +#define hifi_gpu_Framebuffer_h + +#include "Texture.h" +#include + +namespace gpu { + +typedef Element Format; + +class Swapchain { +public: + // Properties + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + uint16 getNumSamples() const { return _numSamples; } + + bool hasDepthStencil() const { return _hasDepthStencil; } + bool isFullscreen() const { return _isFullscreen; } + + uint32 getSwapInterval() const { return _swapInterval; } + + bool isStereo() const { return _isStereo; } + + uint32 getFrameCount() const { return _frameCount; } + + // Pure interface + void setSwapInterval(uint32 interval); + + void resize(uint16 width, uint16 height); + void setFullscreen(bool fullscreen); + + Swapchain() {} + Swapchain(const Swapchain& swapchain) {} + virtual ~Swapchain() {} + +protected: + mutable uint32 _frameCount = 0; + + Format _colorFormat; + uint16 _width = 1; + uint16 _height = 1; + uint16 _numSamples = 1; + uint16 _swapInterval = 0; + + bool _hasDepthStencil = false; + bool _isFullscreen = false; + bool _isStereo = false; + + // Non exposed + + friend class Framebuffer; +}; +typedef std::shared_ptr SwapchainPointer; + + +class Framebuffer { +public: + enum BufferMask { + BUFFER_COLOR0 = 1, + BUFFER_COLOR1 = 2, + BUFFER_COLOR2 = 4, + BUFFER_COLOR3 = 8, + BUFFER_COLOR4 = 16, + BUFFER_COLOR5 = 32, + BUFFER_COLOR6 = 64, + BUFFER_COLOR7 = 128, + BUFFER_COLORS = 0x000000FF, + + BUFFER_DEPTH = 0x40000000, + BUFFER_STENCIL = 0x80000000, + BUFFER_DEPTHSTENCIL = 0xC0000000, + }; + typedef uint32 Masks; + + ~Framebuffer(); + + static Framebuffer* create(const SwapchainPointer& swapchain); + static Framebuffer* create(); + static Framebuffer* create(const Format& colorBufferFormat, uint16 width, uint16 height); + static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height); + static Framebuffer* createShadowmap(uint16 width); + + bool isSwapchain() const; + SwapchainPointer getSwapchain() const { return _swapchain; } + + uint32 getFrameCount() const; + + // Render buffers + void removeRenderBuffers(); + uint32 getNumRenderBuffers() const; + const TextureViews& getRenderBuffers() const { return _renderBuffers; } + + int32 setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource = 0); + TexturePointer getRenderBuffer(uint32 slot) const; + uint32 getRenderBufferSubresource(uint32 slot) const; + + bool setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource = 0); + TexturePointer getDepthStencilBuffer() const; + uint32 getDepthStencilBufferSubresource() const; + Format getDepthStencilBufferFormat() const; + + + // Properties + 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); } + bool hasDepth() const { return (getBufferMask() & BUFFER_DEPTH); } + bool hasStencil() const { return (getBufferMask() & BUFFER_STENCIL); } + + bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const; + + Vec2u getSize() const { return Vec2u(getWidth(), getHeight()); } + uint16 getWidth() const; + uint16 getHeight() const; + uint16 getNumSamples() const; + + float getAspectRatio() const { return getWidth() / (float) getHeight() ; } + + // If not a swapchain canvas, resize can resize all the render buffers and depth stencil attached in one call + void resize( uint16 width, uint16 height, uint16 samples = 1 ); + + static const uint32 MAX_NUM_RENDER_BUFFERS = 8; + static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } + +protected: + SwapchainPointer _swapchain; + + TextureViews _renderBuffers; + TextureView _depthStencilBuffer; + + Masks _bufferMask = 0; + + uint32 _frameCount = 0; + + uint16 _width = 0; + uint16 _height = 0; + uint16 _numSamples = 0; + + void updateSize(const TexturePointer& texture); + + // Non exposed + Framebuffer(const Framebuffer& framebuffer) = delete; + Framebuffer() {} + + // This shouldn't be used by anything else than the Backend class with the proper casting. + mutable GPUObject* _gpuObject = NULL; + void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } + GPUObject* getGPUObject() const { return _gpuObject; } + friend class Backend; +}; +typedef std::shared_ptr FramebufferPointer; + +} + +#endif diff --git a/libraries/gpu/src/gpu/Pipeline.cpp b/libraries/gpu/src/gpu/Pipeline.cpp index 237932b07d..501cb3fea4 100755 --- a/libraries/gpu/src/gpu/Pipeline.cpp +++ b/libraries/gpu/src/gpu/Pipeline.cpp @@ -1,29 +1,29 @@ -// -// Pipeline.cpp -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 3/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 -// - -#include "Pipeline.h" -#include -#include - -using namespace gpu; - -Pipeline::Pipeline(): - _program(), - _state() -{ -} - -Pipeline::~Pipeline() -{ -} +// +// Pipeline.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/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 +// + +#include "Pipeline.h" +#include +#include + +using namespace gpu; + +Pipeline::Pipeline(): + _program(), + _state() +{ +} + +Pipeline::~Pipeline() +{ +} Pipeline* Pipeline::create(const ShaderPointer& program, const StatePointer& state) { Pipeline* pipeline = new Pipeline(); diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index da3ab20c7b..cb5ced2c15 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -1,88 +1,88 @@ -// -// State.cpp -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 3/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 -// - -#include "State.h" -#include - -using namespace gpu; - -State::State() { -} - -State::~State() { -} - -// WARNING: GLBackend::GLState::_resetStateCommands heavily relies on the fact that State::DEFAULT = State::Data() -// Please make sure to go check makeResetStateCommands() before modifying this value -const State::Data State::DEFAULT = State::Data(); - -State::Signature State::evalSignature(const Data& state) { - Signature signature(0); - - if (state.fillMode != State::DEFAULT.fillMode) { - signature.set(State::FILL_MODE); - } - if (state.cullMode != State::DEFAULT.cullMode) { - signature.set(State::CULL_MODE); - } - if (state.frontFaceClockwise != State::DEFAULT.frontFaceClockwise) { - signature.set(State::FRONT_FACE_CLOCKWISE); - } - if (state.depthClampEnable != State::DEFAULT.depthClampEnable) { - signature.set(State::DEPTH_CLAMP_ENABLE); - } - if (state.scissorEnable != State::DEFAULT.scissorEnable) { - signature.set(State::SCISSOR_ENABLE); - } - if (state.multisampleEnable != State::DEFAULT.multisampleEnable) { - signature.set(State::MULTISAMPLE_ENABLE); - } - if (state.antialisedLineEnable != State::DEFAULT.antialisedLineEnable) { - signature.set(State::ANTIALISED_LINE_ENABLE); - } - if (state.depthBias != State::DEFAULT.depthBias) { - signature.set(State::DEPTH_BIAS); - } - if (state.depthBiasSlopeScale != State::DEFAULT.depthBiasSlopeScale) { - signature.set(State::DEPTH_BIAS_SLOPE_SCALE); - } - if (state.depthTest != State::DEFAULT.depthTest) { - signature.set(State::DEPTH_TEST); - } - if (state.stencilActivation != State::DEFAULT.stencilActivation) { - signature.set(State::STENCIL_ACTIVATION); - } - if (state.stencilTestFront != State::DEFAULT.stencilTestFront) { - signature.set(State::STENCIL_TEST_FRONT); - } - if (state.stencilTestBack != State::DEFAULT.stencilTestBack) { - signature.set(State::STENCIL_TEST_BACK); - } - if (state.sampleMask != State::DEFAULT.sampleMask) { - signature.set(State::SAMPLE_MASK); - } - if (state.alphaToCoverageEnable != State::DEFAULT.alphaToCoverageEnable) { - signature.set(State::ALPHA_TO_COVERAGE_ENABLE); - } - if (state.blendFunction != State::DEFAULT.blendFunction) { - signature.set(State::BLEND_FUNCTION); - } - if (state.colorWriteMask != State::DEFAULT.colorWriteMask) { - signature.set(State::COLOR_WRITE_MASK); - } - - return signature; -} - -State::State(const Data& values) : - _values(values) { - _signature = evalSignature(_values); -} +// +// State.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/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 +// + +#include "State.h" +#include + +using namespace gpu; + +State::State() { +} + +State::~State() { +} + +// WARNING: GLBackend::GLState::_resetStateCommands heavily relies on the fact that State::DEFAULT = State::Data() +// Please make sure to go check makeResetStateCommands() before modifying this value +const State::Data State::DEFAULT = State::Data(); + +State::Signature State::evalSignature(const Data& state) { + Signature signature(0); + + if (state.fillMode != State::DEFAULT.fillMode) { + signature.set(State::FILL_MODE); + } + if (state.cullMode != State::DEFAULT.cullMode) { + signature.set(State::CULL_MODE); + } + if (state.frontFaceClockwise != State::DEFAULT.frontFaceClockwise) { + signature.set(State::FRONT_FACE_CLOCKWISE); + } + if (state.depthClampEnable != State::DEFAULT.depthClampEnable) { + signature.set(State::DEPTH_CLAMP_ENABLE); + } + if (state.scissorEnable != State::DEFAULT.scissorEnable) { + signature.set(State::SCISSOR_ENABLE); + } + if (state.multisampleEnable != State::DEFAULT.multisampleEnable) { + signature.set(State::MULTISAMPLE_ENABLE); + } + if (state.antialisedLineEnable != State::DEFAULT.antialisedLineEnable) { + signature.set(State::ANTIALISED_LINE_ENABLE); + } + if (state.depthBias != State::DEFAULT.depthBias) { + signature.set(State::DEPTH_BIAS); + } + if (state.depthBiasSlopeScale != State::DEFAULT.depthBiasSlopeScale) { + signature.set(State::DEPTH_BIAS_SLOPE_SCALE); + } + if (state.depthTest != State::DEFAULT.depthTest) { + signature.set(State::DEPTH_TEST); + } + if (state.stencilActivation != State::DEFAULT.stencilActivation) { + signature.set(State::STENCIL_ACTIVATION); + } + if (state.stencilTestFront != State::DEFAULT.stencilTestFront) { + signature.set(State::STENCIL_TEST_FRONT); + } + if (state.stencilTestBack != State::DEFAULT.stencilTestBack) { + signature.set(State::STENCIL_TEST_BACK); + } + if (state.sampleMask != State::DEFAULT.sampleMask) { + signature.set(State::SAMPLE_MASK); + } + if (state.alphaToCoverageEnable != State::DEFAULT.alphaToCoverageEnable) { + signature.set(State::ALPHA_TO_COVERAGE_ENABLE); + } + if (state.blendFunction != State::DEFAULT.blendFunction) { + signature.set(State::BLEND_FUNCTION); + } + if (state.colorWriteMask != State::DEFAULT.colorWriteMask) { + signature.set(State::COLOR_WRITE_MASK); + } + + return signature; +} + +State::State(const Data& values) : + _values(values) { + _signature = evalSignature(_values); +} diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index e1855e0848..c3e2809c4b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -1,448 +1,448 @@ -// -// Texture.h -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 1/16/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 -// -#ifndef hifi_gpu_Texture_h -#define hifi_gpu_Texture_h - -#include "Resource.h" - -#include //min max and more - -#include - -namespace gpu { - -// THe spherical harmonics is a nice tool for cubemap, so if required, the irradiance SH can be automatically generated -// with the cube texture -class Texture; -class SphericalHarmonics { -public: - glm::vec3 L00 ; float spare0; - glm::vec3 L1m1 ; float spare1; - glm::vec3 L10 ; float spare2; - glm::vec3 L11 ; float spare3; - glm::vec3 L2m2 ; float spare4; - glm::vec3 L2m1 ; float spare5; - glm::vec3 L20 ; float spare6; - glm::vec3 L21 ; float spare7; - glm::vec3 L22 ; float spare8; - - static const int NUM_COEFFICIENTS = 9; - - enum Preset { - OLD_TOWN_SQUARE = 0, - GRACE_CATHEDRAL, - EUCALYPTUS_GROVE, - ST_PETERS_BASILICA, - UFFIZI_GALLERY, - GALILEOS_TOMB, - VINE_STREET_KITCHEN, - BREEZEWAY, - CAMPUS_SUNSET, - FUNSTON_BEACH_SUNSET, - - NUM_PRESET, - }; - - void assignPreset(int p); - - void evalFromTexture(const Texture& texture); -}; -typedef std::shared_ptr< SphericalHarmonics > SHPointer; - -class Sampler { -public: - - enum Filter { - FILTER_MIN_MAG_POINT, // top mip only - FILTER_MIN_POINT_MAG_LINEAR, // top mip only - FILTER_MIN_LINEAR_MAG_POINT, // top mip only - FILTER_MIN_MAG_LINEAR, // top mip only - - FILTER_MIN_MAG_MIP_POINT, - FILTER_MIN_MAG_POINT_MIP_LINEAR, - FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, - FILTER_MIN_POINT_MAG_MIP_LINEAR, - FILTER_MIN_LINEAR_MAG_MIP_POINT, - FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, - FILTER_MIN_MAG_LINEAR_MIP_POINT, - FILTER_MIN_MAG_MIP_LINEAR, - FILTER_ANISOTROPIC, - - NUM_FILTERS, - }; - - enum WrapMode { - WRAP_REPEAT = 0, - WRAP_MIRROR, - WRAP_CLAMP, - WRAP_BORDER, - WRAP_MIRROR_ONCE, - - NUM_WRAP_MODES - }; - - static const uint8 MAX_MIP_LEVEL = 0xFF; - - class Desc { - public: - glm::vec4 _borderColor{ 1.0f }; - uint32 _maxAnisotropy = 16; - - uint8 _filter = FILTER_MIN_MAG_POINT; - uint8 _comparisonFunc = ALWAYS; - - uint8 _wrapModeU = WRAP_REPEAT; - uint8 _wrapModeV = WRAP_REPEAT; - uint8 _wrapModeW = WRAP_REPEAT; - - uint8 _mipOffset = 0; - uint8 _minMip = 0; - uint8 _maxMip = MAX_MIP_LEVEL; - - Desc() {} - Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {} - }; - - Sampler() {} - Sampler(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _desc(filter, wrap) {} - Sampler(const Desc& desc) : _desc(desc) {} - ~Sampler() {} - - const glm::vec4& getBorderColor() const { return _desc._borderColor; } - - uint32 getMaxAnisotropy() const { return _desc._maxAnisotropy; } - - WrapMode getWrapModeU() const { return WrapMode(_desc._wrapModeU); } - WrapMode getWrapModeV() const { return WrapMode(_desc._wrapModeV); } - WrapMode getWrapModeW() const { return WrapMode(_desc._wrapModeW); } - - Filter getFilter() const { return Filter(_desc._filter); } - ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); } - bool doComparison() const { return getComparisonFunction() != ALWAYS; } - - uint8 getMipOffset() const { return _desc._mipOffset; } - uint8 getMinMip() const { return _desc._minMip; } - uint8 getMaxMip() const { return _desc._maxMip; } - -protected: - Desc _desc; -}; - -class Texture : public Resource { -public: - - class Pixels { - public: - Pixels() {} - Pixels(const Pixels& pixels) = default; - Pixels(const Element& format, Size size, const Byte* bytes); - ~Pixels(); - - Sysmem _sysmem; - Element _format; - bool _isGPULoaded; - }; - typedef std::shared_ptr< Pixels > PixelsPointer; - - enum Type { - TEX_1D = 0, - TEX_2D, - TEX_3D, - TEX_CUBE, - - 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_Z, - CUBE_FACE_FRONT_NEG_Z, - - NUM_CUBE_FACES, // Not a valid vace index - }; - - 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()); - static Texture* createCube(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); - - static Texture* createFromStorage(Storage* storage); - - Texture(); - Texture(const Texture& buf); // deep copy of the sysmem texture - Texture& operator=(const Texture& buf); // deep copy of the sysmem texture - ~Texture(); - - Stamp getStamp() const { return _stamp; } - Stamp getDataStamp() const { return _storage->getStamp(); } - - // The size in bytes of data stored in the texture - Size getSize() const { return _size; } - - // Resize, unless auto mips mode would destroy all the sub mips - Size resize1D(uint16 width, uint16 numSamples); - Size resize2D(uint16 width, uint16 height, uint16 numSamples); - Size resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples); - Size resizeCube(uint16 width, uint16 numSamples); - - // Reformat, unless auto mips mode would destroy all the sub mips - Size reformat(const Element& texelFormat); - - // Size and format - Type getType() const { return _type; } - - bool isColorRenderTarget() const; - bool isDepthStencilRenderTarget() const; - - const Element& getTexelFormat() const { return _texelFormat; } - bool hasBorder() const { return false; } - - uint16 getWidth() const { return _width; } - uint16 getHeight() const { return _height; } - uint16 getDepth() const { return _depth; } - - uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); } - - // 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 be packed 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); - - // Mips size evaluation - - // The number mips that a dimension could haves - // = 1 + log2(size) - static uint16 evalDimNumMips(uint16 size); - - // The number mips that the texture could have if all existed - // = 1 + log2(max(width, height, depth)) - uint16 evalNumMips() const; - - // Eval the size that the mips level SHOULD have - // not the one stored in the Texture - 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); } - - // 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 { - uint32 size = 0; - uint16 minMipLevel = 0; - uint16 maxMipLevel = maxMip(); - for (uint16 l = minMipLevel; l <= maxMipLevel; l++) { - size += evalMipSize(l); - } - return size * getNumSlices(); - } - - // max mip is in the range [ 1 if no sub mips, log2(max(width, height, depth))] - // if autoGenerateMip is on => will provide the maxMIp level specified - // else provide the deepest mip level provided through assignMip - uint16 maxMip() const; - - // Generate the mips automatically - // But the sysmem version is not available - // Only works for the standard formats - // Specify the maximum Mip level available - // 0 is the default one - // 1 is the first level - // ... - // nbMips - 1 is the last mip level - // - // If -1 then all the mips are generated - // - // Return the totalnumber of mips that will be available - uint16 autoGenerateMips(uint16 maxMip); - bool isAutogenerateMips() const { return _autoGenerateMips; } - - // Managing Storage and mips - - // Manually allocate the mips down until the specified maxMip - // this is just allocating the sysmem version of it - // in case autoGen is on, this doesn't allocate - // 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 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; - uint16 getStoredMipHeight(uint16 level) const; - uint16 getStoredMipDepth(uint16 level) const; - uint32 getStoredMipNumTexels(uint16 level) const; - uint32 getStoredMipSize(uint16 level) const; - - bool isDefined() const { return _defined; } - - // For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them availalbe with the texture - bool generateIrradiance(); - const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; } - bool isIrradianceValid() const { return _isIrradianceValid; } - - // Own sampler - void setSampler(const Sampler& sampler); - 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; - - Stamp _stamp = 0; - - Sampler _sampler; - Stamp _samplerStamp; - - uint32 _size = 0; - Element _texelFormat; - - uint16 _width = 1; - uint16 _height = 1; - uint16 _depth = 1; - - uint16 _numSamples = 1; - uint16 _numSlices = 1; - - uint16 _maxMip = 0; - - Type _type = TEX_1D; - - SHPointer _irradiance; - bool _autoGenerateMips = false; - bool _isIrradianceValid = 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); - - Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); - - // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = NULL; - void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } - GPUObject* getGPUObject() const { return _gpuObject; } - - friend class Backend; -}; - -typedef std::shared_ptr TexturePointer; -typedef std::vector< TexturePointer > Textures; - - - // TODO: For now TextureView works with Buffer as a place holder for the Texture. - // The overall logic should be about the same except that the Texture will be a real GL Texture under the hood -class TextureView { -public: - typedef Resource::Size Size; - - TexturePointer _texture = TexturePointer(NULL); - uint16 _subresource = 0; - Element _element = Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); - - TextureView() {}; - - TextureView(const Element& element) : - _element(element) - {}; - - // create the TextureView and own the Texture - TextureView(Texture* newTexture, const Element& element) : - _texture(newTexture), - _subresource(0), - _element(element) - {}; - TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) : - _texture(texture), - _subresource(subresource), - _element(element) - {}; - - TextureView(const TexturePointer& texture, uint16 subresource) : - _texture(texture), - _subresource(subresource) - {}; - - ~TextureView() {} - TextureView(const TextureView& view) = default; - TextureView& operator=(const TextureView& view) = default; - - explicit operator bool() const { return bool(_texture); } - bool operator !() const { return (!_texture); } - - bool isValid() const { return bool(_texture); } -}; -typedef std::vector TextureViews; - +// +// Texture.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/16/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 +// +#ifndef hifi_gpu_Texture_h +#define hifi_gpu_Texture_h + +#include "Resource.h" + +#include //min max and more + +#include + +namespace gpu { + +// THe spherical harmonics is a nice tool for cubemap, so if required, the irradiance SH can be automatically generated +// with the cube texture +class Texture; +class SphericalHarmonics { +public: + glm::vec3 L00 ; float spare0; + glm::vec3 L1m1 ; float spare1; + glm::vec3 L10 ; float spare2; + glm::vec3 L11 ; float spare3; + glm::vec3 L2m2 ; float spare4; + glm::vec3 L2m1 ; float spare5; + glm::vec3 L20 ; float spare6; + glm::vec3 L21 ; float spare7; + glm::vec3 L22 ; float spare8; + + static const int NUM_COEFFICIENTS = 9; + + enum Preset { + OLD_TOWN_SQUARE = 0, + GRACE_CATHEDRAL, + EUCALYPTUS_GROVE, + ST_PETERS_BASILICA, + UFFIZI_GALLERY, + GALILEOS_TOMB, + VINE_STREET_KITCHEN, + BREEZEWAY, + CAMPUS_SUNSET, + FUNSTON_BEACH_SUNSET, + + NUM_PRESET, + }; + + void assignPreset(int p); + + void evalFromTexture(const Texture& texture); +}; +typedef std::shared_ptr< SphericalHarmonics > SHPointer; + +class Sampler { +public: + + enum Filter { + FILTER_MIN_MAG_POINT, // top mip only + FILTER_MIN_POINT_MAG_LINEAR, // top mip only + FILTER_MIN_LINEAR_MAG_POINT, // top mip only + FILTER_MIN_MAG_LINEAR, // top mip only + + FILTER_MIN_MAG_MIP_POINT, + FILTER_MIN_MAG_POINT_MIP_LINEAR, + FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, + FILTER_MIN_POINT_MAG_MIP_LINEAR, + FILTER_MIN_LINEAR_MAG_MIP_POINT, + FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, + FILTER_MIN_MAG_LINEAR_MIP_POINT, + FILTER_MIN_MAG_MIP_LINEAR, + FILTER_ANISOTROPIC, + + NUM_FILTERS, + }; + + enum WrapMode { + WRAP_REPEAT = 0, + WRAP_MIRROR, + WRAP_CLAMP, + WRAP_BORDER, + WRAP_MIRROR_ONCE, + + NUM_WRAP_MODES + }; + + static const uint8 MAX_MIP_LEVEL = 0xFF; + + class Desc { + public: + glm::vec4 _borderColor{ 1.0f }; + uint32 _maxAnisotropy = 16; + + uint8 _filter = FILTER_MIN_MAG_POINT; + uint8 _comparisonFunc = ALWAYS; + + uint8 _wrapModeU = WRAP_REPEAT; + uint8 _wrapModeV = WRAP_REPEAT; + uint8 _wrapModeW = WRAP_REPEAT; + + uint8 _mipOffset = 0; + uint8 _minMip = 0; + uint8 _maxMip = MAX_MIP_LEVEL; + + Desc() {} + Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {} + }; + + Sampler() {} + Sampler(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _desc(filter, wrap) {} + Sampler(const Desc& desc) : _desc(desc) {} + ~Sampler() {} + + const glm::vec4& getBorderColor() const { return _desc._borderColor; } + + uint32 getMaxAnisotropy() const { return _desc._maxAnisotropy; } + + WrapMode getWrapModeU() const { return WrapMode(_desc._wrapModeU); } + WrapMode getWrapModeV() const { return WrapMode(_desc._wrapModeV); } + WrapMode getWrapModeW() const { return WrapMode(_desc._wrapModeW); } + + Filter getFilter() const { return Filter(_desc._filter); } + ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); } + bool doComparison() const { return getComparisonFunction() != ALWAYS; } + + uint8 getMipOffset() const { return _desc._mipOffset; } + uint8 getMinMip() const { return _desc._minMip; } + uint8 getMaxMip() const { return _desc._maxMip; } + +protected: + Desc _desc; +}; + +class Texture : public Resource { +public: + + class Pixels { + public: + Pixels() {} + Pixels(const Pixels& pixels) = default; + Pixels(const Element& format, Size size, const Byte* bytes); + ~Pixels(); + + Sysmem _sysmem; + Element _format; + bool _isGPULoaded; + }; + typedef std::shared_ptr< Pixels > PixelsPointer; + + enum Type { + TEX_1D = 0, + TEX_2D, + TEX_3D, + TEX_CUBE, + + 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_Z, + CUBE_FACE_FRONT_NEG_Z, + + NUM_CUBE_FACES, // Not a valid vace index + }; + + 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()); + static Texture* createCube(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); + + static Texture* createFromStorage(Storage* storage); + + Texture(); + Texture(const Texture& buf); // deep copy of the sysmem texture + Texture& operator=(const Texture& buf); // deep copy of the sysmem texture + ~Texture(); + + Stamp getStamp() const { return _stamp; } + Stamp getDataStamp() const { return _storage->getStamp(); } + + // The size in bytes of data stored in the texture + Size getSize() const { return _size; } + + // Resize, unless auto mips mode would destroy all the sub mips + Size resize1D(uint16 width, uint16 numSamples); + Size resize2D(uint16 width, uint16 height, uint16 numSamples); + Size resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples); + Size resizeCube(uint16 width, uint16 numSamples); + + // Reformat, unless auto mips mode would destroy all the sub mips + Size reformat(const Element& texelFormat); + + // Size and format + Type getType() const { return _type; } + + bool isColorRenderTarget() const; + bool isDepthStencilRenderTarget() const; + + const Element& getTexelFormat() const { return _texelFormat; } + bool hasBorder() const { return false; } + + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + uint16 getDepth() const { return _depth; } + + uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); } + + // 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 be packed 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); + + // Mips size evaluation + + // The number mips that a dimension could haves + // = 1 + log2(size) + static uint16 evalDimNumMips(uint16 size); + + // The number mips that the texture could have if all existed + // = 1 + log2(max(width, height, depth)) + uint16 evalNumMips() const; + + // Eval the size that the mips level SHOULD have + // not the one stored in the Texture + 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); } + + // 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 { + uint32 size = 0; + uint16 minMipLevel = 0; + uint16 maxMipLevel = maxMip(); + for (uint16 l = minMipLevel; l <= maxMipLevel; l++) { + size += evalMipSize(l); + } + return size * getNumSlices(); + } + + // max mip is in the range [ 1 if no sub mips, log2(max(width, height, depth))] + // if autoGenerateMip is on => will provide the maxMIp level specified + // else provide the deepest mip level provided through assignMip + uint16 maxMip() const; + + // Generate the mips automatically + // But the sysmem version is not available + // Only works for the standard formats + // Specify the maximum Mip level available + // 0 is the default one + // 1 is the first level + // ... + // nbMips - 1 is the last mip level + // + // If -1 then all the mips are generated + // + // Return the totalnumber of mips that will be available + uint16 autoGenerateMips(uint16 maxMip); + bool isAutogenerateMips() const { return _autoGenerateMips; } + + // Managing Storage and mips + + // Manually allocate the mips down until the specified maxMip + // this is just allocating the sysmem version of it + // in case autoGen is on, this doesn't allocate + // 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 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; + uint16 getStoredMipHeight(uint16 level) const; + uint16 getStoredMipDepth(uint16 level) const; + uint32 getStoredMipNumTexels(uint16 level) const; + uint32 getStoredMipSize(uint16 level) const; + + bool isDefined() const { return _defined; } + + // For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them availalbe with the texture + bool generateIrradiance(); + const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; } + bool isIrradianceValid() const { return _isIrradianceValid; } + + // Own sampler + void setSampler(const Sampler& sampler); + 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; + + Stamp _stamp = 0; + + Sampler _sampler; + Stamp _samplerStamp; + + uint32 _size = 0; + Element _texelFormat; + + uint16 _width = 1; + uint16 _height = 1; + uint16 _depth = 1; + + uint16 _numSamples = 1; + uint16 _numSlices = 1; + + uint16 _maxMip = 0; + + Type _type = TEX_1D; + + SHPointer _irradiance; + bool _autoGenerateMips = false; + bool _isIrradianceValid = 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); + + Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); + + // This shouldn't be used by anything else than the Backend class with the proper casting. + mutable GPUObject* _gpuObject = NULL; + void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } + GPUObject* getGPUObject() const { return _gpuObject; } + + friend class Backend; +}; + +typedef std::shared_ptr TexturePointer; +typedef std::vector< TexturePointer > Textures; + + + // TODO: For now TextureView works with Buffer as a place holder for the Texture. + // The overall logic should be about the same except that the Texture will be a real GL Texture under the hood +class TextureView { +public: + typedef Resource::Size Size; + + TexturePointer _texture = TexturePointer(NULL); + uint16 _subresource = 0; + Element _element = Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); + + TextureView() {}; + + TextureView(const Element& element) : + _element(element) + {}; + + // create the TextureView and own the Texture + TextureView(Texture* newTexture, const Element& element) : + _texture(newTexture), + _subresource(0), + _element(element) + {}; + TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) : + _texture(texture), + _subresource(subresource), + _element(element) + {}; + + TextureView(const TexturePointer& texture, uint16 subresource) : + _texture(texture), + _subresource(subresource) + {}; + + ~TextureView() {} + TextureView(const TextureView& view) = default; + TextureView& operator=(const TextureView& view) = default; + + explicit operator bool() const { return bool(_texture); } + bool operator !() const { return (!_texture); } + + bool isValid() const { return bool(_texture); } +}; +typedef std::vector TextureViews; + // TextureSource is the bridge between a URL or a a way to produce an image and the final gpu::Texture that will be used to render it. // It provides the mechanism to create a texture using a customizable TextureLoader class TextureSource { @@ -463,9 +463,9 @@ protected: gpu::TexturePointer _gpuTexture; QUrl _imageUrl; }; -typedef std::shared_ptr< TextureSource > TextureSourcePointer; - -}; - - -#endif +typedef std::shared_ptr< TextureSource > TextureSourcePointer; + +}; + + +#endif diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index b766cc88d4..e67fbf7f66 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -1,143 +1,143 @@ - -<@if not GPU_TRANSFORM_STATE_SLH@> -<@def GPU_TRANSFORM_STATE_SLH@> - -<@func declareStandardTransform()@> -struct TransformObject { - mat4 _model; - mat4 _modelInverse; -}; - -struct TransformCamera { - mat4 _view; - mat4 _viewInverse; - mat4 _projectionViewUntranslated; - mat4 _projection; - mat4 _projectionInverse; - vec4 _viewport; -}; - -layout(std140) uniform transformObjectBuffer { - TransformObject _object; -}; -TransformObject getTransformObject() { - return _object; -} - -layout(std140) uniform transformCameraBuffer { - TransformCamera _camera; -}; -TransformCamera getTransformCamera() { - return _camera; -} -<@endfunc@> - -<@func transformCameraViewport(cameraTransform, viewport)@> - <$viewport$> = <$cameraTransform$>._viewport; -<@endfunc@> - -<@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> - - { // transformModelToClipPos - vec4 _eyepos = (<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; - } -<@endfunc@> - -<@func transformInstancedModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> - - { // transformModelToClipPos - vec4 _eyepos = (inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; - } -<@endfunc@> - -<@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> - - { // transformModelToClipPos - vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>); - <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - vec4 _eyepos =(<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; - // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); - } -<@endfunc@> - -<@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> - - { // transformModelToClipPos - vec4 _worldpos = (inInstanceTransform * <$modelPos$>); - <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - vec4 _eyepos =(inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; - // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); - } -<@endfunc@> - - -<@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> - { // transformModelToWorldPos - <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); - } -<@endfunc@> - -<@func transformInstancedModelToWorldPos(objectTransform, modelPos, worldPos)@> - { // transformModelToWorldPos - <$worldPos$> = (inInstanceTransform * <$modelPos$>); - } -<@endfunc@> - -<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> - { // transformModelToEyeDir - vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x); - vec3 mr1 = vec3(<$objectTransform$>._modelInverse[0].y, <$objectTransform$>._modelInverse[1].y, <$objectTransform$>._modelInverse[2].y); - vec3 mr2 = vec3(<$objectTransform$>._modelInverse[0].z, <$objectTransform$>._modelInverse[1].z, <$objectTransform$>._modelInverse[2].z); - - vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2)); - vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2)); - vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2)); - - <$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>)); - } -<@endfunc@> - -<@func transformInstancedModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> - { // transformModelToEyeDir - mat4 modelInverse = inverse(inInstanceTransform); - vec3 mr0 = vec3(modelInverse[0].x, modelInverse[1].x, modelInverse[2].x); - vec3 mr1 = vec3(modelInverse[0].y, modelInverse[1].y, modelInverse[2].y); - vec3 mr2 = vec3(modelInverse[0].z, modelInverse[1].z, modelInverse[2].z); - - vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2)); - vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2)); - vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2)); - - <$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>)); - } -<@endfunc@> - -<@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@> - { // transformEyeToWorldDir - <$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); - } -<@endfunc@> - -<@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> - { // transformClipToEyeDir - <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); - } -<@endfunc@> - -<@endif@> + +<@if not GPU_TRANSFORM_STATE_SLH@> +<@def GPU_TRANSFORM_STATE_SLH@> + +<@func declareStandardTransform()@> +struct TransformObject { + mat4 _model; + mat4 _modelInverse; +}; + +struct TransformCamera { + mat4 _view; + mat4 _viewInverse; + mat4 _projectionViewUntranslated; + mat4 _projection; + mat4 _projectionInverse; + vec4 _viewport; +}; + +layout(std140) uniform transformObjectBuffer { + TransformObject _object; +}; +TransformObject getTransformObject() { + return _object; +} + +layout(std140) uniform transformCameraBuffer { + TransformCamera _camera; +}; +TransformCamera getTransformCamera() { + return _camera; +} +<@endfunc@> + +<@func transformCameraViewport(cameraTransform, viewport)@> + <$viewport$> = <$cameraTransform$>._viewport; +<@endfunc@> + +<@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> + + { // transformModelToClipPos + vec4 _eyepos = (<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); + <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; + } +<@endfunc@> + +<@func transformInstancedModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> + + { // transformModelToClipPos + vec4 _eyepos = (inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); + <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; + } +<@endfunc@> + +<@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> + + { // transformModelToClipPos + vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>); + <$eyePos$> = (<$cameraTransform$>._view * _worldpos); + vec4 _eyepos =(<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); + <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; + // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); + } +<@endfunc@> + +<@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> + + { // transformModelToClipPos + vec4 _worldpos = (inInstanceTransform * <$modelPos$>); + <$eyePos$> = (<$cameraTransform$>._view * _worldpos); + vec4 _eyepos =(inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); + <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; + // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); + } +<@endfunc@> + + +<@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> + { // transformModelToWorldPos + <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); + } +<@endfunc@> + +<@func transformInstancedModelToWorldPos(objectTransform, modelPos, worldPos)@> + { // transformModelToWorldPos + <$worldPos$> = (inInstanceTransform * <$modelPos$>); + } +<@endfunc@> + +<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> + { // transformModelToEyeDir + vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x); + vec3 mr1 = vec3(<$objectTransform$>._modelInverse[0].y, <$objectTransform$>._modelInverse[1].y, <$objectTransform$>._modelInverse[2].y); + vec3 mr2 = vec3(<$objectTransform$>._modelInverse[0].z, <$objectTransform$>._modelInverse[1].z, <$objectTransform$>._modelInverse[2].z); + + vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2)); + vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2)); + vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2)); + + <$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>)); + } +<@endfunc@> + +<@func transformInstancedModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> + { // transformModelToEyeDir + mat4 modelInverse = inverse(inInstanceTransform); + vec3 mr0 = vec3(modelInverse[0].x, modelInverse[1].x, modelInverse[2].x); + vec3 mr1 = vec3(modelInverse[0].y, modelInverse[1].y, modelInverse[2].y); + vec3 mr2 = vec3(modelInverse[0].z, modelInverse[1].z, modelInverse[2].z); + + vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2)); + vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2)); + vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2)); + + <$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>)); + } +<@endfunc@> + +<@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@> + { // transformEyeToWorldDir + <$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); + } +<@endfunc@> + +<@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> + { // transformClipToEyeDir + <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); + } +<@endfunc@> + +<@endif@> diff --git a/libraries/model/src/model/Atmosphere.slh b/libraries/model/src/model/Atmosphere.slh index 0af5fa27f3..b8f390de0a 100755 --- a/libraries/model/src/model/Atmosphere.slh +++ b/libraries/model/src/model/Atmosphere.slh @@ -1,245 +1,245 @@ - -<@if not MODEL_ATMOSPHERE_SLH@> -<@def MODEL_ATMOSPHERE_SLH@> - - - -struct Atmosphere { - vec4 _invWaveLength; - vec4 _radiuses; - vec4 _scales; - vec4 _scatterings; - vec4 _control; -}; - -const int numSamples = 2; - -vec3 getAtmosphereInvWaveLength(Atmosphere a) { return a._invWaveLength.xyz; } // 1 / pow(wavelength, 4) for the red, green, and blue channels - -float getAtmosphereInnerRadius(Atmosphere a) { return a._radiuses.x; } // The inner (planetary) radius -float getAtmosphereOuterRadius(Atmosphere a) { return a._radiuses.y; } // The outer (atmosphere) radius - -float getAtmosphereScale(Atmosphere a) { return a._scales.x; } // 1 / (outerRadius - innerRadius) -float getAtmosphereScaleDepth(Atmosphere a) { return a._scales.y; } // The scale depth (i.e. the altitude at which the atmosphere's average density is found) -float getAtmosphereScaleOverScaleDepth(Atmosphere a) { return a._scales.z; } // scale / scaleDepth - -vec4 getAtmosphereScattering(Atmosphere a) { return a._scatterings; } // The full Mie and Rayleigh scattering coefficients -float getAtmosphereKrESun(Atmosphere a) { return a._scatterings.x; } // Kr * ESun -float getAtmosphereKmESun(Atmosphere a) { return a._scatterings.y; } // Km * ESun -float getAtmosphereKr4PI(Atmosphere a) { return a._scatterings.z; } // Kr * 4 * PI -float getAtmosphereKm4PI(Atmosphere a) { return a._scatterings.w; } // Km * 4 * PI - -float getAtmosphereNumSamples(Atmosphere a) { return a._control.x; } // numSamples -vec2 getAtmosphereGAndG2(Atmosphere a) { return a._control.yz; } // g and g2 - -float atmosphereScale(float scaleDepth, float fCos) -{ - float x = 1.0 - fCos; - return scaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); -} - -vec4 evalAtmosphereContribution(Atmosphere atmospheric, vec3 position, vec3 cameraPos, vec3 lightPos) { - float fInnerRadius = getAtmosphereInnerRadius(atmospheric); - float fSamples = getAtmosphereNumSamples(atmospheric); - - vec3 v3InvWavelength = getAtmosphereInvWaveLength(atmospheric); - vec4 scatteringCoefs = getAtmosphereScattering(atmospheric); - float fKrESun = scatteringCoefs.x; - float fKmESun = scatteringCoefs.y; - float fKr4PI = scatteringCoefs.z; - float fKm4PI = scatteringCoefs.w; - - vec2 gAndg2 = getAtmosphereGAndG2(atmospheric); - float g = gAndg2.x; - float g2 = gAndg2.y; - - float fScale = getAtmosphereScale(atmospheric); - float fScaleDepth = getAtmosphereScaleDepth(atmospheric); - float fScaleOverScaleDepth = getAtmosphereScaleOverScaleDepth(atmospheric); - - // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) - vec3 v3Pos = position; - vec3 v3Ray = v3Pos - cameraPos; - float fFar = length(v3Ray); - v3Ray /= fFar; - - // Calculate the ray's starting position, then calculate its scattering offset - vec3 v3Start = cameraPos; - float fHeight = length(v3Start); - float fDepthStart = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); - float fStartAngle = dot(v3Ray, v3Start) / fHeight; - float fStartOffset = fDepthStart * atmosphereScale(fScaleDepth, fStartAngle); - - // Initialize the scattering loop variables - //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); - float fSampleLength = fFar / fSamples; - float fScaledLength = fSampleLength * fScale; - - vec3 v3SampleRay = v3Ray * fSampleLength; - vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; - - // Now loop through the sample rays - vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); - // int nSamples = numSamples; - int nSamples = int(fSamples); - for(int i=0; i -uniform atmosphereBuffer { - Atmosphere _atmosphere; -}; -Atmosphere getAtmosphere() { - return _atmosphere; -} -<@else@> -uniform vec4 atmosphereBuffer[9]; -Atmosphere getAtmosphere() { - Atmosphere atmosphere; - atmosphere._invWaveLength = atmosphereBuffer[0]; - atmosphere._radiuses = atmosphereBuffer[1]; - atmosphere._scales = atmosphereBuffer[2]; - atmosphere._scatterings = atmosphereBuffer[3]; - atmosphere._control = atmosphereBuffer[4]; - - return atmosphere; -} -<@endif@> - - - -<@endif@> + +<@if not MODEL_ATMOSPHERE_SLH@> +<@def MODEL_ATMOSPHERE_SLH@> + + + +struct Atmosphere { + vec4 _invWaveLength; + vec4 _radiuses; + vec4 _scales; + vec4 _scatterings; + vec4 _control; +}; + +const int numSamples = 2; + +vec3 getAtmosphereInvWaveLength(Atmosphere a) { return a._invWaveLength.xyz; } // 1 / pow(wavelength, 4) for the red, green, and blue channels + +float getAtmosphereInnerRadius(Atmosphere a) { return a._radiuses.x; } // The inner (planetary) radius +float getAtmosphereOuterRadius(Atmosphere a) { return a._radiuses.y; } // The outer (atmosphere) radius + +float getAtmosphereScale(Atmosphere a) { return a._scales.x; } // 1 / (outerRadius - innerRadius) +float getAtmosphereScaleDepth(Atmosphere a) { return a._scales.y; } // The scale depth (i.e. the altitude at which the atmosphere's average density is found) +float getAtmosphereScaleOverScaleDepth(Atmosphere a) { return a._scales.z; } // scale / scaleDepth + +vec4 getAtmosphereScattering(Atmosphere a) { return a._scatterings; } // The full Mie and Rayleigh scattering coefficients +float getAtmosphereKrESun(Atmosphere a) { return a._scatterings.x; } // Kr * ESun +float getAtmosphereKmESun(Atmosphere a) { return a._scatterings.y; } // Km * ESun +float getAtmosphereKr4PI(Atmosphere a) { return a._scatterings.z; } // Kr * 4 * PI +float getAtmosphereKm4PI(Atmosphere a) { return a._scatterings.w; } // Km * 4 * PI + +float getAtmosphereNumSamples(Atmosphere a) { return a._control.x; } // numSamples +vec2 getAtmosphereGAndG2(Atmosphere a) { return a._control.yz; } // g and g2 + +float atmosphereScale(float scaleDepth, float fCos) +{ + float x = 1.0 - fCos; + return scaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); +} + +vec4 evalAtmosphereContribution(Atmosphere atmospheric, vec3 position, vec3 cameraPos, vec3 lightPos) { + float fInnerRadius = getAtmosphereInnerRadius(atmospheric); + float fSamples = getAtmosphereNumSamples(atmospheric); + + vec3 v3InvWavelength = getAtmosphereInvWaveLength(atmospheric); + vec4 scatteringCoefs = getAtmosphereScattering(atmospheric); + float fKrESun = scatteringCoefs.x; + float fKmESun = scatteringCoefs.y; + float fKr4PI = scatteringCoefs.z; + float fKm4PI = scatteringCoefs.w; + + vec2 gAndg2 = getAtmosphereGAndG2(atmospheric); + float g = gAndg2.x; + float g2 = gAndg2.y; + + float fScale = getAtmosphereScale(atmospheric); + float fScaleDepth = getAtmosphereScaleDepth(atmospheric); + float fScaleOverScaleDepth = getAtmosphereScaleOverScaleDepth(atmospheric); + + // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) + vec3 v3Pos = position; + vec3 v3Ray = v3Pos - cameraPos; + float fFar = length(v3Ray); + v3Ray /= fFar; + + // Calculate the ray's starting position, then calculate its scattering offset + vec3 v3Start = cameraPos; + float fHeight = length(v3Start); + float fDepthStart = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); + float fStartAngle = dot(v3Ray, v3Start) / fHeight; + float fStartOffset = fDepthStart * atmosphereScale(fScaleDepth, fStartAngle); + + // Initialize the scattering loop variables + //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); + float fSampleLength = fFar / fSamples; + float fScaledLength = fSampleLength * fScale; + + vec3 v3SampleRay = v3Ray * fSampleLength; + vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; + + // Now loop through the sample rays + vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); + // int nSamples = numSamples; + int nSamples = int(fSamples); + for(int i=0; i +uniform atmosphereBuffer { + Atmosphere _atmosphere; +}; +Atmosphere getAtmosphere() { + return _atmosphere; +} +<@else@> +uniform vec4 atmosphereBuffer[9]; +Atmosphere getAtmosphere() { + Atmosphere atmosphere; + atmosphere._invWaveLength = atmosphereBuffer[0]; + atmosphere._radiuses = atmosphereBuffer[1]; + atmosphere._scales = atmosphereBuffer[2]; + atmosphere._scatterings = atmosphereBuffer[3]; + atmosphere._control = atmosphereBuffer[4]; + + return atmosphere; +} +<@endif@> + + + +<@endif@> diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 3fbaba75bf..efc02e3de4 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -77,13 +77,13 @@ public: void setMaximumRadius(float radius); float getMaximumRadius() const { return getSchema()._attenuation.w; } - // Spot properties - bool isSpot() const { return getType() == SPOT; } - void setSpotAngle(float angle); - float getSpotAngle() const { return getSchema()._spot.z; } - glm::vec2 getSpotAngleCosSin() const { return glm::vec2(getSchema()._spot.x, getSchema()._spot.y); } - void setSpotExponent(float exponent); - float getSpotExponent() const { return getSchema()._spot.w; } + // Spot properties + bool isSpot() const { return getType() == SPOT; } + void setSpotAngle(float angle); + float getSpotAngle() const { return getSchema()._spot.z; } + glm::vec2 getSpotAngleCosSin() const { return glm::vec2(getSchema()._spot.x, getSchema()._spot.y); } + void setSpotExponent(float exponent); + float getSpotExponent() const { return getSchema()._spot.w; } // For editing purpose, show the light volume contour. // Set to non 0 to show it, the value is used as the intensity of the contour color @@ -100,20 +100,20 @@ public: void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) { _ambientSphere.assignPreset(preset); } // Schema to access the attribute values of the light - class Schema { - public: - Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f}; - Vec3 _direction{0.0f, 0.0f, -1.0f}; - float _ambientIntensity{0.0f}; - Color _color{1.0f}; - float _intensity{1.0f}; - Vec4 _attenuation{1.0f}; - Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f}; - Vec4 _shadow{0.0f}; - - Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f}; - - Schema() {} + class Schema { + public: + Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f}; + Vec3 _direction{0.0f, 0.0f, -1.0f}; + float _ambientIntensity{0.0f}; + Color _color{1.0f}; + float _intensity{1.0f}; + Vec4 _attenuation{1.0f}; + Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f}; + Vec4 _shadow{0.0f}; + + Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f}; + + Schema() {} }; const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 1aaf0e8327..708e092a0a 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -1,93 +1,93 @@ - -<@if not MODEL_LIGHT_SLH@> -<@def MODEL_LIGHT_SLH@> - -struct Light { - vec4 _position; - vec4 _direction; - vec4 _color; - vec4 _attenuation; - vec4 _spot; - - vec4 _shadow; - vec4 _control; -}; - -vec3 getLightPosition(Light l) { return l._position.xyz; } -vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis - -vec3 getLightColor(Light l) { return l._color.rgb; } -float getLightIntensity(Light l) { return l._color.w; } -float getLightAmbientIntensity(Light l) { return l._direction.w; } - -float evalLightAttenuation(Light l, float r) { - float d = max(r - l._attenuation.x, 0.0); - float denom = d * l._attenuation.y + 1.0; - float attenuation = 1.0 / (denom * denom); - return max((attenuation - l._attenuation.z)/(1.0 - l._attenuation.z), 0.0); - // return clamp(1.0/(l._attenuation.x + l._attenuation.y * r + l._attenuation.z * r * r), 0.0, 1.0); -} - -float getLightSpotAngleCos(Light l) { - return l._spot.x; -} - -vec2 getLightSpotOutsideNormal2(Light l) { - return vec2(-l._spot.y, l._spot.x); -} - -float evalLightSpotAttenuation(Light l, float cosA) { - return pow(cosA, l._spot.w); -} - -float getLightSquareRadius(Light l) { - return l._attenuation.w * l._attenuation.w; -} - -float getLightRadius(Light l) { - return l._attenuation.w; -} - -float getLightAttenuationCutoff(Light l) { - return l._attenuation.z; -} - -float getLightShowContour(Light l) { - return l._control.w; -} - -<@if GPU_FEATURE_PROFILE == GPU_CORE @> -uniform lightBuffer { - Light light; -}; -Light getLight() { - return light; -} -<@else@> -uniform vec4 lightBuffer[7]; -Light getLight() { - Light light; - light._position = lightBuffer[0]; - light._direction = lightBuffer[1]; - light._color = lightBuffer[2]; - light._attenuation = lightBuffer[3]; - light._spot = lightBuffer[4]; - light._shadow = lightBuffer[5]; - light._control = lightBuffer[6]; - - return light; -} -<@endif@> - - - -<@endif@> + +<@if not MODEL_LIGHT_SLH@> +<@def MODEL_LIGHT_SLH@> + +struct Light { + vec4 _position; + vec4 _direction; + vec4 _color; + vec4 _attenuation; + vec4 _spot; + + vec4 _shadow; + vec4 _control; +}; + +vec3 getLightPosition(Light l) { return l._position.xyz; } +vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis + +vec3 getLightColor(Light l) { return l._color.rgb; } +float getLightIntensity(Light l) { return l._color.w; } +float getLightAmbientIntensity(Light l) { return l._direction.w; } + +float evalLightAttenuation(Light l, float r) { + float d = max(r - l._attenuation.x, 0.0); + float denom = d * l._attenuation.y + 1.0; + float attenuation = 1.0 / (denom * denom); + return max((attenuation - l._attenuation.z)/(1.0 - l._attenuation.z), 0.0); + // return clamp(1.0/(l._attenuation.x + l._attenuation.y * r + l._attenuation.z * r * r), 0.0, 1.0); +} + +float getLightSpotAngleCos(Light l) { + return l._spot.x; +} + +vec2 getLightSpotOutsideNormal2(Light l) { + return vec2(-l._spot.y, l._spot.x); +} + +float evalLightSpotAttenuation(Light l, float cosA) { + return pow(cosA, l._spot.w); +} + +float getLightSquareRadius(Light l) { + return l._attenuation.w * l._attenuation.w; +} + +float getLightRadius(Light l) { + return l._attenuation.w; +} + +float getLightAttenuationCutoff(Light l) { + return l._attenuation.z; +} + +float getLightShowContour(Light l) { + return l._control.w; +} + +<@if GPU_FEATURE_PROFILE == GPU_CORE @> +uniform lightBuffer { + Light light; +}; +Light getLight() { + return light; +} +<@else@> +uniform vec4 lightBuffer[7]; +Light getLight() { + Light light; + light._position = lightBuffer[0]; + light._direction = lightBuffer[1]; + light._color = lightBuffer[2]; + light._attenuation = lightBuffer[3]; + light._spot = lightBuffer[4]; + light._shadow = lightBuffer[5]; + light._control = lightBuffer[6]; + + return light; +} +<@endif@> + + + +<@endif@> diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index 35aa96042c..f48bdfa8f1 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -1,66 +1,66 @@ - -<@if not MODEL_MATERIAL_SLH@> -<@def MODEL_MATERIAL_SLH@> - -struct Material { - vec4 _diffuse; - vec4 _specular; - vec4 _emissive; - vec4 _spare; -}; - -uniform materialBuffer { - Material _mat; -}; - -Material getMaterial() { - return _mat; -} - - 0.04045 - // constants: - // T = 0.04045 - // A = 1 / 1.055 = 0.94786729857 - // B = 0.055 * A = 0.05213270142 - // C = 1 / 12.92 = 0.0773993808 - // G = 2.4 - const float T = 0.04045; - const float A = 0.947867; - const float B = 0.052132; - const float C = 0.077399; - const float G = 2.4; - - if (cs > T) { - return pow((cs * A + B), G); - } else { - return cs * C; - } -} - -vec3 SRGBToLinear(vec3 srgb) { - return vec3(componentSRGBToLinear(srgb.x),componentSRGBToLinear(srgb.y),componentSRGBToLinear(srgb.z)); -} -vec3 getMaterialDiffuse(Material m) { return (gl_FragCoord.x < 800 ? SRGBToLinear(m._diffuse.rgb) : m._diffuse.rgb); } -*/!> - -float getMaterialOpacity(Material m) { return m._diffuse.a; } -vec3 getMaterialDiffuse(Material m) { return m._diffuse.rgb; } -vec3 getMaterialSpecular(Material m) { return m._specular.rgb; } -float getMaterialShininess(Material m) { return m._specular.a; } - -<@endif@> + +<@if not MODEL_MATERIAL_SLH@> +<@def MODEL_MATERIAL_SLH@> + +struct Material { + vec4 _diffuse; + vec4 _specular; + vec4 _emissive; + vec4 _spare; +}; + +uniform materialBuffer { + Material _mat; +}; + +Material getMaterial() { + return _mat; +} + + 0.04045 + // constants: + // T = 0.04045 + // A = 1 / 1.055 = 0.94786729857 + // B = 0.055 * A = 0.05213270142 + // C = 1 / 12.92 = 0.0773993808 + // G = 2.4 + const float T = 0.04045; + const float A = 0.947867; + const float B = 0.052132; + const float C = 0.077399; + const float G = 2.4; + + if (cs > T) { + return pow((cs * A + B), G); + } else { + return cs * C; + } +} + +vec3 SRGBToLinear(vec3 srgb) { + return vec3(componentSRGBToLinear(srgb.x),componentSRGBToLinear(srgb.y),componentSRGBToLinear(srgb.z)); +} +vec3 getMaterialDiffuse(Material m) { return (gl_FragCoord.x < 800 ? SRGBToLinear(m._diffuse.rgb) : m._diffuse.rgb); } +*/!> + +float getMaterialOpacity(Material m) { return m._diffuse.a; } +vec3 getMaterialDiffuse(Material m) { return m._diffuse.rgb; } +vec3 getMaterialSpecular(Material m) { return m._specular.rgb; } +float getMaterialShininess(Material m) { return m._specular.a; } + +<@endif@> diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 386569dd08..67f0262b61 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -1,303 +1,303 @@ -// -// Stage.cpp -// libraries/model/src/model -// -// Created by Sam Gateau on 2/24/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 -// -#include "Stage.h" - -#include -#include -#include - -using namespace model; - - -void EarthSunModel::updateAll() const { - updateWorldToSurface(); - updateSurfaceToEye(); - updateSun(); -} - -Mat4d EarthSunModel::evalWorldToGeoLocationMat(double longitude, double latitude, double absAltitude, double scale) { - // Longitude is along Z axis but - from east to west - Mat4d rotLon = glm::rotate(glm::radians(longitude), Vec3d(0.0, 0.0, 1.0)); - - // latitude is along X axis + from south to north - Mat4d rotLat = glm::rotate(-glm::radians(latitude), Vec3d(1.0, 0.0, 0.0)); - - // translation is movin to the earth surface + altiture at the radius along Y axis - Mat4d surfaceT = glm::translate(Vec3d(0.0, -absAltitude, 0.0)); - - // Mat4d worldScale = glm::scale(Vec3d(scale)); - - Mat4d worldToGeoLocMat = surfaceT * rotLat * rotLon; - - return worldToGeoLocMat; -} - -void EarthSunModel::updateWorldToSurface() const { - // Check if the final position is too close to the earth center ? - float absAltitude = _earthRadius + _altitude; - if ( absAltitude < 0.01f) { - absAltitude = 0.01f; - } - - // Final world to local Frame - _worldToSurfaceMat = evalWorldToGeoLocationMat(_longitude, _latitude, absAltitude, _scale); - // and the inverse - _surfaceToWorldMat = glm::inverse(_worldToSurfaceMat); - - _surfacePos = Vec3d(_surfaceToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0)); -} - -void EarthSunModel::updateSurfaceToEye() const { - _surfaceToEyeMat = glm::inverse(_eyeToSurfaceMat); - _worldToEyeMat = _surfaceToEyeMat * _worldToSurfaceMat; - _eyeToWorldMat = _surfaceToWorldMat * _eyeToSurfaceMat; - _eyePos = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0) ); - _eyeDir = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, -1.0, 0.0) ); -} - -void EarthSunModel::updateSun() const { - // Longitude is along Y axis but - from east to west - Mat4d rotSunLon; - - Mat4d rotSun = evalWorldToGeoLocationMat(_sunLongitude, _sunLatitude, _earthRadius, _scale); - rotSun = glm::inverse(rotSun); - - _sunDir = Vec3d(rotSun * Vec4d(0.0, 1.0, 0.0, 0.0)); - - // sun direction is looking up toward Y axis at the specified sun lat, long - Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); - - // apply surface rotation offset - glm::dquat dSurfOrient(_surfaceOrientation); - lssd = glm::rotate(dSurfOrient, lssd); - - _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); -} - -void EarthSunModel::setSurfaceOrientation(const Quat& orientation) { - _surfaceOrientation = orientation; - invalidate(); -} - -double moduloRange(double val, double minVal, double maxVal) { - double range = maxVal - minVal; - double rval = (val - minVal) / range; - rval = rval - floor(rval); - return rval * range + minVal; -} - -const float MAX_LONGITUDE = 180.0f; -const float MAX_LATITUDE = 90.0f; - -float validateLongitude(float lon) { - return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); -} - -float validateLatitude(float lat) { - return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); -} - -float validateAltitude(float altitude) { - const float MIN_ALTITUDE = -1000.0f; - const float MAX_ALTITUDE = 100000.0f; - return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); -} - -void EarthSunModel::setLatitude(float lat) { - _latitude = validateLatitude(lat); - invalidate(); -} -void EarthSunModel::setLongitude(float lon) { - _longitude = validateLongitude(lon); - invalidate(); -} -void EarthSunModel::setAltitude(float altitude) { - _altitude = validateAltitude(altitude); - invalidate(); -} - -void EarthSunModel::setSunLatitude(float lat) { - _sunLatitude = validateLatitude(lat); - invalidate(); -} -void EarthSunModel::setSunLongitude(float lon) { - _sunLongitude = validateLongitude(lon); - invalidate(); -} - -Atmosphere::Atmosphere() { - // only if created from nothing shall we create the Buffer to store the properties - Data data; - _dataBuffer = gpu::BufferView(std::make_shared(sizeof(Data), (const gpu::Byte*) &data)); - - setScatteringWavelength(_scatteringWavelength); - setRayleighScattering(_rayleighScattering); - setInnerOuterRadiuses(getInnerRadius(), getOuterRadius()); -} - -void Atmosphere::setScatteringWavelength(Vec3 wavelength) { - _scatteringWavelength = wavelength; - Data& data = editData(); - data._invWaveLength = Vec4(1.0f / powf(wavelength.x, 4.0f), 1.0f / powf(wavelength.y, 4.0f), 1.0f / powf(wavelength.z, 4.0f), 0.0f); -} - -void Atmosphere::setRayleighScattering(float scattering) { - _rayleighScattering = scattering; - updateScattering(); -} - -void Atmosphere::setMieScattering(float scattering) { - _mieScattering = scattering; - updateScattering(); -} - -void Atmosphere::setSunBrightness(float brightness) { - _sunBrightness = brightness; - updateScattering(); -} - -void Atmosphere::updateScattering() { - Data& data = editData(); - - data._scatterings.x = getRayleighScattering() * getSunBrightness(); - data._scatterings.y = getMieScattering() * getSunBrightness(); - - data._scatterings.z = getRayleighScattering() * 4.0f * glm::pi(); - data._scatterings.w = getMieScattering() * 4.0f * glm::pi(); -} - -void Atmosphere::setInnerOuterRadiuses(float inner, float outer) { - Data& data = editData(); - data._radiuses.x = inner; - data._radiuses.y = outer; - data._scales.x = 1.0f / (outer - inner); - data._scales.z = data._scales.x / data._scales.y; -} - - -const int NUM_DAYS_PER_YEAR = 365; -const float NUM_HOURS_PER_DAY = 24.0f; -const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; - -SunSkyStage::SunSkyStage() : - _sunLight(std::make_shared()), - _skybox(std::make_shared()) -{ - _sunLight->setType(Light::SUN); - - setSunIntensity(1.0f); - setSunAmbientIntensity(0.5f); - setSunColor(Vec3(1.0f, 1.0f, 1.0f)); - - // Default origin location is a special place in the world... - setOriginLocation(122.407f, 37.777f, 0.03f); - // Noun - setDayTime(12.0f); - // Begining of march - setYearTime(60.0f); - - _skybox->setColor(Color(1.0f, 0.0f, 0.0f)); -} - -SunSkyStage::~SunSkyStage() { -} - -void SunSkyStage::setDayTime(float hour) { - _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); - invalidate(); -} - -void SunSkyStage::setYearTime(unsigned int day) { - _yearTime = day % NUM_DAYS_PER_YEAR; - invalidate(); -} - -void SunSkyStage::setOriginOrientation(const Quat& orientation) { - _earthSunModel.setSurfaceOrientation(orientation); - invalidate(); -} - -void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { - _earthSunModel.setLongitude(longitude); - _earthSunModel.setLatitude(latitude); - _earthSunModel.setAltitude(altitude); - invalidate(); -} - -void SunSkyStage::setSunModelEnable(bool isEnabled) { - _sunModelEnable = isEnabled; - invalidate(); -} - -void SunSkyStage::setSunColor(const Vec3& color) { - _sunLight->setColor(color); -} -void SunSkyStage::setSunIntensity(float intensity) { - _sunLight->setIntensity(intensity); -} -void SunSkyStage::setSunAmbientIntensity(float intensity) { - _sunLight->setAmbientIntensity(intensity); -} - -void SunSkyStage::setSunDirection(const Vec3& direction) { - if (!isSunModelEnabled()) { - _sunLight->setDirection(direction); - } -} - -// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun -double evalSunDeclinaison(double dayNumber) { - return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); -} - -void SunSkyStage::updateGraphicsObject() const { - // Always update the sunLongitude based on the current dayTime and the current origin - // The day time is supposed to be local at the origin - float signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; - float sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); - _earthSunModel.setSunLongitude(sunLongitude); - - // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); - - if (isSunModelEnabled()) { - Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); - _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); - - double originAlt = _earthSunModel.getAltitude(); - _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); - } - - // Background - switch (getBackgroundMode()) { - case NO_BACKGROUND: { - break; - } - case SKY_DOME: { - break; - } - case SKY_BOX: { - break; - } - case NUM_BACKGROUND_MODES: - Q_UNREACHABLE(); - }; -} - -void SunSkyStage::setBackgroundMode(BackgroundMode mode) { - _backgroundMode = mode; - invalidate(); -} - -void SunSkyStage::setSkybox(const SkyboxPointer& skybox) { - _skybox = skybox; - invalidate(); -} +// +// Stage.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/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 +// +#include "Stage.h" + +#include +#include +#include + +using namespace model; + + +void EarthSunModel::updateAll() const { + updateWorldToSurface(); + updateSurfaceToEye(); + updateSun(); +} + +Mat4d EarthSunModel::evalWorldToGeoLocationMat(double longitude, double latitude, double absAltitude, double scale) { + // Longitude is along Z axis but - from east to west + Mat4d rotLon = glm::rotate(glm::radians(longitude), Vec3d(0.0, 0.0, 1.0)); + + // latitude is along X axis + from south to north + Mat4d rotLat = glm::rotate(-glm::radians(latitude), Vec3d(1.0, 0.0, 0.0)); + + // translation is movin to the earth surface + altiture at the radius along Y axis + Mat4d surfaceT = glm::translate(Vec3d(0.0, -absAltitude, 0.0)); + + // Mat4d worldScale = glm::scale(Vec3d(scale)); + + Mat4d worldToGeoLocMat = surfaceT * rotLat * rotLon; + + return worldToGeoLocMat; +} + +void EarthSunModel::updateWorldToSurface() const { + // Check if the final position is too close to the earth center ? + float absAltitude = _earthRadius + _altitude; + if ( absAltitude < 0.01f) { + absAltitude = 0.01f; + } + + // Final world to local Frame + _worldToSurfaceMat = evalWorldToGeoLocationMat(_longitude, _latitude, absAltitude, _scale); + // and the inverse + _surfaceToWorldMat = glm::inverse(_worldToSurfaceMat); + + _surfacePos = Vec3d(_surfaceToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0)); +} + +void EarthSunModel::updateSurfaceToEye() const { + _surfaceToEyeMat = glm::inverse(_eyeToSurfaceMat); + _worldToEyeMat = _surfaceToEyeMat * _worldToSurfaceMat; + _eyeToWorldMat = _surfaceToWorldMat * _eyeToSurfaceMat; + _eyePos = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0) ); + _eyeDir = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, -1.0, 0.0) ); +} + +void EarthSunModel::updateSun() const { + // Longitude is along Y axis but - from east to west + Mat4d rotSunLon; + + Mat4d rotSun = evalWorldToGeoLocationMat(_sunLongitude, _sunLatitude, _earthRadius, _scale); + rotSun = glm::inverse(rotSun); + + _sunDir = Vec3d(rotSun * Vec4d(0.0, 1.0, 0.0, 0.0)); + + // sun direction is looking up toward Y axis at the specified sun lat, long + Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); + + // apply surface rotation offset + glm::dquat dSurfOrient(_surfaceOrientation); + lssd = glm::rotate(dSurfOrient, lssd); + + _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); +} + +void EarthSunModel::setSurfaceOrientation(const Quat& orientation) { + _surfaceOrientation = orientation; + invalidate(); +} + +double moduloRange(double val, double minVal, double maxVal) { + double range = maxVal - minVal; + double rval = (val - minVal) / range; + rval = rval - floor(rval); + return rval * range + minVal; +} + +const float MAX_LONGITUDE = 180.0f; +const float MAX_LATITUDE = 90.0f; + +float validateLongitude(float lon) { + return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); +} + +float validateLatitude(float lat) { + return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); +} + +float validateAltitude(float altitude) { + const float MIN_ALTITUDE = -1000.0f; + const float MAX_ALTITUDE = 100000.0f; + return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); +} + +void EarthSunModel::setLatitude(float lat) { + _latitude = validateLatitude(lat); + invalidate(); +} +void EarthSunModel::setLongitude(float lon) { + _longitude = validateLongitude(lon); + invalidate(); +} +void EarthSunModel::setAltitude(float altitude) { + _altitude = validateAltitude(altitude); + invalidate(); +} + +void EarthSunModel::setSunLatitude(float lat) { + _sunLatitude = validateLatitude(lat); + invalidate(); +} +void EarthSunModel::setSunLongitude(float lon) { + _sunLongitude = validateLongitude(lon); + invalidate(); +} + +Atmosphere::Atmosphere() { + // only if created from nothing shall we create the Buffer to store the properties + Data data; + _dataBuffer = gpu::BufferView(std::make_shared(sizeof(Data), (const gpu::Byte*) &data)); + + setScatteringWavelength(_scatteringWavelength); + setRayleighScattering(_rayleighScattering); + setInnerOuterRadiuses(getInnerRadius(), getOuterRadius()); +} + +void Atmosphere::setScatteringWavelength(Vec3 wavelength) { + _scatteringWavelength = wavelength; + Data& data = editData(); + data._invWaveLength = Vec4(1.0f / powf(wavelength.x, 4.0f), 1.0f / powf(wavelength.y, 4.0f), 1.0f / powf(wavelength.z, 4.0f), 0.0f); +} + +void Atmosphere::setRayleighScattering(float scattering) { + _rayleighScattering = scattering; + updateScattering(); +} + +void Atmosphere::setMieScattering(float scattering) { + _mieScattering = scattering; + updateScattering(); +} + +void Atmosphere::setSunBrightness(float brightness) { + _sunBrightness = brightness; + updateScattering(); +} + +void Atmosphere::updateScattering() { + Data& data = editData(); + + data._scatterings.x = getRayleighScattering() * getSunBrightness(); + data._scatterings.y = getMieScattering() * getSunBrightness(); + + data._scatterings.z = getRayleighScattering() * 4.0f * glm::pi(); + data._scatterings.w = getMieScattering() * 4.0f * glm::pi(); +} + +void Atmosphere::setInnerOuterRadiuses(float inner, float outer) { + Data& data = editData(); + data._radiuses.x = inner; + data._radiuses.y = outer; + data._scales.x = 1.0f / (outer - inner); + data._scales.z = data._scales.x / data._scales.y; +} + + +const int NUM_DAYS_PER_YEAR = 365; +const float NUM_HOURS_PER_DAY = 24.0f; +const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; + +SunSkyStage::SunSkyStage() : + _sunLight(std::make_shared()), + _skybox(std::make_shared()) +{ + _sunLight->setType(Light::SUN); + + setSunIntensity(1.0f); + setSunAmbientIntensity(0.5f); + setSunColor(Vec3(1.0f, 1.0f, 1.0f)); + + // Default origin location is a special place in the world... + setOriginLocation(122.407f, 37.777f, 0.03f); + // Noun + setDayTime(12.0f); + // Begining of march + setYearTime(60.0f); + + _skybox->setColor(Color(1.0f, 0.0f, 0.0f)); +} + +SunSkyStage::~SunSkyStage() { +} + +void SunSkyStage::setDayTime(float hour) { + _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); + invalidate(); +} + +void SunSkyStage::setYearTime(unsigned int day) { + _yearTime = day % NUM_DAYS_PER_YEAR; + invalidate(); +} + +void SunSkyStage::setOriginOrientation(const Quat& orientation) { + _earthSunModel.setSurfaceOrientation(orientation); + invalidate(); +} + +void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { + _earthSunModel.setLongitude(longitude); + _earthSunModel.setLatitude(latitude); + _earthSunModel.setAltitude(altitude); + invalidate(); +} + +void SunSkyStage::setSunModelEnable(bool isEnabled) { + _sunModelEnable = isEnabled; + invalidate(); +} + +void SunSkyStage::setSunColor(const Vec3& color) { + _sunLight->setColor(color); +} +void SunSkyStage::setSunIntensity(float intensity) { + _sunLight->setIntensity(intensity); +} +void SunSkyStage::setSunAmbientIntensity(float intensity) { + _sunLight->setAmbientIntensity(intensity); +} + +void SunSkyStage::setSunDirection(const Vec3& direction) { + if (!isSunModelEnabled()) { + _sunLight->setDirection(direction); + } +} + +// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclinaison(double dayNumber) { + return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); +} + +void SunSkyStage::updateGraphicsObject() const { + // Always update the sunLongitude based on the current dayTime and the current origin + // The day time is supposed to be local at the origin + float signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; + float sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); + _earthSunModel.setSunLongitude(sunLongitude); + + // And update the sunLAtitude as the declinaison depending of the time of the year + _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); + + if (isSunModelEnabled()) { + Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); + _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); + + double originAlt = _earthSunModel.getAltitude(); + _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); + } + + // Background + switch (getBackgroundMode()) { + case NO_BACKGROUND: { + break; + } + case SKY_DOME: { + break; + } + case SKY_BOX: { + break; + } + case NUM_BACKGROUND_MODES: + Q_UNREACHABLE(); + }; +} + +void SunSkyStage::setBackgroundMode(BackgroundMode mode) { + _backgroundMode = mode; + invalidate(); +} + +void SunSkyStage::setSkybox(const SkyboxPointer& skybox) { + _skybox = skybox; + invalidate(); +} diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 89a8a4c049..978c308ac6 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -1,247 +1,247 @@ -// -// Stage.h -// libraries/model/src/model -// -// Created by Sam Gateau on 2/24/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 -// -#ifndef hifi_model_Stage_h -#define hifi_model_Stage_h - -#include "gpu/Pipeline.h" - -#include "Light.h" -#include "Skybox.h" - -namespace model { - -typedef glm::dvec3 Vec3d; -typedef glm::dvec4 Vec4d; -typedef glm::dmat4 Mat4d; -typedef glm::mat4 Mat4; - -class EarthSunModel { -public: - - void setScale(float scale); - float getScale() const { return _scale; } - - void setLatitude(float lat); - float getLatitude() const { return _latitude; } - void setLongitude(float lon); - float getLongitude() const { return _longitude; } - void setAltitude(float altitude); - float getAltitude() const { return _altitude; } - - - void setSurfaceOrientation(const Quat& orientation); - const Quat& getSurfaceOrientation() const { valid(); return _surfaceOrientation; } - - const Vec3d& getSurfacePos() const { valid(); return _surfacePos; } - - const Mat4d& getSurfaceToWorldMat() const { valid(); return _surfaceToWorldMat; } - const Mat4d& getWoldToSurfaceMat() const { valid(); return _worldToSurfaceMat; } - - const Mat4d& getEyeToSurfaceMat() const { valid(); return _eyeToSurfaceMat; } - const Mat4d& getSurfaceToEyeMat() const { valid(); return _surfaceToEyeMat; } - - const Mat4d& getEyeToWorldMat() const { valid(); return _eyeToWorldMat; } - const Mat4d& getWorldToEyeMat() const { valid(); return _worldToEyeMat; } - - - //or set the surfaceToEye mat directly - void setEyeToSurfaceMat( const Mat4d& e2s); - - const Vec3d& getEyePos() const { valid(); return _eyePos; } - const Vec3d& getEyeDir() const { valid(); return _eyeDir; } - - void setSunLongitude(float lon); - float getSunLongitude() const { return _sunLongitude; } - - void setSunLatitude(float lat); - float getSunLatitude() const { return _sunLatitude; } - - const Vec3d& getWorldSunDir() const { valid(); return _sunDir; } - const Vec3d& getSurfaceSunDir() const { valid(); return _surfaceSunDir; } - - - EarthSunModel() { valid(); } - -protected: - float _scale = 1000.0f; //Km - float _earthRadius = 6360.0; - - Quat _surfaceOrientation; - - float _longitude = 0.0f; - float _latitude = 0.0f; - float _altitude = 0.01f; - mutable Vec3d _surfacePos; - mutable Mat4d _worldToSurfaceMat; - mutable Mat4d _surfaceToWorldMat; - void updateWorldToSurface() const; - - mutable Mat4d _surfaceToEyeMat; - mutable Mat4d _eyeToSurfaceMat; - mutable Vec3d _eyeDir; - mutable Vec3d _eyePos; - void updateSurfaceToEye() const; - - mutable Mat4d _worldToEyeMat; - mutable Mat4d _eyeToWorldMat; - - float _sunLongitude = 0.0f; - float _sunLatitude = 0.0f; - mutable Vec3d _sunDir; - mutable Vec3d _surfaceSunDir; - void updateSun() const; - - mutable bool _invalid = true; - void invalidate() const { _invalid = true; } - void valid() const { if (_invalid) { updateAll(); _invalid = false; } } - void updateAll() const; - - static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); -}; - - -class Atmosphere { -public: - - Atmosphere(); - Atmosphere(const Atmosphere& atmosphere); - Atmosphere& operator= (const Atmosphere& atmosphere); - virtual ~Atmosphere() {}; - - - void setScatteringWavelength(Vec3 wavelength); - const Vec3& getScatteringWavelength() const { return _scatteringWavelength; } - - void setRayleighScattering(float scattering); - float getRayleighScattering() const { return _rayleighScattering; } - - void setMieScattering(float scattering); - float getMieScattering() const { return _mieScattering; } - - void setSunBrightness(float brightness); - float getSunBrightness() const { return _sunBrightness; } - - void setInnerOuterRadiuses(float inner, float outer); - float getInnerRadius() const { return getData()._radiuses.x; } - float getOuterRadius() const { return getData()._radiuses.y; } - - // Data to access the attribute values of the atmosphere - class Data { - public: - Vec4 _invWaveLength = Vec4(0.0f); - Vec4 _radiuses = Vec4(6000.0f, 6025.0f, 0.0f, 0.0f); - Vec4 _scales = Vec4(0.0f, 0.25f, 0.0f, 0.0f); - Vec4 _scatterings = Vec4(0.0f); - Vec4 _control = Vec4(2.0f, -0.990f, -0.990f*-0.990f, 0.f); - - Data() {} - }; - - const UniformBufferView& getDataBuffer() const { return _dataBuffer; } - -protected: - UniformBufferView _dataBuffer; - Vec3 _scatteringWavelength = Vec3(0.650f, 0.570f, 0.475f); - float _rayleighScattering = 0.0025f; - float _mieScattering = 0.0010f; - float _sunBrightness = 20.0f; - - const Data& getData() const { return _dataBuffer.get(); } - Data& editData() { return _dataBuffer.edit(); } - - void updateScattering(); -}; -typedef std::shared_ptr< Atmosphere > AtmospherePointer; - -// Sun sky stage generates the rendering primitives to display a scene realistically -// at the specified location and time around earth -class SunSkyStage { -public: - - SunSkyStage(); - ~SunSkyStage(); - - // time of the day (local to the position) expressed in decimal hour in the range [0.0, 24.0] - void setDayTime(float hour); - float getDayTime() const { return _dayTime; } - - // time of the year expressed in day in the range [0, 365] - void setYearTime(unsigned int day); - unsigned int getYearTime() const { return _yearTime; } - - // Origin orientation used to modify the cardinal axis alignement used. - // THe default is north along +Z axis and west along +X axis. this orientation gets added - // to the transform stack producing the sun light direction. - void setOriginOrientation(const Quat& orientation); - const Quat& getOriginOrientation() const { return _earthSunModel.getSurfaceOrientation(); } - - // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] - void setOriginLocation(float longitude, float latitude, float surfaceAltitude); - float getOriginLatitude() const { return _earthSunModel.getLatitude(); } - float getOriginLongitude() const { return _earthSunModel.getLongitude(); } - float getOriginSurfaceAltitude() const { return _earthSunModel.getAltitude(); } - - // Enable / disable the effect of the time and location on the sun direction and color - void setSunModelEnable(bool isEnabled); - bool isSunModelEnabled() const { return _sunModelEnable; } - - // Sun properties - void setSunColor(const Vec3& color); - const Vec3& getSunColor() const { return getSunLight()->getColor(); } - void setSunIntensity(float intensity); - float getSunIntensity() const { return getSunLight()->getIntensity(); } - void setSunAmbientIntensity(float intensity); - float getSunAmbientIntensity() const { return getSunLight()->getAmbientIntensity(); } - - // The sun direction is expressed in the world space - void setSunDirection(const Vec3& direction); - const Vec3& getSunDirection() const { return getSunLight()->getDirection(); } - - LightPointer getSunLight() const { valid(); return _sunLight; } - AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; } - - enum BackgroundMode { - NO_BACKGROUND = 0, - SKY_DOME, - SKY_BOX, - - NUM_BACKGROUND_MODES, - }; - void setBackgroundMode(BackgroundMode mode); - BackgroundMode getBackgroundMode() const { return _backgroundMode; } - - // Skybox - void setSkybox(const SkyboxPointer& skybox); - const SkyboxPointer& getSkybox() const { valid(); return _skybox; } - -protected: - BackgroundMode _backgroundMode = SKY_BOX; - - LightPointer _sunLight; - AtmospherePointer _atmosphere; - mutable SkyboxPointer _skybox; - - float _dayTime = 12.0f; - int _yearTime = 0; - mutable EarthSunModel _earthSunModel; - bool _sunModelEnable = true; - - mutable bool _invalid = true; - void invalidate() const { _invalid = true; } - void valid() const { if (_invalid) { updateGraphicsObject(); _invalid = false; } } - void updateGraphicsObject() const; -}; - -typedef std::shared_ptr< SunSkyStage > SunSkyStagePointer; - -}; - -#endif +// +// Stage.h +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/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 +// +#ifndef hifi_model_Stage_h +#define hifi_model_Stage_h + +#include "gpu/Pipeline.h" + +#include "Light.h" +#include "Skybox.h" + +namespace model { + +typedef glm::dvec3 Vec3d; +typedef glm::dvec4 Vec4d; +typedef glm::dmat4 Mat4d; +typedef glm::mat4 Mat4; + +class EarthSunModel { +public: + + void setScale(float scale); + float getScale() const { return _scale; } + + void setLatitude(float lat); + float getLatitude() const { return _latitude; } + void setLongitude(float lon); + float getLongitude() const { return _longitude; } + void setAltitude(float altitude); + float getAltitude() const { return _altitude; } + + + void setSurfaceOrientation(const Quat& orientation); + const Quat& getSurfaceOrientation() const { valid(); return _surfaceOrientation; } + + const Vec3d& getSurfacePos() const { valid(); return _surfacePos; } + + const Mat4d& getSurfaceToWorldMat() const { valid(); return _surfaceToWorldMat; } + const Mat4d& getWoldToSurfaceMat() const { valid(); return _worldToSurfaceMat; } + + const Mat4d& getEyeToSurfaceMat() const { valid(); return _eyeToSurfaceMat; } + const Mat4d& getSurfaceToEyeMat() const { valid(); return _surfaceToEyeMat; } + + const Mat4d& getEyeToWorldMat() const { valid(); return _eyeToWorldMat; } + const Mat4d& getWorldToEyeMat() const { valid(); return _worldToEyeMat; } + + + //or set the surfaceToEye mat directly + void setEyeToSurfaceMat( const Mat4d& e2s); + + const Vec3d& getEyePos() const { valid(); return _eyePos; } + const Vec3d& getEyeDir() const { valid(); return _eyeDir; } + + void setSunLongitude(float lon); + float getSunLongitude() const { return _sunLongitude; } + + void setSunLatitude(float lat); + float getSunLatitude() const { return _sunLatitude; } + + const Vec3d& getWorldSunDir() const { valid(); return _sunDir; } + const Vec3d& getSurfaceSunDir() const { valid(); return _surfaceSunDir; } + + + EarthSunModel() { valid(); } + +protected: + float _scale = 1000.0f; //Km + float _earthRadius = 6360.0; + + Quat _surfaceOrientation; + + float _longitude = 0.0f; + float _latitude = 0.0f; + float _altitude = 0.01f; + mutable Vec3d _surfacePos; + mutable Mat4d _worldToSurfaceMat; + mutable Mat4d _surfaceToWorldMat; + void updateWorldToSurface() const; + + mutable Mat4d _surfaceToEyeMat; + mutable Mat4d _eyeToSurfaceMat; + mutable Vec3d _eyeDir; + mutable Vec3d _eyePos; + void updateSurfaceToEye() const; + + mutable Mat4d _worldToEyeMat; + mutable Mat4d _eyeToWorldMat; + + float _sunLongitude = 0.0f; + float _sunLatitude = 0.0f; + mutable Vec3d _sunDir; + mutable Vec3d _surfaceSunDir; + void updateSun() const; + + mutable bool _invalid = true; + void invalidate() const { _invalid = true; } + void valid() const { if (_invalid) { updateAll(); _invalid = false; } } + void updateAll() const; + + static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); +}; + + +class Atmosphere { +public: + + Atmosphere(); + Atmosphere(const Atmosphere& atmosphere); + Atmosphere& operator= (const Atmosphere& atmosphere); + virtual ~Atmosphere() {}; + + + void setScatteringWavelength(Vec3 wavelength); + const Vec3& getScatteringWavelength() const { return _scatteringWavelength; } + + void setRayleighScattering(float scattering); + float getRayleighScattering() const { return _rayleighScattering; } + + void setMieScattering(float scattering); + float getMieScattering() const { return _mieScattering; } + + void setSunBrightness(float brightness); + float getSunBrightness() const { return _sunBrightness; } + + void setInnerOuterRadiuses(float inner, float outer); + float getInnerRadius() const { return getData()._radiuses.x; } + float getOuterRadius() const { return getData()._radiuses.y; } + + // Data to access the attribute values of the atmosphere + class Data { + public: + Vec4 _invWaveLength = Vec4(0.0f); + Vec4 _radiuses = Vec4(6000.0f, 6025.0f, 0.0f, 0.0f); + Vec4 _scales = Vec4(0.0f, 0.25f, 0.0f, 0.0f); + Vec4 _scatterings = Vec4(0.0f); + Vec4 _control = Vec4(2.0f, -0.990f, -0.990f*-0.990f, 0.f); + + Data() {} + }; + + const UniformBufferView& getDataBuffer() const { return _dataBuffer; } + +protected: + UniformBufferView _dataBuffer; + Vec3 _scatteringWavelength = Vec3(0.650f, 0.570f, 0.475f); + float _rayleighScattering = 0.0025f; + float _mieScattering = 0.0010f; + float _sunBrightness = 20.0f; + + const Data& getData() const { return _dataBuffer.get(); } + Data& editData() { return _dataBuffer.edit(); } + + void updateScattering(); +}; +typedef std::shared_ptr< Atmosphere > AtmospherePointer; + +// Sun sky stage generates the rendering primitives to display a scene realistically +// at the specified location and time around earth +class SunSkyStage { +public: + + SunSkyStage(); + ~SunSkyStage(); + + // time of the day (local to the position) expressed in decimal hour in the range [0.0, 24.0] + void setDayTime(float hour); + float getDayTime() const { return _dayTime; } + + // time of the year expressed in day in the range [0, 365] + void setYearTime(unsigned int day); + unsigned int getYearTime() const { return _yearTime; } + + // Origin orientation used to modify the cardinal axis alignement used. + // THe default is north along +Z axis and west along +X axis. this orientation gets added + // to the transform stack producing the sun light direction. + void setOriginOrientation(const Quat& orientation); + const Quat& getOriginOrientation() const { return _earthSunModel.getSurfaceOrientation(); } + + // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] + void setOriginLocation(float longitude, float latitude, float surfaceAltitude); + float getOriginLatitude() const { return _earthSunModel.getLatitude(); } + float getOriginLongitude() const { return _earthSunModel.getLongitude(); } + float getOriginSurfaceAltitude() const { return _earthSunModel.getAltitude(); } + + // Enable / disable the effect of the time and location on the sun direction and color + void setSunModelEnable(bool isEnabled); + bool isSunModelEnabled() const { return _sunModelEnable; } + + // Sun properties + void setSunColor(const Vec3& color); + const Vec3& getSunColor() const { return getSunLight()->getColor(); } + void setSunIntensity(float intensity); + float getSunIntensity() const { return getSunLight()->getIntensity(); } + void setSunAmbientIntensity(float intensity); + float getSunAmbientIntensity() const { return getSunLight()->getAmbientIntensity(); } + + // The sun direction is expressed in the world space + void setSunDirection(const Vec3& direction); + const Vec3& getSunDirection() const { return getSunLight()->getDirection(); } + + LightPointer getSunLight() const { valid(); return _sunLight; } + AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; } + + enum BackgroundMode { + NO_BACKGROUND = 0, + SKY_DOME, + SKY_BOX, + + NUM_BACKGROUND_MODES, + }; + void setBackgroundMode(BackgroundMode mode); + BackgroundMode getBackgroundMode() const { return _backgroundMode; } + + // Skybox + void setSkybox(const SkyboxPointer& skybox); + const SkyboxPointer& getSkybox() const { valid(); return _skybox; } + +protected: + BackgroundMode _backgroundMode = SKY_BOX; + + LightPointer _sunLight; + AtmospherePointer _atmosphere; + mutable SkyboxPointer _skybox; + + float _dayTime = 12.0f; + int _yearTime = 0; + mutable EarthSunModel _earthSunModel; + bool _sunModelEnable = true; + + mutable bool _invalid = true; + void invalidate() const { _invalid = true; } + void valid() const { if (_invalid) { updateGraphicsObject(); _invalid = false; } } + void updateGraphicsObject() const; +}; + +typedef std::shared_ptr< SunSkyStage > SunSkyStagePointer; + +}; + +#endif diff --git a/libraries/octree/src/Plane.cpp b/libraries/octree/src/Plane.cpp index e9488e7e57..8e782dd087 100644 --- a/libraries/octree/src/Plane.cpp +++ b/libraries/octree/src/Plane.cpp @@ -1,71 +1,71 @@ -// -// Plane.cpp -// libraries/octree/src/ -// -// Created by Brad Hefta-Gaub on 04/11/13. -// Copyright 2013 High Fidelity, Inc. -// -// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards -// Simple plane class. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Plane.h" -#include "OctreeLogging.h" - - -#include - -#include - -void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { - glm::vec3 linev1v2, linev1v3; - - linev1v2 = v2 - v1; - linev1v3 = v3 - v1; - - // this will be perpendicular to both lines - _normal = glm::cross(linev1v2,linev1v3); - _normal = glm::normalize(_normal); - - // this is a point on the plane - _point = v2; - - // the D coefficient from the form Ax+By+Cz=D - _dCoefficient = -(glm::dot(_normal,_point)); -} - -void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) { - _point = point; - _normal = normal; - glm::normalize(_normal); - - // the D coefficient from the form Ax+By+Cz=D - _dCoefficient = -(glm::dot(_normal,_point)); -} - -void Plane::setCoefficients(float a, float b, float c, float d) { - // set the normal vector - _normal = glm::vec3(a,b,c); - - //compute the lenght of the vector - float l = glm::length(_normal); - - // normalize the vector - _normal = glm::vec3(a/l,b/l,c/l); - - // and divide d by th length as well - _dCoefficient = d/l; -} - -float Plane::distance(const glm::vec3 &point) const { - return (_dCoefficient + glm::dot(_normal,point)); -} - -void Plane::print() const { - qCDebug(octree, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f", - (double)_point.x, (double)_point.y, (double)_point.z, - (double)_normal.x, (double)_normal.y, (double)_normal.z, (double)_dCoefficient); -} +// +// Plane.cpp +// libraries/octree/src/ +// +// Created by Brad Hefta-Gaub on 04/11/13. +// Copyright 2013 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Plane.h" +#include "OctreeLogging.h" + + +#include + +#include + +void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { + glm::vec3 linev1v2, linev1v3; + + linev1v2 = v2 - v1; + linev1v3 = v3 - v1; + + // this will be perpendicular to both lines + _normal = glm::cross(linev1v2,linev1v3); + _normal = glm::normalize(_normal); + + // this is a point on the plane + _point = v2; + + // the D coefficient from the form Ax+By+Cz=D + _dCoefficient = -(glm::dot(_normal,_point)); +} + +void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) { + _point = point; + _normal = normal; + glm::normalize(_normal); + + // the D coefficient from the form Ax+By+Cz=D + _dCoefficient = -(glm::dot(_normal,_point)); +} + +void Plane::setCoefficients(float a, float b, float c, float d) { + // set the normal vector + _normal = glm::vec3(a,b,c); + + //compute the lenght of the vector + float l = glm::length(_normal); + + // normalize the vector + _normal = glm::vec3(a/l,b/l,c/l); + + // and divide d by th length as well + _dCoefficient = d/l; +} + +float Plane::distance(const glm::vec3 &point) const { + return (_dCoefficient + glm::dot(_normal,point)); +} + +void Plane::print() const { + qCDebug(octree, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f", + (double)_point.x, (double)_point.y, (double)_point.z, + (double)_normal.x, (double)_normal.y, (double)_normal.z, (double)_dCoefficient); +} diff --git a/libraries/octree/src/Plane.h b/libraries/octree/src/Plane.h index a113c753cc..db809ad542 100644 --- a/libraries/octree/src/Plane.h +++ b/libraries/octree/src/Plane.h @@ -1,47 +1,47 @@ -// -// Plane.h -// libraries/octree/src/ -// -// Created by Brad Hefta-Gaub on 04/11/13. -// Copyright 2013 High Fidelity, Inc. -// -// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards -// Simple plane class. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Plane_h -#define hifi_Plane_h - -#include - -class Plane { -public: - Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); } - Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {}; - ~Plane() {} ; - - // methods for defining the plane - void set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3); - void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point); - void setCoefficients(float a, float b, float c, float d); - - // getters - const glm::vec3& getNormal() const { return _normal; }; - const glm::vec3& getPoint() const { return _point; }; - float getDCoefficient() const { return _dCoefficient; }; - - // utilities - float distance(const glm::vec3 &point) const; - void print() const; - -private: - glm::vec3 _normal; - glm::vec3 _point; - float _dCoefficient; -}; - - +// +// Plane.h +// libraries/octree/src/ +// +// Created by Brad Hefta-Gaub on 04/11/13. +// Copyright 2013 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_Plane_h +#define hifi_Plane_h + +#include + +class Plane { +public: + Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); } + Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {}; + ~Plane() {} ; + + // methods for defining the plane + void set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3); + void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point); + void setCoefficients(float a, float b, float c, float d); + + // getters + const glm::vec3& getNormal() const { return _normal; }; + const glm::vec3& getPoint() const { return _point; }; + float getDCoefficient() const { return _dCoefficient; }; + + // utilities + float distance(const glm::vec3 &point) const; + void print() const; + +private: + glm::vec3 _normal; + glm::vec3 _point; + float _dCoefficient; +}; + + #endif // hifi_Plane_h \ No newline at end of file diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 022bf7898a..bd61de7338 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -16,66 +16,66 @@ #include #include "ProceduralSkybox_vert.h" -#include "ProceduralSkybox_frag.h" - -ProceduralSkybox::ProceduralSkybox() : model::Skybox() { -} - -ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : - model::Skybox(skybox), - _procedural(skybox._procedural) { - -} - -void ProceduralSkybox::setProcedural(const ProceduralPointer& procedural) { - _procedural = procedural; - if (_procedural) { - _procedural->_vertexSource = ProceduralSkybox_vert; - _procedural->_fragmentSource = ProceduralSkybox_frag; - // Adjust the pipeline state for background using the stencil test - _procedural->_state->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)); - } -} - -void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { - ProceduralSkybox::render(batch, frustum, (*this)); -} - -void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) { - if (!(skybox._procedural)) { - skybox.updateDataBuffer(); - Skybox::render(batch, viewFrustum, skybox); - } - - static gpu::BufferPointer theBuffer; - static gpu::Stream::FormatPointer theFormat; - - if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) { - if (!theBuffer) { - 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); - theFormat = std::make_shared(); - theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); - } - - 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); - - if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { - batch.setResourceTexture(0, skybox.getCubemap()); - } - - skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1)); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } -} - +#include "ProceduralSkybox_frag.h" + +ProceduralSkybox::ProceduralSkybox() : model::Skybox() { +} + +ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : + model::Skybox(skybox), + _procedural(skybox._procedural) { + +} + +void ProceduralSkybox::setProcedural(const ProceduralPointer& procedural) { + _procedural = procedural; + if (_procedural) { + _procedural->_vertexSource = ProceduralSkybox_vert; + _procedural->_fragmentSource = ProceduralSkybox_frag; + // Adjust the pipeline state for background using the stencil test + _procedural->_state->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)); + } +} + +void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { + ProceduralSkybox::render(batch, frustum, (*this)); +} + +void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) { + if (!(skybox._procedural)) { + skybox.updateDataBuffer(); + Skybox::render(batch, viewFrustum, skybox); + } + + static gpu::BufferPointer theBuffer; + static gpu::Stream::FormatPointer theFormat; + + if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) { + if (!theBuffer) { + 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); + theFormat = std::make_shared(); + theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); + } + + 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); + + if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { + batch.setResourceTexture(0, skybox.getCubemap()); + } + + skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1)); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } +} + diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index 89b8b26a4f..275966534a 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -25,19 +25,19 @@ uniform sampler2D specularMap; uniform sampler2D depthMap; -struct DeferredTransform { +struct DeferredTransform { mat4 projection; mat4 viewInverse; - vec4 stereoSide_spareABC; -}; - -layout(std140) uniform deferredTransformBuffer { - DeferredTransform _deferredTransform; -}; -DeferredTransform getDeferredTransform() { - return _deferredTransform; -} + vec4 stereoSide_spareABC; +}; + +layout(std140) uniform deferredTransformBuffer { + DeferredTransform _deferredTransform; +}; +DeferredTransform getDeferredTransform() { + return _deferredTransform; +} bool getStereoMode(DeferredTransform deferredTransform) { return (deferredTransform.stereoSide_spareABC.x != 0.0);