Fixed GLES3 demo

This commit is contained in:
pelya
2016-09-11 19:23:33 +03:00
parent e881097c26
commit 12af247a77
6 changed files with 182 additions and 1247 deletions

View File

@@ -1,184 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Book: OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
// Authors: Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
// ISBN-10: 0-321-93388-5
// ISBN-13: 978-0-321-93388-1
// Publisher: Addison-Wesley Professional
// URLs: http://www.opengles-book.com
// http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
//
// ESShader.c
//
// Utility functions for loading shaders and creating program objects.
//
///
// Includes
//
#include "esUtil.h"
#include <stdlib.h>
//////////////////////////////////////////////////////////////////
//
// Private Functions
//
//
//////////////////////////////////////////////////////////////////
//
// Public Functions
//
//
//
///
/// \brief Load a shader, check for compile errors, print error messages to output log
/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
/// \param shaderSrc Shader source string
/// \return A new shader object on success, 0 on failure
//
GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader ( type );
if ( shader == 0 )
{
return 0;
}
// Load the shader source
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader
glCompileShader ( shader );
// Check the compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled )
{
GLint infoLen = 0;
glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char *infoLog = malloc ( sizeof ( char ) * infoLen );
glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
free ( infoLog );
}
glDeleteShader ( shader );
return 0;
}
return shader;
}
//
///
/// \brief Load a vertex and fragment shader, create a program object, link program.
// Errors output to log.
/// \param vertShaderSrc Vertex shader source code
/// \param fragShaderSrc Fragment shader source code
/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
//
GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
{
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
if ( vertexShader == 0 )
{
return 0;
}
fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
if ( fragmentShader == 0 )
{
glDeleteShader ( vertexShader );
return 0;
}
// Create the program object
programObject = glCreateProgram ( );
if ( programObject == 0 )
{
return 0;
}
glAttachShader ( programObject, vertexShader );
glAttachShader ( programObject, fragmentShader );
// Link the program
glLinkProgram ( programObject );
// Check the link status
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
if ( !linked )
{
GLint infoLen = 0;
glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char *infoLog = malloc ( sizeof ( char ) * infoLen );
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
esLogMessage ( "Error linking program:\n%s\n", infoLog );
free ( infoLog );
}
glDeleteProgram ( programObject );
return 0;
}
// Free up no longer needed shader resources
glDeleteShader ( vertexShader );
glDeleteShader ( fragmentShader );
return programObject;
}

View File

@@ -1,367 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Book: OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
// Authors: Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
// ISBN-10: 0-321-93388-5
// ISBN-13: 978-0-321-93388-1
// Publisher: Addison-Wesley Professional
// URLs: http://www.opengles-book.com
// http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
//
// ESShapes.c
//
// Utility functions for generating shapes
//
///
// Includes
//
#include "esUtil.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
///
// Defines
//
#define ES_PI (3.14159265f)
//////////////////////////////////////////////////////////////////
//
// Private Functions
//
//
//////////////////////////////////////////////////////////////////
//
// Public Functions
//
//
//
/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores
/// the results in the arrays. Generate index list for a TRIANGLE_STRIP
/// \param numSlices The number of slices in the sphere
/// \param vertices If not NULL, will contain array of float3 positions
/// \param normals If not NULL, will contain array of float3 normals
/// \param texCoords If not NULL, will contain array of float2 texCoords
/// \param indices If not NULL, will contain the array of indices for the triangle strip
/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
/// if it is not NULL ) as a GL_TRIANGLE_STRIP
//
int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals,
GLfloat **texCoords, GLuint **indices )
{
int i;
int j;
int numParallels = numSlices / 2;
int numVertices = ( numParallels + 1 ) * ( numSlices + 1 );
int numIndices = numParallels * numSlices * 6;
float angleStep = ( 2.0f * ES_PI ) / ( ( float ) numSlices );
// Allocate memory for buffers
if ( vertices != NULL )
{
*vertices = malloc ( sizeof ( GLfloat ) * 3 * numVertices );
}
if ( normals != NULL )
{
*normals = malloc ( sizeof ( GLfloat ) * 3 * numVertices );
}
if ( texCoords != NULL )
{
*texCoords = malloc ( sizeof ( GLfloat ) * 2 * numVertices );
}
if ( indices != NULL )
{
*indices = malloc ( sizeof ( GLuint ) * numIndices );
}
for ( i = 0; i < numParallels + 1; i++ )
{
for ( j = 0; j < numSlices + 1; j++ )
{
int vertex = ( i * ( numSlices + 1 ) + j ) * 3;
if ( vertices )
{
( *vertices ) [vertex + 0] = radius * sinf ( angleStep * ( float ) i ) *
sinf ( angleStep * ( float ) j );
( *vertices ) [vertex + 1] = radius * cosf ( angleStep * ( float ) i );
( *vertices ) [vertex + 2] = radius * sinf ( angleStep * ( float ) i ) *
cosf ( angleStep * ( float ) j );
}
if ( normals )
{
( *normals ) [vertex + 0] = ( *vertices ) [vertex + 0] / radius;
( *normals ) [vertex + 1] = ( *vertices ) [vertex + 1] / radius;
( *normals ) [vertex + 2] = ( *vertices ) [vertex + 2] / radius;
}
if ( texCoords )
{
int texIndex = ( i * ( numSlices + 1 ) + j ) * 2;
( *texCoords ) [texIndex + 0] = ( float ) j / ( float ) numSlices;
( *texCoords ) [texIndex + 1] = ( 1.0f - ( float ) i ) / ( float ) ( numParallels - 1 );
}
}
}
// Generate the indices
if ( indices != NULL )
{
GLuint *indexBuf = ( *indices );
for ( i = 0; i < numParallels ; i++ )
{
for ( j = 0; j < numSlices; j++ )
{
*indexBuf++ = i * ( numSlices + 1 ) + j;
*indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + j;
*indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
*indexBuf++ = i * ( numSlices + 1 ) + j;
*indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
*indexBuf++ = i * ( numSlices + 1 ) + ( j + 1 );
}
}
}
return numIndices;
}
//
/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores
/// the results in the arrays. Generate index list for a TRIANGLES
/// \param scale The size of the cube, use 1.0 for a unit cube.
/// \param vertices If not NULL, will contain array of float3 positions
/// \param normals If not NULL, will contain array of float3 normals
/// \param texCoords If not NULL, will contain array of float2 texCoords
/// \param indices If not NULL, will contain the array of indices for the triangle strip
/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
/// if it is not NULL ) as a GL_TRIANGLE_STRIP
//
int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals,
GLfloat **texCoords, GLuint **indices )
{
int i;
int numVertices = 24;
int numIndices = 36;
GLfloat cubeVerts[] =
{
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
};
GLfloat cubeNormals[] =
{
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, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.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,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.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, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
};
GLfloat cubeTex[] =
{
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
};
// Allocate memory for buffers
if ( vertices != NULL )
{
*vertices = malloc ( sizeof ( GLfloat ) * 3 * numVertices );
memcpy ( *vertices, cubeVerts, sizeof ( cubeVerts ) );
for ( i = 0; i < numVertices * 3; i++ )
{
( *vertices ) [i] *= scale;
}
}
if ( normals != NULL )
{
*normals = malloc ( sizeof ( GLfloat ) * 3 * numVertices );
memcpy ( *normals, cubeNormals, sizeof ( cubeNormals ) );
}
if ( texCoords != NULL )
{
*texCoords = malloc ( sizeof ( GLfloat ) * 2 * numVertices );
memcpy ( *texCoords, cubeTex, sizeof ( cubeTex ) ) ;
}
// Generate the indices
if ( indices != NULL )
{
GLuint cubeIndices[] =
{
0, 2, 1,
0, 3, 2,
4, 5, 6,
4, 6, 7,
8, 9, 10,
8, 10, 11,
12, 15, 14,
12, 14, 13,
16, 17, 18,
16, 18, 19,
20, 23, 22,
20, 22, 21
};
*indices = malloc ( sizeof ( GLuint ) * numIndices );
memcpy ( *indices, cubeIndices, sizeof ( cubeIndices ) );
}
return numIndices;
}
//
/// \brief Generates a square grid consisting of triangles. Allocates memory for the vertex data and stores
/// the results in the arrays. Generate index list as TRIANGLES.
/// \param size create a grid of size by size (number of triangles = (size-1)*(size-1)*2)
/// \param vertices If not NULL, will contain array of float3 positions
/// \param indices If not NULL, will contain the array of indices for the triangle strip
/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
/// if it is not NULL ) as a GL_TRIANGLES
//
int ESUTIL_API esGenSquareGrid ( int size, GLfloat **vertices, GLuint **indices )
{
int i, j;
int numIndices = ( size - 1 ) * ( size - 1 ) * 2 * 3;
// Allocate memory for buffers
if ( vertices != NULL )
{
int numVertices = size * size;
float stepSize = ( float ) size - 1;
*vertices = malloc ( sizeof ( GLfloat ) * 3 * numVertices );
for ( i = 0; i < size; ++i ) // row
{
for ( j = 0; j < size; ++j ) // column
{
( *vertices ) [ 3 * ( j + i * size ) ] = i / stepSize;
( *vertices ) [ 3 * ( j + i * size ) + 1 ] = j / stepSize;
( *vertices ) [ 3 * ( j + i * size ) + 2 ] = 0.0f;
}
}
}
// Generate the indices
if ( indices != NULL )
{
*indices = malloc ( sizeof ( GLuint ) * numIndices );
for ( i = 0; i < size - 1; ++i )
{
for ( j = 0; j < size - 1; ++j )
{
// two triangles per quad
( *indices ) [ 6 * ( j + i * ( size - 1 ) ) ] = j + ( i ) * ( size ) ;
( *indices ) [ 6 * ( j + i * ( size - 1 ) ) + 1 ] = j + ( i ) * ( size ) + 1;
( *indices ) [ 6 * ( j + i * ( size - 1 ) ) + 2 ] = j + ( i + 1 ) * ( size ) + 1;
( *indices ) [ 6 * ( j + i * ( size - 1 ) ) + 3 ] = j + ( i ) * ( size ) ;
( *indices ) [ 6 * ( j + i * ( size - 1 ) ) + 4 ] = j + ( i + 1 ) * ( size ) + 1;
( *indices ) [ 6 * ( j + i * ( size - 1 ) ) + 5 ] = j + ( i + 1 ) * ( size ) ;
}
}
}
return numIndices;
}

View File

@@ -1,314 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Book: OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
// Authors: Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
// ISBN-10: 0-321-93388-5
// ISBN-13: 978-0-321-93388-1
// Publisher: Addison-Wesley Professional
// URLs: http://www.opengles-book.com
// http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
//
// ESUtil.c
//
// A utility library for OpenGL ES. This library provides a
// basic common framework for the example applications in the
// OpenGL ES 3.0 Programming Guide.
//
///
// Includes
//
#include "esUtil.h"
#include <math.h>
#include <string.h>
#define PI 3.1415926535897932384626433832795f
void ESUTIL_API
esScale ( ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz )
{
result->m[0][0] *= sx;
result->m[0][1] *= sx;
result->m[0][2] *= sx;
result->m[0][3] *= sx;
result->m[1][0] *= sy;
result->m[1][1] *= sy;
result->m[1][2] *= sy;
result->m[1][3] *= sy;
result->m[2][0] *= sz;
result->m[2][1] *= sz;
result->m[2][2] *= sz;
result->m[2][3] *= sz;
}
void ESUTIL_API
esTranslate ( ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz )
{
result->m[3][0] += ( result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz );
result->m[3][1] += ( result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz );
result->m[3][2] += ( result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz );
result->m[3][3] += ( result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz );
}
void ESUTIL_API
esRotate ( ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
{
GLfloat sinAngle, cosAngle;
GLfloat mag = sqrtf ( x * x + y * y + z * z );
sinAngle = sinf ( angle * PI / 180.0f );
cosAngle = cosf ( angle * PI / 180.0f );
if ( mag > 0.0f )
{
GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
GLfloat oneMinusCos;
ESMatrix rotMat;
x /= mag;
y /= mag;
z /= mag;
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;
rotMat.m[0][0] = ( oneMinusCos * xx ) + cosAngle;
rotMat.m[0][1] = ( oneMinusCos * xy ) - zs;
rotMat.m[0][2] = ( oneMinusCos * zx ) + ys;
rotMat.m[0][3] = 0.0F;
rotMat.m[1][0] = ( oneMinusCos * xy ) + zs;
rotMat.m[1][1] = ( oneMinusCos * yy ) + cosAngle;
rotMat.m[1][2] = ( oneMinusCos * yz ) - xs;
rotMat.m[1][3] = 0.0F;
rotMat.m[2][0] = ( oneMinusCos * zx ) - ys;
rotMat.m[2][1] = ( oneMinusCos * yz ) + xs;
rotMat.m[2][2] = ( oneMinusCos * zz ) + cosAngle;
rotMat.m[2][3] = 0.0F;
rotMat.m[3][0] = 0.0F;
rotMat.m[3][1] = 0.0F;
rotMat.m[3][2] = 0.0F;
rotMat.m[3][3] = 1.0F;
esMatrixMultiply ( result, &rotMat, result );
}
}
void ESUTIL_API
esFrustum ( ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ )
{
float deltaX = right - left;
float deltaY = top - bottom;
float deltaZ = farZ - nearZ;
ESMatrix frust;
if ( ( nearZ <= 0.0f ) || ( farZ <= 0.0f ) ||
( deltaX <= 0.0f ) || ( deltaY <= 0.0f ) || ( deltaZ <= 0.0f ) )
{
return;
}
frust.m[0][0] = 2.0f * nearZ / deltaX;
frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
frust.m[1][1] = 2.0f * nearZ / deltaY;
frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
frust.m[2][0] = ( right + left ) / deltaX;
frust.m[2][1] = ( top + bottom ) / deltaY;
frust.m[2][2] = - ( nearZ + farZ ) / deltaZ;
frust.m[2][3] = -1.0f;
frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
esMatrixMultiply ( result, &frust, result );
}
void ESUTIL_API
esPerspective ( ESMatrix *result, float fovy, float aspect, float nearZ, float farZ )
{
GLfloat frustumW, frustumH;
frustumH = tanf ( fovy / 360.0f * PI ) * nearZ;
frustumW = frustumH * aspect;
esFrustum ( result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ );
}
void ESUTIL_API
esOrtho ( ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ )
{
float deltaX = right - left;
float deltaY = top - bottom;
float deltaZ = farZ - nearZ;
ESMatrix ortho;
if ( ( deltaX == 0.0f ) || ( deltaY == 0.0f ) || ( deltaZ == 0.0f ) )
{
return;
}
esMatrixLoadIdentity ( &ortho );
ortho.m[0][0] = 2.0f / deltaX;
ortho.m[3][0] = - ( right + left ) / deltaX;
ortho.m[1][1] = 2.0f / deltaY;
ortho.m[3][1] = - ( top + bottom ) / deltaY;
ortho.m[2][2] = -2.0f / deltaZ;
ortho.m[3][2] = - ( nearZ + farZ ) / deltaZ;
esMatrixMultiply ( result, &ortho, result );
}
void ESUTIL_API
esMatrixMultiply ( ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB )
{
ESMatrix tmp;
int i;
for ( i = 0; i < 4; i++ )
{
tmp.m[i][0] = ( srcA->m[i][0] * srcB->m[0][0] ) +
( srcA->m[i][1] * srcB->m[1][0] ) +
( srcA->m[i][2] * srcB->m[2][0] ) +
( srcA->m[i][3] * srcB->m[3][0] ) ;
tmp.m[i][1] = ( srcA->m[i][0] * srcB->m[0][1] ) +
( srcA->m[i][1] * srcB->m[1][1] ) +
( srcA->m[i][2] * srcB->m[2][1] ) +
( srcA->m[i][3] * srcB->m[3][1] ) ;
tmp.m[i][2] = ( srcA->m[i][0] * srcB->m[0][2] ) +
( srcA->m[i][1] * srcB->m[1][2] ) +
( srcA->m[i][2] * srcB->m[2][2] ) +
( srcA->m[i][3] * srcB->m[3][2] ) ;
tmp.m[i][3] = ( srcA->m[i][0] * srcB->m[0][3] ) +
( srcA->m[i][1] * srcB->m[1][3] ) +
( srcA->m[i][2] * srcB->m[2][3] ) +
( srcA->m[i][3] * srcB->m[3][3] ) ;
}
memcpy ( result, &tmp, sizeof ( ESMatrix ) );
}
void ESUTIL_API
esMatrixLoadIdentity ( ESMatrix *result )
{
memset ( result, 0x0, sizeof ( ESMatrix ) );
result->m[0][0] = 1.0f;
result->m[1][1] = 1.0f;
result->m[2][2] = 1.0f;
result->m[3][3] = 1.0f;
}
void ESUTIL_API
esMatrixLookAt ( ESMatrix *result,
float posX, float posY, float posZ,
float lookAtX, float lookAtY, float lookAtZ,
float upX, float upY, float upZ )
{
float axisX[3], axisY[3], axisZ[3];
float length;
// axisZ = lookAt - pos
axisZ[0] = lookAtX - posX;
axisZ[1] = lookAtY - posY;
axisZ[2] = lookAtZ - posZ;
// normalize axisZ
length = sqrtf ( axisZ[0] * axisZ[0] + axisZ[1] * axisZ[1] + axisZ[2] * axisZ[2] );
if ( length != 0.0f )
{
axisZ[0] /= length;
axisZ[1] /= length;
axisZ[2] /= length;
}
// axisX = up X axisZ
axisX[0] = upY * axisZ[2] - upZ * axisZ[1];
axisX[1] = upZ * axisZ[0] - upX * axisZ[2];
axisX[2] = upX * axisZ[1] - upY * axisZ[0];
// normalize axisX
length = sqrtf ( axisX[0] * axisX[0] + axisX[1] * axisX[1] + axisX[2] * axisX[2] );
if ( length != 0.0f )
{
axisX[0] /= length;
axisX[1] /= length;
axisX[2] /= length;
}
// axisY = axisZ x axisX
axisY[0] = axisZ[1] * axisX[2] - axisZ[2] * axisX[1];
axisY[1] = axisZ[2] * axisX[0] - axisZ[0] * axisX[2];
axisY[2] = axisZ[0] * axisX[1] - axisZ[1] * axisX[0];
// normalize axisY
length = sqrtf ( axisY[0] * axisY[0] + axisY[1] * axisY[1] + axisY[2] * axisY[2] );
if ( length != 0.0f )
{
axisY[0] /= length;
axisY[1] /= length;
axisY[2] /= length;
}
memset ( result, 0x0, sizeof ( ESMatrix ) );
result->m[0][0] = -axisX[0];
result->m[0][1] = axisY[0];
result->m[0][2] = -axisZ[0];
result->m[1][0] = -axisX[1];
result->m[1][1] = axisY[1];
result->m[1][2] = -axisZ[1];
result->m[2][0] = -axisX[2];
result->m[2][1] = axisY[2];
result->m[2][2] = -axisZ[2];
// translate (-posX, -posY, -posZ)
result->m[3][0] = axisX[0] * posX + axisX[1] * posY + axisX[2] * posZ;
result->m[3][1] = -axisY[0] * posX - axisY[1] * posY - axisY[2] * posZ;
result->m[3][2] = axisZ[0] * posX + axisZ[1] * posY + axisZ[2] * posZ;
result->m[3][3] = 1.0f;
}

View File

@@ -1,325 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2013 Dan Ginsburg, Budirijanto Purnomo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Book: OpenGL(R) ES 3.0 Programming Guide, 2nd Edition
// Authors: Dan Ginsburg, Budirijanto Purnomo, Dave Shreiner, Aaftab Munshi
// ISBN-10: 0-321-93388-5
// ISBN-13: 978-0-321-93388-1
// Publisher: Addison-Wesley Professional
// URLs: http://www.opengles-book.com
// http://my.safaribooksonline.com/book/animation-and-3d/9780133440133
//
//
/// \file ESUtil.h
/// \brief A utility library for OpenGL ES. This library provides a
/// basic common framework for the example applications in the
/// OpenGL ES 3.0 Programming Guide.
//
#ifndef ESUTIL_H
#define ESUTIL_H
///
// Includes
//
#include <stdlib.h>
#ifdef __APPLE__
#include <OpenGLES/ES3/gl.h>
#else
#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
///
// Macros
//
#ifdef WIN32
#define ESUTIL_API __cdecl
#define ESCALLBACK __cdecl
#else
#define ESUTIL_API
#define ESCALLBACK
#endif
typedef struct
{
GLfloat m[4][4];
} ESMatrix;
typedef struct ESContext ESContext;
struct ESContext
{
/// Put platform specific data here
void *platformData;
/// Put your user data here...
void *userData;
/// Window width
GLint width;
/// Window height
GLint height;
#ifndef __APPLE__
/// Display handle
EGLNativeDisplayType eglNativeDisplay;
/// Window handle
EGLNativeWindowType eglNativeWindow;
/// EGL display
EGLDisplay eglDisplay;
/// EGL context
EGLContext eglContext;
/// EGL surface
EGLSurface eglSurface;
#endif
/// Callbacks
void ( ESCALLBACK *drawFunc ) ( ESContext * );
void ( ESCALLBACK *shutdownFunc ) ( ESContext * );
void ( ESCALLBACK *keyFunc ) ( ESContext *, unsigned char, int, int );
void ( ESCALLBACK *updateFunc ) ( ESContext *, float deltaTime );
};
///
// Public Functions
//
//
/// \brief Create a window with the specified parameters
/// \param esContext Application context
/// \param title Name for title bar of window
/// \param width Width in pixels of window to create
/// \param height Height in pixels of window to create
/// \param flags Bitfield for the window creation flags
/// ES_WINDOW_RGB - specifies that the color buffer should have R,G,B channels
/// ES_WINDOW_ALPHA - specifies that the color buffer should have alpha
/// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
/// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
/// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
/// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise
GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char *title, GLint width, GLint height, GLuint flags );
//
/// \brief Register a draw callback function to be used to render each frame
/// \param esContext Application context
/// \param drawFunc Draw callback function that will be used to render the scene
//
void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void ( ESCALLBACK *drawFunc ) ( ESContext * ) );
//
/// \brief Register a callback function to be called on shutdown
/// \param esContext Application context
/// \param shutdownFunc Shutdown callback function
//
void ESUTIL_API esRegisterShutdownFunc ( ESContext *esContext, void ( ESCALLBACK *shutdownFunc ) ( ESContext * ) );
//
/// \brief Register an update callback function to be used to update on each time step
/// \param esContext Application context
/// \param updateFunc Update callback function that will be used to render the scene
//
void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void ( ESCALLBACK *updateFunc ) ( ESContext *, float ) );
//
/// \brief Register an keyboard input processing callback function
/// \param esContext Application context
/// \param keyFunc Key callback function for application processing of keyboard input
//
void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
void ( ESCALLBACK *drawFunc ) ( ESContext *, unsigned char, int, int ) );
//
/// \brief Log a message to the debug output for the platform
/// \param formatStr Format string for error log.
//
#ifdef __ANDROID__
#include <android/log.h>
#define esLogMessage(...) __android_log_print(ANDROID_LOG_INFO, "Test-GLES3", __VA_ARGS__)
#else
void ESUTIL_API esLogMessage ( const char *formatStr, ... );
#endif
//
///
/// \brief Load a shader, check for compile errors, print error messages to output log
/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
/// \param shaderSrc Shader source string
/// \return A new shader object on success, 0 on failure
//
GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc );
//
///
/// \brief Load a vertex and fragment shader, create a program object, link program.
/// Errors output to log.
/// \param vertShaderSrc Vertex shader source code
/// \param fragShaderSrc Fragment shader source code
/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
//
GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc );
//
/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores
/// the results in the arrays. Generate index list for a TRIANGLE_STRIP
/// \param numSlices The number of slices in the sphere
/// \param vertices If not NULL, will contain array of float3 positions
/// \param normals If not NULL, will contain array of float3 normals
/// \param texCoords If not NULL, will contain array of float2 texCoords
/// \param indices If not NULL, will contain the array of indices for the triangle strip
/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
/// if it is not NULL ) as a GL_TRIANGLE_STRIP
//
int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals,
GLfloat **texCoords, GLuint **indices );
//
/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores
/// the results in the arrays. Generate index list for a TRIANGLES
/// \param scale The size of the cube, use 1.0 for a unit cube.
/// \param vertices If not NULL, will contain array of float3 positions
/// \param normals If not NULL, will contain array of float3 normals
/// \param texCoords If not NULL, will contain array of float2 texCoords
/// \param indices If not NULL, will contain the array of indices for the triangle strip
/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
/// if it is not NULL ) as a GL_TRIANGLES
//
int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals,
GLfloat **texCoords, GLuint **indices );
//
/// \brief Generates a square grid consisting of triangles. Allocates memory for the vertex data and stores
/// the results in the arrays. Generate index list as TRIANGLES.
/// \param size create a grid of size by size (number of triangles = (size-1)*(size-1)*2)
/// \param vertices If not NULL, will contain array of float3 positions
/// \param indices If not NULL, will contain the array of indices for the triangle strip
/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
/// if it is not NULL ) as a GL_TRIANGLES
//
int ESUTIL_API esGenSquareGrid ( int size, GLfloat **vertices, GLuint **indices );
//
/// \brief Loads a 8-bit, 24-bit or 32-bit TGA image from a file
/// \param ioContext Context related to IO facility on the platform
/// \param fileName Name of the file on disk
/// \param width Width of loaded image in pixels
/// \param height Height of loaded image in pixels
/// \return Pointer to loaded image. NULL on failure.
//
char *ESUTIL_API esLoadTGA ( void *ioContext, const char *fileName, int *width, int *height );
//
/// \brief multiply matrix specified by result with a scaling matrix and return new matrix in result
/// \param result Specifies the input matrix. Scaled matrix is returned in result.
/// \param sx, sy, sz Scale factors along the x, y and z axes respectively
//
void ESUTIL_API esScale ( ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz );
//
/// \brief multiply matrix specified by result with a translation matrix and return new matrix in result
/// \param result Specifies the input matrix. Translated matrix is returned in result.
/// \param tx, ty, tz Scale factors along the x, y and z axes respectively
//
void ESUTIL_API esTranslate ( ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz );
//
/// \brief multiply matrix specified by result with a rotation matrix and return new matrix in result
/// \param result Specifies the input matrix. Rotated matrix is returned in result.
/// \param angle Specifies the angle of rotation, in degrees.
/// \param x, y, z Specify the x, y and z coordinates of a vector, respectively
//
void ESUTIL_API esRotate ( ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z );
//
// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
/// \param result Specifies the input matrix. new matrix is returned in result.
/// \param left, right Coordinates for the left and right vertical clipping planes
/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
/// \param nearZ, farZ Distances to the near and far depth clipping planes. Both distances must be positive.
//
void ESUTIL_API esFrustum ( ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ );
//
/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
/// \param result Specifies the input matrix. new matrix is returned in result.
/// \param fovy Field of view y angle in degrees
/// \param aspect Aspect ratio of screen
/// \param nearZ Near plane distance
/// \param farZ Far plane distance
//
void ESUTIL_API esPerspective ( ESMatrix *result, float fovy, float aspect, float nearZ, float farZ );
//
/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
/// \param result Specifies the input matrix. new matrix is returned in result.
/// \param left, right Coordinates for the left and right vertical clipping planes
/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
/// \param nearZ, farZ Distances to the near and far depth clipping planes. These values are negative if plane is behind the viewer
//
void ESUTIL_API esOrtho ( ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ );
//
/// \brief perform the following operation - result matrix = srcA matrix * srcB matrix
/// \param result Returns multiplied matrix
/// \param srcA, srcB Input matrices to be multiplied
//
void ESUTIL_API esMatrixMultiply ( ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB );
//
//// \brief return an indentity matrix
//// \param result returns identity matrix
//
void ESUTIL_API esMatrixLoadIdentity ( ESMatrix *result );
//
/// \brief Generate a transformation matrix from eye position, look at and up vectors
/// \param result Returns transformation matrix
/// \param posX, posY, posZ eye position
/// \param lookAtX, lookAtY, lookAtZ look at vector
/// \param upX, upY, upZ up vector
//
void ESUTIL_API
esMatrixLookAt ( ESMatrix *result,
float posX, float posY, float posZ,
float lookAtX, float lookAtY, float lookAtZ,
float upX, float upY, float upZ );
#ifdef __cplusplus
}
#endif
#endif // ESUTIL_H

View File

@@ -1,10 +1,12 @@
#include <string>
#include <vector>
#include <stdio.h>
#include <GLES3/gl3.h>
#include <SDL.h>
#include <SDL_image.h>
#include "esUtil.h"
#ifdef __ANDROID__
#include <android/log.h>
#define printf(...) __android_log_print(ANDROID_LOG_INFO, "Test-GLES3", __VA_ARGS__)
@@ -30,36 +32,166 @@ static void initSDL()
SDL_Quit();
exit(2);
}
SDL_WM_SetCaption("test", "test");
}
void loadShaders()
static GLuint loadShader ( GLenum type, const char *shaderSrc )
{
char vShaderStr[] =
"#version 300 es \n"
"precision mediump float; \n"
"layout(location = 0) in vec4 a_position; \n"
"layout(location = 1) in vec2 a_texCoord; \n"
"out vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
GLuint shader;
GLint compiled;
char fShaderStr[] =
// Create the shader object
shader = glCreateShader ( type );
if ( shader == 0 )
{
return 0;
}
// Load the shader source
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader
glCompileShader ( shader );
// Check the compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled )
{
GLint infoLen = 0;
glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char *infoLog = (char *) malloc ( sizeof ( char ) * infoLen );
glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
printf ( "===========> Error compiling shader:\n");
printf ( "===========> %s\n", infoLog );
free ( infoLog );
}
glDeleteShader ( shader );
return 0;
}
return shader;
}
static GLuint loadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
{
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = loadShader ( GL_VERTEX_SHADER, vertShaderSrc );
if ( vertexShader == 0 )
{
return 0;
}
fragmentShader = loadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
if ( fragmentShader == 0 )
{
glDeleteShader ( vertexShader );
return 0;
}
// Create the program object
programObject = glCreateProgram ( );
if ( programObject == 0 )
{
return 0;
}
glAttachShader ( programObject, vertexShader );
glAttachShader ( programObject, fragmentShader );
// Link the program
glLinkProgram ( programObject );
// Check the link status
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
if ( !linked )
{
GLint infoLen = 0;
glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char *infoLog = (char *) malloc ( sizeof ( char ) * infoLen );
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
printf ( "===========> Error linking program:\n" );
printf ( "===========> %s\n", infoLog );
free ( infoLog );
}
glDeleteProgram ( programObject );
return 0;
}
// Free up no longer needed shader resources
glDeleteShader ( vertexShader );
glDeleteShader ( fragmentShader );
return programObject;
}
static void initShaders()
{
char *vertexShaderStr = NULL;
asprintf( &vertexShaderStr,
"#version 300 es \n"
"precision mediump float; \n"
"in vec2 v_texCoord; \n"
"layout(location = 0) out vec4 outColor; \n"
"const mediump float screenWidthDiv = 2.0 / %d.0; \n"
"const mediump float screenHeightDiv = 2.0 / %d.0; \n"
"layout(location = 0) in mediump vec2 a_position; \n"
"layout(location = 1) in mediump vec2 a_texCoord; \n"
"out mediump vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = vec4( \n"
" a_position.x * screenWidthDiv - 1.0f, \n"
" 1.0f - a_position.y * screenHeightDiv, \n"
" 0, 1); \n"
" v_texCoord = a_texCoord; \n"
"} \n"
, screenWidth, screenHeight );
const char *fragmentShaderStr =
"#version 300 es \n"
"in mediump vec2 v_texCoord; \n"
"layout(location = 0) out lowp vec4 outColor; \n"
"uniform sampler2D s_texture; \n"
"void main() \n"
"{ \n"
" outColor = texture( s_texture, v_texCoord ); \n"
"} \n";
printf("initShaders(): vertex shader:\n%s\n", vertexShaderStr);
printf("initShaders(): fragment shader:\n%s\n", fragmentShaderStr);
// Load the shaders and get a linked program object
drawTextureProgram = esLoadProgram ( vShaderStr, fShaderStr );
drawTextureProgram = loadProgram ( vertexShaderStr, fragmentShaderStr );
if (drawTextureProgram == 0)
{
printf("Could not init shaders\n");
SDL_Quit();
exit(2);
}
free(vertexShaderStr);
// Get the sampler location
drawTextureSamplerLocation = glGetUniformLocation ( drawTextureProgram, "s_texture" );
@@ -75,7 +207,7 @@ static void initGL()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture ( GL_TEXTURE0 );
loadShaders();
initShaders();
}
static void clearScreen()
@@ -85,10 +217,12 @@ static void clearScreen()
struct Sprite {
Sprite(const char * path)
Sprite(const char * path, GLint wrap = GL_CLAMP_TO_EDGE)
{
w = h = texture = 0;
imagePath = path;
textureWrap = wrap;
loadTexture();
}
@@ -116,39 +250,19 @@ struct Sprite {
// GLES3 always supports non-power-of-two textures, no need to recalculate texture dimensions
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, w, h, 0, glFormat, GL_UNSIGNED_BYTE, pic->pixels);
SDL_FreeSurface(pic);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
disableRepeat();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrap);
return true;
}
void disableRepeat()
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
void enableRepeat()
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
void enableMirroredRepeat()
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
}
void draw(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLfloat tex_x1 = 0.0f, GLfloat tex_y1 = 0.0f, GLfloat tex_x2 = 1.0f, GLfloat tex_y2 = 1.0f)
{
if (texture == 0)
@@ -157,14 +271,14 @@ struct Sprite {
glUseProgram( drawTextureProgram );
GLfloat coords[] = {
x, y, // Position 0
tex_x1, tex_y1, // TexCoord 0
x, y + width, // Position 1
tex_x1, tex_y2, // TexCoord 1
x + height, y + width, // Position 2
tex_x2, tex_y2, // TexCoord 2
x + height, y, // Position 3
tex_x2, tex_y1 // TexCoord 3
x, y, // Position 0
tex_x1, tex_y1, // TexCoord 0
x, y + height, // Position 1
tex_x1, tex_y2, // TexCoord 1
x + width, y + height, // Position 2
tex_x2, tex_y2, // TexCoord 2
x + width, y, // Position 3
tex_x2, tex_y1 // TexCoord 3
};
// Load the vertex position
@@ -191,6 +305,7 @@ struct Sprite {
GLuint texture;
int w, h;
std::string imagePath;
GLint textureWrap;
};
int
@@ -205,10 +320,10 @@ main(int argc, char *argv[])
sprites.push_back(Sprite("element1.png"));
sprites.push_back(Sprite("element2.png"));
sprites.push_back(Sprite("element3.png"));
sprites.push_back(Sprite("stars.jpg"));
sprites.back().enableMirroredRepeat(); // Looks nice
//sprites.push_back(Sprite("stars.jpg", GL_REPEAT)); // Repeating tiles
sprites.push_back(Sprite("stars.jpg", GL_MIRRORED_REPEAT)); // Looks nice
int coords[][2] = { {0, 0},
float coords[][2] = { {0, 0},
{200, 0},
{300, 200},
{400, 300} };
@@ -219,7 +334,11 @@ main(int argc, char *argv[])
while ( ! SDL_GetKeyState(NULL)[SDLK_ESCAPE] ) // Exit by pressing Back button
{
// clearScreen(); // Do not clear screen, we will fill the screens with tiled background image instead
sprites[5].draw(0, 0, screenWidth, screenHeight, 0, 0, (float) screenWidth / sprites[5].w, (float) screenHeight / sprites[5].h);
sprites[5].draw(0, 0, screenWidth, screenHeight,
coords[0][0] / sprites[5].w * 3,
coords[0][0] / sprites[5].h * 2,
coords[0][0] / sprites[5].w * 3 + (float) screenWidth / sprites[5].w,
coords[0][0] / sprites[5].h * 2 + (float) screenHeight / sprites[5].h);
int mouseX = 0, mouseY = 0, buttons = 0;
buttons = SDL_GetMouseState(&mouseX, &mouseY);
@@ -230,6 +349,12 @@ main(int argc, char *argv[])
sprites[3].draw(coords[2][0], coords[2][1], sprites[3].w * pulse * 4, sprites[3].h * 2);
sprites[4].draw(coords[3][0], coords[3][1], sprites[4].w, sprites[4].h * pulse * 2);
sprites[1].draw(screenWidth / 2.0f - sprites[1].w / 2.0f, screenHeight / 2.0f - sprites[1].h / 2.0f);
sprites[1].draw(0 - sprites[1].w / 2.0f, 0 - sprites[1].h / 2.0f);
sprites[1].draw(screenWidth - sprites[1].w / 2.0f, screenHeight - sprites[1].h / 2.0f);
sprites[1].draw(0 - sprites[1].w / 2.0f, screenHeight - sprites[1].h / 2.0f);
sprites[1].draw(screenWidth - sprites[1].w / 2.0f, 0 - sprites[1].h / 2.0f);
SDL_GL_SwapBuffers();
SDL_Event event;
while( SDL_PollEvent(&event) )