mirror of
https://github.com/OPM/ResInsight.git
synced 2026-11-03 20:56:45 -06:00
1312 lines
43 KiB
C++
1312 lines
43 KiB
C++
//##################################################################################################
|
|
//
|
|
// 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 "cvfAssert.h"
|
|
#include "cvfRenderState.h"
|
|
#include "cvfOpenGL.h"
|
|
#include "cvfUniform.h"
|
|
#include "cvfShaderProgram.h"
|
|
#include "cvfTexture.h"
|
|
#include "cvfSampler.h"
|
|
#include "cvfOpenGLCapabilities.h"
|
|
|
|
namespace cvf {
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::RenderState
|
|
/// \ingroup Render
|
|
///
|
|
/// Base class for classes encapsulating OpenGL state
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RenderState::RenderState(Type type)
|
|
: m_stateType(type)
|
|
{
|
|
CVF_ASSERT(type < COUNT);
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RenderState::~RenderState()
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RenderState::Type RenderState::type() const
|
|
{
|
|
return m_stateType;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Returns true if this render state relies on Fixed Function OpenGL.
|
|
///
|
|
/// The default implementation of this function returns false
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RenderState::isFixedFunction() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::Blending
|
|
/// \ingroup Render
|
|
///
|
|
/// Encapsulate OpenGL blending functions: glEnable(GL_BLEND), glBlendEquation(), glBlendEquationSeparate()
|
|
/// glBlendFunc(), glBlendFuncSeparate(), glBlendColor()
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquation.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquationSeparate.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendFunc.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendFuncSeparate.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendColor.xml
|
|
///
|
|
/// \todo
|
|
/// Add support for enable/disable blending per drawbuffer: glEnablei(GL_BLEND, drawBufferIndex)
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Blending::Blending()
|
|
: RenderState(BLENDING),
|
|
m_enableBlending(false),
|
|
m_funcSourceRGB(ONE),
|
|
m_funcDestinationRGB(ZERO),
|
|
m_funcSourceAlpha(ONE),
|
|
m_funcDestinationAlpha(ZERO),
|
|
m_equationRGB(FUNC_ADD),
|
|
m_equationAlpha(FUNC_ADD),
|
|
m_blendColor(0, 0, 0, 0)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// glEnable(GL_BLEND) / glDisable(GL_BLEND)
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::enableBlending(bool blend/*, uint drawBufferIndex*/)
|
|
{
|
|
m_enableBlending = blend;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// glBlendFunc()
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::setFunction(Function source, Function destination)
|
|
{
|
|
m_funcSourceRGB = source;
|
|
m_funcSourceAlpha = source;
|
|
m_funcDestinationRGB = destination;
|
|
m_funcDestinationAlpha = destination;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// glBlendEquation(). Requires OpenGL 2.0
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::setEquation(Equation eq)
|
|
{
|
|
m_equationRGB = eq;
|
|
m_equationAlpha = eq;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// glBlendFuncSeparate(). Requires OpenGL 2.0
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::setFunctionSeparate(Function sourceRGB, Function destinationRGB, Function sourceAlpha, Function destinationAlpha)
|
|
{
|
|
m_funcSourceRGB = sourceRGB;
|
|
m_funcDestinationRGB = destinationRGB;
|
|
m_funcSourceAlpha = sourceAlpha;
|
|
m_funcDestinationAlpha = destinationAlpha;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// glBlendEquationSeparate(). Requires OpenGL 2.0
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::setEquationSeparate(Equation equationRGB, Equation equationAlpha)
|
|
{
|
|
m_equationRGB = equationRGB;
|
|
m_equationAlpha = equationAlpha;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// glBlendColor(). Requires OpenGL 2.0
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::setBlendColor(Color4f blendColor)
|
|
{
|
|
m_blendColor = blendColor;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::configureTransparencyBlending()
|
|
{
|
|
m_enableBlending = true;
|
|
setFunction(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Blending::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
CVF_CALLSITE_OPENGL(oglContext);
|
|
|
|
/// As we do not care about specific support for OpenGL 1.4, 1.3 etc., everything that is not in 1.1
|
|
/// will require at least support for our baseline (currently OpenGL 2.0)
|
|
bool openGL2Support = oglContext->capabilities()->supportsOpenGL2();
|
|
|
|
if (m_enableBlending)
|
|
{
|
|
glEnable(GL_BLEND);
|
|
}
|
|
else
|
|
{
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
if ((m_funcSourceRGB == m_funcSourceAlpha) && (m_funcDestinationRGB == m_funcDestinationAlpha))
|
|
{
|
|
glBlendFunc(blendFuncOpenGL(m_funcSourceRGB), blendFuncOpenGL(m_funcDestinationRGB));
|
|
}
|
|
else
|
|
{
|
|
if (openGL2Support)
|
|
{
|
|
glBlendFuncSeparate(blendFuncOpenGL(m_funcSourceRGB), blendFuncOpenGL(m_funcDestinationRGB), blendFuncOpenGL(m_funcSourceAlpha), blendFuncOpenGL(m_funcDestinationAlpha));
|
|
}
|
|
else
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support separate blend functions.");
|
|
}
|
|
}
|
|
|
|
if (openGL2Support)
|
|
{
|
|
if (m_equationRGB == m_equationAlpha)
|
|
{
|
|
glBlendEquation(blendEquationOpenGL(m_equationRGB));
|
|
}
|
|
else
|
|
{
|
|
glBlendEquationSeparate(blendEquationOpenGL(m_equationRGB), blendEquationOpenGL(m_equationAlpha));
|
|
}
|
|
|
|
glBlendColor(m_blendColor.r(), m_blendColor.g(), m_blendColor.b(), m_blendColor.a());
|
|
}
|
|
else
|
|
{
|
|
// Only error reporting here
|
|
if (m_equationRGB != FUNC_ADD ||
|
|
m_equationRGB != m_equationAlpha)
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support blend equations.");
|
|
}
|
|
|
|
if (m_blendColor != Color4f(0, 0, 0, 0))
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support blend color.");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvfGLenum Blending::blendEquationOpenGL(Equation eq) const
|
|
{
|
|
switch (eq)
|
|
{
|
|
case FUNC_ADD: return GL_FUNC_ADD;
|
|
case FUNC_SUBTRACT: return GL_FUNC_SUBTRACT;
|
|
case FUNC_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
|
|
#ifndef CVF_OPENGL_ES
|
|
case MIN: return GL_MIN;
|
|
case MAX: return GL_MAX;
|
|
#endif
|
|
}
|
|
|
|
CVF_FAIL_MSG("Unhandled blend equation");
|
|
return 0;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvfGLenum Blending::blendFuncOpenGL(Function func) const
|
|
{
|
|
switch (func)
|
|
{
|
|
case ZERO: return GL_ZERO;
|
|
case ONE: return GL_ONE;
|
|
case SRC_COLOR: return GL_SRC_COLOR;
|
|
case ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
|
|
case DST_COLOR: return GL_DST_COLOR;
|
|
case ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
|
|
case SRC_ALPHA: return GL_SRC_ALPHA;
|
|
case ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
|
|
case DST_ALPHA: return GL_DST_ALPHA;
|
|
case ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
|
|
case CONSTANT_COLOR: return GL_CONSTANT_COLOR;
|
|
case ONE_MINUS_CONSTANT_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
|
|
case CONSTANT_ALPHA: return GL_CONSTANT_ALPHA;
|
|
case ONE_MINUS_CONSTANT_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
|
|
case SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE;
|
|
}
|
|
|
|
CVF_FAIL_MSG("Unhandled blend func");
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::ColorMask
|
|
/// \ingroup Render
|
|
///
|
|
/// Encapsulate OpenGL glColorMask() function.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
ColorMask::ColorMask(bool writeAllComponents)
|
|
: RenderState(COLOR_MASK),
|
|
m_writeRed(writeAllComponents),
|
|
m_writeGreen(writeAllComponents),
|
|
m_writeBlue(writeAllComponents),
|
|
m_writeAlpha(writeAllComponents)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void ColorMask::enable(bool writeRed, bool writeGreen, bool writeBlue, bool writeAlpha)
|
|
{
|
|
m_writeRed = writeRed;
|
|
m_writeGreen = writeGreen;
|
|
m_writeBlue = writeBlue;
|
|
m_writeAlpha = writeAlpha;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void ColorMask::enableWriteAllComponents(bool writeAllComponents)
|
|
{
|
|
m_writeRed = writeAllComponents;
|
|
m_writeGreen = writeAllComponents;
|
|
m_writeBlue = writeAllComponents;
|
|
m_writeAlpha = writeAllComponents;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool ColorMask::isRedEnabled() const
|
|
{
|
|
return m_writeRed;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool ColorMask::isGreenEnabled() const
|
|
{
|
|
return m_writeGreen;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool ColorMask::isBlueEnabled() const
|
|
{
|
|
return m_writeBlue;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool ColorMask::isAlphaEnabled() const
|
|
{
|
|
return m_writeAlpha;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void ColorMask::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
GLboolean writeRed = m_writeRed ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
|
|
GLboolean writeGreen = m_writeGreen ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
|
|
GLboolean writeBlue = m_writeBlue ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
|
|
GLboolean writeAlpha = m_writeAlpha ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
|
|
|
|
glColorMask(writeRed, writeGreen, writeBlue, writeAlpha);
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::CullFace
|
|
/// \ingroup Render
|
|
///
|
|
/// Encapsulate OpenGL glCullFace() and glEnable(GL_CULL_FACE) functions.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
CullFace::CullFace(bool enableCulling, Mode faceMode)
|
|
: RenderState(CULL_FACE),
|
|
m_enableCulling(enableCulling),
|
|
m_faceMode(faceMode)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void CullFace::enable(bool enableCulling)
|
|
{
|
|
m_enableCulling = enableCulling;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool CullFace::isEnabled() const
|
|
{
|
|
return m_enableCulling;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void CullFace::setMode(Mode faceMode)
|
|
{
|
|
m_faceMode = faceMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
CullFace::Mode CullFace::mode() const
|
|
{
|
|
return m_faceMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void CullFace::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
if (m_enableCulling)
|
|
{
|
|
if (m_faceMode == BACK)
|
|
{
|
|
glCullFace(GL_BACK);
|
|
}
|
|
else if (m_faceMode == FRONT)
|
|
{
|
|
glCullFace(GL_FRONT);
|
|
}
|
|
else
|
|
{
|
|
glCullFace(GL_FRONT_AND_BACK);
|
|
}
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
}
|
|
else
|
|
{
|
|
glDisable(GL_CULL_FACE);
|
|
}
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::FrontFace
|
|
/// \ingroup Render
|
|
///
|
|
/// Encapsulate OpenGL glFrontFace() used to specify polygon winding. Used together with CullFace
|
|
/// render state and the gl_FrontFacing bultin shader input variable.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_FrontFacing.xml
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
FrontFace::FrontFace(Mode faceMode)
|
|
: RenderState(FRONT_FACE),
|
|
m_faceMode(faceMode)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void FrontFace::setMode(Mode faceMode)
|
|
{
|
|
m_faceMode = faceMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
FrontFace::Mode FrontFace::mode() const
|
|
{
|
|
return m_faceMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void FrontFace::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
if (m_faceMode == CW)
|
|
{
|
|
glFrontFace(GL_CW);
|
|
}
|
|
else
|
|
{
|
|
glFrontFace(GL_CCW);
|
|
}
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::Depth
|
|
/// \ingroup Render
|
|
///
|
|
/// Encapsulate OpenGL glEnable(GL_DEPTH_TEST), glDepthFunc() and glDepthMask() functions.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml
|
|
///
|
|
/// \todo
|
|
/// Add support for glDepthRange() if needed.
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Depth::Depth(bool depthTest, Function func, bool depthWrite)
|
|
: RenderState(DEPTH)
|
|
{
|
|
m_enableDepthTest = depthTest;
|
|
m_depthFunc = func;
|
|
m_enableDepthWrite = depthWrite;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Specifies the depth comparison function.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Depth::setFunction(Function func)
|
|
{
|
|
m_depthFunc = func;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Enable or disable depth testing and updating of the depth buffer.
|
|
///
|
|
/// \param enableTest Specify true to enable testing against and updating of depth buffer.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml with GL_DEPTH_TEST
|
|
///
|
|
/// From OpenGL docs:
|
|
/// If enabled, do depth comparisons and update the depth buffer. Note that even if the depth buffer
|
|
/// exists and the depth mask is non-zero, the depth buffer is not updated if the depth test is disabled
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Depth::enableDepthTest(bool enableTest)
|
|
{
|
|
m_enableDepthTest = enableTest;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Enable or disable writing into the depth buffer
|
|
///
|
|
/// \param enableWrite Specify true to enable writing to depth buffer, false to disable. The default is true.
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Depth::enableDepthWrite(bool enableWrite)
|
|
{
|
|
m_enableDepthWrite = enableWrite;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Depth::Function Depth::function() const
|
|
{
|
|
return m_depthFunc;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool Depth::isDepthTestEnabled() const
|
|
{
|
|
return m_enableDepthTest;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool Depth::isDepthWriteEnabled() const
|
|
{
|
|
return m_enableDepthWrite;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Specify the depth setting to OpenGL.
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Depth::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
if (m_enableDepthTest)
|
|
{
|
|
GLenum depthFuncOGL = depthFuncOpenGL();
|
|
glDepthFunc(depthFuncOGL);
|
|
|
|
GLboolean enableDepthWrite = m_enableDepthWrite ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
|
|
glDepthMask(enableDepthWrite);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
else
|
|
{
|
|
glDisable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvfGLenum Depth::depthFuncOpenGL() const
|
|
{
|
|
switch (m_depthFunc)
|
|
{
|
|
case NEVER: return GL_NEVER;
|
|
case LESS: return GL_LESS;
|
|
case EQUAL: return GL_EQUAL;
|
|
case LEQUAL: return GL_LEQUAL;
|
|
case GREATER: return GL_GREATER;
|
|
case NOTEQUAL: return GL_NOTEQUAL;
|
|
case GEQUAL: return GL_GEQUAL;
|
|
case ALWAYS: return GL_ALWAYS;
|
|
}
|
|
|
|
CVF_FAIL_MSG("Unhandled depth func");
|
|
return 0;
|
|
}
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::Point
|
|
/// \ingroup Render
|
|
///
|
|
///
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Point::Point(Mode sizeMode)
|
|
: RenderState(POINT),
|
|
m_sizeMode(sizeMode),
|
|
m_pointSprite(false),
|
|
m_pointSize(1.0f)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Point::setMode(Mode sizeMode)
|
|
{
|
|
m_sizeMode = sizeMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Point::Mode Point::mode() const
|
|
{
|
|
return m_sizeMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Point::enablePointSprite(bool enable)
|
|
{
|
|
m_pointSprite = enable;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool Point::isPointSpriteEnabled() const
|
|
{
|
|
return m_pointSprite;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Point::setSize(float pointSize)
|
|
{
|
|
m_pointSize = pointSize;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
float Point::size() const
|
|
{
|
|
return m_pointSize;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Point::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
// OpenGL ES does not support fixed point size
|
|
// Point size is always specified using GLSL's gl_PointSize
|
|
#ifndef CVF_OPENGL_ES
|
|
bool openGL2Support = oglContext->capabilities()->supportsOpenGL2();
|
|
|
|
if (m_sizeMode == FIXED_SIZE)
|
|
{
|
|
if (openGL2Support)
|
|
{
|
|
glDisable(GL_PROGRAM_POINT_SIZE);
|
|
}
|
|
|
|
glPointSize(m_pointSize);
|
|
}
|
|
else
|
|
{
|
|
if (openGL2Support)
|
|
{
|
|
glEnable(GL_PROGRAM_POINT_SIZE);
|
|
}
|
|
else
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support program point size.");
|
|
}
|
|
}
|
|
|
|
if (openGL2Support)
|
|
{
|
|
if (m_pointSprite) glEnable(GL_POINT_SPRITE);
|
|
else glDisable(GL_POINT_SPRITE);
|
|
}
|
|
else
|
|
{
|
|
if (m_pointSprite)
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support point sprites.");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::PolygonMode
|
|
/// \ingroup Render
|
|
///
|
|
///
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
PolygonMode::PolygonMode(Mode frontAndBackFaceMode)
|
|
: RenderState(POLYGON_MODE),
|
|
m_frontFaceMode(frontAndBackFaceMode),
|
|
m_backFaceMode(frontAndBackFaceMode)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonMode::set(Mode frontAndBackMode)
|
|
{
|
|
m_frontFaceMode = frontAndBackMode;
|
|
m_backFaceMode = frontAndBackMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonMode::setFrontFace(Mode mode)
|
|
{
|
|
m_frontFaceMode = mode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonMode::setBackFace(Mode mode)
|
|
{
|
|
m_backFaceMode = mode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
PolygonMode::Mode PolygonMode::frontFace() const
|
|
{
|
|
return m_frontFaceMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
PolygonMode::Mode PolygonMode::backFace() const
|
|
{
|
|
return m_backFaceMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonMode::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
#ifndef CVF_OPENGL_ES
|
|
if (m_frontFaceMode == m_backFaceMode)
|
|
{
|
|
glPolygonMode(GL_FRONT_AND_BACK, polygonModeOpenGL(m_frontFaceMode));
|
|
}
|
|
else
|
|
{
|
|
glPolygonMode(GL_FRONT, polygonModeOpenGL(m_frontFaceMode));
|
|
glPolygonMode(GL_BACK, polygonModeOpenGL(m_backFaceMode));
|
|
}
|
|
#endif
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvfGLenum PolygonMode::polygonModeOpenGL(Mode mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
#ifndef CVF_OPENGL_ES
|
|
case FILL: return GL_FILL;
|
|
case LINE: return GL_LINE;
|
|
case POINT: return GL_POINT;
|
|
default: CVF_FAIL_MSG("Unhandled polygon mode");
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::PolygonOffset
|
|
/// \ingroup Render
|
|
///
|
|
/// Encapsulate OpenGL glPolygonOffset() and glEnable()/glDisable() with GL_POLYGON_OFFSET_FILL/LINE/POINT
|
|
///
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml
|
|
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
|
|
///
|
|
//==================================================================================================
|
|
PolygonOffset::PolygonOffset()
|
|
: RenderState(POLYGON_OFFSET),
|
|
m_factor(0.0f),
|
|
m_units(0.0f),
|
|
m_enableFillMode(false),
|
|
m_enableLineMode(false),
|
|
m_enablePointMode(false)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::enableFillMode(bool enableFill)
|
|
{
|
|
m_enableFillMode = enableFill;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::enableLineMode(bool enableLine)
|
|
{
|
|
m_enableLineMode = enableLine;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::enablePointMode(bool enablePoint)
|
|
{
|
|
m_enablePointMode = enablePoint;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool PolygonOffset::isFillModeEnabled() const
|
|
{
|
|
return m_enableFillMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool PolygonOffset::isLineModeEnabled() const
|
|
{
|
|
return m_enableLineMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool PolygonOffset::isPointModeEnabled() const
|
|
{
|
|
return m_enablePointMode;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::setFactor(float factor)
|
|
{
|
|
m_factor = factor;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::setUnits(float units)
|
|
{
|
|
m_units = units;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
float PolygonOffset::factor() const
|
|
{
|
|
return m_factor;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
float PolygonOffset::units() const
|
|
{
|
|
return m_units;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::configurePolygonPositiveOffset()
|
|
{
|
|
m_enableFillMode = true;
|
|
m_enableLineMode = false;
|
|
m_enablePointMode = false;
|
|
m_factor = 1.0;
|
|
m_units = 1.0;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::configureLineNegativeOffset()
|
|
{
|
|
m_enableFillMode = false;
|
|
m_enableLineMode = true;
|
|
m_enablePointMode = false;
|
|
m_factor = -1.0;
|
|
m_units = -1.0;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void PolygonOffset::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
if (m_enableFillMode ||
|
|
m_enableLineMode ||
|
|
m_enablePointMode)
|
|
{
|
|
glPolygonOffset(m_factor, m_units);
|
|
}
|
|
|
|
if (m_enableFillMode) glEnable(GL_POLYGON_OFFSET_FILL);
|
|
else glDisable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
#ifndef CVF_OPENGL_ES
|
|
if (m_enableLineMode) glEnable(GL_POLYGON_OFFSET_LINE);
|
|
else glDisable(GL_POLYGON_OFFSET_LINE);
|
|
|
|
if (m_enablePointMode) glEnable(GL_POLYGON_OFFSET_POINT);
|
|
else glDisable(GL_POLYGON_OFFSET_POINT);
|
|
#endif
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::TextureBindings
|
|
/// \ingroup Render
|
|
///
|
|
/// \warning Requires OpenGL2 support
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
TextureBindings::TextureBindings()
|
|
: RenderState(TEXTURE_BINDINGS),
|
|
m_bindingCount(0)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
TextureBindings::TextureBindings(Texture* texture, Sampler* sampler, const char* samplerUniformName)
|
|
: RenderState(TEXTURE_BINDINGS),
|
|
m_bindingCount(0)
|
|
{
|
|
addBinding(texture, sampler, samplerUniformName);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
TextureBindings::~TextureBindings()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void TextureBindings::addBinding(Texture* texture, Sampler* sampler, const char* samplerUniformName)
|
|
{
|
|
CVF_ASSERT(m_bindingCount < MAX_TEXTURE_UNITS - 1);
|
|
CVF_ASSERT(texture && sampler && samplerUniformName);
|
|
|
|
m_bindings[m_bindingCount].sampler = sampler;
|
|
m_bindings[m_bindingCount].texture = texture;
|
|
m_bindings[m_bindingCount].samplerUniformName = samplerUniformName;
|
|
m_bindingCount++;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
int TextureBindings::bindingCount() const
|
|
{
|
|
return m_bindingCount;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Texture* TextureBindings::texture(int bindingIdx)
|
|
{
|
|
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
|
|
return m_bindings[bindingIdx].texture.p();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const Texture* TextureBindings::texture(int bindingIdx) const
|
|
{
|
|
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
|
|
return m_bindings[bindingIdx].texture.p();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const Sampler* TextureBindings::sampler(int bindingIdx) const
|
|
{
|
|
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
|
|
return m_bindings[bindingIdx].sampler.p();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
Sampler* TextureBindings::sampler(int bindingIdx)
|
|
{
|
|
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
|
|
return m_bindings[bindingIdx].sampler.p();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
String TextureBindings::samplerUniformName(int bindingIdx) const
|
|
{
|
|
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
|
|
return m_bindings[bindingIdx].samplerUniformName;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void TextureBindings::setupTextures(OpenGLContext* oglContext)
|
|
{
|
|
CVF_CALLSITE_OPENGL(oglContext);
|
|
|
|
const OpenGLCapabilities* oglCaps = oglContext->capabilities();
|
|
if (!oglCaps->supportsOpenGL2())
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support texture setup using TextureBindings.");
|
|
return;
|
|
}
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
int i;
|
|
for (i = 0; i < m_bindingCount; i++)
|
|
{
|
|
Texture* texture = m_bindings[i].texture.p();
|
|
|
|
if (texture->textureOglId() == 0)
|
|
{
|
|
glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
|
|
texture->setupTexture(oglContext);
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
else
|
|
{
|
|
// Handle case where mipmap generation is enabled, but the mipmaps are not present
|
|
// This will typically happen if the texture has been rendered to using an FBO
|
|
// In that case the texture exists, but no mipmaps have yet been generated
|
|
if (texture->isMipmapGenerationEnabled() && !texture->hasMipmap())
|
|
{
|
|
if (oglCaps->hasCapability(OpenGLCapabilities::GENERATE_MIPMAP_FUNC))
|
|
{
|
|
glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
|
|
texture->generateMipmap(oglContext);
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
else
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support explicit mipmap generation.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void TextureBindings::applyOpenGL(OpenGLContext* oglContext) const
|
|
{
|
|
CVF_CALLSITE_OPENGL(oglContext);
|
|
|
|
// The apply function needs to work for all contexts in its default state
|
|
// so just return if no bindings have been set
|
|
if (m_bindingCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!oglContext->capabilities()->supportsOpenGL2())
|
|
{
|
|
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support TextureBinding application.");
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
for (i = 0; i < m_bindingCount; i++)
|
|
{
|
|
const Texture* texture = m_bindings[i].texture.p();
|
|
const Sampler* sampler = m_bindings[i].sampler.p();
|
|
CVF_ASSERT(texture && sampler);
|
|
|
|
glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
|
|
|
|
texture->bind(oglContext);
|
|
texture->setupTextureParamsFromSampler(oglContext, *sampler);
|
|
|
|
CVF_CHECK_OGL(oglContext);
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Specify the mapping between the sampler name in the shader program and the texture unit
|
|
/// This is done by providing an Int Uniform with the name of the sampler and the index of the
|
|
/// texture unit.
|
|
//--------------------------------------------------------------------------------------------------
|
|
void TextureBindings::applySamplerTextureUnitUniforms(OpenGLContext* oglContext, ShaderProgram* shaderProgram) const
|
|
{
|
|
CVF_ASSERT(shaderProgram);
|
|
|
|
int i;
|
|
for (i = 0; i < m_bindingCount; i++)
|
|
{
|
|
UniformInt uniform(m_bindings[i].samplerUniformName.toAscii().ptr(), i);
|
|
shaderProgram->applyUniform(oglContext, uniform);
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace cvf
|
|
|