Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlGraphics/Renderer.hpp>
00033 #include <vlGraphics/OpenGLContext.hpp>
00034 #include <vlGraphics/GLSL.hpp>
00035 #include <vlGraphics/RenderQueue.hpp>
00036 #include <vlCore/Log.hpp>
00037
00038 using namespace vl;
00039
00040
00041
00042
00043 Renderer::Renderer()
00044 {
00045 VL_DEBUG_SET_OBJECT_NAME()
00046
00047 mProjViewTransfCallback = new ProjViewTransfCallback;
00048
00049 mDummyEnables = new EnableSet;
00050 mDummyStateSet = new RenderStateSet;
00051 }
00052
00053 namespace
00054 {
00055 struct GLSLProgState
00056 {
00057 public:
00058 GLSLProgState(): mCamera(NULL), mTransform(NULL), mGLSLProgUniformSet(NULL), mShaderUniformSet(NULL), mActorUniformSet(NULL) {}
00059
00060 bool operator<(const GLSLProgState& other) const
00061 {
00062 if ( mCamera != other.mCamera )
00063 return mCamera < other.mCamera;
00064 else
00065 if ( mTransform != other.mTransform )
00066 return mTransform < other.mTransform;
00067 else
00068 if ( mGLSLProgUniformSet != other.mGLSLProgUniformSet )
00069 return mGLSLProgUniformSet < other.mGLSLProgUniformSet;
00070 else
00071 if ( mShaderUniformSet != other.mShaderUniformSet )
00072 return mShaderUniformSet < other.mShaderUniformSet;
00073 else
00074 return mActorUniformSet < other.mActorUniformSet;
00075 }
00076
00077 const Camera* mCamera;
00078 const Transform* mTransform;
00079 const UniformSet* mGLSLProgUniformSet;
00080 const UniformSet* mShaderUniformSet;
00081 const UniformSet* mActorUniformSet;
00082 };
00083 }
00084
00085 const RenderQueue* Renderer::render(const RenderQueue* render_queue, Camera* cur_camera, Real frame_clock)
00086 {
00087 VL_CHECK_OGL()
00088
00089
00090
00091 if (enableMask() == 0)
00092 return render_queue;
00093
00094
00095
00096 class InOutContract
00097 {
00098 Renderer* mRenderer;
00099 public:
00100 InOutContract(Renderer* renderer, Camera* camera): mRenderer(renderer)
00101 {
00102
00103 mRenderer->mRenderTick++;
00104
00105
00106
00107 mRenderer->renderTarget()->activate();
00108
00109
00110 camera->viewport()->setClearFlags( mRenderer->clearFlags() );
00111 camera->viewport()->activate();
00112
00113
00114 mRenderer->dispatchOnRendererStarted();
00115
00116
00117 VL_CHECK_OGL()
00118 }
00119
00120 ~InOutContract()
00121 {
00122
00123 mRenderer->dispatchOnRendererFinished();
00124
00125
00126 VL_CHECK_OGL()
00127
00128
00129 }
00130 } contract(this, cur_camera);
00131
00132
00133
00134 std::map<const GLSLProgram*, GLSLProgState> glslprogram_map;
00135
00136 OpenGLContext* opengl_context = renderTarget()->openglContext();
00137
00138
00139
00140
00141 const RenderStateSet* cur_render_state_set = NULL;
00142 const EnableSet* cur_enable_set = NULL;
00143 const Scissor* cur_scissor = NULL;
00144
00145
00146 #if 1
00147 glEnable(GL_SCISSOR_TEST);
00148 glScissor(cur_camera->viewport()->x(), cur_camera->viewport()->y(), cur_camera->viewport()->width(), cur_camera->viewport()->height());
00149 #else
00150 glDisable(GL_SCISSOR_TEST);
00151 #endif
00152
00153
00154
00155 for(int itok=0; itok < render_queue->size(); ++itok)
00156 {
00157 const RenderToken* tok = render_queue->at(itok); VL_CHECK(tok);
00158 Actor* actor = tok->mActor; VL_CHECK(actor);
00159
00160 if ( !isEnabled(actor->enableMask()) )
00161 continue;
00162
00163
00164
00165 const Scissor* scissor = actor->scissor() ? actor->scissor() : tok->mShader->scissor();
00166 if (cur_scissor != scissor)
00167 {
00168 cur_scissor = scissor;
00169 if (cur_scissor)
00170 {
00171 cur_scissor->enable(cur_camera->viewport());
00172 }
00173 else
00174 {
00175 #if 1
00176
00177 VL_CHECK(glIsEnabled(GL_SCISSOR_TEST))
00178 glScissor(cur_camera->viewport()->x(), cur_camera->viewport()->y(), cur_camera->viewport()->width(), cur_camera->viewport()->height());
00179 #else
00180 glDisable(GL_SCISSOR_TEST);
00181 #endif
00182 }
00183 }
00184
00185
00186 for( int ipass=0; tok != NULL; tok = tok->mNextPass, ++ipass )
00187 {
00188 VL_CHECK_OGL()
00189
00190
00191
00192 const Shader* shader = tok->mShader;
00193
00194
00195
00196 for( std::map< unsigned int, ref<Shader> >::const_iterator eom_it = mShaderOverrideMask.begin();
00197 eom_it != mShaderOverrideMask.end(); ++eom_it )
00198 {
00199 if ( eom_it->first & actor->enableMask() )
00200 shader = eom_it->second.get();
00201 }
00202
00203
00204
00205 if ( cur_render_state_set != shader->getRenderStateSet() )
00206 {
00207 opengl_context->applyRenderStates(cur_render_state_set, shader->getRenderStateSet(), cur_camera );
00208 cur_render_state_set = shader->getRenderStateSet();
00209 }
00210
00211 VL_CHECK_OGL()
00212
00213
00214
00215 if ( cur_enable_set != shader->getEnableSet() )
00216 {
00217 opengl_context->applyEnables(cur_enable_set, shader->getEnableSet() );
00218 cur_enable_set = shader->getEnableSet();
00219 }
00220
00221 #ifndef NDEBUG
00222 if (glGetError() != GL_NO_ERROR)
00223 {
00224 Log::error("An unsupported OpenGL glEnable/glDisable capability has been enabled!\n");
00225 VL_TRAP()
00226 }
00227 #endif
00228
00229
00230
00231
00232
00233
00234 actor->dispatchOnActorRenderStarted( frame_clock, cur_camera, tok->mRenderable, shader, ipass );
00235
00236 VL_CHECK_OGL()
00237
00238
00239
00240 VL_CHECK( !shader->glslProgram() || shader->glslProgram()->linked() );
00241
00242 VL_CHECK_OGL()
00243
00244
00245 const Transform* cur_transform = actor->transform();
00246 const GLSLProgram* cur_glsl_program = NULL;
00247 const UniformSet* cur_glsl_prog_uniform_set = NULL;
00248 const UniformSet* cur_shader_uniform_set = NULL;
00249 const UniformSet* cur_actor_uniform_set = NULL;
00250
00251
00252 if (shader->glslProgram() && shader->glslProgram()->handle())
00253 {
00254 cur_glsl_program = shader->glslProgram();
00255
00256
00257 if (cur_glsl_program->uniformSet() && !cur_glsl_program->uniformSet()->uniforms().empty())
00258 cur_glsl_prog_uniform_set = cur_glsl_program->uniformSet();
00259
00260 if (shader->getUniformSet() && !shader->getUniformSet()->uniforms().empty())
00261 cur_shader_uniform_set = shader->getUniformSet();
00262
00263 if (actor->getUniformSet() && !actor->getUniformSet() ->uniforms().empty())
00264 cur_actor_uniform_set = actor->getUniformSet();
00265 }
00266
00267 bool update_cm = false;
00268 bool update_tr = false;
00269 bool update_pu = false;
00270 bool update_su = false;
00271 bool update_au = false;
00272 GLSLProgState* glsl_state = NULL;
00273
00274
00275 std::map<const GLSLProgram*, GLSLProgState>::iterator glsl_state_it = glslprogram_map.find(cur_glsl_program);
00276
00277 if ( glsl_state_it == glslprogram_map.end() )
00278 {
00279
00280
00281
00282
00283
00284 glsl_state = &glslprogram_map[cur_glsl_program];
00285 update_cm = true;
00286 update_tr = true;
00287 update_pu = cur_glsl_prog_uniform_set != NULL;
00288 update_su = cur_shader_uniform_set != NULL;
00289 update_au = cur_actor_uniform_set != NULL;
00290 }
00291 else
00292 {
00293
00294
00295
00296
00297 glsl_state = &glsl_state_it->second;
00298
00299 update_cm = glsl_state->mCamera != cur_camera;
00300 update_tr = glsl_state->mTransform != cur_transform;
00301 update_pu = glsl_state->mGLSLProgUniformSet != cur_glsl_prog_uniform_set && cur_glsl_prog_uniform_set != NULL;
00302 update_su = glsl_state->mShaderUniformSet != cur_shader_uniform_set && cur_shader_uniform_set != NULL;
00303 update_au = glsl_state->mActorUniformSet != cur_actor_uniform_set && cur_actor_uniform_set != NULL;
00304 }
00305
00306
00307 glsl_state->mCamera = cur_camera;
00308 glsl_state->mTransform = cur_transform;
00309 glsl_state->mGLSLProgUniformSet = cur_glsl_prog_uniform_set;
00310 glsl_state->mShaderUniformSet = cur_shader_uniform_set;
00311 glsl_state->mActorUniformSet = cur_actor_uniform_set;
00312
00313
00314
00315 VL_CHECK_OGL()
00316
00317 if (update_cm || update_tr)
00318 projViewTransfCallback()->updateMatrices( update_cm, update_tr, cur_glsl_program, cur_camera, cur_transform, opengl_context->isCompatible() );
00319
00320 VL_CHECK_OGL()
00321
00322
00323
00324
00325 VL_CHECK( !opengl_context->areUniformsColliding(cur_shader_uniform_set, cur_actor_uniform_set) );
00326 VL_CHECK( !opengl_context->areUniformsColliding(cur_shader_uniform_set, cur_glsl_prog_uniform_set ) );
00327 VL_CHECK( !opengl_context->areUniformsColliding(cur_actor_uniform_set, cur_glsl_prog_uniform_set ) );
00328
00329 VL_CHECK_OGL()
00330
00331
00332 if (update_pu)
00333 {
00334 VL_CHECK( cur_glsl_prog_uniform_set && cur_glsl_prog_uniform_set->uniforms().size() );
00335 VL_CHECK( shader->getRenderStateSet()->glslProgram() && shader->getRenderStateSet()->glslProgram()->handle() )
00336 cur_glsl_program->applyUniformSet( cur_glsl_prog_uniform_set );
00337 }
00338
00339 VL_CHECK_OGL()
00340
00341
00342 if ( update_su )
00343 {
00344 VL_CHECK( cur_shader_uniform_set && cur_shader_uniform_set->uniforms().size() );
00345 VL_CHECK( shader->getRenderStateSet()->glslProgram() && shader->getRenderStateSet()->glslProgram()->handle() )
00346 cur_glsl_program->applyUniformSet( cur_shader_uniform_set );
00347 }
00348
00349 VL_CHECK_OGL()
00350
00351
00352 if ( update_au )
00353 {
00354 VL_CHECK( cur_actor_uniform_set && cur_actor_uniform_set->uniforms().size() );
00355 VL_CHECK( shader->getRenderStateSet()->glslProgram() && shader->getRenderStateSet()->glslProgram()->handle() )
00356 cur_glsl_program->applyUniformSet( cur_actor_uniform_set );
00357 }
00358
00359 VL_CHECK_OGL()
00360
00361
00362
00363
00364 tok->mRenderable->render( actor, shader, cur_camera, opengl_context );
00365
00366 VL_CHECK_OGL()
00367
00368
00369 if (shader != tok->mShader)
00370 break;
00371 }
00372 }
00373
00374
00375 opengl_context->applyEnables(cur_enable_set, mDummyEnables.get() ); VL_CHECK_OGL();
00376
00377
00378 opengl_context->applyRenderStates(cur_render_state_set, mDummyStateSet.get(), cur_camera ); VL_CHECK_OGL();
00379
00380
00381 VL_glActiveTexture( GL_TEXTURE0 ); VL_CHECK_OGL();
00382 if (opengl_context->isCompatible())
00383 VL_glClientActiveTexture( GL_TEXTURE0 ); VL_CHECK_OGL();
00384
00385
00386 glDisable(GL_SCISSOR_TEST); VL_CHECK_OGL();
00387
00388
00389 opengl_context->bindVAS(NULL, false, false); VL_CHECK_OGL();
00390 VL_CHECK( opengl_context->isCleanState(true) );
00391
00392 return render_queue;
00393 }
00394