mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 11:07:07 +02:00
Merge pull request #4636 from samcake/orange
Introduce the gpu::Framebuffer and its sidekick the gpu::Swapchain
This commit is contained in:
commit
d72bb71030
25 changed files with 1243 additions and 454 deletions
|
@ -35,7 +35,6 @@
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkDiskCache>
|
#include <QNetworkDiskCache>
|
||||||
#include <QOpenGLFramebufferObject>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
@ -802,7 +801,7 @@ void Application::paintGL() {
|
||||||
DependencyManager::get<GlowEffect>()->prepare();
|
DependencyManager::get<GlowEffect>()->prepare();
|
||||||
|
|
||||||
// Viewport is assigned to the size of the framebuffer
|
// Viewport is assigned to the size of the framebuffer
|
||||||
QSize size = DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject()->size();
|
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||||
glViewport(0, 0, size.width(), size.height());
|
glViewport(0, 0, size.width(), size.height());
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
@ -2642,8 +2641,9 @@ void Application::updateShadowMap() {
|
||||||
activeRenderingThread = QThread::currentThread();
|
activeRenderingThread = QThread::currentThread();
|
||||||
|
|
||||||
PerformanceTimer perfTimer("shadowMap");
|
PerformanceTimer perfTimer("shadowMap");
|
||||||
QOpenGLFramebufferObject* fbo = DependencyManager::get<TextureCache>()->getShadowFramebufferObject();
|
auto shadowFramebuffer = DependencyManager::get<TextureCache>()->getShadowFramebuffer();
|
||||||
fbo->bind();
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(shadowFramebuffer));
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
@ -2659,16 +2659,18 @@ void Application::updateShadowMap() {
|
||||||
loadViewFrustum(_myCamera, _viewFrustum);
|
loadViewFrustum(_myCamera, _viewFrustum);
|
||||||
|
|
||||||
int matrixCount = 1;
|
int matrixCount = 1;
|
||||||
int targetSize = fbo->width();
|
//int targetSize = fbo->width();
|
||||||
|
int sourceSize = shadowFramebuffer->getWidth();
|
||||||
|
int targetSize = shadowFramebuffer->getWidth();
|
||||||
float targetScale = 1.0f;
|
float targetScale = 1.0f;
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
|
||||||
matrixCount = CASCADED_SHADOW_MATRIX_COUNT;
|
matrixCount = CASCADED_SHADOW_MATRIX_COUNT;
|
||||||
targetSize = fbo->width() / 2;
|
targetSize = sourceSize / 2;
|
||||||
targetScale = 0.5f;
|
targetScale = 0.5f;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < matrixCount; i++) {
|
for (int i = 0; i < matrixCount; i++) {
|
||||||
const glm::vec2& coord = MAP_COORDS[i];
|
const glm::vec2& coord = MAP_COORDS[i];
|
||||||
glViewport(coord.s * fbo->width(), coord.t * fbo->height(), targetSize, targetSize);
|
glViewport(coord.s * sourceSize, coord.t * sourceSize, targetSize, targetSize);
|
||||||
|
|
||||||
// if simple shadow then since the resolution is twice as much as with cascaded, cover 2 regions with the map, not just one
|
// if simple shadow then since the resolution is twice as much as with cascaded, cover 2 regions with the map, not just one
|
||||||
int regionIncrement = (matrixCount == 1 ? 2 : 1);
|
int regionIncrement = (matrixCount == 1 ? 2 : 1);
|
||||||
|
@ -2791,7 +2793,7 @@ void Application::updateShadowMap() {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
fbo->release();
|
// fbo->release();
|
||||||
|
|
||||||
glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
|
glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
|
||||||
activeRenderingThread = nullptr;
|
activeRenderingThread = nullptr;
|
||||||
|
@ -2837,7 +2839,8 @@ PickRay Application::computePickRay(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Application::renderAvatarBillboard() {
|
QImage Application::renderAvatarBillboard() {
|
||||||
DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject()->bind();
|
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
||||||
|
|
||||||
// the "glow" here causes an alpha of one
|
// the "glow" here causes an alpha of one
|
||||||
Glower glower;
|
Glower glower;
|
||||||
|
@ -2850,7 +2853,7 @@ QImage Application::renderAvatarBillboard() {
|
||||||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||||
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
|
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
|
||||||
|
|
||||||
DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject()->release();
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QOpenGLFramebufferObject>
|
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QOpenGLTimerQuery>
|
#include <QOpenGLTimerQuery>
|
||||||
|
|
||||||
|
@ -35,6 +34,8 @@
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include <gpu/GLBackend.h>
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void for_each_eye(Function function) {
|
void for_each_eye(Function function) {
|
||||||
for (ovrEyeType eye = ovrEyeType::ovrEye_Left;
|
for (ovrEyeType eye = ovrEyeType::ovrEye_Left;
|
||||||
|
@ -530,7 +531,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
||||||
DependencyManager::get<GlowEffect>()->prepare();
|
DependencyManager::get<GlowEffect>()->prepare();
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject()->bind();
|
auto primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFBO));
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,15 +623,15 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
QOpenGLFramebufferObject * finalFbo = nullptr;
|
gpu::FramebufferPointer finalFbo;
|
||||||
//Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture
|
//Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
||||||
//Full texture viewport for glow effect
|
//Full texture viewport for glow effect
|
||||||
glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h);
|
glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h);
|
||||||
finalFbo = DependencyManager::get<GlowEffect>()->render(true);
|
finalFbo = DependencyManager::get<GlowEffect>()->render(true);
|
||||||
} else {
|
} else {
|
||||||
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject();
|
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||||
finalFbo->release();
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
@ -653,7 +655,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
|
||||||
//Left over from when OR was not connected.
|
//Left over from when OR was not connected.
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, finalFbo->texture());
|
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)));
|
||||||
|
|
||||||
//Renders the distorted mesh onto the screen
|
//Renders the distorted mesh onto the screen
|
||||||
renderDistortionMesh(eyeRenderPose);
|
renderDistortionMesh(eyeRenderPose);
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
#include <QOpenGLFramebufferObject>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include <GlowEffect.h>
|
#include <GlowEffect.h>
|
||||||
|
|
|
@ -25,7 +25,8 @@ Batch::Batch() :
|
||||||
_textures(),
|
_textures(),
|
||||||
_streamFormats(),
|
_streamFormats(),
|
||||||
_transforms(),
|
_transforms(),
|
||||||
_pipelines()
|
_pipelines(),
|
||||||
|
_framebuffers()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,8 @@ void Batch::clear() {
|
||||||
_textures.clear();
|
_textures.clear();
|
||||||
_streamFormats.clear();
|
_streamFormats.clear();
|
||||||
_transforms.clear();
|
_transforms.clear();
|
||||||
_pipelines.clear();
|
_pipelines.clear();
|
||||||
|
_framebuffers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Batch::cacheData(uint32 size, const void* data) {
|
uint32 Batch::cacheData(uint32 size, const void* data) {
|
||||||
|
@ -186,3 +188,10 @@ void Batch::setUniformTexture(uint32 slot, const TextureView& view) {
|
||||||
setUniformTexture(slot, view._texture);
|
setUniformTexture(slot, view._texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::setFramebuffer(const FramebufferPointer& framebuffer) {
|
||||||
|
ADD_COMMAND(setUniformTexture);
|
||||||
|
|
||||||
|
_params.push_back(_framebuffers.cache(framebuffer));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "Pipeline.h"
|
#include "Pipeline.h"
|
||||||
|
|
||||||
|
#include "Framebuffer.h"
|
||||||
|
|
||||||
#if defined(NSIGHT_FOUND)
|
#if defined(NSIGHT_FOUND)
|
||||||
#include "nvToolsExt.h"
|
#include "nvToolsExt.h"
|
||||||
class ProfileRange {
|
class ProfileRange {
|
||||||
|
@ -112,6 +114,8 @@ public:
|
||||||
void setUniformTexture(uint32 slot, const TexturePointer& view);
|
void setUniformTexture(uint32 slot, const TexturePointer& view);
|
||||||
void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
|
void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
|
||||||
|
|
||||||
|
// Framebuffer Stage
|
||||||
|
void setFramebuffer(const FramebufferPointer& framebuffer);
|
||||||
|
|
||||||
// TODO: As long as we have gl calls explicitely issued from interface
|
// TODO: As long as we have gl calls explicitely issued from interface
|
||||||
// code, we need to be able to record and batch these calls. THe long
|
// code, we need to be able to record and batch these calls. THe long
|
||||||
|
@ -170,6 +174,8 @@ public:
|
||||||
COMMAND_setUniformBuffer,
|
COMMAND_setUniformBuffer,
|
||||||
COMMAND_setUniformTexture,
|
COMMAND_setUniformTexture,
|
||||||
|
|
||||||
|
COMMAND_setFramebuffer,
|
||||||
|
|
||||||
// TODO: As long as we have gl calls explicitely issued from interface
|
// TODO: As long as we have gl calls explicitely issued from interface
|
||||||
// code, we need to be able to record and batch these calls. THe long
|
// code, we need to be able to record and batch these calls. THe long
|
||||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||||
|
@ -266,6 +272,7 @@ public:
|
||||||
typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
|
typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
|
||||||
typedef Cache<Transform>::Vector TransformCaches;
|
typedef Cache<Transform>::Vector TransformCaches;
|
||||||
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
||||||
|
typedef Cache<FramebufferPointer>::Vector FramebufferCaches;
|
||||||
|
|
||||||
// Cache Data in a byte array if too big to fit in Param
|
// Cache Data in a byte array if too big to fit in Param
|
||||||
// FOr example Mat4s are going there
|
// FOr example Mat4s are going there
|
||||||
|
@ -289,6 +296,7 @@ public:
|
||||||
StreamFormatCaches _streamFormats;
|
StreamFormatCaches _streamFormats;
|
||||||
TransformCaches _transforms;
|
TransformCaches _transforms;
|
||||||
PipelineCaches _pipelines;
|
PipelineCaches _pipelines;
|
||||||
|
FramebufferCaches _framebuffers;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
#include "Shader.h"
|
|
||||||
#include "Pipeline.h"
|
#include "Pipeline.h"
|
||||||
|
#include "Framebuffer.h"
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static void setGPUObject(const Buffer& buffer, T* bo) {
|
static void setGPUObject(const Buffer& buffer, T* object) {
|
||||||
buffer.setGPUObject(bo);
|
buffer.setGPUObject(object);
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static T* getGPUObject(const Buffer& buffer) {
|
static T* getGPUObject(const Buffer& buffer) {
|
||||||
|
@ -56,8 +56,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static void setGPUObject(const Texture& texture, T* to) {
|
static void setGPUObject(const Texture& texture, T* object) {
|
||||||
texture.setGPUObject(to);
|
texture.setGPUObject(object);
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static T* getGPUObject(const Texture& texture) {
|
static T* getGPUObject(const Texture& texture) {
|
||||||
|
@ -65,8 +65,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static void setGPUObject(const Shader& shader, T* so) {
|
static void setGPUObject(const Shader& shader, T* object) {
|
||||||
shader.setGPUObject(so);
|
shader.setGPUObject(object);
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static T* getGPUObject(const Shader& shader) {
|
static T* getGPUObject(const Shader& shader) {
|
||||||
|
@ -74,8 +74,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static void setGPUObject(const Pipeline& pipeline, T* po) {
|
static void setGPUObject(const Pipeline& pipeline, T* object) {
|
||||||
pipeline.setGPUObject(po);
|
pipeline.setGPUObject(object);
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static T* getGPUObject(const Pipeline& pipeline) {
|
static T* getGPUObject(const Pipeline& pipeline) {
|
||||||
|
@ -83,14 +83,23 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static void setGPUObject(const State& state, T* so) {
|
static void setGPUObject(const State& state, T* object) {
|
||||||
state.setGPUObject(so);
|
state.setGPUObject(object);
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static T* getGPUObject(const State& state) {
|
static T* getGPUObject(const State& state) {
|
||||||
return reinterpret_cast<T*>(state.getGPUObject());
|
return reinterpret_cast<T*>(state.getGPUObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
static void setGPUObject(const Framebuffer& framebuffer, T* object) {
|
||||||
|
framebuffer.setGPUObject(object);
|
||||||
|
}
|
||||||
|
template< typename T >
|
||||||
|
static T* getGPUObject(const Framebuffer& framebuffer) {
|
||||||
|
return reinterpret_cast<T*>(framebuffer.getGPUObject());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,6 +34,8 @@ typedef glm::mat3 Mat3;
|
||||||
typedef glm::vec4 Vec4;
|
typedef glm::vec4 Vec4;
|
||||||
typedef glm::vec3 Vec3;
|
typedef glm::vec3 Vec3;
|
||||||
typedef glm::vec2 Vec2;
|
typedef glm::vec2 Vec2;
|
||||||
|
typedef glm::ivec2 Vec2i;
|
||||||
|
typedef glm::uvec2 Vec2u;
|
||||||
|
|
||||||
// Description of a scalar type
|
// Description of a scalar type
|
||||||
enum Type {
|
enum Type {
|
||||||
|
@ -118,7 +120,8 @@ enum Semantic {
|
||||||
INDEX, //used by index buffer of a mesh
|
INDEX, //used by index buffer of a mesh
|
||||||
PART, // used by part buffer of a mesh
|
PART, // used by part buffer of a mesh
|
||||||
|
|
||||||
DEPTH, // Depth buffer
|
DEPTH, // Depth only buffer
|
||||||
|
STENCIL, // Stencil only buffer
|
||||||
DEPTH_STENCIL, // Depth Stencil buffer
|
DEPTH_STENCIL, // Depth Stencil buffer
|
||||||
|
|
||||||
SRGB,
|
SRGB,
|
||||||
|
@ -171,12 +174,28 @@ public:
|
||||||
return getRaw() != right.getRaw();
|
return getRaw() != right.getRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const Element COLOR_RGBA_32;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8 _semantic;
|
uint8 _semantic;
|
||||||
uint8 _dimension : 4;
|
uint8 _dimension : 4;
|
||||||
uint8 _type : 4;
|
uint8 _type : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum ComparisonFunction {
|
||||||
|
NEVER = 0,
|
||||||
|
LESS,
|
||||||
|
EQUAL,
|
||||||
|
LESS_EQUAL,
|
||||||
|
GREATER,
|
||||||
|
NOT_EQUAL,
|
||||||
|
GREATER_EQUAL,
|
||||||
|
ALWAYS,
|
||||||
|
|
||||||
|
NUM_COMPARISON_FUNCS,
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
279
libraries/gpu/src/gpu/Framebuffer.cpp
Executable file
279
libraries/gpu/src/gpu/Framebuffer.cpp
Executable file
|
@ -0,0 +1,279 @@
|
||||||
|
//
|
||||||
|
// Framebuffer.cpp
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#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) {
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
164
libraries/gpu/src/gpu/Framebuffer.h
Executable file
164
libraries/gpu/src/gpu/Framebuffer.h
Executable file
|
@ -0,0 +1,164 @@
|
||||||
|
//
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
~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
|
||||||
|
uint32 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 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;
|
||||||
|
|
||||||
|
uint32 _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) {}
|
||||||
|
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
|
|
@ -32,6 +32,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::GLBackend::do_setUniformBuffer),
|
(&::gpu::GLBackend::do_setUniformBuffer),
|
||||||
(&::gpu::GLBackend::do_setUniformTexture),
|
(&::gpu::GLBackend::do_setUniformTexture),
|
||||||
|
|
||||||
|
(&::gpu::GLBackend::do_setFramebuffer),
|
||||||
|
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_glEnable),
|
(&::gpu::GLBackend::do_glEnable),
|
||||||
(&::gpu::GLBackend::do_glDisable),
|
(&::gpu::GLBackend::do_glDisable),
|
||||||
|
|
||||||
|
@ -67,7 +70,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
GLBackend::GLBackend() :
|
GLBackend::GLBackend() :
|
||||||
_input(),
|
_input(),
|
||||||
_transform(),
|
_transform(),
|
||||||
_pipeline()
|
_pipeline(),
|
||||||
|
_output()
|
||||||
{
|
{
|
||||||
initTransform();
|
initTransform();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
Stamp _storageStamp;
|
Stamp _storageStamp;
|
||||||
Stamp _contentStamp;
|
Stamp _contentStamp;
|
||||||
GLuint _texture;
|
GLuint _texture;
|
||||||
|
GLenum _target;
|
||||||
GLuint _size;
|
GLuint _size;
|
||||||
|
|
||||||
GLTexture();
|
GLTexture();
|
||||||
|
@ -61,6 +62,9 @@ public:
|
||||||
static GLTexture* syncGPUObject(const Texture& texture);
|
static GLTexture* syncGPUObject(const Texture& texture);
|
||||||
static GLuint getTextureID(const TexturePointer& texture);
|
static GLuint getTextureID(const TexturePointer& texture);
|
||||||
|
|
||||||
|
// very specific for now
|
||||||
|
static void syncSampler(const Sampler& sampler, Texture::Type type, GLTexture* object);
|
||||||
|
|
||||||
class GLShader : public GPUObject {
|
class GLShader : public GPUObject {
|
||||||
public:
|
public:
|
||||||
GLuint _shader;
|
GLuint _shader;
|
||||||
|
@ -133,14 +137,25 @@ public:
|
||||||
|
|
||||||
class GLPipeline : public GPUObject {
|
class GLPipeline : public GPUObject {
|
||||||
public:
|
public:
|
||||||
GLShader* _program;
|
GLShader* _program = 0;
|
||||||
GLState* _state;
|
GLState* _state = 0;
|
||||||
|
|
||||||
GLPipeline();
|
GLPipeline();
|
||||||
~GLPipeline();
|
~GLPipeline();
|
||||||
};
|
};
|
||||||
static GLPipeline* syncGPUObject(const Pipeline& pipeline);
|
static GLPipeline* syncGPUObject(const Pipeline& pipeline);
|
||||||
|
|
||||||
|
|
||||||
|
class GLFramebuffer : public GPUObject {
|
||||||
|
public:
|
||||||
|
GLuint _fbo = 0;
|
||||||
|
|
||||||
|
GLFramebuffer();
|
||||||
|
~GLFramebuffer();
|
||||||
|
};
|
||||||
|
static GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer);
|
||||||
|
static GLuint getFramebufferID(const FramebufferPointer& framebuffer);
|
||||||
|
|
||||||
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
|
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
|
||||||
static const int MAX_NUM_INPUT_BUFFERS = 16;
|
static const int MAX_NUM_INPUT_BUFFERS = 16;
|
||||||
|
|
||||||
|
@ -276,8 +291,8 @@ protected:
|
||||||
State::Signature _stateSignatureCache;
|
State::Signature _stateSignatureCache;
|
||||||
|
|
||||||
GLState* _state;
|
GLState* _state;
|
||||||
bool _invalidState;
|
bool _invalidState = false;
|
||||||
bool _needStateSync;
|
bool _needStateSync = true;
|
||||||
|
|
||||||
PipelineStageState() :
|
PipelineStageState() :
|
||||||
_pipeline(),
|
_pipeline(),
|
||||||
|
@ -291,6 +306,16 @@ protected:
|
||||||
{}
|
{}
|
||||||
} _pipeline;
|
} _pipeline;
|
||||||
|
|
||||||
|
// Output stage
|
||||||
|
void do_setFramebuffer(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
|
struct OutputStageState {
|
||||||
|
|
||||||
|
FramebufferPointer _framebuffer = nullptr;
|
||||||
|
|
||||||
|
OutputStageState() {}
|
||||||
|
} _output;
|
||||||
|
|
||||||
// TODO: As long as we have gl calls explicitely issued from interface
|
// TODO: As long as we have gl calls explicitely issued from interface
|
||||||
// code, we need to be able to record and batch these calls. THe long
|
// code, we need to be able to record and batch these calls. THe long
|
||||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||||
|
|
157
libraries/gpu/src/gpu/GLBackendOutput.cpp
Executable file
157
libraries/gpu/src/gpu/GLBackendOutput.cpp
Executable file
|
@ -0,0 +1,157 @@
|
||||||
|
//
|
||||||
|
// GLBackendTexture.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 1/19/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 "GPULogging.h"
|
||||||
|
#include "GLBackendShared.h"
|
||||||
|
|
||||||
|
|
||||||
|
GLBackend::GLFramebuffer::GLFramebuffer() {}
|
||||||
|
|
||||||
|
GLBackend::GLFramebuffer::~GLFramebuffer() {
|
||||||
|
if (_fbo != 0) {
|
||||||
|
glDeleteFramebuffers(1, &_fbo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffer) {
|
||||||
|
GLFramebuffer* object = Backend::getGPUObject<GLBackend::GLFramebuffer>(framebuffer);
|
||||||
|
|
||||||
|
// If GPU object already created and in sync
|
||||||
|
bool needUpdate = false;
|
||||||
|
if (object) {
|
||||||
|
return object;
|
||||||
|
} else if (framebuffer.isEmpty()) {
|
||||||
|
// NO framebuffer definition yet so let's avoid thinking
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to have a gpu object?
|
||||||
|
if (!object) {
|
||||||
|
GLuint fbo;
|
||||||
|
glGenFramebuffers(1, &fbo);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
|
unsigned int nbColorBuffers = 0;
|
||||||
|
GLenum colorBuffers[16];
|
||||||
|
if (framebuffer.hasColor()) {
|
||||||
|
static const GLenum colorAttachments[] = {
|
||||||
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_COLOR_ATTACHMENT1,
|
||||||
|
GL_COLOR_ATTACHMENT2,
|
||||||
|
GL_COLOR_ATTACHMENT3,
|
||||||
|
GL_COLOR_ATTACHMENT4,
|
||||||
|
GL_COLOR_ATTACHMENT5,
|
||||||
|
GL_COLOR_ATTACHMENT6,
|
||||||
|
GL_COLOR_ATTACHMENT7,
|
||||||
|
GL_COLOR_ATTACHMENT8,
|
||||||
|
GL_COLOR_ATTACHMENT9,
|
||||||
|
GL_COLOR_ATTACHMENT10,
|
||||||
|
GL_COLOR_ATTACHMENT11,
|
||||||
|
GL_COLOR_ATTACHMENT12,
|
||||||
|
GL_COLOR_ATTACHMENT13,
|
||||||
|
GL_COLOR_ATTACHMENT14,
|
||||||
|
GL_COLOR_ATTACHMENT15 };
|
||||||
|
|
||||||
|
int unit = 0;
|
||||||
|
for (auto& b : framebuffer.getRenderBuffers()) {
|
||||||
|
auto surface = b._texture;
|
||||||
|
if (surface) {
|
||||||
|
auto gltexture = GLBackend::syncGPUObject(*surface);
|
||||||
|
if (gltexture) {
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[unit], GL_TEXTURE_2D, gltexture->_texture, 0);
|
||||||
|
}
|
||||||
|
colorBuffers[nbColorBuffers] = colorAttachments[unit];
|
||||||
|
nbColorBuffers++;
|
||||||
|
unit++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framebuffer.hasDepthStencil()) {
|
||||||
|
auto surface = framebuffer.getDepthStencilBuffer();
|
||||||
|
if (surface) {
|
||||||
|
auto gltexture = GLBackend::syncGPUObject(*surface);
|
||||||
|
if (gltexture) {
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gltexture->_texture, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last but not least, define where we draw
|
||||||
|
if (nbColorBuffers > 0) {
|
||||||
|
glDrawBuffers(nbColorBuffers, colorBuffers);
|
||||||
|
} else {
|
||||||
|
glDrawBuffer( GL_NONE );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check for completness
|
||||||
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
bool result = false;
|
||||||
|
switch (status) {
|
||||||
|
case GL_FRAMEBUFFER_COMPLETE :
|
||||||
|
// Success !
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT :
|
||||||
|
qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT.";
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :
|
||||||
|
qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT.";
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER :
|
||||||
|
qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER.";
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER :
|
||||||
|
qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER.";
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_UNSUPPORTED :
|
||||||
|
qCDebug(gpulogging) << "GLFramebuffer::syncGPUObject : Framebuffer not valid, GL_FRAMEBUFFER_UNSUPPORTED.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!result && fbo) {
|
||||||
|
glDeleteFramebuffers( 1, &fbo );
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// All is green, assign the gpuobject to the Framebuffer
|
||||||
|
object = new GLFramebuffer();
|
||||||
|
object->_fbo = fbo;
|
||||||
|
Backend::setGPUObject(framebuffer, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLuint GLBackend::getFramebufferID(const FramebufferPointer& framebuffer) {
|
||||||
|
if (!framebuffer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
GLFramebuffer* object = GLBackend::syncGPUObject(*framebuffer);
|
||||||
|
if (object) {
|
||||||
|
return object->_fbo;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) {
|
||||||
|
auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
|
||||||
|
|
||||||
|
if (_output._framebuffer != framebuffer) {
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(framebuffer));
|
||||||
|
_output._framebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -237,26 +237,26 @@ void GLBackend::resetPipelineState(State::Signature nextSignature) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
State::ComparisonFunction comparisonFuncFromGL(GLenum func) {
|
ComparisonFunction comparisonFuncFromGL(GLenum func) {
|
||||||
if (func == GL_NEVER) {
|
if (func == GL_NEVER) {
|
||||||
return State::NEVER;
|
return NEVER;
|
||||||
} else if (func == GL_LESS) {
|
} else if (func == GL_LESS) {
|
||||||
return State::LESS;
|
return LESS;
|
||||||
} else if (func == GL_EQUAL) {
|
} else if (func == GL_EQUAL) {
|
||||||
return State::EQUAL;
|
return EQUAL;
|
||||||
} else if (func == GL_LEQUAL) {
|
} else if (func == GL_LEQUAL) {
|
||||||
return State::LESS_EQUAL;
|
return LESS_EQUAL;
|
||||||
} else if (func == GL_GREATER) {
|
} else if (func == GL_GREATER) {
|
||||||
return State::GREATER;
|
return GREATER;
|
||||||
} else if (func == GL_NOTEQUAL) {
|
} else if (func == GL_NOTEQUAL) {
|
||||||
return State::NOT_EQUAL;
|
return NOT_EQUAL;
|
||||||
} else if (func == GL_GEQUAL) {
|
} else if (func == GL_GEQUAL) {
|
||||||
return State::GREATER_EQUAL;
|
return GREATER_EQUAL;
|
||||||
} else if (func == GL_ALWAYS) {
|
} else if (func == GL_ALWAYS) {
|
||||||
return State::ALWAYS;
|
return ALWAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return State::ALWAYS;
|
return ALWAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
State::StencilOp stencilOpFromGL(GLenum stencilOp) {
|
State::StencilOp stencilOpFromGL(GLenum stencilOp) {
|
||||||
|
|
|
@ -16,7 +16,8 @@ GLBackend::GLTexture::GLTexture() :
|
||||||
_storageStamp(0),
|
_storageStamp(0),
|
||||||
_contentStamp(0),
|
_contentStamp(0),
|
||||||
_texture(0),
|
_texture(0),
|
||||||
_size(0)
|
_size(0),
|
||||||
|
_target(GL_TEXTURE_2D)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
GLBackend::GLTexture::~GLTexture() {
|
GLBackend::GLTexture::~GLTexture() {
|
||||||
|
@ -144,7 +145,38 @@ public:
|
||||||
texel.internalFormat = GL_RED;
|
texel.internalFormat = GL_RED;
|
||||||
break;
|
break;
|
||||||
case gpu::DEPTH:
|
case gpu::DEPTH:
|
||||||
|
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
|
||||||
texel.internalFormat = GL_DEPTH_COMPONENT;
|
texel.internalFormat = GL_DEPTH_COMPONENT;
|
||||||
|
switch (dstFormat.getType()) {
|
||||||
|
case gpu::UINT32:
|
||||||
|
case gpu::INT32:
|
||||||
|
case gpu::NUINT32:
|
||||||
|
case gpu::NINT32: {
|
||||||
|
texel.internalFormat = GL_DEPTH_COMPONENT32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NFLOAT:
|
||||||
|
case gpu::FLOAT: {
|
||||||
|
texel.internalFormat = GL_DEPTH_COMPONENT32F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::UINT16:
|
||||||
|
case gpu::INT16:
|
||||||
|
case gpu::NUINT16:
|
||||||
|
case gpu::NINT16:
|
||||||
|
case gpu::HALF:
|
||||||
|
case gpu::NHALF: {
|
||||||
|
texel.internalFormat = GL_DEPTH_COMPONENT16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::UINT8:
|
||||||
|
case gpu::INT8:
|
||||||
|
case gpu::NUINT8:
|
||||||
|
case gpu::NINT8: {
|
||||||
|
texel.internalFormat = GL_DEPTH_COMPONENT24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qCDebug(gpulogging) << "Unknown combination of texel format";
|
qCDebug(gpulogging) << "Unknown combination of texel format";
|
||||||
|
@ -254,66 +286,77 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
// GO through the process of allocating the correct storage and/or update the content
|
// GO through the process of allocating the correct storage and/or update the content
|
||||||
switch (texture.getType()) {
|
switch (texture.getType()) {
|
||||||
case Texture::TEX_2D: {
|
case Texture::TEX_2D: {
|
||||||
if (needUpdate) {
|
if (texture.getNumSlices() == 1) {
|
||||||
if (texture.isStoredMipAvailable(0)) {
|
|
||||||
GLint boundTex = -1;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
|
|
||||||
|
|
||||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
|
||||||
const GLvoid* bytes = mip->_sysmem.read<Resource::Byte>();
|
|
||||||
Element srcFormat = mip->_format;
|
|
||||||
|
|
||||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
|
||||||
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
|
||||||
texelFormat.format, texelFormat.type, bytes);
|
|
||||||
|
|
||||||
if (texture.isAutogenerateMips()) {
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point the mip piels have been loaded, we can notify
|
|
||||||
texture.notifyGPULoaded(0);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, boundTex);
|
|
||||||
object->_contentStamp = texture.getDataStamp();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const GLvoid* bytes = 0;
|
|
||||||
Element srcFormat = texture.getTexelFormat();
|
|
||||||
if (texture.isStoredMipAvailable(0)) {
|
|
||||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
|
||||||
|
|
||||||
bytes = mip->_sysmem.read<Resource::Byte>();
|
|
||||||
srcFormat = mip->_format;
|
|
||||||
|
|
||||||
object->_contentStamp = texture.getDataStamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLint boundTex = -1;
|
GLint boundTex = -1;
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
|
||||||
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
||||||
|
|
||||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
if (needUpdate) {
|
||||||
|
if (texture.isStoredMipAvailable(0)) {
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
||||||
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
const GLvoid* bytes = mip->_sysmem.read<Resource::Byte>();
|
||||||
texelFormat.format, texelFormat.type, bytes);
|
Element srcFormat = mip->_format;
|
||||||
|
|
||||||
|
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
||||||
|
|
||||||
if (bytes && texture.isAutogenerateMips()) {
|
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
||||||
|
texelFormat.format, texelFormat.type, bytes);
|
||||||
|
|
||||||
|
if (texture.isAutogenerateMips()) {
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
object->_target = GL_TEXTURE_2D;
|
||||||
|
|
||||||
|
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||||
|
|
||||||
|
|
||||||
|
// At this point the mip piels have been loaded, we can notify
|
||||||
|
texture.notifyGPULoaded(0);
|
||||||
|
|
||||||
|
object->_contentStamp = texture.getDataStamp();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const GLvoid* bytes = 0;
|
||||||
|
Element srcFormat = texture.getTexelFormat();
|
||||||
|
if (texture.isStoredMipAvailable(0)) {
|
||||||
|
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
||||||
|
|
||||||
|
bytes = mip->_sysmem.read<Resource::Byte>();
|
||||||
|
srcFormat = mip->_format;
|
||||||
|
|
||||||
|
object->_contentStamp = texture.getDataStamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||||
|
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
||||||
|
texelFormat.format, texelFormat.type, bytes);
|
||||||
|
|
||||||
|
if (bytes && texture.isAutogenerateMips()) {
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
} else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
object->_target = GL_TEXTURE_2D;
|
||||||
|
|
||||||
|
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||||
|
|
||||||
|
// At this point the mip piels have been loaded, we can notify
|
||||||
|
texture.notifyGPULoaded(0);
|
||||||
|
|
||||||
|
object->_storageStamp = texture.getStamp();
|
||||||
|
object->_size = texture.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point the mip piels have been loaded, we can notify
|
|
||||||
texture.notifyGPULoaded(0);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, boundTex);
|
glBindTexture(GL_TEXTURE_2D, boundTex);
|
||||||
object->_storageStamp = texture.getStamp();
|
|
||||||
object->_size = texture.getSize();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -339,3 +382,70 @@ GLuint GLBackend::getTextureID(const TexturePointer& texture) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, GLTexture* object) {
|
||||||
|
if (!object) return;
|
||||||
|
if (!object->_texture) return;
|
||||||
|
|
||||||
|
class GLFilterMode {
|
||||||
|
public:
|
||||||
|
GLint minFilter;
|
||||||
|
GLint magFilter;
|
||||||
|
};
|
||||||
|
static const GLFilterMode filterModes[] = {
|
||||||
|
{GL_NEAREST, GL_NEAREST}, //FILTER_MIN_MAG_POINT,
|
||||||
|
{GL_NEAREST, GL_LINEAR}, //FILTER_MIN_POINT_MAG_LINEAR,
|
||||||
|
{GL_LINEAR, GL_NEAREST}, //FILTER_MIN_LINEAR_MAG_POINT,
|
||||||
|
{GL_LINEAR, GL_LINEAR}, //FILTER_MIN_MAG_LINEAR,
|
||||||
|
|
||||||
|
{GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, //FILTER_MIN_MAG_MIP_POINT,
|
||||||
|
{GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, //FILTER_MIN_MAG_MIP_POINT,
|
||||||
|
{GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, //FILTER_MIN_MAG_POINT_MIP_LINEAR,
|
||||||
|
{GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR}, //FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
|
||||||
|
{GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR}, //FILTER_MIN_POINT_MAG_MIP_LINEAR,
|
||||||
|
{GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST}, //FILTER_MIN_LINEAR_MAG_MIP_POINT,
|
||||||
|
{GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST}, //FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
|
||||||
|
{GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, //FILTER_MIN_MAG_LINEAR_MIP_POINT,
|
||||||
|
{GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}, //FILTER_MIN_MAG_MIP_LINEAR,
|
||||||
|
{GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} //FILTER_ANISOTROPIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto fm = filterModes[sampler.getFilter()];
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_MAG_FILTER, fm.magFilter);
|
||||||
|
|
||||||
|
static const GLenum comparisonFuncs[] = {
|
||||||
|
GL_NEVER,
|
||||||
|
GL_LESS,
|
||||||
|
GL_EQUAL,
|
||||||
|
GL_LEQUAL,
|
||||||
|
GL_GREATER,
|
||||||
|
GL_NOTEQUAL,
|
||||||
|
GL_GEQUAL,
|
||||||
|
GL_ALWAYS };
|
||||||
|
|
||||||
|
if (sampler.doComparison()) {
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_COMPARE_FUNC, comparisonFuncs[sampler.getComparisonFunction()]);
|
||||||
|
} else {
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GLenum wrapModes[] = {
|
||||||
|
GL_REPEAT, // WRAP_REPEAT,
|
||||||
|
GL_MIRRORED_REPEAT, // WRAP_MIRROR,
|
||||||
|
GL_CLAMP_TO_EDGE, // WRAP_CLAMP,
|
||||||
|
GL_CLAMP_TO_BORDER, // WRAP_BORDER,
|
||||||
|
GL_MIRROR_CLAMP_TO_EDGE_EXT }; // WRAP_MIRROR_ONCE,
|
||||||
|
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_WRAP_S, wrapModes[sampler.getWrapModeU()]);
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_WRAP_T, wrapModes[sampler.getWrapModeV()]);
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_WRAP_R, wrapModes[sampler.getWrapModeW()]);
|
||||||
|
|
||||||
|
glTexParameterfv(object->_target, GL_TEXTURE_BORDER_COLOR, (const float*) &sampler.getBorderColor());
|
||||||
|
glTexParameteri(object->_target, GL_TEXTURE_BASE_LEVEL, sampler.getMipOffset());
|
||||||
|
glTexParameterf(object->_target, GL_TEXTURE_MIN_LOD, (float) sampler.getMinMip());
|
||||||
|
glTexParameterf(object->_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
|
glTexParameterf(object->_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
|
||||||
|
const Element Element::COLOR_RGBA_32 = Element(VEC4, UINT8, RGBA);
|
||||||
|
|
||||||
Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) {
|
Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) {
|
||||||
if ( !dataAllocated ) {
|
if ( !dataAllocated ) {
|
||||||
qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer.";
|
qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer.";
|
||||||
|
|
|
@ -42,19 +42,8 @@ public:
|
||||||
virtual ~State();
|
virtual ~State();
|
||||||
|
|
||||||
const Stamp getStamp() const { return _stamp; }
|
const Stamp getStamp() const { return _stamp; }
|
||||||
|
|
||||||
enum ComparisonFunction {
|
typedef ::gpu::ComparisonFunction ComparisonFunction;
|
||||||
NEVER = 0,
|
|
||||||
LESS,
|
|
||||||
EQUAL,
|
|
||||||
LESS_EQUAL,
|
|
||||||
GREATER,
|
|
||||||
NOT_EQUAL,
|
|
||||||
GREATER_EQUAL,
|
|
||||||
ALWAYS,
|
|
||||||
|
|
||||||
NUM_COMPARISON_FUNCS,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FillMode {
|
enum FillMode {
|
||||||
FILL_POINT = 0,
|
FILL_POINT = 0,
|
||||||
|
@ -415,5 +404,4 @@ typedef std::vector< StatePointer > States;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -93,23 +93,23 @@ bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size s
|
||||||
return allocated == size;
|
return allocated == size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Texture::create1D(const Element& texelFormat, uint16 width) {
|
Texture* Texture::create1D(const Element& texelFormat, uint16 width, const Sampler& sampler) {
|
||||||
return create(TEX_1D, texelFormat, width, 1, 1, 1, 1);
|
return create(TEX_1D, texelFormat, width, 1, 1, 1, 1, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height) {
|
Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler) {
|
||||||
return create(TEX_2D, texelFormat, width, height, 1, 1, 1);
|
return create(TEX_2D, texelFormat, width, height, 1, 1, 1, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth) {
|
Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler) {
|
||||||
return create(TEX_3D, texelFormat, width, height, depth, 1, 1);
|
return create(TEX_3D, texelFormat, width, height, depth, 1, 1, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Texture::createCube(const Element& texelFormat, uint16 width) {
|
Texture* Texture::createCube(const Element& texelFormat, uint16 width, const Sampler& sampler) {
|
||||||
return create(TEX_CUBE, texelFormat, width, width, 1, 1, 1);
|
return create(TEX_CUBE, texelFormat, width, width, 1, 1, 1, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices)
|
Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler)
|
||||||
{
|
{
|
||||||
Texture* tex = new Texture();
|
Texture* tex = new Texture();
|
||||||
tex->_storage.reset(new Storage());
|
tex->_storage.reset(new Storage());
|
||||||
|
@ -118,6 +118,8 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui
|
||||||
tex->_maxMip = 0;
|
tex->_maxMip = 0;
|
||||||
tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices);
|
tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices);
|
||||||
|
|
||||||
|
tex->_sampler = sampler;
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,3 +348,8 @@ uint16 Texture::evalNumSamplesUsed(uint16 numSamplesTried) {
|
||||||
|
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Texture::setSampler(const Sampler& sampler) {
|
||||||
|
_sampler = sampler;
|
||||||
|
_samplerStamp++;
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,85 @@
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
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 _wrapModeU = WRAP_REPEAT;
|
||||||
|
uint8 _wrapModeV = WRAP_REPEAT;
|
||||||
|
uint8 _wrapModeW = WRAP_REPEAT;
|
||||||
|
|
||||||
|
uint8 _filter = FILTER_MIN_MAG_POINT;
|
||||||
|
uint8 _comparisonFunc = ALWAYS;
|
||||||
|
|
||||||
|
uint8 _mipOffset = 0;
|
||||||
|
uint8 _minMip = 0;
|
||||||
|
uint8 _maxMip = MAX_MIP_LEVEL;
|
||||||
|
|
||||||
|
Desc() {}
|
||||||
|
Desc(const Filter filter) : _filter(filter) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
Sampler() {}
|
||||||
|
Sampler(const Filter filter) : _desc(filter) {}
|
||||||
|
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 {
|
class Texture : public Resource {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -61,10 +140,10 @@ public:
|
||||||
TEX_CUBE,
|
TEX_CUBE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static Texture* create1D(const Element& texelFormat, uint16 width);
|
static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler());
|
||||||
static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height);
|
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);
|
static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler());
|
||||||
static Texture* createCube(const Element& texelFormat, uint16 width);
|
static Texture* createCube(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler());
|
||||||
|
|
||||||
static Texture* createFromStorage(Storage* storage);
|
static Texture* createFromStorage(Storage* storage);
|
||||||
|
|
||||||
|
@ -181,11 +260,21 @@ public:
|
||||||
|
|
||||||
bool isDefined() const { return _defined; }
|
bool isDefined() const { return _defined; }
|
||||||
|
|
||||||
|
|
||||||
|
// Own sampler
|
||||||
|
void setSampler(const Sampler& sampler);
|
||||||
|
const Sampler& getSampler() const { return _sampler; }
|
||||||
|
const Stamp getSamplerStamp() const { return _samplerStamp; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr< Storage > _storage;
|
std::unique_ptr< Storage > _storage;
|
||||||
|
|
||||||
Stamp _stamp;
|
Stamp _stamp;
|
||||||
|
|
||||||
|
Sampler _sampler;
|
||||||
|
Stamp _samplerStamp;
|
||||||
|
|
||||||
|
|
||||||
uint32 _size;
|
uint32 _size;
|
||||||
Element _texelFormat;
|
Element _texelFormat;
|
||||||
|
|
||||||
|
@ -202,7 +291,7 @@ protected:
|
||||||
bool _autoGenerateMips;
|
bool _autoGenerateMips;
|
||||||
bool _defined;
|
bool _defined;
|
||||||
|
|
||||||
static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);
|
static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler);
|
||||||
Texture();
|
Texture();
|
||||||
|
|
||||||
Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);
|
Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);
|
||||||
|
@ -240,15 +329,25 @@ public:
|
||||||
_subresource(0),
|
_subresource(0),
|
||||||
_element(element)
|
_element(element)
|
||||||
{};
|
{};
|
||||||
TextureView(const TexturePointer& texture, const Element& element) :
|
TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) :
|
||||||
_texture(texture),
|
_texture(texture),
|
||||||
_subresource(0),
|
_subresource(subresource),
|
||||||
_element(element)
|
_element(element)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
TextureView(const TexturePointer& texture, uint16 subresource) :
|
||||||
|
_texture(texture),
|
||||||
|
_subresource(subresource)
|
||||||
|
{};
|
||||||
|
|
||||||
~TextureView() {}
|
~TextureView() {}
|
||||||
TextureView(const TextureView& view) = default;
|
TextureView(const TextureView& view) = default;
|
||||||
TextureView& operator=(const TextureView& view) = default;
|
TextureView& operator=(const TextureView& view) = default;
|
||||||
|
|
||||||
|
explicit operator bool() const { return (_texture); }
|
||||||
|
bool operator !() const { return (!_texture); }
|
||||||
};
|
};
|
||||||
|
typedef std::vector<TextureView> TextureViews;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||||
#include <gpu/GPUConfig.h>
|
#include <gpu/GPUConfig.h>
|
||||||
|
|
||||||
#include <QOpenGLFramebufferObject>
|
#include <gpu/GLBackend.h>
|
||||||
|
|
||||||
#include <glm/gtc/random.hpp>
|
#include <glm/gtc/random.hpp>
|
||||||
|
|
||||||
|
@ -107,8 +107,8 @@ void AmbientOcclusionEffect::render() {
|
||||||
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
||||||
|
|
||||||
// render with the occlusion shader to the secondary/tertiary buffer
|
// render with the occlusion shader to the secondary/tertiary buffer
|
||||||
QOpenGLFramebufferObject* freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebufferObject();
|
auto freeFramebuffer = DependencyManager::get<GlowEffect>()->getFreeFramebuffer();
|
||||||
freeFBO->bind();
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFramebuffer));
|
||||||
|
|
||||||
float left, right, bottom, top, nearVal, farVal;
|
float left, right, bottom, top, nearVal, farVal;
|
||||||
glm::vec4 nearClipPlane, farClipPlane;
|
glm::vec4 nearClipPlane, farClipPlane;
|
||||||
|
@ -118,9 +118,10 @@ void AmbientOcclusionEffect::render() {
|
||||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||||
const int VIEWPORT_X_INDEX = 0;
|
const int VIEWPORT_X_INDEX = 0;
|
||||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||||
QOpenGLFramebufferObject* primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject();
|
|
||||||
float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width();
|
auto framebufferSize = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||||
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width();
|
float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width();
|
||||||
|
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width();
|
||||||
|
|
||||||
_occlusionProgram->bind();
|
_occlusionProgram->bind();
|
||||||
_occlusionProgram->setUniformValue(_nearLocation, nearVal);
|
_occlusionProgram->setUniformValue(_nearLocation, nearVal);
|
||||||
|
@ -128,7 +129,7 @@ void AmbientOcclusionEffect::render() {
|
||||||
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
|
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
|
||||||
_occlusionProgram->setUniformValue(_rightTopLocation, right, top);
|
_occlusionProgram->setUniformValue(_rightTopLocation, right, top);
|
||||||
_occlusionProgram->setUniformValue(_noiseScaleLocation, viewport[VIEWPORT_WIDTH_INDEX] / (float)ROTATION_WIDTH,
|
_occlusionProgram->setUniformValue(_noiseScaleLocation, viewport[VIEWPORT_WIDTH_INDEX] / (float)ROTATION_WIDTH,
|
||||||
primaryFBO->height() / (float)ROTATION_HEIGHT);
|
framebufferSize.height() / (float)ROTATION_HEIGHT);
|
||||||
_occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f);
|
_occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f);
|
||||||
_occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f);
|
_occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f);
|
||||||
|
|
||||||
|
@ -136,22 +137,24 @@ void AmbientOcclusionEffect::render() {
|
||||||
|
|
||||||
_occlusionProgram->release();
|
_occlusionProgram->release();
|
||||||
|
|
||||||
freeFBO->release();
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
// now render secondary to primary with 4x4 blur
|
// now render secondary to primary with 4x4 blur
|
||||||
DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject()->bind();
|
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
|
glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
|
auto freeFramebufferTexture = freeFramebuffer->getRenderBuffer(0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFramebufferTexture));
|
||||||
|
|
||||||
_blurProgram->bind();
|
_blurProgram->bind();
|
||||||
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / primaryFBO->width(), 1.0f / primaryFBO->height());
|
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height());
|
||||||
|
|
||||||
renderFullscreenQuad(sMin, sMin + sWidth);
|
renderFullscreenQuad(sMin, sMin + sWidth);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||||
#include <gpu/GPUConfig.h>
|
#include <gpu/GPUConfig.h>
|
||||||
|
|
||||||
#include <QOpenGLFramebufferObject>
|
|
||||||
|
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
@ -183,15 +182,18 @@ void DeferredLightingEffect::render() {
|
||||||
|
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
|
||||||
QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject();
|
glBindFramebuffer(GL_FRAMEBUFFER, 0 );
|
||||||
primaryFBO->release();
|
|
||||||
|
QSize framebufferSize = textureCache->getFrameBufferSize();
|
||||||
|
|
||||||
QOpenGLFramebufferObject* freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebufferObject();
|
auto freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebuffer();
|
||||||
freeFBO->bind();
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFBO));
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
// glEnable(GL_FRAMEBUFFER_SRGB);
|
// glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
|
// glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryColorTextureID());
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryNormalTextureID());
|
glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryNormalTextureID());
|
||||||
|
@ -209,11 +211,13 @@ void DeferredLightingEffect::render() {
|
||||||
const int VIEWPORT_Y_INDEX = 1;
|
const int VIEWPORT_Y_INDEX = 1;
|
||||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||||
const int VIEWPORT_HEIGHT_INDEX = 3;
|
const int VIEWPORT_HEIGHT_INDEX = 3;
|
||||||
float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width();
|
|
||||||
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width();
|
float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width();
|
||||||
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height();
|
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width();
|
||||||
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height();
|
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height();
|
||||||
|
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height();
|
||||||
|
|
||||||
|
|
||||||
// Fetch the ViewMatrix;
|
// Fetch the ViewMatrix;
|
||||||
glm::mat4 invViewMat;
|
glm::mat4 invViewMat;
|
||||||
_viewState->getViewTransform().getMatrix(invViewMat);
|
_viewState->getViewTransform().getMatrix(invViewMat);
|
||||||
|
@ -245,7 +249,7 @@ void DeferredLightingEffect::render() {
|
||||||
program->bind();
|
program->bind();
|
||||||
}
|
}
|
||||||
program->setUniformValue(locations->shadowScale,
|
program->setUniformValue(locations->shadowScale,
|
||||||
1.0f / textureCache->getShadowFramebufferObject()->width());
|
1.0f / textureCache->getShadowFramebuffer()->getWidth());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (_ambientLightMode > -1) {
|
if (_ambientLightMode > -1) {
|
||||||
|
@ -428,7 +432,9 @@ void DeferredLightingEffect::render() {
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
freeFBO->release();
|
//freeFBO->release();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// glDisable(GL_FRAMEBUFFER_SRGB);
|
// glDisable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
@ -437,9 +443,12 @@ void DeferredLightingEffect::render() {
|
||||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||||
glColorMask(true, true, true, false);
|
glColorMask(true, true, true, false);
|
||||||
|
|
||||||
primaryFBO->bind();
|
auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryFramebuffer());
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, primaryFBO);
|
||||||
|
|
||||||
|
//primaryFBO->bind();
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
|
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFBO->getRenderBuffer(0)));
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "RenderUtilsLogging.h"
|
#include "RenderUtilsLogging.h"
|
||||||
|
|
||||||
|
#include "gpu/GLBackend.h"
|
||||||
|
|
||||||
GlowEffect::GlowEffect()
|
GlowEffect::GlowEffect()
|
||||||
: _initialized(false),
|
: _initialized(false),
|
||||||
|
@ -45,10 +46,10 @@ GlowEffect::~GlowEffect() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const {
|
gpu::FramebufferPointer GlowEffect::getFreeFramebuffer() const {
|
||||||
return (_isOddFrame ?
|
return (_isOddFrame ?
|
||||||
DependencyManager::get<TextureCache>()->getSecondaryFramebufferObject():
|
DependencyManager::get<TextureCache>()->getSecondaryFramebuffer():
|
||||||
DependencyManager::get<TextureCache>()->getTertiaryFramebufferObject());
|
DependencyManager::get<TextureCache>()->getTertiaryFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProgramObject* createProgram(const QString& name) {
|
static ProgramObject* createProgram(const QString& name) {
|
||||||
|
@ -105,7 +106,10 @@ int GlowEffect::getDeviceHeight() const {
|
||||||
|
|
||||||
|
|
||||||
void GlowEffect::prepare() {
|
void GlowEffect::prepare() {
|
||||||
DependencyManager::get<TextureCache>()->getPrimaryFramebufferObject()->bind();
|
auto primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||||
|
GLuint fbo = gpu::GLBackend::getFramebufferID(primaryFBO);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
_isEmpty = true;
|
_isEmpty = true;
|
||||||
|
@ -124,25 +128,28 @@ void GlowEffect::end() {
|
||||||
glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop());
|
glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maybeBind(QOpenGLFramebufferObject* fbo) {
|
static void maybeBind(const gpu::FramebufferPointer& fbo) {
|
||||||
if (fbo) {
|
if (fbo) {
|
||||||
fbo->bind();
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(fbo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maybeRelease(QOpenGLFramebufferObject* fbo) {
|
static void maybeRelease(const gpu::FramebufferPointer& fbo) {
|
||||||
if (fbo) {
|
if (fbo) {
|
||||||
fbo->release();
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
|
gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
|
||||||
PerformanceTimer perfTimer("glowEffect");
|
PerformanceTimer perfTimer("glowEffect");
|
||||||
|
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject();
|
|
||||||
primaryFBO->release();
|
auto primaryFBO = gpu::GLBackend::getFramebufferID(textureCache->getPrimaryFramebuffer());
|
||||||
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryColorTextureID());
|
||||||
|
auto framebufferSize = textureCache->getFrameBufferSize();
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
@ -155,12 +162,14 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
|
|
||||||
QOpenGLFramebufferObject* destFBO = toTexture ?
|
gpu::FramebufferPointer destFBO = toTexture ?
|
||||||
textureCache->getSecondaryFramebufferObject() : NULL;
|
textureCache->getSecondaryFramebuffer() : nullptr;
|
||||||
if (!_enabled || _isEmpty) {
|
if (!_enabled || _isEmpty) {
|
||||||
// copy the primary to the screen
|
// copy the primary to the screen
|
||||||
if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
|
if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
|
||||||
QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
|
||||||
|
glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), 0, 0, framebufferSize.width(), framebufferSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
} else {
|
} else {
|
||||||
maybeBind(destFBO);
|
maybeBind(destFBO);
|
||||||
if (!destFBO) {
|
if (!destFBO) {
|
||||||
|
@ -175,35 +184,35 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// diffuse into the secondary/tertiary (alternating between frames)
|
// diffuse into the secondary/tertiary (alternating between frames)
|
||||||
QOpenGLFramebufferObject* oldDiffusedFBO =
|
auto oldDiffusedFBO =
|
||||||
textureCache->getSecondaryFramebufferObject();
|
textureCache->getSecondaryFramebuffer();
|
||||||
QOpenGLFramebufferObject* newDiffusedFBO =
|
auto newDiffusedFBO =
|
||||||
textureCache->getTertiaryFramebufferObject();
|
textureCache->getTertiaryFramebuffer();
|
||||||
if (_isOddFrame) {
|
if (_isOddFrame) {
|
||||||
qSwap(oldDiffusedFBO, newDiffusedFBO);
|
qSwap(oldDiffusedFBO, newDiffusedFBO);
|
||||||
}
|
}
|
||||||
newDiffusedFBO->bind();
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(newDiffusedFBO));
|
||||||
|
|
||||||
if (_isFirstFrame) {
|
if (_isFirstFrame) {
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture());
|
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(oldDiffusedFBO->getRenderBuffer(0)));
|
||||||
|
|
||||||
_diffuseProgram->bind();
|
_diffuseProgram->bind();
|
||||||
QSize size = primaryFBO->size();
|
|
||||||
_diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height());
|
_diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height());
|
||||||
|
|
||||||
renderFullscreenQuad();
|
renderFullscreenQuad();
|
||||||
|
|
||||||
_diffuseProgram->release();
|
_diffuseProgram->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
newDiffusedFBO->release();
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// add diffused texture to the primary
|
// add diffused texture to the primary
|
||||||
glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture());
|
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0)));
|
||||||
|
|
||||||
if (toTexture) {
|
if (toTexture) {
|
||||||
destFBO = oldDiffusedFBO;
|
destFBO = oldDiffusedFBO;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define hifi_GlowEffect_h
|
#define hifi_GlowEffect_h
|
||||||
|
|
||||||
#include <gpu/GPUConfig.h>
|
#include <gpu/GPUConfig.h>
|
||||||
|
#include <gpu/Framebuffer.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
|
@ -20,8 +21,6 @@
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
class QOpenGLFramebufferObject;
|
|
||||||
|
|
||||||
class ProgramObject;
|
class ProgramObject;
|
||||||
|
|
||||||
/// A generic full screen glow effect.
|
/// A generic full screen glow effect.
|
||||||
|
@ -33,7 +32,7 @@ public:
|
||||||
|
|
||||||
/// Returns a pointer to the framebuffer object that the glow effect is *not* using for persistent state
|
/// Returns a pointer to the framebuffer object that the glow effect is *not* using for persistent state
|
||||||
/// (either the secondary or the tertiary).
|
/// (either the secondary or the tertiary).
|
||||||
QOpenGLFramebufferObject* getFreeFramebufferObject() const;
|
gpu::FramebufferPointer getFreeFramebuffer() const;
|
||||||
|
|
||||||
void init(QGLWidget* widget, bool enabled);
|
void init(QGLWidget* widget, bool enabled);
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ public:
|
||||||
/// Renders the glow effect. To be called after rendering the scene.
|
/// Renders the glow effect. To be called after rendering the scene.
|
||||||
/// \param toTexture whether to render to a texture, rather than to the frame buffer
|
/// \param toTexture whether to render to a texture, rather than to the frame buffer
|
||||||
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
|
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
|
||||||
QOpenGLFramebufferObject* render(bool toTexture = false);
|
gpu::FramebufferPointer render(bool toTexture = false);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleGlowEffect(bool enabled);
|
void toggleGlowEffect(bool enabled);
|
||||||
|
|
|
@ -130,7 +130,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Z test depends if transparent or not
|
// Z test depends if transparent or not
|
||||||
state->setDepthTest(true, !key.isTranslucent(), gpu::State::LESS_EQUAL);
|
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
||||||
|
|
||||||
// Blend on transparent
|
// Blend on transparent
|
||||||
state->setBlendFunction(key.isTranslucent(),
|
state->setBlendFunction(key.isTranslucent(),
|
||||||
|
@ -673,8 +673,6 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto glowEffectIntensity = DependencyManager::get<GlowEffect>()->getIntensity();
|
|
||||||
|
|
||||||
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
||||||
_renderBatch.clear();
|
_renderBatch.clear();
|
||||||
gpu::Batch& batch = _renderBatch;
|
gpu::Batch& batch = _renderBatch;
|
||||||
|
@ -703,35 +701,12 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
batch.setViewTransform(_transforms[0]);
|
batch.setViewTransform(_transforms[0]);
|
||||||
|
|
||||||
// GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
|
||||||
|
|
||||||
// taking care of by the state?
|
|
||||||
/* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
|
|
||||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
|
||||||
} else {
|
|
||||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
|
||||||
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
|
||||||
GLBATCH(glCullFace)(GL_FRONT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// render opaque meshes with alpha testing
|
|
||||||
|
|
||||||
// GLBATCH(glDisable)(GL_BLEND);
|
|
||||||
// GLBATCH(glEnable)(GL_ALPHA_TEST);
|
|
||||||
|
|
||||||
/* if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
|
||||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
||||||
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
|
||||||
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
|
||||||
mode == RenderArgs::DEFAULT_RENDER_MODE);
|
mode == RenderArgs::DEFAULT_RENDER_MODE);
|
||||||
*/
|
*/
|
||||||
{
|
/*if (mode != RenderArgs::SHADOW_RENDER_MODE)*/ {
|
||||||
GLenum buffers[3];
|
GLenum buffers[3];
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
|
|
||||||
|
@ -748,6 +723,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||||
}
|
}
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
||||||
|
@ -790,12 +766,6 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true);
|
||||||
|
|
||||||
// GLBATCH(glDisable)(GL_ALPHA_TEST);
|
|
||||||
/* GLBATCH(glEnable)(GL_BLEND);
|
|
||||||
GLBATCH(glDepthMask)(false);
|
|
||||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
|
||||||
*/
|
|
||||||
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
|
|
||||||
{
|
{
|
||||||
GLenum buffers[1];
|
GLenum buffers[1];
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
|
@ -805,6 +775,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
|
||||||
|
|
||||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true);
|
||||||
|
@ -814,6 +786,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args, true);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args, true);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args, true);
|
||||||
|
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
GLBATCH(glDepthMask)(true);
|
GLBATCH(glDepthMask)(true);
|
||||||
|
@ -1758,14 +1732,6 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
|
||||||
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
// auto glowEffectIntensity = DependencyManager::get<GlowEffect>()->getIntensity();
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(ANDROID)
|
|
||||||
#else
|
|
||||||
glPushMatrix();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO;
|
RenderArgs::RenderSide renderSide = RenderArgs::MONO;
|
||||||
if (args) {
|
if (args) {
|
||||||
renderSide = args->_renderSide;
|
renderSide = args->_renderSide;
|
||||||
|
@ -1792,34 +1758,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
_sceneRenderBatch.clear();
|
_sceneRenderBatch.clear();
|
||||||
gpu::Batch& batch = _sceneRenderBatch;
|
gpu::Batch& batch = _sceneRenderBatch;
|
||||||
|
|
||||||
// GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
|
||||||
|
|
||||||
/* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
|
|
||||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
|
||||||
} else {
|
|
||||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
|
||||||
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
|
||||||
GLBATCH(glCullFace)(GL_FRONT);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// render opaque meshes with alpha testing
|
|
||||||
|
|
||||||
// GLBATCH(glDisable)(GL_BLEND);
|
|
||||||
// GLBATCH(glEnable)(GL_ALPHA_TEST);
|
|
||||||
|
|
||||||
/* if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
|
||||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
||||||
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
|
||||||
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
|
||||||
mode == RenderArgs::DEFAULT_RENDER_MODE);
|
mode == RenderArgs::DEFAULT_RENDER_MODE);
|
||||||
*/
|
*/
|
||||||
{
|
|
||||||
|
/* if (mode != RenderArgs::SHADOW_RENDER_MODE) */{
|
||||||
GLenum buffers[3];
|
GLenum buffers[3];
|
||||||
|
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
|
@ -1834,6 +1781,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||||
}
|
}
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
|
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
||||||
|
@ -1856,7 +1805,6 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args);
|
||||||
|
|
||||||
// render translucent meshes afterwards
|
// render translucent meshes afterwards
|
||||||
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(false, true, true);
|
|
||||||
{
|
{
|
||||||
GLenum buffers[2];
|
GLenum buffers[2];
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
|
@ -1876,21 +1824,19 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
// GLBATCH(glDisable)(GL_ALPHA_TEST);
|
|
||||||
/* GLBATCH(glEnable)(GL_BLEND);
|
|
||||||
GLBATCH(glDepthMask)(false);
|
|
||||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
|
||||||
*/
|
|
||||||
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
|
|
||||||
{
|
{
|
||||||
GLenum buffers[1];
|
GLenum buffers[1];
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
|
||||||
|
|
||||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
|
||||||
|
@ -1900,6 +1846,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
|
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
GLBATCH(glDepthMask)(true);
|
GLBATCH(glDepthMask)(true);
|
||||||
|
@ -1938,10 +1886,10 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
// Back to no program
|
// Back to no program
|
||||||
GLBATCH(glUseProgram)(0);
|
GLBATCH(glUseProgram)(0);
|
||||||
|
|
||||||
if (args) {
|
if (args) {
|
||||||
args->_translucentMeshPartsRendered = translucentParts;
|
args->_translucentMeshPartsRendered = translucentParts;
|
||||||
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
|
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1951,12 +1899,6 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
backend.render(_sceneRenderBatch);
|
backend.render(_sceneRenderBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(ANDROID)
|
|
||||||
#else
|
|
||||||
glPopMatrix();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// restore all the default material settings
|
// restore all the default material settings
|
||||||
_viewState->setupWorldLight();
|
_viewState->setupWorldLight();
|
||||||
|
|
||||||
|
@ -2334,17 +2276,15 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
||||||
RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
auto pipeline = _renderPipelineLib.find(key.getRaw());
|
auto pipeline = _renderPipelineLib.find(key.getRaw());
|
||||||
if (pipeline == _renderPipelineLib.end()) {
|
if (pipeline == _renderPipelineLib.end()) {
|
||||||
qDebug() << "No good, couldn;t find a pipeline from the key ?" << key.getRaw();
|
qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram();
|
gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram();
|
||||||
locations = (*pipeline).second._locations.get();
|
locations = (*pipeline).second._locations.get();
|
||||||
|
|
||||||
//GLuint glprogram = gpu::GLBackend::getShaderID(program);
|
|
||||||
//GLBATCH(glUseProgram)(glprogram);
|
|
||||||
|
|
||||||
// dare!
|
// Setup the One pipeline
|
||||||
batch.setPipeline((*pipeline).second._pipeline);
|
batch.setPipeline((*pipeline).second._pipeline);
|
||||||
|
|
||||||
if ((locations->alphaThreshold > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
if ((locations->alphaThreshold > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
||||||
|
@ -2354,9 +2294,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
||||||
if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
||||||
GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get<GlowEffect>()->getIntensity());
|
GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get<GlowEffect>()->getIntensity());
|
||||||
}
|
}
|
||||||
// if (!(translucent && alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
|
||||||
// GLBATCH(glAlphaFunc)(GL_EQUAL, DependencyManager::get<GlowEffect>()->getIntensity());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
|
@ -2383,10 +2320,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we selected a program, then unselect it
|
|
||||||
if (!pickProgramsNeeded) {
|
|
||||||
// GLBATCH(glUseProgram)(0);
|
|
||||||
}
|
|
||||||
return meshPartsRendered;
|
return meshPartsRendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2415,8 +2349,6 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
||||||
args, locations);
|
args, locations);
|
||||||
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
|
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
|
||||||
args, locations, forceRenderSomeMeshes);
|
args, locations, forceRenderSomeMeshes);
|
||||||
// GLBATCH(glUseProgram)(0);
|
|
||||||
|
|
||||||
|
|
||||||
return meshPartsRendered;
|
return meshPartsRendered;
|
||||||
}
|
}
|
||||||
|
@ -2427,7 +2359,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
// auto glowEffect = DependencyManager::get<GlowEffect>();
|
|
||||||
QString lastMaterialID;
|
QString lastMaterialID;
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
updateVisibleJointStates();
|
updateVisibleJointStates();
|
||||||
|
@ -2531,13 +2463,6 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
qCDebug(renderutils) << "NEW part.materialID:" << part.materialID;
|
qCDebug(renderutils) << "NEW part.materialID:" << part.materialID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (locations->glowIntensity >= 0) {
|
|
||||||
GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity());
|
|
||||||
}
|
|
||||||
if (!(translucent && alphaThreshold == 0.0f)) {
|
|
||||||
GLBATCH(glAlphaFunc)(GL_EQUAL, glowEffect->getIntensity());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (locations->materialBufferUnit >= 0) {
|
if (locations->materialBufferUnit >= 0) {
|
||||||
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
|
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,6 @@ TextureCache::TextureCache() :
|
||||||
_permutationNormalTexture(0),
|
_permutationNormalTexture(0),
|
||||||
_whiteTexture(0),
|
_whiteTexture(0),
|
||||||
_blueTexture(0),
|
_blueTexture(0),
|
||||||
_primaryDepthTextureID(0),
|
|
||||||
_primaryNormalTextureID(0),
|
|
||||||
_primarySpecularTextureID(0),
|
|
||||||
_primaryFramebufferObject(NULL),
|
|
||||||
_secondaryFramebufferObject(NULL),
|
|
||||||
_tertiaryFramebufferObject(NULL),
|
|
||||||
_shadowFramebufferObject(NULL),
|
|
||||||
_frameBufferSize(100, 100),
|
_frameBufferSize(100, 100),
|
||||||
_associatedWidget(NULL)
|
_associatedWidget(NULL)
|
||||||
{
|
{
|
||||||
|
@ -47,24 +40,6 @@ TextureCache::TextureCache() :
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::~TextureCache() {
|
TextureCache::~TextureCache() {
|
||||||
|
|
||||||
if (_primaryFramebufferObject) {
|
|
||||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
|
||||||
glDeleteTextures(1, &_primaryNormalTextureID);
|
|
||||||
glDeleteTextures(1, &_primarySpecularTextureID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_primaryFramebufferObject) {
|
|
||||||
delete _primaryFramebufferObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_secondaryFramebufferObject) {
|
|
||||||
delete _secondaryFramebufferObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_tertiaryFramebufferObject) {
|
|
||||||
delete _tertiaryFramebufferObject;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
|
void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
|
||||||
|
@ -72,26 +47,15 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
|
||||||
if (_frameBufferSize != frameBufferSize) {
|
if (_frameBufferSize != frameBufferSize) {
|
||||||
_frameBufferSize = frameBufferSize;
|
_frameBufferSize = frameBufferSize;
|
||||||
|
|
||||||
if (_primaryFramebufferObject) {
|
_primaryFramebuffer.reset();
|
||||||
delete _primaryFramebufferObject;
|
_primaryDepthTexture.reset();
|
||||||
_primaryFramebufferObject = NULL;
|
_primaryColorTexture.reset();
|
||||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
_primaryNormalTexture.reset();
|
||||||
_primaryDepthTextureID = 0;
|
_primarySpecularTexture.reset();
|
||||||
glDeleteTextures(1, &_primaryNormalTextureID);
|
|
||||||
_primaryNormalTextureID = 0;
|
|
||||||
glDeleteTextures(1, &_primarySpecularTextureID);
|
|
||||||
_primarySpecularTextureID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_secondaryFramebufferObject) {
|
_secondaryFramebuffer.reset();
|
||||||
delete _secondaryFramebufferObject;
|
|
||||||
_secondaryFramebufferObject = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_tertiaryFramebufferObject) {
|
_tertiaryFramebuffer.reset();
|
||||||
delete _tertiaryFramebufferObject;
|
|
||||||
_tertiaryFramebufferObject = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,58 +170,78 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
|
void TextureCache::createPrimaryFramebuffer() {
|
||||||
|
_primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
|
|
||||||
if (!_primaryFramebufferObject) {
|
auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
||||||
_primaryFramebufferObject = createFramebufferObject();
|
auto width = _frameBufferSize.width();
|
||||||
|
auto height = _frameBufferSize.height();
|
||||||
|
|
||||||
glGenTextures(1, &_primaryDepthTextureID);
|
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
||||||
glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID);
|
_primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, _frameBufferSize.width(), _frameBufferSize.height(),
|
_primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||||
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
_primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
_primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture);
|
||||||
|
_primaryFramebuffer->setRenderBuffer(1, _primaryNormalTexture);
|
||||||
glGenTextures(1, &_primaryNormalTextureID);
|
_primaryFramebuffer->setRenderBuffer(2, _primarySpecularTexture);
|
||||||
glBindTexture(GL_TEXTURE_2D, _primaryNormalTextureID);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _frameBufferSize.width(), _frameBufferSize.height(),
|
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
_primaryFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||||
|
}
|
||||||
glGenTextures(1, &_primarySpecularTextureID);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, _primarySpecularTextureID);
|
gpu::FramebufferPointer TextureCache::getPrimaryFramebuffer() {
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _frameBufferSize.width(), _frameBufferSize.height(),
|
if (!_primaryFramebuffer) {
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
createPrimaryFramebuffer();
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
_primaryFramebufferObject->bind();
|
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _primaryDepthTextureID, 0);
|
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _primaryNormalTextureID, 0);
|
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _primarySpecularTextureID, 0);
|
|
||||||
_primaryFramebufferObject->release();
|
|
||||||
}
|
}
|
||||||
return _primaryFramebufferObject;
|
return _primaryFramebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer TextureCache::getPrimaryDepthTexture() {
|
||||||
|
if (!_primaryDepthTexture) {
|
||||||
|
createPrimaryFramebuffer();
|
||||||
|
}
|
||||||
|
return _primaryDepthTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer TextureCache::getPrimaryColorTexture() {
|
||||||
|
if (!_primaryColorTexture) {
|
||||||
|
createPrimaryFramebuffer();
|
||||||
|
}
|
||||||
|
return _primaryColorTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer TextureCache::getPrimaryNormalTexture() {
|
||||||
|
if (!_primaryNormalTexture) {
|
||||||
|
createPrimaryFramebuffer();
|
||||||
|
}
|
||||||
|
return _primaryNormalTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer TextureCache::getPrimarySpecularTexture() {
|
||||||
|
if (!_primarySpecularTexture) {
|
||||||
|
createPrimaryFramebuffer();
|
||||||
|
}
|
||||||
|
return _primarySpecularTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint TextureCache::getPrimaryDepthTextureID() {
|
GLuint TextureCache::getPrimaryDepthTextureID() {
|
||||||
// ensure that the primary framebuffer object is initialized before returning the depth texture id
|
return gpu::GLBackend::getTextureID(getPrimaryDepthTexture());
|
||||||
getPrimaryFramebufferObject();
|
}
|
||||||
return _primaryDepthTextureID;
|
|
||||||
|
GLuint TextureCache::getPrimaryColorTextureID() {
|
||||||
|
return gpu::GLBackend::getTextureID(getPrimaryColorTexture());
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint TextureCache::getPrimaryNormalTextureID() {
|
GLuint TextureCache::getPrimaryNormalTextureID() {
|
||||||
// ensure that the primary framebuffer object is initialized before returning the normal texture id
|
return gpu::GLBackend::getTextureID(getPrimaryNormalTexture());
|
||||||
getPrimaryFramebufferObject();
|
|
||||||
return _primaryNormalTextureID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint TextureCache::getPrimarySpecularTextureID() {
|
GLuint TextureCache::getPrimarySpecularTextureID() {
|
||||||
getPrimaryFramebufferObject();
|
return gpu::GLBackend::getTextureID(getPrimarySpecularTexture());
|
||||||
return _primarySpecularTextureID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) {
|
void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) {
|
||||||
|
@ -275,70 +259,50 @@ void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular)
|
||||||
glDrawBuffers(bufferCount, buffers);
|
glDrawBuffers(bufferCount, buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
|
gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() {
|
||||||
if (!_secondaryFramebufferObject) {
|
if (!_secondaryFramebuffer) {
|
||||||
_secondaryFramebufferObject = createFramebufferObject();
|
_secondaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()));
|
||||||
}
|
}
|
||||||
return _secondaryFramebufferObject;
|
return _secondaryFramebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() {
|
gpu::FramebufferPointer TextureCache::getTertiaryFramebuffer() {
|
||||||
if (!_tertiaryFramebufferObject) {
|
if (!_tertiaryFramebuffer) {
|
||||||
_tertiaryFramebufferObject = createFramebufferObject();
|
_tertiaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()));
|
||||||
}
|
}
|
||||||
return _tertiaryFramebufferObject;
|
return _tertiaryFramebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() {
|
|
||||||
if (!_shadowFramebufferObject) {
|
gpu::FramebufferPointer TextureCache::getShadowFramebuffer() {
|
||||||
|
if (!_shadowFramebuffer) {
|
||||||
const int SHADOW_MAP_SIZE = 2048;
|
const int SHADOW_MAP_SIZE = 2048;
|
||||||
_shadowFramebufferObject = new QOpenGLFramebufferObject(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE,
|
_shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE));
|
||||||
QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D, GL_RGB);
|
|
||||||
|
_shadowTexture = _shadowFramebuffer->getDepthStencilBuffer();
|
||||||
glGenTextures(1, &_shadowDepthTextureID);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE,
|
|
||||||
0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
|
||||||
const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
||||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
_shadowFramebufferObject->bind();
|
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowDepthTextureID, 0);
|
|
||||||
_shadowFramebufferObject->release();
|
|
||||||
}
|
}
|
||||||
return _shadowFramebufferObject;
|
return _shadowFramebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint TextureCache::getShadowDepthTextureID() {
|
GLuint TextureCache::getShadowDepthTextureID() {
|
||||||
// ensure that the shadow framebuffer object is initialized before returning the depth texture id
|
// ensure that the shadow framebuffer object is initialized before returning the depth texture id
|
||||||
getShadowFramebufferObject();
|
getShadowFramebuffer();
|
||||||
return _shadowDepthTextureID;
|
return gpu::GLBackend::getTextureID(_shadowTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
|
bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
|
||||||
if (event->type() == QEvent::Resize) {
|
if (event->type() == QEvent::Resize) {
|
||||||
QSize size = static_cast<QResizeEvent*>(event)->size();
|
QSize size = static_cast<QResizeEvent*>(event)->size();
|
||||||
if (_primaryFramebufferObject && _primaryFramebufferObject->size() != size) {
|
if (_frameBufferSize != size) {
|
||||||
delete _primaryFramebufferObject;
|
_primaryFramebuffer.reset();
|
||||||
_primaryFramebufferObject = NULL;
|
_primaryColorTexture.reset();
|
||||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
_primaryDepthTexture.reset();
|
||||||
glDeleteTextures(1, &_primaryNormalTextureID);
|
_primaryNormalTexture.reset();
|
||||||
glDeleteTextures(1, &_primarySpecularTextureID);
|
_primarySpecularTexture.reset();
|
||||||
}
|
|
||||||
if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) {
|
_secondaryFramebuffer.reset();
|
||||||
delete _secondaryFramebufferObject;
|
|
||||||
_secondaryFramebufferObject = NULL;
|
_tertiaryFramebuffer.reset();
|
||||||
}
|
|
||||||
if (_tertiaryFramebufferObject && _tertiaryFramebufferObject->size() != size) {
|
|
||||||
delete _tertiaryFramebufferObject;
|
|
||||||
_tertiaryFramebufferObject = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,17 +323,6 @@ void TextureCache::associateWithWidget(QGLWidget* widget) {
|
||||||
_associatedWidget->installEventFilter(this);
|
_associatedWidget->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* TextureCache::createFramebufferObject() {
|
|
||||||
QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, fbo->texture());
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
return fbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture::Texture() {
|
Texture::Texture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +512,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
|
||||||
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
||||||
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
|
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
|
||||||
}
|
}
|
||||||
_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height()));
|
_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
_gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
_gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||||
_gpuTexture->autoGenerateMips(-1);
|
_gpuTexture->autoGenerateMips(-1);
|
||||||
}
|
}
|
||||||
|
@ -598,7 +551,7 @@ QSharedPointer<Texture> DilatableNetworkTexture::getDilatedTexture(float dilatio
|
||||||
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
||||||
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::BGRA));
|
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::BGRA));
|
||||||
}
|
}
|
||||||
texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height()));
|
texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
texture->_gpuTexture->assignStoredMip(0, formatMip, dilatedImage.byteCount(), dilatedImage.constBits());
|
texture->_gpuTexture->assignStoredMip(0, formatMip, dilatedImage.byteCount(), dilatedImage.constBits());
|
||||||
texture->_gpuTexture->autoGenerateMips(-1);
|
texture->_gpuTexture->autoGenerateMips(-1);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <gpu/GPUConfig.h>
|
#include <gpu/GPUConfig.h>
|
||||||
#include <gpu/Texture.h>
|
#include <gpu/Texture.h>
|
||||||
|
#include <gpu/Framebuffer.h>
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
@ -22,8 +23,6 @@
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
|
|
||||||
class QOpenGLFramebufferObject;
|
|
||||||
|
|
||||||
class NetworkTexture;
|
class NetworkTexture;
|
||||||
|
|
||||||
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
|
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
|
||||||
|
@ -60,11 +59,17 @@ public:
|
||||||
|
|
||||||
/// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
|
/// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
|
||||||
/// used for scene rendering.
|
/// used for scene rendering.
|
||||||
QOpenGLFramebufferObject* getPrimaryFramebufferObject();
|
gpu::FramebufferPointer getPrimaryFramebuffer();
|
||||||
|
|
||||||
|
gpu::TexturePointer getPrimaryDepthTexture();
|
||||||
|
gpu::TexturePointer getPrimaryColorTexture();
|
||||||
|
gpu::TexturePointer getPrimaryNormalTexture();
|
||||||
|
gpu::TexturePointer getPrimarySpecularTexture();
|
||||||
|
|
||||||
/// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
|
/// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
|
||||||
GLuint getPrimaryDepthTextureID();
|
GLuint getPrimaryDepthTextureID();
|
||||||
|
GLuint getPrimaryColorTextureID();
|
||||||
|
|
||||||
/// Returns the ID of the primary framebuffer object's normal texture.
|
/// Returns the ID of the primary framebuffer object's normal texture.
|
||||||
GLuint getPrimaryNormalTextureID();
|
GLuint getPrimaryNormalTextureID();
|
||||||
|
|
||||||
|
@ -76,15 +81,16 @@ public:
|
||||||
|
|
||||||
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
|
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
|
||||||
/// screen effects.
|
/// screen effects.
|
||||||
QOpenGLFramebufferObject* getSecondaryFramebufferObject();
|
gpu::FramebufferPointer getSecondaryFramebuffer();
|
||||||
|
|
||||||
/// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
|
/// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
|
||||||
/// screen effects.
|
/// screen effects.
|
||||||
QOpenGLFramebufferObject* getTertiaryFramebufferObject();
|
gpu::FramebufferPointer getTertiaryFramebuffer();
|
||||||
|
|
||||||
/// Returns a pointer to the framebuffer object used to render shadow maps.
|
|
||||||
QOpenGLFramebufferObject* getShadowFramebufferObject();
|
|
||||||
|
|
||||||
|
/// Returns the framebuffer object used to render shadow maps;
|
||||||
|
gpu::FramebufferPointer getShadowFramebuffer();
|
||||||
|
|
||||||
|
|
||||||
/// Returns the ID of the shadow framebuffer object's depth texture.
|
/// Returns the ID of the shadow framebuffer object's depth texture.
|
||||||
GLuint getShadowDepthTextureID();
|
GLuint getShadowDepthTextureID();
|
||||||
|
|
||||||
|
@ -99,24 +105,26 @@ private:
|
||||||
TextureCache();
|
TextureCache();
|
||||||
virtual ~TextureCache();
|
virtual ~TextureCache();
|
||||||
friend class DilatableNetworkTexture;
|
friend class DilatableNetworkTexture;
|
||||||
|
|
||||||
QOpenGLFramebufferObject* createFramebufferObject();
|
|
||||||
|
|
||||||
gpu::TexturePointer _permutationNormalTexture;
|
gpu::TexturePointer _permutationNormalTexture;
|
||||||
gpu::TexturePointer _whiteTexture;
|
gpu::TexturePointer _whiteTexture;
|
||||||
gpu::TexturePointer _blueTexture;
|
gpu::TexturePointer _blueTexture;
|
||||||
|
|
||||||
|
|
||||||
QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;
|
QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;
|
||||||
|
|
||||||
GLuint _primaryDepthTextureID;
|
gpu::TexturePointer _primaryDepthTexture;
|
||||||
GLuint _primaryNormalTextureID;
|
gpu::TexturePointer _primaryColorTexture;
|
||||||
GLuint _primarySpecularTextureID;
|
gpu::TexturePointer _primaryNormalTexture;
|
||||||
QOpenGLFramebufferObject* _primaryFramebufferObject;
|
gpu::TexturePointer _primarySpecularTexture;
|
||||||
QOpenGLFramebufferObject* _secondaryFramebufferObject;
|
gpu::FramebufferPointer _primaryFramebuffer;
|
||||||
QOpenGLFramebufferObject* _tertiaryFramebufferObject;
|
void createPrimaryFramebuffer();
|
||||||
|
|
||||||
QOpenGLFramebufferObject* _shadowFramebufferObject;
|
gpu::FramebufferPointer _secondaryFramebuffer;
|
||||||
GLuint _shadowDepthTextureID;
|
gpu::FramebufferPointer _tertiaryFramebuffer;
|
||||||
|
|
||||||
|
gpu::FramebufferPointer _shadowFramebuffer;
|
||||||
|
gpu::TexturePointer _shadowTexture;
|
||||||
|
|
||||||
QSize _frameBufferSize;
|
QSize _frameBufferSize;
|
||||||
QGLWidget* _associatedWidget;
|
QGLWidget* _associatedWidget;
|
||||||
|
|
Loading…
Reference in a new issue