(Bresenham算法绘制直线和圆;纹理和光照的应用)
1、实验目的和要求
2、实验设备
PC机、CodeBlocks\VS系列\OpenGL安装包
3、实验内容及原理
题目1:
选择实验目的和要求中的2个以上要求。
Bresenham法绘制直线、圆,完成一副图形。
实现OpenGL中光照和纹理的应用。
实验原理(基本知识):
1. OpenGL纹理。
1) 定义以下三个函数分别指定一维、二维和三维的纹理:
void glTexImage1D(GLenum target,GLint level, GLint internalformat, GLsizei width, GLint border, GLint format, GLenum type, const GLvoid *pixels);
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLint format, GLenum type, const GLvoid *pixels);
void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * data);
2) 定义纹理后,使用GLenable(GL_TEXTURE_{123}D)启用纹理。
3) 常用的放大和缩小滤波的方法:GL_NEAREST和GL_LINEAR。
其中,GL_LINEAR的质量更高,GL_NEAREST的执行速度更快、计算量更小。
2. OpenGL点光源。
void glLight{if}(GLenum light, GLenum pname, TYPE param);
void glLight{if}v(GLenum light, GLenum pname, TYPE param);
light参数指定光源,pname指定属性属性名,param即为设置的参数。
其中,pname的取值包括以下部分:
pname |
含义 |
GL_AMBIENT |
环境光强度 |
GL_DIFFUSE |
漫射强度 |
GL_SPECULAR |
反射强度 |
GL_POSITION |
光在同质对象坐标中的位置 |
GL_SPOT_DIRECTION |
同质对象坐标中光的方向 |
GL_SPOT_EXPONENT |
光的强度分布 |
GL_SPOT_CUTOFF |
光源的最大分布角度。 |
GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION |
三个光衰减因子,即固定衰减因子、线性衰减因子和二次衰减因子 |
4、实验源程序代码、运行结果 (截图)
4.1 Bresenham算法绘制直线和圆的组合图形
4.1.1源程序代码
#ifdef __APPLE__
#include
#else
#include
#endif
#include
#include
#include
using namespace std;
void resize(GLsizei w, GLsizei h) {
if (h == 0) {
h = 1;
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
glOrtho(-200.0f, 200.0f, -200.0f, 200.f * h / w, 1.0f, -1.0f);
} else {
glOrtho(-200.0f, 200.0f * w / h, -200.0f, 200.0f, 1.0f, -1.0f);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void drawPixel(int x, int y) {
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
// BresenhamLine
void BresenhamLine(vector p0, vector p1) {
int x0 = p0[0], y0 = p0[1],
x1 = p1[0], y1 = p1[1];
// 两种特殊情况: x0 == x1 || y0 == y1
if (x0 == x1) {
if (y0 > y1) {
swap(y0, y1);
}
for (int i = y0; i <= y1; i++) {
drawPixel(x0, i);
}
return ;
} else if (y0 == y1) {
if (x0 > x1) {
swap(x0, x1);
}
for (int i = x0; i <= x1; i++) {
drawPixel(i, y0);
}
return ;
}
int kRev = (y1 - y0) / (x1 - x0);
bool isKGT1 = false; // 1 : K is greater than 1
bool isKNeg = (y1 - y0) * (x1 - x0) >= 0 ? false : true; // 1 : K is negative
if (abs(kRev) >= 1) { // |k| > 1
swap(x0, y0);
swap(x1, y1);
isKGT1 = true;
}
if (isKGT1) {
if (isKNeg) {
if (y0 < y1) {
swap(y0, y1);
swap(x0, x1);
}
} else {
if (y0 > y1) {
swap(y0, y1);
swap(x0, x1);
}
}
} else {
if (x0 > x1) {
swap(y0, y1);
swap(x0, x1);
}
}
int x = x0, y = y0;
int dx = x1 - x0, dy = y1 - y0;
if (isKNeg) {
dy = -dy;
}
int e = -dx;
while (x <= x1) {
if (isKGT1) {
drawPixel(y, x);
} else {
drawPixel(x, y);
}
x++;
e += 2 * dy;
if (e > 0) {
if (isKNeg) {
y--;
} else {
y++;
}
e -= 2 * dx;
}
}
}
// 八分法画圆
void drawPixels(int x, int y) {
glBegin(GL_POINTS);
glVertex2i(x, y);
glVertex2i(y, x);
glVertex2i(-x, y);
glVertex2i(y, -x);
glVertex2i(x, -y);
glVertex2i(-y, x);
glVertex2i(-x, -y);
glVertex2i(-y, -x);
glEnd();
}
// BresenhamCircle
void BresenhamCircle(int r) {
int x = 0, y = r;
int d = 1 - r; // 判别式
while (x <= y) {
drawPixels(x, y);
if (d < 0) {
d += 2 * x + 3;
} else {
d += 2 * (x - y) + 5;
y--;
}
x++;
}
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3d(0, 0, 0);
vector p0(2), p1(2);
p0[0] = -150, p0[1] = -150;
p1[0] = 150, p1[1] = 150;
BresenhamLine(p1, p0);
int r = 30;
glColor3d(1, 0, 0);
for (int i = -1; i < 4; i++) {
glTranslated(sqrt(2) * r * i, sqrt(2) * r * i, 0);
BresenhamCircle(r);
glLoadIdentity();
}
glutSwapBuffers();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(400, 400);
glutInitWindowPosition(10, 10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("BresenhamLine Line && Circle");
glutReshapeFunc(resize);
glutDisplayFunc(display);
// setRC
glClearColor(1, 1, 1, 1);
glutMainLoop();
return 0;
}
4.1.2运行结果
4.2结合纹理和光照
4.2.1源代码
#ifdef __APPLE__
#include
#else
#include
#endif
static GLubyte TextureImage[16][16][3];
void Init() {
/** 材质 **/
GLfloat mat_ambient[] = {0.8f, 0.8f, 0.8f, 1.0f}; // 对环境光的反射系数
GLfloat mat_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 对漫射光的反射系数
GLfloat mat_specular[] = {0.5f, 0.5f, 0.5f, 1.0f}; // 对镜面光的反射系统
GLfloat mat_shininess[] = {100.0f}; // 镜面反射指数
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
/** 光源 **/
GLfloat diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat position[] = {1.0f, 1.0f, 1.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
/** 纹理 **/
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 16; j++) {
// #e3fdfd
TextureImage[i][j][0] = 0xe3;
TextureImage[i][j][1] = 0xfd;
TextureImage[i][j][2] = 0xfd;
}
}
for (int i = 4; i < 8; i++) {
for (int j = 0; j < 16; j++) {
// #cbf1f5
TextureImage[i][j][0] = 0xcb;
TextureImage[i][j][1] = 0xf1;
TextureImage[i][j][2] = 0xf5;
}
}
for (int i = 8; i < 12; i++) {
for (int j = 0; j < 16; j++) {
// #a6e3e9
TextureImage[i][j][0] = 0xa6;
TextureImage[i][j][1] = 0xe3;
TextureImage[i][j][2] = 0xe9;
}
}
for (int i = 12; i < 16; i++) {
for (int j = 0; j < 16; j++) {
// #71c9c3
TextureImage[i][j][0] = 0x71;
TextureImage[i][j][1] = 0xc9;
TextureImage[i][j][2] = 0xc3;
}
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
void ChangeSize(GLsizei w, GLsizei h) {
if (h == 0) {
h = 1;
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
glOrtho(-10.0f, 10.0f, -10.0f * h / w, 10.0f * h / w, -10.0f, 10.0f);
} else {
glOrtho(-10.0f * w / h, 10.0f * w / h, -10.0f, 10.0f, -10.0f, 10.0f);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // 纹理受光照影响
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glutSolidTeapot(5);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
}
int main(int argc, char *argv[]) {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(10, 10);
glutCreateWindow("纹理 && 光照");
glutDisplayFunc(Display);
glutReshapeFunc(ChangeSize);
Init();
glutMainLoop();
return 0;
}
4.2.2运行结果