opengl android编译,Android OpenGL ES - 环境搭建与简单三角形的绘制

OpenGL ES Android 环境搭建

EGL

OpenGL 是一个跨平台的API,而不同的操作系统(Windows,Android,IOS)各有自己的屏幕渲染实现。所以OpenGL定义了一个中间接口层EGL(Embedded Graphics Library)标准,具体实现交给各个操作系统本身。关于EGL我们后面会仔细介绍,现在先有个概念。

基于EGL的GLSurfaceView

Android 框架中有如下两个基本类,用于通过 OpenGL ES API 来创建和操控图形:[GLSurfaceView](https://developer.android.com/reference/android/opengl/GLSurfaceView) 和 [GLSurfaceView.Renderer](https://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer)。如果您要在 Android 应用中使用 OpenGL,那么了解如何在 Activity 中实现这些类应是您的首要任务。

GLSurfaceView 以及 GLSurfaceView.Renderer

GLSurfaceView作为Android中的View组件,在View的属性上与其他组件并无不同,不过在其中实现了我们上面所说的EGL接口,GLSurfaceView.Renderer是一个接口,用来给用户自己处理回调

总体流程如下图所示:

bVcHgCB

下面给出核心代码,完整代码链接放在文末public class DemoActivity extends AppCompatActivity {

@BindView(R.id.gl_surface)

GLSurfaceView glSurface;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_demo);

ButterKnife.bind(this);

MyGLRender renderer = new MyGLRender();

renderer.setDrawer(createTriangleDrawer());

glSurface.setEGLContextClientVersion(2);

glSurface.setRenderer(renderer);

}

}private static class MyGLRender implements GLSurfaceView.Renderer {

private int iDrawer = -1;

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

GLES20.glClearColor(0f, 0f, 0f, 0f);

//------开启混合,即半透明---------

// 开启很混合模式

GLES20.glEnable(GLES20.GL_BLEND);

// 配置混合算法

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

//------------------------------

}

@Override

public void onSurfaceChanged(GL10 gl, int width, int height) {

GLES20.glViewport(0, 0, width, height);

}

@Override

public void onDrawFrame(GL10 gl) {

// 清屏,否则会有画面残留

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

if (iDrawer != -1)

drawTriangle(iDrawer);

}

public void setDrawer(int iDrawer) {

this.iDrawer = iDrawer;

}

public native int createTriangleDrawer();

public native void drawTriangle(int drawer);

}

上面使我们的环境搭建,大家可以看到TriangleDrawer这个类,这个就是我们搭建好环境之后真正进入OpenGL中的敲门砖了。

关于GLSurfaceView 以及 GLSurfaceView.Renderer

的详情可参考官方文档Android OpenGL ES官方文档,入门必看。不过我开始看官方文档的时候也是一头雾水,所以写了博客,一是加深自己的理解,二是希望能帮助到大家。

简单三角形的绘制

我们前面也说过在OpenGL中只有3种基本图形,点,线,三角形,其他的几何图形都是有这几种图形表示

所以我们先来牛刀小试,来实现一个三角形增加一下信心:由于OpenGL是跨平台的,所以我下面的代码核心部分是用C/C++写的,可能要求对于NDK有一定熟悉度,Android本身也提供了一些API,不过我们之所以绕一圈用C/C++是因为Android中的Java API的部分底层也是调用OpenGL C/C++的SO库。

首先定义一个纯虚类(用作接口)

base_drawer.h#ifndef BLOGDEMO_BASE_DRAWER_H

#define BLOGDEMO_BASE_DRAWER_H

class BaseDrawer {

virtual void Draw() = 0;

virtual void Release() = 0;

};

#endif //BLOGDEMO_BASE_DRAWER_H

接着定义TriangleDrawer来实现绘制三角形

triangle_drawer.h部分代码#ifndef BLOGDEMO_TRIANGLE_DRAWER_H

#define BLOGDEMO_TRIANGLE_DRAWER_H

#include "base_drawer.h"

#include

class TriangleDrawer : public BaseDrawer {

private:

const char *TAG = "Drawer";

const GLfloat m_vertex_coors[9] = {

-0.5f, -0.5f, 0.0f,//左下

0.5f, -0.5f, 0.0f,//右下

0.0f, 0.5f, 0.0f//上

};

GLuint m_program_id = 0;

GLint m_vertex_pos_handler = -1;

void CreateProgram();

GLuint LoadShader(GLenum type, const GLchar *shader_code);

public:

TriangleDrawer();

~TriangleDrawer();

void Draw() override;

void Release() override;

void DoDraw();

const GLchar *GetVertexShader();

const GLchar *GetFragmentShader();

};

#endif //BLOGDEMO_TRIANGLE_DRAWER_H

base_drawer.cpp部分代码void TriangleDrawer::Draw() {

CreateProgram();

DoDraw();

}

void TriangleDrawer::CreateProgram() {

if (m_program_id == 0) {

//创建一个空的OpenGLES程序,注意:需要在OpenGL渲染线程中创建,否则无法渲染

m_program_id = glCreateProgram();

LOGI(TAG, "create gl program : %d, %x", m_program_id, glGetError());

if (glGetError() != GL_NO_ERROR) {

return;

}

GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, GetVertexShader());

GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, GetFragmentShader());

//将顶点着色器加入到程序

glAttachShader(m_program_id, vertexShader);

//将片元着色器加入到程序中

glAttachShader(m_program_id, fragmentShader);

//连接到着色器程序

glLinkProgram(m_program_id);

m_vertex_pos_handler = glGetAttribLocation(m_program_id, "aPosition");

glDeleteShader(vertexShader);

glDeleteShader(fragmentShader);

}

//使用OpenGL程序

if (m_program_id != 0) {

glUseProgram(m_program_id);

}

}

GLuint TriangleDrawer::LoadShader(GLenum type, const GLchar *shader_code) {

LOGI(TAG, "Load shader:n %s", shader_code)

//根据type创建顶点着色器或者片元着色器

GLuint shader = glCreateShader(type);

//将资源加入到着色器中,并编译

glShaderSource(shader, 1, &shader_code, NULL);

glCompileShader(shader);

GLint compiled;

// 检查编译状态

glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);

if (!compiled) {

GLint infoLen = 0;

glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);

if (infoLen > 1) {

GLchar *infoLog = (GLchar *) malloc(sizeof(GLchar) * infoLen);

glGetShaderInfoLog(shader, infoLen, NULL, infoLog);

LOGI(TAG, "Error compiling shader:n%sn", infoLog);

free(infoLog);

}

glDeleteShader(shader);

return 0;

}

return shader;

}

void TriangleDrawer::DoDraw() {

//启用顶点的句柄

glEnableVertexAttribArray(m_vertex_pos_handler);

glVertexAttribPointer(m_vertex_pos_handler, 3, GL_FLOAT, GL_FALSE, 0, m_vertex_coors);

//开始绘制

glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);

}

上来就是一对代码是不是一脸懵,我刚开始学习的时候也是这样,上面的官方文档中也没给出什么能让人容易理解的文字描述。所以这也是这篇博客的意义。

我们先来看2个字符串

//顶点着色器(Vertex Shader)const char *TriangleDrawer::GetVertexShader() {

return "attribute vec4 aPosition; \n"

"void main() \n"

"{ \n"

" gl_Position = aPosition; \n"

"} \n";

}

//片段着色器(Fragment Shader)const char *TriangleDrawer::GetFragmentShader() {

return "precision mediump float; \n"

"void main() \n"

"{ \n"

" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"

"} \n";

}

这2个字符串就是我们所谓的OpenGL Shader代码,它是用一种被称作GLSL(GL Shader Language)的类似C语言的语言所写的,是不是很拗口,其实把GLSL当做是一种开发语言就行了,在开发语言层面上跟java啦,C啊差不多,只不过它的写法与C十分类似。既然是一种开发语言,数据结构、关键字、语法这些东西总是绕不过的,不过GLSL虽然比较简单,但是完整的介绍其语法也不是一两句能说清楚的,我们后面会说,这不是本章的重点,本章的重点是我们已经写好了上面的Vertex Shader和Fragment Shader,但是OpenGL如何使用呢,下面看图

bVcHkET

我上面的代码也是根据这个流程写的,这个是个通用的流程,大家可以封装一下,避免重复劳动

总结

本篇介绍了OpenGL ES在Android上的环境,并且用GLSL写了一个三角形增加信心,经过这篇文章之后我们应该对GLSL的使用流程有了初步的理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值