Thank you, Martin
#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 3
const char c_sz_BK_TextureFile[] = "BG-m.pvr";
const char c_sz_FG_TextureFile[] = "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] = {
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f};
GLfloat BK_TRIANGLE_COLOR[24] = {
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,1.0f,1.0f,
1.0f,1.0f,1.0f,1.0f};
GLfloat BK_TRIANGLE_TEXTCOORD[12] = {
0.0f,1.0f , // UVs
1.0f,1.0f ,
1.0f,0.0f,
0.0f,1.0f ,
1.0f,0.0f ,
0.0f,0.0f};
//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, -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] = {
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f};
GLfloat FG_TRIANGLE_COLOR[24] = {
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,1.0f,1.0f,
1.0f,1.0f,1.0f,1.0f};
GLfloat FG_TRIANGLE_TEXTCOORD[12] = {
0.0f,1.0f , // UVs
1.0f,1.0f ,
1.0f,0.0f,
0.0f,1.0f ,
1.0f,0.0f ,
0.0f,0.0f};
/*!****************************************************************************
Class implementing the PVRShell functions.
******************************************************************************/
class OGLESBasicTnL : public PVRShell
{
// The vertex and fragment shader OpenGL handles
GLuint m_uiVertexShader, m_uiFragShader;
// The program object containing the 2 shader objects
GLuint m_uiProgramObject;
// Texture handle
GLuint m_uiBKTex;
GLuint m_uiFGTex;
GLuint depthRenderbuffer;
public:
virtual bool InitApplication();
virtual bool InitView();
virtual bool ReleaseView();
virtual bool QuitApplication();
virtual bool RenderScene();
};
/*!****************************************************************************
@Function InitApplication
@Return bool 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()
{
bool m_bUseVertexProgram = true;
return true;
}
/*!****************************************************************************
@Function QuitApplication
@Return bool 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()
{
return true;
}
/*!****************************************************************************
@Function InitView
@Return bool true if no error occured
@Description Code in InitView() will be called by PVRShell upon
initialization or after a change in the rendering context.
Used to initialize variables that are dependant on the rendering
context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLESBasicTnL::InitView()
{
// Fragment and vertex shaders code
char* pszFragShader = "
uniform sampler2D sampler2d;
varying mediump float varDot;
varying mediump vec2 varCoord;
varying mediump vec4 v_primaryColor;
void main (void)
{
gl_FragColor = texture2D(sampler2d,varCoord) * varDot*v_primaryColor;
}";
char* pszVertShader = "
attribute highp vec4 myVertex;
attribute mediump vec3 myNormal;
attribute mediump vec4 myUV;
attribute mediump vec4 myColor;
uniform mediump mat4 myPMVMatrix;
uniform mediump vec4 myTMatrix;
uniform mediump float myScale;
uniform mediump float myYScale;
uniform mediump mat3 myModelViewIT;
uniform mediump vec3 myLightDirection;
varying mediump float varDot;
varying mediump vec2 varCoord;
varying mediump vec4 v_primaryColor;
void main(void)
{
v_primaryColor = myColor;
gl_Position = (myPMVMatrix * myVertex);
gl_Position.x = gl_Position.x*myScale;
gl_Position.y = gl_Position.y*myScale*myYScale;
gl_Position.z = gl_Position.z*myScale;
gl_Position = gl_Position + myTMatrix;
varCoord = myUV.st;
mediump vec3 transNormal = myModelViewIT * myNormal;
varDot = max( dot(transNormal, myLightDirection), 0.0 );
}";
// Create the fragment shader object
m_uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);
// Load the source code into it
glShaderSource(m_uiFragShader, 1, (const char**)&pszFragShader, NULL);
// Compile the source code
glCompileShader(m_uiFragShader);
// Check if compilation succeeded
GLint bShaderCompiled;
glGetShaderiv(m_uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);
if (!bShaderCompiled)
{
// An error happened, first retrieve the length of the log message
int i32InfoLogLength, i32CharsWritten;
glGetShaderiv(m_uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
// Allocate enough space for the message and retrieve it
char* pszInfoLog = new char[i32InfoLogLength];
glGetShaderInfoLog(m_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
/*
Displays the message in a dialog box when the application quits
using the shell PVRShellSet function with first parameter prefExitMessage.
*/
char* pszMsg = new char[i32InfoLogLength+256];
sprintf(pszMsg, "Failed to compile fragment shader: %s", pszInfoLog);
PVRShellSet(prefExitMessage, pszMsg);
delete [] pszMsg;
delete [] pszInfoLog;
return false;
}
// Loads the vertex shader in the same way
m_uiVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(m_uiVertexShader, 1, (const char**)&pszVertShader, NULL);
glCompileShader(m_uiVertexShader);
glGetShaderiv(m_uiVertexShader, GL_COMPILE_STATUS, &bShaderCompiled);
if (!bShaderCompiled)
{
int i32InfoLogLength, i32CharsWritten;
glGetShaderiv(m_uiVertexShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
char* pszInfoLog = new char[i32InfoLogLength];
glGetShaderInfoLog(m_uiVertexShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
char* pszMsg = new char[i32InfoLogLength+256];
sprintf(pszMsg, "Failed to compile vertex shader: %s", pszInfoLog);
PVRShellSet(prefExitMessage, pszMsg);
delete [] pszMsg;
delete [] pszInfoLog;
return false;
}
// Create the shader program
m_uiProgramObject = glCreateProgram();
// Attach the fragment and vertex shaders to it
glAttachShader(m_uiProgramObject, m_uiFragShader);
glAttachShader(m_uiProgramObject, m_uiVertexShader);
// Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
glBindAttribLocation(m_uiProgramObject, VERTEX_ARRAY, "myVertex");
// Bind the custom vertex attribute "myUV" to location TEXCOORD_ARRAY
glBindAttribLocation(m_uiProgramObject, TEXCOORD_ARRAY, "myUV");
// Bind the custom vertex attribute "myNormal" to location NORMAL_ARRAY
glBindAttribLocation(m_uiProgramObject, NORMAL_ARRAY, "myNormal");
// Bind the custom vertex attribute "myColor" to location COLOR_ARRAY
glBindAttribLocation(m_uiProgramObject, COLOR_ARRAY, "myColor");
// Link the program
glLinkProgram(m_uiProgramObject);
// Check if linking succeeded in the same way we checked for compilation success
GLint bLinked;
glGetProgramiv(m_uiProgramObject, GL_LINK_STATUS, &bLinked);
if (!bLinked)
{
int i32InfoLogLength, i32CharsWritten;
glGetProgramiv(m_uiProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
char* pszInfoLog = new char[i32InfoLogLength];
glGetProgramInfoLog(m_uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
char* pszMsg = new char[i32InfoLogLength+256];
sprintf(pszMsg, "Failed to link program: %s", pszInfoLog);
PVRShellSet(prefExitMessage, pszMsg);
delete [] pszMsg;
delete [] pszInfoLog;
return false;
}
if(PVRTTextureLoadFromPVR(c_sz_BK_TextureFile, &m_uiBKTex) != PVR_SUCCESS)
{
PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");
return false;
}
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
if(PVRTTextureLoadFromPVR(c_sz_FG_TextureFile, &m_uiFGTex) != PVR_SUCCESS)
{
PVRShellSet(prefExitMessage, "ERROR: Cannot load the texturen");
return false;
}
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
//glUniform1i(glGetUniformLocation(m_uiProgramObject, "sampler2d"), 0);
//glGenRenderbuffers(1, &depthRenderbuffer);
return true;
}
/*!****************************************************************************
@Function ReleaseView
@Return bool 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()
{
// Frees the texture
glDeleteTextures(1, &m_uiBKTex);
glDeleteTextures(1, &m_uiFGTex);
// Frees the OpenGL handles for the program and the 2 shaders
glDeleteProgram(m_uiProgramObject);
glDeleteShader(m_uiVertexShader);
glDeleteShader(m_uiFragShader);
return true;
}
/*!****************************************************************************
@Function RenderScene
@Return bool true if no error occured
@Description Main rendering loop function of the program. The shell will
call this function every frame.
eglSwapBuffers() will be performed by PVRShell automatically.
PVRShell will also manage important OS events.
Will also manage relevent OS events. The user has access to
these events through an abstraction layer provided by PVRShell.
******************************************************************************/
bool OGLESBasicTnL::RenderScene()
{
glViewport(0, 0, 800, 600);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glUseProgram(m_uiProgramObject);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
//glEnable(GL_DEPTH_TEST);
// Clears the color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
//*************************************************************************
//Draw the background
//*************************************************************************
float alpha = 0; //-p
float beta = 0; //-q
float theta = 0; // o
float aModelViewIT0[] =
{
cos(theta)*cos(alpha), cos(alpha)*sin(beta)*sin(theta)-sin(alpha)*cos(beta), cos(alpha)*cos(beta)*sin(theta)+sin(alpha)*sin(beta),
cos(theta)*sin(alpha), sin(alpha)*sin(beta)*sin(theta)+cos(alpha)*cos(beta), sin(alpha)*cos(beta)*sin(theta)-sin(beta)*cos(alpha),
-sin(theta), sin(beta)*cos(theta), cos(beta)*cos(theta)
};
/*
Bind the projection model view matrix (PMVMatrix) to the
corresponding uniform variable in the shader.
This matrix is used in the vertex shader to transform the vertices.
*/
float aPMVMatrix0[] =
{
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,
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,
-sin(theta), sin(beta)*cos(theta), cos(beta)*cos(theta),0,
0,0,0,1
};
int i32Location = glGetUniformLocation(m_uiProgramObject, "myPMVMatrix");
glUniformMatrix4fv( i32Location, 1, GL_FALSE, aPMVMatrix0);
i32Location = glGetUniformLocation(m_uiProgramObject, "myModelViewIT");
glUniformMatrix3fv( i32Location, 1, GL_FALSE, aModelViewIT0);
float aTMatrix0[] = {0.0f,0.0f,0.0f,0.0f};
i32Location = glGetUniformLocation(m_uiProgramObject, "myTMatrix");
glUniform4fv( i32Location,1,aTMatrix0);
float aScale0 = 1.0;
i32Location = glGetUniformLocation(m_uiProgramObject, "myScale");
glUniform1f( i32Location,aScale0);
float aYScale0 = 1.0;
i32Location = glGetUniformLocation(m_uiProgramObject, "myYScale");
glUniform1f( i32Location,aYScale0);
// Bind the Light Direction vector to the shader
i32Location = glGetUniformLocation(m_uiProgramObject, "myLightDirection");
glUniform3f( i32Location, 0, 0, 1.5);
//*************************************************************************
//Draw the background
//*************************************************************************
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, BK_TRIANGLE_VETEX);
glEnableVertexAttribArray(NORMAL_ARRAY);
glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, BK_TRIANGLE_NORMAL);
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, BK_TRIANGLE_TEXTCOORD);
glEnableVertexAttribArray(COLOR_ARRAY);
glVertexAttribPointer(COLOR_ARRAY, 4, GL_FLOAT, GL_FALSE, 0, BK_TRIANGLE_COLOR);
glBindTexture(GL_TEXTURE_2D, m_uiBKTex);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
// Draws a non-indexed triangle array
glDrawArrays(GL_TRIANGLES, 0,6);
glUseProgram(m_uiProgramObject);
//*************************************************************************
//Draw the foreground
//*************************************************************************
glViewport(0, 0, 800, 600);
i32Location = glGetUniformLocation(m_uiProgramObject, "myPMVMatrix");
glUniformMatrix4fv( i32Location, 1, GL_FALSE, aPMVMatrix0);
i32Location = glGetUniformLocation(m_uiProgramObject, "myModelViewIT");
glUniformMatrix3fv( i32Location, 1, GL_FALSE, aModelViewIT0);
i32Location = glGetUniformLocation(m_uiProgramObject, "myTMatrix");
glUniform4fv( i32Location,1,aTMatrix0);
i32Location = glGetUniformLocation(m_uiProgramObject, "myScale");
glUniform1f( i32Location,aScale0);
i32Location = glGetUniformLocation(m_uiProgramObject, "myYScale");
glUniform1f( i32Location,aYScale0);
i32Location = glGetUniformLocation(m_uiProgramObject, "myLightDirection");
glUniform3f( i32Location, 0, 0, 1.5);
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, FG_TRIANGLE_VETEX);
glEnableVertexAttribArray(NORMAL_ARRAY);
glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, FG_TRIANGLE_NORMAL);
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, FG_TRIANGLE_TEXTCOORD);
glEnableVertexAttribArray(COLOR_ARRAY);
glVertexAttribPointer(COLOR_ARRAY, 4, GL_FLOAT, GL_FALSE, 0, FG_TRIANGLE_COLOR);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glBindTexture(GL_TEXTURE_2D, m_uiFGTex);
// Draws a non-indexed triangle array
glDrawArrays(GL_TRIANGLES, 0,6);
return true;
}
/*!****************************************************************************
@Function NewDemo
@Return PVRShell* 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()
{
return new OGLESBasicTnL();
}
/******************************************************************************
End of file (OGLESBasicTnL.cpp)
******************************************************************************/