Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ToonRenderer.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision: 18127 $ *
45 * $LastChangedBy: moebius $ *
46 * $Date: 2014-02-05 10:12:54 +0100 (Wed, 05 Feb 2014) $ *
47 * *
48 \*===========================================================================*/
49
50 #include <ACG/GL/acg_glew.hh>
51 #include "ToonRenderer.hh"
52
53 #include <OpenFlipper/common/GlobalOptions.hh>
54 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
55 #include <ACG/GL/ShaderCache.hh>
56 #include <ACG/GL/ScreenQuad.hh>
57 #include <ACG/GL/GLError.hh>
58
59 // =================================================
60
61 #define CELSHADING_INCLUDE_FILE "ToonRenderer/celshading.glsl"
62 #define OUTLINE_VERTEXSHADER_FILE "ToonRenderer/screenquad.glsl"
63 #define OUTLINE_FRAGMENTSHADER_FILE "ToonRenderer/outline.glsl"
64
65 class CelShadingModifier : public ACG::ShaderModifier{
66 public:
67
68 void modifyVertexIO( ACG::ShaderGenerator* _shader ) {
69 // include cel lighting functions defined in CELSHADING_INCLUDE_FILE
70 QString includeCelShading = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(CELSHADING_INCLUDE_FILE);
71 _shader->addIncludeFile(includeCelShading);
72
73 // add shader constant that defines the number of different intensity levels used in lighting
74 _shader->addUniform("float g_celPaletteSize", "//number of palettes/intensity levels for cel shading");
75 }
76
77 void modifyFragmentIO( ACG::ShaderGenerator* _shader ) {
78 // include cel lighting functions defined in CELSHADING_INCLUDE_FILE
79 QString includeCelShading = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(CELSHADING_INCLUDE_FILE);
80 _shader->addIncludeFile(includeCelShading);
81
82 // Note: We include the cel lighting functions in both shader stages
83 // because the ShaderGenerator may call modifyLightingCode() for either a vertex or fragment shader.
84 // It is not yet known in which stage the lighting is performed.
85
86
87 // Additionally write the depth of each fragment to a secondary render-target.
88 // This depth texture is used in a post-processing outlining step.
89 _shader->addOutput("float outDepth");
90 _shader->addUniform("float g_celPaletteSize", "//number of palettes/intensity levels for cel shading");
91 }
92
93
94 void modifyFragmentEndCode(QStringList* _code) {
95 _code->push_back("outDepth = gl_FragCoord.z;"); // write depth to secondary render texture
96 }
97
98 // modifier replaces default lighting with cel lighting
99 bool replaceDefaultLightingCode() {return true;}
100
101 void modifyLightingCode(QStringList* _code, int _lightId, ACG::ShaderGenLightType _lightType) {
102 // use cel shading functions instead of default lighting:
103
104 QString buf;
105
106 switch (_lightType) {
107 case ACG::SG_LIGHT_DIRECTIONAL:
108 buf.sprintf("sg_cColor.xyz += LitDirLight_Cel(sg_vPosVS.xyz, sg_vNormalVS, g_vLightDir_%d, g_cLightAmbient_%d, g_cLightDiffuse_%d, g_cLightSpecular_%d, g_celPaletteSize);", _lightId, _lightId, _lightId, _lightId);
109 break;
110
111 case ACG::SG_LIGHT_POINT:
112 buf.sprintf("sg_cColor.xyz += LitPointLight_Cel(sg_vPosVS.xyz, sg_vNormalVS, g_vLightPos_%d, g_cLightAmbient_%d, g_cLightDiffuse_%d, g_cLightSpecular_%d, g_vLightAtten_%d, g_celPaletteSize);", _lightId, _lightId, _lightId, _lightId, _lightId);
113 break;
114
115 case ACG::SG_LIGHT_SPOT:
116 buf.sprintf("sg_cColor.xyz += LitSpotLight_Cel(sg_vPosVS.xyz, sg_vNormalVS, g_vLightPos_%d, g_vLightDir_%d, g_cLightAmbient_%d, g_cLightDiffuse_%d, g_cLightSpecular_%d, g_vLightAtten_%d, g_vLightAngleExp_%d, g_celPaletteSize);", _lightId, _lightId, _lightId, _lightId, _lightId, _lightId, _lightId);
117 break;
118
119 default: break;
120 }
121
122 _code->push_back(buf);
123 }
124
125
126 static CelShadingModifier instance;
127 };
128
129
130 CelShadingModifier CelShadingModifier::instance;
131
132 // =================================================
133
134 ToonRenderer::ToonRenderer()
135 : progOutline_(0), paletteSize_(2.0f), outlineCol_(0.0f, 0.0f, 0.0f)
136 {
137 ACG::ShaderProgGenerator::registerModifier(&CelShadingModifier::instance);
138 }
139
140
141 ToonRenderer::~ToonRenderer() {
142 delete progOutline_;
143 }
144
145 QString ToonRenderer::checkOpenGL() {
146 if ( !ACG::openGLVersion(3, 2) )
147 return QString("Insufficient OpenGL Version! OpenGL 3.2 or higher required");
148
149 // Check extensions
150 QString missing("");
151 if ( !ACG::checkExtensionSupported("GL_ARB_vertex_buffer_object") )
152 missing += "GL_ARB_vertex_buffer_object extension missing\n";
153
154 #ifndef __APPLE__
155 if ( !ACG::checkExtensionSupported("GL_ARB_vertex_program") )
156 missing += "GL_ARB_vertex_program extension missing\n";
157 #endif
158
159 return missing;
160 }
161
162 void ToonRenderer::initializePlugin() {
163 }
164
165 QString ToonRenderer::renderObjectsInfo(bool _outputShaderInfo) {
166 std::vector<ACG::ShaderModifier*> modifiers;
167 modifiers.push_back(&CelShadingModifier::instance);
168 return dumpCurrentRenderObjectsToString(&sortedObjects_[0], _outputShaderInfo, &modifiers);
169 }
170
171 void ToonRenderer::render(ACG::GLState* _glState, Viewer::ViewerProperties& _properties) {
172
173 // Cel shading:
174 // - Restriction of the number of lighting intensity levels
175 // - in shader: l dot n is quantized based on the number of allowed shading tones.
176 // currently a constant sized step function is used to quantize the intensity
177
178 // collect renderobjects + prepare OpenGL state
179 prepareRenderingPipeline(_glState, _properties.drawMode(), PluginFunctions::getSceneGraphRootNode());
180
181 // init/update fbos
182 ViewerResources* viewRes = &viewerRes_[_properties.viewerId()];
183 viewRes->resize(_glState->viewport_width(), _glState->viewport_height());
184
185 // --------------------------------------------------
186 // 1st pass: draw scene to intermediate fbo
187
188 // enable color/depth write access
189 glDepthMask(1);
190 glColorMask(1,1,1,1);
191
192 // bind fbo for scene + depth tex
193 viewRes->scene_->bind();
194
195 glViewport(0, 0, _glState->viewport_width(), _glState->viewport_height());
196
197 // clear depth texture
198 glDrawBuffer(GL_COLOR_ATTACHMENT1);
199 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
200 glClear(GL_COLOR_BUFFER_BIT);
201
202 // clear scene color
203 glDrawBuffer(GL_COLOR_ATTACHMENT0);
204 ACG::Vec4f clearColor = _properties.backgroundColor();
205 glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0f);
206 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
207
208 // attachment0: scene colors
209 // attachment1: scene depth
210 GLenum colorDepthTarget[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
211 glDrawBuffers(2, colorDepthTarget);
212
213 // render every object
214 for (int i = 0; i < getNumRenderObjects(); ++i) {
215
216 // Take original shader and modify the output to take only the normal as the color
217 GLSL::Program* prog = ACG::ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, CelShadingModifier::instance);
218
219 int bRelink = 0;
220 if (prog->getFragDataLocation("outFragment") != 0) {
221 prog->bindFragDataLocation(0, "outFragment");
222 bRelink++;
223 }
224 if (prog->getFragDataLocation("outDepth") != 1) {
225 prog->bindFragDataLocation(1, "outDepth");
226 bRelink++;
227 }
228 if (bRelink)
229 prog->link();
230
231 prog->use();
232 prog->setUniform("g_celPaletteSize", paletteSize_);
233
234 renderObject(sortedObjects_[i], prog);
235 }
236
237 viewRes->scene_->unbind();
238
239 // ----------------------------------------------------------
240 // 2nd pass: compose final image with outlining as scene color * edge factor
241
242 if (!progOutline_)
243 progOutline_ = GLSL::loadProgram(OUTLINE_VERTEXSHADER_FILE, OUTLINE_FRAGMENTSHADER_FILE);
244
245 // restore previous fbo
246 restoreInputFbo();
247
248
249 // enable color/depth write access
250 glDepthMask(1);
251 glColorMask(1,1,1,1);
252
253 // note: using glDisable(GL_DEPTH_TEST) not only disables depth testing,
254 // but actually discards any write operations to the depth buffer.
255 // However, we can provide scene depth for further post-processing.
256 // -> Enable depth testing with func=always
257 glEnable(GL_DEPTH_TEST);
258 glDepthFunc(GL_ALWAYS);
259 glDisable(GL_BLEND);
260
261 // setup composition shader
262 progOutline_->use();
263 progOutline_->setUniform("samplerScene", 0);
264 progOutline_->setUniform("samplerDepth", 1);
265 progOutline_->setUniform("texcoordOffset", ACG::Vec2f(1.0f / float(viewRes->scene_->width()), 1.0f / float(viewRes->scene_->height()) ));
266 progOutline_->setUniform("clipPlanes", ACG::Vec2f(_glState->near_plane(), _glState->far_plane()));
267 progOutline_->setUniform("outlineColor", outlineCol_);
268
269 glActiveTexture(GL_TEXTURE1);
270 glBindTexture(GL_TEXTURE_2D, viewRes->scene_->getAttachment(GL_COLOR_ATTACHMENT1));
271
272 glActiveTexture(GL_TEXTURE0);
273 glBindTexture(GL_TEXTURE_2D, viewRes->scene_->getAttachment(GL_COLOR_ATTACHMENT0));
274
275
276 ACG::ScreenQuad::draw(progOutline_);
277
278 progOutline_->disable();
279
280 // reset depth func to opengl default
281 glDepthFunc(GL_LESS);
282
283 ACG::glCheckErrors();
284
285 // restore common opengl state
286 // log window remains hidden otherwise
287 finishRenderingPipeline();
288 }
289
290
291 QAction* ToonRenderer::optionsAction()
292 {
293 QAction * action = new QAction("Toon Renderer Options" , this );
294
295 connect(action,SIGNAL(triggered( bool )),this,SLOT(actionDialog( bool )));
296
297 return action;
298 }
299
300 void ToonRenderer::paletteSizeChanged( int _val ) {
301 paletteSize_ = float(_val) / 100.0f;
302 }
303
304 void ToonRenderer::outlineColorChanged( QColor _col ) {
305 outlineCol_[0] = _col.redF();
306 outlineCol_[1] = _col.greenF();
307 outlineCol_[2] = _col.blueF();
308 }
309
310 void ToonRenderer::ViewerResources::resize( int _newWidth, int _newHeight ) {
311 if (!_newHeight || !_newWidth) return;
312
313
314 if (!scene_) {
315 // scene fbo with 2 color attachments + depth buffer
316 // attachment0: scene color
317 // attachment1: scene depth
318 scene_ = new ACG::FBO();
319 scene_->init();
320 scene_->attachTexture2D(GL_COLOR_ATTACHMENT0, _newWidth, _newHeight, GL_RGBA, GL_RGBA);
321 scene_->attachTexture2D(GL_COLOR_ATTACHMENT1, _newWidth, _newHeight, GL_R32F, GL_RED);
322 scene_->attachTexture2DDepth(_newWidth, _newHeight);
323 }
324
325 if (scene_->height() == _newHeight &&
326 scene_->width() == _newWidth)
327 return;
328
329 scene_->resize(_newWidth, _newHeight);
330 }
331
332
333
334 #if QT_VERSION < 0x050000
335 Q_EXPORT_PLUGIN2( toonrenderer , ToonRenderer );
336 #endif
337
Viewer::ViewerProperties
Definition: ViewerProperties.hh:119
ACG::ShaderGenerator::addUniform
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
Definition: ShaderGenerator.cc:536
ToonRenderer::paletteSize_
float paletteSize_
size of cel shading palette
Definition: ToonRenderer.hh:109
ACG::GLState::far_plane
double far_plane() const
get far clipping distance
Definition: GLState.hh:839
GLSL::Program::getFragDataLocation
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:730
ACG::IRenderer::renderObject
virtual void renderObject(ACG::RenderObject *_obj, GLSL::Program *_prog=0, bool _constRenderStates=false, const std::vector< unsigned int > *_shaderModifiers=0)
Render one renderobject.
Definition: IRenderer.cc:986
CelShadingModifier::modifyLightingCode
void modifyLightingCode(QStringList *_code, int _lightId, ACG::ShaderGenLightType _lightType)
Modify the default lighting code of the shader generator.
Definition: ToonRenderer.cc:101
ACG::FBO::attachTexture2D
void attachTexture2D(GLenum _attachment, GLsizei _width, GLsizei _height, GLuint _internalFmt, GLenum _format, GLint _wrapMode=GL_CLAMP, GLint _minFilter=GL_NEAREST, GLint _magFilter=GL_NEAREST)
function to attach a texture to fbo
Definition: FBO.cc:200
GLSL::Program::bindFragDataLocation
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:698
ACG::IRenderer::sortedObjects_
std::vector< ACG::RenderObject * > sortedObjects_
sorted list of renderobjects without overlay objects (sorted in rendering order)
Definition: IRenderer.hh:463
ACG::FBO::width
GLsizei width() const
get width of fbo texture
Definition: FBO.hh:161
ACG::ScreenQuad::draw
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:147
GLSL::loadProgram
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1082
ACG::FBO
Definition: FBO.hh:83
ToonRenderer::optionsAction
QAction * optionsAction()
Return options menu.
Definition: ToonRenderer.cc:291
ACG::ShaderProgGenerator::registerModifier
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
Definition: ShaderGenerator.cc:2412
Viewer::ViewerProperties::drawMode
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
Definition: ViewerProperties.cc:162
ACG::openGLVersion
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
PluginFunctions::getSceneGraphRootNode
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
Definition: PluginFunctions.cc:961
ACG::GLState
Definition: GLState.hh:220
ToonRenderer::renderObjectsInfo
QString renderObjectsInfo(bool _outputShaderInfo)
Return a qstring of the current render objects.
Definition: ToonRenderer.cc:165
ACG::ShaderGenerator::addOutput
void addOutput(const QString &_output)
Add one GLSL output specifier.
Definition: ShaderGenerator.cc:472
ToonRenderer::progOutline_
GLSL::Program * progOutline_
outline shader: multiply scene color with edge factor derived from edges in depth buffer ...
Definition: ToonRenderer.hh:106
ToonRenderer::outlineCol_
ACG::Vec3f outlineCol_
outline color
Definition: ToonRenderer.hh:112
ACG::checkExtensionSupported
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
ACG::IRenderer::dumpCurrentRenderObjectsToString
virtual QString dumpCurrentRenderObjectsToString(ACG::RenderObject **_list=0, bool _outputShaders=false, std::vector< ACG::ShaderModifier * > *_modifiers=0)
Outputs the current render objects to the string.
Definition: IRenderer.cc:1135
ACG::ShaderCache::getProgram
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:108
GLSL::Program::use
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
ACG::GLState::viewport_width
int viewport_width() const
get viewport width
Definition: GLState.hh:825
ACG::FBO::resize
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
Definition: FBO.cc:543
CelShadingModifier::modifyFragmentIO
void modifyFragmentIO(ACG::ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
Definition: ToonRenderer.cc:77
CelShadingModifier
Definition: ToonRenderer.cc:65
ACG::ShaderGenerator::addIncludeFile
void addIncludeFile(QString _fileName)
Imports another shader, same as #include.
Definition: ShaderGenerator.cc:634
Viewer::ViewerProperties::viewerId
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
Definition: ViewerProperties.cc:153
ACG::FBO::attachTexture2DDepth
void attachTexture2DDepth(GLsizei _width, GLsizei _height, GLuint _internalFmt=GL_DEPTH_COMPONENT32, GLenum _format=GL_DEPTH_COMPONENT)
function to attach a depth-buffer texture to fbo (using GL_DEPTH_ATTACHMENT)
Definition: FBO.cc:327
ACG::GLState::near_plane
double near_plane() const
get near clipping distance
Definition: GLState.hh:836
ToonRenderer::viewerRes_
std::map< int, ViewerResources > viewerRes_
Definition: ToonRenderer.hh:129
CelShadingModifier::modifyVertexIO
void modifyVertexIO(ACG::ShaderGenerator *_shader)
Add your own inputs/outputs to the vertex shader.
Definition: ToonRenderer.cc:68
ACG::ShaderModifier
Definition: ShaderGenerator.hh:932
OpenMesh::VectorT
Definition: Vector11T.hh:83
GLSL::Program::link
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:332
CelShadingModifier::replaceDefaultLightingCode
bool replaceDefaultLightingCode()
Specify whether this modifier replaces or extends the default lighting code.
Definition: ToonRenderer.cc:99
ToonRenderer
Definition: ToonRenderer.hh:60
ACG::ShaderCache::getInstance
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:90
ACG::glCheckErrors
void glCheckErrors()
Definition: GLError.hh:105
CelShadingModifier::modifyFragmentEndCode
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: ToonRenderer.cc:94
GlobalOptions.hh
GLSL::Program::setUniform
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:217
ACG::FBO::init
void init()
function to generate the framebuffer object
Definition: FBO.cc:86
ACG::IRenderer::finishRenderingPipeline
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:589
ACG::IRenderer::restoreInputFbo
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:700
ACG::IRenderer::prepareRenderingPipeline
virtual void prepareRenderingPipeline(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode *_scenegraphRoot)
Prepares renderer and OpenGL for any draw-related calls including.
Definition: IRenderer.cc:486
PluginFunctions.hh
GLSL::Program::disable
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:361
ACG::FBO::height
GLsizei height() const
get height of fbo texture
Definition: FBO.hh:164
ACG::ShaderProgGenerator::getShaderDir
static QString getShaderDir()
Definition: ShaderGenerator.cc:2406
ACG::GLState::viewport_height
int viewport_height() const
get viewport height
Definition: GLState.hh:827
ACG::ShaderGenerator
Definition: ShaderGenerator.hh:518
Viewer::ViewerProperties::backgroundColor
ACG::Vec4f backgroundColor()
Get current background color.
Definition: ViewerProperties.cc:226
ACG::IRenderer::getNumRenderObjects
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Definition: IRenderer.cc:1045