• OpenGLES:绘制一个混色旋转的3D立方体


    效果展示

    混色旋转的3D立方体

    一.概述

    之前关于OpenGLES实战开发的博文,不论是实现相机滤镜还是绘制图形,都是在2D纬度

    这篇博文开始,将会使用OpenGLES进入3D世界

    本篇博文会实现一个颜色渐变、旋转的3D立方体

    动态3D图形的绘制,需要具备一些基础的线性代数(向量、矩阵)空间坐标系转换相关知识,这里就不再做理论科普,需要自己先行学习,具体可以参考OpenGL官网的如下三章,讲解得十分详细:

    1. 《变换》
    2. 《坐标系统》
    3. 《摄像机》

    二.GLRender:变量定义

    2.1 常规变量定义

    1. //shader程序/渲染器
    2. private int shaderProgram;
    3. private int vPosition;
    4. private int aColor;
    5. private int mvpMatrix;
    6. //suface宽高比
    7. private float ratio;

    2.2 定义顶点、颜色、索引数组和缓冲

    本次立方体的绘制,先定义顶点、颜色和索引数组,然后通过直接绘制索引缓冲来绘制立方体

    三个数组及缓冲定义如下:

    1. private FloatBuffer vertexBuffer;
    2. private FloatBuffer colorBuffer;
    3. private ShortBuffer indexBuffer;
    4. private float vertexData[] = {
    5. -1.0f, 1.0f, 1.0f, //正面左上0
    6. -1.0f, -1.0f, 1.0f, //正面左下1
    7. 1.0f, -1.0f, 1.0f, //正面右下2
    8. 1.0f, 1.0f, 1.0f, //正面右上3
    9. -1.0f, 1.0f, -1.0f, //反面左上4
    10. -1.0f, -1.0f, -1.0f, //反面左下5
    11. 1.0f, -1.0f, -1.0f, //反面右下6
    12. 1.0f, 1.0f, -1.0f, //反面右上7
    13. };
    14. //八个顶点的颜色,与顶点坐标一一对应
    15. private float colorData[] = {
    16. 1.0f, 1.0f, 0.0f, // v0 Yellow
    17. 1.0f, 0.0f, 1.0f, // v1 Magenta 粉红
    18. 1.0f, 0.0f, 0.0f, // v2 Red
    19. 1.0f, 1.0f, 1.0f, // v3 White
    20. 0.0f, 0.0f, 1.0f, // v4 Blue
    21. 0.0f, 1.0f, 1.0f, // v5 Cyan 蓝绿
    22. 0.0f, 1.0f, 0.0f, // v6 Green
    23. 0.0f, 0.0f, 0.0f, // v7 Black
    24. };
    25. private short indexData[] = {
    26. 6, 7, 4, 6, 4, 5, //后面
    27. 6, 3, 7, 6, 2, 3, //右面
    28. 6, 5, 1, 6, 1, 2, //下面
    29. 0, 3, 2, 0, 2, 1, //正面
    30. 0, 1, 5, 0, 5, 4, //左面
    31. 0, 7, 3, 0, 4, 7, //上面
    32. };

    2.3 定义MVP矩阵

    1. //MVP矩阵
    2. private float[] mMVPMatrix = new float[16];

    三.GLRender:着色器、内存分配等

    3.1 着色器创建、链接、使用

    3.2 着色器属性获取、赋值

    3.3 三个缓冲内存分配

    这几个部分的代码实现与上一篇2D圆绘制基本一致

    可以参考上一篇博文:《OpenGLES:绘制一个颜色渐变的圆》

    不再重复展示代码

    四.GLRender:绘制

    绘制流程与之前2D的基本一致,有两点不太一样要注意

    4.1 MVP矩阵赋值

    1. //填充MVP矩阵
    2. mMVPMatrix = TransformUtils.getCubeMVPMatrix(ratio);
    3. //设置MVP变换矩阵到着色器程序/渲染器
    4. glUniformMatrix4fv(mvpMatrix, 1, false, mMVPMatrix, 0);
    1. //计算MVP变换矩阵
    2. public static float[] getCubeMVPMatrix(float ratio) {
    3. //初始化modelMatrix, viewMatrix, projectionMatrix
    4. float[] modelMatrix = getIdentityMatrix(16, 0); //模型变换矩阵
    5. float[] viewMatrix = getIdentityMatrix(16, 0); //观测变换矩阵/相机矩阵
    6. float[] projectionMatrix = getIdentityMatrix(16, 0); //投影变换矩阵
    7. //获取modelMatrix, viewMatrix, projectionMatrix
    8. mCubeRotateAgree = (mCubeRotateAgree + 1) % 360;
    9. Matrix.rotateM(modelMatrix, 0, mCubeRotateAgree, -1, -1, 1); //获取模型旋转变换矩阵
    10. Matrix.setLookAtM(viewMatrix, 0, 0, 5, 10, 0, 0, 0, 0, 1, 0); //获取观测变换矩阵,设置相机位置
    11. Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 20); //获取透视投影变换矩阵,正交投影:Matrix.orthoM(...)
    12. //计算MVP变换矩阵: mvpMatrix = projectionMatrix * viewMatrix * modelMatrix
    13. float[] tempMatrix = new float[16];
    14. float[] mvpMatrix = new float[16];
    15. Matrix.multiplyMM(tempMatrix, 0, viewMatrix, 0, modelMatrix, 0);
    16. Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, tempMatrix, 0);
    17. return mvpMatrix;
    18. }

    4.2 绘制索引缓冲

    1. //索引法绘制正方体
    2. glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_SHORT, indexBuffer);

    五.着色器代码

    着色器代码与上一篇2D圆绘制其实也是相同的

    再展示一遍以示关键点

    如下:

    (1).cube_vertex_shader.glsl

    1. #version 300 es
    2. layout (location = 0) in vec4 vPosition;
    3. layout (location = 1) in vec4 aColor;
    4. uniform mat4 mvpMatrix;
    5. out vec4 vColor;
    6. void main() {
    7. gl_Position = mvpMatrix * vPosition;
    8. vColor = aColor;
    9. }

    (2).cube_fragtment_shader.glsl

    1. #version 300 es
    2. #extension GL_OES_EGL_image_external_essl3 : require
    3. precision mediump float;
    4. in vec4 vColor;
    5. out vec4 outColor;
    6. void main(){
    7. outColor = vColor;
    8. }

    六.结束语

    混色旋转3D立方体的实现过程到此讲解结束

    最终实现效果如博文开始的效果展示

  • 相关阅读:
    Java对象的创建
    Go语言GoFrame+Vue+ElementUI搭建的系统后台框架
    nodejs毕业设计源码基于node.js的博客系统
    1000元订金?华为折叠屏手机MateX5今日开始预订,售价尚未公布
    第五章 树 24 AcWing 1636. 最低公共祖先
    行为型模式-策略模式
    什么是Jsoup
    《算法通关村——最长公共前缀问题解析》
    获取网卡上的IP、网关及DNS信息,获取最佳路由,遍历路由表中的条目(附源码)
    配置测试ip、正式ip、本地ip
  • 原文地址:https://blog.csdn.net/geyichongchujianghu/article/details/133282747