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_H
TriangleOpengl.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参数了,目前顶点坐标数组和其他数组是分离的,暂时可以不管 。
在Activity中调用一下测试结果:
public class DrawTriangleActivity extends AppCompatActivity {private TriangleOpengl mTriangleOpengl;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_draw_triangle);MyGLSurfaceView glSurfaceView = findViewById(R.id.my_gl_surface_view);mTriangleOpengl = new TriangleOpengl();glSurfaceView.setBaseOpengl(mTriangleOpengl);glSurfaceView.setOnDrawListener(new MyGLSurfaceView.OnDrawListener() {@Overridepublic void onDrawFrame() {mTriangleOpengl.onGlDraw();}});}@Overrideprotected void onDestroy() {if(null != mTriangleOpengl){mTriangleOpengl.release();}super.onDestroy();}}
如果运行起来,看到一个蓝色的三角形,则说明三角形绘制成功啦!
文章插图
源码想来还是不贴源码链接了,纸上得来终觉浅,绝知此事要躬行 。很多时候就是这样,你看着觉得很简单,实际如何还得动手敲,只有在敲的过程中出了问题,然后你解决了 , 只是才算是你的 。
在这个系列完毕后再贴出整个项目demo的代码吧 。。。
推荐阅读
- 24 《吐血整理》高级系列教程-吃透Fiddler抓包教程-Fiddler如何优雅地在正式和测试环境之间来回切换-中篇
- 阴阳师六道之门白狼怎么玩
- 阴阳师六道之门大天狗怎么玩
- flutter系列之:查询设备信息的利器:MediaQuery
- ERP 与 CRM 之间有什么联系?
- DophineSheduler上下游任务之间动态传参案例及易错点总结
- 跟我学Python图像处理丨傅里叶变换之高通滤波和低通滤波
- 【原创】推流录屏软件OBS使用教程--录屏
- 之三 2流高手速成记:SpringBoot整合mybatis/mybatis-plus实现数据持久化
- 怎样打麻将,才能立于不败之地(麻将三不打三必输)