OpenGL-ES 学习(1)---- AlphaBlend

AlphaBlend

OpenGL-ES 混合本质上是将 2 个片元的颜色进行调和(一般是求和操作),产生一个新的颜色
OpenGL ES 混合发生在片元通过各项测试之后,准备进入帧缓冲区的片元和原有的片元按照特定比例加权计算出最终片元的颜色值,不再是新(源)片元直接覆盖缓冲区中的(目标)片元。
OpenGL-ES 混合方程:
Cresult=Csource∗Fsource + Cdestination∗Fdestination

其中:
其中:
Csource:源颜色向量,来自纹理的颜色向量;
Cdestination:目标颜色向量,储存在颜色缓冲中当前位置的颜色向量;
Fsource:源因子,设置了对源颜色加权;
Fdestination:目标因子,设置了对目标颜色加权;
操作符可以是加(+)、减(-)、Min、Max 等。

这里的向量可以理解为通道的含义,比如 RGB 可以用 Vec3 来表示;

编程方法

开启 Alpha Blend

启用 OpenGL ES 混合使用 glEnable(GL_BLEND);
然后通过 glBlendFunc 设置混合的方式,其中 sfactor 表示源因子,dfactor 表示目标因子

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// GL_SRC_ALPHA 表示源因子取值为源颜色的 alpha
// GL_ONE_MINUS_SRC_ALPHA 表示目标因子取值为 1- alpha(源颜色的 alpha)
// 操作符默认为 GL_FUNC_ADD ,即加权相加。
// 混合公式变成了 源颜色向量 × alpha + 目标颜色向量 × (1- alpha)

注意下面的混和因子说明表格中,存在 const alpha 的选项,既可以使用 const alpha 混合
混合的参数说明

定义颜色操作符

我们也可以通过 glBlendEquation 自定义两个颜色之间的操作符:

GL_FUNC_ADD:默认的,彼此元素相加:Cresult=CSrc + CDst

GL_FUNC_SUBTRACT:彼此元素相减:Cresult=CSrc − CDst

GL_FUNC_REVERSE_SUBTRACT:彼此元素相减,但顺序相反:Cresult=CDst - CSrc

GL_MIN:混合结果的 4 个通道值分别取 2 元素中 4 个通道较小的值;

GL_MAX:混合结果的 4 个通道值分别取 2 元素中 4 个通道较大的值;

颜色通道和Alpha 通道分开设置
//对 RGB 和 Alpha 分别设置 BLEND 函数
//void glBlendFuncSeparate(GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha);
glBlendFuncSeperate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);//混合结果颜色 RGB 向量 = 源颜色 RGB 向量 × alpha + 目标颜色 RGB 向量 × (1- alpha);
//混合结果颜色 alpha = 源颜色 alpha × 1 + 目标颜色 alpha × 0;

也可以为 RGB通道和 alpha 通道设置不同的操作符:

void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);`

sss

验证代码

下面的代码中,loadTgaTextures 生成了两张 Texture,在绘制的时候绘制了两次,第一次绘制了 Dst,第二次绘制了 Src,指定 const alpha 的 SFactor 和 DFactor 都为 0.5

typedef struct
{GLuint programObject;GLint  samplerLocal;GLuint textureIdDst;GLuint textureIdSrc;
} UserData;static int Init(ESContext *esContext)
{UserData *userData = esContext->userData;char vShaderStr[] ="#version 300 es                            \n""layout(location = 0) in vec4 a_position;   \n""layout(location = 1) in vec2 a_texCoord;   \n""out vec2 v_texCoord;                       \n""void main()                                \n""{                                          \n""   gl_Position = a_position;               \n""   v_texCoord = a_texCoord;                \n""}                                          \n";char fShaderStr[] ="#version 300 es                                     \n""precision mediump float;                            \n""in vec2 v_texCoord;                                 \n""layout(location = 0) out vec4 outColor;             \n""uniform sampler2D s_texture;                        \n""vec4 tempColor;                                     \n""void main()                                         \n""{                                                   \n""  tempColor = texture( s_texture, v_texCoord );    \n""  outColor = vec4(tempColor.r, tempColor.b, tempColor.g, tempColor.a); \n""}                                                   \n";userData->programObject = esLoadProgram(vShaderStr, fShaderStr);userData->samplerLocal = glGetUniformLocation(userData->programObject, "s_texture");userData->textureIdSrc = loadTgaTextures("./Huskey.tga");userData->textureIdDst = loadTgaTextures("./scene.tga");// 启用 alpha 混合 指定 const alpha 值为 0.5glEnable(GL_BLEND);glBlendColor(1.0f, 1.0f, 1.0f, 0.5f);glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);glClearColor(1.0f, 1.0f, 1.0f, 0.0f);return TRUE;
}static void Draw(ESContext *esContext)
{UserData *userData = esContext->userData;GLfloat vVertices[] = {-1.0f, 1.0f, 0.0f,  // Position 00.0f,  0.0f,        // TexCoord 0 -1.0f, -1.0f, 0.0f,  // Position 10.0f,  1.0f,        // TexCoord 11.0f, -1.0f, 0.0f,  // Position 21.0f,  1.0f,        // TexCoord 21.0f,  1.0f, 0.0f,  // Position 31.0f,  0.0f         // TexCoord 3};GLushort indices[] = { 0, 1, 2, 0, 2, 3 };glViewport(0, 0, esContext->width, esContext->height);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(userData->programObject);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);glEnableVertexAttribArray(0);glEnableVertexAttribArray(1);// Bind the textureglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, userData->textureIdDst);// Set the sampler texture unit to 0glUniform1i(userData->samplerLocal, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);// 任然使用可以 texture0, 但是可以指定不同的 texture idglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, userData->textureIdSrc);glUniform1i(userData->samplerLocal, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}

实际效果如下:
Alpha Blend 效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/469615.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 920 (Div. 3)

D. Very Different Array(贪心双指针/前缀和) 思路:绝对值就是线段-->让线段最长(肯定是越在最短端找最右端的 越最右端找最左端的)-->判断怎么连哪段最长(采用双指针的策略去判断) (左红…

Swift Combine 通过用户输入更新声明式 UI 从入门到精通十五

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

uniapp前端手机获取安全区域css值 防止按键不能被点击

引入 再编写小程序和移动端的时候可能会出现这种情况,页面中的按键刚好才手机中按不到的位置 如下 这是苹果手机的home按键 如果刚好我们的按钮再这个位置,用户是点击不到的 我们就需要一个办法,能够自动的让我们的按键移动到安全可点击的区域 解决 我们可以使用…

第四篇:SQL语法-DDL-数据定义语言

大年初一限定篇😀 (祝广大IT学习者、工作者0 error 0 warning!) DDL英文全称是Data Definition Language(数据定义语言),用来定义关系模式、删除关系、修改关系模式以及创建数据库中的各种对象 …

PHP毕业设计图片分享网站76t17

图片分享网站主要是为了提高工作人员的工作效率和更方便快捷的满足用户,更好存储所有数据信息及快速方便的检索功能,对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑用户的可操作性,遵循开发的系统优化的原则,…

oppo手机QQ上传文件所在位置

一、打开手机“文件管理”APP 点击“点击查看”,按钮,会进入到新的根目录。 寻找下面的目录进入

《区块链公链数据分析简易速速上手小册》第5章:高级数据分析技术(2024 最新版)

文章目录 5.1 跨链交易分析5.1.1 基础知识5.1.2 重点案例:分析以太坊到 BSC 的跨链交易理论步骤和工具准备Python 代码示例构思步骤1: 设置环境和获取合约信息步骤2: 分析以太坊上的锁定交易步骤3: 跟踪BSC上的铸币交易 结论 5.1.3 拓展案例 1:使用 Pyth…

返回输入字中BIT=1的位个数(博途SCL代码)

返回输入字中BIT1的位个数有很多实际意义,比如我们可以统计同一时间外部的呼叫请求总数、电梯同一时间有多少个请求呼叫等。这里编程我们用到了博途的覆盖指令AT,有关AT指令的其他用法可以参看下面文章链接: https://rxxw-control.blog.csdn.net/articl…

VS Code之Java代码重构和源代码操作

文章目录 支持的代码操作列表调用重构分配变量字段和局部变量的差别Assign statement to new local variable在有参构造函数中将参数指定成一个新的字段 将匿名类转换为嵌套类什么是匿名类?匿名类转换为嵌套类的完整演示 转换为Lambda表达式Lambda 表达式是什么?转…

每日一题(最大连续1的个数,完全数计算)

485. 最大连续 1 的个数 - 力扣&#xff08;LeetCode&#xff09; #include <stdio.h> int findMaxConsecutiveOnes(int* nums, int numsSize) { if (numsSize 0) return 0; // 如果数组为空&#xff0c;返回0 int maxCount 0; // 最大连续1的个数 int currentCo…

C#利用接口实现选择不同的语种

目录 一、涉及到的知识点 1.接口定义 2.接口具有的特征 3.接口通过类继承来实现 4.有效使用接口进行组件编程 5.Encoding.GetBytes(String)方法 &#xff08;1&#xff09;检查给定字符串中是否包含中文字符 &#xff08;2&#xff09;编码和还原前后 6.Encoding.GetS…

地缘政治紧张局势加剧网络战策略的兴起

在某种程度上&#xff0c;网络安全疲劳和自满情绪留下了漏洞&#xff0c;威胁行为者利用旧的漏洞&#xff0c;包括日志记录和修补方面的漏洞&#xff0c;在网络中取得了坚定的滩头阵地。即使是最老练的威胁行为者&#xff0c;也经常选择扫描未修补的漏洞和其他基本配置弱点来渗…