fix line endings grumble gruble

This commit is contained in:
Andrew Meadows 2015-10-20 09:38:25 -07:00
parent 341bc3666f
commit 7fa069cf30
16 changed files with 2309 additions and 2309 deletions

View file

@ -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 <math.h>
#include <QDebug>
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 <math.h>
#include <QDebug>
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<<slot);
_bufferMask = (_bufferMask & ~(mask));
if (texture) {
_bufferMask |= mask;
}
return slot;
}
void Framebuffer::removeRenderBuffers() {
if (isSwapchain()) {
return;
}
_bufferMask = _bufferMask & BUFFER_DEPTHSTENCIL;
for (auto renderBuffer : _renderBuffers) {
renderBuffer._texture.reset();
}
updateSize(TexturePointer(nullptr));
}
uint32 Framebuffer::getNumRenderBuffers() const {
uint32 nb = 0;
for (auto i : _renderBuffers) {
nb += (!i);
}
return nb;
}
TexturePointer Framebuffer::getRenderBuffer(uint32 slot) const {
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
return _renderBuffers[slot]._texture;
} else {
return TexturePointer();
}
}
uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const {
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
return _renderBuffers[slot]._subresource;
} else {
return 0;
}
}
bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) {
if (isSwapchain()) {
return false;
}
// Check for the compatibility of size
if (texture) {
if (!validateTargetCompatibility(*texture)) {
return false;
}
}
updateSize(texture);
// assign the new one
_depthStencilBuffer = TextureView(texture, subresource, format);
_bufferMask = ( _bufferMask & ~BUFFER_DEPTHSTENCIL);
if (texture) {
if (format.getSemantic() == gpu::DEPTH) {
_bufferMask |= BUFFER_DEPTH;
} else if (format.getSemantic() == gpu::STENCIL) {
_bufferMask |= BUFFER_STENCIL;
} else if (format.getSemantic() == gpu::DEPTH_STENCIL) {
_bufferMask |= BUFFER_DEPTHSTENCIL;
}
}
return true;
}
TexturePointer Framebuffer::getDepthStencilBuffer() const {
if (isSwapchain()) {
return TexturePointer();
} else {
return _depthStencilBuffer._texture;
}
}
uint32 Framebuffer::getDepthStencilBufferSubresource() const {
if (isSwapchain()) {
return 0;
} else {
return _depthStencilBuffer._subresource;
}
}
Format Framebuffer::getDepthStencilBufferFormat() const {
if (isSwapchain()) {
// return getSwapchain()->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<<slot);
_bufferMask = (_bufferMask & ~(mask));
if (texture) {
_bufferMask |= mask;
}
return slot;
}
void Framebuffer::removeRenderBuffers() {
if (isSwapchain()) {
return;
}
_bufferMask = _bufferMask & BUFFER_DEPTHSTENCIL;
for (auto renderBuffer : _renderBuffers) {
renderBuffer._texture.reset();
}
updateSize(TexturePointer(nullptr));
}
uint32 Framebuffer::getNumRenderBuffers() const {
uint32 nb = 0;
for (auto i : _renderBuffers) {
nb += (!i);
}
return nb;
}
TexturePointer Framebuffer::getRenderBuffer(uint32 slot) const {
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
return _renderBuffers[slot]._texture;
} else {
return TexturePointer();
}
}
uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const {
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
return _renderBuffers[slot]._subresource;
} else {
return 0;
}
}
bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) {
if (isSwapchain()) {
return false;
}
// Check for the compatibility of size
if (texture) {
if (!validateTargetCompatibility(*texture)) {
return false;
}
}
updateSize(texture);
// assign the new one
_depthStencilBuffer = TextureView(texture, subresource, format);
_bufferMask = ( _bufferMask & ~BUFFER_DEPTHSTENCIL);
if (texture) {
if (format.getSemantic() == gpu::DEPTH) {
_bufferMask |= BUFFER_DEPTH;
} else if (format.getSemantic() == gpu::STENCIL) {
_bufferMask |= BUFFER_STENCIL;
} else if (format.getSemantic() == gpu::DEPTH_STENCIL) {
_bufferMask |= BUFFER_DEPTHSTENCIL;
}
}
return true;
}
TexturePointer Framebuffer::getDepthStencilBuffer() const {
if (isSwapchain()) {
return TexturePointer();
} else {
return _depthStencilBuffer._texture;
}
}
uint32 Framebuffer::getDepthStencilBufferSubresource() const {
if (isSwapchain()) {
return 0;
} else {
return _depthStencilBuffer._subresource;
}
}
Format Framebuffer::getDepthStencilBufferFormat() const {
if (isSwapchain()) {
// return getSwapchain()->getDepthStencilBufferFormat();
return _depthStencilBuffer._element;
} else {
return _depthStencilBuffer._element;
}
}

View file

@ -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 <memory>
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<Swapchain> 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<Framebuffer> 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 <memory>
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<Swapchain> 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<Framebuffer> FramebufferPointer;
}
#endif

View file

@ -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 <math.h>
#include <QDebug>
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 <math.h>
#include <QDebug>
using namespace gpu;
Pipeline::Pipeline():
_program(),
_state()
{
}
Pipeline::~Pipeline()
{
}
Pipeline* Pipeline::create(const ShaderPointer& program, const StatePointer& state) {
Pipeline* pipeline = new Pipeline();

View file

@ -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 <QDebug>
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 <QDebug>
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);
}

View file

@ -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 <algorithm> //min max and more
#include <QUrl>
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<std::vector<PixelsPointer>> _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<Texture> 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<TextureView> 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 <algorithm> //min max and more
#include <QUrl>
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<std::vector<PixelsPointer>> _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<Texture> 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<TextureView> 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

View file

@ -1,143 +1,143 @@
<!
// gpu/TransformState.slh
//
// Created by Sam Gateau on 2/10/15.
// Copyright 2013 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
!>
<@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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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@>
<!
// gpu/TransformState.slh
//
// Created by Sam Gateau on 2/10/15.
// Copyright 2013 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
!>
<@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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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@>

View file

@ -1,245 +1,245 @@
<!
// Atmospheric.slh
//
// Created by Sam Gateau on 3/9/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not MODEL_ATMOSPHERE_SLH@>
<@def MODEL_ATMOSPHERE_SLH@>
<!
// Code is a modified version of:
// http://http.developer.nvidia.com/GPUGems/gpugems_app01.html
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
!>
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<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(lightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot((v3Ray), v3SamplePoint) / fHeight * 0.99;
float fScatter = (fStartOffset + fDepth * (atmosphereScale(fScaleDepth, fLightAngle) - atmosphereScale(fScaleDepth, fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = cameraPos - v3Pos;
float fCos = dot(lightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
vec4 finalColor;
finalColor.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
finalColor.a = finalColor.b;
finalColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2));
return finalColor;
}
<@if GLPROFILE == PC_GL@>
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@>
<!
/*
// uniform vec3 v3CameraPos; // The camera's current position
const int nSamples = 2;
const float fSamples = 2.0;
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 position;
float scale(float fCos)
{
float x = 1.0 - fCos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
void main (void)
{
// 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 - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos;
float fHeight = length(v3Start);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fStartAngle = dot(v3Ray, v3Start) / fHeight;
float fStartOffset = fDepth * scale(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);
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot((v3Ray), v3SamplePoint) / fHeight * 0.99;
float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = v3CameraPos - v3Pos;
float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
outFragColor.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
outFragColor.a = outFragColor.b;
outFragColor.rgb = pow(outFragColor.rgb, vec3(1.0/2.2));
}
*/
!>
<@endif@>
<!
// Atmospheric.slh
//
// Created by Sam Gateau on 3/9/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not MODEL_ATMOSPHERE_SLH@>
<@def MODEL_ATMOSPHERE_SLH@>
<!
// Code is a modified version of:
// http://http.developer.nvidia.com/GPUGems/gpugems_app01.html
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
!>
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<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(lightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot((v3Ray), v3SamplePoint) / fHeight * 0.99;
float fScatter = (fStartOffset + fDepth * (atmosphereScale(fScaleDepth, fLightAngle) - atmosphereScale(fScaleDepth, fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = cameraPos - v3Pos;
float fCos = dot(lightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
vec4 finalColor;
finalColor.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
finalColor.a = finalColor.b;
finalColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2));
return finalColor;
}
<@if GLPROFILE == PC_GL@>
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@>
<!
/*
// uniform vec3 v3CameraPos; // The camera's current position
const int nSamples = 2;
const float fSamples = 2.0;
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 position;
float scale(float fCos)
{
float x = 1.0 - fCos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
void main (void)
{
// 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 - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos;
float fHeight = length(v3Start);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fStartAngle = dot(v3Ray, v3Start) / fHeight;
float fStartOffset = fDepth * scale(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);
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot((v3Ray), v3SamplePoint) / fHeight * 0.99;
float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = v3CameraPos - v3Pos;
float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
outFragColor.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
outFragColor.a = outFragColor.b;
outFragColor.rgb = pow(outFragColor.rgb, vec3(1.0/2.2));
}
*/
!>
<@endif@>

View file

@ -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; }

View file

@ -1,93 +1,93 @@
<!
// Light.slh
// fragment shader
//
// Created by Sam Gateau on 1/25/14.
// Copyright 2013 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
!>
<@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@>
<!
// Light.slh
// fragment shader
//
// Created by Sam Gateau on 1/25/14.
// Copyright 2013 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
!>
<@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@>

View file

@ -1,66 +1,66 @@
<!
// Material.slh
// fragment shader
//
// Created by Sam Gateau on 12/16/14.
// Copyright 2013 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
!>
<@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;
}
<! // TODO: use this code for correct gamma correction
/*
float componentSRGBToLinear(float cs) {
// sRGB to linear conversion
// { cs / 12.92, cs <= 0.04045
// cl = {
// { ((cs + 0.055)/1.055)^2.4, cs > 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@>
<!
// Material.slh
// fragment shader
//
// Created by Sam Gateau on 12/16/14.
// Copyright 2013 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
!>
<@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;
}
<! // TODO: use this code for correct gamma correction
/*
float componentSRGBToLinear(float cs) {
// sRGB to linear conversion
// { cs / 12.92, cs <= 0.04045
// cl = {
// { ((cs + 0.055)/1.055)^2.4, cs > 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@>

View file

@ -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 <glm/gtx/transform.hpp>
#include <math.h>
#include <qcompilerdetection.h>
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<gpu::Buffer>(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<float>();
data._scatterings.w = getMieScattering() * 4.0f * glm::pi<float>();
}
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<Light>()),
_skybox(std::make_shared<Skybox>())
{
_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 <glm/gtx/transform.hpp>
#include <math.h>
#include <qcompilerdetection.h>
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<gpu::Buffer>(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<float>();
data._scatterings.w = getMieScattering() * 4.0f * glm::pi<float>();
}
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<Light>()),
_skybox(std::make_shared<Skybox>())
{
_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();
}

View file

@ -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>(); }
Data& editData() { return _dataBuffer.edit<Data>(); }
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>(); }
Data& editData() { return _dataBuffer.edit<Data>(); }
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

View file

@ -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 <QtCore/QDebug>
#include <stdio.h>
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 <QtCore/QDebug>
#include <stdio.h>
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);
}

View file

@ -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 <glm/glm.hpp>
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 <glm/glm.hpp>
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

View file

@ -16,66 +16,66 @@
#include <ViewFrustum.h>
#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<gpu::Buffer>(sizeof(vertices), (const gpu::Byte*) vertices);
theFormat = std::make_shared<gpu::Stream::Format>();
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<gpu::Buffer>(sizeof(vertices), (const gpu::Byte*) vertices);
theFormat = std::make_shared<gpu::Stream::Format>();
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);
}
}

View file

@ -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);