OpenGL ES入门教程(三)之为平面桌子添加混合色

这篇具有很好参考价值的文章主要介绍了OpenGL ES入门教程(三)之为平面桌子添加混合色。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

上一篇文章我们讲解了OpenGL ES如何绘制一个平面桌子,本文在其基础上继续讲解如何使绘制的平面桌子具有混合色,效果类似在桌子中心上面吊一盏灯,越靠近桌子中心颜色越亮白,越远离桌子中心颜色越暗灰。如果是OpenGL ES小白,在阅读本篇文章之前一定要搞懂上篇文章OpenGL ES入门教程(二)之绘制一个平面桌子

零、OpenGL ES实现混合色的原理

首先混合色指的是将两种及以上的颜色进行混合而得出的其它颜色。之前的文章中我们讲过OpenGL只有点,线,三角形三种基本图元,其余图元都是有这三种基本图元构成。很明显只有线和三角形这两种图元有实现混合色的意义,混合色最常见的实现方式就是对颜色进行线性插值,OpenGL实现混合色的原理也是如此。

  • 一条直线实现混合色,只需要给定直线两个顶点的颜色,线其余的颜色都是由这两个顶点线性插值而得。混合色结果取决于线上的位置与两个顶点之间的距离,线上的位置越接近哪个顶点,那混合色就越倾向于哪个顶点的颜色。直线上各个位置通过线性插值计算的混合色的公式如下:
    OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android
    可以看到distance_ratio的值越大,vertex_1_value所占的比重就越大,而对应vertex_0_value所占的比重就越小,即distance_ratio的值越大,颜色越接近于vertex_1_value的颜色。

  • 三角形平面实现混合色,只需要给定三角形三个顶点的颜色,三角形内部其余的颜色都是由这三个顶点线性插值而得。对于三角形内任何给定的点,从那个点向每个顶点所对应的点画一条直线就可以生成三个内部三角形。这三个内部三角形的面积的比例决定了那个点上每种颜色的权重。如下图所示三角形,那个点上黄色的强度就取决于黄色顶点相对的那个内部三角形的面积。距离黄色顶点越近的点,它相对的三角形就越大,在那个点的片段就越显黄。
    OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android
    三角形内每个点的混合色线性插值的计算公式如下:
    OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android

说到底,就是最普通的线性插值,只是插值插的是颜色值而已,与我们上学时数学课上的线性插值一样(z=ax+by),相信稍微思考下就明白啦~,而且下面的混合色实现也不需要我们写公式,OpenGL都封装好了。

一、修改绘制的桌子结构

我们要实现效果类似在桌子中心上面吊一盏灯,越靠近桌子中心颜色越亮白,越远离桌子中心颜色越暗灰。那我们就要在桌子的中心放置一个顶点,且该处顶点颜色是纯白色,因此,长方形平面桌子应该有如下图所示的4个三角形组成,而上一篇文章中我们实现的平面桌面是由两个三角形组成的,因此我们应该先修改桌面的结构。OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android

1. 三角形扇介绍

一个三角形扇以一个中心顶点作为起始,使用相邻的两个顶点创建第一个三角形,接下来的每个顶点都会创建一个三角形,围绕起始的中心点按扇形展开。为了使这个扇形闭合,我们只需要在最后重复第二个点。

三角形扇完全可以实现我们上面所提到的由4个三角形构成的长方形,该三角形扇包含的顶点如下图所示,一共由5个顶点组成。
OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android

2. 基于三角形扇结构绘制平面桌子

  1. 上面提到三角形扇需要5个顶点,同时由于为了使得三角形扇闭合,我们需要重复第二个顶点使其成为最后一个顶点,因此,平面桌子的坐标数据修改如下:
float[] tableVerticesWithTriangles = {
                /**
                无论是x还是y坐标,OpenGL都会把屏幕映射到[-1,1]的范围内。
                即屏幕的左边对应x轴的-1,右边对应+1;
                屏幕的底边对应y轴的-1,顶边对应+1
                */
                // Triangle Fan
                0f, 0f,//三角形扇的中心点坐标
                -0.5f, -0.5f,//三角形扇第二个顶点坐标
                0.5f, -0.5f,
                0.5f, 0.5f,
                -0.5f, 0.5f,
                -0.5f, -0.5f,//三角形扇必须封闭,因此这个就是第二个顶点坐标

                // Line 1
                -0.5f, 0f,
                0.5f, 0f,

                // Mallets
                0f, -0.25f,
                0f,  0.25f
        };
  1. 调用glDrawArrays方法,第一个参数选择GL_TRIANGLE_FAN绘制三角形扇即可,平面桌子的绘制代码如下
	@Override
    public void onDrawFrame(GL10 gl) {
        glClear(GL_COLOR_BUFFER_BIT);
        /*
        绘制桌子
         */
        //更新着色器中u_Color的值(蓝色)
        glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
        //参数1:绘制三角形扇;参数2:从顶点数组的开头开始读顶点;参数3:读取6个顶点
        //之前glVertexAttribPointer告诉过OpenGL每个顶点的位置包含两个浮点分量,因此OpenGL会使用vertexData中如下12个浮点数

        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

        /*
        绘制分割线
         */
        //更新u_Color的值(红色)
        glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
        //参数1:绘制直线; 参数2:从顶点数组的第6个顶点之后(即第7个顶点)开始读取;参数3:读取两个顶点
        glDrawArrays(GL_LINES, 6, 2);

        /*
        绘制两个木槌
         */
        //更新u_Color的值(黑色)
        glUniform4f(uColorLocation, 0.0f, 0.0f, 0.0f, 1.0f);
        glDrawArrays(GL_POINTS, 8, 1);
        //更新u_Color的值(绿色)
        glUniform4f(uColorLocation, 0.0f, 1.0f, 0.0f, 1.0f);
        glDrawArrays(GL_POINTS, 9, 1);
    }
  1. 此时,运行代码结果和上一篇文章绘制的平面桌子效果一致,只是长方形的结构由两个三角形组成变成了由4个三角形组成而已。
    OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android

二、为每个顶点添加颜色属性

我们之前在数组中记录了每个顶点的位置坐标数据,同理,我们也可以再定义一个数组,对应记录每个顶点的颜色数据。但为了数据处理更加高效,我们不用另外再定义一个数组存储颜色数据,完全可以把顶点的位置数据和颜色数据存储在同一个数组中。包含顶点位置坐标数据和颜色数据的数组如下,每个顶点包含x,y两个位置坐标数据,紧邻其后是r,g,b三个颜色分量数据

	float[] tableVerticesWithTriangles = {
                /**
                无论是x还是y坐标,OpenGL都会把屏幕映射到[-1,1]的范围内。
                即屏幕的左边对应x轴的-1,右边对应+1;
                屏幕的底边对应y轴的-1,顶边对应+1
                */
                // Triangle Fan
                0f,    0f,   1f,   1f,   1f,//前两位是三角形扇的中心点坐标,后面三位是代表rgb的颜色分量(此处代表的颜色是白色)
                -0.5f, -0.5f, 0.7f, 0.7f, 0.7f,//三角形扇第二个顶点坐标
                0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
                0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
                -0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
                -0.5f, -0.5f, 0.7f, 0.7f, 0.7f,//三角形扇必须封闭,因此这个就是第二个顶点坐标

                // Line 1
                -0.5f, 0f, 1f, 0f, 0f,//顶点颜色是红色
                0.5f, 0f, 0f, 1f, 0f,//顶点颜色是绿色

                // Mallets
                0f, -0.25f, 0f, 0f, 1f,//顶点颜色是蓝色
                0f,  0.25f, 1f, 0f, 0f//顶点颜色是红色
        };

三、修改着色器

1. 顶点着色器

顶点带有颜色属性的,顶点着色器代码如下。
加入了a_Color颜色属性和v_Color混合颜色属性,a_Color存储顶点的颜色,v_Color用于实现颜色的线性插值,为片段生成混合色。可以理解为咱们在第零章讲解的混合色原理,OpenGL通过varying这种特殊标记实现了。

/*
attribute:属性数据的特定标识
vec4:一种包含4个分量的向量数据类型(x,y,z,w)
     a_Position中x,y,z代表顶点的三维位置坐标,w是一个特殊坐标,后面会讲解
a_Position:变量名称,该名称后面OpenGL的glGetAttribLocation方法要用到,
           如果修改后面就要一起修改
*/
attribute vec4 a_Position;//代表位置的属性数据(x,y,z,w)
attribute vec4 a_Color;//代表颜色的属性数据(r,g,b,a)

/*
varying:一种特殊的变量类型,它把给它的哪些值进行混合,并把这些混合的值发送给片段着色器。
其实所谓混合,就是通过线性插值方法生成片段中除了顶点之外的其它颜色。
例如生成直线的片段是由两个顶点构成,顶点0的a_Color是红色,顶点1的a_Color是绿色,通过将a_Color赋值给varying这种特殊类型的变量,
就可以使得越靠近顶点0的直线片段颜色越红,越靠近顶点1的直线片段颜色越绿。
*/
varying vec4 v_Color;

//和C语言类似,main函数是着色器的入口函数
void main()
{
    //将颜色数据赋值给varying类型的变量
    v_Color = a_Color;
    //gl_Position :OpenGL特定的变量名,用于存储我们定义的顶点数据
    gl_Position = a_Position;
    //gl_PointSize:OpenGL特定的变量名,用于存储点的大小
    gl_PointSize = 10.0;
}

2. 片段这色器

为片段生成混合颜色的片段着色器代码如下。
将uniform标识的一个片段只有一个颜色的属性修改为varying标识的混合颜色属性,这个属性与顶点着色器定义的varying属性相对应,属性名必须一致。

//OpenGL定义float数据类型的精度(lowp;mediump;highp),就像java代码中浮点型选择float类型还是double类型。
//精度是以性能为代价的,这里选择mediump
precision mediump float;

varying vec4 v_Color;//通过线性插值顶点颜色,形成混合颜色(这个参数名必须与顶点着色器中的参数名一致)

//和C语言类似,main函数是着色器的入口函数
void main()
{
    gl_FragColor = v_Color;
}

四、绘制具有混合颜色的平面桌子

1. 计算跨度

上一篇文章中,我们讲解到通过glVertexAttribPointer方法将顶点位置与着色器进行关联,该方法中有一个跨度参数stride,我们直接赋值为0,并没有对其进行详细讲解,因为那时数组中只存储了顶点位置坐标数据,不包含颜色属性数据,因此OpenGL只需要一个顶点数据挨着一个顶点数据的读取就能得到每个顶点的正确位置坐标数据。

		//获取顶点着色器中(attribute)位置属性
        aPositionLocation = glGetAttribLocation(program, A_POSITION);
        //告诉OpenGL从vertexData中读取a_Position的数据
        vertexData.position(0);//将缓冲区数据中的指针指向第一个数据,即从第一个数据开始读
 		/*
 		public static void glVertexAttribPointer(
        int indx,
        int size,
        int type,
        boolean normalized,
        int stride,
        java.nio.Buffer ptr
   		)
        将着色器中的位置属性与本地顶点数据相关联。
        aPositionLocation:着色器中定义的位置属性
        POSITION_COMPONENT_COUNT:每次从本地数组中读取两个数据(即x,y代表一个顶点坐标)
        GL_FLOAT:OpenGL采用的数据类型,因为我们定义的是浮点数数组,所以采用GL_FLOAT
        vertexData:要关联的本地数据列表
        */
        glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
                false, 0, vertexData);

但是,现在我们的每个顶点不仅存储了位置坐标数据,同时存储了颜色属性数据,因此,第一个顶点的位置坐标数据和第二个顶点的位置坐标数据之间多个三个颜色属性数据,为了正常的获得每个顶点的位置坐标数据,我们需要把中间的颜色属性数据跨过去,所以,才有了跨度stride这个参数。因为,现在我们每个顶点位置坐标数据直接插入了三个颜色属性数据,因此下一个顶点的位置坐标数据需要跨过上一个顶点中的两个位置坐标数据和3个颜色属性数据,因此跨距stride计算方式如下(跨距的单位是字节):

	//每个float由4个字节组成
	private static final int BYTES_PER_FLOAT = 4;
 	//每个顶点前两个浮点数代表位置:x,y
    private static final int POSITION_COMPONENT_COUNT = 2;
    //每个顶点后三个浮点数代表颜色:r,g,b
    private static final int COLOR_COMPONENT_COUNT = 3;
	//STRIDE代表每个顶点位置之间间隔多少个字节(因为现在顶点位置和顶点颜色数据混在一起,只有明确跨度才能查找到每个顶点的位置)
    private static final int STRIDE =
            (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;

2. 关联顶点位置数据和颜色数据

通过glVertexAttribPointer函数将数组中存储的顶点数据与着色器中的属性相关联

		//获取顶点着色器中代表顶点颜色的属性
        aColorLocation = glGetAttribLocation(program, A_COLOR);
        //获取顶点着色器中代表顶点位置的属性(attribute)
        aPositionLocation = glGetAttribLocation(program, A_POSITION);
        //告诉OpenGL从vertexData中读取a_Position的数据
        vertexData.position(0);//将缓冲区数据中的指针指向第一个顶点的位置数据开始的位置
        glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
                false, STRIDE, vertexData);
        //使能顶点数组
        glEnableVertexAttribArray(aPositionLocation);

        //告诉OpenGL从vertexData中读取a_Color的数据
        vertexData.position(POSITION_COMPONENT_COUNT); //将缓冲区中的指针指向第一个顶点的颜色数据开始的位置
        glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
                false, STRIDE, vertexData);
        //使能顶点数组
        glEnableVertexAttribArray(aColorLocation);

3. 绘制图形

现在每个顶点都有了自己的颜色,并且采用varying实现片段的混合色,因此,不要再调用glUniform4f方法为片段设置颜色了,每个片段的颜色都会由顶点插值而得。

	@Override
    public void onDrawFrame(GL10 gl) {
        glClear(GL_COLOR_BUFFER_BIT);
        /*
        绘制桌子
         */
        //参数1:绘制三角形扇;参数2:从顶点数组的开头开始读顶点;参数3:读取6个顶点
        //之前glVertexAttribPointer告诉过OpenGL每个顶点的位置包含两个浮点分量,因此OpenGL会使用vertexData中12个浮点数
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

        /*
        绘制分割线
         */
        //参数1:绘制直线; 参数2:从顶点数组的第6个顶点之后(即第7个顶点)开始读取;参数3:读取两个顶点
        glDrawArrays(GL_LINES, 6, 2);
        glLineWidth(10); //设置线宽,不设置线宽,无法体现线的渐变颜色

        /*
        绘制两个木槌
         */
        glDrawArrays(GL_POINTS, 8, 1);
        glDrawArrays(GL_POINTS, 9, 1);
    }

运行代码,绘制图形效果如下图所示
OpenGL ES入门教程(三)之为平面桌子添加混合色,OpenGL ES,OpenGL,绘制混合色,颜色,varying,android

五、完整示例代码下载

完整的代码都上传到了Gitee仓库
OpenGL_ES_DEMO中,仓库代码具有详细的提交记录,博友可以执行git命令:
git reset --hard f5081f05963ed48b4d149d4f9bc8476ee81caac8,切到本篇文章所讲解内容的完整示例代码。文章来源地址https://www.toymoban.com/news/detail-752994.html

到了这里,关于OpenGL ES入门教程(三)之为平面桌子添加混合色的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 一看就懂的OpenGL ES教程——仿抖音滤镜的各种奇技淫巧(一)_opengl es添加视频(1)

    一看就懂的OpenGL ES教程——仿抖音滤镜的各种奇技淫巧(一)_opengl es添加视频(1)

    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。 深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学

    2024年04月16日
    浏览(12)
  • odoo 开发入门教程系列-添加修饰

    odoo 开发入门教程系列-添加修饰

    我们的房地产模块现在从商业角度来看是有意义的。我们创建了特定的视图,添加了几个操作按钮和约束。然而,我们的用户界面仍然有点粗糙。我们希望为列表视图添加一些颜色,并使一些字段和按钮有条件地消失。例如,当房产已出售或取消时,“已售出”和“取消”按

    2023年04月09日
    浏览(10)
  • ES教程:从入门到入土

    ES教程:从入门到入土

    建议直接用docker。 docker启动参数说明: -d 后台启动 -p 9200:9200 将虚拟机9200端口映射到elasticsearch的9200端口(web通信默认使用9200端口) -p 9300:9300 将虚拟机9300端口映射到elasticsearch的9300端口(分布式情况下,各个节点之间通信默认使用9300端口) –name MyEs7 指定一个名字(MyEs

    2024年02月07日
    浏览(12)
  • Midjourney【系列教程1】人工智能艺术创作从入门到精通·基础篇:注册 & 添加 Midjourney BOT 至自己的服务器

    Midjourney【系列教程1】人工智能艺术创作从入门到精通·基础篇:注册 & 添加 Midjourney BOT 至自己的服务器

     随着 ChatGPT 的火爆全网,有关 AIGC(AI Generated Content)的相关应用也逐步走入了大众视野。其中,人工智能绘画尤为受欢迎,也越来越吸引人们的注意。在我的身边中就有越来越多的设计者和艺术爱好者想学习和应用这项技术,但却苦于目前网上的很多教程都比较零散充满了

    2024年02月09日
    浏览(13)
  • [python][pcl]python-pcl案例之为平面模型构造凹凸外壳多边形

    测试环境: pcl==1.12.1 python-pcl==0.3.1 python==3.7 代码: 运行结果: PointCloud after filtering has: 139656 data points. PointCloud after segmentation has: built-in method count of list object at 0x0000028CA3429A48 inliers. PointCloud after projection has: 139656 data points. Concave hull has: 281 data points. table_scene_mug_stereo_textured.p

    2024年02月11日
    浏览(13)
  • OpenGL ES入门介绍

    OpenGL ES入门介绍

    目录 1.OpenGL ES的简介 2. 基本流程和概念 2.1 渲染的基本流程 2.2 管线 2.3 顶点 2.4 纹理 2.5 顶点着色器(VertexShader) 2.6 图元装配 2.7 光栅化 2.8 片段着色器(FragmentShader) 2.9 逐片段操作         第一次接触OpenGL ES是两年前,但是看到OpenGL中各种专业名词和专业术语,

    2024年01月22日
    浏览(9)
  • OpenGL ES入门指南(一)

    OpenGL ES入门指南(一)

    一、OpenGL ES 基础简介     OpenGL ES(OpenGL for Embedded Systems)是从OpenGL裁剪定制而来的,去除了glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性。 OpenGL 和 OpenGL ES的区别 二、为什么需要OpenGL或者说OpenGL ES? 对比相同的算法处理在GPU和CPU上的

    2024年02月11日
    浏览(14)
  • Compose 实战之为下拉刷新添加自定义指示器

    Compose 实战之为下拉刷新添加自定义指示器

    在安卓开发中,下拉刷新是一个非常常用的功能,几乎只要是涉及到列表展示数据的界面都会用到它。 而 Compose 却直到 2022年10月份才在 compose.material:1.3.0 中添加了对下拉刷新的支持: Modifier.pullRefresh 。 在此之前,我们只能使用 accompanist-swiperefresh 来实现下拉刷新。 然而,更

    2024年02月07日
    浏览(10)
  • 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教程(八) OpenGL ES 2.0 for Android教程(九) 本章介绍我们

    2023年04月14日
    浏览(9)
  • 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教程(八) OpenGL ES 2.0 for Android教程(九) 本章将继续我

    2023年04月26日
    浏览(9)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包