颜色混合源码实例,此程序使用透明度来实现可以在白色背景上来回移动的半透明红色的幻觉,并且移动过程中实现了有其他色块颜色混合的效果。
此实例是在Move.cpp示例程序基础上编写的,所以这里只贴出新增的源码,在源码解析继续学习。可以回顾Move.cpp :http://blog.csdn.net/perseverancep/article/details/72598284
一、混合的简单介绍
我们已经了解,通常情况下OpenGL渲染时会把颜色值放在颜色缓冲区中。每个片段的深度值放在深度缓冲区中。当深度测试关闭(禁用)时,新的颜色值简单地覆盖颜色缓冲区中已存在的其他值。当深度测试被打开(启用)时,新的颜色片段只有当它们比原来的值更接近临近的裁剪平面时才会替换原来的颜色片段。正常情况下,任何绘制操作不是完全丢弃,就是完全覆盖原来的颜色值,这取决于深度测试的结果。然而在打开了混合功能(glEnabble(GL_BLEND))后,新的颜色会与已经存在的颜色值在颜色缓冲区进行组合。
已存在缓冲区的颜色:目标颜色。
作为当前渲染的颜色:源颜色。它可以与目标颜色进行交互与不交互。
Cf=(Cs*S)+(Cd*D);
Cf是最终计算的颜色,Cs是源颜色,Cd是目标颜色,S和D分别是源和目标颜色的混合因子。用glBlendFunc(GLeum S,GLenum D)函数进行设置混合因子。
例如:glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);查上表推导:
Cd = (1,0f,0.0f,0.0f,0.0f);//目标颜色 (Red) alpha值是0
Cs = (0.0f,0.0f,1.0f,0.6f);//源颜色 (Blue) alpha值0.6
GL_SRC_ALPHA代表源颜色(S)的混合因子的值是源颜色的alpha值,即0.6。GL_ONE_MINUS_SRC_ALPHA代表目标颜色的混合因子(D)的值是1减去源颜色的alpha值,即(1-0.6)
所以 Cf = (Cs*S)+(Cd*D) Cf = (Blue*0.5)+(Red*0.4)
二、源码解析
void SetupRc()
{
//设置清除窗口的清除颜色,当在渲染函数(RenderScene)执行清除缓冲区时执行
glClearColor(1.0f, 1.0f, 1.0f, 1.0f );
//初始化着色器
shaderManager.InitializeStockShaders();
//图元初始化,上图中中间的小方块
squareBatch.Begin(GL_TRIANGLE_FAN, 4);
squareBatch.CopyVertexData3f(vVerts);
squareBatch.End();
//图元初始化,图中窗口4个角的绿、红、蓝和黑色的方块。给出了4个顶点坐标系,并拷贝给批次容器。
GLfloat vBlock[] = { 0.25f, 0.25f, 0.0f,
0.75f, 0.25f, 0.0f,
0.75f, 0.75f, 0.0f,
0.25f, 0.75f, 0.0f};
greenBatch.Begin(GL_TRIANGLE_FAN, 4);
greenBatch.CopyVertexData3f(vBlock);
greenBatch.End();
Lfloat vBlock2[] = { -0.75f, 0.25f, 0.0f,
-0.25f, 0.25f, 0.0f,
-0.25f, 0.75f, 0.0f,
-0.75f, 0.75f, 0.0f};
redBatch.Begin(GL_TRIANGLE_FAN, 4);
redBatch.CopyVertexData3f(vBlock2);
redBatch.End();
GLfloat vBlock3[] = { -0.75f, -0.75f, 0.0f,
-0.25f, -0.75f, 0.0f,
-0.25f, -0.25f, 0.0f,
-0.75f, -0.25f, 0.0f};
blueBatch.Begin(GL_TRIANGLE_FAN, 4);
blueBatch.CopyVertexData3f(vBlock3);
blueBatch.End();
GLfloat vBlock4[] = { 0.25f, -0.75f, 0.0f,
0.75f, -0.75f, 0.0f,
0.75f, -0.25f, 0.0f,
0.25f, -0.25f, 0.0f};
blackBatch.Begin(GL_TRIANGLE_FAN, 4);
blackBatch.CopyVertexData3f(vBlock4);
blackBatch.End();
}
void RenderScene(void)
{
//使用当前的清除颜色来清除窗口(在SetupRC中的glClearColor(1.0f,1.0f,1.0f,1.0f),即白色背景)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//设置图元要被渲染的颜色
GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 0.5f };
GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
GLfloat vBlue[] = { 0.0f, 0.0f, 1.0f, 1.0f };
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
//选择单位着色器,并为这个着色器提供颜色值,最后将几个图形提交给着色器
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vGreen);
greenBatch.Draw();
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
redBatch.Draw();
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vBlue);
blueBatch.Draw();
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vBlack);
blackBatch.Draw();
glEnable(GL_BLEND); //开启颜色混合功能
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//设置混合因子,看上文介绍
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed); //选择单位着色器,并为这个着色器提供颜色值
squareBatch.Draw();//将上图中中间的小方形提交给着色器
glDisable(GL_BLEND);//关闭混合模式,避免对后续图形渲染产生的影响
// Flush drawing commands
glutSwapBuffers();
}
通过在源码中添加的注释来解析,回顾Move.cpp的源码,当按下方向键后,中间的小方块就可以上下左右移动,可以实现颜色混合的效果。
注意:
1、每当按下方向键是,就会重新渲染,即重复调用RenderScene函数。
2、在源码中,设置了中间小方块的着色器所提供的颜色是红色,然而在测试时它的颜色确是粉色,是由于开启了颜色混和功能,并且注意细节GLfloat vRed = {1.0f,1.0f,1.0f,0.5f},其中alpha的值是0.5,所以在混合功能下,红色和窗口背景色(白色)glClearColor(1.0f, 1.0f, 1.0f, 1.0f )进行混合后,就是粉色的方块了。我在测试中,把glEnable(GL_BLEND)去掉后,中间的方块的颜色是纯红色(把背景色覆盖了),并且中间的方块的颜色不会与四个角的方块颜色混合。
三、小结
此源码示例虽然是在Move.cpp上添加了新功能,但是通过一边看书一边测试源码进行学习,可以找到许多知识细节,也能回顾之前的许多知识,达到举一反三的效果。