有了以上基类,既然我们的目标是绘制一个三角形,那么我们在Java层和C++层再新建一个TriangleOpengl的类吧,他们都继承TriangleOpengl:
TriangleOpengl.javapublic class TriangleOpengl extends BaseOpengl{public TriangleOpengl() {super(BaseOpengl.DRAW_TYPE_TRIANGLE);}}C++ TriangleOpengl类,TriangleOpengl.h:
#ifndef NDK_OPENGLES_LEARN_TRIANGLEOPENGL_H#define NDK_OPENGLES_LEARN_TRIANGLEOPENGL_H#include "BaseOpengl.h"class TriangleOpengl: public BaseOpengl{public:TriangleOpengl();virtual ~TriangleOpengl();virtual void onDraw();private:GLint positionHandle{-1};GLint colorHandle{-1};};#endif //NDK_OPENGLES_LEARN_TRIANGLEOPENGL_HTriangleOpengl.cpp:
#include "TriangleOpengl.h"#include "../utils/Log.h"// 定点着色器static const char *ver = "#version 300 es\n""in vec4 aColor;\n""in vec4 aPosition;\n""out vec4 vColor;\n""void main() {\n""vColor = aColor;\n""gl_Position = aPosition;\n""}";// 片元着色器static const char *fragment = "#version 300 es\n""precision mediump float;\n""in vec4 vColor;\n""out vec4 fragColor;\n""void main() {\n""fragColor = vColor;\n""}";// 三角形三个顶点const static GLfloat VERTICES[] = {0.0f,0.5f,-0.5f,-0.5f,0.5f,-0.5f};// rgbaconst static GLfloat COLOR_ICES[] = {0.0f,0.0f,1.0f,1.0f};TriangleOpengl::TriangleOpengl():BaseOpengl() {initGlProgram(ver,fragment);positionHandle = glGetAttribLocation(program,"aPosition");colorHandle = glGetAttribLocation(program,"aColor");LOGD("program:%d",program);LOGD("positionHandle:%d",positionHandle);LOGD("colorHandle:%d",colorHandle);}TriangleOpengl::~TriangleOpengl() noexcept {}void TriangleOpengl::onDraw() {LOGD("TriangleOpengl onDraw");glClearColor(0.0f, 1.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(program);/*** size 几个数字表示一个点,显示是两个数字表示一个点* normalized 是否需要归一化,不用,这里已经归一化了* stride 步长,连续顶点之间的间隔,如果顶点直接是连续的,也可填0*/glVertexAttribPointer(positionHandle,2,GL_FLOAT,GL_FALSE,0,VERTICES);// 启用顶点数据glEnableVertexAttribArray(positionHandle);// 这个不需要glEnableVertexAttribArrayglVertexAttrib4fv(colorHandle, COLOR_ICES);glDrawArrays(GL_TRIANGLES,0,3);glUseProgram(0);// 禁用顶点glDisableVertexAttribArray(positionHandle);if(nullptr != eglHelper){eglHelper->swapBuffers();}LOGD("TriangleOpengl onDraw--end");}在前面的章节中我们介绍了着色器的创建、编译、链接等,但是缺少了具体使用方式,这里我们补充说明一下 。
着色器的使用只要搞懂如何传递数据给着色器中变量 。首先我们需要获取到着色器程序中的变量,然后赋值 。
我们看上面的TriangleOpengl.cpp的构造函数:
TriangleOpengl::TriangleOpengl():BaseOpengl() {initGlProgram(ver,fragment);// 获取aPosition变量positionHandle = glGetAttribLocation(program,"aPosition");// 获取aColorcolorHandle = glGetAttribLocation(program,"aColor");LOGD("program:%d",program);LOGD("positionHandle:%d",positionHandle);LOGD("colorHandle:%d",colorHandle);}由上,我们通过函数glGetAttribLocation获取了变量aPosition和aColor的句柄,这里我们定义的aPosition和aColor是向量变量,如果我们定义的是uniform统一变量的话,则需要使用函数glGetUniformLocation获取统一变量句柄 。有了这些变量句柄,我们就可以通过这些变量句柄传递函数给着色器程序了,具体可参考TriangleOpengl.cpp的onDraw函数 。
此外如果变量是一个统一变量(uniform)的话,则通过一系列的 glUniform...函数传递参数 。
这里说明一下函数glVertexAttribPointer的stride参数,一般情况下不会用到,传递0即可,但是如果需要提高性能,例如将顶点坐标和纹理/颜色坐标等放在同一个数组中传递,则需要使用到这个stride参数了,目前顶点坐标数组和其他数组是分离的,暂时可以不管 。
经验总结扩展阅读
- 投我以木桃报之以琼瑶是什么意思
- 陆战之王里面的叶晓俊是谁演的
- 24 《吐血整理》高级系列教程-吃透Fiddler抓包教程-Fiddler如何优雅地在正式和测试环境之间来回切换-中篇
- 阴阳师六道之门白狼怎么玩
- 阴阳师六道之门大天狗怎么玩
- 烟雨江湖宋谦之在哪里
- 晕车后吃什么可以缓解
- 尿道炎是怎么引起的
- flutter系列之:查询设备信息的利器:MediaQuery
- 皇帝系统之类的小说
