OpenGL ES for Android 绘制立方体

news/2024/7/24 12:40:20

在这里插入图片描述
立方体有6个面,8个顶点,因此绘制立方体其实就是绘制6个面。

顶点shader

attribute vec4 a_Position;
attribute vec4 a_color;
varying vec4 v_color;
void main()
{
    v_color = a_color;
    gl_Position = a_Position;
}

a_Position为顶点数据,a_color为顶点颜色数据,v_color为varying变量,传递给我片段shader使用。

片段shader

precision mediump float;
uniform vec4 u_color;
varying vec4 v_color;
void main()
{
    gl_FragColor = v_color;
}

创建program

private fun createProgram() {
            var vertexCode =
                AssetsUtils.readAssetsTxt(
                    context = context,
                    filePath = "glsl/cube_vs.glsl"
                )
            var fragmentCode =
                AssetsUtils.readAssetsTxt(
                    context = context,
                    filePath = "glsl/cube_fs.glsl"
                )
            mProgramHandle = GLTools.createAndLinkProgram(vertexCode, fragmentCode)
        }

cube_vs.cube_fs.glsl分别表示顶点shader和片段shader的文件,存放于assets/glsl目录下,readAssetsTxt为读取assets目录下文件的公用方法。

获取参数句柄

vPositionLoc = GLES20.glGetAttribLocation(mProgramHandle, "a_Position")
mColorLoc = GLES20.glGetAttribLocation(mProgramHandle, "a_color")

初始化顶点数据

private val r: Float = 0.5f
        //顶点坐标
        var vertexBuffer = GLTools.array2Buffer(
            floatArrayOf(
                -r, r, r,//0
                -r, -r, r,//1
                r, -r, r,//2
                r, r, r,//3
                r, -r, -r,//4
                r, r, -r,//5
                -r, -r, -r,//6
                -r, r, -r//7
            )
        )

初始化索引数据

var mIndices = shortArrayOf(
            0, 1, 2, 0, 2, 3,
            3, 2, 4, 3, 4, 5,
            5, 4, 6, 5, 6, 7,
            7, 6, 1, 7, 1, 0,
            7, 0, 3, 7, 3, 5,
            6, 1, 2, 6, 2, 4
        )
val mIndicesBuffer = GLTools.array2Buffer(mIndices)

初始化颜色数据

        var colorBuffer = GLTools.array2Buffer(
            floatArrayOf(
                1f,1f,0f,1f,
                1f,1f,0f,1f,
                1f,1f,0f,1f,
                1f,1f,0f,1f,
                1f,0f,0f,1f,
                1f,0f,0f,1f,
                1f,0f,0f,1f,
                1f,0f,0f,1f
            )
        )

绘制

GLES20.glUseProgram(mProgramHandle)
            //设置顶点数据
            vertexBuffer.position(0)
            GLES20.glEnableVertexAttribArray(vPositionLoc)
            GLES20.glVertexAttribPointer(vPositionLoc, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer)
            //设置颜色数据
            colorBuffer.position(0)
            GLES20.glEnableVertexAttribArray(mColorLoc)
            GLES20.glVertexAttribPointer(mColorLoc, 3, GLES20.GL_FLOAT, false, 0, colorBuffer)
            GLES20.glDrawElements(
                GLES20.GL_TRIANGLES,
                mIndices.size,
                GLES20.GL_UNSIGNED_SHORT,
                mIndicesBuffer
            )

效果图如下:
在这里插入图片描述
我们仅仅看到一个矩形,并没有看到立方体啊?实际上我们已经绘制立方体了,只不过其他面被前面的面挡住了导致我们看不到其他面,如何才能看到其他面呢?这时候需要使用mvp矩阵。

修改顶点shader如下

attribute vec4 a_Position;
attribute vec4 a_color;
uniform mat4 mvpMatrix;
varying vec4 v_color;
void main()
{
    v_color = a_color;
    gl_Position = mvpMatrix * a_Position;
}

添加了mvpMatrix矩阵。

获取mvpMatrix矩阵句柄

mvpMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle,"mvpMatrix")

设置mvp矩阵

override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
            GLES20.glViewport(0, 0, width, height)
            var modelMatrix = FloatArray(16)
            Matrix.setIdentityM(modelMatrix, 0)
            var viewMatrix = FloatArray(16)
            Matrix.setIdentityM(viewMatrix, 0)
            Matrix.setLookAtM(viewMatrix, 0,
                0F, 5F, 10F,
                0F, 0F, 0F,
                0F, 1F, 0F)
            var projectionMatrix = FloatArray(16)
            Matrix.setIdentityM(projectionMatrix, 0)
            val ratio = width.toFloat() / height
            //设置透视投影
            Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 20f)
            var mTempMvMatrix = FloatArray(16)
            Matrix.setIdentityM(mTempMvMatrix, 0)
            Matrix.multiplyMM(mTempMvMatrix, 0, viewMatrix, 0, modelMatrix, 0)
            Matrix.multiplyMM(mMvpMatrix, 0, projectionMatrix, 0, mTempMvMatrix, 0)
        }

在onSurfaceChanged中设置矩阵,绘制的时候设置矩阵数据:

GLES20.glUniformMatrix4fv(mvpMatrixLoc, 1, false, mMvpMatrix, 0)

效果如下:
在这里插入图片描述
我们发现立方体穿透了,出现这样的效果是因为没有开启深度检测,在绘制前清除深度缓存并开启深度检测,代码如下:

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
GLES20.glEnable(GLES20.GL_DEPTH_TEST)

效果如下:
在这里插入图片描述
我们将立方体旋转45度,这样就可以看到立方体的侧面了,将模型矩阵旋转45度代码如下:

var modelMatrix = FloatArray(16)
Matrix.setIdentityM(modelMatrix, 0)
Matrix.rotateM(modelMatrix,0,45F,0F,1F,0F)

效果如下:
在这里插入图片描述

更多相关阅读:

  • OpenGL ES for Android 总览

  • OpenGL ES for Android 环境搭建

  • OpenGL ES 绘制纹理

  • OpenGL ES for Android 绘制三角形


http://www.niftyadmin.cn/n/1846020.html

相关文章

[前端面试套餐css+js+vue]第九天

前端面试套餐css:说说flexbox(弹性盒布局模型)属性容器属性成员属性javascript:解释下什么是事件代理?应用场景?应用场景vue:给对象添加新属性界面不刷新?直接添加属性的问题原理分析解决方案css&#xff1…

OpenGL ES for Android 深度测试

什么是深度 深度就像是现实世界中物体与我们自己之间的距离,而在OpenGL中,深度是像素点(可以理解为现实世界中的物体)距离相机的距离,深度信息保存在深度缓存中,深度值越大则离相机越远。 深度测试有什么…

OpenGL ES for Android 绘制旋转的地球

No 图 No Code,我们先来欣赏下旋转的地球: 是不是很酷炫,要想绘制出上面酷炫的效果需要3个步骤: 计算球体顶点数据地球纹理贴图通过MVP矩阵旋转地球 计算球体顶点数据 我们知道OpenGL中最基本的图元是三角形,任何复…

关于阿里巴巴icon矢量图显示空白问题

关于阿里巴巴icon矢量图显示空白问题关于icon显示空白关于icon显示空白 最近在帮着做一些小项目,期间遇到不少问题,也尝试着在网上找问题的答案,接下来就有一个很细节的问题使得我在使用阿里巴巴的iconfont矢量图的时候出现了矢量图在页面中…

小白记录学习Dajngo的第二天

小白学习Django的第二天 用博客记录 python学习 沙雕错误 今天学到了给url命名与url反转的时候 新建了两个app,在两个新建的app下的urls.py文件中导入path模块后的一系列操作后运行项目,结果Pycharm毫不留情的弹出了错误 我再到urls.py中看时发现了这…

关于VC++6.0显示“不能启动工具,操作成功完成”问题

小白迷惑之VC6.0运行错误 今天在上C语言实验课的时候,在运行一个C程序的时候VC6.0显示错误:不能启动工具,操作成功完成 如图: 就像这样,嗯???这是什么情况??…

Django链接MySQL数据库,报错Did you install mysqlclient?

Django链接MySQL数据库,报错"Did you install mysqlclient?" 环境说明: win10 专业版 python 3.8.4 Django 2.3.1 在一切都配置好之后我操作数据库时,弹出错误 django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module…

MySQL安装的requirements问题

MySQL安装的requirements问题 环境说明: win10 专业版 python 3.8.4 安装Microsoft Visual C 2019安装Microsoft Visual 2015和 2017或者2019的Python需要下载64位的,这个我当时下载了3.8.x的64位的,但是在check requirements页面还是显示py…