【OpenGL】计算机图形学实验六: 综合实验(Bresenham算法绘制直线和圆;纹理和光照的应用)

实验六: 综合实验

(Bresenham算法绘制直线和圆;纹理和光照的应用)

1、实验目的和要求

  1. 巩固图形学中以前所学的算法,例如:Bresenham画线、圆,种子填充等;
  2. 巩固图形学算法的基础上,加入光照、纹理、阴影、动画、碰撞等实现综合与创新; 
  3. 熟练掌握图形学,做到学为己用。

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 <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <cmath>
#include <vector>
#include <iostream>

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<int> p0, vector<int> 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<int> 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 <GLUT/glut.h>
#else

#include <GL/glut.h>

#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运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值