实验三 基于OpenGL的圆柱绘制 OpenGL纹理光照

实验三基于OpenGL的圆柱绘制

1. 实验目的

通过圆柱的绘制,掌握OpenGL编程环境的设置,基本图元的使用,光照的设置以及纹理的设置,理解曲面绘制的基本原理。

2. 实验内容

(1)设置OpenGL编程环境;

(2)利用三角形和四边形等基本图元绘制底面圆圆心在坐标原点,半径为r,高为h,方向沿z轴方向的圆柱;

(3)设置光照

(4)设置纹理:在圆柱的侧面上显示一张图片

3.主要问题&结果截图

①如何绘制圆柱?

一种方法是调用gluc中的函数gluCylinder

但本实验要求利用三角形和四边形等基本图元绘制

所以这里主要采用类似微积分的方式绘制,就是将椭圆的侧面用多个四边形,底面用多个三角形来表示

关键代码

void Circle()底面的圆形void Cylinder()圆柱的侧面

glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串

glVertex3f(0.0f, 0.0f, 0.0f);//圆心:这是三角形作为圆心的顶点

int i = 0;

for (i = 0; i <= 360; i += 15) glBegin(GL_QUAD_STRIP);//连续填充四边形串int i = 0;

for (i = 0; i <= 360; i += 15)

{

float p = i * 3.14 / 180;

glTexCoord2f(p/10,0.1f);

{

float p = i * 3.14 / 180;

glVertex3f(sin(p), cos(p), 0.0f);//圆周:这是三角形作为扇形弧端点的顶点(p的值取0-2PI)就能画出一个类似圆形

}

glEnd();

glVertex3f(sin(p), cos(p), 1.0f);//这个1.0f 指定的是高度

glTexCoord2f(p/10,0.0f);

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

效果:

再调用画圆形的函数画上两个底面

Circle();

glTranslatef(0, 0, 1);//设定高度为1,画

上底面

Circle();

效果:

②如何纹理贴图?

关键代码:

glEnable(GL_TEXTURE_2D);//执行纹理映射,启用二维文理

glBindTexture(GL_TEXTURE_2D, ID);//允许建立一个绑定到目标纹理的有名称的纹理

//ID ——纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用

纹理贴图的原理是纹理映射,即将纹理图片上的点和图形中的点建立对应关系。所以,我们需要glEnable底下的点定义之前关联上与之对应的纹理坐标

即先调用glTexCoord2f设置纹理,再调用glVertex3f绘制点

例如之前的圆形:

glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串

glTexCoord2f(0.0f, 0.0f); //将纹理图(0,0)映射到圆心

glVertex3f(0.0f, 0.0f, 0.0f);

int i = 0;

for (i = 0; i <= 360; i += 15)

{

float p = i * 3.14 / 180;

glTexCoord2f(1.0f, 0.0f);//将纹理图(1,0)映射到圆周

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

这实际上不是一个贴图的效果,因为圆心到圆周上距离相等的点对应的纹理点都是一样的,是一个同心圆的图样

效果:纹理

那么再看圆柱侧面:

glBegin(GL_QUAD_STRIP);//连续填充四边形串

int i = 0;

for (i = 0; i <= 360; i += 15)

{

float p = i * 3.14 / 180;

glTexCoord2f(p/10,0.1f);//p和圆周是相对应的,这里让纹理的横坐标随圆周扫过的角度一起改变,就能够将纹理图“刷”上去了,而纵坐标设置为图像的高度和纹理高度的对应,这里合适的参数是根据实际测试得到的glVertex3f(sin(p), cos(p), 1.0f);

glTexCoord2f(p/10,0.0f);

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

这是最终的效果图:

是不是很像一段木桩呢?

③如何设置光照?

//定义光源

GLfloat ambient[]={0.0,0.0,0.0,1.0};

GLfloat diffuse[]={9.0,9.0,9.0,9.0};

GLfloat position[]={i/6,2.0,2.0,0.0};

//我把光源位置设置得和旋转时用到的角度相关联

//把定义值给GL_LIGHT1

glLightfv(GL_LIGHT1,GL_AMBIENT,ambient);//设置环境光

glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuse);//设置漫反射光

glLightfv(GL_LIGHT1,GL_POSITION,position);//设置光源位置

glEnable(GL_LIGHTING);//启用光照

glEnable(GL_LIGHT1);//启用1号光源

效果:可以观察到物体亮度明暗交替的变化

4.实验总结

这次实验,我算花了比较多心思的。不过我也不是从零开始写的代码,其实原本对于Opengl我也没有很好的基础。我先是从网上找到了几个demo,有的是只能完成贴图的,有的是只能画圆的,有的是只能画侧面的,这些小型的程序比较简单易懂,我通过学习它们的源码,举一反三,最终按照实验要求完成了自己的程序。其中,自己看代码最难理解的就是纹理映射的方式,看懂了之后会发现很简单,学习Opengl,就要理解它状态机的基本思想,自己动手实践一下,改改代码,就很容易理解。

附录:源码

main.cpp

#include

#include

#include

#include

#include

#include "texture.h"

void Circle()

{

glClearColor(0.0,0.0,0.0,0.0);

//glClear(GL_COLOR_BUFFER_BIT);//有l这个会把圆柱侧面清掉

glEnable(GL_TEXTURE_2D);//执行纹理映射,启用二维文理

glBindTexture(GL_TEXTURE_2D, ID);//允许建立一个绑定到目标纹理的有名称的纹理

//ID ——纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串

glTexCoord2f(0.0f, 0.0f);

glVertex3f(0.0f, 0.0f, 0.0f);

int i = 0;

for (i = 0; i <= 360; i += 15)

{

float p = i * 3.14 / 180;

glTexCoord2f(1.0f, 0.0f);

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

glDisable(GL_TEXTURE_2D);

}

void Cylinder()

{

glClearColor(0.0,0.0,0.0,0.0);

//glClear(GL_COLOR_BUFFER_BIT);//有l这个会把圆柱侧面清掉

glEnable(GL_TEXTURE_2D);//执行纹理映射,启用二维文理

glBindTexture(GL_TEXTURE_2D, ID);//允许建立一个绑定到目标纹理的有名称的纹理

//ID ——纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用

glBegin(GL_QUAD_STRIP);//连续填充四边形串

int i = 0;

for (i = 0; i <= 360; i += 15)

{

float p = i * 3.14 / 180;

glTexCoord2f(p/10,0.1f);

glVertex3f(sin(p), cos(p), 1.0f);

glTexCoord2f(p/10,0.0f);

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

glDisable(GL_TEXTURE_2D);

Circle();

glTranslatef(0, 0, 1);

Circle();

}

void renderScene(void)

{

static float i = 0;

i += 0.1;//旋转速度

if (i > 360)

i = 0;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glPushMatrix();

//glColor3f(0, 1, 1);//设置颜色

glTranslatef(0.0, 0.0, -7);//指定位置,大小

glRotatef(i, 1, 1 ,1);//旋转轴

//定义光源

GLfloat ambient[]= {0.0,0.0,0.0,1.0};

GLfloat diffuse[]= {9.0,9.0,9.0,9.0};

GLfloat position[]= {i/6,2.0,2.0,0.0};

//把定义值给GL_LIGHT1

glLightfv(GL_LIGHT1,GL_AMBIENT,ambient);//设置环境光glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuse);//设置漫反射光

glLightfv(GL_LIGHT1,GL_POSITION,position);//设置光源位置

glEnable(GL_LIGHTING);//启用光照

glEnable(GL_LIGHT1);//启用1号光源

Cylinder();//绘制圆柱

//Circle();

glDisable(GL_TEXTURE_2D);

glPopMatrix();

glutSwapBuffers();

}

void changeSize(int w, int h)

{

// 防止除数即高度为0

// (你可以设置窗口宽度为0).

if (h == 0)

h = 1;

float ratio = 1.0* w / h;

// 单位化投影矩阵。

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// 设置视口大小为整个窗口大小

glViewport(0, 0, w, h);

// 设置正确的投影矩阵

gluPerspective(45, ratio, 1, 1000);

//下面是设置模型视图矩阵

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);//设置观测点}

int main(int argc, char * argv[])

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

glutInitWindowPosition(100, 100);

glutInitWindowSize(400, 400);

glutCreateWindow("圆柱by陈羽丰");

glutDisplayFunc(renderScene);

glutIdleFunc(renderScene); //指定程序空闲时调用函数

glutReshapeFunc(changeSize); //指定窗口形状变化时的回调函数

glEnable(GL_DEPTH_TEST);

init();

glutMainLoop();

return 0;

}

texture.h

#include

#include

#include

using std::vector;

using std::cout;

using std::endl;

unsigned int ID;

int LoadBitmap(const char *file)

{

unsigned int ID; //纹理的id

int width,height,i;

byte *image,t; //接受图像数据

FILE *fp; //文件指针

BITMAPFILEHEADER FileHeader; //接受位图文件头

BITMAPINFOHEADER InfoHeader; //接受位图信息头

fp=fopen(file,"rb");

if (fp == NULL)

{

perror("LoadBitmap"); //打开文件失败

return -1;

}

fread(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);

if(FileHeader.bfType != 0x4D42) //确保文件是一个位图文件,效验文件类型{

printf("Error: This file is not a bmp file!");

fclose(fp);

return -1;

}

fread(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);

width=InfoHeader.biWidth;

height=InfoHeader.biHeight;

if (InfoHeader.biSizeImage == 0) //确保图像数据的大小

{

InfoHeader.biSizeImage = width*height*3;

}

fseek(fp, FileHeader.bfOffBits, SEEK_SET); //将文件指针移动到实际图像数据处

image=(byte *)malloc(sizeof(byte)*InfoHeader.biSizeImage); //申请空间

if (image == NULL)

{

free(image);

printf("Error: No enough space!");

return -1;

}

fread(image, 1, InfoHeader.biSizeImage, fp);

for(i=0; i

{

t=image[i];

image[i]=image[i+2];

image[i+2]=t;

}

fclose(fp);

glGenTextures(1, &ID);

glBindTexture(GL_TEXTURE_2D, ID);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width,

height, GL_RGB, GL_UNSIGNED_BYTE,

image);

return ID;

}

void Update()

{

glutPostRedisplay();

}

void Reshape(int w,int h)

{

w=w>h?h:w;

glViewport(0,0,(GLsizei)w,(GLsizei)w); }

void init()

{

ID=LoadBitmap("cyf.bmp");

if (ID == -1)

exit(0);

}

OpenGL入门学习之七——使用光照来表现立体感

OpenGL入门学习之七——使用光照来表现立体感 2009-01-07 11:49 从生理学的角度上讲,眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。因此对于人类而言,光线很大程度上表现了物体的立体感。 请看图1,图中绘制了两个大小相同的白色球体。其中右边的一个是没有使用任何光照效果的,它看起来就像是一个二维的圆盘,没有立体的感觉。左边的一个是使用了简单的光照效果的,我们通过光照的层次,很容易的认为它是一个三维的物体。 图1 OpenGL对于光照效果提供了直接的支持,只需要调用某些函数,便可以实现简单的光照效果。但是在这之前,我们有必要了解一些基础知识。 一、建立光照模型 在现实生活中,某些物体本身就会发光,例如太阳、电灯等,而其它物体虽然不会发光,但可以反射来自其它物体的光。这些光通过各种方式传播,最后进入我们的眼睛——于是一幅画面就在我们的眼中形成了。 就目前的计算机而言,要准确模拟各种光线的传播,这是无法做到的事情。比如一个四面都是粗糙墙壁的房间,一盏电灯所发出的光线在很短的时间内就会经过非常多次的反射,最终几乎布满了房间的每一个角落,这一过程即使使用目前运算速度最快的计算机,也无法精确模拟。不过,我们并不需要精确的模拟各种光线,只需要找到一种近似的计算方式,使它的最终结果让我们的眼睛认为它是真实的,这就可以了。 OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。光源就是光的来源,可以是前面所说的太阳或者电灯等。材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。

实验7 OpenGL光照

实验7 OpenGL光照 一、实验目的 了解掌握OpenGL程序的光照与材质,能正确使用光源与材质函数设置所需的绘制效果。 二、实验内容 (1)下载并运行Nate Robin教学程序包中的lightmaterial 程序,试验不同的光照与材质系数; (2)运行示范代码1,了解光照与材质函数使用。 三、实验原理 为在场景中增加光照,需要执行以下步骤: (1)设置一个或多个光源,设定它的有关属性; (2)选择一种光照模型; (3)设置物体的材料属性。 具体见教材第8章8.6节用OpenGL生成真实感图形的相关内容。 四、实验代码 #include #include static int year =0,day=0; void init(void){ GLfloat mat_specular[]={1.0,1.0,1.0,1.0}; GLfloat mat_shininess[]={50.0}; GLfloat light_position[]={1.0,1.0,1.0,0.0};

GLfloat white_light[]={1.0,1.0,1.0,1.0}; GLfloat Light_Model_Ambient[]={0.2,0.2,0.2,1.0}; glClearColor(0.0,0.0,0.0,0.0); glShadeModel(GL_SMOOTH); //glMaterialfv(材质指定,单值材质参数,具体指针); glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);//镜面反射光的反射系数 glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);//镜面反射指数 //glLightfv(光源,属性名,属性值); glLightfv(GL_LIGHT0, GL_POSITION, light_position); //光源位置 glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); //漫放射光分量强度 glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); //折射光强度 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,Light_Model_Ambient); //光源2 GL_LIGHT1 GLfloat mat_specular1[]={1.0,1.0,1.0,1.0}; GLfloat mat_shininess1[]={50.0}; GLfloat light_position1[]={0.0,0.0,0.0,0.0}; GLfloat red_light[]={1.0,0.0,0.0,1.0}; GLfloat Light_Model_Ambient1[]={0.2,0.2,0.2,1.0}; glLightfv(GL_LIGHT1, GL_POSITION, light_position1); //光源位置 glLightfv(GL_LIGHT1, GL_DIFFUSE, red_light); //漫放射光分量强度 glLightfv(GL_LIGHT1, GL_SPECULAR, red_light); //折射光强度 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,Light_Model_Ambient1); //开启灯光

第三章光照模型纹理映射

第三章光照模型及纹理映射 基本光照模型 1.在现实生活中,当光照在非透明物体上时,部分光线被物体吸收,剩余的部分光线被反射。人眼依靠这种反射光来感知物体的形状、颜色和其他细节。从光源投向物体的光称为入射光,从物体表面反射回的光称为反射光。 1.1光照模型概述 当光照射到物体表面上时,将出现3种情况: ●光从物体表面反射,形成反射光 ●光穿透物体,形成透射光 ●光被物体吸收,转化成为物体的内能 在上述三种情形的光线中,通常只有前2种情形的光线会对人眼产生视觉效果,使人察觉到物体的色彩变化。 OpenGL用一种近似的光照模型模拟现实世界的光照效果。在该模型中,仅当物体表面吸收和反射光线时,光源才会起做作用。每一个物体表面都假定是由某种特性的材料构成的。一种材料可能发出自己的光线,也可能在各个方向上发散一些射入的光线,还有可能像镜子一样在某个方向强烈地反射入射光。 1.2光照分量 在OpenGL的简化光照模型中,将光照分为4个独立的组成部分:辐射光、环境光、漫反射光和镜面反射光。 1)辐射光

辐射光是直接从物体或光源发出的,不受任何其他光源的影响。 2)环境光 环境光是这样一种光线,它被环境多次反射,以致于连初始 方向也难以确定。这种光线看起来就像来自于所有的方向, 当它照在一个物体表面时,它在所有的方向上等量地反射。 3)漫反射光 在被照射物体表面的反射光中,那些均匀地向各个方向反射 出去的光,称为漫反射光,如黑板反射就属于漫反射光 4)镜面反射光 镜面反射光是指超一定方向的反射光,如点光源照射光滑金 属球表面时,会在球表面形成一个特别亮的区域,呈现所谓 的高亮(Highlight>,这就是光源在该物体表面形成的镜面反射光(Specular Light>。点光源照射表面光滑的物体时,高亮区域小而亮;而点光源照射表面粗糙的物体时,高亮区域大而不亮。 1.3创建光源 光源有许多特性,如颜色、位置、方向等。不同特性的光源,作用在物体上的效果是不一样的。 1.3.1定义一个简单光源 在OpenGL中,定义一个光源是由函数glLight(>来实现的,该函数的原型为:void glLight(GLenum light,GLenum pname>; light为一个光源,pname为光源light指定一个单值的光源参数,

opengl机器人纹理

opengl 机器人纹理 #include <glut.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; //是否停止转动 bool IsStop=false; //光照使用光源 GLfloat lightPos[] = { 1.0f, 0.0f, -1.0f, 0.0f }; GLfloat specular[] = { 1.0f, 1.0f, 1.0f, -1.0f};//反射光 GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };//a GLfloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f};//环绕光GLfloat spotDir[] = { 0.0f, 0.0f, -1.0f }; GLboolean bEdgeFlag = TRUE; void showText(void); void resetPerspectiveProjection() ; void setOrthographicProjection() ; void Something(); void renderBitmapString(float x, float y, void *font,char *string); //设置背景 void SetupRC(void) { glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,ambientLight); glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,30.0f); glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0f);

二维纹理映射

二维纹理映射 一、实验目的和要求 掌握纹理映射的基本原理,利用VC++ OpenGL实现纹理映射技术。 二、实验原理 纹理映射是真实感图形制作的一个重要部分,运用纹理映射可以方面地制作真实感图形,而不必花更多的时间去考虑物体的表面纹理。如一张木制桌子其表面的木纹是不规范的,看上去又是那么自然,如果在图形制作中不用纹理映射,那么只是这张桌面纹理的设计,就要花费很大精力,而且设计结果也未必能像现实中那么自然。如果运用纹理映射就非常方便,可以用扫描仪将这样的一张桌子扫成一个位图。然后的具体的操作中,只需把桌面形状用多边形画出来,把桌面纹理贴上去就可以了。 另外,纹理映射能够在多边形进行变换时仍保证纹理的图案与多边形保持一致性。例如,以透视投影方式观察墙面时,远端的砖会变小,而近处的砖就会大一些。 此外,纹理映射也可以用于其他方面。例如,使用一大片植被的图像映射到一些连续的多边形上,以模拟地貌,或者以大理石、木纹等自然物质的图像作为纹理映射到相应的多边形上,作为物体的真实表面。 在OpenGL中提供了一系列完整的纹理操作函数,用户可以用它们构造理想的物体表面,可以对光照物体进行处理,使其映射出所处环境的景象,可以用不同方式应用到曲面上,而且可以随几何物体的几何属性变换而变化,从而使制作的三维场景和三维物体更真实更自然。 在OpenGL中要实现纹理映射,需要经历创建纹理、指定纹理应用方式、启用纹理映射、使用纹理坐标和几何坐标绘制场景几个过程。 用于指定一维、二维和三维纹理的函数分别为: Void glTexImage1D(GLenum target, Glint level, Glint components, GLsizei width, Glint border, GLenum format, GLenum type, const GLvoid *texels); Void glTexImage2D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels); Void glTexImage3D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLsizei depth, Glint border, GLenum format, GLenum type, const GLvoid *texels); 其中,参数target取值一般为GL_TEXTURE_1D, GL_TEXTURE_2D和GL_TEXTURE_3D,分别与一维、二维和三维的纹理相对应。参数Level表示纹理多分辨率层数,通常取值为0,表示只有一种分辨率。参数components的可能取值为1~4的整数以及多种符号常量(如GL_RGBA),表示纹理元素中存储的哪些分量(RGBA颜色、深度等)在纹理映射中被使用,1表示使用R颜色分量,2表示使用R和A颜色分量,3表示使用RGB颜色分量,4表示使用RGBA颜色分量。参数width,height,depth分别指定纹理的宽度、高度、深度。参数format和type表示给出的图像数据的数据格式和数据类型,这两个参数的取值都是符号常量(比如format指定为GL_RGBA,type指定为GL_UNSIGNED_BYTE,参数texels指向内存中指定的纹理图像数据。 在定义了纹理之后,需要启用纹理的函数: glEnable(GL_TEXTURE_1D);

实验七 OPENGL光照效果

1.实验七OpenGL光照效果(选做) 1.实验七:OpenGL光照效果。 2.实验目的:通过上机编程,熟悉并掌握OpenGL中光照效果的制造方法。 3.实验要求: (1)先做实验项目:实验六“OpenGL组合图形”。 (2)每人一组,独立完成。 (3)利用OpenGL提供的颜色、光源、材质设置,对实验六“OpenGL组合图形” 中自己设计的物体设置绘制颜色和材质参数,并在场景中添加光源,形成一 定的光照明暗效果。 4.实验原理及内容: 在现实世界中,光线和物体的材质共同决定了物体在人眼中的效果。OpenGL 中则涉及到绘制颜色、物体的材质参数、场景中的光源颜色和位置,以此达到一定 的真实感光照效果。 (1)颜色: OpenGL通过指定红、绿、蓝(RGB)三个成分的各自亮度来确定颜色,有时还有第四个成分alpha:glColor*(red,green,blue[,alpha]); glColor()函数设置当前的绘图颜色,red、green和blue分别为红、绿、蓝的亮度,alpha为透明度,取值均为0.0~1.0。在该函数之后绘制的所有物体都将使用该 颜色。 (2)光线: OpenGL的光照模型中将光源分成四种: 发射光:一个物体本身就是一个发光源,如太阳、电灯等,这种光不受其它任何光源的影响。 环境光:从光源出发后光线被环境多次反射,以致没有明确的方向,或者说来自于所有的方向。被环境光照射的物体,各个表面都均等受光。 散射光:来自于某个方向,被物体表面均匀地反射,例如荧光照明、窗口射入的阳光等。 镜面光:来自于一个方向,被物体强烈地反射到另一个特定的方向。高亮

度的镜面光往往能在被照射的物体表面产生亮斑,如金属球上的高光区。 对于散射光和镜面光,入射角度、距离和衰减因子还会影响到最终的光照效果。 除了物体本身的发射光以外,通常意义上的光并不会是单纯的环境光、散射光或镜面光,而是由这三种类型的光混合组成的。 在OpenGL中,光也是采用RGBA值来定义的,分别描述光线中红绿蓝各成分的相对亮度。计算混合光的亮度时,则把相应的颜色亮度叠加即可,例如:环境光为(R1,G1,B1),散射光为(R2,G2,B2),镜面光为(R3,G3,B3),则混合后的光线为(R1+R2+R3,G1+G2+G3,B1+B2+B3)。 (3)材质: 材质是物体本身的一种属性,主要用来表征物体对不同颜色、不同类型光线的反射、吸收性能。 在OpenGL中设置材质参数,就是要指定这种材质对环境光、散射光、镜面光的反射能力,有时还需要说明该种材质是否具有发光能力。 在最终绘制每个像素时,OpenGL自行将物体材质的各分量与光线的各分量相乘再叠加,从而得到每个像素的RGB值。例如:光线为(R,G,B),材质为(MR,MG, MB),则最终绘制时颜色为(MR*R,MG*G,MB*B)。 (4)获得光照效果的一般过程为: a)使能光照:glEnable(GL_LIGHTING); b)设置一种光照模式:glLightModel*(); 如果只需要普通的无方向的环境光: GLfloat light_ambient[]={red,green,blue,alpha};//环境光的分值 //全局环境光的默认取值为(0.2,0.2,0.2,1.0) glLightModel*(GL_LIGHT_MODEL_AMBIENT,light_ambient); 如果需要在某个具体位置上放置某个光源,例如: GLfloat light_ambient[]={0.3,0.3,0.3,1.0};//环境光 glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); GLfloat light_diffuse[]={0.7,0.7,0.7,1.0};//散射光 glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); GLfloat light_specular[]={1.0,1.0,1.0,1.0};//镜面光 glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);

计算机图形学大作业报告记录(灯光纹理映射)

计算机图形学大作业报告记录(灯光纹理映射)

————————————————————————————————作者:————————————————————————————————日期:

大作业报告 实验课程名称:计算机图形学 学生姓名: 班级: 学院(系):学生学号: 指导教师:成绩:

一、目的 这次大作业是作为这学期的最后的一个考核,所以必须要用到所有的本学期学过的知识,比如怎样画出三维图形,怎样在图像上在图像上添加纹理光照,怎样使用鼠标和键盘进行人机交互等。 二、主要功能模块设计 1 矩阵运算模块的设计: 功能描述:程序启动后,这部分功能模块会为整个应用程序提供算法支持,具体是矩阵直接的相互运算,在2D向3D转化过程中会起到很重要的作用。 代码设计: float vv(float * v1, float * v2){ return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; } void vxv(float * n, float * v1, float * v2){ n[0] = v1[1] * v2[2] - v1[2] * v2[1]; n[1] = v1[2] * v2[0] - v1[0] * v2[2]; n[2] = v1[0] * v2[1] - v1[1] * v2[0]; } void loadIdentity(Matrix m){ Matrix identity = {{1.0,0.0,0.0,0.0}, {0.0,1.0,0.0,0.0}, {0.0,0.0,1.0,0.0}, {0.0,0.0,0.0,1.0}}; for(int i = 0;i < 4; i++) for(int j = 0;j < 4; j++) m[i][j] = identity[i][j]; } void preMultiply(Matrix p, Matrix m){

OpenGL光照与材质

OpenGL---------光照的基本知识 从生理学的角度上讲,眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。因此对于人类而言,光线很大程度上表现了物体的立体感。 请看图1,图中绘制了两个大小相同的白色球体。其中右边的一个是没有使用任何光照效果的,它看起来就像是一个二维的圆盘,没有立体的感觉。左边的一个是使用了简单的光照效果的,我们通过光照的层次,很容易的认为它是一个三维的物体。 OpenGL对于光照效果提供了直接的支持,只需要调用某些函数,便可以实现简单的光照效果。但是在这之前,我们有必要了解一些基础知识。 一、建立光照模型 在现实生活中,某些物体本身就会发光,例如太阳、电灯等,而其它物体虽然不会发光,但可以反射来自其它物体的光。这些光通过各种方式传播,最后进入我们的眼睛——于是一幅画面就在我们的眼中形成了。 就目前的计算机而言,要准确模拟各种光线的传播,这是无法做到的事情。比如一个四面都是粗糙墙壁的房间,一盏电灯所发出的光线在很短的时间内就会经过非常多次的反射,最终几乎布满了房间的每一个角落,这一过程即使使用目前运算速度最快的计算机,也无法精确模拟。不过,我们并不需要精确的模拟各种光线,只需要找到一种近似的计算方式,使它的最终结果让我们的眼睛认为它是真实的,这就可以了。 OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。光源就是光的来源,可以是前面所说的太阳或者电灯等。材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。 在物理学中,光线如果射入理想的光滑平面,则反射后的光线是很规则的(这样的反射称为镜面反射)。光线如果射入粗糙的、不光滑的平面,则反射后的光线是杂乱的(这样的反射称为漫反射)。现实生活中的物体在反射光线时,并不是绝对的镜面反射或漫反射,但可以看成是这两种反射的叠加。对于光源发出的光线,可以分别设置其经过镜面反射和漫反射后的光线强度。对于被光线照射的材质,也可以分别设置光线经过镜面反射和漫反射后的光线强度。这些因素综合起来,就形成了最终的光照效果。 二、法线向量 在OpenGL中,法线的方向是用一个向量来表示。不幸的是,OpenGL并不会根据你所指定的多边形各个顶点来计算出这些多边形所构成的物体的表面的每个点的法线(这话听着有些迷糊),通常,为了实现光照效果,需要在代码中为每一个顶点指定其法线向量。 指定法线向量的方式与指定颜色的方式有雷同之处。在指定颜色时,只需要指定每一个顶点的颜色,OpenGL就可以自行计算顶点之间的其它点的颜色。并且,颜色一旦被指定,除非再指定新的颜色,否则以后指定的所有顶点都将以这一向量作为自己的颜色。在指定法线向量时,只需要指定每一个顶点的法线向量,OpenGL会自行计算顶点之间的其它点的法线向量。并且,法线向量一旦被指定,除非再指定新的法线向量,否则以后指定的所有顶点都将以这一向量作为自

opengl纹理

OpenGL可以把纹理映射到指定的图形的表面上。简单一点的,就是给平面映射纹理,比如一个四边形,一个长方体的6个面,都 关于将一个位图作为纹理映射到某个或者多个面上,可以学习Jeff Molofee的OpenGL系列 对于指定的多个纹理,要根据自己的需要映射到不同的面上,需要对位图创建一个数组,用来存储位图的名称,然后在初始化Op 成多个纹理存储到一个纹理数组中,接着就可以指定绘制的某个面,对该指定的面进行纹理 下面,在的Jeff Molofee教程的第六课的基础上,实现对6个面分别进行不同的纹理映射 准备工作就是制作6幅不同的位图,如图所示: 关键代码及其说明如下。 创建全局纹理数组 GLuint texture[6]; // 创建一个全局的纹理数组,用来存储将位图转换之后得到的纹理,对应于立方 加载位图文件 加载位图,也就是把位图读取到内存空间,实现纹理的创建,加载位图的函数说明一下 AUX_RGBImageRec *LoadBMP(char *Filename) // 根据位图文件的名称进行加载 {

FILE *File=NULL; // 文件指针 if (!Filename) // 如果没有指定位图文件名称就返回NULL { return NULL; } File=fopen(Filename,"r"); // 根据指定的位图文件名称,打开该位图文件 if (File) // 如果位图文件存在 { fclose(File); // 因为只是需要判断问题是否存在,而不需要对位图文件进行写操作,所以关闭位return auxDIBImageLoad(Filename); // 其实,只需要一个真正存在的位图文件的名称,实现加载位图文 } return NULL; // 位图文件加载失败就返回NULL } 上面实现加载位图的函数中,AUX_RGBImageRec是glaux.h中定义的类型,该类型的定义如下 /* ** RGB Image Structure */ typedef struct _AUX_RGBImageRec { GLint sizeX, sizeY; unsigned char *data; } AUX_RGBImageRec; 首先,AUX_RGBImageRec类型是一个RGB图像结构类型。该结构定义了三个成员: sizeX ——图像的宽度; sizeY ——图像的高度; data; ——图形所包含的数据,其实也就是该图形在内存中的像素数据的一个指针。 AUX_RGBImageRec类型的变量描述了一幅图像的特征。 上述函数中,调用了glaux.h库文件中的auxDIBImageLoad函数,其实它是一个宏,函数原型为auxRGBImageLoadW(LPCWSTR 在该库文件中找到它的定义,如下所示: /* AUX_RGBImageRec * APIENTRY auxRGBImageLoad(LPCTSTR); */ #ifdef UNICODE #define auxRGBImageLoad auxRGBImageLoadW #else #define auxRGBImageLoad auxRGBImageLoadA

OpenGL中的光照模型

OpenGL中的光照模型 一、OpenGL的光照模型 在OpenGL的简单光照模型中反射光可以分成三个分量,环境反射光(Ambient Light)、漫反射光(Diffuse Light)和镜面反射光(Specular Light): a、环境光Ambient,是由光源发出经环境多次散射而无法确定其入射方向的光,即似乎来自所有方向。当环境光照到曲面上时,它在各个方向上均等地发散(类似于无影灯光)。特征:入射方向和出射方向均为任意方向。 b、漫射光Diffuse,来自特定方向,它垂直于物体时比倾斜时更明亮。一旦它照射到物体上,则在各个方向上均匀地发散出去,效果为无论视点在哪里它都一样亮。特征:入射方向唯一、出射方向为任意方向。 c、镜面光Specular,来自特定方向并沿另一方向反射出去,一个平行激光束在高质量的镜面上产生100%的镜面反射。特征:入射方向和出射方向均唯一。 二、创建光源 定义光源特性的函数:glLight*(light , pname, param) 其中第一个参数light指定所创建的光源号,如GL_LIGHT0、GL_LIGHT1、...、GL_LIGHT7;第二个参数pname指定光源特性,这个参数的辅助信息见表1所示;最 GL_LIGHT0,其他几个光源的GL_DIFFUSE和GL_SPECULAR缺省值为 (0.0,0.0,0.0,1.0)。 三、启用光源和明暗处理 如果光照无效,则只是简单地将当前颜色映射到当前顶点上去,不进行法向、光源、材质等复杂计算。要启用光照或关闭光照,调用函数:glEnable(GL_LIGHTING) 或glDisable(GL_LIGHTING)。 启用光照后必须调用函数glEnable(GL_LIGHT0) ,使所定义的光源有效。其它光

实验三基于OpenGL的圆柱绘制OpenGL纹理光照课件资料

实验三基于OpenGL的圆柱绘制 1. 实验目的 通过圆柱的绘制,掌握OpenGL编程环境的设置,基本图元的使用,光照的设置以及纹理的设置,理解曲面绘制的基本原理。 2. 实验内容 (1)设置OpenGL编程环境; (2)利用三角形和四边形等基本图元绘制底面圆圆心在坐标原点,半径为r,高为h,方向沿z轴方向的圆柱; (3)设置光照 (4)设置纹理:在圆柱的侧面上显示一张图片 3.主要问题&结果截图 ①如何绘制圆柱? 一种方法是调用gluc中的函数gluCylinder 但本实验要求利用三角形和四边形等基本图元绘制 所以这里主要采用类似微积分的方式绘制,就是将椭圆的侧面用多个四边形,底面用多个三角形来表示 关键代码 void Circle()底面的圆形void Cylinder()圆柱的侧面 glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串 glVertex3f(0.0f, 0.0f, 0.0f);//圆心:这是三角形作为圆心的顶点 int i = 0; for (i = 0; i <= 360; i += 15) glBegin(GL_QUAD_STRIP);//连续填充四边形串int i = 0; for (i = 0; i <= 360; i += 15) { float p = i * 3.14 / 180; glTexCoord2f(p/10,0.1f);

{ float p = i * 3.14 / 180; glVertex3f(sin(p), cos(p), 0.0f);//圆周:这是三角形作为扇形弧端点的顶点(p的值取0-2PI)就能画出一个类似圆形 } glEnd(); glVertex3f(sin(p), cos(p), 1.0f);//这个1.0f 指定的是高度 glTexCoord2f(p/10,0.0f); glVertex3f(sin(p), cos(p), 0.0f); } glEnd(); 效果: 再调用画圆形的函数画上两个底面 Circle(); glTranslatef(0, 0, 1);//设定高度为1,画 上底面 Circle(); 效果: ②如何纹理贴图? 关键代码:

计算机图形学实验三(纹理映射)

实验三纹理映射 一、实验目的 (1)掌握OpenGl的三维图形制作方法 (2)掌握Visual C++环境下的OpenGL图形开发 二、实验内容 在三维图像上添加纹理映射 三、实验结果 实验代码如下: /*********************************************** * glut_applicationwriten by yyb * ***********************************************/ #include #include #include #include #pragma comment(lib,"glaux.lib") #define MAX_TEXTURES 6 // max textures displayed /* creates a enum type for mouse buttons */ enum { BUTTON_LEFT = 0, BUTTON_RIGHT, BUTTON_LEFT_TRANSLATE, }; intmButton = -1; intmOldY, mOldX; boolfullscreen; //////////////////////////////////// float eye[3] = {0.0f, 0.0f, 7.0f}; float rot[3] = {45.0f, 45.0f, 0.0f}; constint ESC = 27; int wireframe = 0; constint GL_WIN_WIDTH = 640; constint GL_WIN_HEIGHT = 480; constint GL_WIN_INITIAL_X = 0; constint GL_WIN_INITIAL_Y = 0; /* array to hold texture handles */ GLuintg_TexturesArray[MAX_TEXTURES];

OpenGL完全教程 第六章 纹理贴图

OpenGL完全教程 第六章 纹理贴图 作者:何咏 日期:2006-2-3 20:56:39 点击:4719 如需转载本文,请声明作者及出处。 第六章 纹理贴图 截至目前为止,我们已经能够绘制各种3D物体,并为它们增加光照效果,使它们更具有立体感。但是,在实际运用中,我们不仅仅需要简单地绘制一个物体的轮廓,我们需要绘制蓝天白云、真实的墙壁和物体、人物和树木。要达到这一目的,简单的将模型的轮廓绘制出来时远远不够的。我们需要使用纹理贴图来再现真实的细节。 在计算机硬件高速发展的今天,即使是最低端的显卡也能很快地处理大量的纹理,满足我们的需求。这些条件可以让我们毫无顾虑的使用OpenGL的纹理贴图功能,绘制出形形色色的物体。 本章将是学习OpenGL的最后一个基础章节。本章之后,我们将开始接触一些OpenGL的高级专题 学习本章内容,你将了解: ?什么是纹理贴图 ?如何创建纹理图像 ?OpenGL中贴图的方式 ?使用纹理对象来管理的纹理 ?将纹理运用到图元上 ?自动生成纹理坐标 ?多贴图纹理 6.0 准备工作 由于Delphi为我们所提供的OpenGL头文件是OpenGL1.0版本的,因此里面缺少一些函数的声明,这导致我们不能使用直接调用这些函数。因此我们要手动为OpenGL库添加下面的代码一进行补完: procedure glBindTexture(target: GLEnum; texture: GLuint); stdcall; external opengl32; procedure glDeleteTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32; procedure glGenTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32; function glIsTexture(texture: GLuint): GLboolean; stdcall; external opengl32; procedure glPolygonOffset(factor, units: GLfloat); stdcall; external opengl32; function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum;

OpenGL光照

计算机图形学实验指导(三) – OpenGL光照 1.光照简介 采用光照要做的工作包括:创建光源,激活光照以及光源,以及定义物体的材质。创建光源是要定义光源的特征,物体的材质则与光源一起决定到达人眼的光的颜色。若光源颜色为(LR,LG,LB),材质颜色为(MR,MG,MB),则到达人眼的颜色为(LR*MR, LG*MG, LB*MB)。 2.简单光照模型 一般来说,反射光可以分成三个分量,即环境反射、漫反射和镜面反射。环境反射分量假定入射光均匀地从周围环境入射至景物表面并等量地向各个方向反射出去,通常物体表面还会受到从周围环境来的反射光(如来自地面、天空、墙壁等的反射光)的照射,这些光常统称为环境光(Ambient Light);漫反射分量表示特定光源在景物表面的反射光中那些向空间各方向均匀反射出去的光,这些光常称为漫射光(Diffuse Light);镜面反射光为朝一定方向的反射光,如一个点光源照射一个金属球时会在球面上形成一块特别亮的区域,呈现所谓“高光(Highlight)”,它是光源在金属球面上产生的镜面反射光(Specular Light)。对于较光滑物体,其镜面反射光的高光区域小而亮;相反,粗糙表面的镜面反射光呈发散状态,其高光区域大而不亮。 3.OpenGL光源 光源有许多特性,如颜色、位置、方向等。选择不同的特性值,则对应的光源作用在物体上的效果也不一样,下面的函数定义了OpenGL的光源。 void glLightfv(GLenum light , GLenum pname, TYPE param) 其中第一个参数light指定所创建的光源号,如GL_LIGHT0、GL_LIGHT1、...、GL_LIGHT7。第二个参数pname指定光源特性,这个参数的具体信息见下表所示。最后一个参数设置相应的光源特性值。 pname 参数名说明 GL_AMBIENT RGBA模式下环境光 GL_DIFFUSE RGBA模式下漫反射光 GL_SPECULAR RGBA模式下镜面光 GL_POSITION 光源位置齐次坐标(x,y,z,w) GL_SPOT_DIRECTION 点光源聚光方向矢量(x,y,z) GL_SPOT_EXPONENT 点光源聚光指数 GL_SPOT_CUTOFF 点光源聚光截止角 例如:下面定义了一个位置在(1,1,1),没有环境光,镜面反射光和漫反射光都为白光的光源GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat light_ambient [] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat light_diffuse [] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT , light_ambient ); glLightfv(GL_LIGHT0, GL_DIFFUSE , light_diffuse );

Opengl实验报告及源代码实验六 颜色与光照

南昌大学实验报告 学生姓名:学号:专业班级: 实验类型:□验证□综合□设计□创新实验日期:2018.11 实验成绩: 一、实验名称 实验六颜色与光照 二、实验内容 1.指定几何模型的绘制颜色,使用平滑着色模式用多种不同的颜色绘制多边形; 2.通过定义光源、材质和光照模型属性渲染物体的光照效果; 3.创建一个3D虚拟场景,利用定向光、点光源和聚光灯等不同光源实现3D场景的光 照效果。 三、实验目的 1.了解RGBA颜色的实现原理,掌握利用Flat和Smooth着色模式来绘制不同颜色的物 体的方法; 2.掌握OpenGL光照模型,理解光源、材质和光照模型如何综合影响物体的光照效果。 3.掌握定向光、点光源和聚光灯的不同属性及三种光源光照效果的计算方法。 四、实验步骤 1.建立立方体几何模型。定义立方体顶点的位置坐标和纹理坐标,设置不同立方体在 世界坐标系中的位置: // Set up vertex data (and buffer(s)) and attribute pointers GLfloat vertices[] = { // Positions // Normals // Texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,

基于OpenGL的三维图形的绘制_吴爱兰

PSLIBLINGS|WS_CLIPCHILDREN;(2)OnCreate 为了使OpenGL能在绘图表面(窗口或位图)上绘制图象,必须先对绘图表面进行初始化,既通过对象素格式的描述(分配并填充PIXELFORMATDESCRIPTOR结构)、选择(通过ChoosePixelFormat函数)和设置(通过SetPixelFormat函数),规定绘图表面的某些属性。此外,只有在OpenGL环境中,OpenGL命令才能被接受并执行,所以我们必须创建OpenGL绘制环境(由函数wgCreatContext完成)。在必要的情况下,还将进一步创建调色板。我们选择视图类消息句柄OnCreate作为完成这些工作的恰当场所。 (3)OnSize 窗口大小变动时会触发消息句柄,OnSize在此函数中,我们的目的是建立3D OpenGL坐标与2D屏幕坐标之间的映射,体现为做三件事: 获取当前的绘制环境。这个使用wgMakeCurrent函数来完成,函数如下所示,BOOL bResult=wgMakeCurrent(dc.m_Hdc,m_hrc); 设置映射方式。OpenGL大量使用矩阵运算,因为场地景到屏幕的变换,以及3D图形的3D旋转、平移和缩放都是采用矩阵变换实现的。在OnSize函数中,我们使用投影栈来设置我们观察物体的方法,总共用到四个函数,如下所示, GLdouble gldAspect=(GLdouble)cx/(GLdouble)cy; GlMatrixMode(GL_PROJECTION);//指定所使用的矩阵栈 GlLoadIdentity(); //清空矩阵栈GlPerspective(45.0,gldAspect,1.0,10.0);//设定用户的可见区域 GlViewport(0,0,cx,xy); //设置在用户区上的绘制区域 激活当前绘制环境。在使用多个绘 基于OpenGL的三维图形的绘制 吴爱兰1 楼建列2 1、浙江公路机械技工学校 310014 2、浙江经济职业技术学院教育技术中心 310018 一、OpenGL的简介 目前OpenGL是工业界公认的先进而强大的三维图形编程接口(3D API)。它有着功能完备的二维和三维图形处理能力,是理想的三维应用程序开发工具。它包含将近120个绘制点、线和多边形等3D图形原语的绘制命令,及其他众多的功能函数,能处理各种图形基本元素及图形特征效果,如明暗度、纹理贴图、Z缓冲、反走样、光照模型等。 OpenGL是Visual C++中附带的SDK(Software Development Kit)。它直接使用绘制环境,间接使用设备环境,因此设备环境中的当前画笔、画刷、颜色、字体等均对OpenGL绘制无任何影响。甚至GDI映射模式都对OpenGL不起作用。所以,使用MFC开发应用程序并采用OpenGL进行绘制,必须遵循一定的规范,先建立OpenGL绘制环境,然后才能使用OpenGL命令。 二、OpenGL绘图环境的设置 2.1 准备工作 为了能够使用OpenGL命令,必须要在预编译头文件中加入两个库函数,openggl32.lib、glu32.lib,如果还需要使用辅助库中所定义的函数,则需要再加入 glaux.lib 库函数。 2.2 消息句柄 (1)PrecreateWindow 为了使用OpenGL绘制,必须先在有关窗口的客户区中进行OpenGL初始化,即需要重载消息句柄PrecreateWindow并将窗口风格规定为:cs_style|=WS_SLI 制环境的情况下,即将离开时,应调用wglMakeCurrent来激活当前绘制环境,wglMakeCurrent(NULL,NULL); (4)OnDraw 此函数真正负责绘制3D图象,包括以下步骤: 在DC中选择并实现调色板; 调用wglMakeCurrent使绘制环境成为当前的; 调用OpenGL命令绘制场景; 如果使用双缓存像素格式,交替绘制缓存; 重新为DC选择原始的调色板。经过上述一系列步骤以后,OpenGL的绘图环境就已经设置完成,下面就可以通过OpenGL的绘图命令进行图形的绘制。 三、三维图形的绘制 设置完成OpenGL的绘图环境后,就可以在VC++中使用OpenGL三维函数库进行图形的绘制。函数的使用如下: glPolygonMode函数是用来选择多边形光栅化模式的。它的原型是voidglPolygonMode(Glenum face ,Glenummode),其中,参数face用来指定mode应用的多边形,对于正面多边形,必须为GL_FRONT,对于反面多边形,必须为GL_BACK,对于正面和反面多边形,必须为GL_FRONT_AND_BACK。参数mode用来指定多边形光栅化的方式,可以选择的值为GL_POINT、GL_LINE和GL_FILL。 glBegin和glEnd函数用来限定一组或多组图原的顶点定义。OpenGL绘制的所有复杂的三维物体都是由一定数量的基本图形元素(点、线、多边形)构成。曲线和曲面分别是由一系列直线段和多边形近似得到。基本图元类型由glBegin的参数设定,它的参数只有一个变量,该

相关文档
最新文档