OpenGL笔记3

OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式。
无论哪种颜色模式,计算机都必须为每一个像素保存一些数据。不同的是,RGBA模式中,数据直接就代表了颜色;而颜色索引模式中,数据代表的是一个索引,要得到真正的颜色,还必须去查索引表。

1. RGBA颜色
  RGBA模式中,每一个像素会保存以下数据:R值(红色分量)、G值(绿色分量)、B值(蓝色分量)和A值(alpha分量)。其中红、绿、蓝三种颜色相组合,就可以得到我们所需要的各种颜色,而alpha不直接影响颜色,它将留待以后介绍。
  在RGBA模式下选择颜色是十分简单的事情,只需要一个函数就可以搞定。
glColor*系列函数可以用于设置颜色,其中三个参数的版本可以指定R、G、B的值,而A值采用默认;四个参数的版本可以分别指定R、G、B、A的值。例如:
void glColor3f(GLfloat red, GLfloat green, GLfloat blue);
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
  (还记得吗?3f表示有三个浮点参数~请看第二课中关于glVertex*函数的叙述。)
将浮点数作为参数,其中0.0表示不使用该种颜色,而1.0表示将该种颜色用到最多。例如:
glColor3f(1.0f, 0.0f, 0.0f);    表示不使用绿、蓝色,而将红色使用最多,于是得到最纯净的红色。
glColor3f(0.0f, 1.0f, 1.0f);    表示使用绿、蓝色到最多,而不使用红色。混合的效果就是浅蓝色。
glColor3f(0.5f, 0.5f, 0.5f);    表示各种颜色使用一半,效果为灰色。
  注意:浮点数可以精确到小数点后若干位,这并不表示计算机就可以显示如此多种颜色。实际上,计算机可以显示的颜色种数将由硬件决定。如果OpenGL找不到精确的颜色,会进行类似“四舍五入”的处理。

  大家可以通过改变下面代码中glColor3f的参数值,绘制不同颜色的矩形。

void myDisplay(void)
{
     glClear(GL_COLOR_BUFFER_BIT);
     glColor3f(0.0f, 1.0f, 1.0f);
     glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
     glFlush();
}

  注意:glColor系列函数,在参数类型不同时,表示“最大”颜色的值也不同。
采用f和d做后缀的函数,以1.0表示最大的使用。
采用b做后缀的函数,以127表示最大的使用。
采用ub做后缀的函数,以255表示最大的使用。
采用s做后缀的函数,以32767表示最大的使用。
采用us做后缀的函数,以65535表示最大的使用。
这些规则看似麻烦,但熟悉后实际使用中不会有什么障碍。

2、索引颜色
  在索引颜色模式中,OpenGL需要一个颜色表。这个表就相当于画家的调色板:虽然可以调出很多种颜色,但同时存在于调色板上的颜色种数将不会超过调色板的格数。试将颜色表的每一项想象成调色板上的一个格子:它保存了一种颜色。
在使用索引颜色模式画图时,我说“我把第i种颜色设置为某某”,其实就相当于将调色板的第i格调为某某颜色。“我需要第k种颜色来画图”,那么就用画笔去蘸一下第k格调色板。
  颜色表的大小是很有限的,一般在256~4096之间,且总是2的整数次幂。在使用索引颜色方式进行绘图时,总是先设置颜色表,然后选择颜色。

2.1、选择颜色
  使用glIndex*系列函数可以在颜色表中选择颜色。其中最常用的可能是glIndexi,它的参数是一个整形。void glIndexi(GLint c);
  是的,这的确很简单。

2.2、设置颜色表
  OpenGL

并直接没有提供设置颜色表的方法,因此设置颜色表需要使用操作系统的支持。我们所用的Windows和其他大多数图形操作系统都具有这个功能,但所使用的
函数却不相同。正如我没有讲述如何自己写代码在Windows下建立一个窗口,这里我也不会讲述如何在Windows下设置颜色表。
  GLUT工具
包提供了设置颜色表的函数glutSetColor,但我测试始终有问题。现在为了让大家体验一下索引颜色,我向大家介绍另一个OpenGL工具包:
aux。这个工具包是VisualStudio自带的,不必另外安装,但它已经过时,这里仅仅是体验一下,大家不必深入。

#include <windows.h>
#include <GL/gl.h>
#include <GL/glaux.h>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glaux.lib")

#include <math.h>
const GLdouble Pi = 3.1415926536;
void myDisplay(void)
{
     int i;
     for(i=0; i<8; ++i)
         auxSetOneColor(i, (float)(i&0x04), (float)(i&0x02), (float)(i&0x01));
     glShadeModel(GL_FLAT);
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin(GL_TRIANGLE_FAN);
     glVertex2f(0.0f, 0.0f);
     for(i=0; i<=8; ++i)
     {
         glIndexi(i);
         glVertex2f(cos(i*Pi/4), sin(i*Pi/4));
     }
     glEnd();
     glFlush();
}

int main(void)
{
     auxInitDisplayMode(AUX_SINGLE|AUX_INDEX);
     auxInitPosition(0, 0, 400, 400);
     auxInitWindow(L"");
     myDisplay();
     Sleep(10 * 1000);
     return 0;
}

  其它部分大家都可以不管,只看myDisplay函数就可以了。首先,使用auxSetOneColor设置颜色表中的一格。循环八次就可以设置八格。
  glShadeModel等下再讲,这里不提。
  然后在循环中用glVertex设置顶点,同时用glIndexi改变顶点代表的颜色。
  最终得到的效果是八个相同形状、不同颜色的三角形。

  索
引颜色虽然讲得多了点。索引颜色的主要优势是占用空间小(每个像素不必单独保存自己的颜色,只用很少的二进制位就可以代表其颜色在颜色表中的位置),花费
系统资源少,图形运算速度快,但它编程稍稍显得不是那么方便,并且画面效果也会比RGB颜色差一些。“星际争霸”可能代表了256色的颜色表的画面效果,
虽然它在一台很烂的PC上也可以运行很流畅,但以目前的眼光来看,其画面效果就显得不足了。
  目前的PC机性能已经足够在各种场合下使用RGB颜色,因此PC程序开发中,使用索引颜色已经不是主流。当然,一些小型设备例如GBA、手机等,索引颜色还是有它的用武之地。

3、指定清除屏幕用的颜色
  我们写:glClear(GL_COLOR_BUFFER_BIT);意思是把屏幕上的颜色清空。
  但实际上什么才叫“空”呢?在宇宙中,黑色代表了“空”;在一张白纸上,白色代表了“空”;在信封上,信封的颜色才是“空”。
  OpenGL用下面的函数来定义清楚屏幕后屏幕所拥有的颜色。
  在RGB模式下,使用glClearColor来指定“空”的颜色,它需要四个参数,其参数的意义跟glColor4f相似。
  在索引颜色模式下,使用glClearIndex来指定“空”的颜色所在的索引,它需要一个参数,其意义跟glIndexi相似。

void myDisplay(void)
{
     glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
     glClear(GL_COLOR_BUFFER_BIT);
     glFlush();
}

  呵,这个还真简单~

4、指定着色模型
OpenGL允许为同一多边形的不同顶点指定不同的颜色。例如:

#include <math.h>
const GLdouble Pi = 3.1415926536;
void myDisplay(void)
{
     int i;
     // glShadeModel(GL_FLAT);
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin(GL_TRIANGLE_FAN); //TRIANGLE 三角形
     glColor3f(1.0f, 1.0f, 1.0f); //v1
     glVertex2f(0.0f, 0.0f);
     for(i=0; i<=8; ++i)
     {
         glColor3f(i&0x04, i&0x02, i&0x01);
         glVertex2f(cos(i*Pi/4), sin(i*Pi/4)); //v2,3,4,5,6,7,8
     }
     glEnd();
     glFlush();
}

  在默认情况下,OpenGL会计算两点顶点之间的其它点,并为它们填上“合适”的颜色,使相邻的点的颜色值都比较接近。如果使用的是RGB模式,看起来就具有渐变的效果。如果是使用颜色索引模式,则其相邻点的索引值是接近的,如果将颜色表中接近的项设置成接近的颜色,则看起来也是渐变的效果。但如果颜色表中接近的项颜色却差距很大,则看起来可能是很奇怪的效果。
使用glShadeModel函数可以关闭这种计算,如果顶点的颜色不同,则将顶点之间的其它点全部设置为与某一个点相同。(直线以后指定的点的颜色为准,而多边形将以任意顶点的颜色为准,由实现决定。)为了避免这个不确定性,尽量在多边形中使用同一种颜色。
glShadeModel的使用方法:
glShadeModel(GL_SMOOTH);    // 平滑方式,这也是默认方式
glShadeModel(GL_FLAT);      // 单色方式

小结:
本课学习了如何设置颜色。其中RGB颜色方式是目前PC机上的常用方式。
可以设置glClear清除后屏幕所剩的颜色。
可以设置颜色填充方式:平滑方式或单色方式。

=====================    第四课 完    =====================
=====================TO BE CONTINUED=====================

时间: 2024-08-09 08:58:15

OpenGL笔记3的相关文章

OpenGL笔记12

OpenGL入门学习[十二] 片断测试其实就是测试每一个像素,只有通过测试的像素才会被绘制,没有通过测试的像素则不进行绘制.OpenGL提供了多种测试操作,利用这些操作可以实现一些特殊的效果.我们在前面的课程中,曾经提到了“深度测试”的概念,它在绘制三维场景的时候特别有用.在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的.如 果使用了深度测试,则情况就会有所不同:每当一个像素被绘制,Op

OpenGL笔记2.1 角的顶点vertex

本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念.向量:http://zh.wikipedia.org/wiki/%E7%9F%A2%E9%87%8F 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中会有所不同. 数学上的点,只有位置,没有大小.但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点.另一方面,无论图形输出设备(例如,显示器)如何精 确,始终不能输出一个无穷小的点.一般情况下,OpenGL中的

opengl 笔记(一)

参考<opengl入门教程>.<OpenGL之坐标转换>.<OpenGL绘制管线操作细节>等资料. 复习下留个备忘:) /*- * Opengl Demo Test * * Fredric : 2016-7-8 */ #include <GLUT/GLUT.h> void display_demo01(); void display_demo02(); void display_demo03(); void display_demo04(); /* * Ma

OpenGL笔记10

今天我们先简单介绍Windows中常用的BMP文件格式,然后讲OpenGL的像素操作.虽然看起来内容可能有点多,但实际只有少量几个知识点,如果读者对诸如“显示BMP图象”等内容比较感兴趣的话,可能不知不觉就看完了. 像素操作可以很复杂,这里仅涉及了简单的部分,让大家对OpenGL像素操作有初步的印象. 学过多媒体技术的朋友可能知道,计算机保存图象的方法通常有两种:一是“矢量图”,一是“像素图”.矢量图保存了图象中每一几何物体的位置.形状.大小等信 息,在显示图象时,根据这些信息计算得到完整的图象

OpenGL笔记2.2 镂空

在第二课中,我们学习了如何绘制几何图形,但大家如果多写几个程序,就会发现其实还是有些郁闷之处.例如:点太小,难以看清楚:直线也太细,不舒服:或者想画虚线,但不知道方法只能用许多短直线,甚至用点组合而成. 这些问题将在本课中被解决. 下面就点.直线.多边形分别讨论. 1.关于点 点的大小默认为1个像素,但也可以改变之.改变的命令为glPointSize,其函数原型如下: void glPointSize(GLfloat size); size必须大于0.0f,默认值为1.0f,单位为“像素”. 注

OpenGl笔记 12.1 stencil 模版 缓冲区

在OpenGL中存在着多种缓冲区,这些缓冲区大致分为: 深度缓冲区:存储每个像素的深度值,当启动深度测试时,片段像素深度值和深度缓冲区深度值进行比较,决定片段哪些像素点数据可以替换到颜色缓冲区中. 模板缓冲区(Stencil Buffer):与颜色缓冲区和深度缓冲区类似,模板缓冲区可以为屏幕上的每个像素点保存一个无符号整数值.这个值的具体意义视程序的具体应用而定.在渲染的过程中,可以用这个值与一个预先设定的参考值相比较,根据比较的结果来决定是否更新相应的像素点的颜色值.这个比较的过程被称为模板测

OpenGL笔记15 顶点数据

这次讲的所有内容都装在一个立方体中,呵呵.呵呵,绘制一个立方体,简单呀,我们学了第一课第二课,早就会了.先别着急,立方体是很简单,但是这里只是拿立方体做一个例子,来说明OpenGL在绘制方法上的改进.从原始一点的办法开始一个立方体有六个面,每个面是一个正方形,好,绘制六个正方形就可以了. glBegin(GL_QUADS);     glVertex3f(...);     glVertex3f(...);     glVertex3f(...);     glVertex3f(...); //

OpenGL笔记11

我们在前一课中,学习了简单的像素操作,这意味着我们可以使用各种各样的BMP文件来丰富程序的显示效果,于是我们的OpenGL图形程序也不再像以前总是 只显示几个多边形那样单调了.——但是这还不够.虽然我们可以将像素数据按照矩形进行缩小和放大,但是还不足以满足我们的要求.例如要将一幅世界地图绘制 到一个球体表面,只使用glPixelZoom这样的函数来进行缩放显然是不够的.OpenGL纹理映射功能支持将一些像素数据经过变换(即使是比较不规 则的变换)将其附着到各种形状的多边形表面.纹理映射功能十分强

OpenGL笔记9

今天介绍关于OpenGL混合的基本知识.混合是一种常用的技巧,通常可以用来实现半透明.但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象.混合是什么呢?混合就是把两种颜色混在一起.具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果.假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃.在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混

OpenGL笔记13

前一段时间里,论坛有位朋友问什么是状态机.按我的理解,状态机就是一种存在于理论中的机器,它具有以下的特点: 1. 它有记忆的能力,能够记住自己当前的状态. 2. 它可以接收输入,根据输入的内容和自己的状态,修改自己的状态,并且可以得到输出. 3. 当它进入某个特殊的状态(停机状态)的时候,它不再接收输入,停止工作. 理论说起来很抽象,但实际上是很好理解的. 首先,从本质上讲,我们现在的电脑就是典型的状态机.可以对照理解: 1. 电脑的存储器(内存.硬盘等等),可以记住电脑自己当前的状态(当前安装