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;
		}
	}
Exemple #2
0
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();
}
Exemple #3
0
	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();
	}
Exemple #4
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
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);
    }
}
Exemple #5
0
	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();
	}