当前位置: 首页 > article >正文

Android Opengl(三)绘制三角形

一、GLSurfaceView

GLSurfaceView 类提供了用于管理 EGL 上下文、在线程间通信以及与 activity 生命周期交互的辅助程序类。您无需使用 GLSurfaceView 即可使用 GLES。

例如,GLSurfaceView 会创建一个渲染线程,并在线程上配置 EGL 上下文。当 Activity 暂停时,状态将自动清除。大多数应用无需了解有关 EGL 的任何信息即可通过 GLSurfaceView 来使用GLES。

二、绘制三角形

OpenGl绘制图形的基本步

  • 使用GLSurfaceView创建OpenGl ES环境

  • 编译着色器程序(顶点着色器+片元着色器)

    创建shader对象,GLES30.glCreateShader(type)
    指定Shader源码,GLES30.glShaderSource()
    编译Shader,GLES30.glCompileShader(shader)

  • 链接OpenGL程序
    创建OpenGl程序,GLES30.glCreateProgram()
    绑定Shader到OpenGL程序,GLES30.glAttachShader()
    链接OpenGL程序,GLES30.glLinkProgram()

  • 使用OpenGL程序
    使用OpenGL程序,GLES30.glUseProgram()
    传递顶点数据
    传递片元数据

绘制三角形大体步骤

1、使用GLSurfaceView作为布局展示
2、对GLSurfaceView初始化,初始化时需要使用到GLSurfaceView.Renderer。
3、GLSurfaceView.Renderer中回调

  • onSurfaceCreated
  • onSurfaceChanged
  • onDrawFrame

在上面三个函数中进行处理绘制三角形逻辑。

1、使用GLSurfaceView作为布局展示

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.opengl.GLSurfaceView
        android:id="@+id/glSurfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

2、对GLSurfaceView初始化,初始化时需要使用到GLSurfaceView.Renderer。

下面的代码是在Activity中的。

    private fun initGlSurfaceView() {
        // 设置OpenGL版本号
        glSurfaceView?.setEGLContextClientVersion(2)
        val render = DemoGlRender()
        // 设置openGl的Render
        glSurfaceView?.setRenderer(render)
        // 默认渲染方式为RENDERMODE_CONTINUOUSLY
        //  当设置为RENDERMODE_WHEN_DIRTY时只有在创建和调用requestRender()时才会刷新。
        glSurfaceView?.renderMode = RENDERMODE_WHEN_DIRTY
        //   当设置为RENDERMODE_CONTINUOUSLY时渲染器会不停地渲染场景
//        glSurfaceView?.renderMode = RENDERMODE_CONTINUOUSLY
    }

    override fun onResume() {
        super.onResume()
        glSurfaceView?.onResume()
    }

    override fun onPause() {
        super.onPause()
        glSurfaceView?.onPause()
    }

默认渲染方式为RENDERMODE_CONTINUOUSLY

  • RENDERMODE_CONTINUOUSLY模式
    当设置为RENDERMODE_CONTINUOUSLY时渲染器会不停地渲染场景,

  • RENDERMODE_WHEN_DIRTY模式
    当设置为RENDERMODE_WHEN_DIRTY时只有在创建和调用requestRender()时才会刷新。

3、GLSurfaceView.Renderer实现类中处理onSurfaceCreated、onSurfaceChanged、onDrawFrame

onSurfaceCreated:设置屏幕颜色、加载shader程序、挂载program
onDrawFrame:激活顶点坐标、绑定定点数据、绑定颜色数据、绘制

class DemoGlRender : GLSurfaceView.Renderer {
    /*
     * 顶点位置程序
     */
    private val vertexShaderCode =
        "attribute vec4 vPosition;" +
                "void main() { " +
                "   gl_Position = vPosition;" +
                "}"

    /**
     * 片元颜色程序
     */
    private val fragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() { " +
                "   gl_FragColor = vColor;" +
                "}"

    /**
     * 三角形顶点位置
     */
    private val triangleCoors = floatArrayOf(
        0.5f, 0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    )

    /**
     * 三角形颜色值
     */
    private val color = floatArrayOf(
        1.0f, 1.0f, 1.0f, 1.0f
    )

    private var program: Int? = null
    private var vertexBuffer: FloatBuffer? = null
    override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
        // 设置背景颜色
        GLES20.glClearColor(1f, 0f, 0f, 1.0f)
        // 清理缓存
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        createFloatBuffer()
        // 创建定点着色程序
        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
        // 创建片元着色程序
        val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)
        if (vertexShader == 0 || fragmentShader == 0) {
            return;
        }
        linkProgram(vertexShader, fragmentShader)
    }

    private fun createFloatBuffer() {
        // 申请物理层空间
        val byteBuffer = ByteBuffer.allocateDirect(triangleCoors.size * 4).apply {
            this.order(ByteOrder.nativeOrder())
        }
        // 坐标数据转换
        vertexBuffer = byteBuffer.asFloatBuffer()
        vertexBuffer?.put(triangleCoors, 0, triangleCoors.size)
        vertexBuffer?.position(0)
    }

    private fun linkProgram(vertexShader: Int, fragmentShader: Int) {
        // 创建空的opengl es 程序
        program = GLES20.glCreateProgram()
        program?.let {
            // 将顶点着色器加入程序
            GLES20.glAttachShader(it, vertexShader)
            // 将片元着色器加入程序
            GLES20.glAttachShader(it, fragmentShader)
            // 链接到着色器程序
            GLES20.glLinkProgram(it)
            // 将程序加入到opengl30环境中
            GLES20.glUseProgram(it)
            val info = GLES20.glGetProgramInfoLog(it)
            // 打印链接程序日志
            Log.e("wdf", "info==" + info)
        }
    }


    override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
        // 设置绘制窗口
        GLES20.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(p0: GL10?) {
        program ?: return
        if (program == 0) {
            return
        }
        program?.let {
            GLES20.glClear(GLES30.GL_COLOR_BUFFER_BIT)
            GLES20.glUseProgram(it)
            // 获取顶点着色器的vPosition,与程序中声明vPosition变量名保持一致
            val vPosition = GLES20.glGetAttribLocation(it, "vPosition")
            GLES20.glEnableVertexAttribArray(vPosition)
            // 3*4是指  跨3个读下一个顶点
            GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer)
            // 设置三角形颜色,与程序中声明vColor变量名保持一致
            val vColor = GLES20.glGetUniformLocation(it, "vColor")
            GLES20.glUniform4fv(vColor, 1, color, 0)
            // 绘制
            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3)
            GLES20.glDisableVertexAttribArray(vPosition)
        }
    }


    /**
     * 创建shader,加载shader程序
     */
    private fun loadShader(type: Int, shaderCode: String): Int {
        val shader = GLES20.glCreateShader(type)
        GLES20.glShaderSource(shader, shaderCode)
        GLES20.glCompileShader(shader)
        return shader
    }

}

三、为什么要给GLSurfaceView设置GLSurfaceView.Renderer

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/463574.html

相关文章:

  • Python 数据可视化的完整指南
  • LLaMA详解
  • springboot520基于Spring Boot的民宿租赁系统的设计与实现(论文+源码)_kaic
  • 安卓入门四 Application Component
  • ubuntu2204 gpu 没接显示器,如何连接vnc
  • JnetPcap抓取数据包IP数据包
  • 3、redis的集群模式
  • selenium 安装Chrome驱动
  • 用点包图洞察医学数据:以血压分析为例
  • 服务器网卡绑定mode和交换机的对应关系
  • MySQL 索引优化实战 – 结合 Explain 深度解析慢查询
  • REST与RPC的对比:从性能到扩展性的全面分析
  • 非关系型数据库和关系型数据库的区别
  • 免登录游客卡密发放系统PHP网站源码
  • Excel 面试 01 “Highlight in red the 10 lowest orders”
  • 如何查看下载到本地的大模型的具体大小?占了多少存储空间:Llama-3.1-8B下载到本地大概15GB
  • 系统架构风险、敏感点和权衡点的理解
  • MySQL数据库笔记——主从复制
  • Redis 实战篇 ——《黑马点评》(上)
  • 关于内网服务器依托可上网电脑实现访问互联网