请登陆或者注册新用户 用户名 密码 记住密码 注册新用户 忘记密码了

回 帖 快速回帖 发 新 帖 刷新版面
主题:[原创]OpenGL入门学习——第四课

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-2 22:33:00    [回复] 
楼主
现在放出第四课的内容。
先回顾一下我们都学习了些什么:

第一课,编写第一个OpenGL程序
第二课,绘制几何图形
第三课,绘制几何图形的一些细节问题
第四课,颜色的选择  ——→  本次课程的内容

本次学习的是颜色的选择。终于要走出黑白的世界了~~


=====================未完,请勿跟帖=====================

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-2 22:34:00    [回复]  [引用]
1楼
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表示最大的使用。
这些规则看似麻烦,但熟悉后实际使用中不会有什么障碍。

=====================未完,请勿跟帖=====================

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-2 22:36:00    [回复]  [引用]
2楼
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、手机等,索引颜色还是有它的用武之地。


=====================未完,请勿跟帖=====================

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-2 22:36:00    [回复]  [引用]
3楼
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();
}
呵,这个还真简单~

=====================未完,请勿跟帖=====================

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

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

=====================未完,请勿跟帖=====================

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-2 22:38:00    [回复]  [引用]
5楼
小结:
本课学习了如何设置颜色。其中RGB颜色方式是目前PC机上的常用方式。
可以设置glClear清除后屏幕所剩的颜色。
可以设置颜色填充方式:平滑方式或单色方式。

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

 

作者:sarrow

专家分:35450

级别:178级别:178级别:178级别:178级别:178

发表时间:2006-8-2 23:05:00    [回复]  [引用]
6楼
偶顶!

 

作者:cracker007

专家分:22080

级别:111级别:111级别:111级别:111级别:111级别:111

发表时间:2006-8-2 23:20:00    [回复]  [引用]
7楼
2楼内容的一个建议:

尽量不要用glaux.
原因:
1 功能不完善,不适合于编程人员。
2 和平台有关,这有悖于openGL通用平台的初衷。

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-2 23:27:00    [回复]  [引用]
8楼
这个我知道的,我也说了aux已经过时,目前很多平台都放弃支持它了。
只是不知道为什么我的GLUT无法设置颜色表,所以就找了这个aux来做例子,但我不打算讲解aux的。

 

作者:eften

专家分:80

级别:1

发表时间:2006-8-3 8:14:00    [回复]  [引用]
9楼
先顶了!收藏!还得慢慢学阿!

 

作者:jdxyw

专家分:230

级别:2

发表时间:2006-8-3 15:30:00    [回复]  [引用]
10楼
好东西,希望下课快点出来啊!

 

作者:vfdff

专家分:740

级别:4级别:4级别:4

发表时间:2006-8-5 20:37:00    [回复]  [引用]
11楼
#include <GL/glut.h>
#include <math.h>
#include <conio.h>

const int N = 20;
const GLfloat R = 0.5f;
const GLfloat Pi = 3.1415926536f;


void myDisplay(void)
{
    int i;
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POINTS /* &Ocirc;&Uacute;&Otilde;&acirc;&Agrave;&iuml;&Igrave;&icirc;&Eacute;&Iuml;&Auml;&atilde;&Euml;ù&Iuml;&pound;&Iacute;&ucirc;&micro;&Auml;&Auml;&pound;&Ecirc;&frac12; */ );
        glVertex2f(0.0f, 0.0f);/* &Ocirc;&Uacute;&Otilde;&acirc;&Agrave;&iuml;&Ecirc;&sup1;&Oacute;&Atilde;glVertex*&Iuml;&micro;&Aacute;&ETH;&ordm;&macr;&Ecirc;&yacute; */
        glVertex2f(0.5f, 0.0f);/* &Ouml;&cedil;&para;¨&Auml;&atilde;&Euml;ù&Iuml;&pound;&Iacute;&ucirc;&micro;&Auml;&para;&yen;&micro;&atilde;&Icirc;&raquo;&Ouml;&Atilde; */
    glEnd();
    glFlush();
     getch();  /*为什么按如一个键,还是不能画出下面的圈呢 ??*/
    glBegin(GL_LINES); 
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.5f, 0.0f);
    glEnd();
    glFlush();
}难道一次只能 画一种图的吗??

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-5 22:53:00    [回复]  [引用]
12楼
getch函数只检测在命令行窗口下按的键。
而我们现在是在OpenGL图形窗口,所以getch不会收到任何信息。

我并不准备讲如何处理键盘和鼠标的事件。
如果需要看到先画一条线,再画第二条,可以使用Sleep函数等待一段时间。
Sleep(3000); // 等待3000毫秒,即3秒。

使用Sleep函数需要加上#include <windows.h>



P.S.
最近两天都没有更新,但这并不表示学习就到此为止。
大家不要着急,我会陆续写出后面的课程的。

 

作者:lybaby

专家分:0

级别:1

发表时间:2006-8-6 9:51:00    [回复]  [引用]
13楼
顶一下

 

作者:vfdff

专家分:740

级别:4级别:4级别:4

发表时间:2006-8-6 22:13:00    [回复]  [引用]
14楼
难道 这个新建的窗口就只能处理 图象拉 
不能再象普通窗口一样可以接收输入的数据吗 ???

 

作者:eastcowboy

专家分:22560

级别:113级别:113级别:113级别:113级别:113级别:113级别:113级别:113

发表时间:2006-8-7 20:51:00    [回复]  [引用]
15楼
我们的主题是OpenGL,而OpenGL是一个图形接口,它不包括处理输入输出之类的东西,因此我们需要借助其他工具,比如GLUT。使用glutKeyboardFunc函数可以获取键盘消息,然后就可以处理输入了。(具体的使用方法请自己Google)
当然也可以完全不使用GLUT,自己建立窗口,并处理其中的键盘事件。或者使用控件之类。这就越扯越远了~

 

作者:vfdff

专家分:740

级别:4级别:4级别:4

发表时间:2006-8-8 18:45:00    [回复]  [引用]
16楼
//glutMainLoop();
    
    Sleep(3000); // &micro;&Egrave;&acute;&yacute;3000&ordm;&Aacute;&Atilde;&euml;&pound;&not;&frac14;&acute;3&Atilde;&euml;&iexcl;&pound;
上面的 glutMainLoop();语句到底还需不需要,我按照你的方式弄好后 
用 VC运行的时候 ,在注释 掉 glutMainLoop();的时候 只有出来直线的那个图
而不注释的时候,好象中间并没有间隔 3秒,而是仍然一起两个窗口出来 
而且着两个窗口好象都延迟拉一些时间才出来的!!

 

作者:vfdff

专家分:740

级别:4级别:4级别:4

发表时间:2006-8-8 18:55:00    [回复]  [引用]
17楼
#include <stdlib.h>
#include <GL/glut.h>

GLfloat light_ambient[] = {0.1,0.1,0.1,0.0};
GLfloat light_diffuse[] = {1.0,1.0,1.0,0.0};
GLfloat light_specular[] = {1.0,1.0,1.0,0.0};
GLfloat light_position[] = {-10.0,0.0,5.0,0.0};

GLfloat material_ambient[] = {0.1745,0.01175,0.01175};
GLfloat material_diffuse[] = {0.61424,0.04136,0.04136};
GLfloat material_specular[] = {0.727811,0.626959,0.62659};

GLfloat fogColorWhite[] = {1.0,1.0,1.0,1.0};
GLfloat fogColorGreen[] = {0.0,1.0,0.0,1.0};
float fogDensity = 0.02;


void myInit(void)
{
 /*设置背景色*/
 glClearColor(0.5,0.5,0.5,1.0);

 /*设置光照*/
 glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
 glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
 glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
 glLightfv(GL_LIGHT0,GL_POSITION,light_position);

 /*设置材质*/
 glMaterialfv(GL_FRONT,GL_AMBIENT,material_ambient);
 glMaterialfv(GL_FRONT,GL_DIFFUSE,material_diffuse);
 glMaterialfv(GL_FRONT,GL_SPECULAR,material_specular);
 glMaterialf(GL_FRONT,GL_SHININESS,0.6*128);

 glShadeModel(GL_SMOOTH);

 glEnable(GL_DEPTH_TEST);
 glDepthFunc(GL_LESS);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
 glEnable(GL_AUTO_NORMAL);
 glEnable(GL_NORMALIZE);
 glFrontFace(GL_CW);

 /*设置雾化*/
 glEnable(GL_FOG);
 glFogi(GL_FOG_MODE,GL_LINEAR);
 glFogfv(GL_FOG_COLOR,fogColorWhite);
 glFogf(GL_FOG_DENSITY,fogDensity);
 glFogf(GL_FOG_START,0.0);
 glFogf(GL_FOG_END,15.0);

 glHint(GL_FOG_HINT,GL_DONT_CARE);
}

/*根据不同的键值设置不同的雾化效果*/
static void myKey(unsigned char key,int x,int y)
{
 switch(key)
 {
  case 33: //shift+1
   fogDensity *= 1.10;
   glFogi(GL_FOG_MODE,GL_EXP);
   glFogf(GL_FOG_DENSITY,fogDensity);
   glutPostRedisplay();
   break;

  case 64: //shift+2
   fogDensity /= 1.10;
   glFogi(GL_FOG_MODE,GL_EXP);
   glFogf(GL_FOG_DENSITY,fogDensity);
   glutPostRedisplay();
   break;

  case 35: //shift+3
   glFogi(GL_FOG_START,0.0);
   glFogi(GL_FOG_END,8.0);
   glutPostRedisplay();
   break;

  case 36: //shift+4
   glFogi(GL_FOG_MODE,GL_EXP2);
   glutPostRedisplay();
   break;

  case 37: //shift+5
   glFogi(GL_FOG_MODE,GL_LINEAR);
   glutPostRedisplay();
   break;

  case 94: //shift+6
   glFogfv(GL_FOG_COLOR,fogColorGreen);
   glutPostRedisplay();
   break;

  case 27: //Esc
   exit(0);

  default:
   break;
 }
}

/*绘制圆锥体*/
void myDisplay(void)
{
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

 glPushMatrix();
 glTranslatef(-4.0,4.0,0.0);
 glRotatef(30.0,1.0,1.0,0.0);
 glutSolidCone(1.0,50.0,20.0,20.0);
 glPopMatrix();
 glutSwapBuffers();
}

void myReshape(int w,int h)
{
 glViewport(0,0,(GLsizei)w,(GLsizei)h);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(100.0,1.0,1.0,20.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glTranslatef(0.0,0.0,-15.5);
}

int main(int argc,char ** argv)
{
 /*初始化*/
 glutInit(&argc,argv);
 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
 glutInitWindowSize(300,300);
 glutInitWindowPosition(100,100);

 /*创建窗口*/
 glutCreateWindow(" FOG ");

 /*绘制与显示*/
 myInit();
 glutKeyboardFunc(myKey); // 键处理  
 glutReshapeFunc(myReshape);
 glutDisplayFunc(myDisplay);

 /*进入GLUT事件处理循环*/
 glutMainLoop();
 return 0;
}
在网上找到这个示例代码
怎么一运行好多错误
希望楼主看看,还需要注意什么??

另外还想为下,能不能再使用以前 那种自己 弄的子程序 
这些程序不是以  gl, glut标志 等开始的

 

作者:houfaqing

专家分:2610

级别:14级别:14级别:14级别:14级别:14

发表时间:2006-9-2 13:17:00    [回复]  [引用]
18楼
UP!~MARK!

 

作者:阿斯兰

专家分:1700

级别:9级别:9级别:9级别:9

发表时间:2006-9-26 20:23:00    [回复]  [引用]
19楼
好久没出了

 

作者:vfdff

专家分:740

级别:4级别:4级别:4

发表时间:2006-10-28 0:29:00    [回复]  [引用]
20楼
第四课终于见到拉 
真好 
谢谢楼主

 

[首页] [上页] [下页] [尾页]     共有 27 回帖 当前第 1 页(共2页 20帖/页)     跳转至第
回 帖 快速回帖 发 新 帖 刷新版面

版主管理:  删除此帖   转贴   置顶   取消精华   强制结帖   >>>进入管理页面