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