前段时间稍微看了看opengles,试着用android提供的java层代码写了几个小例子,最近几天找到了android6.01的源码中学习opengl的小例子,自己试着写了个小程序分享给大家。opengles从2.0开始编程用的shader变成了可进行编程的shader,书面点说就是由固定管线进化成了可编程管线,opengl 绘图会调用gpu提供的接口,最终工作在gpu中,所以可以减轻cpu的工作,从而在提高绘图效率的同时,减少cpu的消耗,起到降低功耗的目的。这里对这些基本的知识不再阐述,有时间慢慢学习了再给大家分享。另外android自身提供的opengles编程规范也是仿照opengl的,所以二者可以同时学习,但网上大多是1.0的资料,所以大家搜索时一定要搜索2.0的api进行学习。
今天要讲的不多,主要是把自己修改/LINUX/android/frameworks/native/opengl/tests/下的小例子展示给大家,这个例子绘制了一个旋转的同时移动的六面体,自己仿照网上的指导写了定点shader和片段shader,并利用了VBO提高性能。
Android.mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
gl2_basic.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libEGL \
libGLESv2 \
libui \
libgui \
libutils
LOCAL_STATIC_LIBRARIES += libglTest
LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
LOCAL_MODULE:= myopengl
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
include $(BUILD_EXECUTABLE)
test.cpp程序
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sched.h>
#include <sys/resource.h>
#include <math.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <utils/Timers.h>
#include <WindowSurface.h>
#include <EGLUtils.h>
using namespace android;
typedef struct _gmVector3
{
GLfloat x;
GLfloat y;
GLfloat z;
}gmVector3;
typedef struct _gmMatrix4
{
GLfloat m[16];
}gmMatrix4;
typedef struct _gmVector2
{
float x;
float y;
}gmVector2;
typedef struct _gmVector4
{
float x;
float y;
float z;
float w;
}gmVector4;
void gmVec3Normalize(gmVector3* out, gmVector3* in)
{
GLfloat f = in->x * in->x + in->y * in->y + in->z * in->z;
f = 1.0f / sqrt(f);
out->x = in->x * f;
out->y = in->y * f;
out->z = in->z * f;
}
void gmVec3CrossProduct(gmVector3* out, gmVector3* v1, gmVector3* v2)
{
gmVector3 result;
result.x = v1->y * v2->z - v1->z * v2->y;
result.y = v1->z * v2->x - v1->x * v2->z;
result.z = v1->x * v2->y - v1->y * v2->x;
*out = result;
}
//实现移动的矩阵操作
void gmMatrixTranslate(gmMatrix4* out, GLfloat x, GLfloat y, GLfloat z)
{
if (out == NULL)
{
return;
}
out->m[ 0]=1.0f; out->m[ 4]=0.0f; out->m[ 8]=0.0f; out->m[12]=x;
out->m[ 1]=0.0f; out->m[ 5]=1.0f; out->m[ 9]=0.0f; out->m[13]=y;
out->m[ 2]=0.0f; out->m[ 6]=0.0f; out->m[10]=1.0f; out->m[14]=z;
out->m[ 3]=0.0f; out->m[ 7]=0.0f; out->m[11]=0.0f; out->m[15]=1.0f;
}
//缩放的操作
void gmMatrixScale(gmMatrix4* out, GLfloat x, GLfloat y, GLfloat z)
{
if (out == NULL)
{
return;
}
out->m[ 0]=x; out->m[ 4]=0.0f; out->m[ 8]=0.0f; out->m[12]=0.0f;
out->m[ 1]=0.0f; out->m[ 5]=y; out->m[ 9]=0.0f; out->m[13]=0.0f;
out->m[ 2]=0.0f; out->m[ 6]=0.0f; out->m[10]=z; out->m[14]=0.0f;
out->m[ 3]=0.0f; out->m[ 7]=0.0f; out->m[11]=0.0f; out->m[15]=1.0f;
}
//绕X旋转的操作
void gmMatrixRotateX(gmMatrix4* out, GLfloat x)
{
if (out == NULL)
{
return;
}
GLfloat fcos, fsin;
fcos = cos(x);
fsin = sin(x);
out->m[ 0]=1.0f; out->m[ 4]=0.0f; out->m[ 8]=0.0f; out->m[12]=0.0f;
out->m[ 1]=0.0f; out->m[ 5]=fcos; out->m[ 9]=fsin; out->m[13]=0.0f;
out->m[ 2]=0.0f; out->m[ 6]=-fsin; out->m[10]=fcos; out->m[14]=0.0f;
out->m[ 3]=0.0f; out->m[ 7]=0.0f; out->m[11]=0.0f; out->m[15]=1.0f;
}
void gmMatrixRotateY(gmMatrix4* out, GLfloat y)
{
if (out == NULL)
{
return;
}
GLfloat fcos, fsin;
fcos = cos(y);
fsin = sin(y);
out->m[ 0]=fcos; out->m[ 4]=0.0f; out->m[ 8]=-fsin; out->m[12]=0.0f;
out->m[ 1]=0.0f; out->m[ 5]=1.0f; out->m[ 9]=0.0f; out->m[13]=0.0f;
out->m[ 2]=fsin; out->m[ 6]=0.0f; out->m[10]=fcos; out->m[14]=0.0f;
out->m[ 3]=0.0f; out->m[ 7]=0.0f; out->m[11]=0.0f; out->m[15]=1.0f;
}
void gmMatrixRotateZ(gmMatrix4* out, GLfloat z)
{
if (out == NULL)
{
return;
}
GLfloat fcos, fsin;
fcos = cos(z);
fsin = sin(z);
out->m[ 0]=fcos; out->m[ 4]=fsin; out->m[ 8]=0.0f; out->m[12]=0.0f;
out->m[ 1]=-fsin; out->m[ 5]=fcos; out->m[ 9]=0.0f; out->m[13]=0.0f;
out->m[ 2]=0.0f; out->m[ 6]=0.0f; out->m[10]=1.0f; out->m[14]=0.0f;
out->m[ 3]=0.0f; out->m[ 7]=0.0f; out->m[11]=0.0f; out->m[15]=1.0f;
}
void InitgmMatrix4(gmMatrix4* mat)
{
if (mat == NULL)
{
return;
}
memset(mat, 0, sizeof(gmMatrix4));
mat->m[0] = 1.0f;
mat->m[1] = 1.0f;
mat->m[2] = 1.0f;
mat->m[3] = 1.0f;
}
void gmMatrixMultiply(gmMatrix4* out, gmMatrix4* m1, gmMatrix4* m2)
{
if (out == NULL || m1 == NULL || m2 == NULL)
{
return;
}
gmMatrix4 tmpout;
tmpout.m[ 0] = m1->m[ 0]*m2->m[ 0] + m1->m[ 1]*m2->m[ 4] + m1->m[ 2]*m2->m[ 8] + m1->m[ 3]*m2->m[12];
tmpout.m[ 1] = m1->m[ 0]*m2->m[ 1] + m1->m[ 1]*m2->m[ 5] + m1->m[ 2]*m2->m[ 9] + m1->m[ 3]*m2->m[13];
tmpout.m[ 2] = m1->m[ 0]*m2->m[ 2] + m1->m[ 1]*m2->m[ 6] + m1->m[ 2]*m2->m[10] + m1->m[ 3]*m2->m[14];
tmpout.m[ 3] = m1->m[ 0]*m2->m[ 3] + m1->m[ 1]*m2->m[ 7] + m1->m[ 2]*m2->m[11] + m1->m[ 3]*m2->m[15];
tmpout.m[ 4] = m1->m[ 4]*m2->m[ 0] + m1->m[ 5]*m2->m[ 4] + m1->m[ 6]*m2->m[ 8] + m1->m[ 7]*m2->m[12];
tmpout.m[ 5] = m1->m[ 4]*m2->m[ 1] + m1->m[ 5]*m2->m[ 5] + m1->m[ 6]*m2->m[ 9] + m1->m[ 7]*m2->m[13];
tmpout.m[ 6] = m1->m[ 4]*m2->m[ 2] + m1->m[ 5]*m2->m[ 6] + m1->m[ 6]*m2->m[10] + m1->m[ 7]*m2->m[14];
tmpout.m[ 7] = m1->m[ 4]*m2->m[ 3] + m1->m[ 5]*m2->m[ 7] + m1->m[ 6]*m2->m[11] + m1->m[ 7]*m2->m[15];
tmpout.m[ 8] = m1->m[ 8]*m2->m[ 0] + m1->m[ 9]*m2->m[ 4] + m1->m[10]*m2->m[ 8] + m1->m[11]*m2->m[12];
tmpout.m[ 9] = m1->m[ 8]*m2->m[ 1] + m1->m[ 9]*m2->m[ 5] + m1->m[10]*m2->m[ 9] + m1->m[11]*m2->m[13];
tmpout.m[10] = m1->m[ 8]*m2->m[ 2] + m1->m[ 9]*m2->m[ 6] + m1->m[10]*m2->m[10] + m1->m[11]*m2->m[14];
tmpout.m[11] = m1->m[ 8]*m2->m[ 3] + m1->m[ 9]*m2->m[ 7] + m1->m[10]*m2->m[11] + m1->m[11]*m2->m[15];
tmpout.m[12] = m1->m[12]*m2->m[ 0] + m1->m[13]*m2->m[ 4] + m1->m[14]*m2->m[ 8] + m1->m[15]*m2->m[12];
tmpout.m[13] = m1->m[12]*m2->m[ 1] + m1->m[13]*m2->m[ 5] + m1->m[14]*m2->m[ 9] + m1->m[15]*m2->m[13];
tmpout.m[14] = m1->m[12]*m2->m[ 2] + m1->m[13]*m2->m[ 6] + m1->m[14]*m2->m[10] + m1->m[15]*m2->m[14];
tmpout.m[15] = m1->m[12]*m2->m[ 3] + m1->m[13]*m2->m[ 7] + m1->m[14]*m2->m[11] + m1->m[15]*m2->m[15];
*out = tmpout;
}
void gmMatrixLookAtLH(gmMatrix4* out, gmVector3* eye, gmVector3* at, gmVector3* up)
{
gmVector3 f, s, u;
gmMatrix4 t;
f.x = eye->x - at->x;
f.y = eye->y - at->y;
f.z = eye->z - at->z;
//取最小值
gmVec3Normalize(&f, &f);
gmVec3CrossProduct(&s, &f, up);
gmVec3Normalize(&s, &s);
gmVec3CrossProduct(&u, &s, &f);
gmVec3Normalize(&u, &u);
out->m[ 0] = s.x;
out->m[ 1] = u.x;
out->m[ 2] = -f.x;
out->m[ 3] = 0;
out->m[ 4] = s.y;
out->m[ 5] = u.y;
out->m[ 6] = -f.y;
out->m[ 7] = 0;
out->m[ 8] = s.z;
out->m[ 9] = u.z;
out->m[10] = -f.z;
out->m[11] = 0;
out->m[12] = 0;
out->m[13] = 0;
out->m[14] = 0;
out->m[15] = 1;
gmMatrixTranslate(&t, -eye->x, -eye->y, -eye->z);
gmMatrixMultiply(out, &t, out);
}
void gmMatrixPerspectiveFovLH(gmMatrix4* out, GLfloat foy, GLfloat aspect, GLfloat near, GLfloat far)
{
GLfloat f, n;
f = 1.0f / (GLfloat)tan(foy * 0.5f);
n = 1.0f / (far - near);
out->m[ 0] = f / aspect;
out->m[ 1] = 0;
out->m[ 2] = 0;
out->m[ 3] = 0;
out->m[ 4] = 0;
out->m[ 5] = f;
out->m[ 6] = 0;
out->m[ 7] = 0;
out->m[ 8] = 0;
out->m[ 9] = 0;
out->m[10] = far * n;
out->m[11] = 1;
out->m[12] = 0;
out->m[13] = 0;
out->m[14] = -far * near * n;
out->m[15] = 0;
}
static void printGLString(const char *name, GLenum s) {
// fprintf(stderr, "printGLString %s, %d\n", name, s);
const char *v = (const char *) glGetString(s);
// int error = glGetError();
// fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
// (unsigned int) v);
// if ((v < (const char*) 0) || (v > (const char*) 0x10000))
// fprintf(stderr, "GL %s = %s\n", name, v);
// else
// fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
fprintf(stderr, "GL %s = %s\n", name, v);
}
static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
if (returnVal != EGL_TRUE) {
fprintf(stderr, "%s() returned %d\n", op, returnVal);
}
for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
= eglGetError()) {
fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
error);
}
}
static void checkGlError(const char* op) {
for (GLint error = glGetError(); error; error
= glGetError()) {
fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
}
}
/*
static const char gVertexShader[] = "attribute vec4 vPosition;\n"
"uniform mat4 vMatrix;\n"
"varying vec4 vColor;\n"
"attribute vec4 aColor;\n"
"void main() {\n"
" gl_Position = vMatrix*vPosition;\n"
" vColor=aColor;\n"
"}\n";
static const char gFragmentShader[] = "precision mediump float;\n"
"varying vec4 vColor;\n"
"void main() {\n"
" gl_FragColor = vColor;\n"
"}\n";
*/
static const char gVertexShader[] =
"precision mediump float;\n"
"attribute vec4 vPosition;\n"
"attribute vec4 aColor;\n"
"uniform mat4 uMvp;\n"
"varying vec4 vColor;\n"
"void main() {\n"
"gl_Position = uMvp*vPosition;\n"
" vColor = aColor;\n"
"}\n";
static const char gFragmentShader[] = "precision mediump float;\n"
"varying vec4 vColor;\n"
"void main() {\n"
"gl_FragColor = vColor;\n"
"}\n";
GLuint loadShader(GLenum shaderType, const char* pSource) {
GLuint shader = glCreateShader(shaderType);
if (shader) {
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* buf = (char*) malloc(infoLen);
if (buf) {
glGetShaderInfoLog(shader, infoLen, NULL, buf);
fprintf(stderr, "Could not compile shader %d:\n%s\n",
shaderType, buf);
free(buf);
}
glDeleteShader(shader);
shader = 0;
}
}
}
return shader;
}
GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
if (!vertexShader) {
return 0;
}
GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
if (!pixelShader) {
return 0;
}
GLuint program = glCreateProgram();
if (program) {
glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
glLinkProgram(program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE) {
GLint bufLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
if (bufLength) {
char* buf = (char*) malloc(bufLength);
if (buf) {
glGetProgramInfoLog(program, bufLength, NULL, buf);
fprintf(stderr, "Could not link program:\n%s\n", buf);
free(buf);
}
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}
GLfloat cubePositions[] = {
-0.5f,0.5f,0.5f, //正面左上0
-0.5f,-0.5f,0.5f, //正面左下1
0.5f,-0.5f,0.5f, //正面右下2
0.5f,0.5f,0.5f, //正面右上3
-0.5f,0.5f,-0.5f, //反面左上4
-0.5f,-0.5f,-0.5f, //反面左下5
0.5f,-0.5f,-0.5f, //反面右下6
0.5f,0.5f,-0.5f //反面右上7
};
/*
const GLfloat Vertices[] = {
-0.5,-0.5,0,// 左下,黑色
0.5,-0.5,0, // 右下,红色
-0.5,0.5,0, // 左上,蓝色
0.5,0.5,0 // 右上,绿色
};
const GLshort Indices[] = {
0,1,2, // 三角形0
1,2,3 // 三角形1
};
*/
void initMat(gmMatrix4* out){
if (out == NULL)
{
return;
}
out->m[ 0]=1.0f; out->m[ 4]=0.0f; out->m[ 8]=0.0f; out->m[12]=0.0f;
out->m[ 1]=0.0f; out->m[ 5]=1.0f; out->m[ 9]=0.0f; out->m[13]=0.0f;
out->m[ 2]=0.0f; out->m[ 6]=0.0f; out->m[10]=1.0f; out->m[14]=0.0f;
out->m[ 3]=0.0f; out->m[ 7]=0.0f; out->m[11]=0.0f; out->m[15]=1.0f;
}
/*const GLfloat Vertices[] = {
-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,
};
*/
const GLfloat Vertices111[] =
{
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.5f, 0.5f, 1.0f,
};
const GLfloat Vertices[] =
{
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.5f, 0.5f, 1.0f,
};
const GLshort Indices1111[] = {
0, 1, 2, 1, 2, 3,
0, 4, 2, 6, 4, 2,
0, 1, 4, 1, 5, 4,
1, 3, 5, 3, 5, 7,
2, 3, 6, 3, 6, 7,
4, 5, 6, 5, 6, 7,
};
GLshort Indices[]={
0,3,2,0,2,1, //正面
0,1,5,0,5,4, //左面
0,7,3,0,4,7, //上面
6,7,4,6,4,5, //后面
6,3,7,6,2,3, //右面
6,5,1,6,1,2 //下面
};
//八个顶点的颜色,与顶点坐标一一对应
GLfloat color[] = {
0.0f,1.0f,0.0f,1.0f,
0.0f,1.0f,0.0f,1.0f,
0.0f,1.0f,0.0f,1.0f,
0.0f,1.0f,0.0f,1.0f,
1.0f,0.0f,0.0f,1.0f,
1.0f,0.0f,0.0f,1.0f,
1.0f,0.0f,0.0f,1.0f,
1.0f,0.0f,0.0f,1.0f,
};
/
gmMatrix4 mvp;
GLuint gProgram;
GLuint gvPositionHandle;
GLuint gvColorHandle;
GLuint uLocMvp;
GLuint ibo;
GLuint vbo;
GLuint cbo;
bool setupGraphics(int w, int h) {
gProgram = createProgram(gVertexShader, gFragmentShader);
if (!gProgram) {
return false;
}
//否则颜色清除错误错误
glUseProgram(gProgram);
checkGlError("glUseProgram");
uLocMvp = glGetUniformLocation(gProgram, "uMvp");
gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
checkGlError("glGetAttribLocation");
gvColorHandle = glGetAttribLocation(gProgram, "aColor");
checkGlError("glGetAttribLocation");
initMat(&mvp);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(Indices), Indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return true;
}
gmMatrix4 model,view, proj;
gmVector3 eye = {0.0f, 2.0f, -2.0f};
gmVector3 at = {0.0f, 0.0f, 0.0f};
gmVector3 up = {0.0f, 1.0f, 0.0f};
void setMatrix(GLfloat viewWidth , GLfloat viewHeight){
gmMatrixLookAtLH(&view, &eye, &at, &up);
gmMatrixPerspectiveFovLH(&proj, 3.1415f / 2, (GLfloat)viewWidth / (GLfloat)viewHeight, 1.0f, 1000.0f);
}
GLfloat angle = 0.0f;
GLfloat tranx = 0.0f;
int changeTime=1;
GLfloat changeZ=0.0f;
GLfloat flag=1.0f;
void renderFrame(int _viewWidth ,int _viewHeight) {
/*
//多种效果复合
gmMatrix4 model, view, proj;
gmMatrix4 modelnum;
gmMatrix4 modelx, modely,modelz;
//在多种变换同时施加到顶点上时以相反的顺序矩阵相乘
//gmMatrixTranslate(&model,tranx,0,0);
// gmMatrixRotateY(&model, angle);
gmMatrixRotateY(&modelx,angle);
gmMatrixRotateZ(&modely,angle);
gmMatrixRotateX(&modelz,angle);
gmMatrixMultiply(&modelnum, &modelx, &modely);
gmMatrixMultiply(&model, &modelnum, &modelz);
angle += 0.05f;
*/
gmMatrix4 modela,modelb, view, proj;
gmMatrixTranslate(&modela,0,0,changeZ);
gmMatrixRotateY(&modelb, angle);
gmMatrixMultiply(&model, &modelb, &modela);
changeZ=changeZ+0.001f;
angle += 0.05f;
if(angle>=44){
angle=0.0f;
}
gmVector3 eye = {0.0f, 0.0f, -2.0f};
gmVector3 at = {0.0f, 0.0f, 0.0f};
gmVector3 up = {0.0f, 1.0f, 0.0f};
gmMatrixLookAtLH(&view, &eye, &at, &up);
gmMatrixPerspectiveFovLH(&proj, 3.1415f / 2, (float)_viewWidth / (float)_viewHeight, 1.0f, 1000.0f);
gmMatrixMultiply(&mvp, &model, &view);
gmMatrixMultiply(&mvp, &mvp, &proj);
glUniformMatrix4fv(uLocMvp, 1, 0, (GLfloat*)&mvp);
//剔除不需要的面,那其实言外之意就是我们认为逆时针为正面
// glEnable(GL_CULL_FACE);
// glCullFace(GL_CW);
//深度测试
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
//glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
checkGlError("glClearColor");
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
checkGlError("glClear");
glUseProgram(gProgram);
checkGlError("glUseProgram");
// glUseProgram(gProgram);
// checkGlError("glUseProgram");
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, 0);
//glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, vertices);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvPositionHandle);
checkGlError("glEnableVertexAttribArray");
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*7, 0);
glVertexAttribPointer(gvColorHandle, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*7, (GLvoid*)(sizeof(GLfloat)*4));
//glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, vertices);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvPositionHandle);
checkGlError("glEnableVertexAttribArray");
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvColorHandle);
checkGlError("glEnableVertexAttribArray");
//glBindBuffer(GL_ARRAY_BUFFER, gvColorHandle);
// glVertexAttribPointer(gvColorHandle, 4, GL_FLOAT, GL_FALSE, 0, color);
// glVertexAttribPointer(gvColorHandle, 4, GL_FLOAT, GL_FALSE, 0, 0);
//checkGlError("glVertexAttribPointer");
//glEnableVertexAttribArray(gvColorHandle);
// checkGlError("glEnableVertexAttribArray");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES,36, GL_UNSIGNED_SHORT, 0);
checkGlError("glDrawElements");
}
void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
#define X(VAL) {VAL, #VAL}
struct {EGLint attribute; const char* name;} names[] = {
X(EGL_BUFFER_SIZE),
X(EGL_ALPHA_SIZE),
X(EGL_BLUE_SIZE),
X(EGL_GREEN_SIZE),
X(EGL_RED_SIZE),
X(EGL_DEPTH_SIZE),
X(EGL_STENCIL_SIZE),
X(EGL_CONFIG_CAVEAT),
X(EGL_CONFIG_ID),
X(EGL_LEVEL),
X(EGL_MAX_PBUFFER_HEIGHT),
X(EGL_MAX_PBUFFER_PIXELS),
X(EGL_MAX_PBUFFER_WIDTH),
X(EGL_NATIVE_RENDERABLE),
X(EGL_NATIVE_VISUAL_ID),
X(EGL_NATIVE_VISUAL_TYPE),
X(EGL_SAMPLES),
X(EGL_SAMPLE_BUFFERS),
X(EGL_SURFACE_TYPE),
X(EGL_TRANSPARENT_TYPE),
X(EGL_TRANSPARENT_RED_VALUE),
X(EGL_TRANSPARENT_GREEN_VALUE),
X(EGL_TRANSPARENT_BLUE_VALUE),
X(EGL_BIND_TO_TEXTURE_RGB),
X(EGL_BIND_TO_TEXTURE_RGBA),
X(EGL_MIN_SWAP_INTERVAL),
X(EGL_MAX_SWAP_INTERVAL),
X(EGL_LUMINANCE_SIZE),
X(EGL_ALPHA_MASK_SIZE),
X(EGL_COLOR_BUFFER_TYPE),
X(EGL_RENDERABLE_TYPE),
X(EGL_CONFORMANT),
};
#undef X
for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
EGLint value = -1;
EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
EGLint error = eglGetError();
if (returnVal && error == EGL_SUCCESS) {
printf(" %s: ", names[j].name);
printf("%d (0x%x)", value, value);
}
}
printf("\n");
}
int printEGLConfigurations(EGLDisplay dpy) {
EGLint numConfig = 0;
EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
checkEglError("eglGetConfigs", returnVal);
if (!returnVal) {
return false;
}
printf("Number of EGL configuration: %d\n", numConfig);
EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
if (! configs) {
printf("Could not allocate configs.\n");
return false;
}
returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
checkEglError("eglGetConfigs", returnVal);
if (!returnVal) {
free(configs);
return false;
}
for(int i = 0; i < numConfig; i++) {
printf("Configuration %d\n", i);
printEGLConfiguration(dpy, configs[i]);
}
free(configs);
return true;
}
int main(int argc, char** argv) {
EGLBoolean returnValue;
EGLConfig myConfig = {0};
EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
//第四步:指定需要的配置属性,一个EGL的配置描述了Surfaces上像素的格式信息。
//当前我们要的是Windows的surface,在屏幕上是可见的,以EGL_NONE结尾。
EGLint s_configAttribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE };
EGLint majorVersion;
EGLint minorVersion;
EGLContext context;
EGLSurface surface;
EGLint w, h;
EGLDisplay dpy;
checkEglError("<init>");
//获得默认的Display。通常我们只有一块屏幕,参数传EGL_DEFAULT_DISPLAY就可以了。
dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
checkEglError("eglGetDisplay");
if (dpy == EGL_NO_DISPLAY) {
printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
return 0;
}
//第三步:初始化EGL,如果我们不想要版本号,后两个参数也可以传NULL进去。
returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
checkEglError("eglInitialize", returnValue);
fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
if (returnValue != EGL_TRUE) {
printf("eglInitialize failed\n");
return 0;
}
if (!printEGLConfigurations(dpy)) {
printf("printEGLConfigurations failed\n");
return 0;
}
checkEglError("printEGLConfigurations");
WindowSurface windowSurface;
EGLNativeWindowType window = windowSurface.getSurface();
returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig);
if (returnValue) {
printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue);
return 0;
}
checkEglError("EGLUtils::selectConfigForNativeWindow");
printf("Chose this configuration:\n");
// printEGLConfiguration(dpy, myConfig);
//第六步:创建一个可画的surface。
surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
checkEglError("eglCreateWindowSurface");
if (surface == EGL_NO_SURFACE) {
printf("gelCreateWindowSurface failed.\n");
return 0;
}
//第七步:创建Context。我们OpenGL ES的资源,比如纹理只有在这个context里是可见的。
context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
checkEglError("eglCreateContext");
if (context == EGL_NO_CONTEXT) {
printf("eglCreateContext failed\n");
return 0;
}
//第八步:将创建的context绑定到当前的线程,使用我们创建的surface进行读和写。
//Context绑定到线程上,可不用担心其他进程影响你的OpenGLES应用程序。
returnValue = eglMakeCurrent(dpy, surface, surface, context);
checkEglError("eglMakeCurrent", returnValue);
if (returnValue != EGL_TRUE) {
return 0;
}
//Surface也有一些attribute,基本上都可以故名思意,
//EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET
//EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL,通过eglSurfaceAttrib()设置、eglQuerySurface()读取。
eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
checkEglError("eglQuerySurface");
eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
checkEglError("eglQuerySurface");
GLint dim = w < h ? w : h;
fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
printGLString("Version", GL_VERSION);
printGLString("Vendor", GL_VENDOR);
printGLString("Renderer", GL_RENDERER);
printGLString("Extensions", GL_EXTENSIONS);
GLfloat rotatex=10;
GLfloat step=0.001f;
GLfloat angle = 0.1f;
//开始绘制
if(!setupGraphics(w, h)) {
fprintf(stderr, "Could not set up graphics.\n");
return 0;
}
for (;;) {
renderFrame(w,h);
eglSwapBuffers(dpy, surface);
checkEglError("eglSwapBuffers");
}
return 0;
}
上面的程序直接放到源码中,利用Android.mk文件进行编译,会生成可执行的文件,push到android设备中,直接就可以执行看到效果。