上节介绍了 Native 工程初始化,但是我们的窗口什么都没有,这节我们将 NativeActivity 创建的 window 绑定到 OpenGL 创建的 display 的 surface 上,并且绘制背景颜色和三角形,通过三角形绘制出一个矩形
显示系统创建
void Render::initRenderer(android_app *pApp) {
LOGI("initRenderer !")
// 选择您的渲染属性
constexpr EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_NONE
};
// Android 上的默认显示可能就是您想要的
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);
// 找出有多少个配置
EGLint numConfigs;
eglChooseConfig(display, attribs, nullptr, 0, &numConfigs);
// 获取配置列表
std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs);
// 找到我们喜欢的配置。
// 如果我们不关心配置中的其他任何内容,可能会只获取第一个。
// 否则就加入你自己的启发式
config_ = *std::find_if(
supportedConfigs.get(),
supportedConfigs.get() + numConfigs,
[&display](const EGLConfig &config) {
EGLint red, green, blue, depth;
if (eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red)
&& eglGetConfigAttrib(display, config, EGL_GREEN_SIZE,
&green)
&& eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,
&blue)
&& eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE,
&depth)) {
LOGI("Found config with: %d , %d , %d , %d", red,
green, blue, depth);
return red == 8 && green == 8 && blue == 8 &&
depth == 24;
}
return false;
}
);
LOGI("Found %d Configs", numConfigs)
// 创建 GLES 3 上下文
EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLContext context = eglCreateContext(display, config_, nullptr, contextAttribs);
display_ = display;
context_ = context;
// 检查系统上的 openGL
auto opengl_info = {GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS};
for (auto name: opengl_info) {
auto info = glGetString(name);
LOGI("OpenGL Info: %s", info);
}
initSurface(pApp);
LOGI("init completed!")
}
void Render::initSurface(android_app *pApp) {
// 创建合适的 window surface
surface_ = eglCreateWindowSurface(display_, config_, pApp->window, nullptr);
//获取一些窗口指标
if (eglMakeCurrent(display_, surface_, surface_, context_) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent")
return;
}
eglQuerySurface(display_, surface_, EGL_WIDTH, &width_);
eglQuerySurface(display_, surface_, EGL_HEIGHT, &height_);
LOGI("QuerySurface : width = %d , height = %d", width_, height_)
}
绘制
绘制背景色
void BackgroundLayer::draw(Render *render) {
glClearColor(state.x / (float) render->width_,
state.angle,
state.y / (float) render->height_,
1);
glClear(GL_COLOR_BUFFER_BIT);
}
绘制三角形
初始化
class TriangleLayer : public Layer {
void handleInput(AInputEvent *event);
void draw(Render *render);
private:
unsigned int VBO = 0, VAO = 0 , VEO = 0;
bool isInit = false;
float* color = new float [0.0f,0.0f,0.0f,1.f];
float dis = 0.005f;
void init() {
if (isInit) {
return;
}
isInit = true;
// 初始化代码(只运行一次 (除非你的物体频繁改变))
float vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
unsigned int indices[] = {
1, 2, 3 // 第二个三角形
};
//创建 VAO,VBO,VEO
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VEO);
// 绑定VAO
glBindVertexArray(VAO);
// 绑定缓冲,填充数据,把顶点数组复制到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 绑定索引,填充索引数据
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VEO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices),indices,GL_STATIC_DRAW);
// 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) 0);
glEnableVertexAttribArray(0);
// 解绑
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
}
public:
TriangleLayer() {
}
~TriangleLayer(){
glDeleteBuffers(1,&VAO);
glDeleteBuffers(1,&VBO);
glDeleteBuffers(1,&VEO);
}
};
绘制
void TriangleLayer::draw(Render *render) {
// 绘制物体
init();
render->shader_->use();
// 更新uniform颜色
color[0] = color[0] + dis;
color[1] = color[1] + dis;
if (color[1] >= 1.0f) {
color[0] = 1.0f;
color[1] = 1.0f;
dis = -0.005f;
} else if (color[1] <= 0.0f) {
color[0] = 0.0f;
color[1] = 0.0f;
dis = 0.005f;
}
// int vertexColorLocation = render->shader_->getUniformLocation("ourColor");
// glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
// glUniform4f(vertexColorLocation, color[0], color[1], color[2], color[3]);
// glUniform4fv(vertexColorLocation,0,color);
// glUniform4fv(vertexColorLocation,1,color);
render->shader_->setFloat("ourColor",0,color);
render->shader_->setFloat("ourColor",1,color);
glBindVertexArray(VAO);
// glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
}
绘制矩形
只需要将三角形的索引改为6个即可
class TriangleLayer : public Layer {
void init() {
......
unsigned int indices[] = {
// 注意索引从0开始!
// 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
// 这样可以由下标代表顶点组合成矩形
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
......
}
};
绘制
void TriangleLayer::draw(Render *render) {
......
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
......
}
源码:OpenGLDemo#triangle
你好,三角形