Android OpenGL ES 学习(五) -- 渐变色

这篇具有很好参考价值的文章主要介绍了Android OpenGL ES 学习(五) -- 渐变色。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

OpenGL 学习教程
Android OpenGL ES 学习(一) – 基本概念
Android OpenGL ES 学习(二) – 图形渲染管线和GLSL
Android OpenGL ES 学习(三) – 绘制平面图形
Android OpenGL ES 学习(四) – 正交投屏
Android OpenGL ES 学习(五) – 渐变色
Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序
Android OpenGL ES 学习(七) – 纹理
代码工程地址: https://github.com/LillteZheng/OpenGLDemo.git

这次要完成的效果:
Android OpenGL ES 学习(五) -- 渐变色
前面的代码中,我们的颜色是写死一种的,如何实现上面的渐变色呢?
这里就需要用到光栅化:
Android OpenGL ES 学习(五) -- 渐变色
再复习一下光栅化的概念:它会图元映射成屏幕上相应的像素,生成供片段着色器使用上色的片段。

前面说道,顶点数据不止包含位置,还有其他信息,所以,在绘制顶点位置的时候,也传递顶点颜色,由 OpenGL 实现栅格化的效果。
这里,你可能会有疑惑,传递了三个颜色,也应该也是三个颜色啊,怎么会有渐变色呢?
带着疑问,我们来试试。

一. 着色器代码

前面说道,GLSL 在3.0 使用 in 和 out 来在着色器之间,传递数值。所以,我们在顶点着色器中使用 out 定义相同名字的颜色,在片段着色器中,使用 in 接收端相同的名字的颜色值。

private const val VERTEX_SHADER = """#version 300 es
          layout(location = 0) in vec4 a_Position;
          // mat4:4×4的矩阵
          uniform mat4 u_Matrix;
          //定义可以给外部赋值的顶点数据
          layout(location = 1) in vec4 a_Color;
          //给片段着色器的颜色顶点
          out vec4 vTextColor;
          void main()
          {
              // 矩阵与向量相乘得到最终的位置
              gl_Position = u_Matrix * a_Position;
              gl_PointSize = 30.0;
              //传递给片段着色器的颜色
              vTextColor = a_Color;
          
          }
  """

private const val FRAGMENT_SHADER = """#version 300 es
        precision mediump float;
        out vec4 FragColor;
        //接收端顶点着色器的数据,名字要相同
        in vec4 vTextColor;
        void main()
        {
          FragColor = vTextColor;
        }
"""

1.1 定义三角形的顶点位置和颜色

        private val POINT_DATA = floatArrayOf(
            //三角形,用三个分量,z 分量为 0
            0f,0.5f,0f,
            -0.5f,-0.5f,0f,
            0.5f,-0.5f,0f
        )
        private val COLOR_DATA = floatArrayOf(
            //颜色值 RGB
            1f,0.5f,0.5f,
            1f,0f,1f,
            0f,0.5f,1f
        )
 
 //加载到内存
 private var vertexData = BufferUtil.createFloatBuffer(POINT_DATA)
 private var colorData = BufferUtil.createFloatBuffer(COLOR_DATA)

1.2 关联和使用顶点索引数据:

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(1f, 1f, 1f, 1f)
        makeProgram(VERTEX_SHADER, FRAGMENT_SHADER)

        uMatrix = getUniform(U_MATRIX)

        GLES30.glVertexAttribPointer(
            0, 3, GLES30.GL_FLOAT,
            false, 0, vertexData
        )
        GLES30.glEnableVertexAttribArray(0)

        GLES30.glVertexAttribPointer(
            1, 3, GLES30.GL_FLOAT,
            false, 0, colorData
        )
        GLES30.glEnableVertexAttribArray(1)
    }

1.3 绘制:

    override fun onDrawFrame(gl: GL10?) {
        //步骤1:使用glClearColor设置的颜色,刷新Surface
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP,0,3)

    }

效果:
Android OpenGL ES 学习(五) -- 渐变色
嗯嗯。。。 ,是的,为啥是渐变色的?不是传了三个颜色吗?
看看官网的解释:

这个图片可能不是你所期望的那种,因为我们只提供了3个颜色,而不是我们现在看到的大调色板。这是在片段着色器中进行的所谓片段插值(Fragment Interpolation)的结果。当渲染一个三角形时,光栅化(Rasterization)阶段通常会造成比原指定顶点更多的片段。光栅会根据每个片段在三角形形状上所处相对位置决定这些片段的位置。
基于这些位置,它会插值(Interpolate)所有片段着色器的输入变量。比如说,我们有一个线段,上面的端点是绿色的,下面的端点是蓝色的。如果一个片段着色器在线段的70%的位置运行,它的颜色输入属性就会是一个绿色和蓝色的线性结合;更精确地说就是30%蓝 + 70%绿。
这正是在这个三角形中发生了什么。我们有3个顶点,和相应的3个颜色,从这个三角形的像素来看它可能包含50000左右的片段,片段着色器为这些像素进行插值颜色。

什么意思呢,我的理解是,这个三角形在光栅化的时候,被分割成N多个小像素点,再填充颜色时候,也是按像素去填充的,从三角形的颜色来看,也可以知道,它是从酒红色过度到蓝色的。

为了验证这个说法也比较简单,我们绘制一条先,它只有两个点,红色和蓝色,看看表现如何,修改顶点数据为线:

        private val POINT_DATA = floatArrayOf(
            //线段
            -0.5f,0f,0f,
            0.5f,0f,0f
        )
        private val COLOR_DATA = floatArrayOf(
            //颜色值 RGB
            1f,0f,0f,
            0f,0f,1f,
        )

绘制那里从三角形改成线

    override fun onDrawFrame(gl: GL10?) {
        //步骤1:使用glClearColor设置的颜色,刷新Surface
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        GLES30.glLineWidth(10f)
        GLES30.glDrawArrays(GLES30.GL_LINES,0,2)

    }

Android OpenGL ES 学习(五) -- 渐变色

二. 优化数据

上面的数据,位置和颜色是分开的,一个位置数组,对应一个颜色数组,他们需要一一对应。
但我们可以用另外一种方式,把位置和颜色放到同个数组里面,如:

        private val POINT_COLOR_DATA = floatArrayOf(
            //定点+颜色
            0f,0.5f,0f,1f,0.5f,0.5f,
            -0.5f,-0.5f,0f,1f,0f,1f,
            0.5f,-0.5f,0f,0f,0.5f,1f
        )
private var vertexData = BufferUtil.createFloatBuffer(POINT_COLOR_DATA)

这样,我们只需要一个数组,加载一次内存就可以了。

修改加载索引的方式:

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(1f, 1f, 1f, 1f)
        makeProgram(VERTEX_SHADER, FRAGMENT_SHADER)

        uMatrix = getUniform(U_MATRIX)

        vertexData.position(0)
        //步进为 24
        GLES30.glVertexAttribPointer(
            0, 3, GLES30.GL_FLOAT,
            false, 24, vertexData
        )
        GLES30.glEnableVertexAttribArray(0)
        //颜色地址从3开始,前面3个为位置
        vertexData.position(3)
        GLES30.glVertexAttribPointer(
            1, 3, GLES30.GL_FLOAT,
            false, 24, vertexData
        )
        GLES30.glEnableVertexAttribArray(1)
    }

两个点要解释:

步进为啥是24:
顶点着色器允许我们指定任何以顶点属性为形式的输入。这使其具有很强的灵活性的同时,它还的确意味着我们必须手动指定输入数据的哪一个部分对应顶点着色器的哪一个顶点属性。所以,我们必须在渲染前指定OpenGL该如何解释顶点数据。
数据之间是紧密排列的,所以,当只有顶点数据的时候,我们认为它是正确能被获取的:
Android OpenGL ES 学习(五) -- 渐变色

  • 位置数据被储存为32位(4字节)浮点值。
  • 每个位置包含3个这样的值。
  • 在这3个值之间没有空隙(或其他值)。这几个值在数组中紧密排列(Tightly Packed)。
  • 数据中第一个值在缓冲开始的位置。

从这里的解释来看,我们第一次完成的渐变色,也可以修改成:

//旧方案
 GLES30.glVertexAttribPointer(
            0, 3, GLES30.GL_FLOAT,
            false, 0, vertexData
        )
 // 根据步进定义,定个分量个数 * 4(字节)
 GLES30.glVertexAttribPointer(
    0, 3, GLES30.GL_FLOAT,
    false, 3 * 4, vertexData
)

也能正常绘制渐变色的三角形。

现在插入了颜色值,所以它的步进为 6 * 4 = 24:
Android OpenGL ES 学习(五) -- 渐变色
vertexData.position(3)
对每个顶点属性来说,他们的其实位置都不同,位置默认为0,而颜色值的偏移量是在位置之后,所以偏移量为3。

这样,渐变色我们就学习完了。

参考:
https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/
https://learnopengl-cn.github.io/01%20Getting%20started/05%20Shaders/
https://juejin.cn/post/7145094035521470500文章来源地址https://www.toymoban.com/news/detail-470265.html

到了这里,关于Android OpenGL ES 学习(五) -- 渐变色的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ES学习日记(六)-------head使用教程(简易教程)

    head可以看到的信息,和之前讲到的查看的单节点看到的一样,适当了解一下就行: 一、添加索引 ps:讲下增加索引涉及的知识点 1.索引 1个索引,索引相当于什么?相当于数据库啊 2.分片 5个分片,分片就是存放数据的东西,数据是存在分片上面的,分片是存在节点上面的,当分片切到别的

    2024年04月10日
    浏览(40)
  • Android OpenGL ES 学习(九) – 坐标系统和实现3D效果

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年01月25日
    浏览(46)
  • OpenGL ES 2.0 for Android教程(三):编译着色器并绘制到屏幕

    文章传送门 OpenGL ES 2.0 for Android教程(一) OpenGL ES 2.0 for Android教程(二) OpenGL ES 2.0 for Android教程(四) OpenGL ES 2.0 for Android教程(五) OpenGL ES 2.0 for Android教程(六) OpenGL ES 2.0 for Android教程(七) OpenGL ES 2.0 for Android教程(八) OpenGL ES 2.0 for Android教程(九) 本章将继续我

    2023年04月26日
    浏览(60)
  • Android OpenGL ES 学习(十) – GLSurfaceView 源码解析GL线程以及自定义 EGL

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年02月05日
    浏览(48)
  • Android OpenGL ES 学习(十三) -离屏渲染FBO(截图)RBO, OES转 FBO

    Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenGL ES 学习(七) –

    2024年02月12日
    浏览(42)
  • 《Android 移动应用基础教程(Android Studio)(第2版)》【学习笔记】【2023春】【附源码】

    《Android 移动应用基础教程(Android Studio)(第2版)》黑马程序员 源代码 Android——六大基本布局总结/CSDN@小马 同学 【Android】线性布局(LinearLayout)最全解析/CSDN@Teacher.Hu 一个不错的计算器界面👇 Android Studio App LinearLayout多层布局嵌套/CSDN@pythontojava 一个简单的布局👇 Andro

    2024年02月01日
    浏览(68)
  • 【Android OpenGL开发】OpenGL ES与EGL介绍

    OpenGL(Open Graphics Library)是一个跨编程语言、跨平台的编程图形程序接口,主要用于图像的渲染。 Android提供了简化版的OpenGL接口,即OpenGL ES。 早先定义 OpenGL ES 是 OpenGL 的嵌入式设备版本,用于移动端平台(Android、iOS),但由于嵌入式设备要求的是高性能,所以一些其它纯

    2024年02月04日
    浏览(90)
  • Android OpenGL ES实现简单绿幕抠图

    目录 正文 OES Filter BlendShader Filter 最后的效果 缺陷 实现绿幕抠图,其实想法很简单。 这里简单粗暴的使用着色器替换。 OES Filter 直接实现在相机预览上的Shader ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #extension GL_OES_EGL_image_external : require precision mediump float ;        

    2024年02月13日
    浏览(31)
  • OpenGL ES入门教程(一)编写第一个OpenGL程序

    从本文开始我将参考学习OpenGL ES应用开发实践指南 Android卷 [(美)KevinBrothaler著](提取码: 394m),并基于自己的理解以更加通俗易懂的方式讲解如何应用OpenGL ES。本系列教程的目标是应用OpenGL,所以不会涉及太多的理论知识,主要讲解方式是基于简单功能的代码拆解,学会对

    2024年02月06日
    浏览(49)
  • OpenGL-ES 学习(4)---- OpenGL-ES 坐标体系

    坐标体系 我们知道 OpenGL -ES 坐标系中每个顶点的 x,y,z 坐标都应该在 -1.0 到 1.0 之间,超出这个坐标范围的顶点都将不可见。 将一个物体(图像)渲染到屏幕上,通常经过将物体坐标转换为标准化设备坐标,然后再将标准化设备坐标转化为屏幕坐标的过程。 ( 将物体坐标转

    2024年02月19日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包