/****************************************************************************** @File OGLES2/PVRTBackground.cpp @Title OGLES2/PVRTBackground @Version @Copyright Copyright (c) Imagination Technologies Limited. @Platform ANSI compatible @Description Function to draw a background texture. ******************************************************************************/ #include "PVRTShader.h" #include "PVRTBackground.h" // The header that contains the shaders #include "PVRTBackgroundShaders.h" // Index to bind the attributes to vertex shaders const int VERTEX_ARRAY = 0; const int TEXCOORD_ARRAY = 1; /**************************************************************************** ** Structures ****************************************************************************/ // The struct to include various API variables struct SPVRTBackgroundAPI { GLuint m_ui32VertexShader; GLuint m_ui32FragShader; GLuint m_ui32ProgramObject; GLuint m_ui32VertexBufferObject; }; /**************************************************************************** ** Class: CPVRTBackground ****************************************************************************/ /***************************************************************************** @Function Background @Description Init some values. *****************************************************************************/ CPVRTBackground::CPVRTBackground(void) { m_bInit = false; m_pAPI = 0; } /***************************************************************************** @Function ~Background @Description Calls Destroy() *****************************************************************************/ CPVRTBackground::~CPVRTBackground(void) { delete m_pAPI; m_pAPI = 0; } /*!*************************************************************************** @Function Destroy @Description Destroys the background and releases API specific resources *****************************************************************************/ void CPVRTBackground::Destroy() { if(m_bInit) { // Delete shaders glDeleteProgram(m_pAPI->m_ui32ProgramObject); glDeleteShader(m_pAPI->m_ui32VertexShader); glDeleteShader(m_pAPI->m_ui32FragShader); // Delete buffer objects glDeleteBuffers(1, &m_pAPI->m_ui32VertexBufferObject); m_bInit = false; } delete m_pAPI; m_pAPI = 0; } /*!*************************************************************************** @Function Init @Input pContext A pointer to a PVRTContext @Input bRotate true to rotate texture 90 degrees. @Input pszError An option string for returning errors @Return PVR_SUCCESS on success @Description Initialises the background *****************************************************************************/ EPVRTError CPVRTBackground::Init(const SPVRTContext * const pContext, bool bRotate, CPVRTString *pszError) { PVRT_UNREFERENCED_PARAMETER(pContext); Destroy(); m_pAPI = new SPVRTBackgroundAPI; if(!m_pAPI) { if(pszError) *pszError = "Error: Insufficient memory to allocate SCPVRTBackgroundAPI."; return PVR_FAIL; } m_pAPI->m_ui32VertexShader = 0; m_pAPI->m_ui32FragShader = 0; m_pAPI->m_ui32ProgramObject = 0; m_pAPI->m_ui32VertexBufferObject = 0; bool bResult; CPVRTString sTmpErrStr; // The shader loading code doesn't expect a null pointer for the error string if(!pszError) pszError = &sTmpErrStr; /* Compiles the shaders. For a more detailed explanation, see IntroducingPVRTools */ #if defined(GL_SGX_BINARY_IMG) // Try binary shaders first bResult = (PVRTShaderLoadBinaryFromMemory(_BackgroundFragShader_fsc, _BackgroundFragShader_fsc_size, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_pAPI->m_ui32FragShader, pszError) == PVR_SUCCESS) && (PVRTShaderLoadBinaryFromMemory(_BackgroundVertShader_vsc, _BackgroundVertShader_vsc_size, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_pAPI->m_ui32VertexShader, pszError) == PVR_SUCCESS); if(!bResult) #endif { // if binary shaders don't work, try source shaders bResult = (PVRTShaderLoadSourceFromMemory(_BackgroundFragShader_fsh, GL_FRAGMENT_SHADER, &m_pAPI->m_ui32FragShader, pszError) == PVR_SUCCESS) && (PVRTShaderLoadSourceFromMemory(_BackgroundVertShader_vsh, GL_VERTEX_SHADER, &m_pAPI->m_ui32VertexShader, pszError) == PVR_SUCCESS); } _ASSERT(bResult); if(!bResult) return PVR_FAIL; // Reset the error string if(pszError) *pszError = ""; // Create the shader program m_pAPI->m_ui32ProgramObject = glCreateProgram(); // Attach the fragment and vertex shaders to it glAttachShader(m_pAPI->m_ui32ProgramObject, m_pAPI->m_ui32FragShader); glAttachShader(m_pAPI->m_ui32ProgramObject, m_pAPI->m_ui32VertexShader); // Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY glBindAttribLocation(m_pAPI->m_ui32ProgramObject, VERTEX_ARRAY, "myVertex"); // Bind the custom vertex attribute "myUV" to location TEXCOORD_ARRAY glBindAttribLocation(m_pAPI->m_ui32ProgramObject, TEXCOORD_ARRAY, "myUV"); // Link the program glLinkProgram(m_pAPI->m_ui32ProgramObject); GLint Linked; glGetProgramiv(m_pAPI->m_ui32ProgramObject, GL_LINK_STATUS, &Linked); if (!Linked) { int i32InfoLogLength, i32CharsWritten; glGetProgramiv(m_pAPI->m_ui32ProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength); char* pszInfoLog = new char[i32InfoLogLength]; glGetProgramInfoLog(m_pAPI->m_ui32ProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog); *pszError = CPVRTString("Failed to link: ") + pszInfoLog + "\n"; delete [] pszInfoLog; bResult = false; } _ASSERT(bResult); if(!bResult) return PVR_FAIL; // Use the loaded shader program glUseProgram(m_pAPI->m_ui32ProgramObject); // Set the sampler2D variable to the first texture unit glUniform1i(glGetUniformLocation(m_pAPI->m_ui32ProgramObject, "sampler2d"), 0); // Create the vertex buffer object GLfloat *pVertexData = 0; // The vertex data for non-rotated GLfloat afVertexData[16] = { -1, -1, 1, -1, -1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1}; // The vertex data for rotated GLfloat afVertexDataRotated[16] = {-1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 0, 1, 1, 0, 0, 0}; if(!bRotate) pVertexData = &afVertexData[0]; else pVertexData = &afVertexDataRotated[0]; glGenBuffers(1, &m_pAPI->m_ui32VertexBufferObject); glBindBuffer(GL_ARRAY_BUFFER, m_pAPI->m_ui32VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, pVertexData, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); m_bInit = true; return PVR_SUCCESS; } /*!*************************************************************************** @Function Draw @Input ui32Texture Texture to use @Return PVR_SUCCESS on success @Description Draws a texture on a quad covering the whole screen. *****************************************************************************/ EPVRTError CPVRTBackground::Draw(const GLuint ui32Texture) { if(!m_bInit) return PVR_FAIL; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ui32Texture); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Use the loaded shader program glUseProgram(m_pAPI->m_ui32ProgramObject); // Set vertex data glBindBuffer(GL_ARRAY_BUFFER, m_pAPI->m_ui32VertexBufferObject); glEnableVertexAttribArray(VERTEX_ARRAY); glVertexAttribPointer(VERTEX_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, (const void*) 0); // Set texture coordinates glEnableVertexAttribArray(TEXCOORD_ARRAY); glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, (const void*) (8 * sizeof(float))); // Render geometry glDrawArrays(GL_TRIANGLE_STRIP,0,4); glDisableVertexAttribArray(VERTEX_ARRAY); glDisableVertexAttribArray(TEXCOORD_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); glUseProgram(0); return PVR_SUCCESS; } /***************************************************************************** End of file (CPVRTBackground.cpp) *****************************************************************************/