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

AlphaBlend

OpenGL-ES 混合本质上是将 2 个片元的颜色进行调和(一般是求和操作),产生一个新的颜色

OpenGL ES 混合发生在片元通过各项测试 之后,准备进入帧缓冲区的片元和原有的片元按照特定比例加权计算出最终片元的颜色值,不再是新(源)片元直接覆盖缓冲区中的(目标)片元。

OpenGL-ES 混合方程:
Cresult=C~source~∗F~source~ + C~destination~∗F~destination~

其中:

其中:

C~source~:源颜色向量,来自纹理的颜色向量;

C~destination~:目标颜色向量,储存在颜色缓冲中当前位置的颜色向量;

F~source~:源因子,设置了对源颜色加权;

F~destination~:目标因子,设置了对目标颜色加权;

操作符可以是加(+)、减(-)、Min、Max 等。

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

编程方法

开启 Alpha Blend

启用 OpenGL ES 混合使用 glEnable(GL_BLEND);

然后通过 glBlendFunc 设置混合的方式,其中 sfactor 表示源因子,dfactor 表示目标因子

cpp 复制代码
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:默认的,彼此元素相加:C~result~=C~Src~ + C~Dst~;

GL_FUNC_SUBTRACT:彼此元素相减:C~result~=C~Src~ − C~Dst~ ;

GL_FUNC_REVERSE_SUBTRACT:彼此元素相减,但顺序相反:C~result~=C~Dst~ - C~Src~;

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

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

颜色通道和Alpha 通道分开设置
cpp 复制代码
//对 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 通道设置不同的操作符:

cpp 复制代码
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);`

sss

验证代码

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

cpp 复制代码
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);
}

实际效果如下:

相关推荐
n***85941 小时前
嵌入式 UI 开发的开源项目推荐
windows·开源·开源软件
sinovoip5 小时前
Banana Pi BPI-CanMV-K230D-Zero 采用嘉楠科技 K230D RISC-V芯片设计
人工智能·科技·物联网·开源·risc-v
OpenAnolis小助手5 小时前
开源生态发展合作倡议
开源·操作系统·龙蜥社区·龙蜥·openanolis
杭州奥能充电桩6 小时前
移动充储机器人“小奥”的多场景应用(上)
开源·能源
lsjweiyi1 天前
极简AI工具箱网站开源啦!
opencv·开源·微信支付·支付宝支付·百度ai·极简ai工具箱·ai图像处理
开源社1 天前
一场开源视角的AI会议即将在南京举办
人工智能·开源
FreeIPCC1 天前
谈一下开源生态对 AI人工智能大模型的促进作用
大数据·人工智能·机器人·开源
海害嗨1 天前
阿里巴巴官方「SpringCloudAlibaba全彩学习手册」限时开源!
学习·开源
生命是有光的1 天前
【开源风云】从若依系列脚手架汲取编程之道(八)
开源
HuggingFace1 天前
Halo 正式开源: 使用可穿戴设备进行开源健康追踪
开源·健康追踪