Commit 84d2e0d5 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Improved GeometryRenderer and RenderTargetCompositor:

* GeometryRenderer supports textured rendering
* GeometryRenderer and RenderTargetCompositor support alpha blending of (semi-)transparent surfaces
* Updated GeometryRendererDemo to show a demo implementation of the new features
parent bd6d9177
......@@ -23,7 +23,7 @@
// ================================================================================================
#include "tools/shading.frag"
#include "tools/texture3d.frag"
#include "tools/texture2d.frag"
// input from geometry shader
in vec3 geom_Position;
......@@ -36,7 +36,7 @@ noperspective in vec3 geom_EdgeDistance;
out vec4 out_Color;
// additional uniforms
uniform bool _useSolidColor;
uniform int _coloringMode;
uniform vec4 _solidColor;
uniform vec4 _wireframeColor;
uniform float _lineWidth = 1.0;
......@@ -44,9 +44,22 @@ uniform float _lineWidth = 1.0;
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;
#ifdef ENABLE_TEXTURING
uniform sampler2D _texture;
uniform TextureParameters2D _textureParams;
#endif
void main() {
out_Color = _useSolidColor ? _solidColor : geom_Color;
out_Color = vec4(1.0, 0.5, 0.0, 1.0);
#ifdef ENABLE_TEXTURING
out_Color = texture(_texture, geom_TexCoord.xy);
#else
if (_coloringMode == 0)
out_Color = geom_Color;
else if (_coloringMode == 1)
out_Color = _solidColor;
#endif
#ifdef ENABLE_SHADING
// perform Phong shading
......
......@@ -22,35 +22,6 @@
//
// ================================================================================================
/**********************************************************************
* *
* Voreen - The Volume Rendering Engine *
* *
* Copyright (C) 2005-2012 Visualization and Computer Graphics Group, *
* Department of Computer Science, University of Muenster, Germany. *
* <http://viscg.uni-muenster.de> *
* *
* This file is part of the Voreen software package. Voreen is free *
* software: you can redistribute it and/or modify it under the terms *
* of the GNU General Public License version 2 as published by the *
* Free Software Foundation. *
* *
* Voreen 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 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* in the file "LICENSE.txt" along with this program. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
* The authors reserve all rights not expressly granted herein. For *
* non-commercial academic use see the license exception specified in *
* the file "LICENSE-academic.txt". To get information about *
* commercial licensing please contact the authors. *
* *
**********************************************************************/
in vec3 ex_TexCoord;
out vec4 out_Color;
......@@ -67,17 +38,20 @@ uniform TextureParameters2D _secondTexParams;
uniform int _compositingMethod;
uniform float _alpha;
uniform bool _enableBackground;
void main() {
float depth = 1.0;
if (_compositingMethod == 0) {
// only first
out_Color = texture(_firstColor, ex_TexCoord.xy);
gl_FragDepth = texture(_firstDepth, ex_TexCoord.xy).r;
depth = texture(_firstDepth, ex_TexCoord.xy).r;
}
else if (_compositingMethod == 1) {
// only second
out_Color = texture(_secondColor, ex_TexCoord.xy);
gl_FragDepth = texture(_secondDepth, ex_TexCoord.xy).r;
depth = texture(_secondDepth, ex_TexCoord.xy).r;
}
else if (_compositingMethod == 2) {
// alpha blending
......@@ -87,7 +61,7 @@ void main() {
float secondDepth = texture(_secondDepth, ex_TexCoord.xy).r;
out_Color = mix(firstColor, secondColor, _alpha);
gl_FragDepth = min(firstDepth, secondDepth);
depth = min(firstDepth, secondDepth);
}
else if (_compositingMethod == 3) {
// difference
......@@ -97,20 +71,22 @@ void main() {
float secondDepth = texture(_secondDepth, ex_TexCoord.xy).r;
out_Color = vec4(vec3(1.0) - abs(firstColor - secondColor).xyz, max(firstColor.w, secondColor.w));
gl_FragDepth = min(firstDepth, secondDepth);
depth = min(firstDepth, secondDepth);
}
else if (_compositingMethod == 4) {
// depth test
vec4 firstColor = texture(_firstColor, ex_TexCoord.xy);
float firstDepth = texture(_firstDepth, ex_TexCoord.xy).r;
vec4 secondColor = texture(_secondColor, ex_TexCoord.xy);
float secondDepth = texture(_secondDepth, ex_TexCoord.xy).r;
if (firstDepth > secondDepth) {
out_Color = texture(_secondColor, ex_TexCoord.xy);
gl_FragDepth = secondDepth;
out_Color = mix(firstColor, secondColor, secondColor.a);
depth = secondDepth;
}
else {
out_Color = texture(_firstColor, ex_TexCoord.xy);
gl_FragDepth = firstDepth;
out_Color = mix(secondColor, firstColor, firstColor.a);
depth = firstDepth;
}
}
else {
......@@ -118,8 +94,9 @@ void main() {
out_Color = vec4(0.0);
}
if (out_Color.a == 0) {
renderBackground(ex_TexCoord.xy, out_Color);
}
if (_enableBackground)
out_Color = blendBackground(ex_TexCoord.xy, out_Color);
gl_FragDepth = depth;
}
......@@ -24,7 +24,10 @@
#include "geometryrendererdemo.h"
#include "tgt/texturereadertga.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
......@@ -39,7 +42,9 @@ namespace campvis {
, _geometryReader()
, _lvRenderer(&_canvasSize)
, _teapotRenderer(&_canvasSize)
, _compositor(&_canvasSize)
, _cubeRenderer(&_canvasSize)
, _compositor1(&_canvasSize)
, _compositor2(&_canvasSize)
, _trackballEH(0)
{
addProperty(&_camera);
......@@ -50,7 +55,9 @@ namespace campvis {
addProcessor(&_geometryReader);
addProcessor(&_teapotRenderer);
addProcessor(&_lvRenderer);
addProcessor(&_compositor);
addProcessor(&_cubeRenderer);
addProcessor(&_compositor1);
addProcessor(&_compositor2);
}
GeometryRendererDemo::~GeometryRendererDemo() {
......@@ -61,18 +68,29 @@ namespace campvis {
void GeometryRendererDemo::init() {
AutoEvaluationPipeline::init();
// load textureData from file
tgt::TextureReaderTga trt;
tgt::Texture* campTexture = trt.loadTexture(CAMPVIS_SOURCE_DIR "/modules/vis/sampledata/camplogo.tga", tgt::Texture::LINEAR);
ImageData* textureData = new ImageData(2, campTexture->getDimensions(), campTexture->getNumChannels());
ImageRepresentationGL::create(textureData, campTexture);
getDataContainer().addData("CampTexture", textureData);
// connect slots
_geometryReader.s_validated.connect(this, &GeometryRendererDemo::onProcessorValidated);
// create Teapot
MultiIndexedGeometry* teapot = GeometryDataFactory::createTeapot();
teapot->applyTransformation(tgt::mat4::createTranslation(tgt::vec3(5.f, 10.f, 5.f)) * tgt::mat4::createScale(tgt::vec3(16.f)));
teapot->applyTransformationToVertices(tgt::mat4::createTranslation(tgt::vec3(5.f, 10.f, 5.f)) * tgt::mat4::createScale(tgt::vec3(16.f)));
getDataContainer().addData("teapot", teapot);
_trackballEH->reinitializeCamera(teapot);
// create cube
MeshGeometry* cube = GeometryDataFactory::createCube(tgt::Bounds(tgt::vec3(7.f), tgt::vec3(9.f)), tgt::Bounds(tgt::vec3(0.f), tgt::vec3(1.f)));
getDataContainer().addData("cube", cube);
// setup pipeline
_camera.addSharedProperty(&_lvRenderer.p_camera);
_camera.addSharedProperty(&_teapotRenderer.p_camera);
_camera.addSharedProperty(&_cubeRenderer.p_camera);
_geometryReader.p_url.setValue(CAMPVIS_SOURCE_DIR "/modules/vis/sampledata/left_ventricle_mesh.vtk");
_geometryReader.p_targetImageID.setValue("reader.output");
......@@ -80,20 +98,33 @@ namespace campvis {
_lvRenderer.p_geometryID.setValue("reader.output");
_lvRenderer.p_renderTargetID.setValue("lv.render");
_lvRenderer.p_renderMode.selectById("triangles");
_lvRenderer.p_solidColor.setValue(tgt::vec4(0.8f, 0.f, 0.f, 1.f));
_lvRenderer.p_solidColor.setValue(tgt::vec4(0.8f, 0.f, 0.f, .9f));
_teapotRenderer.p_geometryID.setValue("teapot");
_teapotRenderer.p_renderTargetID.setValue("teapot.render");
_teapotRenderer.p_renderMode.selectById("trianglestrip");
_teapotRenderer.p_showWireframe.setValue(false);
_teapotRenderer.p_solidColor.setValue(tgt::vec4(0.75f, 0.75f, 0.75f, 1.f));
_compositor.p_firstImageId.setValue("lv.render");
_compositor.p_secondImageId.setValue("teapot.render");
_compositor.p_compositingMethod.selectById("depth");
_compositor.p_targetImageId.setValue("combine");
_renderTargetID.setValue("combine");
_teapotRenderer.p_solidColor.setValue(tgt::vec4(1.f, 0.5f, 0.f, 1.f));
_cubeRenderer.p_geometryID.setValue("cube");
_cubeRenderer.p_renderTargetID.setValue("cube.render");
_cubeRenderer.p_renderMode.selectById("polygon");
_cubeRenderer.p_showWireframe.setValue(false);
_cubeRenderer.p_textureID.setValue("CampTexture");
_cubeRenderer.p_coloringMode.selectByOption(GeometryRenderer::TEXTURE_COLOR);
_compositor1.p_firstImageId.setValue("lv.render");
_compositor1.p_secondImageId.setValue("teapot.render");
_compositor1.p_compositingMethod.selectById("depth");
_compositor1.p_targetImageId.setValue("combine1");
_compositor1.p_enableBackground.setValue(false);
_compositor2.p_firstImageId.setValue("combine1");
_compositor2.p_secondImageId.setValue("cube.render");
_compositor2.p_compositingMethod.selectById("depth");
_compositor2.p_targetImageId.setValue("combine2");
_renderTargetID.setValue("combine2");
}
void GeometryRendererDemo::deinit() {
......@@ -106,10 +137,12 @@ namespace campvis {
// update camera
ScopedTypedData<IHasWorldBounds> lv(*_data, _geometryReader.p_targetImageID.getValue());
ScopedTypedData<IHasWorldBounds> teapot(*_data, "teapot");
ScopedTypedData<IHasWorldBounds> cube(*_data, "cube");
if (lv != 0 && teapot != 0) {
tgt::Bounds unionBounds;
unionBounds.addVolume(lv->getWorldBounds());
unionBounds.addVolume(teapot->getWorldBounds());
unionBounds.addVolume(cube->getWorldBounds());
_trackballEH->reinitializeCamera(unionBounds);
}
......
......@@ -68,7 +68,9 @@ namespace campvis {
VtkImageReader _geometryReader;
GeometryRenderer _lvRenderer;
GeometryRenderer _teapotRenderer;
RenderTargetCompositor _compositor;
GeometryRenderer _cubeRenderer;
RenderTargetCompositor _compositor1;
RenderTargetCompositor _compositor2;
TrackballNavigationEventListener* _trackballEH;
......
......@@ -31,6 +31,7 @@
#include "core/datastructures/imagedata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/meshgeometry.h"
#include "core/pipeline/processordecoratorshading.h"
......@@ -45,32 +46,41 @@ namespace campvis {
GenericOption<GLenum>("polygon", "GL_POLYGON", GL_POLYGON)
};
static const GenericOption<GeometryRenderer::ColoringMode> coloringOptions[3] = {
GenericOption<GeometryRenderer::ColoringMode>("GeometryColor", "Original Geometry Color", GeometryRenderer::GEOMETRY_COLOR),
GenericOption<GeometryRenderer::ColoringMode>("SolidColor", "Solid Color", GeometryRenderer::SOLID_COLOR),
GenericOption<GeometryRenderer::ColoringMode>("TextureColor", "Color from Texture Lookup", GeometryRenderer::TEXTURE_COLOR),
};
const std::string GeometryRenderer::loggerCat_ = "CAMPVis.modules.vis.GeometryRenderer";
GeometryRenderer::GeometryRenderer(IVec2Property* viewportSizeProp)
: VisualizationProcessor(viewportSizeProp)
, p_geometryID("geometryID", "Input Geometry ID", "gr.input", DataNameProperty::READ)
, p_textureID("TextureId", "Input Texture ID (optional)", "gr.inputtexture", DataNameProperty::READ)
, p_renderTargetID("p_renderTargetID", "Output Image", "gr.output", DataNameProperty::WRITE)
, p_camera("camera", "Camera")
, p_renderMode("RenderMode", "Render Mode", renderOptions, 7, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES)
, p_useSolidColor("UseSolidColor", "Use Solid Color", true, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES)
, p_renderMode("RenderMode", "Render Mode", renderOptions, 7, INVALID_RESULT | INVALID_PROPERTIES)
, p_coloringMode("ColoringMode", "ColoringMode", coloringOptions, 3, INVALID_RESULT | INVALID_SHADER | INVALID_PROPERTIES)
, p_solidColor("SolidColor", "Solid Color", tgt::vec4(1.f, .5f, 0.f, 1.f), tgt::vec4(0.f), tgt::vec4(1.f))
, p_pointSize("PointSize", "Point Size", 3.f, .1f, 10.f)
, p_lineWidth("LineWidth", "Line Width", 1.f, .1f, 10.f)
, p_showWireframe("ShowWireframe", "Show Wireframe", true, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_PROPERTIES)
, p_showWireframe("ShowWireframe", "Show Wireframe", true, INVALID_RESULT | INVALID_SHADER | INVALID_PROPERTIES)
, p_wireframeColor("WireframeColor", "Wireframe Color", tgt::vec4(1.f, 1.f, 1.f, 1.f), tgt::vec4(0.f), tgt::vec4(1.f))
, _pointShader(0)
, _meshShader(0)
{
p_coloringMode.selectByOption(SOLID_COLOR);
addDecorator(new ProcessorDecoratorShading());
addProperty(&p_geometryID);
addProperty(&p_textureID);
addProperty(&p_renderTargetID);
addProperty(&p_camera);
addProperty(&p_renderMode);
addProperty(&p_useSolidColor);
addProperty(&p_coloringMode);
addProperty(&p_solidColor);
addProperty(&p_pointSize);
......@@ -102,8 +112,23 @@ namespace campvis {
void GeometryRenderer::updateResult(DataContainer& data) {
ScopedTypedData<GeometryData> proxyGeometry(data, p_geometryID.getValue());
ScopedTypedData<RenderData> rd(data, p_textureID.getValue());
ImageRepresentationGL::ScopedRepresentation repGl(data, p_textureID.getValue());
const ImageRepresentationGL* texture = nullptr;
if (p_coloringMode.getOptionValue() == TEXTURE_COLOR) {
if (proxyGeometry->hasTextureCoordinates()) {
if (rd != nullptr && rd->getNumColorTextures() > 0)
texture = rd->getColorTexture()->getRepresentation<ImageRepresentationGL>();
else if (repGl != nullptr)
texture = repGl;
}
else {
LERROR("Cannot use textured rendering since input geometry has no texture coordinates!");
}
}
if (proxyGeometry != 0 && _pointShader != 0 && _meshShader != 0) {
if (proxyGeometry != 0 && (p_coloringMode.getOptionValue() != TEXTURE_COLOR || texture != nullptr) && _pointShader != 0 && _meshShader != 0) {
// select correct shader
tgt::Shader* leShader = 0;
if (p_renderMode.getOptionValue() == GL_POINTS || p_renderMode.getOptionValue() == GL_LINES || p_renderMode.getOptionValue() == GL_LINE_STRIP)
......@@ -115,8 +140,15 @@ namespace campvis {
tgt::vec2 halfViewport = tgt::vec2(getEffectiveViewportSize()) / 2.f;
tgt::mat4 viewportMatrix = tgt::mat4::createTranslation(tgt::vec3(halfViewport, 0.f)) * tgt::mat4::createScale(tgt::vec3(halfViewport, 1.f));
// set modelview and projection matrices
leShader->activate();
// bind texture if needed
tgt::TextureUnit tut, narf, blub, textureUnit;
tut.activate();
if (texture != nullptr)
texture->bind(leShader, textureUnit, "_texture", "_textureParams");
// set modelview and projection matrices
leShader->setIgnoreUniformLocationError(true);
decorateRenderProlog(data, leShader);
leShader->setUniform("_projectionMatrix", p_camera.getValue().getProjectionMatrix());
......@@ -125,7 +157,7 @@ namespace campvis {
leShader->setUniform("_computeNormals", proxyGeometry->getNormalsBuffer() == 0);
leShader->setUniform("_useSolidColor", p_useSolidColor.getValue());
leShader->setUniform("_coloringMode", p_coloringMode.getValue());
leShader->setUniform("_solidColor", p_solidColor.getValue());
leShader->setUniform("_wireframeColor", p_wireframeColor.getValue());
leShader->setUniform("_lineWidth", p_lineWidth.getValue());
......@@ -137,6 +169,8 @@ namespace campvis {
createAndAttachColorTexture();
createAndAttachDepthTexture();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearDepth(1.0f);
......@@ -155,7 +189,9 @@ namespace campvis {
decorateRenderEpilog(leShader);
leShader->deactivate();
glDepthFunc(GL_LESS);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
LGL_ERROR;
data.addData(p_renderTargetID.getValue(), new RenderData(_fbo));
......@@ -176,6 +212,9 @@ namespace campvis {
if (hasGeometryShader)
toReturn += "#define HAS_GEOMETRY_SHADER\n";
if (p_coloringMode.getOptionValue() == TEXTURE_COLOR)
toReturn += "#define ENABLE_TEXTURING\n";
return toReturn;
}
......@@ -188,7 +227,7 @@ namespace campvis {
}
void GeometryRenderer::updateProperties(DataContainer& dataContainer) {
p_solidColor.setVisible(p_useSolidColor.getValue());
p_solidColor.setVisible(p_coloringMode.getOptionValue() == SOLID_COLOR);
switch (p_renderMode.getOptionValue()) {
case GL_POINTS:
......
......@@ -45,6 +45,13 @@ namespace campvis {
*/
class GeometryRenderer : public VisualizationProcessor, public HasProcessorDecorators {
public:
/// Coloring mode for fragments used during rendering
enum ColoringMode {
GEOMETRY_COLOR = 0, ///< Original color as stored in geometry
SOLID_COLOR = 1, ///< Solid color set by property
TEXTURE_COLOR = 2 ///< Color determined from texture lookup
};
/**
* Constructs a new GeometryRenderer Processor
**/
......@@ -70,20 +77,21 @@ namespace campvis {
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
DataNameProperty p_geometryID; ///< ID for input geometry
DataNameProperty p_renderTargetID; ///< image ID for output image
DataNameProperty p_geometryID; ///< ID for input geometry
DataNameProperty p_textureID; ///< ID for input texture (optional)
DataNameProperty p_renderTargetID; ///< image ID for output image
CameraProperty p_camera;
GenericOptionProperty<GLenum> p_renderMode; ///< Render mode for the geometry
GenericOptionProperty<GLenum> p_renderMode; ///< Render mode for the geometry
GenericOptionProperty<ColoringMode> p_coloringMode; ///< Coloring mode for fragments used during rendering
BoolProperty p_useSolidColor; ///< Use solid color for rendering
Vec4Property p_solidColor; ///< rendering color
Vec4Property p_solidColor; ///< rendering color
FloatProperty p_pointSize; ///< Point Size when rendering points
FloatProperty p_lineWidth; ///< Line Width when rendering lines
FloatProperty p_pointSize; ///< Point Size when rendering points
FloatProperty p_lineWidth; ///< Line Width when rendering lines
BoolProperty p_showWireframe; ///< Show wire frame
Vec4Property p_wireframeColor; ///< Wireframe color
BoolProperty p_showWireframe; ///< Show wire frame
Vec4Property p_wireframeColor; ///< Wireframe color
protected:
......@@ -102,6 +110,7 @@ namespace campvis {
tgt::Shader* _pointShader;
tgt::Shader* _meshShader;
private:
static const std::string loggerCat_;
};
......
......@@ -53,6 +53,7 @@ namespace campvis {
, p_targetImageId("TargetImageId", "Output Image", "", DataNameProperty::WRITE)
, p_compositingMethod("CompositingMethod", "Compositing Method", compositingOptions, 5)
, p_alphaValue("AlphaValue", "AlphaValue", .5f, 0.f, 1.f)
, p_enableBackground("EnableBackground", "Enable Background", true)
, _shader(0)
{
addProperty(&p_firstImageId);
......@@ -60,6 +61,7 @@ namespace campvis {
addProperty(&p_targetImageId);
addProperty(&p_compositingMethod);
addProperty(&p_alphaValue);
addProperty(&p_enableBackground);
addDecorator(new ProcessorDecoratorBackground());
......@@ -98,11 +100,20 @@ namespace campvis {
secondImage->bind(_shader, secondColorUnit, secondDepthUnit, "_secondColor", "_secondDepth", "_secondTexParams");
_shader->setUniform("_compositingMethod", p_compositingMethod.getOptionValue());
_shader->setUniform("_alpha", p_alphaValue.getValue());
_shader->setUniform("_enableBackground", p_enableBackground.getValue());
decorateRenderProlog(data, _shader);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
glDepthFunc(GL_LESS);
glDisable(GL_DEPTH_TEST);
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
LGL_ERROR;
......
......@@ -85,6 +85,8 @@ namespace campvis {
GenericOptionProperty<CompositingMode> p_compositingMethod;
FloatProperty p_alphaValue;
BoolProperty p_enableBackground;
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment