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

news/2024/7/10 18:54:42 标签: es, 开源

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.5
    glEnable(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 0
		0.0f,  0.0f,        // TexCoord 0 
		-1.0f, -1.0f, 0.0f,  // Position 1
		0.0f,  1.0f,        // TexCoord 1
		1.0f, -1.0f, 0.0f,  // Position 2
		1.0f,  1.0f,        // TexCoord 2
		1.0f,  1.0f, 0.0f,  // Position 3
		1.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 texture
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, userData->textureIdDst);

	// Set the sampler texture unit to 0
	glUniform1i(userData->samplerLocal, 0);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

	// 任然使用可以 texture0, 但是可以指定不同的 texture id
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, userData->textureIdSrc);
	glUniform1i(userData->samplerLocal, 0);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}

实际效果如下:
Alpha Blend 效果


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

相关文章

如何使用 Python 通过代码创建图表

简介 Diagram as Code 工具允许您创建基础架构的架构图。您可以重复使用代码、测试、集成和自动化绘制图表的过程,这将使您能够将文档视为代码,并构建用于映射基础架构的流水线。您可以使用 diagrams 脚本与许多云提供商和自定义基础架构。 在本教程中…

Codeforces Round 924(Div.2) A~E

A.Rectangle Cutting (模拟) 题意: 给出一个长方形,通过平行于原始矩形的一条边进行切割,将该矩形切割成两个边长为整数的矩形。询问是否能通过旋转和移动这两个矩形,得到新的矩形。 分析: 可以发现拼成的新长方形…

判断能否形成等差数列

1502. 判断能否形成等差数列 给你一个数字数组 arr 。 如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。 如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。 示例…

ubuntu中尝试安装ros2

首先,ubuntu打开后有个机器人栏目,打开后,有好多可选的,看了半天 ,好像是博客,算了,没啥关系,再看看其他菜单 这些都不是下载链接。先不管,考虑了一下,问了ai&#xff…

vue3 之 倒计时函数封装

理解需求 编写一个函数useCountDown可以把秒数格式化为倒计时的显示xx分钟xx秒 1️⃣formatTime为显示的倒计时时间 2️⃣start是倒计时启动函数,调用时可以设置初始值并且开始倒计时 实现思路分析 安装插件 dayjs npm i dayjs倒计时逻辑函数封装 // 封装倒计时…

机器学习系列——(十六)回归模型的评估

引言 在机器学习领域,回归模型是一种预测连续数值输出的重要工具。无论是预测房价、股票价格还是天气温度,回归模型都扮演着不可或缺的角色。然而,构建模型只是第一步,评估模型的性能是确保模型准确性和泛化能力的关键环节。本文…

C++的继承(两个类互相继承/单个类继承/真实案例分享/心得体会)

前言 最近复习到二叉树的遍历,递归依旧不是十分的清楚。 暂时不用递归遍历了,改用层序遍历二叉树,以下是层序遍历的详细原理: 从根节点开始,逐层访问二叉树的节点,同一层中的节点按照从左到右的顺序被访…

【计算机网络】网络层之IP协议

文章目录 1.基本概念2.协议头格式3.网段划分4.特殊的IP地址5.IP地址的数量限制6.私有IP地址和公网IP地址7.路由 1.基本概念 IP地址是定位主机的,具有一个将数据报从A主机跨网络可靠的送到B主机的能力。 但是有能力就一定能做到吗,只能说有很大的概率。…