//################################################################################################## // // 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 <> // for more details. // //################################################################################################## #include "cvfBase.h" #include "cvfRenderStateBlending.h" #include "cvfAssert.h" #include "cvfOpenGL.h" #include "cvfOpenGLCapabilities.h" namespace cvf { //================================================================================================== /// /// \class cvf::RenderStateBlending /// \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) //================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RenderStateBlending::RenderStateBlending() : 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 RenderStateBlending::enableBlending(bool blend/*, uint drawBufferIndex*/) { m_enableBlending = blend; } //-------------------------------------------------------------------------------------------------- /// glBlendFunc() //-------------------------------------------------------------------------------------------------- void RenderStateBlending::setFunction(Function source, Function destination) { m_funcSourceRGB = source; m_funcSourceAlpha = source; m_funcDestinationRGB = destination; m_funcDestinationAlpha = destination; } //-------------------------------------------------------------------------------------------------- /// glBlendEquation(). Requires OpenGL 2.0 //-------------------------------------------------------------------------------------------------- void RenderStateBlending::setEquation(Equation eq) { m_equationRGB = eq; m_equationAlpha = eq; } //-------------------------------------------------------------------------------------------------- /// glBlendFuncSeparate(). Requires OpenGL 2.0 //-------------------------------------------------------------------------------------------------- void RenderStateBlending::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 RenderStateBlending::setEquationSeparate(Equation equationRGB, Equation equationAlpha) { m_equationRGB = equationRGB; m_equationAlpha = equationAlpha; } //-------------------------------------------------------------------------------------------------- /// glBlendColor(). Requires OpenGL 2.0 //-------------------------------------------------------------------------------------------------- void RenderStateBlending::setBlendColor(Color4f blendColor) { m_blendColor = blendColor; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RenderStateBlending::configureTransparencyBlending() { m_enableBlending = true; setFunction(SRC_ALPHA, ONE_MINUS_SRC_ALPHA); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RenderStateBlending::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 RenderStateBlending::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 RenderStateBlending::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; } } // namespace cvf