shuffling the rendering steps to get to render transparent and light it correctly

This commit is contained in:
Sam Gateau 2015-06-06 09:50:56 -07:00
parent aa5e6fa1b0
commit 8d3a3221b0
16 changed files with 271 additions and 44 deletions

View file

@ -66,19 +66,19 @@ panel.newCheckbox("Enable Render Transparent",
function(value) { return (value); }
);
panel.newSlider("Num Feed Transparents", 0, 1000,
panel.newSlider("Num Feed Transparents", 0, 100,
function(value) { },
function() { return Scene.getEngineNumFeedTransparentItems(); },
function(value) { return (value); }
);
panel.newSlider("Num Drawn Transparents", 0, 1000,
panel.newSlider("Num Drawn Transparents", 0, 100,
function(value) { },
function() { return Scene.getEngineNumDrawnTransparentItems(); },
function(value) { return (value); }
);
panel.newSlider("Max Drawn Transparents", -1, 1000,
panel.newSlider("Max Drawn Transparents", -1, 100,
function(value) { Scene.setEngineMaxDrawnTransparentItems(value); },
function() { return Scene.getEngineMaxDrawnTransparentItems(); },
function(value) { return (value); }

View file

@ -13,6 +13,8 @@
#include <assert.h>
#include "Batch.h"
#include "Resource.h"
#include "Texture.h"
#include "Pipeline.h"
@ -20,14 +22,6 @@
namespace gpu {
class GPUObject {
public:
GPUObject() {}
virtual ~GPUObject() {}
};
class Batch;
class Backend {
public:

View file

@ -16,7 +16,11 @@
namespace gpu {
class GPUObject;
class GPUObject {
public:
GPUObject() {}
virtual ~GPUObject() {}
};
typedef int Stamp;

View file

@ -8,8 +8,6 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Context.h"
#include "Resource.h"
#include <QDebug>

View file

@ -103,6 +103,22 @@ TransformCamera getTransformCamera() {
<@endif@>
<@endfunc@>
<@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // transformModelToClipPos
vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>);
<$eyePos$> = (<$cameraTransform$>._viewInverse * _worldpos);
vec4 _eyepos =(<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0);
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos;
}
<@else@>
<$eyePos$> = gl_ModelViewMatrix * <$modelPos$>;
<$clipPos$> = gl_ModelViewProjectionMatrix * <$modelPos$>;
<@endif@>
<@endfunc@>
<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>
{ // transformModelToEyeDir

View file

@ -219,6 +219,7 @@ void DeferredLightingEffect::render() {
QSize framebufferSize = textureCache->getFrameBufferSize();
// binding the first framebuffer
auto freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFBO));
@ -489,11 +490,20 @@ void DeferredLightingEffect::render() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
// glDisable(GL_FRAMEBUFFER_SRGB);
// End of the Lighting pass
}
void DeferredLightingEffect::copyBack(RenderArgs* args) {
auto textureCache = DependencyManager::get<TextureCache>();
QSize framebufferSize = textureCache->getFrameBufferSize();
auto freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebuffer();
//freeFBO->release();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// glDisable(GL_FRAMEBUFFER_SRGB);
glDisable(GL_CULL_FACE);
@ -516,6 +526,18 @@ void DeferredLightingEffect::render() {
glPushMatrix();
glLoadIdentity();
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
const int VIEWPORT_X_INDEX = 0;
const int VIEWPORT_Y_INDEX = 1;
const int VIEWPORT_WIDTH_INDEX = 2;
const int VIEWPORT_HEIGHT_INDEX = 3;
float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width();
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width();
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height();
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height();
renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight);
glBindTexture(GL_TEXTURE_2D, 0);
@ -531,12 +553,11 @@ void DeferredLightingEffect::render() {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
// now render the objects we held back until after deferred lighting
foreach (PostLightingRenderable* renderable, _postLightingRenderables) {
renderable->renderPostLighting();
}
_postLightingRenderables.clear();
}
void DeferredLightingEffect::setupTransparent(RenderArgs* args) {
auto globalLight = _allocatedLights[_globalLights.front()];
args->_batch->setUniformBuffer(4, globalLight->getSchemaBuffer());
}
void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations) {

View file

@ -23,7 +23,7 @@
#include "model/Stage.h"
class AbstractViewStateInterface;
class PostLightingRenderable;
class RenderArgs;
/// Handles deferred lighting for the bits that require it (voxels...)
class DeferredLightingEffect : public Dependency {
@ -66,11 +66,11 @@ public:
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f),
float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI);
/// Adds an object to render after performing the deferred lighting for the current frame (e.g., a translucent object).
void addPostLightingRenderable(PostLightingRenderable* renderable) { _postLightingRenderables.append(renderable); }
void prepare();
void render();
void copyBack(RenderArgs* args);
void setupTransparent(RenderArgs* args);
// update global lighting
void setAmbientLightMode(int preset);
@ -153,7 +153,6 @@ private:
std::vector<int> _globalLights;
std::vector<int> _pointLights;
std::vector<int> _spotLights;
QVector<PostLightingRenderable*> _postLightingRenderables;
AbstractViewStateInterface* _viewState;
@ -162,10 +161,4 @@ private:
model::SkyboxPointer _skybox;
};
/// Simple interface for objects that require something to be rendered after deferred lighting.
class PostLightingRenderable {
public:
virtual void renderPostLighting() = 0;
};
#endif // hifi_DeferredLightingEffect_h

View file

@ -112,6 +112,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4));
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
gpu::Shader::makeProgram(*program, slotBindings);
@ -2158,6 +2159,11 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
const FBXMeshPart& part = mesh.parts.at(partIndex);
model::MaterialPointer material = part._material;
float shininess = 0;
if (translucent) {
shininess = material->getShininess();
}
if (material == nullptr) {
// qCDebug(renderutils) << "WARNING: material == nullptr!!!";
}

View file

@ -10,7 +10,11 @@
//
#include "RenderDeferredTask.h"
#include "gpu/Batch.h"
#include "gpu/Context.h"
#include "DeferredLightingEffect.h"
#include "ViewFrustum.h"
#include "RenderArgs.h"
#include <PerfStat.h>
@ -22,9 +26,15 @@ template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPo
DependencyManager::get<DeferredLightingEffect>()->prepare();
}
template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("RenderDeferred");
DependencyManager::get<DeferredLightingEffect>()->render();
// renderContext->args->_context->syncCache();
}
template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("ResolveDeferred");
DependencyManager::get<DeferredLightingEffect>()->render();
DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args);
}
@ -34,10 +44,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
_jobs.push_back(Job(DrawBackground()));
_jobs.push_back(Job(DrawOpaque()));
_jobs.push_back(Job(DrawLight()));
_jobs.push_back(Job(DrawTransparent()));
_jobs.push_back(Job(ResetGLState()));
_jobs.push_back(Job(RenderDeferred()));
_jobs.push_back(Job(ResolveDeferred()));
_jobs.push_back(Job(DrawTransparentDeferred()));
_jobs.push_back(Job(ResetGLState()));
}
RenderDeferredTask::~RenderDeferredTask() {
@ -62,3 +73,85 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
job.run(sceneContext, renderContext);
}
};
template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawTransparentDeferred");
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render transparents
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDs culledItems;
if (renderContext->_cullTransparent) {
cullItems(sceneContext, renderContext, inItems, culledItems);
renderedItems = culledItems;
}
renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDs sortedItems;
if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems;
}
if (renderContext->_renderTransparent) {
RenderArgs* args = renderContext->args;
gpu::Batch batch;
args->_batch = &batch;
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(renderContext->args);
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
args->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
/* // render translucent meshes afterwards
{
GLenum buffers[2];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
batch._glDrawBuffers(bufferCount, buffers);
args->_alphaThreshold = MOSTLY_OPAQUE_THRESHOLD;
}
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
*/
{
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
batch._glDrawBuffers(bufferCount, buffers);
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
}
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
args->_context->render((*args->_batch));
args->_batch = nullptr;
}
}

View file

@ -14,8 +14,6 @@
#include "render/DrawTask.h"
#include "DeferredLightingEffect.h"
class PrepareDeferred {
public:
};
@ -23,6 +21,13 @@ namespace render {
template <> void jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class RenderDeferred {
public:
};
namespace render {
template <> void jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class ResolveDeferred {
public:
};
@ -30,6 +35,13 @@ namespace render {
template <> void jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class DrawTransparentDeferred {
public:
};
namespace render {
template <> void jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class RenderDeferredTask : public render::Task {
public:

View file

@ -52,6 +52,8 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
_primaryNormalTexture.reset();
_primarySpecularTexture.reset();
_transparentFramebuffer.reset();
_secondaryFramebuffer.reset();
_tertiaryFramebuffer.reset();
@ -264,6 +266,14 @@ void TextureCache::setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool nor
batch._glDrawBuffers(bufferCount, buffers);
}
gpu::FramebufferPointer TextureCache::getTransparentFramebuffer() {
if (!_transparentFramebuffer) {
_transparentFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()));
_transparentFramebuffer->setDepthStencilBuffer(getPrimaryDepthTexture(), getPrimaryDepthTexture()->getTexelFormat());
}
return _transparentFramebuffer;
}
gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() {
if (!_secondaryFramebuffer) {
_secondaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()));

View file

@ -71,6 +71,8 @@ public:
gpu::TexturePointer getPrimaryNormalTexture();
gpu::TexturePointer getPrimarySpecularTexture();
gpu::FramebufferPointer getTransparentFramebuffer();
/// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
GLuint getPrimaryDepthTextureID();
GLuint getPrimaryColorTextureID();
@ -124,6 +126,8 @@ private:
gpu::FramebufferPointer _primaryFramebuffer;
void createPrimaryFramebuffer();
gpu::FramebufferPointer _transparentFramebuffer;
gpu::FramebufferPointer _secondaryFramebuffer;
gpu::FramebufferPointer _tertiaryFramebuffer;

View file

@ -19,6 +19,9 @@ const int MAX_TEXCOORDS = 2;
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -35,7 +38,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$>
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);

View file

@ -11,8 +11,7 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredBufferWrite.slh@>
<!/*<@include DeferredBufferWrite.slh@>
<@include model/Material.slh@>
@ -39,4 +38,72 @@ void main(void) {
// set the diffuse data
// gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].st);
}*/!>
<@include model/Material.slh@>
// Everything about global lighting
<@include DeferredLighting.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
// Everything about light
<@include model/Light.slh@>
// The view Matrix
//uniform mat4 invViewMat;
vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
TransformCamera cam = getTransformCamera();
mat4 invViewMat = cam._viewInverse;
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 color = diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
return color;
}
// the diffuse texture
uniform sampler2D diffuseMap;
// the interpolated view position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
varying vec3 color;
void main(void) {
vec3 fragPosition = interpolatedPosition.xyz;
// Fetch diffuse map
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
Material mat = getMaterial();
vec3 fragNormal = normalize(interpolatedNormal.xyz);
float fragOpacity = getMaterialOpacity(mat) * diffuse.a;
vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * color;
vec3 fragSpecular = getMaterialSpecular(mat);
float fragGloss = getMaterialShininess(mat);
vec3 color = evalAmbienGlobalColor(1.0,
fragPosition,
fragNormal,
fragDiffuse,
fragSpecular,
fragGloss);
gl_FragColor = vec4(color, fragOpacity);
}

View file

@ -25,6 +25,9 @@ uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
attribute vec4 clusterIndices;
attribute vec4 clusterWeights;
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -49,7 +52,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
<$transformModelToWorldAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);

View file

@ -28,6 +28,9 @@ attribute vec3 tangent;
attribute vec4 clusterIndices;
attribute vec4 clusterWeights;
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -37,13 +40,13 @@ varying vec4 interpolatedTangent;
varying vec3 color;
void main(void) {
vec4 interpolatedPosition = vec4(0.0, 0.0, 0.0, 0.0);
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);
interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])];
float clusterWeight = clusterWeights[i];
interpolatedPosition += clusterMatrix * gl_Vertex * clusterWeight;
position += clusterMatrix * gl_Vertex * clusterWeight;
interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight;
interpolatedTangent += clusterMatrix * vec4(tangent, 0.0) * clusterWeight;
}
@ -60,7 +63,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, position, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
<$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$>