meta-digi/meta-digi-dey/recipes-digi/dey-examples/dey-examples-opengles/ccimx5/opengles/es20_example.c

480 lines
12 KiB
C

/*
* es20_example.c
*
* Based on example code from Freescale's GPU SDK.
* (ported to ConnectCore Wi-i.MX51 by Digi International Inc '10)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Description: Rotating textured 3D object (using OpenGL ES 2.0)
*
*/
#define EGL_USE_GLES2
#include <assert.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <FSL/fslutil.h>
#include <GLES2/gl2.h>
#define TRUE 1
#define FALSE !TRUE
EGLDisplay egldisplay;
EGLConfig eglconfig;
EGLSurface eglsurface;
EGLContext eglcontext;
int currentFrame = 0;
GLuint g_hShaderProgram = 0;
GLuint g_hModelViewMatrixLoc = 0;
GLuint g_hProjMatrixLoc = 0;
GLuint g_hVertexLoc = 0;
GLuint g_hVertexTexLoc = 2;
GLuint g_hColorLoc = 1;
//--------------------------------------------------------------------------------------
// Name: g_strVertexShader / g_strFragmentShader
// Desc: The vertex and fragment shader programs
//--------------------------------------------------------------------------------------
const char *g_strVertexShader =
"uniform mat4 g_matModelView; \n"
"uniform mat4 g_matProj; \n"
" \n"
"attribute vec4 g_vPosition; \n"
"attribute vec3 g_vColor; \n"
"attribute vec2 g_vTexCoord; \n"
" \n"
"varying vec3 g_vVSColor; \n"
"varying vec2 g_vVSTexCoord; \n"
" \n"
"void main() \n"
"{ \n"
" vec4 vPositionES = g_matModelView * g_vPosition; \n"
" gl_Position = g_matProj * vPositionES; \n"
" g_vVSColor = g_vColor; \n"
" g_vVSTexCoord = g_vTexCoord; \n"
"} \n";
const char *g_strFragmentShader =
"#ifdef GL_FRAGMENT_PRECISION_HIGH \n"
" precision highp float; \n"
"#else \n"
" precision mediump float; \n"
"#endif \n"
" \n"
"uniform sampler2D s_texture; \n"
"varying vec3 g_vVSColor; \n"
"varying vec2 g_vVSTexCoord; \n"
" \n"
"void main() \n"
"{ \n"
" gl_FragColor = texture2D(s_texture,g_vVSTexCoord); \n"
"} \n";
float VertexPositions[] = {
/* Draw A Quad */
/* Top Right Of The Quad (Top) */
1.0f, 1.0f, -1.0f,
/* Top Left Of The Quad (Top) */
-1.0f, 1.0f, -1.0f,
/* Bottom Right Of The Quad (Top) */
1.0f, 1.0f, 1.0f,
/* Bottom Left Of The Quad (Top) */
-1.0f, 1.0f, 1.0f,
/* Top Right Of The Quad (Bottom) */
1.0f, -1.0f, 1.0f,
/* Top Left Of The Quad (Bottom) */
-1.0f, -1.0f, 1.0f,
/* Bottom Right Of The Quad (Bottom) */
1.0f, -1.0f, -1.0f,
/* Bottom Left Of The Quad (Bottom) */
-1.0f, -1.0f, -1.0f,
/* Top Right Of The Quad (Front) */
1.0f, 1.0f, 1.0f,
/* Top Left Of The Quad (Front) */
-1.0f, 1.0f, 1.0f,
/* Bottom Right Of The Quad (Front) */
1.0f, -1.0f, 1.0f,
/* Bottom Left Of The Quad (Front) */
-1.0f, -1.0f, 1.0f,
/* Top Right Of The Quad (Back) */
1.0f, -1.0f, -1.0f,
/* Top Left Of The Quad (Back) */
-1.0f, -1.0f, -1.0f,
/* Bottom Right Of The Quad (Back) */
1.0f, 1.0f, -1.0f,
/* Bottom Left Of The Quad (Back) */
-1.0f, 1.0f, -1.0f,
/* Top Right Of The Quad (Left) */
-1.0f, 1.0f, 1.0f,
/* Top Left Of The Quad (Left) */
-1.0f, 1.0f, -1.0f,
/* Bottom Right Of The Quad (Left) */
-1.0f, -1.0f, 1.0f,
/* Bottom Left Of The Quad (Left) */
-1.0f, -1.0f, -1.0f,
/* Top Right Of The Quad (Right) */
1.0f, 1.0f, -1.0f,
/* Top Left Of The Quad (Right) */
1.0f, 1.0f, 1.0f,
/* Bottom Right Of The Quad (Right) */
1.0f, -1.0f, -1.0f,
/* Bottom Left Of The Quad (Right) */
1.0f, -1.0f, 1.0f
};
float VertexTexCoords[] = {
/* Top Face */
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
/* Bottom Face */
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
/* Front Face */
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
/* Back Face */
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
/*left face */
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
/* Right face */
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
};
float VertexColors[] = {
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Red */
1.0f, 0.0, 0.0f, 1.0f,
/* Red */
1.0f, 0.0, 0.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Blue */
0.0f, 0.0f, 1.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f
};
GLuint texture[1]; /* Storage For One Texture ( NEW ) */
/* function to load in bitmap as a GL texture */
int LoadGLTextures()
{
Image *image1;
// allocate space for texture we will use
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
return 0;
}
/* Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit */
if (ImageLoad("texture.bmp", image1)) {
/* Create The Texture */
glGenTextures(1, texture);
/* Typical Texture Generation Using Data From The Bitmap */
glBindTexture(GL_TEXTURE_2D, *texture);
/* Generate The Texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB,
GL_UNSIGNED_BYTE, image1->data);
/* Linear Filtering */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
printf("texture loaded and created successfully");
} else {
return 0;
}
/* Free up any memory we may have used */
if (image1 != NULL) {
free(image1);
}
return 1;
}
void render(float w, float h)
{
static float fAngle = 0.0f;
fAngle += 0.01f;
// Rotate and translate the model view matrix
float matModelView[16] = { 0 };
matModelView[0] = +cosf(fAngle);
matModelView[2] = +sinf(fAngle);
matModelView[5] = 1.0f;
matModelView[8] = -sinf(fAngle);
matModelView[10] = +cosf(fAngle);
matModelView[12] = 0.0f; //X
matModelView[14] = -6.0f; //z
matModelView[15] = 1.0f;
// Build a perspective projection matrix
float matProj[16] = { 0 };
matProj[0] = cosf(0.5f) / sinf(0.5f);
matProj[5] = matProj[0] * (w / h);
matProj[10] = -(10.0f) / (9.0f);
matProj[11] = -1.0f;
matProj[14] = -(10.0f) / (9.0f);
// Clear the colorbuffer and depth-buffer
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set some state
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Set the shader program
glUseProgram(g_hShaderProgram);
glUniformMatrix4fv(g_hModelViewMatrixLoc, 1, 0, matModelView);
glUniformMatrix4fv(g_hProjMatrixLoc, 1, 0, matProj);
// Bind the vertex attributes
glVertexAttribPointer(g_hVertexLoc, 3, GL_FLOAT, 0, 0, VertexPositions);
glEnableVertexAttribArray(g_hVertexLoc);
glVertexAttribPointer(g_hColorLoc, 4, GL_FLOAT, 0, 0, VertexColors);
glEnableVertexAttribArray(g_hColorLoc);
glVertexAttribPointer(g_hVertexTexLoc, 2, GL_FLOAT, 0, 0, VertexTexCoords);
glEnableVertexAttribArray(g_hVertexTexLoc);
/* Select Our Texture */
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
/* Drawing Using Triangle strips, draw triangle strips using 4 vertices */
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
// Cleanup
glDisableVertexAttribArray(g_hVertexLoc);
glDisableVertexAttribArray(g_hColorLoc);
glDisableVertexAttribArray(g_hVertexTexLoc);
}
int init(void)
{
/*static const EGLint gl_context_attribs[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
}; */
static const EGLint s_configAttribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 0,
EGL_SAMPLES, 0,
EGL_NONE
};
EGLint numconfigs;
egldisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(egldisplay, NULL, NULL);
assert(eglGetError() == EGL_SUCCESS);
eglBindAPI(EGL_OPENGL_ES_API);
eglChooseConfig(egldisplay, s_configAttribs, &eglconfig, 1, &numconfigs);
assert(eglGetError() == EGL_SUCCESS);
assert(numconfigs == 1);
//You must pass in the file system handle to the linux framebuffer when creating a window
eglsurface =
eglCreateWindowSurface(egldisplay, eglconfig, open("/dev/fb0", O_RDWR), NULL);
assert(eglGetError() == EGL_SUCCESS);
EGLint ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
eglcontext = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT, ContextAttribList);
assert(eglGetError() == EGL_SUCCESS);
eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext);
assert(eglGetError() == EGL_SUCCESS);
GLfloat xmin, xmax, ymin, ymax;
EGLint h, w;
eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &w);
eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &h);
ymax = 0.1f * tan(45.0f * M_PI / 360.0f);
ymin = -ymax;
xmin = ymin * ((GLfloat) w / (GLfloat) h);
xmax = ymax * ((GLfloat) w / (GLfloat) h);
{
// Compile the shaders
GLuint hVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(hVertexShader, 1, &g_strVertexShader, NULL);
glCompileShader(hVertexShader);
// Check for compile success
GLint nCompileResult = 0;
glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &nCompileResult);
if (0 == nCompileResult) {
char strLog[1024];
GLint nLength;
glGetShaderInfoLog(hVertexShader, 1024, &nLength, strLog);
return FALSE;
}
GLuint hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(hFragmentShader, 1, &g_strFragmentShader, NULL);
glCompileShader(hFragmentShader);
// Check for compile success
glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &nCompileResult);
if (0 == nCompileResult) {
char strLog[1024];
GLint nLength;
glGetShaderInfoLog(hFragmentShader, 1024, &nLength, strLog);
return FALSE;
}
// Attach the individual shaders to the common shader program
g_hShaderProgram = glCreateProgram();
glAttachShader(g_hShaderProgram, hVertexShader);
glAttachShader(g_hShaderProgram, hFragmentShader);
// Init attributes BEFORE linking
glBindAttribLocation(g_hShaderProgram, g_hVertexLoc, "g_vPosition");
glBindAttribLocation(g_hShaderProgram, g_hColorLoc, "g_vColor");
printf("about to link shader...");
glBindAttribLocation(g_hShaderProgram, g_hVertexTexLoc, "g_vTexCoord");
// Link the vertex shader and fragment shader together
glLinkProgram(g_hShaderProgram);
// Check for link success
GLint nLinkResult = 0;
glGetProgramiv(g_hShaderProgram, GL_LINK_STATUS, &nLinkResult);
if (0 == nLinkResult) {
char strLog[1024];
GLint nLength;
glGetProgramInfoLog(g_hShaderProgram, 1024, &nLength, strLog);
printf("error linking shader");
return FALSE;
}
// Get uniform locations
g_hModelViewMatrixLoc =
glGetUniformLocation(g_hShaderProgram, "g_matModelView");
g_hProjMatrixLoc = glGetUniformLocation(g_hShaderProgram, "g_matProj");
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
//gen textures
/* Load in the texture */
if (LoadGLTextures() == 0) {
printf("error loading texture");
return 0;
}
/* Enable Texture Mapping ( NEW ) */
glEnable(GL_TEXTURE_2D);
}
return 1;
}
void Cleanup()
{
}
void deinit(void)
{
Cleanup();
eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
assert(eglGetError() == EGL_SUCCESS);
eglTerminate(egldisplay);
assert(eglGetError() == EGL_SUCCESS);
eglReleaseThread();
}
int main(void)
{
assert(init());
while (currentFrame < 1000) {
EGLint width = 0;
EGLint height = 0;
eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &width);
eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &height);
render(width, height);
currentFrame++;
eglSwapBuffers(egldisplay, eglsurface);
}
deinit();
return 0;
}