void RenderLine::Draw(_DC* pDC, _Rect rcLine, _Rect rcDraw, ESChildControl* pControl){ RenderItem* pItem = m_pFirstItem; _Rect rcItem, rcInvalid; int nOffsetX = rcLine.left; int nClientWidth = pControl->GetClientWidth(); while( pItem ){ if( pItem->m_fPosX > 0.0f ) nOffsetX = (pItem->m_fPosX*((float)nClientWidth)) + rcLine.left; rcItem.left = nOffsetX + pItem->m_ptOffset.x; rcItem.top = rcLine.top + pItem->m_ptOffset.y; if( pItem->m_fCX > 0.0f ){ rcItem.right = rcItem.left + (pItem->m_fCX*((float)nClientWidth)); rcItem.bottom = rcItem.top + pItem->m_szItem.cy; } else{ rcItem.right = rcItem.left + pItem->m_szItem.cx; rcItem.bottom = rcItem.top + pItem->m_szItem.cy; } rcInvalid = rcItem&rcDraw; if( !rcInvalid.IsRectEmpty() ) pItem->Draw(pDC, rcItem, rcInvalid, pControl); if( pItem->m_bBreakLine ) nOffsetX = rcLine.left; else nOffsetX += rcItem.Width(); pItem = pItem->m_pNext; } }
void Renderer::Update() { if ( !_pGraphics ) return; _pGraphics->SetCamera( &_camera ); _pGraphics->ClearColor( _clearColor ); uint size = _renderItemList.size(); RenderItem *item; for ( uint i = 0; i < size; ++i ) { item = _renderItemList[i]; item->Update(); _pGraphics->Draw( item->GetSurface() ); } _pGraphics->EndFrame(); }
RenderItem* LayerNode::addToRenderItem(ITexture* _texture, bool _firstQueue, bool _manualRender) { // для первичной очереди нужен порядок if (_firstQueue) { if (mFirstRenderItems.empty() || _manualRender) { // создаем новый буфер RenderItem* item = new RenderItem(); item->setTexture(_texture); item->setManualRender(_manualRender); mFirstRenderItems.push_back(item); mOutOfDate = false; return item; } // если в конце пустой буфер, то нуна найти последний пустой с краю // либо с нужной текстурой за пустым VectorRenderItem::reverse_iterator iter = mFirstRenderItems.rbegin(); if ((*iter)->getNeedVertexCount() == 0) { while (true) { VectorRenderItem::reverse_iterator next = iter + 1; if (next != mFirstRenderItems.rend()) { if ((*next)->getNeedVertexCount() == 0) { iter = next; continue; } else if (!(*next)->getManualRender() && (*next)->getTexture() == _texture) { iter = next; } } break; } (*iter)->setTexture(_texture); mOutOfDate = false; return (*iter); } // последний буфер с нужной текстурой else if (!(*iter)->getManualRender() && (*iter)->getTexture() == _texture) { mOutOfDate = false; return *iter; } // создаем новый буфер RenderItem* item = new RenderItem(); item->setTexture(_texture); item->setManualRender(_manualRender); mFirstRenderItems.push_back(item); mOutOfDate = false; return item; } // для второй очереди порядок неважен for (VectorRenderItem::iterator iter = mSecondRenderItems.begin(); iter != mSecondRenderItems.end(); ++iter) { // либо такая же текстура, либо пустой буфер if ((*iter)->getTexture() == _texture) { mOutOfDate = false; return (*iter); } else if ((*iter)->getNeedVertexCount() == 0) { (*iter)->setTexture(_texture); mOutOfDate = false; return (*iter); } } // не найденно создадим новый RenderItem* item = new RenderItem(); item->setTexture(_texture); item->setManualRender(_manualRender); mSecondRenderItems.push_back(item); mOutOfDate = false; return mSecondRenderItems.back(); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RenderEngine::render(OpenGLContext* oglContext, RenderQueue* renderQueue, size_t maxNumPartsToDraw, const Camera& camera, const UniformSet* globalUniformSet) { CVF_ASSERT(oglContext); CVF_ASSERT(renderQueue); m_renderedPartCount = 0; m_renderedVertexCount = 0; m_renderedTriangleCount = 0; m_renderedOpenGLPrimitiveCount = 0; m_applyRenderStateCount = 0; m_shaderProgramChangesCount = 0; m_renderStateTracker.resetAndApplyDefaultRenderStates(oglContext); // Use immediate mode either if forced or if buffer objects are not supported (OpenGL 1.5 and below) // This is because the current fixed function rendering relies on the buffer object binding points being present const bool renderUsingImmediateMode = (m_forceImmediateMode || !BufferObjectManaged::supportedOpenGL(oglContext)); // Does the current OpenGL context support OpenGL shaders const bool contextSupportsShaders = ShaderProgram::supportedOpenGL(oglContext); // Init matrix state tracker MatrixState matrixState(camera); uint lastAppliedMatrixStateVersionTick = matrixState.versionTick() - 1; uint lastAppliedMatrixStateVersionTickFixedFunction = matrixState.versionTick() - 1; const Effect* prevEffect = NULL; const RenderStateSet* prevRenderStateSet = NULL; const ShaderProgram* prevShaderProgram = NULL; // Track the current shader program being used. // Will be NULL when effect has no shader program or if usage of shader program fails ShaderProgram* shaderProgramInUse = NULL; if (contextSupportsShaders) { // Start out with fixed function ShaderProgram::useNoProgram(oglContext); } // Determine number of parts we'll draw size_t numPartsInQueue = renderQueue->count(); size_t numPartsToDraw = std::min(numPartsInQueue, maxNumPartsToDraw); bool debugLogging = CVF_SHOULD_LOG_RENDER_DEBUG(oglContext); if (debugLogging) { CVF_LOG_RENDER_DEBUG(oglContext, "RenderEngine::render(), numParts=" + String(static_cast<uint>(numPartsInQueue))); } size_t i; for (i = 0; i < numPartsToDraw; i++) { RenderItem* item = renderQueue->item(i); CVF_ASSERT(item); Drawable* drawable = item->drawable(); Effect* effect = item->effect(); Part* part = item->part(); CVF_ASSERT(drawable); CVF_ASSERT(effect); CVF_ASSERT(part); if (debugLogging) { CVF_LOG_RENDER_DEBUG(oglContext, String("part#=%1, partName='%2'").arg(static_cast<uint>(i)).arg(part->name())); } // Update matrix state to reflect any part transformations // Register if the pass modifies the view matrix so that we can reset it at the end of this part bool lastPartModifiedViewMatrix = false; if (part->transform()) { const Transform* trans = part->transform(); if (trans->eyeLiftFactor() != 0) { // Eye lifting done by scaling the vertex coordinates after transforming them to eye space. See Transform::setEyeLiftFactor() // An eye lift factor of 1.0 results in scaling by 0.995. Might have to tweak the value below somewhat double scaleFactor = 1 - (trans->eyeLiftFactor()*0.005); Mat4d scaleMatrix = Mat4d::fromScaling(Vec3d(scaleFactor, scaleFactor, scaleFactor)); matrixState.setViewMatrix(scaleMatrix*camera.viewMatrix()); lastPartModifiedViewMatrix = true; } matrixState.setModelMatrix(trans->worldTransform()); } else { matrixState.clearModelMatrix(); } if (effect != prevEffect && !m_disableApplyEffects) { const RenderStateSet* const renderStateSet = effect->renderStateSet(); if (renderStateSet != prevRenderStateSet) { // This apply function is designed to work with NULL pointers m_renderStateTracker.applyRenderStates(oglContext, renderStateSet, prevRenderStateSet); prevRenderStateSet = renderStateSet; m_applyRenderStateCount++; } if (contextSupportsShaders) { ShaderProgram* shaderProgThisEffect = effect->shaderProgram(); if (shaderProgThisEffect != prevShaderProgram) { // Reset the 'in use' pointer, and only set it if we have a shader program AND we manage to use it shaderProgramInUse = NULL; if (shaderProgThisEffect) { // Will fail if program hasn't been linked if (shaderProgThisEffect->useProgram(oglContext)) { shaderProgramInUse = shaderProgThisEffect; } } if (!shaderProgramInUse) { ShaderProgram::useNoProgram(oglContext); } prevShaderProgram = shaderProgThisEffect; m_shaderProgramChangesCount++; } if (shaderProgramInUse) { // Apply uniforms for this shader program // Note order of application here. // - shader program default uniforms // - global dynamic uniforms // - (texture binding uniforms) // - effect uniforms // - fixed uniforms // We would really like the effect's uniforms to be at the very end, but that would give inconsistent // behavior since the fixed uniforms may get applied also when the effect does NOT change. shaderProgramInUse->clearUniformApplyTracking(); shaderProgramInUse->applyDefaultUniforms(oglContext); if (globalUniformSet) { shaderProgramInUse->applyActiveUniformsOnly(oglContext, *globalUniformSet); } const RenderStateTextureBindings* textureBindings = static_cast<const RenderStateTextureBindings*>(effect->renderStateOfType(RenderState::TEXTURE_BINDINGS)); if (textureBindings) { textureBindings->applySamplerTextureUnitUniforms(oglContext, shaderProgramInUse); } // Apply the effect's uniform last so that they win in case of clashes const UniformSet* uniformSet = effect->uniformSet(); if (uniformSet) { shaderProgramInUse->applyUniforms(oglContext, *uniformSet); } // Still, the fixed ones have to go at the end for consistency shaderProgramInUse->applyFixedUniforms(oglContext, matrixState); lastAppliedMatrixStateVersionTick = matrixState.versionTick(); } } prevEffect = effect; } if (shaderProgramInUse) { if (lastAppliedMatrixStateVersionTick != matrixState.versionTick()) { shaderProgramInUse->applyFixedUniforms(oglContext, matrixState); lastAppliedMatrixStateVersionTick = matrixState.versionTick(); } // Will check that all active uniforms in shader program have been set since last call to >clearUniformApplyTracking() // Reports error to log if any uniforms are missing. shaderProgramInUse->checkReportAllUniformsApplied(oglContext); } else { #ifndef CVF_OPENGL_ES if (lastAppliedMatrixStateVersionTickFixedFunction != matrixState.versionTick()) { glLoadMatrixf(matrixState.modelViewMatrix().ptr()); lastAppliedMatrixStateVersionTickFixedFunction = matrixState.versionTick(); } #endif // CVF_OPENGL_ES } // Do actual rendering if (!m_disableDrawableRender) { if (renderUsingImmediateMode) { drawable->renderImmediateMode(oglContext, matrixState); } else { if (shaderProgramInUse) { drawable->render(oglContext, shaderProgramInUse, matrixState); } else { drawable->renderFixedFunction(oglContext, matrixState); } } m_renderedPartCount++; } // Must reset the view matrix if it was modified during drawing of this part if (lastPartModifiedViewMatrix) { matrixState.setViewMatrix(camera.viewMatrix()); } // Update counters if (m_enableItemCountUpdate) { m_renderedVertexCount += drawable->vertexCount(); m_renderedTriangleCount += drawable->triangleCount(); m_renderedOpenGLPrimitiveCount += drawable->faceCount(); } } // Do an apply with an empty new render state set to get defaults back before leaving // This really isn't the optimal place to do this, but until we expose application of render states it's the only place m_renderStateTracker.applyRenderStates(oglContext, NULL, prevRenderStateSet); // For now, set back to fixed function if (contextSupportsShaders) { ShaderProgram::useNoProgram(oglContext); } // Set back VBO settings (do we need this?) if (BufferObjectManaged::supportedOpenGL(oglContext)) { BufferObjectManaged::unbindAllBuffers(oglContext); } }
RenderItem* LayerNode::addToRenderItem(ITexture* _texture, ISubWidget* _item) { bool first = _item->castType<ISubWidgetText>(false) == nullptr; // для первичной очереди нужен порядок if (first) { if (mFirstRenderItems.empty()) { // создаем новый буфер RenderItem * item = new RenderItem(); item->setTexture(_texture); mFirstRenderItems.push_back(item); return item; } // если последний буфер пустой, то мона не создавать if (mFirstRenderItems.back()->getNeedVertexCount() == 0) { // пустых может быть сколько угодно, нужен самый первый из пустых for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter) { if ((*iter)->getNeedVertexCount() == 0) { // а теперь внимание, если перед пустым наш, то его и юзаем if (iter != mFirstRenderItems.begin()) { VectorRenderItem::iterator prev = iter - 1; if ((*prev)->getTexture() == _texture) { return (*prev); } } (*iter)->setTexture(_texture); return (*iter); } } } // та же текстура if (mFirstRenderItems.back()->getTexture() == _texture) { return mFirstRenderItems.back(); } // создаем новый буфер RenderItem * item = new RenderItem(); item->setTexture(_texture); mFirstRenderItems.push_back(item); return item; } // для второй очереди порядок неважен for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter) { // либо такая же текстура, либо пустой буфер if ((*iter)->getTexture() == _texture) { return (*iter); } else if ((*iter)->getNeedVertexCount() == 0) { (*iter)->setTexture(_texture); return (*iter); } } // не найденно создадим новый RenderItem * item = new RenderItem(); item->setTexture(_texture); mSecondRenderItems.push_back(item); return mSecondRenderItems.back(); }