# Could not show multiple textures

**URL:** <https://forums.imgtec.com/t/could-not-show-multiple-textures/879>\
**Category:** PowerVR Insider\
**Created:** [October 26, 2010, 7:37pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879 "2010-10-26T19:37:56Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [October 26, 2010, 7:37pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/1 "2010-10-26T19:37:56Z")

</div>

I use the PVRTTextureLoadFromPVR to load two different textures into two different GLuint as following

&nbsp;
  

&nbsp;if(PVRTTextureLoadFromPVR(c\_sz\_BK\_TextureFile, &m\_uiBKTex) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );
  

  
&nbsp;if(PVRTTextureLoadFromPVR(c\_sz\_FG\_TextureFile, &m\_uiFGTex) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );
  

&nbsp;
  

In the RenderScene function, I did the following
  

&nbsp;glActiveTexture(GL\_TEXTURE0);  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
&nbsp;glActiveTexture(GL\_TEXTURE1);  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);
  

&nbsp;
  

Then I draw two planes, one big and one small. Each is with the corresponding texture. However, I always see the same texture is mapped on both planes. The second one is not mapped on the 2nd plane as I expected. 
  

&nbsp;
  

Can you give me a hint why I could not map the 2nd texture?
  

&nbsp;
  

&nbsp;

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [October 26, 2010, 8:28pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/2 "2010-10-26T20:28:11Z")

</div>

Here is the complete source code.

&nbsp;
  

  
_#include \<math.h\>  
#include \<stdio.h\>_
  

_#include \<EGL/egl.h\>  
#include \<GLES2/gl2.h\>  
#include "OGLES2Tools.h"&nbsp;   
#include "PVRShell.h"_
  

_// Index to bind the attributes to vertex shaders  
#define VERTEX\_ARRAY&nbsp;0  
#define TEXCOORD\_ARRAY&nbsp;1  
#define NORMAL\_ARRAY&nbsp;2  
#define COLOR\_ARRAY&nbsp;&nbsp;3_
  

_const char c\_sz\_BK\_TextureFile[]&nbsp;&nbsp;= "BG-m.pvr";  
const char c\_sz\_FG\_TextureFile[]&nbsp;&nbsp;= "FG-m.pvr";_
  

  
_//two triangles  
GLfloat BK\_TRIANGLE\_VETEX[18] ={  
-1.0f, 1.0f, -1.0f,   
1.0f, 1.0f, -1.0f,   
1.0f, -1.0f, -1.0f,  
-1.0f, 1.0f, -1.0f,   
1.0f, -1.0f, -1.0f,   
-1.0f, -1.0f, -1.0f  
};_
  

_//normal for each vertex of the two triangles   
GLfloat BK\_TRIANGLE\_NORMAL[18] = {  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f};_
  

_GLfloat BK\_TRIANGLE\_COLOR[24] = {  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f};_
  

_GLfloat BK\_TRIANGLE\_TEXTCOORD[12] = {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.0f,1.0f ,&nbsp;&nbsp; // UVs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,1.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,0.0f};_
  

&nbsp;
  

_//two triangles as popup button  
GLfloat FG\_TRIANGLE\_VETEX[18] ={  
0.55f, 0.22f, 1.0f,   
1.0f, 0.22f, 1.0f,   
1.0f, -1.0f, 1.0f,  
0.55f, 0.22f,&nbsp; 1.0f,   
1.0f, -1.0f, 1.0f,   
0.55f, -1.0f, 1.0f  
};_
  

_//normal for each vertex of the two triangles as popup button  
GLfloat FG\_TRIANGLE\_NORMAL[18] = {  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f};_
  

_GLfloat FG\_TRIANGLE\_COLOR[24] = {  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f};_
  

_GLfloat FG\_TRIANGLE\_TEXTCOORD[12] = {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp; // UVs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,1.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,0.0f};_
  

  
_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;Class implementing the PVRShell functions.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
class OGLESBasicTnL : public PVRShell  
{  
&nbsp;// The vertex and fragment shader OpenGL handles  
&nbsp;GLuint m\_uiVertexShader, m\_uiFragShader;_
  

_&nbsp;// The program object containing the 2 shader objects  
&nbsp;GLuint m\_uiProgramObject;_
  

_&nbsp;// Texture handle  
&nbsp;GLuint&nbsp;m\_uiBKTex;  
&nbsp;GLuint&nbsp;m\_uiFGTex;_
  

  
_public:  
&nbsp;virtual bool InitApplication();  
&nbsp;virtual bool InitView();  
&nbsp;virtual bool ReleaseView();  
&nbsp;virtual bool QuitApplication();  
&nbsp;virtual bool RenderScene();  
};_
  

  
_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;InitApplication  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in InitApplication() will be called by PVRShell once per  
&nbsp;&nbsp;&nbsp;&nbsp;run, before the rendering context is created.  
&nbsp;&nbsp;&nbsp;&nbsp;Used to initialize variables that are not dependant on it  
&nbsp;&nbsp;&nbsp;&nbsp;(e.g. external modules, loading meshes, etc.)  
&nbsp;&nbsp;&nbsp;&nbsp;If the rendering context is lost, InitApplication() will  
&nbsp;&nbsp;&nbsp;&nbsp;not be called again.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::InitApplication()  
{  
&nbsp;&nbsp;&nbsp; bool m\_bUseVertexProgram = true;_
  

_&nbsp;return true;  
}_
  

_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;QuitApplication  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in QuitApplication() will be called by PVRShell once per  
&nbsp;&nbsp;&nbsp;&nbsp;run, just before exiting the program.  
&nbsp;&nbsp;&nbsp;&nbsp;If the rendering context is lost, QuitApplication() will  
&nbsp;&nbsp;&nbsp;&nbsp;not be called.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::QuitApplication()  
{  
&nbsp;&nbsp;&nbsp; return true;  
}_
  

_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;InitView  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in InitView() will be called by PVRShell upon  
&nbsp;&nbsp;&nbsp;&nbsp;initialization or after a change in the rendering context.  
&nbsp;&nbsp;&nbsp;&nbsp;Used to initialize variables that are dependant on the rendering  
&nbsp;&nbsp;&nbsp;&nbsp;context (e.g. textures, vertex buffers, etc.)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::InitView()  
{  
&nbsp;// Fragment and vertex shaders code_
  

_&nbsp;char\* pszFragShader = "  
&nbsp;&nbsp;uniform sampler2D sampler2d;  
&nbsp;&nbsp;varying mediump float&nbsp;varDot;  
&nbsp;&nbsp;varying mediump vec2&nbsp;varCoord;  
&nbsp;&nbsp;varying mediump vec4 v\_primaryColor;  
&nbsp;&nbsp;void main (void)  
&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;gl\_FragColor = texture2D(sampler2d,varCoord) \* varDot\*v\_primaryColor;  
&nbsp;&nbsp;}";  
&nbsp;char\* pszVertShader = "  
&nbsp;&nbsp;attribute highp vec4&nbsp;myVertex;  
&nbsp;&nbsp;attribute mediump vec3&nbsp;myNormal;  
&nbsp;&nbsp;attribute mediump vec4&nbsp;myUV;  
&nbsp;&nbsp;attribute mediump vec4&nbsp; myColor;  
&nbsp;&nbsp;uniform mediump mat4&nbsp;myPMVMatrix;  
&nbsp;&nbsp;uniform mediump vec4&nbsp;myTMatrix;  
&nbsp;&nbsp;uniform mediump float&nbsp;myScale;  
&nbsp;&nbsp;uniform mediump float&nbsp;myYScale;  
&nbsp;&nbsp;uniform mediump mat3&nbsp;myModelViewIT;  
&nbsp;&nbsp;uniform mediump vec3&nbsp;myLightDirection;  
&nbsp;&nbsp;varying mediump float&nbsp;varDot;  
&nbsp;&nbsp;varying mediump vec2&nbsp;varCoord;  
&nbsp;&nbsp;varying mediump vec4&nbsp;v\_primaryColor;  
&nbsp;&nbsp;void main(void)  
&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;v\_primaryColor = myColor;  
&nbsp;&nbsp;&nbsp;gl\_Position = (myPMVMatrix \* myVertex);  
&nbsp;&nbsp;&nbsp;gl\_Position.x = gl\_Position.x\*myScale;  
&nbsp;&nbsp;&nbsp;gl\_Position.y = gl\_Position.y\*myScale\*myYScale;  
&nbsp;&nbsp;&nbsp;gl\_Position.z = gl\_Position.z\*myScale;  
&nbsp;&nbsp;&nbsp;gl\_Position = gl\_Position + myTMatrix;  
&nbsp;&nbsp;&nbsp;varCoord = myUV.st;  
&nbsp;&nbsp;&nbsp;mediump vec3 transNormal = myModelViewIT \* myNormal;  
&nbsp;&nbsp;&nbsp;varDot = max( dot(transNormal, myLightDirection), 0.0 );  
&nbsp;&nbsp;}";_
  

  
_&nbsp;// Create the fragment shader object  
&nbsp;m\_uiFragShader = glCreateShader(GL\_FRAGMENT\_SHADER);_
  

_&nbsp;// Load the source code into it  
&nbsp;glShaderSource(m\_uiFragShader, 1, (const char\*\*)&pszFragShader, NULL);_
  

_&nbsp;// Compile the source code  
&nbsp;glCompileShader(m\_uiFragShader);_
  

_&nbsp;// Check if compilation succeeded  
&nbsp;GLint bShaderCompiled;  
&nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiFragShader, GL\_COMPILE\_STATUS, &bShaderCompiled);  
&nbsp;if (!bShaderCompiled)  
&nbsp;{  
&nbsp;&nbsp;// An error happened, first retrieve the length of the log message  
&nbsp;&nbsp;int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;glGetShaderiv(m\_uiFragShader, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);_
  

_&nbsp;&nbsp;// Allocate enough space for the message and retrieve it  
&nbsp;&nbsp;char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glGetShaderInfoLog(m\_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);_
  

_&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Displays the message in a dialog box when the application quits  
&nbsp;&nbsp;&nbsp;using the shell PVRShellSet function with first parameter prefExitMessage.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;sprintf(pszMsg, "Failed to compile fragment shader: %s", pszInfoLog);  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;delete [] pszMsg;  
&nbsp;&nbsp;delete [] pszInfoLog;  
&nbsp;&nbsp;return false;  
&nbsp;}_
  

_&nbsp;// Loads the vertex shader in the same way  
&nbsp;m\_uiVertexShader = glCreateShader(GL\_VERTEX\_SHADER);  
&nbsp;glShaderSource(m\_uiVertexShader, 1, (const char\*\*)&pszVertShader, NULL);  
&nbsp;glCompileShader(m\_uiVertexShader);  
&nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiVertexShader, GL\_COMPILE\_STATUS, &bShaderCompiled);  
&nbsp;if (!bShaderCompiled)  
&nbsp;{  
&nbsp;&nbsp;int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;glGetShaderiv(m\_uiVertexShader, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glGetShaderInfoLog(m\_uiVertexShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;sprintf(pszMsg, "Failed to compile vertex shader: %s", pszInfoLog);  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;delete [] pszMsg;  
&nbsp;&nbsp;delete [] pszInfoLog;  
&nbsp;&nbsp;return false;  
&nbsp;}_
  

_&nbsp;// Create the shader program  
&nbsp;&nbsp;&nbsp; m\_uiProgramObject = glCreateProgram();_
  

_&nbsp;// Attach the fragment and vertex shaders to it  
&nbsp;&nbsp;&nbsp; glAttachShader(m\_uiProgramObject, m\_uiFragShader);  
&nbsp;&nbsp;&nbsp; glAttachShader(m\_uiProgramObject, m\_uiVertexShader);_
  

_&nbsp;// Bind the custom vertex attribute "myVertex" to location VERTEX\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, VERTEX\_ARRAY, "myVertex");  
&nbsp;// Bind the custom vertex attribute "myUV" to location TEXCOORD\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, TEXCOORD\_ARRAY, "myUV");  
&nbsp;// Bind the custom vertex attribute "myNormal" to location NORMAL\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, NORMAL\_ARRAY, "myNormal");  
&nbsp;// Bind the custom vertex attribute "myColor" to location COLOR\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, COLOR\_ARRAY, "myColor");  
&nbsp;// Link the program  
&nbsp;&nbsp;&nbsp; glLinkProgram(m\_uiProgramObject);_
  

_&nbsp;// Check if linking succeeded in the same way we checked for compilation success  
&nbsp;&nbsp;&nbsp; GLint bLinked;  
&nbsp;&nbsp;&nbsp; glGetProgramiv(m\_uiProgramObject, GL\_LINK\_STATUS, &bLinked);  
&nbsp;if (!bLinked)  
&nbsp;{  
&nbsp;&nbsp;int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;glGetProgramiv(m\_uiProgramObject, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;glGetProgramInfoLog(m\_uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;sprintf(pszMsg, "Failed to link program: %s", pszInfoLog);  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;delete [] pszMsg;  
&nbsp;&nbsp;delete [] pszInfoLog;  
&nbsp;&nbsp;return false;  
&nbsp;}  
&nbsp;  
&nbsp;if(PVRTTextureLoadFromPVR(c\_sz\_BK\_TextureFile, &m\_uiBKTex) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;return false;  
&nbsp;}_
  

_&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );_
  

_&nbsp;if(PVRTTextureLoadFromPVR(c\_sz\_FG\_TextureFile, &m\_uiFGTex) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;return false;  
&nbsp;}_
  

_&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );_
  

_&nbsp;return true;  
}_
  

_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;ReleaseView  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in ReleaseView() will be called by PVRShell when the  
&nbsp;&nbsp;&nbsp;&nbsp;application quits or before a change in the rendering context.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::ReleaseView()  
{  
&nbsp;// Frees the texture  
&nbsp;glDeleteTextures(1, &m\_uiBKTex);  
&nbsp;glDeleteTextures(1, &m\_uiFGTex);_
  

_&nbsp;// Frees the OpenGL handles for the program and the 2 shaders  
&nbsp;glDeleteProgram(m\_uiProgramObject);  
&nbsp;glDeleteShader(m\_uiVertexShader);  
&nbsp;glDeleteShader(m\_uiFragShader);_
  

  
_&nbsp;return true;  
}_
  

_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;RenderScene  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Main rendering loop function of the program. The shell will  
&nbsp;&nbsp;&nbsp;&nbsp;call this function every frame.  
&nbsp;&nbsp;&nbsp;&nbsp;eglSwapBuffers() will be performed by PVRShell automatically.  
&nbsp;&nbsp;&nbsp;&nbsp;PVRShell will also manage important OS events.  
&nbsp;&nbsp;&nbsp;&nbsp;Will also manage relevent OS events. The user has access to  
&nbsp;&nbsp;&nbsp;&nbsp;these events through an abstraction layer provided by PVRShell.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::RenderScene()  
{  
&nbsp;glViewport(0, 0, 800, 600);  
&nbsp;glClearColor(0.0f, 0.0f, 0.0f, 1.0f);_
  

_&nbsp;glUseProgram(m\_uiProgramObject);_
  

_&nbsp;glActiveTexture(GL\_TEXTURE0);  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
&nbsp;glActiveTexture(GL\_TEXTURE1);  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);_
  

_&nbsp;glEnable(GL\_CULL\_FACE);  
&nbsp;glCullFace(GL\_FRONT);_
  

_&nbsp;// Clears the color and depth buffer  
&nbsp;glClear(GL\_COLOR\_BUFFER\_BIT | GL\_DEPTH\_BUFFER\_BIT);_
  

_&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;//Draw the background  
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*_
  

_&nbsp;float alpha = 0;&nbsp;&nbsp;//-p  
&nbsp;float beta =&nbsp; 0;&nbsp; //-q  
&nbsp;float theta = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // o_
  

  
_&nbsp;float aModelViewIT0[] =  
&nbsp;{  
&nbsp;&nbsp;cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta),  
&nbsp;&nbsp;cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),  
&nbsp;&nbsp;-sin(theta),&nbsp;&nbsp;&nbsp;sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta)  
&nbsp;};_
  

  
_&nbsp;/\*  
&nbsp;&nbsp;Bind the projection model view matrix (PMVMatrix) to the  
&nbsp;&nbsp;corresponding uniform variable in the shader.  
&nbsp;&nbsp;This matrix is used in the vertex shader to transform the vertices.  
&nbsp;\*/  
&nbsp;float aPMVMatrix0[] =  
&nbsp;{  
&nbsp;&nbsp;cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta), 0,  
&nbsp;&nbsp;cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),0,  
&nbsp;&nbsp;-sin(theta),&nbsp;&nbsp;&nbsp;sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta),0,  
&nbsp;&nbsp;0,0,0,1  
&nbsp;};_
  

  
_&nbsp;int i32Location = glGetUniformLocation(m\_uiProgramObject, "myPMVMatrix");  
&nbsp;glUniformMatrix4fv( i32Location, 1, GL\_FALSE, aPMVMatrix0);_
  

_&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myModelViewIT");  
&nbsp;glUniformMatrix3fv( i32Location, 1, GL\_FALSE, aModelViewIT0);_
  

_&nbsp;float aTMatrix0[] = {0.0f,0.0f,0.0f,0.0f};  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myTMatrix");  
&nbsp;glUniform4fv( i32Location,1,aTMatrix0);_
  

_&nbsp;float aScale0 = 1.0;  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myScale");  
&nbsp;glUniform1f( i32Location,aScale0);_
  

_&nbsp;float aYScale0 = 1.0;  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myYScale");  
&nbsp;glUniform1f( i32Location,aYScale0);_
  

_&nbsp;// Bind the Light Direction vector to the shader  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myLightDirection");&nbsp;  
&nbsp;glUniform3f( i32Location, 0, 0, 1.5);_
  

  
_&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;//Draw the background   
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_VETEX);  
&nbsp;  
&nbsp;glEnableVertexAttribArray(NORMAL\_ARRAY);  
&nbsp;glVertexAttribPointer(NORMAL\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_NORMAL);_
  

_&nbsp;glEnableVertexAttribArray(TEXCOORD\_ARRAY);&nbsp;  
&nbsp;glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_TEXTCOORD);_
  

_&nbsp;glEnableVertexAttribArray(COLOR\_ARRAY);&nbsp;  
&nbsp;glVertexAttribPointer(COLOR\_ARRAY, 4, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_COLOR);_
  

_&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
&nbsp;// Draws a non-indexed triangle array  
&nbsp;glDrawArrays(GL\_TRIANGLES, 0,6);_
  

  
_&nbsp;glUseProgram(m\_uiProgramObject);  
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;//Draw the foreground   
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;glViewport(0, 0, 800, 600);  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myPMVMatrix");  
&nbsp;glUniformMatrix4fv( i32Location, 1, GL\_FALSE, aPMVMatrix0);_
  

_&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myModelViewIT");  
&nbsp;glUniformMatrix3fv( i32Location, 1, GL\_FALSE, aModelViewIT0);_
  

_&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myTMatrix");  
&nbsp;glUniform4fv( i32Location,1,aTMatrix0);_
  

_&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myScale");  
&nbsp;glUniform1f( i32Location,aScale0);_
  

_&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myYScale");  
&nbsp;glUniform1f( i32Location,aYScale0);  
&nbsp;  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myLightDirection");  
&nbsp;glUniform3f( i32Location, 0, 0, 1.5);_
  

_&nbsp;glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_VETEX);  
&nbsp;  
&nbsp;glEnableVertexAttribArray(NORMAL\_ARRAY);  
&nbsp;glVertexAttribPointer(NORMAL\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_NORMAL);_
  

_&nbsp;glEnableVertexAttribArray(TEXCOORD\_ARRAY);&nbsp;&nbsp;  
&nbsp;glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_TEXTCOORD);&nbsp;_
  

_&nbsp;glEnableVertexAttribArray(COLOR\_ARRAY);&nbsp;  
&nbsp;glVertexAttribPointer(COLOR\_ARRAY, 4, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_COLOR);_
  

_&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);&nbsp;  
&nbsp;// Draws a non-indexed triangle array  
&nbsp;glDrawArrays(GL\_TRIANGLES, 0,6);_
  

  
_&nbsp;return true;_
  

_}_
  

_/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;NewDemo  
&nbsp;@Return&nbsp;&nbsp;PVRShell\*&nbsp;&nbsp;The demo supplied by the user  
&nbsp;@Description&nbsp;This function must be implemented by the user of the shell.  
&nbsp;&nbsp;&nbsp;&nbsp;The user should return its PVRShell object defining the  
&nbsp;&nbsp;&nbsp;&nbsp;behaviour of the application.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
PVRShell\* NewDemo()  
{  
&nbsp;return new OGLESBasicTnL();  
}_
  

_/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;End of file (OGLESBasicTnL.cpp)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/_

---

<div class="post-metadata">

**Author:** ![tobias](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@tobias](https://forums.imgtec.com/u/tobias)\
**Post date:** [October 27, 2010, 1:02pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/3 "2010-10-27T13:02:50Z")

</div>

Hi renaissance,\<?: prefix = o ns = "urn:schemas-microsoft-com:office:office" /\>

  

The reason you are getting this problem seems to stem from your use of glActiveTexture. GL has up to 8 active texture units, GL\_TEXTURE0-7 which can be used for multitexturing.

  

You've assigned your background to active texture 0 and then the foreground to active texture 1. Calls to glActiveTexture() are used to bind a given texture to your specified texture unit (e.g. GL\_TEXTURE0), and this texture unit will remain active until you call it again with a different texture unit. So later in your render loop, when you call glBindTexture again to set the texture, it is binding them to GL\_TEXTURE1.

  

Although it is essentially undefined behaviour, it appears that GL\_TEXTURE0 is used by your sampler in the shader. So GL\_TEXTURE0 is never changing, whilst GL\_TEXTURE1 is changing but is never sampled, which causes you to see the same texture twice.

  

&nbsp;

  

To solve your issue, firstly, you should add **glUniform1i(glGetUniformLocation(m\_uiProgramObject, "sampler2d"), 0);** within InitView to explicitly state that you are sampling GL\_TEXTURE0 in your shader. The integer value you pass in to this function refers to the active texture you are using, so 0 means that the sampler will use GL\_TEXTURE0.

  

You also need to remove the following four lines from your RenderScene function

  

_glActiveTexture(GL\_TEXTURE0);  
glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
glActiveTexture(GL\_TEXTURE1);  
glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);_[/CODE]

But leave in your other glBindTexture calls as these will be needed to change textures.

For a good example of how to use multiple textures in a program I suggest you look at the Bumpmap training course in the SDK. The second texture is actually a normal map but the methods still apply. I'd also suggest taking a look at our performance recommendations on optimising your code (particularly for reducing the number of calls you make to GL), which you can find in the SDK package documentation folder.

Hope this helps :)

[CODE]_glActiveTexture(GL\_TEXTURE0);  
glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
glActiveTexture(GL\_TEXTURE1);  
glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);_[/CODE]  

But leave in your other glBindTexture calls as these will be needed to change textures.

  

For a good example of how to use multiple textures in a program I suggest you look at the Bumpmap training course in the SDK. The second texture is actually a normal map but the methods still apply. I'd also suggest taking a look at our performance recommendations on optimising your code (particularly for reducing the number of calls you make to GL), which you can find in the SDK package documentation folder.

  

Hope this helps :)

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [October 27, 2010, 5:24pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/4 "2010-10-27T17:24:05Z")

</div>

Thank you so much, Tobias.

As you suggested, I did the modification and the method works for the two texture code.

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 2, 2010, 7:24pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/5 "2010-11-02T19:24:45Z")

</div>

Here is a follow-up question.

&nbsp;
  

In my original code, you may see the two planes are with the same z offset. But the final rendering effect is related to the order which plane is rendered first.&nbsp; If I change the the following offset as
  

  

_//two triangles as popup button  
GLfloat FG\_TRIANGLE\_VETEX[18] ={  
0.55f, 0.22f, 1.0f,   
1.0f, 0.22f, 1.0f,   
1.0f, -1.0f, 1.0f,  
0.55f, 0.22f,&nbsp; 1.0f,   
1.0f, -1.0f, 1.0f,   
0.55f, -1.0f, 1.0f  
};_
  

&nbsp;
  

_=\>_
  

&nbsp;
  

  

_//two triangles as popup button  
GLfloat FG\_TRIANGLE\_VETEX[18] ={  
0.55f, 0.22f, -1.0f,   
1.0f, 0.22f, -1.0f,   
1.0f, -1.0f, -1.0f,  
0.55f, 0.22f,&nbsp; -1.0f,   
1.0f, -1.0f, -1.0f,   
0.55f, -1.0f, -1.0f  
};_
  

&nbsp;
  

The small plane is not blocked by the big one as I expected. However, if I choose to render this plane before the big one, we can see it is blocked. Looks to me the rendering result is only related to the order which plane is rendered first in this example. I am just wondering why the depth information is not taking effect in the example.
  

&nbsp;
  

Thank you very much,
  

&nbsp;
  

Renaissance

---

<div class="post-metadata">

**Author:** ![martin-kraus](https://avatars.discourse-cdn.com/v4/letter/m/85f322/32.png) [@martin-kraus](https://forums.imgtec.com/u/martin-kraus)\
**Post date:** [November 3, 2010, 7:10am UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/6 "2010-11-03T07:10:44Z")

</div>

You might have to enable the depth test with glEnable(GL\_DEPTH\_TEST);

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 3, 2010, 3:59pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/7 "2010-11-03T15:59:12Z")

</div>

Thank you, Martin.

&nbsp;
  

First of all, I tried what you suggested by enabling GL\_DEPTH\_TEST. However, I can only have on plane rendered.
  

&nbsp;
  

Do I also need to create a depthRenderbuffer object when enabling GL\_DEPTH\_TEST?&nbsp;&nbsp;I tried the following approach but it is still not working. I still can only get on plane in the output window...
  

&nbsp;
  

GLuint depthRenderbuffer
  

...
  

glGenRenderbuffers(1, &depthRenderbuffer);
  

....
  

glBindRenderbuffer(GL\_RENDERBUFFER, depthRenderbuffer);

---

<div class="post-metadata">

**Author:** ![martin-kraus](https://avatars.discourse-cdn.com/v4/letter/m/85f322/32.png) [@martin-kraus](https://forums.imgtec.com/u/martin-kraus)\
**Post date:** [November 3, 2010, 9:15pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/8 "2010-11-03T21:15:19Z")

</div>

No, I don’t think you need renderbuffers for depth tests. Make sure that the z coordinates returned by the vertex shader are in the visible range (between -w coordinate and +w coordinate). Your vertex shader is somewhat strange, in particular these lines:  
  
_&nbsp;&nbsp; gl\_Position.x = gl\_Position.xmyScale;  
&nbsp;&nbsp;&nbsp;gl\_Position.y = gl\_Position.ymyScalemyYScale;  
&nbsp;&nbsp;&nbsp;gl\_Position.z = gl\_Position.zmyScale;  
&nbsp;&nbsp;&nbsp;gl\_Position = gl\_Position + myTMatrix;_  
  
It is hard to understand what your are doing if you use this kind of nonstandard transformations. You should probably use the viewport transformation (glViewport) for whatever you are trying to achieve with these lines.

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 3, 2010, 9:22pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/9 "2010-11-03T21:22:38Z")

</div>

Hi Martin:

Thank you again for your response.
  

&nbsp;
  

The Z coordinate range I am using is -1.0 to 1.0 for x, y, z. For the shader, since my output screen is 800 by 600 and it is not square, I have to squeeze my target a littlle bit. But for the two planes, you can see these scaling factors are all 1.0. In other word, it will not affact the rendering of the two planes.&nbsp; If you run my very original code, you will see the shader works fine.
  

&nbsp;
  

As to my question in the previous post, the z location for the two planes are 1.0 and -1.0 and they are in the valid range.
  

&nbsp;
  

Thanks,
  

&nbsp;
  

Renaissance

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 15, 2010, 4:24pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/10 "2010-11-15T16:24:23Z")

</div>

Can anyone give me some help on this question?

&nbsp;
  

Thank you,
  

&nbsp;
  

Renaissance

---

<div class="post-metadata">

**Author:** ![martin-kraus](https://avatars.discourse-cdn.com/v4/letter/m/85f322/32.png) [@martin-kraus](https://forums.imgtec.com/u/martin-kraus)\
**Post date:** [November 15, 2010, 6:27pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/11 "2010-11-15T18:27:15Z")

</div>

Could you post your current code again?

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 17, 2010, 6:30pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/12 "2010-11-17T18:30:59Z")

</div>

Thank you, Martin

&nbsp;
  

  
#include \<math.h\>  
#include \<stdio.h\>
  

#include \<EGL/egl.h\>  
#include \<GLES2/gl2.h\>  
#include "OGLES2Tools.h"&nbsp;   
#include "PVRShell.h"
  

// Index to bind the attributes to vertex shaders  
#define VERTEX\_ARRAY&nbsp;0  
#define TEXCOORD\_ARRAY&nbsp;1  
#define NORMAL\_ARRAY&nbsp;2  
#define COLOR\_ARRAY&nbsp;&nbsp;3
  

const char c\_sz\_BK\_TextureFile[]&nbsp;&nbsp;= "BG-m.pvr";  
const char c\_sz\_FG\_TextureFile[]&nbsp;&nbsp;= "FG-m.pvr";
  

  
//two triangles  
GLfloat BK\_TRIANGLE\_VETEX[18] ={  
-1.0f, 1.0f, 1.0f,   
1.0f, 1.0f, 1.0f,   
1.0f, -1.0f, 1.0f,  
-1.0f, 1.0f, 1.0f,   
1.0f, -1.0f, 1.0f,   
-1.0f, -1.0f, 1.0f  
};
  

//normal for each vertex of the two triangles   
GLfloat BK\_TRIANGLE\_NORMAL[18] = {  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f};
  

GLfloat BK\_TRIANGLE\_COLOR[24] = {  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f};
  

GLfloat BK\_TRIANGLE\_TEXTCOORD[12] = {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp; // UVs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,1.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,0.0f};
  

&nbsp;
  

//two triangles as popup button  
GLfloat FG\_TRIANGLE\_VETEX[18] ={  
0.55f, 0.22f, -1.0f,   
1.0f, 0.22f, -1.0f,   
1.0f, -1.0f, -1.0f,  
0.55f, 0.22f,&nbsp; -1.0f,   
1.0f, -1.0f, -1.0f,   
0.55f, -1.0f, -1.0f  
};
  

//normal for each vertex of the two triangles as popup button  
GLfloat FG\_TRIANGLE\_NORMAL[18] = {  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f,  
&nbsp;0.0f,0.0f,1.0f};
  

GLfloat FG\_TRIANGLE\_COLOR[24] = {  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f,  
&nbsp;1.0f,1.0f,1.0f,1.0f};
  

GLfloat FG\_TRIANGLE\_TEXTCOORD[12] = {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp; // UVs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,1.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f,0.0f ,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,0.0f};
  

  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;Class implementing the PVRShell functions.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
class OGLESBasicTnL : public PVRShell  
{  
&nbsp;// The vertex and fragment shader OpenGL handles  
&nbsp;GLuint m\_uiVertexShader, m\_uiFragShader;
  

&nbsp;// The program object containing the 2 shader objects  
&nbsp;GLuint m\_uiProgramObject;
  

&nbsp;// Texture handle  
&nbsp;GLuint&nbsp;m\_uiBKTex;  
&nbsp;GLuint&nbsp;m\_uiFGTex;  
&nbsp;GLuint depthRenderbuffer;
  

public:  
&nbsp;virtual bool InitApplication();  
&nbsp;virtual bool InitView();  
&nbsp;virtual bool ReleaseView();  
&nbsp;virtual bool QuitApplication();  
&nbsp;virtual bool RenderScene();  
};
  

  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;InitApplication  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in InitApplication() will be called by PVRShell once per  
&nbsp;&nbsp;&nbsp;&nbsp;run, before the rendering context is created.  
&nbsp;&nbsp;&nbsp;&nbsp;Used to initialize variables that are not dependant on it  
&nbsp;&nbsp;&nbsp;&nbsp;(e.g. external modules, loading meshes, etc.)  
&nbsp;&nbsp;&nbsp;&nbsp;If the rendering context is lost, InitApplication() will  
&nbsp;&nbsp;&nbsp;&nbsp;not be called again.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::InitApplication()  
{  
&nbsp;&nbsp;&nbsp; bool m\_bUseVertexProgram = true;
  

&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;QuitApplication  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in QuitApplication() will be called by PVRShell once per  
&nbsp;&nbsp;&nbsp;&nbsp;run, just before exiting the program.  
&nbsp;&nbsp;&nbsp;&nbsp;If the rendering context is lost, QuitApplication() will  
&nbsp;&nbsp;&nbsp;&nbsp;not be called.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::QuitApplication()  
{  
&nbsp;&nbsp;&nbsp; return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;InitView  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in InitView() will be called by PVRShell upon  
&nbsp;&nbsp;&nbsp;&nbsp;initialization or after a change in the rendering context.  
&nbsp;&nbsp;&nbsp;&nbsp;Used to initialize variables that are dependant on the rendering  
&nbsp;&nbsp;&nbsp;&nbsp;context (e.g. textures, vertex buffers, etc.)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::InitView()  
{  
&nbsp;// Fragment and vertex shaders code
  

&nbsp;char\* pszFragShader = "  
&nbsp;&nbsp;uniform sampler2D sampler2d;  
&nbsp;&nbsp;varying mediump float&nbsp;varDot;  
&nbsp;&nbsp;varying mediump vec2&nbsp;varCoord;  
&nbsp;&nbsp;varying mediump vec4 v\_primaryColor;  
&nbsp;&nbsp;void main (void)  
&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;gl\_FragColor = texture2D(sampler2d,varCoord) \* varDot\*v\_primaryColor;  
&nbsp;&nbsp;}";  
&nbsp;char\* pszVertShader = "  
&nbsp;&nbsp;attribute highp vec4&nbsp;myVertex;  
&nbsp;&nbsp;attribute mediump vec3&nbsp;myNormal;  
&nbsp;&nbsp;attribute mediump vec4&nbsp;myUV;  
&nbsp;&nbsp;attribute mediump vec4&nbsp; myColor;  
&nbsp;&nbsp;uniform mediump mat4&nbsp;myPMVMatrix;  
&nbsp;&nbsp;uniform mediump vec4&nbsp;myTMatrix;  
&nbsp;&nbsp;uniform mediump float&nbsp;myScale;  
&nbsp;&nbsp;uniform mediump float&nbsp;myYScale;  
&nbsp;&nbsp;uniform mediump mat3&nbsp;myModelViewIT;  
&nbsp;&nbsp;uniform mediump vec3&nbsp;myLightDirection;  
&nbsp;&nbsp;varying mediump float&nbsp;varDot;  
&nbsp;&nbsp;varying mediump vec2&nbsp;varCoord;  
&nbsp;&nbsp;varying mediump vec4&nbsp;v\_primaryColor;  
&nbsp;&nbsp;void main(void)  
&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;v\_primaryColor = myColor;  
&nbsp;&nbsp;&nbsp;gl\_Position = (myPMVMatrix \* myVertex);  
&nbsp;&nbsp;&nbsp;gl\_Position.x = gl\_Position.x\*myScale;  
&nbsp;&nbsp;&nbsp;gl\_Position.y = gl\_Position.y\*myScale\*myYScale;  
&nbsp;&nbsp;&nbsp;gl\_Position.z = gl\_Position.z\*myScale;  
&nbsp;&nbsp;&nbsp;gl\_Position = gl\_Position + myTMatrix;  
&nbsp;&nbsp;&nbsp;varCoord = myUV.st;  
&nbsp;&nbsp;&nbsp;mediump vec3 transNormal = myModelViewIT \* myNormal;  
&nbsp;&nbsp;&nbsp;varDot = max( dot(transNormal, myLightDirection), 0.0 );  
&nbsp;&nbsp;}";
  

  
&nbsp;// Create the fragment shader object  
&nbsp;m\_uiFragShader = glCreateShader(GL\_FRAGMENT\_SHADER);
  

&nbsp;// Load the source code into it  
&nbsp;glShaderSource(m\_uiFragShader, 1, (const char\*\*)&pszFragShader, NULL);
  

&nbsp;// Compile the source code  
&nbsp;glCompileShader(m\_uiFragShader);
  

&nbsp;// Check if compilation succeeded  
&nbsp;GLint bShaderCompiled;  
&nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiFragShader, GL\_COMPILE\_STATUS, &bShaderCompiled);  
&nbsp;if (!bShaderCompiled)  
&nbsp;{  
&nbsp;&nbsp;// An error happened, first retrieve the length of the log message  
&nbsp;&nbsp;int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;glGetShaderiv(m\_uiFragShader, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);
  

&nbsp;&nbsp;// Allocate enough space for the message and retrieve it  
&nbsp;&nbsp;char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glGetShaderInfoLog(m\_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Displays the message in a dialog box when the application quits  
&nbsp;&nbsp;&nbsp;using the shell PVRShellSet function with first parameter prefExitMessage.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;sprintf(pszMsg, "Failed to compile fragment shader: %s", pszInfoLog);  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;delete [] pszMsg;  
&nbsp;&nbsp;delete [] pszInfoLog;  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;// Loads the vertex shader in the same way  
&nbsp;m\_uiVertexShader = glCreateShader(GL\_VERTEX\_SHADER);  
&nbsp;glShaderSource(m\_uiVertexShader, 1, (const char\*\*)&pszVertShader, NULL);  
&nbsp;glCompileShader(m\_uiVertexShader);  
&nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiVertexShader, GL\_COMPILE\_STATUS, &bShaderCompiled);  
&nbsp;if (!bShaderCompiled)  
&nbsp;{  
&nbsp;&nbsp;int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;glGetShaderiv(m\_uiVertexShader, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glGetShaderInfoLog(m\_uiVertexShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;sprintf(pszMsg, "Failed to compile vertex shader: %s", pszInfoLog);  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;delete [] pszMsg;  
&nbsp;&nbsp;delete [] pszInfoLog;  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;// Create the shader program  
&nbsp;&nbsp;&nbsp; m\_uiProgramObject = glCreateProgram();
  

&nbsp;// Attach the fragment and vertex shaders to it  
&nbsp;&nbsp;&nbsp; glAttachShader(m\_uiProgramObject, m\_uiFragShader);  
&nbsp;&nbsp;&nbsp; glAttachShader(m\_uiProgramObject, m\_uiVertexShader);
  

&nbsp;// Bind the custom vertex attribute "myVertex" to location VERTEX\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, VERTEX\_ARRAY, "myVertex");  
&nbsp;// Bind the custom vertex attribute "myUV" to location TEXCOORD\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, TEXCOORD\_ARRAY, "myUV");  
&nbsp;// Bind the custom vertex attribute "myNormal" to location NORMAL\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, NORMAL\_ARRAY, "myNormal");  
&nbsp;// Bind the custom vertex attribute "myColor" to location COLOR\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, COLOR\_ARRAY, "myColor");  
&nbsp;// Link the program  
&nbsp;&nbsp;&nbsp; glLinkProgram(m\_uiProgramObject);
  

&nbsp;// Check if linking succeeded in the same way we checked for compilation success  
&nbsp;&nbsp;&nbsp; GLint bLinked;  
&nbsp;&nbsp;&nbsp; glGetProgramiv(m\_uiProgramObject, GL\_LINK\_STATUS, &bLinked);  
&nbsp;if (!bLinked)  
&nbsp;{  
&nbsp;&nbsp;int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;glGetProgramiv(m\_uiProgramObject, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;glGetProgramInfoLog(m\_uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;sprintf(pszMsg, "Failed to link program: %s", pszInfoLog);  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;delete [] pszMsg;  
&nbsp;&nbsp;delete [] pszInfoLog;  
&nbsp;&nbsp;return false;  
&nbsp;}  
&nbsp;  
&nbsp;if(PVRTTextureLoadFromPVR(c\_sz\_BK\_TextureFile, &m\_uiBKTex) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;//glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;//glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );
  

&nbsp;if(PVRTTextureLoadFromPVR(c\_sz\_FG\_TextureFile, &m\_uiFGTex) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;//glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;//glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );
  

&nbsp;//glUniform1i(glGetUniformLocation(m\_uiProgramObject, "sampler2d"), 0); 
  

  
&nbsp;//glGenRenderbuffers(1, &depthRenderbuffer);
  

&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;ReleaseView  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in ReleaseView() will be called by PVRShell when the  
&nbsp;&nbsp;&nbsp;&nbsp;application quits or before a change in the rendering context.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::ReleaseView()  
{  
&nbsp;// Frees the texture  
&nbsp;glDeleteTextures(1, &m\_uiBKTex);  
&nbsp;glDeleteTextures(1, &m\_uiFGTex);
  

&nbsp;// Frees the OpenGL handles for the program and the 2 shaders  
&nbsp;glDeleteProgram(m\_uiProgramObject);  
&nbsp;glDeleteShader(m\_uiVertexShader);  
&nbsp;glDeleteShader(m\_uiFragShader);
  

  
&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;RenderScene  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Main rendering loop function of the program. The shell will  
&nbsp;&nbsp;&nbsp;&nbsp;call this function every frame.  
&nbsp;&nbsp;&nbsp;&nbsp;eglSwapBuffers() will be performed by PVRShell automatically.  
&nbsp;&nbsp;&nbsp;&nbsp;PVRShell will also manage important OS events.  
&nbsp;&nbsp;&nbsp;&nbsp;Will also manage relevent OS events. The user has access to  
&nbsp;&nbsp;&nbsp;&nbsp;these events through an abstraction layer provided by PVRShell.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::RenderScene()  
{  
&nbsp;glViewport(0, 0, 800, 600);  
&nbsp;glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  

&nbsp;glUseProgram(m\_uiProgramObject);
  

&nbsp;glEnable(GL\_CULL\_FACE);  
&nbsp;glCullFace(GL\_FRONT);
  

&nbsp;//glEnable(GL\_DEPTH\_TEST);&nbsp;
  

  
&nbsp;// Clears the color and depth buffer  
&nbsp;glClear(GL\_COLOR\_BUFFER\_BIT | GL\_DEPTH\_BUFFER\_BIT);
  

&nbsp;glEnable(GL\_TEXTURE\_2D);
  

  
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;//Draw the background  
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
  

&nbsp;float alpha = 0;&nbsp;&nbsp;//-p  
&nbsp;float beta =&nbsp; 0;&nbsp; //-q  
&nbsp;float theta = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // o
  

  
&nbsp;float aModelViewIT0[] =  
&nbsp;{  
&nbsp;&nbsp;cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta),  
&nbsp;&nbsp;cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),  
&nbsp;&nbsp;-sin(theta),&nbsp;&nbsp;&nbsp;sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta)  
&nbsp;};
  

  
&nbsp;/\*  
&nbsp;&nbsp;Bind the projection model view matrix (PMVMatrix) to the  
&nbsp;&nbsp;corresponding uniform variable in the shader.  
&nbsp;&nbsp;This matrix is used in the vertex shader to transform the vertices.  
&nbsp;\*/  
&nbsp;float aPMVMatrix0[] =  
&nbsp;{  
&nbsp;&nbsp;cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta), 0,  
&nbsp;&nbsp;cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),0,  
&nbsp;&nbsp;-sin(theta),&nbsp;&nbsp;&nbsp;sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta),0,  
&nbsp;&nbsp;0,0,0,1  
&nbsp;};
  

  
&nbsp;int i32Location = glGetUniformLocation(m\_uiProgramObject, "myPMVMatrix");  
&nbsp;glUniformMatrix4fv( i32Location, 1, GL\_FALSE, aPMVMatrix0);
  

&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myModelViewIT");  
&nbsp;glUniformMatrix3fv( i32Location, 1, GL\_FALSE, aModelViewIT0);
  

&nbsp;float aTMatrix0[] = {0.0f,0.0f,0.0f,0.0f};  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myTMatrix");  
&nbsp;glUniform4fv( i32Location,1,aTMatrix0);
  

&nbsp;float aScale0 = 1.0;  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myScale");  
&nbsp;glUniform1f( i32Location,aScale0);
  

&nbsp;float aYScale0 = 1.0;  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myYScale");  
&nbsp;glUniform1f( i32Location,aYScale0);
  

&nbsp;// Bind the Light Direction vector to the shader  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myLightDirection");&nbsp;  
&nbsp;glUniform3f( i32Location, 0, 0, 1.5);
  

  
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;//Draw the background   
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_VETEX);  
&nbsp;  
&nbsp;glEnableVertexAttribArray(NORMAL\_ARRAY);  
&nbsp;glVertexAttribPointer(NORMAL\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_NORMAL);
  

&nbsp;glEnableVertexAttribArray(TEXCOORD\_ARRAY);&nbsp;  
&nbsp;glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_TEXTCOORD);
  

&nbsp;glEnableVertexAttribArray(COLOR\_ARRAY);&nbsp;  
&nbsp;glVertexAttribPointer(COLOR\_ARRAY, 4, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_COLOR);
  

  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
&nbsp;glBindRenderbuffer(GL\_RENDERBUFFER, depthRenderbuffer);
  

&nbsp;// Draws a non-indexed triangle array  
&nbsp;glDrawArrays(GL\_TRIANGLES, 0,6);
  

&nbsp;
  

  
&nbsp;glUseProgram(m\_uiProgramObject);  
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;//Draw the foreground   
&nbsp;//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;glViewport(0, 0, 800, 600);
  

  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myPMVMatrix");  
&nbsp;glUniformMatrix4fv( i32Location, 1, GL\_FALSE, aPMVMatrix0);
  

&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myModelViewIT");  
&nbsp;glUniformMatrix3fv( i32Location, 1, GL\_FALSE, aModelViewIT0);
  

&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myTMatrix");  
&nbsp;glUniform4fv( i32Location,1,aTMatrix0);
  

&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myScale");  
&nbsp;glUniform1f( i32Location,aScale0);
  

&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myYScale");  
&nbsp;glUniform1f( i32Location,aYScale0);  
&nbsp;  
&nbsp;i32Location = glGetUniformLocation(m\_uiProgramObject, "myLightDirection");  
&nbsp;glUniform3f( i32Location, 0, 0, 1.5);
  

&nbsp;glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_VETEX);
  

&nbsp;glEnableVertexAttribArray(NORMAL\_ARRAY);  
&nbsp;glVertexAttribPointer(NORMAL\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_NORMAL);
  

&nbsp;glEnableVertexAttribArray(TEXCOORD\_ARRAY);&nbsp;&nbsp;  
&nbsp;glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_TEXTCOORD);&nbsp;
  

&nbsp;glEnableVertexAttribArray(COLOR\_ARRAY);&nbsp;  
&nbsp;glVertexAttribPointer(COLOR\_ARRAY, 4, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_COLOR);
  

glBindRenderbuffer(GL\_RENDERBUFFER, depthRenderbuffer);  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);&nbsp;  
&nbsp;// Draws a non-indexed triangle array  
&nbsp;glDrawArrays(GL\_TRIANGLES, 0,6);
  

&nbsp;
  

  
&nbsp;return true;
  

}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;NewDemo  
&nbsp;@Return&nbsp;&nbsp;PVRShell\*&nbsp;&nbsp;The demo supplied by the user  
&nbsp;@Description&nbsp;This function must be implemented by the user of the shell.  
&nbsp;&nbsp;&nbsp;&nbsp;The user should return its PVRShell object defining the  
&nbsp;&nbsp;&nbsp;&nbsp;behaviour of the application.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
PVRShell\* NewDemo()  
{  
&nbsp;return new OGLESBasicTnL();  
}
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;End of file (OGLESBasicTnL.cpp)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

---

<div class="post-metadata">

**Author:** ![GordonMaclachlan](https://avatars.discourse-cdn.com/v4/letter/g/c68b51/32.png) [@GordonMaclachlan](https://forums.imgtec.com/u/GordonMaclachlan)\
**Post date:** [November 18, 2010, 6:04pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/13 "2010-11-18T18:04:25Z")

</div>

Some notes:  
  
- I suspect your projection matrix is not helping as drawing outside a very small z range results in nothing appearing on the screen.  
- You really don't need a renderbuffer for this stuff at all  
  
I've taken the liberty of editing your code. I would suggest comparing what's below with what you hav in an automated diff, if you have one.  
  
I stripped out a lot of redundant calls and manipulated the vertex positions a bit. Also, I have added a little interactivity - on windows, press 1 to enable and disable the depth test; press 2 to reverse the render order of the quads. The keys will be different on other platforms - they are the standard PVRShell Action1 and Action2 keys. Switching the render order should make no difference to the output until the depth test is disabled.  
  
I hope this helps - if you have further questions please post.  
  

Code:

  
#include \<math.h\>  
#include \<stdio.h\>  
#include \<EGL/egl.h\>  
#include \<GLES2/gl2.h\>  
#include "OGLES2Tools.h"   
#include "PVRShell.h"  
// Index to bind the attributes to vertex shaders  
#define VERTEX\_ARRAY 0  
#define TEXCOORD\_ARRAY 1  
#define NORMAL\_ARRAY 2  
#define COLOR\_ARRAY&nbsp; 3  
const char c\_sz\_BK\_TextureFile[]&nbsp; = "BG-m.pvr";  
const char c\_sz\_FG\_TextureFile[]&nbsp; = "FG-m.pvr";  
  
//two triangles  
GLfloat BK\_TRIANGLE\_VETEX[18] ={  
&nbsp;&nbsp;&nbsp; -1.0f, 1.0f, 0.6f,  
&nbsp;&nbsp;&nbsp; 1.0f, 1.0f, 0.6f,  
&nbsp;&nbsp;&nbsp; 1.0f, -1.0f, 0.6f,  
&nbsp;&nbsp;&nbsp; -1.0f, 1.0f, 0.6f,  
&nbsp;&nbsp;&nbsp; 1.0f, -1.0f, 0.6f,  
&nbsp;&nbsp;&nbsp; -1.0f, -1.0f, 0.6f  
};  
//normal for each vertex of the two triangles  
GLfloat BK\_TRIANGLE\_NORMAL[18] = {  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f  
};  
GLfloat BK\_TRIANGLE\_COLOR[24] = {  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f  
};  
GLfloat BK\_TRIANGLE\_TEXTCOORD[12] = {  
&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp; // UVs  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f ,  
&nbsp;&nbsp;&nbsp; 1.0f,0.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;   
&nbsp;&nbsp;&nbsp; 1.0f,0.0f ,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f  
};  
  
GLfloat FG\_TRIANGLE\_VETEX[18] ={  
&nbsp;&nbsp;&nbsp; -1.0f, 0.5f, 0.5f,  
&nbsp;&nbsp;&nbsp; 0.5f, 0.5f, 0.5f,  
&nbsp;&nbsp;&nbsp; 0.5f, -1.0f, 0.5f,  
&nbsp;&nbsp;&nbsp; -1.0f, 0.5f, 0.5f,  
&nbsp;&nbsp;&nbsp; 0.5f, -1.0f, 0.5f,  
&nbsp;&nbsp;&nbsp; -1.0f, -1.0f, 0.5f  
};  
  
//normal for each vertex of the two triangles as popup button  
GLfloat FG\_TRIANGLE\_NORMAL[18] = {  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f,1.0f  
};  
GLfloat FG\_TRIANGLE\_COLOR[24] = {  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f,  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f,1.0f,1.0f  
};  
GLfloat FG\_TRIANGLE\_TEXTCOORD[12] = {  
&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;&nbsp; // UVs  
&nbsp;&nbsp;&nbsp; 1.0f,1.0f ,  
&nbsp;&nbsp;&nbsp; 1.0f,0.0f,  
&nbsp;&nbsp;&nbsp; 0.0f,1.0f ,&nbsp;   
&nbsp;&nbsp;&nbsp; 1.0f,0.0f ,  
&nbsp;&nbsp;&nbsp; 0.0f,0.0f  
};  
  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
Class implementing the PVRShell functions.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
class OGLESBasicTnL : public PVRShell  
{  
&nbsp;&nbsp;&nbsp; // The vertex and fragment shader OpenGL handles  
&nbsp;&nbsp;&nbsp; GLuint m\_uiVertexShader, m\_uiFragShader;  
&nbsp;&nbsp;&nbsp; // The program object containing the 2 shader objects  
&nbsp;&nbsp;&nbsp; GLuint m\_uiProgramObject;  
&nbsp;&nbsp;&nbsp; // Texture handle  
&nbsp;&nbsp;&nbsp; GLuint m\_uiBKTex;  
&nbsp;&nbsp;&nbsp; GLuint m\_uiFGTex;  
  
&nbsp;&nbsp;&nbsp; bool m\_bDepthTest, m\_bRenderOrder;  
public:  
&nbsp;&nbsp;&nbsp; virtual bool InitApplication();  
&nbsp;&nbsp;&nbsp; virtual bool InitView();  
&nbsp;&nbsp;&nbsp; virtual bool ReleaseView();  
&nbsp;&nbsp;&nbsp; virtual bool QuitApplication();  
&nbsp;&nbsp;&nbsp; virtual bool RenderScene();  
};  
  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
@Function&nbsp; InitApplication  
@Return&nbsp; bool&nbsp; true if no error occured  
@Description Code in InitApplication() will be called by PVRShell once per  
run, before the rendering context is created.  
Used to initialize variables that are not dependant on it  
(e.g. external modules, loading meshes, etc.)  
If the rendering context is lost, InitApplication() will  
not be called again.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::InitApplication()  
{  
&nbsp;&nbsp;&nbsp; PVRShellSet(prefWidth,800);  
&nbsp;&nbsp;&nbsp; PVRShellSet(prefHeight,600);  
  
&nbsp;&nbsp;&nbsp; m\_bDepthTest = m\_bRenderOrder = true;  
&nbsp;&nbsp;&nbsp; return true;  
}  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
@Function&nbsp; QuitApplication  
@Return&nbsp; bool&nbsp; true if no error occured  
@Description Code in QuitApplication() will be called by PVRShell once per  
run, just before exiting the program.  
If the rendering context is lost, QuitApplication() will  
not be called.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::QuitApplication()  
{  
&nbsp;&nbsp;&nbsp; return true;  
}  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
@Function&nbsp; InitView  
@Return&nbsp; bool&nbsp; 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 OGLESBasicTnL::InitView()  
{  
&nbsp;&nbsp;&nbsp; // Fragment and vertex shaders code  
&nbsp;&nbsp;&nbsp; char\* pszFragShader = "  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform sampler2D sampler2d;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varying mediump float varDot;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varying mediump vec2 varCoord;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varying mediump vec4 v\_primaryColor;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; void main (void)  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; gl\_FragColor = texture2D(sampler2d,varCoord) \* varDot\*v\_primaryColor;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }";  
&nbsp;&nbsp;&nbsp; char\* pszVertShader = "  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; attribute highp vec4 myVertex;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; attribute mediump vec3 myNormal;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; attribute mediump vec4 myUV;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; attribute mediump vec4&nbsp; myColor;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform mediump mat4 myPMVMatrix;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform mediump vec4 myTMatrix;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform mediump float myScale;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform mediump float myYScale;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform mediump mat3 myModelViewIT;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; uniform mediump vec3 myLightDirection;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varying mediump float varDot;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varying mediump vec2 varCoord;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varying mediump vec4 v\_primaryColor;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; void main(void)  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; v\_primaryColor = myColor;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; gl\_Position = (myPMVMatrix \* myVertex);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; gl\_Position.x = gl\_Position.x\*myScale;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; gl\_Position.y = gl\_Position.y\*myScale\*myYScale;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; gl\_Position.z = gl\_Position.z\*myScale;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; gl\_Position = gl\_Position + myTMatrix;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varCoord = myUV.st;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; mediump vec3 transNormal = myModelViewIT \* myNormal;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; varDot = max( dot(transNormal, myLightDirection), 0.0 );  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }";  
  
&nbsp;&nbsp;&nbsp; // Create the fragment shader object  
&nbsp;&nbsp;&nbsp; m\_uiFragShader = glCreateShader(GL\_FRAGMENT\_SHADER);  
&nbsp;&nbsp;&nbsp; // Load the source code into it  
&nbsp;&nbsp;&nbsp; glShaderSource(m\_uiFragShader, 1, (const char\*\*)&pszFragShader, NULL);  
&nbsp;&nbsp;&nbsp; // Compile the source code  
&nbsp;&nbsp;&nbsp; glCompileShader(m\_uiFragShader);  
&nbsp;&nbsp;&nbsp; // Check if compilation succeeded  
&nbsp;&nbsp;&nbsp; GLint bShaderCompiled;  
&nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiFragShader, GL\_COMPILE\_STATUS, &bShaderCompiled);  
&nbsp;&nbsp;&nbsp; if (!bShaderCompiled)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // An error happened, first retrieve the length of the log message  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiFragShader, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Allocate enough space for the message and retrieve it  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glGetShaderInfoLog(m\_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Displays the message in a dialog box when the application quits  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; using the shell PVRShellSet function with first parameter prefExitMessage.  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; \*/  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sprintf(pszMsg, "Failed to compile fragment shader: %s", pszInfoLog);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete [] pszMsg;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete [] pszInfoLog;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;  
&nbsp;&nbsp;&nbsp; }  
&nbsp;&nbsp;&nbsp; // Loads the vertex shader in the same way  
&nbsp;&nbsp;&nbsp; m\_uiVertexShader = glCreateShader(GL\_VERTEX\_SHADER);  
&nbsp;&nbsp;&nbsp; glShaderSource(m\_uiVertexShader, 1, (const char\*\*)&pszVertShader, NULL);  
&nbsp;&nbsp;&nbsp; glCompileShader(m\_uiVertexShader);  
&nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiVertexShader, GL\_COMPILE\_STATUS, &bShaderCompiled);  
&nbsp;&nbsp;&nbsp; if (!bShaderCompiled)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glGetShaderiv(m\_uiVertexShader, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glGetShaderInfoLog(m\_uiVertexShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sprintf(pszMsg, "Failed to compile vertex shader: %s", pszInfoLog);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete [] pszMsg;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete [] pszInfoLog;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;  
&nbsp;&nbsp;&nbsp; }  
&nbsp;&nbsp;&nbsp; // Create the shader program  
&nbsp;&nbsp;&nbsp; m\_uiProgramObject = glCreateProgram();  
&nbsp;&nbsp;&nbsp; // Attach the fragment and vertex shaders to it  
&nbsp;&nbsp;&nbsp; glAttachShader(m\_uiProgramObject, m\_uiFragShader);  
&nbsp;&nbsp;&nbsp; glAttachShader(m\_uiProgramObject, m\_uiVertexShader);  
&nbsp;&nbsp;&nbsp; // Bind the custom vertex attribute "myVertex" to location VERTEX\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, VERTEX\_ARRAY, "myVertex");  
&nbsp;&nbsp;&nbsp; // Bind the custom vertex attribute "myUV" to location TEXCOORD\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, TEXCOORD\_ARRAY, "myUV");  
&nbsp;&nbsp;&nbsp; // Bind the custom vertex attribute "myNormal" to location NORMAL\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, NORMAL\_ARRAY, "myNormal");  
&nbsp;&nbsp;&nbsp; // Bind the custom vertex attribute "myColor" to location COLOR\_ARRAY  
&nbsp;&nbsp;&nbsp; glBindAttribLocation(m\_uiProgramObject, COLOR\_ARRAY, "myColor");  
&nbsp;&nbsp;&nbsp; // Link the program  
&nbsp;&nbsp;&nbsp; glLinkProgram(m\_uiProgramObject);  
&nbsp;&nbsp;&nbsp; // Check if linking succeeded in the same way we checked for compilation success  
&nbsp;&nbsp;&nbsp; GLint bLinked;  
&nbsp;&nbsp;&nbsp; glGetProgramiv(m\_uiProgramObject, GL\_LINK\_STATUS, &bLinked);  
&nbsp;&nbsp;&nbsp; if (!bLinked)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i32InfoLogLength, i32CharsWritten;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glGetProgramiv(m\_uiProgramObject, GL\_INFO\_LOG\_LENGTH, &i32InfoLogLength);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char\* pszInfoLog = new char[i32InfoLogLength];  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glGetProgramInfoLog(m\_uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char\* pszMsg = new char[i32InfoLogLength+256];  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sprintf(pszMsg, "Failed to link program: %s", pszInfoLog);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PVRShellSet(prefExitMessage, pszMsg);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete [] pszMsg;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete [] pszInfoLog;  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;  
&nbsp;&nbsp;&nbsp; }  
  
&nbsp;&nbsp;&nbsp; if(PVRTTextureLoadFromPVR(c\_sz\_BK\_TextureFile, &m\_uiBKTex) != PVR\_SUCCESS)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;  
&nbsp;&nbsp;&nbsp; }  
&nbsp;&nbsp;&nbsp; //glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;&nbsp;&nbsp; //glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );  
&nbsp;&nbsp;&nbsp; if(PVRTTextureLoadFromPVR(c\_sz\_FG\_TextureFile, &m\_uiFGTex) != PVR\_SUCCESS)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;  
&nbsp;&nbsp;&nbsp; }  
&nbsp;&nbsp;&nbsp; //glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_NEAREST );  
&nbsp;&nbsp;&nbsp; //glTexParameteri(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_NEAREST );  
&nbsp;&nbsp;&nbsp; //glUniform1i(glGetUniformLocation(m\_uiProgramObject, "sampler2d"), 0);  
  
&nbsp;&nbsp;&nbsp; //glGenRenderbuffers(1, &depthRenderbuffer);  
&nbsp;&nbsp;&nbsp; return true;  
}  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
@Function&nbsp; ReleaseView  
@Return&nbsp; bool&nbsp; true if no error occured  
@Description Code in ReleaseView() will be called by PVRShell when the  
application quits or before a change in the rendering context.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLESBasicTnL::ReleaseView()  
{  
&nbsp;&nbsp;&nbsp; // Frees the texture  
&nbsp;&nbsp;&nbsp; glDeleteTextures(1, &m\_uiBKTex);  
&nbsp;&nbsp;&nbsp; glDeleteTextures(1, &m\_uiFGTex);  
&nbsp;&nbsp;&nbsp; // Frees the OpenGL handles for the program and the 2 shaders  
&nbsp;&nbsp;&nbsp; glDeleteProgram(m\_uiProgramObject);  
&nbsp;&nbsp;&nbsp; glDeleteShader(m\_uiVertexShader);  
&nbsp;&nbsp;&nbsp; glDeleteShader(m\_uiFragShader);  
  
&nbsp;&nbsp;&nbsp; return true;  
}  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
@Function&nbsp; RenderScene  
@Return&nbsp; bool&nbsp; 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 OGLESBasicTnL::RenderScene()  
{  
  
&nbsp;&nbsp;&nbsp; if(PVRShellIsKeyPressed(PVRShellKeyNameACTION1))  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m\_bDepthTest = !m\_bDepthTest;  
&nbsp;&nbsp;&nbsp; if(PVRShellIsKeyPressed(PVRShellKeyNameACTION2))  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m\_bRenderOrder = !m\_bRenderOrder;  
  
&nbsp;&nbsp;&nbsp; glViewport(0, 0, 800, 600);  
&nbsp;&nbsp;&nbsp; glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  
&nbsp;&nbsp;&nbsp; glEnable(GL\_CULL\_FACE);  
&nbsp;&nbsp;&nbsp; glCullFace(GL\_FRONT);  
&nbsp;&nbsp;&nbsp; if(m\_bDepthTest)  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glEnable(GL\_DEPTH\_TEST);  
&nbsp;&nbsp;&nbsp; }  
&nbsp;&nbsp;&nbsp; else  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glDisable(GL\_DEPTH\_TEST);  
&nbsp;&nbsp;&nbsp; }  
  
&nbsp;&nbsp;&nbsp; // Clears the color and depth buffer  
&nbsp;&nbsp;&nbsp; glClear(GL\_COLOR\_BUFFER\_BIT | GL\_DEPTH\_BUFFER\_BIT);  
  
&nbsp;&nbsp;&nbsp; glEnable(GL\_TEXTURE\_2D);  
  
&nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; //Draw the background  
&nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; float alpha = 0;&nbsp; //-p  
&nbsp;&nbsp;&nbsp; float beta =&nbsp; 0;&nbsp; //-q  
&nbsp;&nbsp;&nbsp; float theta = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // o  
  
&nbsp;&nbsp;&nbsp; float aModelViewIT0[] =  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta),  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -sin(theta),&nbsp;&nbsp; sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta)  
&nbsp;&nbsp;&nbsp; };  
  
&nbsp;&nbsp;&nbsp; /\*  
&nbsp;&nbsp;&nbsp; Bind the projection model view matrix (PMVMatrix) to the  
&nbsp;&nbsp;&nbsp; corresponding uniform variable in the shader.  
&nbsp;&nbsp;&nbsp; This matrix is used in the vertex shader to transform the vertices.  
&nbsp;&nbsp;&nbsp; \*/  
&nbsp;&nbsp;&nbsp; float aPMVMatrix0[] =  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta), 0,  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),0,  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -sin(theta),&nbsp;&nbsp; sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta),0,  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0,0,0,1  
&nbsp;&nbsp;&nbsp; };  
  
&nbsp;&nbsp;&nbsp; // same shader for both quads so only need to make these calls once  
&nbsp;&nbsp;&nbsp; glUseProgram(m\_uiProgramObject);&nbsp;&nbsp;&nbsp;   
  
&nbsp;&nbsp;&nbsp; int i32Location = glGetUniformLocation(m\_uiProgramObject, "myPMVMatrix");  
&nbsp;&nbsp;&nbsp; glUniformMatrix4fv( i32Location, 1, GL\_FALSE, aPMVMatrix0);  
&nbsp;&nbsp;&nbsp; i32Location = glGetUniformLocation(m\_uiProgramObject, "myModelViewIT");  
&nbsp;&nbsp;&nbsp; glUniformMatrix3fv( i32Location, 1, GL\_FALSE, aModelViewIT0);  
&nbsp;&nbsp;&nbsp; float aTMatrix0[] = {0.0f,0.0f,0.0f,0.0f};  
&nbsp;&nbsp;&nbsp; i32Location = glGetUniformLocation(m\_uiProgramObject, "myTMatrix");  
&nbsp;&nbsp;&nbsp; glUniform4fv( i32Location,1,aTMatrix0);  
&nbsp;&nbsp;&nbsp; float aScale0 = 1.0;  
&nbsp;&nbsp;&nbsp; i32Location = glGetUniformLocation(m\_uiProgramObject, "myScale");  
&nbsp;&nbsp;&nbsp; glUniform1f( i32Location,aScale0);  
&nbsp;&nbsp;&nbsp; float aYScale0 = 1.0;  
&nbsp;&nbsp;&nbsp; i32Location = glGetUniformLocation(m\_uiProgramObject, "myYScale");  
&nbsp;&nbsp;&nbsp; glUniform1f( i32Location,aYScale0);  
&nbsp;&nbsp;&nbsp; // Bind the Light Direction vector to the shader  
&nbsp;&nbsp;&nbsp; i32Location = glGetUniformLocation(m\_uiProgramObject, "myLightDirection");   
&nbsp;&nbsp;&nbsp; glUniform3f( i32Location, 0, 0, 1.5);  
  
  
&nbsp;&nbsp;&nbsp; // these are the same for both quads as well so only make the calls once  
&nbsp;&nbsp;&nbsp; glEnableVertexAttribArray(NORMAL\_ARRAY);  
&nbsp;&nbsp;&nbsp; glVertexAttribPointer(NORMAL\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_NORMAL);  
&nbsp;&nbsp;&nbsp; glEnableVertexAttribArray(TEXCOORD\_ARRAY);   
&nbsp;&nbsp;&nbsp; glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_TEXTCOORD);  
&nbsp;&nbsp;&nbsp; glEnableVertexAttribArray(COLOR\_ARRAY);   
&nbsp;&nbsp;&nbsp; glVertexAttribPointer(COLOR\_ARRAY, 4, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_COLOR);  
  
  
&nbsp;&nbsp;&nbsp; // draw  
  
&nbsp;&nbsp;&nbsp; if(m\_bRenderOrder)  
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; // draw one way  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Draw the background  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_VETEX);  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glDrawArrays(GL\_TRIANGLES, 0,6);  
  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Draw the foreground  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // different vertex positions  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_VETEX);  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // different texture  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);   
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glDrawArrays(GL\_TRIANGLES, 0,6);  
&nbsp;&nbsp;&nbsp; }  
&nbsp;&nbsp;&nbsp; else  
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; // draw in the other order  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Draw the foreground  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // different vertex positions  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, FG\_TRIANGLE\_VETEX);  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // different texture  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glBindTexture(GL\_TEXTURE\_2D, m\_uiFGTex);   
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glDrawArrays(GL\_TRIANGLES, 0,6);  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Draw the background  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 0, BK\_TRIANGLE\_VETEX);  
  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glBindTexture(GL\_TEXTURE\_2D, m\_uiBKTex);  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glDrawArrays(GL\_TRIANGLES, 0,6);  
  
&nbsp;&nbsp;&nbsp; }  
  
  
  
&nbsp;&nbsp;&nbsp; return true;  
}  
/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
@Function&nbsp; NewDemo  
@Return&nbsp; PVRShell\*&nbsp; The demo supplied by the user  
@Description This function must be implemented by the user of the shell.  
The user should return its PVRShell object defining the  
behaviour of the application.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
PVRShell\* NewDemo()  
{  
&nbsp;&nbsp;&nbsp; return new OGLESBasicTnL();  
}  
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
End of file (OGLESBasicTnL.cpp)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  

  
  
Gordon2010-11-18 19:04:44

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 18, 2010, 11:19pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/14 "2010-11-18T23:19:47Z")

</div>

Thank you so much, Gordon.&nbsp;&nbsp;I do appreciate it that you trimmed my code and made it running.

&nbsp;
  

I played with the program and I found out that after setting a new z locations for BK\_TRIANGLE\_VETEX and FG\_TRIANGLE\_VETEX, such as 
  

&nbsp;
  

GLfloat BK\_TRIANGLE\_VETEX[18] ={\<?: prefix = o ns = "urn:schemas-microsoft-com:office:office" /\>

  

-1.0f, 1.0f, 1.0f,

  

1.0f, 1.0f, 1.0f,

  

1.0f, -1.0f, 1.0f,

  

-1.0f, 1.0f, 1.0f,

  

1.0f, -1.0f, 1.0f,

  

-1.0f, -1.0f, 1.0f

  

};
  

&nbsp;
  

Your code will fail too and it&nbsp;generated a black background when depth\_test is enabled. If I choose to set as following, 
  

&nbsp;
  
 

GLfloat BK\_TRIANGLE\_VETEX[18] ={

   
 

-1.0f, 1.0f, 0.995f,

   
 

1.0f, 1.0f, 0.995f,

   
 

1.0f, -1.0f, 0.995f,

   
 

-1.0f, 1.0f, 0.995f,

   
 

1.0f, -1.0f, 0.995f,

   
 

-1.0f, -1.0f, 0.995f

   
 
};
   
 
&nbsp;
   
 
  
 
Your code runs well and background is visualized correctly when depth\_test is enabled. 
   
 
&nbsp;
   
 
For the Foreground, your program works even I choose the following setting 
   
 

GLfloat FG\_TRIANGLE\_VETEX[18] ={

   
 

&nbsp;&nbsp;&nbsp; -1.0f, 0.5f, -1.0f,

   
 

&nbsp;&nbsp;&nbsp; 0.5f, 0.5f, -1.0f,

   
 

&nbsp;&nbsp;&nbsp; 0.5f, -1.0f,-1.0f,

   
 

&nbsp;&nbsp;&nbsp; -1.0f, 0.5f, -1.0f,

   
 

&nbsp;&nbsp;&nbsp; 0.5f, -1.0f, -1.0f,

   
 

&nbsp;&nbsp;&nbsp; -1.0f, -1.0f, -1.0f

   
 
};
   
 
&nbsp;
   
 
  
 
I run my original code with the above tests, I got the same visualization results as yours. So, I think the real problem is I should have not use the 1.0 setting for BK.
   
 
&nbsp;

   
 
So from the above test, can I say in the PVRShell, the range of z is actually 
   
 
-1.0\<= z \< 1.0
   
 
Is this correct? 
   
 
&nbsp;
   
 
Thank you very much.
   
 
&nbsp;
   
 
Renaissance.
   
 
&nbsp;
   
 
&nbsp;

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 19, 2010, 12:05am UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/15 "2010-11-19T00:05:01Z")

</div>

Another related question is that if we define the location close to the view point with small value and the location far away&nbsp;with large value, how about the normal definition?

&nbsp;
  

In the above code, the normal is defined as&nbsp;&nbsp;0.0f,0.0f,1.0f, which is&nbsp;not towards the view point. But why we still can see the light reflect from this plane?&nbsp;Can you help me explain this? I have a feeling I do not have a correct understanding of the coordinate system in the OpenGL ES.
  

&nbsp;
  

Thank u very much,
  

&nbsp;
  

Renaissance

---

<div class="post-metadata">

**Author:** ![martin-kraus](https://avatars.discourse-cdn.com/v4/letter/m/85f322/32.png) [@martin-kraus](https://forums.imgtec.com/u/martin-kraus)\
**Post date:** [November 19, 2010, 8:11am UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/16 "2010-11-19T08:11:05Z")

</div>

About z \< 1.0 or z \<= 1.0 (actually I think it should be: z \< w or z \<= w): as a rule of thumb you should never rely on the outcome of an equality comparison of floating-point numbers. The reason is that usually you cannot be sure which values can be represented accurately on your machine. Consider the value 1.1: it uses 2 digits in the decimal system but requires infinitely many digits in the binary system and is therefore usually not represented with infinite precision on a computer.   
  
About the coordinate system: the standard modelview and projection matrices in OpenGL assume a right-handed coordinate system with the camera looking in the negative(!) z direction. (Thus, (0,0,1) is towards the camera for an object in front of the camera.)  
  
Martin Kraus2010-11-19 10:46:23

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 19, 2010, 4:59pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/17 "2010-11-19T16:59:03Z")

</div>

Thank you, Martin.

&nbsp;
  

As you said, the camera (view point) is looking in the negative direction. So, the near plane should have a larger z value and the far plane should have a smaller z value. This is just opposite of what we used in the above code, where FG (near plane) is at -1.0 and BK (far plane) is at 0.995.&nbsp;

---

<div class="post-metadata">

**Author:** ![martin-kraus](https://avatars.discourse-cdn.com/v4/letter/m/85f322/32.png) [@martin-kraus](https://forums.imgtec.com/u/martin-kraus)\
**Post date:** [November 19, 2010, 7:08pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/18 "2010-11-19T19:08:57Z")

</div>

renaissance,  
  
sorry, my comment about the standard viewing direction doesn’t apply to your code since you are using a non-standard modelview and projection matrix. What happens with the gl\_Position computed by the vertex shader (which I will call (x,y,z,w) ) is:  
  
1) The hardware clips the primitives such that -w \< x \< w, -w \< y \< w, -w \< z \< w.  
2) Then all coordinates are divided by w.  
3) Then z/w is transformed according to the parameters given to glDepthRangef. By default, the depth of a fragment is computed as 0.5 \* z/w + 0.5  
4) The default depth test is GL\_LESS, i.e. a fragment passes the depth test, if its depth is less than the depth stored in the depth buffer.   
  
Thus, with an identity projection matrix and w=1, it should actually be the fragments with the smallest z coordinate that survive the depth test (which is not what you would get if you used the “standard” projection and modelview matrices that would emulate fixed-function OpenGL behaviour).  
  
With vertex shaders you have to set up appropriate transformation matrices yourself; thus, basically you should either use some standard matrices (which you find in many books and courses about OpenGL) or you really have to know what you are doing.

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [November 19, 2010, 9:27pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/19 "2010-11-19T21:27:15Z")

</div>

Hi Martin, Thank you for your response.

&nbsp;
  

If the standard modelview and projection matrix you talked about should be defined as following,&nbsp;actually they are exactly the same as&nbsp;I used in my code (just need a little bit calculation). Maybe the shader does look complicated, but actually, based on the input parameters, there should be no special&nbsp;effect on the visualization.
  

&nbsp;
  

&nbsp;float aModelViewIT[] =  
&nbsp;{1,0,0,
  

&nbsp;&nbsp; 0,1,0,
  

&nbsp;&nbsp; 0,0,1}
  

&nbsp;float aPMVMatrix[] =  
&nbsp;{ 1,0,0,0,
  

&nbsp;&nbsp;&nbsp; 0,1,0,0,
  

  
 
&nbsp;&nbsp;&nbsp; 0,0,1,0,
   
 
  
 
&nbsp;&nbsp;&nbsp; 0,0,0,1

  

}
  

&nbsp;
  

&nbsp;
  

  
 

&nbsp;&nbsp;&nbsp; float alpha = 0;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp; float beta =&nbsp; 0;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp; float theta = 0;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp; float aModelViewIT0[] =  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta),  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -sin(theta),&nbsp;&nbsp; sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta)  
&nbsp;&nbsp;&nbsp; };

   
 
  
&nbsp;&nbsp;&nbsp; float aPMVMatrix0[] =  
&nbsp;&nbsp;&nbsp; {  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*cos(alpha), cos(alpha)\*sin(beta)\*sin(theta)-sin(alpha)\*cos(beta), cos(alpha)\*cos(beta)\*sin(theta)+sin(alpha)\*sin(beta), 0,  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cos(theta)\*sin(alpha), sin(alpha)\*sin(beta)\*sin(theta)+cos(alpha)\*cos(beta), sin(alpha)\*cos(beta)\*sin(theta)-sin(beta)\*cos(alpha),0,  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -sin(theta),&nbsp;&nbsp; sin(beta)\*cos(theta),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cos(beta)\*cos(theta),0,  
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0,0,0,1  
&nbsp;&nbsp;&nbsp; };\<?: prefix = o ns = "urn:schemas-microsoft-com:office:office" /\>
   
 

&nbsp;

---

<div class="post-metadata">

**Author:** ![martin-kraus](https://avatars.discourse-cdn.com/v4/letter/m/85f322/32.png) [@martin-kraus](https://forums.imgtec.com/u/martin-kraus)\
**Post date:** [November 19, 2010, 10:30pm UTC](https://forums.imgtec.com/t/could-not-show-multiple-textures/879/20 "2010-11-19T22:30:00Z")

</div>

Sorry, I wasn't clear enough: when I refer to "standard" projection and modelview matrices I'm refering to the matrices that are typically used in the fixed-function pipeline. See for example Appendix G of the "OpenGL Programming Guide": [http://www.opengl.org/documentation/red\_book/](http://www.opengl.org/documentation/red_book/) for the "standard" projection matrices. The PowerVR SDK comes also with some utility function to compute these matrices. And here is some code I recently wrote to compute the "standard" matrices (and other vector/matrix operations):   
  
#include \<assert.h\>  

```
// data types

typedef struct
{
GLfloat m[4][4];
} matrix4x4;

// functions for vectors

///
// Returns the length of a 3D vector.
//
GLfloat length3f(GLfloat x, GLfloat y, GLfloat z)
{
return (GLfloat)sqrtf( x * x + y * y + z * z );
}

///
// Normalizes a 3D vector.
//
void normalize3f(GLfloat *result, GLfloat x, GLfloat y, GLfloat z)
{
GLfloat length;

assert( NULL != result );

length = length3f( x, y, z );
if ((GLfloat)0.0f == length)
{
// we panic, but at least we can initialize the result to a unit vector
result[0] = (GLfloat)1.0f;
result[1] = (GLfloat)0.0f;
result[2] = (GLfloat)0.0f;
}
else
{
result[0] = x / length;
result[1] = y / length;
result[2] = z / length;
}
return;
}

///
// Returns the dot product of two 2D vectors.
//
GLfloat dot3f(GLfloat ax, GLfloat ay, GLfloat az, GLfloat bx, GLfloat by, GLfloat bz)
{
return ax * bx + ay * by + az * bz;
}

///
// Computes the cross product of two 3D vectors
//
void cross3f(GLfloat *result, GLfloat ax, GLfloat ay, GLfloat az, GLfloat bx, GLfloat by, GLfloat bz)
{
assert( NULL != result );

result[0] = ay * bz - az * by;
result[1] = az * bx - ax * bz;
result[2] = ax * by - ay * bx;
return;
}

// functions for 4x4 matrices

///
// Sets a 4x4 matrix. (The indices of the arguments are in traditional row-major order from 1 to 4.)
//
void matrixSet(matrix4x4 *result,
GLfloat m11, GLfloat m12, GLfloat m13, GLfloat m14,
GLfloat m21, GLfloat m22, GLfloat m23, GLfloat m24,
GLfloat m31, GLfloat m32, GLfloat m33, GLfloat m34,
GLfloat m41, GLfloat m42, GLfloat m43, GLfloat m44)
{
assert( NULL != result );

result->m[0][0] = m11;
result->m[0][1] = m21;
result->m[0][2] = m31;
result->m[0][3] = m41;

result->m[1][0] = m12;
result->m[1][1] = m22;
result->m[1][2] = m32;
result->m[1][3] = m42;

result->m[2][0] = m13;
result->m[2][1] = m23;
result->m[2][2] = m33;
result->m[2][3] = m43;

result->m[3][0] = m14;
result->m[3][1] = m24;
result->m[3][2] = m34;
result->m[3][3] = m44;

return;
}

///
// Multiplies a 4x4 matrix with a 4D vector
//
void matrixMultiply4f(GLfloat *result, matrix4x4 *matrix, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
assert( NULL != result && NULL != matrix);

result[0] = matrix->m[0][0] * x + matrix->m[1][0] * y +
matrix->m[2][0] * z + matrix->m[3][0] * w;
result[1] = matrix->m[0][1] * x + matrix->m[1][1] * y +
matrix->m[2][1] * z + matrix->m[3][1] * w;
result[2] = matrix->m[0][2] * x + matrix->m[1][2] * y +
matrix->m[2][2] * z + matrix->m[3][2] * w;
result[3] = matrix->m[0][3] * x + matrix->m[1][3] * y +
matrix->m[2][3] * z + matrix->m[3][3] * w;
return;
}

///
// Multiplies two 4x4 matrices.
//
void matrixMultiply(matrix4x4 *result, matrix4x4 *a, matrix4x4 *b)
{
int i, j;
matrix4x4 tmp;

assert( NULL != result && NULL != a && NULL != b );

for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tmp.m[j] _=   
 a-\>m[0] \* b-\>m[j][0] +  
 a-\>m[1] \* b-\>m[j][1] +  
 a-\>m[2] \* b-\>m[j][2] +  
 a-\>m[3] \* b-\>m[j][3];  
 }  
 }  
 \*result = tmp;  
 return;  
}_  
  
_///   
// Computes the determinant of the upper, left 3x3 submatrix   
//  
GLfloat matrixDeterminant(matrix4x4 \*matrix)  
{  
 assert( NULL != matrix );_  
  
 _return matrix-\>m[0][0] \* matrix-\>m[1][1] \* matrix-\>m[2][2] +  
 matrix-\>m[1][0] \* matrix-\>m[2][1] \* matrix-\>m[0][2] +  
 matrix-\>m[2][0] \* matrix-\>m[0][1] \* matrix-\>m[1][2] -  
 matrix-\>m[2][0] \* matrix-\>m[1][1] \* matrix-\>m[0][2] -  
 matrix-\>m[0][0] \* matrix-\>m[2][1] \* matrix-\>m[1][2] -  
 matrix-\>m[1][0] \* matrix-\>m[0][1] \* matrix-\>m[2][2];  
}_  
  
_///   
// Computes the transpose of the upper left 3x3 matrix and adjusts the last column  
// such that a rigid-body transformation is inverted.  
//  
void matrixTranspose(matrix4x4 \*result, matrix4x4 \*matrix)  
{  
 matrix4x4 tmp;_  
  
 _assert( NULL != result && NULL != matrix );_  
  
 _tmp.m[0][0] = matrix-\>m[0][0];   
 tmp.m[0][1] = matrix-\>m[1][0];   
 tmp.m[0][2] = matrix-\>m[2][0];   
 tmp.m[0][3] = matrix-\>m[0][3];_   
   
 _tmp.m[1][0] = matrix-\>m[0][1];   
 tmp.m[1][1] = matrix-\>m[1][1];   
 tmp.m[1][2] = matrix-\>m[2][1];   
 tmp.m[1][3] = matrix-\>m[1][3];_   
  
 _tmp.m[2][0] = matrix-\>m[0][2];   
 tmp.m[2][1] = matrix-\>m[1][2];   
 tmp.m[2][2] = matrix-\>m[2][2];   
 tmp.m[2][3] = matrix-\>m[2][3];_   
  
 _tmp.m[3][0] = -matrix-\>m[0][0] \* matrix-\>m[3][0] -   
 matrix-\>m[0][1] \* matrix-\>m[3][1] - matrix-\>m[0][2] \* matrix-\>m[3][2];  
 tmp.m[3][1] = -matrix-\>m[1][0] \* matrix-\>m[3][0] -   
 matrix-\>m[1][1] \* matrix-\>m[3][1] - matrix-\>m[1][2] \* matrix-\>m[3][2];  
 tmp.m[3][2] = -matrix-\>m[2][0] \* matrix-\>m[3][0] -   
 matrix-\>m[2][1] \* matrix-\>m[3][1] - matrix-\>m[2][2] \* matrix-\>m[3][2];  
 tmp.m[3][3] = matrix-\>m[3][3];_   
  
 _\*result = tmp;  
 return;  
}_  
  
_///   
// Computes the inverse of a 4x4 matrix if the bottom row is (0,0,0,1)   
// and the determinant of the upper left 3x3 matrix is not 0.  
//  
void matrixInverse(matrix4x4 \*result, matrix4x4 \*matrix)  
{  
 GLfloat determinant;  
 GLfloat determinant\_inv;  
 matrix4x4 tmp;_  
  
 _assert( NULL != result && NULL != matrix &&   
 matrix-\>m[0][3] == 0.0f && matrix-\>m[1][3] == 0.0f &&   
 matrix-\>m[2][3] == 0.0f && matrix-\>m[3][3] == 1.0f );_  
  
 _determinant = matrixDeterminant( matrix );  
 if (0.0f == determinant)  
 {   
 // matrix is not invertible: we panic, but at least we can initialize the result to the transpose  
 matrixTranspose(result, matrix);   
 return;  
 }  
 determinant\_inv = (GLfloat)( 1.0f / determinant );_   
  
 _// compute inverse of upper left 3x3 matrix  
 tmp.m[0][0] = determinant\_inv \* (matrix-\>m[1][1] \* matrix-\>m[2][2] - matrix-\>m[2][1] \* matrix-\>m[1][2]);   
 tmp.m[0][1] = determinant\_inv \* (matrix-\>m[2][1] \* matrix-\>m[0][2] - matrix-\>m[0][1] \* matrix-\>m[2][2]);   
 tmp.m[0][2] = determinant\_inv \* (matrix-\>m[0][1] \* matrix-\>m[1][2] - matrix-\>m[1][1] \* matrix-\>m[0][2]);   
 tmp.m[0][3] = (GLfloat)0.0f;_   
  
 _tmp.m[1][0] = determinant\_inv \* (matrix-\>m[2][0] \* matrix-\>m[1][2] - matrix-\>m[1][0] \* matrix-\>m[2][2]);   
 tmp.m[1][1] = determinant\_inv \* (matrix-\>m[0][0] \* matrix-\>m[2][2] - matrix-\>m[2][0] \* matrix-\>m[0][2]);   
 tmp.m[1][2] = determinant\_inv \* (matrix-\>m[1][0] \* matrix-\>m[0][2] - matrix-\>m[0][0] \* matrix-\>m[1][2]);   
 tmp.m[1][3] = (GLfloat)0.0f;_   
  
 _tmp.m[2][0] = determinant\_inv \* (matrix-\>m[1][0] \* matrix-\>m[2][1] - matrix-\>m[2][0] \* matrix-\>m[1][1]);   
 tmp.m[2][1] = determinant\_inv \* (matrix-\>m[2][0] \* matrix-\>m[0][1] - matrix-\>m[0][0] \* matrix-\>m[2][1]);   
 tmp.m[2][2] = determinant\_inv \* (matrix-\>m[0][0] \* matrix-\>m[1][1] - matrix-\>m[1][0] \* matrix-\>m[0][1]);   
 tmp.m[2][3] = (GLfloat)0.0f;_   
  
 _// compute new translation vector as minus inverse of upper left 3x3 matrix times old translation vector  
 tmp.m[3][0] = -tmp.m[0][0] \* matrix-\>m[3][0] -   
 tmp.m[1][0] \* matrix-\>m[3][1] - tmp.m[2][0] \* matrix-\>m[3][2];   
 tmp.m[3][1] = -tmp.m[0][1] \* matrix-\>m[3][0] -   
 tmp.m[1][1] \* matrix-\>m[3][1] - tmp.m[2][1] \* matrix-\>m[3][2];   
 tmp.m[3][2] = -tmp.m[0][2] \* matrix-\>m[3][0] -   
 tmp.m[1][2] \* matrix-\>m[3][1] - tmp.m[2][2] \* matrix-\>m[3][2];   
 tmp.m[3][3] = (GLfloat)1.0f;_   
  
 _\*result = tmp;  
 return;  
}_  
  
_///  
// Computes an identity transformation.  
//  
void matrixIdentity(matrix4x4 \*result)  
{  
 matrixSet(result,   
 1.0f, 0.0f, 0.0f, 0.0f,  
 0.0f, 1.0f, 0.0f, 0.0f,  
 0.0f, 0.0f, 1.0f, 0.0f,  
 0.0f, 0.0f, 0.0f, 1.0f  
 );  
 return;  
}_  
  
_///  
// Computes a scaling.  
//  
void matrixScaling(matrix4x4 \*result, GLfloat sx, GLfloat sy, GLfloat sz)  
{  
 matrixSet(result,   
 sx, 0.0f, 0.0f, 0.0f,  
 0.0f, sy, 0.0f, 0.0f,  
 0.0f, 0.0f, sz, 0.0f,  
 0.0f, 0.0f, 0.0f, 1.0f  
 );  
 return;  
}_  
  
_///  
// Computes a translation.  
//  
void matrixTranslation(matrix4x4 \*result, GLfloat tx, GLfloat ty, GLfloat tz)  
{  
 matrixSet(result,   
 1.0f, 0.0f, 0.0f, tx,  
 0.0f, 1.0f, 0.0f, ty,  
 0.0f, 0.0f, 1.0f, tz,  
 0.0f, 0.0f, 0.0f, 1.0f  
 );  
 return;  
}_  
  
_///  
// Computes a rotation about the axis (x,y,z) by angle (in degrees).  
//  
void matrixRotation(matrix4x4 \*result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)  
{  
 GLfloat sinAngle, cosAngle;  
 GLfloat mag = sqrtf(x \* x + y \* y + z \* z);  
 GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;  
 GLfloat oneMinusCos;_  
  
 _assert( NULL != result );_  
  
 _if (mag \<= 0.0f)  
 {  
 // no rotation axis: we panic, but we initialize the result with the identity  
 matrixIdentity(result);  
 return;  
 }_  
  
 _x /= mag;  
 y /= mag;  
 z /= mag;_  
  
 _sinAngle = sinf ( angle \* M\_PI / 180.0f );  
 cosAngle = cosf ( angle \* M\_PI / 180.0f );_  
  
 _xx = x \* x;  
 yy = y \* y;  
 zz = z \* z;  
 xy = x \* y;  
 yz = y \* z;  
 zx = z \* x;  
 xs = x \* sinAngle;  
 ys = y \* sinAngle;  
 zs = z \* sinAngle;  
 oneMinusCos = 1.0f - cosAngle;_  
  
 _result-\>m[0][0] = (oneMinusCos \* xx) + cosAngle;  
 result-\>m[0][1] = (oneMinusCos \* xy) - zs;  
 result-\>m[0][2] = (oneMinusCos \* zx) + ys;  
 result-\>m[0][3] = 0.0f;_   
  
 _result-\>m[1][0] = (oneMinusCos \* xy) + zs;  
 result-\>m[1][1] = (oneMinusCos \* yy) + cosAngle;  
 result-\>m[1][2] = (oneMinusCos \* yz) - xs;  
 result-\>m[1][3] = 0.0f;_  
  
 _result-\>m[2][0] = (oneMinusCos \* zx) - ys;  
 result-\>m[2][1] = (oneMinusCos \* yz) + xs;  
 result-\>m[2][2] = (oneMinusCos \* zz) + cosAngle;  
 result-\>m[2][3] = 0.0f;_   
  
 _result-\>m[3][0] = 0.0f;  
 result-\>m[3][1] = 0.0f;  
 result-\>m[3][2] = 0.0f;  
 result-\>m[3][3] = 1.0f;_  
  
 _return;  
}_  
  
_///   
// Computes a viewing transformation.  
//  
void matrixLookAt(matrix4x4 \*result, GLfloat eye\_x, GLfloat eye\_y, GLfloat eye\_z,   
 GLfloat lookat\_x, GLfloat lookat\_y, GLfloat lookat\_z,   
 GLfloat worldup\_x, GLfloat worldup\_y, GLfloat worldup\_z)  
{  
 GLfloat dir[3];  
 GLfloat side[3];  
 GLfloat up[3];  
 matrix4x4 view\_to\_model;_  
  
 _assert( NULL != result );_  
  
 _// compute normalized view direction (will be negative z axis)  
 normalize3f(dir, lookat\_x - eye\_x, lookat\_y - eye\_y, lookat\_z - eye\_z);_  
  
 _// compute normalized side vector (will be positive x axis)  
 cross3f(side, dir[0], dir[1], dir[2], worldup\_x, worldup\_y, worldup\_z);  
 normalize3f(side, side[0], side[1], side[2]);_  
  
 _// compute (normalized) up vector (will be positive y axis)  
 cross3f(up, side[0], side[1], side[2], dir[0], dir[1], dir[2]);_  
  
 _// set view to model transformation  
 matrixSet(&view\_to\_model,  
 side[0], up[0], -dir[0], eye\_x,  
 side[1], up[1], -dir[1], eye\_y,  
 side[2], up[2], -dir[2], eye\_z,  
 0.0f, 0.0f, 0.0f, 1.0f  
 );_  
  
 _// invert matrix (by transposing)  
 matrixTranspose( result, &view\_to\_model );  
 return;  
}_  
  
_///  
// Computes an oblique perspective projection matrix.  
//  
void matrixFrustum(matrix4x4 \*result, GLfloat left, GLfloat right,   
 GLfloat bottom, GLfloat top, GLfloat nearZ, GLfloat farZ)  
{  
 GLfloat deltaX = right - left;  
 GLfloat deltaY = top - bottom;  
 GLfloat deltaZ = farZ - nearZ;_  
  
 _assert( NULL != result && (nearZ \> 0.0f) && (farZ \> 0.0f) &&  
 (deltaX \> 0.0f) && (deltaY \> 0.0f) && (deltaZ \> 0.0f) );_  
  
 _matrixSet(result,   
 2.0f \* nearZ / deltaX, 0.0f, (right + left) / deltaX, 0.0f,  
 0.0f, 2.0f \* nearZ / deltaY, (top + bottom) / deltaY, 0.0f,  
 0.0f, 0.0f, -(nearZ + farZ) / deltaZ, -2.0f \* nearZ \* farZ / deltaZ,  
 0.0f, 0.0f, -1.0f, 0.0f  
 );  
 return;  
}_  
  
_///  
// Computes a perspective projection matrix.  
//  
void matrixPerspective(matrix4x4 \*result, GLfloat fovy, GLfloat aspect, GLfloat nearZ, GLfloat farZ)  
{  
 GLfloat frustumW, frustumH;_  
  
 _frustumH = tanf( fovy / 360.0f \* M\_PI ) \* nearZ;  
 frustumW = frustumH \* aspect;_  
  
 _matrixFrustum( result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ );  
}_  
  
_///  
// Computes an orthographic projection matrix.  
//  
void matrixOrtho(matrix4x4 \*result, GLfloat left, GLfloat right,   
 GLfloat bottom, GLfloat top, GLfloat nearZ, GLfloat farZ)  
{  
 GLfloat deltaX = right - left;  
 GLfloat deltaY = top - bottom;  
 GLfloat deltaZ = farZ - nearZ;_  
  
 _assert( NULL != result && (deltaX != 0.0f) && (deltaY != 0.0f) && (deltaZ != 0.0f) );_  
  
 _matrixSet(result,   
 2.0f / deltaX, 0.0f, 0.0f, -(right + left) / deltaX,  
 0.0f, 2.0f / deltaY, 0.0f, -(top + bottom) / deltaY,  
 0.0f, 0.0f, -2.0f / deltaZ, -(nearZ + farZ) / deltaZ,  
 0.0f, 0.0f, 0.0f, 1.0f  
 );  
 return;  
}_
```
  
  
 Martin Kraus2010-11-19 23:32:08

[Next page](https://forums.imgtec.com/t/could-not-show-multiple-textures/879.md?page=2)
