一、首先需要对EGL进行初始化:
void Renderer::initEGL()
{
const EGLint attribs[] =
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE };
EGLint width, height, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
//instance->surface = eglCreateWindowSurface(instance->display, instance->config[0], WindowTypes, NULL);
surface = eglCreateWindowSurface(display, config, mWindow, NULL);
EGLint attrs[] =
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
context = eglCreateContext(display, config, NULL, attrs);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
{
printf("------EGL-FALSE\n");
return;
}
eglQuerySurface(display, surface, EGL_WIDTH, &width);
eglQuerySurface(display, surface, EGL_HEIGHT, &height);
mDisplay = display;
mSurface = surface;
mContext = context;
mWidth = width;
mHeight = height;
printf("width:%d, height:%d\n", mWidth, mHeight);
}
EGL 是 OpenGL ES 和底层 Native 平台视窗系统之间的接口,主要是为了保证opengl es的平台独立性,EGL可以理解为一块一块画布,提供给
OpengGL ES来绘图。
display用来获取默认的显示设备,可以理解为显示屏幕。surface可以理解为使用native创建的java层中的surface。
比较重要的是:eglMakeCurrent(display, surface, surface, context),主要告诉设备在这个surface上面绘制图像,经过测试,创建多个surface,
然后决定在哪个surface上面绘制图像就由这个函数来决定。
二、模仿java层的glsurface进行初始化以及绘制:
void Renderer::nativeSurfaceCreated()
{
printf("nativeSurfaceCreated\n");
int program = 0;
glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
program = glutil->createProgram(vertexShaderCode, fragmentShaderCode);
glUseProgram(program);
aColorLocation = glGetAttribLocation(program, A_COLOR);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, tableVerticesWithTriangles);
glEnableVertexAttribArray(aPositionLocation);
glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, tableVerticesWithTriangles + POSITION_COMPONENT_COUNT);
glEnableVertexAttribArray(aColorLocation);
}
函数;
createProgram是自己写的作为编译连接glsl语言,主要就是运行在GPU上面的语言,主要的顶点以及颜色信息就是在这个里面运算渲染;
aColorLocation就是获取program中的句柄,使用glVertexAttribPointer对其进行赋值交给GPU去运算,告诉GPU渲染的颜色,COLOR_COMPONENET
是读取颜色的长度,也就是在后面的数组中读取颜色,STRIDE也是自己定义的每次读取需要偏移的位数,最后一个参数是确定从哪里开始读取;
aPositionLocation是告诉GPU在哪些顶点去渲染;
glEnableVertexAttribArray就是使句柄生效。
void Renderer::nativeSurfaceChanged(EGLint width, EGLint height)
{
glViewport(0, 0, width, height);
}
这个可以理解为java层的Render中的SurfaceChanged;
void Renderer::nativeDraw()
{
//printf("nativeDraw!!!\n");
//glClearColor(0.3f, 0.0f, 0.0f, 0.3f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
glDrawArrays(GL_LINES, 6, 2);
glDrawArrays(GL_POINTS, 8, 2);
glDrawArrays(GL_POINTS, 9, 1);
}
const GLfloat tableVerticesWithTriangles[] =
{
0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
0.5f, 0.5f, 0.7f, 0.7f, 0.7f,
-0.5f, 0.5f, 0.7f, 0.7f, 0.7f,
-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
// Line 1
-0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.0f, 0.0f, 0.0f, 0.0f,
// Mallets
0.0f, -0.25f, 1.0f, 0.0f, 0.0f,
0.0f, 0.25f, 0.0f, 1.0f, 0.0f
};
这个就是具体绘制的函数,首先绘制两个三角形,在本程序中就是绘制了一个长方形,从以上的数组中第0个开始的六个点确定了这两个三角形
的位置信息,也就是(0.0f, 0.0f),( -0.5f,-0.5),(0.5, -0.5),(0.5, 0.5),(-0.5,0.5),(-0.5, -0.5),偏移量是由上面的surfaceCreate
中已经确定,每个点后面的三个值是RGB值,A默认为1;
后面贴一下主要的代码:
/*main.cpp*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "GLUtil.h"
#include "Renderer.h"
using namespace android;
int main(int argc, char ** argv)
{
Renderer * mRenderer = NULL;
mRenderer = new Renderer();
//mRenderer->start();
EGLNativeWindowType WindowTypes = (EGLNativeWindowType) mRenderer->glutil->getNativeWindow(800, 600, 100, 100, 0);
mRenderer->requestInitEGL(WindowTypes);
while(1)
mRenderer->requestRenderFrame();
mRenderer->requestDestroy();
ANativeWindow_release(WindowTypes);
delete mRenderer;
return 0;
}
Render.cpp:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "GLUtil.h"
#include "Renderer.h"
const char * vertexShaderCode =
"attribute vec4 a_Position;"
"attribute vec4 a_Color;"
"varying vec4 v_Color;"
"void main(){"
"v_Color = a_Color;"
"gl_Position = a_Position;"
"gl_PointSize = 10.0;}";
const char * fragmentShaderCode =
"precision mediump float;"
"varying vec4 v_Color;"
"void main(){"
"gl_FragColor = v_Color;}";
#define COLOR_COMPONENT_COUNT 3
#define POSITION_COMPONENT_COUNT 2
#define STRIDE ((COLOR_COMPONENT_COUNT + POSITION_COMPONENT_COUNT) * 4)
#define A_COLOR "a_Color"
#define A_POSITION "a_Position"
const GLfloat tableVerticesWithTriangles[] =
{
0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
0.5f, 0.5f, 0.7f, 0.7f, 0.7f,
-0.5f, 0.5f, 0.7f, 0.7f, 0.7f,
-0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
// Line 1
-0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.0f, 0.0f, 0.0f, 0.0f,
// Mallets
0.0f, -0.25f, 1.0f, 0.0f, 0.0f,
0.0f, 0.25f, 0.0f, 1.0f, 0.0f
};
Renderer::Renderer()
{
//pthread_mutex_init(&mMutex, NULL);
//pthread_cond_init(&mCondVar, NULL);
mDisplay = EGL_NO_DISPLAY;
mSurface = EGL_NO_SURFACE;
mContext = EGL_NO_CONTEXT;
glutil = new GLUtil();
}
Renderer::~Renderer()
{
//pthread_mutex_destroy(&mMutex);
//pthread_cond_destroy(&mCondVar);
}
void Renderer::start()
{
pthread_create(&mThread, NULL, startRenderThread, this);
}
void Renderer::requestInitEGL(EGLNativeWindowType pWindow)
{
//pthread_mutex_lock(&mMutex);
mWindow = pWindow;
//mEnumRenderEvent = RE_SURFACE_CHANGED;
initEGL();
nativeSurfaceCreated();
nativeSurfaceChanged(mWidth, mHeight);
//pthread_mutex_unlock(&mMutex);
//pthread_cond_signal(&mCondVar);
}
void Renderer::requestRenderFrame()
{
//pthread_mutex_lock(&mMutex);
mEnumRenderEvent = RE_DRAW_FRAME;
nativeDraw();
eglSwapBuffers(mDisplay, mSurface);
//pthread_mutex_unlock(&mMutex);
//pthread_cond_signal(&mCondVar);
}
void Renderer::requestDestroy()
{
//pthread_mutex_lock(&mMutex);
//mEnumRenderEvent = RE_EXIT;
terminateDisplay();
mISRenderering = false;
//pthread_mutex_unlock(&mMutex);
//pthread_cond_signal(&mCondVar);
}
void Renderer::onRenderThreadRun()
{
mISRenderering = true;
while (mISRenderering)
{
//pthread_mutex_lock(&mMutex);
// 姣忓畬鎴愪竴涓簨浠跺氨wait鍦ㄨ繖閲岀洿鍒版湁鍏朵粬浜嬩欢鍞ら啋
//pthread_cond_wait(&mCondVar, &mMutex);
printf("-------this mEnumRenderEvent is %d\n", mEnumRenderEvent);
switch (mEnumRenderEvent)
{
case RE_SURFACE_CHANGED:
printf("-------case RE_SURFACE_CHANGED\n");
//mEnumRenderEvent = RE_NONE;
//pthread_mutex_unlock(&mMutex);
initEGL();
nativeSurfaceCreated();
nativeSurfaceChanged(mWidth, mHeight);
break;
case RE_DRAW_FRAME:
//mEnumRenderEvent = RE_NONE;
//pthread_mutex_unlock(&mMutex);
// draw
nativeDraw();
eglSwapBuffers(mDisplay, mSurface);
break;
case RE_EXIT:
//mEnumRenderEvent = RE_NONE;
//pthread_mutex_unlock(&mMutex);
terminateDisplay();
mISRenderering = false;
break;
//default:
//mEnumRenderEvent = RE_NONE;
//pthread_mutex_unlock(&mMutex);
}
}
}
void *Renderer::startRenderThread(void * pVoid)
{
Renderer * render = (Renderer*) pVoid;
render->onRenderThreadRun();
return NULL;
}
void Renderer::initEGL()
{
const EGLint attribs[] =
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE };
EGLint width, height, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
//instance->surface = eglCreateWindowSurface(instance->display, instance->config[0], WindowTypes, NULL);
surface = eglCreateWindowSurface(display, config, mWindow, NULL);
EGLint attrs[] =
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
context = eglCreateContext(display, config, NULL, attrs);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
{
printf("------EGL-FALSE\n");
return;
}
eglQuerySurface(display, surface, EGL_WIDTH, &width);
eglQuerySurface(display, surface, EGL_HEIGHT, &height);
mDisplay = display;
mSurface = surface;
mContext = context;
mWidth = width;
mHeight = height;
printf("width:%d, height:%d\n", mWidth, mHeight);
}
void Renderer::terminateDisplay()
{
if (mDisplay != EGL_NO_DISPLAY)
{
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
if (mContext != EGL_NO_CONTEXT)
{
eglDestroyContext(mDisplay, mContext);
}
if (mSurface != EGL_NO_SURFACE)
{
eglDestroySurface(mDisplay, mSurface);
}
eglTerminate(mDisplay);
}
mDisplay = EGL_NO_DISPLAY;
mSurface = EGL_NO_SURFACE;
mContext = EGL_NO_CONTEXT;
}
int program = 0;
int angle = 0;
void Renderer::nativeSurfaceCreated()
{
#if 1
printf("nativeSurfaceCreated\n");
int program = 0;
glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
program = glutil->createProgram(vertexShaderCode, fragmentShaderCode);
glUseProgram(program);
aColorLocation = glGetAttribLocation(program, A_COLOR);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, tableVerticesWithTriangles);
glEnableVertexAttribArray(aPositionLocation);
glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, tableVerticesWithTriangles + POSITION_COMPONENT_COUNT);
glEnableVertexAttribArray(aColorLocation);
#else
//int program = 0;
glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
program = glutil->createProgram(vertexShaderCode, fragmentShaderCode);
//glViewport(0, 0, width, height);
glUseProgram(program);
#endif
}
void Renderer::nativeSurfaceChanged(EGLint width, EGLint height)
{
glViewport(0, 0, width, height);
}
void Renderer::nativeDraw()
{
//printf("nativeDraw!!!\n");
//glClearColor(0.3f, 0.0f, 0.0f, 0.3f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
glDrawArrays(GL_LINES, 6, 2);
glDrawArrays(GL_POINTS, 8, 2);
glDrawArrays(GL_POINTS, 9, 1);
}
EGLNativeWindowType GLUtil::getNativeWindow(int width, int hight, int position_x, int position_y, int type)
{
DisplayInfo dinfo;
mComposerClient = new SurfaceComposerClient();
sp dtoken(SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
printf("w=%d,h=%d,xdpi=%f,ydpi=%f,fps=%f,ds=%f\n",
dinfo.w, dinfo.h, dinfo.xdpi, dinfo.ydpi, dinfo.fps, dinfo.density);
mSurfaceControl = mComposerClient->createSurface(
String8("Test Surface"),
dinfo.w, dinfo.h,
PIXEL_FORMAT_RGBA_8888, 0);
SurfaceComposerClient::openGlobalTransaction();
mSurfaceControl->setLayer(100000);//设定Z坐标
mSurfaceControl->setPosition(position_x, position_y);
mSurfaceControl->setSize(width, hight);
SurfaceComposerClient::closeGlobalTransaction();
sp window = mSurfaceControl->getSurface();
return window.get();
}
void GLUtil::disposeNativeWindow(void)
{
if (mComposerClient != NULL)
{
mComposerClient->dispose();
mComposerClient = NULL;
mSurfaceControl = NULL;
}
}
看看效果:opengl_test