mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-02 01:38:14 -05:00
Initial commit of ResInsight version 0.4.8
This commit is contained in:
@@ -0,0 +1,424 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfRenderEngine.h"
|
||||
#include "cvfRenderQueue.h"
|
||||
#include "cvfPart.h"
|
||||
#include "cvfDrawable.h"
|
||||
#include "cvfTransform.h"
|
||||
#include "cvfEffect.h"
|
||||
#include "cvfRenderStateSet.h"
|
||||
#include "cvfShaderProgram.h"
|
||||
#include "cvfTrace.h"
|
||||
#include "cvfOpenGL.h"
|
||||
#include "cvfBufferObjectManaged.h"
|
||||
#include "cvfMatrixState.h"
|
||||
#include "cvfCamera.h"
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::RenderEngine
|
||||
/// \ingroup Viewing
|
||||
///
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RenderEngine::RenderEngine()
|
||||
: m_renderedPartCount(0),
|
||||
m_renderedVertexCount(0),
|
||||
m_renderedTriangleCount(0),
|
||||
m_renderedOpenGLPrimitiveCount(0),
|
||||
m_disableDrawableRender(false),
|
||||
m_disableApplyEffects(false),
|
||||
m_forceImmediateMode(false),
|
||||
m_enableItemCountUpdate(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RenderEngine::render(OpenGLContext* oglContext, RenderQueue* renderQueue, size_t maxNumPartsToDraw, const Camera& camera, const UniformSet* globalUniformSet)
|
||||
{
|
||||
CVF_ASSERT(oglContext);
|
||||
CVF_ASSERT(renderQueue);
|
||||
|
||||
m_renderedPartCount = 0;
|
||||
m_renderedVertexCount = 0;
|
||||
m_renderedTriangleCount = 0;
|
||||
m_renderedOpenGLPrimitiveCount = 0;
|
||||
m_applyRenderStateCount = 0;
|
||||
m_shaderProgramChangesCount = 0;
|
||||
|
||||
m_renderStateTracker.resetAndApplyDefaultRenderStates(oglContext);
|
||||
|
||||
// Use immediate mode either if forced or if buffer objects are not supported (OpenGL 1.5 and below)
|
||||
// This is because the current fixed function rendering relies on the buffer object binding points being present
|
||||
const bool renderUsingImmediateMode = (m_forceImmediateMode || !BufferObjectManaged::supportedOpenGL(oglContext));
|
||||
|
||||
// Does the current OpenGL context support OpenGL shaders
|
||||
const bool contextSupportsShaders = ShaderProgram::supportedOpenGL(oglContext);
|
||||
|
||||
// Init matrix state tracker
|
||||
MatrixState matrixState(camera);
|
||||
uint lastAppliedMatrixStateVersionTick = matrixState.versionTick() - 1;
|
||||
|
||||
const Effect* prevEffect = NULL;
|
||||
const RenderStateSet* prevRenderStateSet = NULL;
|
||||
const ShaderProgram* prevShaderProgram = NULL;
|
||||
|
||||
// Track the current shader program being used.
|
||||
// Will be NULL when effect has no shader program or if usage of shader program fails
|
||||
ShaderProgram* shaderProgramInUse = NULL;
|
||||
if (contextSupportsShaders)
|
||||
{
|
||||
// Start out with fixed function
|
||||
ShaderProgram::useNoProgram(oglContext);
|
||||
}
|
||||
|
||||
// Determine number of parts we'll draw
|
||||
size_t numPartsInQueue = renderQueue->count();
|
||||
size_t numPartsToDraw = std::min(numPartsInQueue, maxNumPartsToDraw);
|
||||
|
||||
bool debugLogging = CVF_SHOULD_LOG_RENDER_DEBUG(oglContext);
|
||||
if (debugLogging)
|
||||
{
|
||||
CVF_LOG_RENDER_DEBUG(oglContext, "RenderEngine::render(), numParts=" + String(static_cast<uint>(numPartsInQueue)));
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numPartsToDraw; i++)
|
||||
{
|
||||
RenderItem* item = renderQueue->item(i);
|
||||
CVF_ASSERT(item);
|
||||
|
||||
Drawable* drawable = item->drawable();
|
||||
Effect* effect = item->effect();
|
||||
Part* part = item->part();
|
||||
CVF_ASSERT(drawable);
|
||||
CVF_ASSERT(effect);
|
||||
CVF_ASSERT(part);
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
CVF_LOG_RENDER_DEBUG(oglContext, String("part#=%1, partName='%2'").arg(static_cast<uint>(i)).arg(part->name()));
|
||||
}
|
||||
|
||||
// Update matrix state to reflect any part transformations
|
||||
if (part->transform())
|
||||
{
|
||||
matrixState.setModelMatrix(part->transform()->worldTransform());
|
||||
}
|
||||
else
|
||||
{
|
||||
matrixState.clearModelMatrix();
|
||||
}
|
||||
|
||||
if (effect != prevEffect && !m_disableApplyEffects)
|
||||
{
|
||||
const RenderStateSet* const renderStateSet = effect->renderStateSet();
|
||||
if (renderStateSet != prevRenderStateSet)
|
||||
{
|
||||
// This apply function is designed to work with NULL pointers
|
||||
m_renderStateTracker.applyRenderStates(oglContext, renderStateSet, prevRenderStateSet);
|
||||
prevRenderStateSet = renderStateSet;
|
||||
m_applyRenderStateCount++;
|
||||
}
|
||||
|
||||
if (contextSupportsShaders)
|
||||
{
|
||||
ShaderProgram* shaderProgThisEffect = effect->shaderProgram();
|
||||
if (shaderProgThisEffect != prevShaderProgram)
|
||||
{
|
||||
// Reset the 'in use' pointer, and only set it if we have a shader program AND we manage to use it
|
||||
shaderProgramInUse = NULL;
|
||||
if (shaderProgThisEffect)
|
||||
{
|
||||
// Will fail if program hasn't been linked
|
||||
if (shaderProgThisEffect->useProgram(oglContext))
|
||||
{
|
||||
shaderProgramInUse = shaderProgThisEffect;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shaderProgramInUse)
|
||||
{
|
||||
ShaderProgram::useNoProgram(oglContext);
|
||||
}
|
||||
|
||||
prevShaderProgram = shaderProgThisEffect;
|
||||
m_shaderProgramChangesCount++;
|
||||
}
|
||||
|
||||
if (shaderProgramInUse)
|
||||
{
|
||||
// Apply uniforms for this shader program
|
||||
// Note order of application here.
|
||||
// - shader program default uniforms
|
||||
// - global dynamic uniforms
|
||||
// - (texture binding uniforms)
|
||||
// - effect uniforms
|
||||
// - fixed uniforms
|
||||
// We would really like the effect's uniforms to be at the very end, but that would give inconsistent
|
||||
// behavior since the fixed uniforms may get applied also when the effect does NOT change.
|
||||
shaderProgramInUse->clearUniformApplyTracking();
|
||||
|
||||
shaderProgramInUse->applyDefaultUniforms(oglContext);
|
||||
|
||||
if (globalUniformSet)
|
||||
{
|
||||
shaderProgramInUse->applyActiveUniformsOnly(oglContext, *globalUniformSet);
|
||||
}
|
||||
|
||||
const TextureBindings* textureBindings = static_cast<const TextureBindings*>(effect->renderStateOfType(RenderState::TEXTURE_BINDINGS));
|
||||
if (textureBindings)
|
||||
{
|
||||
textureBindings->applySamplerTextureUnitUniforms(oglContext, shaderProgramInUse);
|
||||
}
|
||||
|
||||
// Apply the effect's uniform last so that they win in case of clashes
|
||||
const UniformSet* uniformSet = effect->uniformSet();
|
||||
if (uniformSet)
|
||||
{
|
||||
shaderProgramInUse->applyUniforms(oglContext, *uniformSet);
|
||||
}
|
||||
|
||||
// Still, the fixed ones have to go at the end for consistency
|
||||
shaderProgramInUse->applyFixedUniforms(oglContext, matrixState);
|
||||
lastAppliedMatrixStateVersionTick = matrixState.versionTick();
|
||||
}
|
||||
}
|
||||
|
||||
prevEffect = effect;
|
||||
}
|
||||
|
||||
|
||||
if (shaderProgramInUse)
|
||||
{
|
||||
if (lastAppliedMatrixStateVersionTick != matrixState.versionTick())
|
||||
{
|
||||
shaderProgramInUse->applyFixedUniforms(oglContext, matrixState);
|
||||
lastAppliedMatrixStateVersionTick = matrixState.versionTick();
|
||||
}
|
||||
|
||||
// Will check that all active uniforms in shader program have been set since last call to >clearUniformApplyTracking()
|
||||
// Reports error to log if any uniforms are missing.
|
||||
shaderProgramInUse->checkReportAllUniformsApplied(oglContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef CVF_OPENGL_ES
|
||||
if (lastAppliedMatrixStateVersionTick != matrixState.versionTick())
|
||||
{
|
||||
glLoadMatrixf(matrixState.modelViewMatrix().ptr());
|
||||
lastAppliedMatrixStateVersionTick = matrixState.versionTick();
|
||||
}
|
||||
#endif // CVF_OPENGL_ES
|
||||
}
|
||||
|
||||
|
||||
// Do actual rendering
|
||||
if (!m_disableDrawableRender)
|
||||
{
|
||||
if (renderUsingImmediateMode)
|
||||
{
|
||||
drawable->renderImmediateMode(oglContext, matrixState);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shaderProgramInUse)
|
||||
{
|
||||
drawable->render(oglContext, shaderProgramInUse, matrixState);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawable->renderFixedFunction(oglContext, matrixState);
|
||||
}
|
||||
}
|
||||
|
||||
m_renderedPartCount++;
|
||||
}
|
||||
|
||||
// Update counters
|
||||
if (m_enableItemCountUpdate)
|
||||
{
|
||||
m_renderedVertexCount += drawable->vertexCount();
|
||||
m_renderedTriangleCount += drawable->triangleCount();
|
||||
m_renderedOpenGLPrimitiveCount += drawable->faceCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Do an apply with an empty new render state set to get defaults back before leaving
|
||||
// This really isn't the optimal place to do this, but until we expose application of render states it's the only place
|
||||
m_renderStateTracker.applyRenderStates(oglContext, NULL, prevRenderStateSet);
|
||||
|
||||
// For now, set back to fixed function
|
||||
if (contextSupportsShaders)
|
||||
{
|
||||
ShaderProgram::useNoProgram(oglContext);
|
||||
}
|
||||
|
||||
// Set back VBO settings (do we need this?)
|
||||
if (BufferObjectManaged::supportedOpenGL(oglContext))
|
||||
{
|
||||
BufferObjectManaged::unbindAllBuffers(oglContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RenderEngine::renderedPartCount() const
|
||||
{
|
||||
return m_renderedPartCount;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the number of vertices used for the last rendering
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RenderEngine::renderedVertexCount() const
|
||||
{
|
||||
return m_renderedVertexCount;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the number of triangles (GL_TRIANGLE) rendered in the last rendering
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RenderEngine::renderedTriangleCount() const
|
||||
{
|
||||
return m_renderedTriangleCount;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the number of OpenGL primitives (triangles, points, lines, etc) rendered in the last rendering
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RenderEngine::renderedOpenGLPrimitiveCount() const
|
||||
{
|
||||
return m_renderedOpenGLPrimitiveCount;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RenderEngine::applyRenderStateCount() const
|
||||
{
|
||||
return m_applyRenderStateCount;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RenderEngine::shaderProgramChangesCount() const
|
||||
{
|
||||
return m_shaderProgramChangesCount;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RenderEngine::enableForcedImmediateMode(bool enable)
|
||||
{
|
||||
m_forceImmediateMode = enable;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RenderEngine::disableRenderDrawables(bool disable)
|
||||
{
|
||||
m_disableDrawableRender = disable;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RenderEngine::disableApplyEffects(bool disable)
|
||||
{
|
||||
m_disableApplyEffects = disable;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RenderEngine::isForcedImmediateModeEnabled() const
|
||||
{
|
||||
return m_forceImmediateMode;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RenderEngine::isRenderDrawableDisabled() const
|
||||
{
|
||||
return m_disableDrawableRender;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RenderEngine::isApplyEffectsDisabled() const
|
||||
{
|
||||
return m_disableApplyEffects;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RenderEngine::enableItemCountUpdate(bool enable)
|
||||
{
|
||||
m_enableItemCountUpdate = enable;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RenderEngine::isItemCountUpdateEnabled() const
|
||||
{
|
||||
return m_enableItemCountUpdate;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
Reference in New Issue
Block a user