コード例 #1
0
/*******************************************************************************
 * Function Name  : DoShearCentered
 * Description    : Demonstrate the effect of shearing centred on a
 *                  shape. Each path is transformed separately.
 *******************************************************************************/
void CTransforms::DoShearCentered()
{
	// Make sure we're operating on the path user-to-surface matrix
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);

	// Load Identity matrix. This clears all previous transformations
	vgLoadIdentity();

	// To be independent of screen resolution, we need to scale the
	// coordinates so everything in the range [0, 1] will be visible
	vgScale((float)PVRShellGet(prefWidth), (float)PVRShellGet(prefHeight));

	// Unlike OpenGL, OpenVG does not maintain a matrix stack. So instead of
	// pushing the current matrix to the stack, we have to store it ourselves
	float afUnitMatrix[3 * 3];
	vgGetMatrix(afUnitMatrix);

	// turn time(ms) into a clipped periodic triangle function
	int i32Zigzag1 = m_ui32AbsTime % 2000;

	if(i32Zigzag1 > 1000)
		i32Zigzag1 = 2000 - i32Zigzag1;

	i32Zigzag1 = PVRT_MAX(250, PVRT_MIN(750, i32Zigzag1)) - 500;

	// and again, now with shifted phase
	int i32Zigzag2 = (m_ui32AbsTime + 500) % 2000;

	if(i32Zigzag2 > 1000)
		i32Zigzag2 = 2000 - i32Zigzag2;

	i32Zigzag2 = PVRT_MAX(250, PVRT_MIN(750, i32Zigzag2)) - 500;

	// Scaling a shape from its center is identical to moving it to the
	// origin, scaling it there, and moving it back where it was.
	//
	// IMPORTANT:
	// Since OpenVG right-multiplies matrices, you conceptually need to
	// call the transformation functions in backwards order.
	vgTranslate(0.5f, 0.75f);
	vgShear(0.001f * i32Zigzag1, 0);
	vgTranslate(-0.5f, -0.75f);

	// draw first path
	vgDrawPath(m_avgPaths[0], VG_STROKE_PATH | VG_FILL_PATH);

	// restore the unit matrix ([0, 1] visible)
	vgLoadMatrix(afUnitMatrix);

	// transformation for second path
	vgTranslate(0.5f, 0.25f);
	vgShear(0.001f * i32Zigzag2, 0);
	vgTranslate(-0.5f, -0.25f);

	// draw second path
	vgDrawPath(m_avgPaths[1], VG_STROKE_PATH | VG_FILL_PATH);
}
コード例 #2
0
/*******************************************************************************
 * Function Name  : DoTranslate
 * Description    : Demonstrate the effect of translations. Each path is
 *                  translated separately
 *******************************************************************************/
void CTransforms::DoTranslate()
{
	// Make sure we're operating on the path user-to-surface matrix
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);

	// Load Identity matrix. This clears all previous transformations
	vgLoadIdentity();

	// To be independent of screen resolution, we need to scale the
	// coordinates so everything in the range [0, 1] will be visible
	vgScale((float) PVRShellGet(prefWidth), (float) PVRShellGet(prefHeight));

	// Unlike OpenGL, OpenVG does not maintain a matrix stack. So instead of
	// pushing the current matrix to the stack, we have to store it ourselves
	float afUnitMatrix[3 * 3];
	vgGetMatrix(afUnitMatrix);

	// turn time(ms) into a clipped periodic triangle function
	int i32Zigzag1 = m_ui32AbsTime % 2000;

	if(i32Zigzag1 > 1000)
		i32Zigzag1 = 2000 - i32Zigzag1;

	i32Zigzag1 = PVRT_MAX(250, PVRT_MIN(750, i32Zigzag1)) - 500;

	// and again, now with shifted phase
	int i32Zigzag2 = (m_ui32AbsTime + 500) % 2000;

	if(i32Zigzag2 > 1000)
		i32Zigzag2 = 2000 - i32Zigzag2;

	i32Zigzag2 = PVRT_MAX(250, PVRT_MIN(750, i32Zigzag2)) - 250;

	// translation for first path
	vgTranslate(-0.001f * i32Zigzag1, -0.001f * i32Zigzag2);

	// draw first path
	vgDrawPath(m_avgPaths[0], VG_STROKE_PATH | VG_FILL_PATH);

	// restore the unit matrix ([0, 1] visible)
	vgLoadMatrix(afUnitMatrix);

	// translation for second path
	vgTranslate(0.001f * i32Zigzag1, 0.001f * i32Zigzag2);

	// draw second path
	vgDrawPath(m_avgPaths[1], VG_STROKE_PATH | VG_FILL_PATH);
}
コード例 #3
0
/*******************************************************************************
 * Function Name  : DoShearOrigin
 * Description    : Demonstrate the effect of shearing from the origin.
 *******************************************************************************/
void CTransforms::DoShearOrigin()
{
	// Make sure we're operating on the path user-to-surface matrix
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);

	// Load Identity matrix. This clears all previous transformations
	vgLoadIdentity();

	// To be independent of screen resolution, we need to scale the
	// coordinates so everything in the range [0, 1] will be visible
	vgScale((float)PVRShellGet(prefWidth), (float)PVRShellGet(prefHeight));

	// turn time(ms) into a periodic triangle function
	int i32Zigzag = m_ui32AbsTime % 2000;

	if(i32Zigzag > 1000)
		i32Zigzag = 2000 - i32Zigzag;

	i32Zigzag = PVRT_MAX(100, PVRT_MIN(900, i32Zigzag)) - 500;

	vgShear(i32Zigzag * 0.001f, 0);

	// draw first path
	vgDrawPath(m_avgPaths[0], VG_STROKE_PATH | VG_FILL_PATH);
	// draw second path
	vgDrawPath(m_avgPaths[1], VG_STROKE_PATH | VG_FILL_PATH);
}
コード例 #4
0
/*******************************************************************************
 * Function Name  : DoScaleOrigin
 * Description    : Demonstrate the effect of scaling from the origin.
 *******************************************************************************/
void CTransforms::DoScaleOrigin()
{
	// Make sure we're operating on the path user-to-surface matrix
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);

	// Load Identity matrix. This clears all previous transformations
	vgLoadIdentity();

	// To be independent of screen resolution, we need to scale the
	// coordinates so everything in the range [0, 1] will be visible
	vgScale((float) PVRShellGet(prefWidth), (float) PVRShellGet(prefHeight));

	// turn time(ms) into a periodic triangle function
	int i32Zigzag = m_ui32AbsTime % 2000;

	if(i32Zigzag > 1000)
		i32Zigzag = 2000 - i32Zigzag;

	i32Zigzag = PVRT_MAX(100, PVRT_MIN(900, i32Zigzag));

	float fScaleFactor = 0.3f + (i32Zigzag * 0.0009f);

	// Scaling a scene from the origin means that objects will
	// either get pulled towards the origin or move away from it
	// along with being resized.
	vgScale(fScaleFactor, fScaleFactor);

	// draw first path
	vgDrawPath(m_avgPaths[0], VG_STROKE_PATH | VG_FILL_PATH);
	// draw second path
	vgDrawPath(m_avgPaths[1], VG_STROKE_PATH | VG_FILL_PATH);
}
コード例 #5
0
ファイル: PVRTString.cpp プロジェクト: Nlcke/gideros
/*!***********************************************************************
@Function			copy
@Modified			_Ptr 	A string to copy to
@Input				_Count	Size of _Ptr
@Input				_Off	Position to start copying from
@Returns			Number of bytes copied
@Description		Copies the string to _Ptr
*************************************************************************/
size_t CPVRTString::copy(char* _Ptr, size_t _Count, size_t _Off) const
{
	if(memcpy(_Ptr, &m_pString[_Off], PVRT_MIN(_Count, m_Size - _Off)))
		return _Count;

	return 0;
}
コード例 #6
0
ファイル: PVRTPrint3D.cpp プロジェクト: Sheph/gles-tests
/*!***************************************************************************
 @Function			SetTextures
 @Input				pContext		Context
 @Input				dwScreenX		Screen resolution along X
 @Input				dwScreenY		Screen resolution along Y
 @Input				bRotate			Rotate print3D by 90 degrees
 @Input				bMakeCopy		This instance of Print3D creates a copy
									of it's data instead of sharing with previous
									contexts. Set this parameter if you require
									thread safety.	
 @Return			PVR_SUCCESS or PVR_FAIL
 @Description		Initialization and texture upload. Should be called only once
					for a given context.
*****************************************************************************/
EPVRTError CPVRTPrint3D::SetTextures(
	const SPVRTContext	* const pContext,
	const unsigned int	dwScreenX,
	const unsigned int	dwScreenY,
	const bool bRotate,
	const bool bMakeCopy)
{
	// Determine which set of textures to use depending on the screen resolution.
	const unsigned int uiShortestEdge = PVRT_MIN(dwScreenX, dwScreenY);
	const void* pData = NULL;
	unsigned int uiDataSize   = 0;
	if(uiShortestEdge >= 720)
	{
		pData = (void*)_arialbd_56_pvr;
		uiDataSize = _arialbd_56_pvr_size;
	}
	else if(uiShortestEdge >= 640)
	{
		pData = (void*)_arialbd_46_pvr;
		uiDataSize = _arialbd_46_pvr_size;
	}
	else
	{
		pData = (void*)_arialbd_36_pvr;
		uiDataSize = _arialbd_36_pvr_size;
	}

	return SetTextures(pContext, pData, dwScreenX, dwScreenY, bRotate, bMakeCopy);
}
コード例 #7
0
/*!***************************************************************************
 @fn       			DrawLineUP
 @return			true or false
 @brief      		Draw a single line of text.
*****************************************************************************/
bool CPVRTPrint3D::DrawLine(SPVRTPrint3DAPIVertex *pVtx, unsigned int nVertices)
{
	if(!nVertices)
		return true;

	_ASSERT((nVertices % 4) == 0);
	_ASSERT((nVertices/4) < MAX_LETTERS);

	while(m_nVtxCache + (int)nVertices > m_nVtxCacheMax) {
		if(m_nVtxCache + nVertices > MAX_CACHED_VTX) {
			_RPT1(_CRT_WARN, "Print3D: Out of space to cache text! (More than %d vertices!)\n", MAX_CACHED_VTX);
			return false;
		}

		m_nVtxCacheMax	= PVRT_MIN(m_nVtxCacheMax * 2, MAX_CACHED_VTX);
		SPVRTPrint3DAPIVertex* pTmp = (SPVRTPrint3DAPIVertex*)realloc(m_pVtxCache, m_nVtxCacheMax * sizeof(*m_pVtxCache));

		_ASSERT(pTmp);
		if(!pTmp)
		{
			free(m_pVtxCache);
			m_pVtxCache = 0;
			return false; // Failed to re-allocate data
		}

		m_pVtxCache = pTmp;
		
		_RPT1(_CRT_WARN, "Print3D: TextCache increased to %d vertices.\n", m_nVtxCacheMax);
	}

	memcpy(&m_pVtxCache[m_nVtxCache], pVtx, nVertices * sizeof(*pVtx));
	m_nVtxCache += nVertices;
	return true;
}
コード例 #8
0
ファイル: PVRTString.cpp プロジェクト: Nlcke/gideros
/*!***********************************************************************
@Function			compare
@Input				_Pos1	Position to start comparing from
@Input				_Num1	Number of chars to compare
@Input				_Str 	A string to compare with
@Input				_Off 	Position in _Str to compare from
@Input				_Count	Number of chars in _Str to compare with
@Returns			0 if the strings match
@Description		Compares the string with _Str
*************************************************************************/
int CPVRTString::compare(size_t _Pos1, size_t _Num1, const CPVRTString& _Str, size_t /*_Off*/, size_t _Count) const
{
	assert(_Pos1<=m_Size);	// check comparison starts within lhs CPVRTString

	int i32Ret;	// value to return if no difference in actual comparisons between chars
	size_t stLhsLength = m_Size-_Pos1;
	size_t stSearchLength = PVRT_MIN(stLhsLength,PVRT_MIN(_Str.m_Size,PVRT_MIN(_Num1,_Count)));	// number of comparisons to do
	if(PVRT_MIN(stLhsLength,_Num1)<PVRT_MIN(_Str.m_Size,_Count))
	{
		i32Ret = -1;
	}
	else if(PVRT_MIN(stLhsLength,_Num1)>PVRT_MIN(_Str.m_Size,_Count))
	{
		i32Ret = 1;
	}
	else
	{
		i32Ret = 0;
	}


	// do actual comparison
	char* lhptr = &m_pString[_Pos1];
	char* rhptr = _Str.m_pString;
	for(size_t i=0;i<stSearchLength;++i)
	{
		if(*lhptr<*rhptr)
			return -1;
		else if (*lhptr>*rhptr)
			return 1;
		lhptr++;rhptr++;
	}
	// no difference found in compared characters
	return i32Ret;
}
コード例 #9
0
ファイル: PVRTPrint3D.cpp プロジェクト: Arideas/isgl3d
/*!***************************************************************************
 @Function			SetTitle
 @Input				dwWin				Window handle
 @Input				dwBackgroundColor	Background color
 @Input				fFontSize			Font size
 @Input				dwFontColorLeft
 @Input				sTitleLeft
 @Input				dwFontColorRight
 @Input				sTitleRight
 @Description		Set window title.
*****************************************************************************/
void CPVRTPrint3D::SetTitle(unsigned int dwWin, unsigned int dwBackgroundColor, float fFontSize,
						 unsigned int dwFontColorLeft, const char * const sTitleLeft,
						 unsigned int dwFontColorRight, const char * const sTitleRight)
{
#if !defined (DISABLE_PRINT3D)

	FREE(m_pWin[dwWin].pTitleVtxL);
	FREE(m_pWin[dwWin].pTitleVtxR);

	if(sTitleLeft)  memcpy(m_pWin[dwWin].bTitleTextL, sTitleLeft , PVRT_MIN((size_t)(MAX_LETTERS-1), strlen(sTitleLeft )+1));
	if(sTitleRight) memcpy(m_pWin[dwWin].bTitleTextR, sTitleRight, PVRT_MIN((size_t)(MAX_LETTERS-1), strlen(sTitleRight)+1));

	/* Set title properties */
	m_pWin[dwWin].fTitleFontSize		= fFontSize;
	m_pWin[dwWin].dwTitleFontColorL	= dwFontColorLeft;
	m_pWin[dwWin].dwTitleFontColorR	= dwFontColorRight;
	m_pWin[dwWin].dwTitleBaseColor	= dwBackgroundColor;
	m_pWin[dwWin].fTextRMinPos		= GetLength(m_pWin[dwWin].fTitleFontSize, m_pWin[dwWin].bTitleTextL) + 10.0f;
	m_pWin[dwWin].bNeedUpdated		= true;

#endif
}
コード例 #10
0
/*!***************************************************************************
 @Function			Flush
 @Description		Flushes all the print text commands
*****************************************************************************/
int CPVRTPrint3D::Flush()
{
#if !defined (DISABLE_PRINT3D)

	int		nTris, nVtx, nVtxBase, nTrisTot = 0;

	_ASSERT((m_nVtxCache % 4) == 0);
	_ASSERT(m_nVtxCache <= m_nVtxCacheMax);

	// Save render states
	APIRenderStates(INIT_PRINT3D_STATE);

	// Draw font
	if(m_nVtxCache)
	{
		SPVRTPrint3DAPI::SInstanceData& Data = (m_pAPI->m_pInstanceData ? *m_pAPI->m_pInstanceData : SPVRTPrint3DAPI::s_InstanceData);

		float fW = m_fScreenScale[0] * 640.0f;
		float fH = m_fScreenScale[1] * 480.0f;

		PVRTMat4 mxOrtho = PVRTMat4::Ortho(0.0f, 0.0f, fW, -fH, -1.0f, 1.0f, PVRTMat4::OGL, m_bRotate);
		if(m_bRotate)
		{
			PVRTMat4 mxTrans = PVRTMat4::Translation(-fH,fW,0.0f);
			mxOrtho = mxOrtho * mxTrans;
		}

		// Use the shader
		_ASSERT(Data.uProgramFont != UNDEFINED_HANDLE);
		glUseProgram(Data.uProgramFont);

		// Bind the projection and modelview matrices to the shader
		PVRTMat4& mProj = (m_bUsingProjection ? m_mProj : mxOrtho);	
		PVRTMat4 mMVP = mProj * m_mModelView;
		glUniformMatrix4fv(Data.mvpLocationFont, 1, GL_FALSE, mMVP.f);

		// Reset
		m_bUsingProjection = false;
		PVRTMatrixIdentity(m_mModelView);

		// Set client states
		glEnableVertexAttribArray(VERTEX_ARRAY);
		glEnableVertexAttribArray(COLOR_ARRAY);
		glEnableVertexAttribArray(UV_ARRAY);

		// texture
		glBindTexture(GL_TEXTURE_2D, m_pAPI->m_uTextureFont);

		unsigned int uiIndex = m_eFilterMethod[eFilterProc_Min] + (m_eFilterMethod[eFilterProc_Mip]*2);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c_eMagTable[m_eFilterMethod[eFilterProc_Mag]]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_eMinTable[uiIndex]);

		nTrisTot = m_nVtxCache >> 1;

		// Render the text then. Might need several submissions.
		nVtxBase = 0;
		while(m_nVtxCache)
		{
			nVtx	= PVRT_MIN(m_nVtxCache, 0xFFFC);
			nTris	= nVtx >> 1;

			_ASSERT(nTris <= (PVRTPRINT3D_MAX_RENDERABLE_LETTERS*2));
			_ASSERT((nVtx % 4) == 0);

			// Draw triangles
			glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(SPVRTPrint3DAPIVertex), (const void*)&m_pVtxCache[nVtxBase].sx);
			glVertexAttribPointer(COLOR_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SPVRTPrint3DAPIVertex), (const void*)&m_pVtxCache[nVtxBase].color);
			glVertexAttribPointer(UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(SPVRTPrint3DAPIVertex), (const void*)&m_pVtxCache[nVtxBase].tu);

			glDrawElements(GL_TRIANGLES, nTris * 3, GL_UNSIGNED_SHORT, m_pwFacesFont);

			if(glGetError())
			{
				PVRTERROR_OUTPUT_DEBUG("glDrawElements(GL_TRIANGLES, (VertexCount/2)*3, GL_UNSIGNED_SHORT, m_pFacesFont); failed\n");
			}

			nVtxBase	+= nVtx;
			m_nVtxCache	-= nVtx;
		}

		// Restore render states
		glDisableVertexAttribArray(VERTEX_ARRAY);
		glDisableVertexAttribArray(COLOR_ARRAY);
		glDisableVertexAttribArray(UV_ARRAY);
	}
	// Draw a logo if requested
#if !defined(FORCE_NO_LOGO)
	// User selected logos
	if(m_uLogoToDisplay & ePVRTPrint3DLogoPowerVR && m_uLogoToDisplay & ePVRTPrint3DLogoIMG)
	{
		APIDrawLogo(ePVRTPrint3DLogoIMG, eBottom | eRight);	// IMG to the right
		APIDrawLogo(ePVRTPrint3DLogoPowerVR, eBottom | eLeft);	// PVR to the left
	}
	else if(m_uLogoToDisplay & ePVRTPrint3DLogoPowerVR)
	{
		APIDrawLogo(ePVRTPrint3DLogoPowerVR, eBottom | eRight);	// logo to the right
	}
	else if(m_uLogoToDisplay & ePVRTPrint3DLogoIMG)
	{
		APIDrawLogo(ePVRTPrint3DLogoIMG, eBottom | eRight);	// logo to the right
	}
#endif

	// Restore render states
	APIRenderStates(DEINIT_PRINT3D_STATE);

	return nTrisTot;

#else
	return 0;
#endif
}
コード例 #11
0
/****************************************************************************
@Function 		Fill
@Input			pOb				Object to fill with
@Return			int				-1 if the block if the best option is already full
@Description	Note: Ask Aaron
****************************************************************************/
int CBlock::Fill(
	CObject	* const pOb)
{
	SVtx	*pVtx;
	int		i;
	SMesh	*pMesh;

	/*
		Build blocks from the large meshes
	*/
	if(!pOb->m_vMeshLg.empty()) {
		pMesh = &pOb->m_vMeshLg.back();

//		_RPT1(_CRT_WARN, "Fill() using large with %d vtx\n", pMesh->nVtxNum);

		// Find the vertex with the fewest unused triangles
		for(i = 0; i < pMesh->nVtxNum; ++i) {
			pVtx = pMesh->ppVtx[i];

			if(pVtx->nTriNumFree == 1) {
				if(FillFrom(pMesh, pVtx, pOb))
					return Fill(pOb);
			}
		}

		if(m_sOptBest.IsEmpty()) {
			// Just start from any old vertex
			for(i = 0; i < pMesh->nVtxNum; ++i) {
				pVtx = pMesh->ppVtx[i];

				if(pVtx->nTriNumFree) {
					if(FillFrom(pMesh, pVtx, pOb))
						return Fill(pOb);
					break;
				}
			}

			if(m_sOptBest.IsEmpty()) {
				pOb->m_vMeshLg.pop_back();					// Delete the mesh from the list
				return Fill(pOb);
			}
		}

		if(m_sOptBest.IsFull())
			return -1;
	}

	/*
		Match together the small meshes into blocks
	*/
	_ASSERT(m_sOptBest.IsEmpty());
	i = m_nVtxLimit - m_sOptBest.nVtxNum - 3;

//	_RPT0(_CRT_WARN, "Fill() grouping small ");

	// Starting with the largest meshes, lump them into this block
	while(i >= 0 && (m_nVtxLimit - m_sOptBest.nVtxNum) >= 3) {
		if(pOb->m_pvMesh[i].empty()) {
			--i;
			continue;
		}

		pMesh = &pOb->m_pvMesh[i].back();
		m_sOptBest.Add(pMesh);
//		_RPT1(_CRT_WARN, "+%d", pMesh->nVtxNum);
		pOb->m_pvMesh[i].pop_back();
		i = PVRT_MIN(i, m_nVtxLimit - m_sOptBest.nVtxNum - 3);
	}

	// If there's any space left in this block (and clearly there are no blocks
	// just the right size to fit) then take SOME of the largest block available.
	if(!m_sOptBest.IsFull()) {
		m_sOpt.Copy(&m_sOptBest);

		// Note: This loop purposely does not check m_pvMesh[0] - any block
		// which is looking to grab more geometry would have already sucked
		// up those meshes
		for(i = (m_nVtxLimit-3); i; --i) {
			if(!pOb->m_pvMesh[i].empty()) {
				pMesh = &pOb->m_pvMesh[i].back();

				_ASSERT(pMesh->ppVtx[0]->nTriNumFree);
				_ASSERT(!m_sOpt.UsingVertex(pMesh->ppVtx[0]));

				m_sOpt.AddVertex(pMesh->ppVtx[0]);
//				_RPT1(_CRT_WARN, "(+%d)\n", pMesh->nVtxNum);
				AddBestTriangles(pOb);

				m_sOptBest.Copy(&m_sOpt);
				_ASSERT(m_sOptBest.IsFull());
				return i;
			}
		}
	}
//	_RPT0(_CRT_WARN, "\n");
	return -1;
}
コード例 #12
0
/*!****************************************************************************
 @Function		CreateFBOorPBuffer
 @Return		bool		true if no error occured
 @Description	Attempts to create our FBO if supported or a PBuffer if they
				are not.
******************************************************************************/
bool OGLESRenderToTexture::CreateFBOorPBuffer()
{
#if !defined(EGL_NOT_PRESENT)
	EGLConfig eglConfig = 0;
	EGLint list[9];
#endif

	// Find the largest square power of two texture that fits into the viewport
	m_i32TexSize = 1;
	int iSize = PVRT_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight));
	while (m_i32TexSize * 2 < iSize) m_i32TexSize *= 2;

	// Check for FBO extension
	if(CPVRTglesExt::IsGLExtensionSupported("GL_OES_framebuffer_object"))
	{
		// FBOs are present so we're going to use them
		m_eR2TType = eFBO;

		// Load the extensions as they are required
		m_Extensions.LoadExtensions();

		// Check to see if the GL_EXT_discard_framebuffer extension is supported by seeing if
		// CPVRTglesExt has a valid pointer for glDiscardFramebufferEXT
		m_bDiscard = m_Extensions.glDiscardFramebufferEXT != 0;

		// Get the currently bound frame buffer object. On most platforms this just gives 0.
		glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &m_i32OriginalFbo);

		// Generate and bind a render buffer which will become a depth buffer shared between our two FBOs
		m_Extensions.glGenRenderbuffersOES(1, &m_uDepthBuffer);
		m_Extensions.glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_uDepthBuffer);

		/*
			Currently it is unknown to GL that we want our new render buffer to be a depth buffer.
			glRenderbufferStorage will fix this and in this case will allocate a depth buffer
			m_i32TexSize by m_i32TexSize.
		*/
		m_Extensions.glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, m_i32TexSize, m_i32TexSize);
	}
#if !defined(EGL_NOT_PRESENT)
	else
	{
		// FBOs aren't present so we're going to use PBuffers
		m_eR2TType = ePBuffer;

		// Set up a configuration and attribute list used for creating a PBuffer surface.
		eglConfig = SelectEGLConfig();

		// First we specify the width of the surface...
		list[0] = EGL_WIDTH;
		list[1] = m_i32TexSize;
		// ...then the height of the surface...
		list[2] = EGL_HEIGHT;
		list[3] = m_i32TexSize;
		/* ... then we specifiy the target for the texture
			that will be created when the pbuffer is created...*/
		list[4] = EGL_TEXTURE_TARGET;
		list[5] = EGL_TEXTURE_2D;
		/*..then the format of the texture that will be created
			when the pBuffer is bound to a texture...*/
		list[6] = EGL_TEXTURE_FORMAT;
		list[7] = EGL_TEXTURE_RGB;
		// The final thing is EGL_NONE which signifies the end.
		list[8] = EGL_NONE;

		/*
			Get the current display, context and surface so we can switch between the
			PBuffer surface and the main render surface.
		*/

		m_CurrentDisplay = eglGetCurrentDisplay();
		m_CurrentContext = eglGetCurrentContext();
		m_CurrentSurface = eglGetCurrentSurface(EGL_DRAW);
	}
#else
	else
	{
コード例 #13
0
/*!***************************************************************************
 @Function			PVRTMatrixQuaternionSlerpF
 @Output			qOut	Result of the interpolation
 @Input				qA		First quaternion to interpolate from
 @Input				qB		Second quaternion to interpolate from
 @Input				t		Coefficient of interpolation
 @Description		Perform a Spherical Linear intERPolation between quaternion A
					and quaternion B at time t. t must be between 0.0f and 1.0f
*****************************************************************************/
void PVRTMatrixQuaternionSlerpF(
	PVRTQUATERNIONf			&qOut,
	const PVRTQUATERNIONf	&qA,
	const PVRTQUATERNIONf	&qB,
	const float				t)
{
	float		fCosine, fAngle, A, B;

	/* Parameter checking */
	if (t<0.0f || t>1.0f)
	{
		_RPT0(_CRT_WARN, "PVRTMatrixQuaternionSlerp : Bad parameters\n");
		qOut.x = 0;
		qOut.y = 0;
		qOut.z = 0;
		qOut.w = 1;
		return;
	}

	/* Find sine of Angle between Quaternion A and B (dot product between quaternion A and B) */
	fCosine = qA.w*qB.w + qA.x*qB.x + qA.y*qB.y + qA.z*qB.z;

	if (fCosine < 0)
	{
		PVRTQUATERNIONf qi;

		/*
			<http://www.magic-software.com/Documentation/Quaternions.pdf>

			"It is important to note that the quaternions q and -q represent
			the same rotation... while either quaternion will do, the
			interpolation methods require choosing one over the other.

			"Although q1 and -q1 represent the same rotation, the values of
			Slerp(t; q0, q1) and Slerp(t; q0,-q1) are not the same. It is
			customary to choose the sign... on q1 so that... the angle
			between q0 and q1 is acute. This choice avoids extra
			spinning caused by the interpolated rotations."
		*/
		qi.x = -qB.x;
		qi.y = -qB.y;
		qi.z = -qB.z;
		qi.w = -qB.w;

		PVRTMatrixQuaternionSlerpF(qOut, qA, qi, t);
		return;
	}

	fCosine = PVRT_MIN(fCosine, 1.0f);
	fAngle = (float)PVRTFACOS(fCosine);

	/* Avoid a division by zero */
	if (fAngle==0.0f)
	{
		qOut = qA;
		return;
	}

	/* Precompute some values */
	A = (float)(PVRTFSIN((1.0f-t)*fAngle) / PVRTFSIN(fAngle));
	B = (float)(PVRTFSIN(t*fAngle) / PVRTFSIN(fAngle));

	/* Compute resulting quaternion */
	qOut.x = A * qA.x + B * qB.x;
	qOut.y = A * qA.y + B * qB.y;
	qOut.z = A * qA.z + B * qB.z;
	qOut.w = A * qA.w + B * qB.w;

	/* Normalise result */
	PVRTMatrixQuaternionNormalizeF(qOut);
}
コード例 #14
0
/*!****************************************************************************
 @Function		RenderScene
 @Return		bool		true if no error occured
 @Description	Main rendering loop function of the program. The shell will
				call this function every frame.
				eglSwapBuffers() will be performed by PVRShell automatically.
				PVRShell will also manage important OS events.
				Will also manage relevent OS events. The user has access to
				these events through an abstraction layer provided by PVRShell.
******************************************************************************/
bool OGLES2LevelOfDetail::RenderScene()
{
	// Clear the color and depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Use shader program
	glUseProgram(m_ShaderProgram.uiId);

	// Bind textures
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, m_uiReflectTex);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, m_uiNormalTex);

	// Rotate and Translate the model matrix
	PVRTMat4 mModel, mRotY, mTrans;
	float fDistance = 1400.0f * cos(m_fPositionZ) - 1350.0f;
	
	mTrans = PVRTMat4::Translation(0.0, 0.0, fDistance);
	mRotY = PVRTMat4::RotationY(m_fAngleY);
	mModel = mTrans * mRotY;

	m_fAngleY += PVRT_PI / 210;
	m_fPositionZ += 2 * PVRT_PI * 0.0008f;

	// Set model view projection matrix
	PVRTMat4 mModelView, mMVP;
	mModelView = m_mView * mModel;
	mMVP = m_mProjection * mModelView;
	glUniformMatrix4fv(m_ShaderProgram.auiLoc[eMVPMatrix], 1, GL_FALSE, mMVP.ptr());

	// Set model matrix
	PVRTMat3 Model3x3 = PVRTMat3(mModel);

	glUniformMatrix3fv(m_ShaderProgram.auiLoc[eModelWorld], 1, GL_FALSE, Model3x3.ptr());

	// Set eye position in model space
	PVRTVec4 vEyePosModel;
	vEyePosModel = mModelView.inverse() * PVRTVec4(0, 0, 0, 1);

	glUniform3fv(m_ShaderProgram.auiLoc[eEyePosModel], 1, &vEyePosModel.x);

	// Calculate the square of the pixel area that the mesh takes up on screen
	// This is done by projecting the vertices of the bounding box to screen space
	// then taking the axis aligned 2D bounding box of the projected vertices.
	// This is a very conservative estimate
	float fMinX, fMaxX, fMinY, fMaxY, fX, fY;
	ProjectVertex(m_avBoundingBox[0], mMVP, fX, fY);
	fMinX = fMaxX = fX;
	fMinY = fMaxY = fY;

	for (int i = 1; i < 8; ++i)
	{
		ProjectVertex(m_avBoundingBox[i], mMVP, fX, fY);
		fMinX = PVRT_MIN(fMinX, fX);
		fMinY = PVRT_MIN(fMinY, fY);
		fMaxX = PVRT_MAX(fMaxX, fX);
		fMaxY = PVRT_MAX(fMaxY, fY);
	}

	// Choose high detail if the mesh bounding box covers more than 2% of the screen
	m_bHighDetail = ((fMaxX - fMinX) * (fMaxY - fMinY) > 0.02);
	glUniform1i(m_ShaderProgram.auiLoc[eHighDetail], m_bHighDetail);

	/*
		Now that the uniforms are set, call another function to actually draw the mesh.
	*/
	DrawMesh(m_bHighDetail ? 0 : 1);

	// Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools
	m_Print3D.DisplayDefaultTitle("Level of detail", (m_bHighDetail) ? "Detail: high" : "Detail: low", ePVRTPrint3DLogoIMG);
	m_Print3D.Flush();
	return true;
}
コード例 #15
0
/*!****************************************************************************
 @Function		LoadVbos
 @Description	Loads the mesh data required for this training course into
				vertex buffer objects
******************************************************************************/
void OGLES2LevelOfDetail::LoadVbos()
{
	if (!m_puiVbo)      m_puiVbo = new GLuint[m_Scene.nNumMesh];
	if (!m_puiIndexVbo) m_puiIndexVbo = new GLuint[m_Scene.nNumMesh];

	/*
		Load vertex data of all meshes in the scene into VBOs

		The meshes have been exported with the "Interleave Vectors" option,
		so all data is interleaved in the buffer at pMesh->pInterleaved.
		Interleaving data improves the memory access pattern and cache efficiency,
		thus it can be read faster by the hardware.
	*/
	glGenBuffers(m_Scene.nNumMesh, m_puiVbo);
	for (unsigned int i = 0; i < m_Scene.nNumMesh; ++i)
	{
		// Load vertex data into buffer object
		SPODMesh& Mesh = m_Scene.pMesh[i];
		unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
		glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]);
		glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);

		// Load index data into buffer object if available
		m_puiIndexVbo[i] = 0;
		if (Mesh.sFaces.pData)
		{
			glGenBuffers(1, &m_puiIndexVbo[i]);
			uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
		}

		if (i == 0)
		{
			PVRTVec3 vBoundingBoxMin, vBoundingBoxMax;

			// calculate bounding box for mesh 0
			float* pfData = (float*)Mesh.pInterleaved;
			vBoundingBoxMin.x = vBoundingBoxMax.x = pfData[0];
			vBoundingBoxMin.y = vBoundingBoxMax.y = pfData[1];
			vBoundingBoxMin.z = vBoundingBoxMax.z = pfData[2];

			for(unsigned int i = 1; i < Mesh.nNumVertex; ++i)
			{
				pfData = (float*)(((char*)pfData) + Mesh.sVertex.nStride);

				vBoundingBoxMin.x = PVRT_MIN(vBoundingBoxMin.x, pfData[0]);
				vBoundingBoxMin.y = PVRT_MIN(vBoundingBoxMin.y, pfData[1]);
				vBoundingBoxMin.z = PVRT_MIN(vBoundingBoxMin.z, pfData[2]);
				vBoundingBoxMax.x = PVRT_MAX(vBoundingBoxMax.x, pfData[0]);
				vBoundingBoxMax.y = PVRT_MAX(vBoundingBoxMax.y, pfData[1]);
				vBoundingBoxMax.z = PVRT_MAX(vBoundingBoxMax.z, pfData[2]);
			}

			for (int i = 0; i < 8; ++i)
			{
				m_avBoundingBox[i].x = (i & 1) ? vBoundingBoxMin.x : vBoundingBoxMax.x;
				m_avBoundingBox[i].y = (i & 2) ? vBoundingBoxMin.y : vBoundingBoxMax.y;
				m_avBoundingBox[i].z = (i & 4) ? vBoundingBoxMin.z : vBoundingBoxMax.z;
				m_avBoundingBox[i].w = 1.0f;
			}
		}
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
コード例 #16
0
/*!***************************************************************************
 @Function		Draw
 @Input			i32StartPath Path to start drawing from
 @Input			i32EndPath	Path to end drawing on
 @Returns		True on success
 @Description	Draw a set of the paths loaded from the file. If no argument
				is specified this function will draw all paths.
*****************************************************************************/
bool CPVRTPVGObject::Draw(int i32StartPath, int i32EndPath)
{
	if (!m_bInitialized)
	{
		// This set has not been initialised so return.
		return false;
	}

	if(i32EndPath < i32StartPath)
	{
		i32EndPath = m_i32NumPaths;
	}

	i32StartPath = PVRT_MAX(0, i32StartPath);
	i32EndPath = PVRT_MIN(i32EndPath, m_i32NumPaths);

	for(int i = i32StartPath; i < i32EndPath; ++i)
	{
		// Set the blending options. PVG files only support standard translucency.
		if(m_pPaths[i].m_bNeedsBlending)
		{
			vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
		}
		else
		{
			vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
		}

		// Check whether this one is a path without fill or stroke and ignore it.
		if(m_pPaths[i].m_paintMode == 0)
		{
			continue;
		}

		// Fill the parameters for the current Fill Paint
		// Check if the paint is present, if it is different than the previous one or if it is the first one.
		if(((m_pPaths[i].m_paintMode & VG_FILL_PATH) && m_pPaths[i].m_bIsNewFill) || (i==i32StartPath))
		{
			vgSeti(VG_FILL_RULE, m_pPaths[i].m_fillRule);

			vgSetPaint(m_pPaths[i].m_fillPaint, VG_FILL_PATH);
		}

		// Fill the parameters for the current Stroke Paint
		if(((m_pPaths[i].m_paintMode & VG_STROKE_PATH) && m_pPaths[i].m_bIsNewStroke) || (i==i32StartPath))
        {
			vgSetf(VG_STROKE_LINE_WIDTH, m_pPaths[i].m_fStrokeWidth);
			vgSeti(VG_STROKE_CAP_STYLE,	 m_pPaths[i].m_capStyle);
			vgSeti(VG_STROKE_JOIN_STYLE, m_pPaths[i].m_joinStyle);
			vgSetf(VG_STROKE_MITER_LIMIT,m_pPaths[i].m_fMiterLimit);

			// Get current stroke 'dash' if any
			if (m_pPaths[i].m_ui32DashID != 666)
			{
				vgSetf(VG_STROKE_DASH_PHASE, m_pPaths[i].m_fDashPhase);
				vgSetfv(VG_STROKE_DASH_PATTERN, m_pPaths[i].m_ui32NumDashes, m_pPaths[i].m_fDashValues);
			}
			else
			{
				vgSetfv(VG_STROKE_DASH_PATTERN, 0, (VGfloat *) 0); // disable dashes
			}

 			vgSetPaint(m_pPaths[i].m_strokePaint, VG_STROKE_PATH);
        }

		// Draw this path.
		vgDrawPath(m_pPaths[i].m_path, m_pPaths[i].m_paintMode);
	}

	// Success!
	return true;
}
コード例 #17
0
ファイル: OGLES2FilmTV.cpp プロジェクト: klokik/Examples
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no error occurred
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependant on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLES2FilmTV::InitView()
{
	CPVRTString ErrorStr;

	//	Initialize VBO data
	if(!LoadVbos(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	//	Load textures
	if(!LoadTextures(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	//	Load and compile the shaders & link programs
	if(!LoadShaders(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	//	Initialize Print3D
	bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);

	if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
	{
		PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
		return false;
	}

	//Set OpenGL ES render states needed for this demo

	// Enable backface culling and depth test
	glCullFace(GL_BACK);
	glEnable(GL_CULL_FACE);

	glEnable(GL_DEPTH_TEST);

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	// Find the largest square power of two texture that fits into the viewport
	m_i32TexSize = 1;
	int iSize = PVRT_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight));
	while (m_i32TexSize * 2 < iSize) m_i32TexSize *= 2;

	// Get the currently bound frame buffer object. On most platforms this just gives 0.
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFB);

	for(int i = 0; i < 2; ++i)
	{
		// Create texture for the FBO
		glGenTextures(1, &m_uiTexture[i]);
		glBindTexture(GL_TEXTURE_2D, m_uiTexture[i]);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_i32TexSize, m_i32TexSize, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		// Create FBO
		glGenFramebuffers(1, &m_uiFbo[i]);
		glBindFramebuffer(GL_FRAMEBUFFER, m_uiFbo[i]);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uiTexture[i], 0);

		glGenRenderbuffers(1, &m_uiDepthBuffer[i]);
		glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthBuffer[i]);

		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_i32TexSize, m_i32TexSize);
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthBuffer[i]);

        // Check that our FBO creation was successful
        GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);

        if(uStatus != GL_FRAMEBUFFER_COMPLETE)
        {
            m_bFBOsCreated = false;
            PVRShellOutputDebug("ERROR: Failed to initialise FBO");
            break;
        }

		// Clear the colour buffer for this FBO
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFB);

	// Setup the main camera
	PVRTVec3	vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f);
	float fFOV;

	// Camera nodes are after the mesh and light nodes in the array
	int i32CamID = m_Scene.pNode[m_Scene.nNumMeshNode + m_Scene.nNumLight + g_ui32Camera].nIdx;

	// Get the camera position, target and field of view (fov)
	if(m_Scene.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target?
		fFOV = m_Scene.GetCameraPos( vFrom, vTo, g_ui32Camera); // vTo is taken from the target node
	else
		fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, g_ui32Camera); // vTo is calculated from the rotation

	m_View = PVRTMat4::LookAtRH(vFrom, vTo, vUp);

	// Calculate the projection matrix
	PVRTMat4 mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate);
	m_ViewProjection = mProjection * m_View;

	// Check to see if the GL_EXT_discard_framebuffer extension is supported
    if(m_bFBOsCreated && (m_bDiscard = CPVRTgles2Ext::IsGLExtensionSupported("GL_EXT_discard_framebuffer")) != false)
	{
		m_Extensions.LoadExtensions();
		m_bDiscard = m_Extensions.glDiscardFramebufferEXT != 0;
	}

	return true;
}
コード例 #18
0
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no  error occured
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependant on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLES2RenderToTexture::InitView()
{
	// Find the largest square power of two texture that fits into the viewport
	m_i32TexSize = 1;
	int iSize = PVRT_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight));
	while (m_i32TexSize * 2 < iSize) m_i32TexSize *= 2;

	srand(PVRShellGetTime());
	m_ui32Framenum = rand() % 5000;

	// Get the initial time
	m_ui32Time = PVRShellGetTime();

	/*
		Initialize VBO data and load textures
	*/
	LoadVbos();
	LoadTextures();

	/*
		Load and compile the shaders & link programs
	*/
	CPVRTString ErrorStr;
	if (!LoadShaders(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	// Set the sampler2D uniforms to corresponding texture units
	glUniform1i(glGetUniformLocation(m_ShaderProgram.uiId, "sTexture"), 0);

	/*
		Initialize Print3D
	*/

	// Is the screen rotated?
	bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);

	if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
	{
		PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
		return false;
	}

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	
	/*
		Create two handles for a frame buffer object.
	*/
	glGenFramebuffers(2, m_auiFbo);
	m_i32CurrentFbo = 1;

	/*
		Get the currently bound frame buffer object. On most platforms this just gives 0.
	 */
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo);

	/*
		Attach the renderable objects (e.g. textures) to the frame buffer object now as 
		they will stay attached to the frame buffer object even when it is not bound.
	*/

	// We have two FBOs so we're doing the same for each
	for(int i = 0; i < 2; ++i)
	{
		/*
			Firstly, to do anything with a frame buffer object we need to bind it. In the case
			below we are binding our frame buffer object to the frame buffer.
		*/
		glBindFramebuffer(GL_FRAMEBUFFER, m_auiFbo[i]);

		/*
			To render to a texture we need to attach it texture to the frame buffer object.
			GL_COLOR_ATTACHMENT0 tells it to attach the texture to the colour buffer, the 0 on the
			end refers to the colour buffer we want to attach it to as a frame buffer object can
			have more than one colour buffer.
		*/
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_auiTexture[i], 0);

		// Clear the color buffer for this FBO
		glClear(GL_COLOR_BUFFER_BIT);

		/*
			Create and bind a depth buffer to the frame buffer object.

			A depth buffer isn't needed for this training course but will likely be 
			required for most uses of frame buffer objects so its attachment is being 
			demonstrated here.
		*/

		// Generate and bind the handle for the render buffer (which will become our depth buffer)
		glGenRenderbuffers(1, &m_auiDepthBuffer[i]);
		glBindRenderbuffer(GL_RENDERBUFFER, m_auiDepthBuffer[i]);

		/* 
			Currently it is unknown to GL that we want our new render buffer to be a depth buffer.
			glRenderbufferStorage will fix this and in this case will allocate a depth buffer of
			m_i32TexSize by m_i32TexSize.
		*/
		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_i32TexSize, m_i32TexSize);

		// Now we have our depth buffer attach it to our frame buffer object.
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_auiDepthBuffer[i]);
	}

	/*
		Unbind the frame buffer object so rendering returns back to the backbuffer.
	*/
	glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo);

	// Use a nice bright blue as clear colour
	glClearColor(0.6f, 0.8f, 1.0f, 1.0f);

	return true;
}
コード例 #19
0
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no error occured
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependant on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLESAntialiasedLines::InitView()
{
	bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
	m_iWidth  = PVRShellGet(prefWidth);
	m_iHeight = PVRShellGet(prefHeight);

	myglClearColor(f2vt(0.6f), f2vt(0.8f), f2vt(1.0f), f2vt(1.0f));

	// Initialise Print3D
	if(m_Print3D.SetTextures(0, m_iWidth, m_iHeight, bRotate) != PVR_SUCCESS)
	{
		PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D.\n");
		return false;
	}

	// Initialise the texture
	if (PVRTTextureLoadFromPVR("LineRound.pvr", &m_uiTexture) != PVR_SUCCESS)
	{
		PVRShellSet(prefExitMessage, "ERROR: Failed to load texture.\n");
		return false;
	}
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	// Initialise geometry
	SVertex *paVertices = new SVertex[c_iNumLines * 2];       // 2 vertices per GL_LINE
	STexVertex *paTexVertices = new STexVertex[c_iNumLines * 8]; // 8 vertices per AA line (includes caps)
	GLushort *paui16Indices = new GLushort[c_iNumLines * 18];  // 18 indices per AA line (6 triangles) 

	if(!paVertices || !paTexVertices || !paui16Indices)
	{
		delete[] paVertices;
		delete[] paTexVertices;
		delete[] paui16Indices;
		PVRShellSet(prefExitMessage, "ERROR: Failed to allocate line vertices and indices.\n");
		return false;
	}

	srand(0);
	float fAngleStep = PVRT_TWO_PI / c_iNumLines;
	VERTTYPE fSize = f2vt(PVRT_MIN(m_iWidth, m_iHeight) * 0.4f);
	for (int i = 0; i < c_iNumLines; ++i)
	{
		// Place the line vertices on a circle 
		paVertices[i*2].vPosition.x = VERTTYPEMUL(fSize, PVRTSIN(fAngleStep * (i + c_fLineArc)));
		paVertices[i*2].vPosition.y = VERTTYPEMUL(fSize, PVRTCOS(fAngleStep * (i + c_fLineArc)));
		paVertices[i*2+1].vPosition.x = VERTTYPEMUL(fSize, PVRTSIN(fAngleStep * i));
		paVertices[i*2+1].vPosition.y = VERTTYPEMUL(fSize, PVRTCOS(fAngleStep * i));

		// Pick a random RGB color
		paVertices[i*2].uiColor = (0xFF << 24) + 
			((rand() & 0xFF) << 16) + ((rand() & 0xFF) << 8) + (rand() & 0xFF);
		paVertices[i*2+1].uiColor = paVertices[i*2].uiColor;

		// Tessellate the antialiased line
		TessellateLine(paVertices[i*2].vPosition, paVertices[i*2+1].vPosition, 
			c_fLineWidth, paVertices[i*2].uiColor, 
			&paTexVertices[i * 8], i * 8, &paui16Indices[i * 18]);
	}

	// We use 3 VBOs for clarity:
	// 0: AA line vertex data
	// 1: AA line index data
	// 2: GL_LINES vertex data
	glGenBuffers(3, m_uiVbos);

	// Bind the VBOs and fill them with data
	glBindBuffer(GL_ARRAY_BUFFER, m_uiVbos[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(*paTexVertices) * c_iNumLines * 8, paTexVertices, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiVbos[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(*paui16Indices) * c_iNumLines * 18, paui16Indices, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, m_uiVbos[2]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(*paVertices) * c_iNumLines * 2, paVertices, GL_STATIC_DRAW);

	// Unbind buffers
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	// Set projection to use pixel coordinates
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	myglOrtho(0, f2vt((float)PVRShellGet(prefWidth)), f2vt((float)PVRShellGet(prefHeight)), 0, 0, 1);

	delete[] paVertices;
	delete[] paTexVertices;
	delete[] paui16Indices;

	return true;
}
コード例 #20
0
/*!***************************************************************************
 @Function			PVRTMatrixQuaternionSlerpX
 @Output			qOut	Result of the interpolation
 @Input				qA		First quaternion to interpolate from
 @Input				qB		Second quaternion to interpolate from
 @Input				t		Coefficient of interpolation
 @Description		Perform a Spherical Linear intERPolation between quaternion A
					and quaternion B at time t. t must be between 0.0f and 1.0f
					Requires input quaternions to be normalized
*****************************************************************************/
void PVRTMatrixQuaternionSlerpX(
	PVRTQUATERNIONx			&qOut,
	const PVRTQUATERNIONx	&qA,
	const PVRTQUATERNIONx	&qB,
	const int				t)
{
	int		fCosine, fAngle, A, B;

	/* Parameter checking */
	if (t<PVRTF2X(0.0f) || t>PVRTF2X(1.0f))
	{
		_RPT0(_CRT_WARN, "PVRTMatrixQuaternionSlerp : Bad parameters\n");
		qOut.x = PVRTF2X(0.0f);
		qOut.y = PVRTF2X(0.0f);
		qOut.z = PVRTF2X(0.0f);
		qOut.w = PVRTF2X(1.0f);
		return;
	}

	/* Find sine of Angle between Quaternion A and B (dot product between quaternion A and B) */
	fCosine = PVRTXMUL(qA.w, qB.w) +
		PVRTXMUL(qA.x, qB.x) + PVRTXMUL(qA.y, qB.y) + PVRTXMUL(qA.z, qB.z);

	if(fCosine < PVRTF2X(0.0f))
	{
		PVRTQUATERNIONx qi;

		/*
			<http://www.magic-software.com/Documentation/Quaternions.pdf>

			"It is important to note that the quaternions q and -q represent
			the same rotation... while either quaternion will do, the
			interpolation methods require choosing one over the other.

			"Although q1 and -q1 represent the same rotation, the values of
			Slerp(t; q0, q1) and Slerp(t; q0,-q1) are not the same. It is
			customary to choose the sign... on q1 so that... the angle
			between q0 and q1 is acute. This choice avoids extra
			spinning caused by the interpolated rotations."
		*/
		qi.x = -qB.x;
		qi.y = -qB.y;
		qi.z = -qB.z;
		qi.w = -qB.w;

		PVRTMatrixQuaternionSlerpX(qOut, qA, qi, t);
		return;
	}

	fCosine = PVRT_MIN(fCosine, PVRTF2X(1.0f));
	fAngle = PVRTXACOS(fCosine);

	/* Avoid a division by zero */
	if (fAngle==PVRTF2X(0.0f))
	{
		qOut = qA;
		return;
	}

	/* Precompute some values */
	A = PVRTXDIV(PVRTXSIN(PVRTXMUL((PVRTF2X(1.0f)-t), fAngle)), PVRTXSIN(fAngle));
	B = PVRTXDIV(PVRTXSIN(PVRTXMUL(t, fAngle)), PVRTXSIN(fAngle));

	/* Compute resulting quaternion */
	qOut.x = PVRTXMUL(A, qA.x) + PVRTXMUL(B, qB.x);
	qOut.y = PVRTXMUL(A, qA.y) + PVRTXMUL(B, qB.y);
	qOut.z = PVRTXMUL(A, qA.z) + PVRTXMUL(B, qB.z);
	qOut.w = PVRTXMUL(A, qA.w) + PVRTXMUL(B, qB.w);

	/* Normalise result */
	PVRTMatrixQuaternionNormalizeX(qOut);
}
コード例 #21
0
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no error occurred
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependent on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLES2IntroducingPrint3D::InitView()
{
	/*
		Initialize the textures used by Print3D.
		To properly display text, Print3D needs to know the viewport dimensions
		and whether the text should be rotated. We get the dimensions using the
		shell function PVRShellGet(prefWidth/prefHeight). We can also get the
		rotate parameter by checking prefIsRotated and prefFullScreen.
	*/
	bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);

	// Retrieve screen metrics from PVRShell
	unsigned int uiWidth  = PVRShellGet(prefWidth);
	unsigned int uiHeight = PVRShellGet(prefHeight);

	/*
		The fonts are loaded here using a PVRTool's ResourceFile wrapper. However, 
		it is possible to load the textures in any way that provides access to a pointer 
		to memory, and the size of the file.
	*/
	CPVRTResourceFile CustomFont(c_szTextFile);
	if(!CustomFont.IsOpen())
	{
		PVRShellSet(prefExitMessage, "ERROR: Failed to load font file!");
		return false;
	}

	CPVRTResourceFile IntroFont(c_szIntroFile);
	if(!IntroFont.IsOpen())
	{
		PVRShellSet(prefExitMessage, "ERROR: Failed to load font file!");
		return false;
	}
	
	// Determine which size title font to use.
	unsigned int uiMinScreenLen = PVRT_MIN(uiWidth, uiHeight);
	const char* pTitleFontFile = NULL;
	if(uiMinScreenLen >= 720)
		pTitleFontFile = c_szTitleFont[eFontSize_56];
	else if(uiMinScreenLen >= 640)
		pTitleFontFile = c_szTitleFont[eFontSize_46];
	else
		pTitleFontFile = c_szTitleFont[eFontSize_36];

	CPVRTResourceFile TitleFont(pTitleFontFile);
	if(!TitleFont.IsOpen())
	{
		PVRShellSet(prefExitMessage, "ERROR: Failed to load font file!");
		return false;
	}

	/*
		The first version of Print3D.SetTextures() presented here sets up m_Print3D 
		with default, built-in textures. The overloaded functions provided allow user-defined 
		textures to be loaded instead. Please refer to PVRTexTool's user manual for 
		instructions on generating fonts files.
	*/
	m_Print3D.SetTextures(NULL, uiWidth, uiHeight, bRotate);
	m_CentralText.SetTextures(NULL, CustomFont.DataPtr(), uiWidth, uiHeight, bRotate);
	m_IntroText.SetTextures(NULL, IntroFont.DataPtr(), uiWidth, uiHeight, bRotate);
	m_TitleText.SetTextures(NULL, TitleFont.DataPtr(), uiWidth, uiHeight, bRotate);

	// Sets the clear color
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	// Generate background texture
	GenerateBackgroundTexture(uiWidth, uiHeight);

	m_ulStartTime = PVRShellGetTime();

	return true;
}