PART ONE
codes.cpp
#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
using namespace std;
#define width 222
#define height 207
#define num 3 //三角形顶点计数器
#define point_num 4 //顶点空间计数器
#define triangle_num 2 //三角形图元计数器
struct Vector3f {
GLfloat x;
GLfloat y;
GLfloat z;
};
struct Color {
GLubyte r;
GLubyte g;
GLubyte b;
GLubyte a;
};
struct Indice {
int v0;
int v1;
int v2;
};
GLubyte image[height][width][4];
void initRectangle()
{
//NDC下点位置信息的初始化
Vector3f points[point_num] = {
{0.0f,0.0f,0.0f},
{0.5f,0.0f,0.0f},
{0.5f,0.5f,0.0f},
{0.0f,0.5f,0.0f}
};
//颜色空间初始化
Color colors[point_num] = {
{255,0,0,0},
{0,255,0,0},
{0,0,255,0},
{255,255,0,0}
};
//索引空间初始化
Indice indices[triangle_num] = {
{0,1,3},
{3,2,1},
};
for (int j = 0; j < triangle_num; j++) {
//采样出三角形的索引存入v[num]
int v[num] = { indices[j].v0,indices[j].v1,indices[j].v2 };
//cout << v[0] << " " << v[1] << " " <<v[2] << endl;
//根据采样出的索引v[]对points[]和colors[]空间进行采样
Vector3f triangle_points[num] = { points[v[0]],points[v[1]],points[v[2]] };
Color triangle_colors[num] = { colors[v[0]],colors[v[1]],colors[v[2]] };
//cout << triangle_points[0].x << " " << triangle_points[0].y << " " << triangle_points[0].z << endl;
//triangle_points[]空间转换的结果存入screen[]空间
Vector3f screen[num];
for (int i = 0; i < num; i++) {
screen[i].x = (triangle_points[i].x + 1.0f) * (width / 2 - 1);
screen[i].y = (triangle_points[i].y + 1.0f) * (height / 2 - 1);
screen[i].z = triangle_points[i].z; //zbuffer维持NDC空间
}
int LINE_LOOP = num; //模式选择器
//if (j == 0) {
// LINE_LOOP = num; //GL_LINE_LOOP
// cout << "GL_LINE_LOOP" << endl;
//}
//else {
// LINE_LOOP = num - 1;//GL_LINE_STRIP
// cout << "GL_LINE_STRIP" << endl;
//}
for (int i = 0; i < LINE_LOOP; i++) {
//screen[]空间线段起点和终点x、y的采样
int start_x = (int)screen[i].x;
int start_y = (int)screen[i].y;
int end_x;
int end_y;
if (i == LINE_LOOP - 1) {
end_x = (int)screen[0].x;
end_y = (int)screen[0].y;
}
else {
end_x = (int)screen[i+1].x;
end_y = (int)screen[i+1].y;
}
//点关于x轴的排序
if (start_x > end_x) {
swap(start_x, end_x);
swap(start_y, end_y);
}
//斜率算法画线
float delta_x = end_x - start_x;
float delta_y = end_y - start_y;
if (delta_x == 0) {
if (delta_y < 0) {
swap(start_y, end_y);
}
for (int y = start_y, x = start_x; y < end_y; y++) {
image[y][x][0] = triangle_colors[i].r;
image[y][x][1] = triangle_colors[i].g;
image[y][x][2] = triangle_colors[i].b;
image[y][x][3] = triangle_colors[i].a;
}
}
else {
float gradient = (float)delta_y / delta_x; //斜率定义
for (int x = start_x; x < end_x; x++) {
int y = (int)(gradient * (x - start_x) + start_y);//斜率公式变形
image[y][x][0] = triangle_colors[i].r;
image[y][x][1] = triangle_colors[i].g;
image[y][x][2] = triangle_colors[i].b;
image[y][x][3] = triangle_colors[i].a;
}
}
}
}
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(width, height);
glutInitWindowPosition(200, 100);
int id = glutCreateWindow("线框矩形");
GLenum err = glewInit();
if (err != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(err));
return 1;
}
initRectangle();
glutDisplayFunc(render);
glutMainLoop();
return 0;
}
部分二
代码分析
1、将顶点计数器point_num设为4,在initRectangle()中定义四个顶点points[point_num]。将三角形计数器triangle_num设为2,通过对indices[triangle_num]初始化构造出两个三角形的顶点索引。通过for (int i = 0; i < point_num; i++){.......}对NDC顶点坐变换成屏幕空间的像素坐标。通过for (int j = 0; j < triangle_num; j++){......}实现对不同三角形顶点的索引数据的获取,indices[j].v0、indices[j].v1、indices[j].v2实现第j个三角形的三个顶点v0、v1、v2索引的采样。将当前三角形的顶点索引indices[j].v0、indices[j].v1、indices[j].v2放入points[?]中的“?”后,有points[indices[j].v0]、points[indices[j].v1]、points[indices[j].v2] ,根据三角形顶点的索引数据完成对顶点坐标数据的采样。triangle[3] = {points[indices[j].v1, points[indices[j].v1], points[indices[j].v2] }实现对三角形三个顶点位置数据的装配,生成一个三角形图元;color[3] = { colors[indices[j].v0], colors[indices[j].v1], colors[indices[j].v2] }实现相应顶点的颜色采样。通过for (int i = 0; i < 3; i++) {......}实现GL_LINE_LOOP模式的“连点成线”。
2、在计算机图形学中,三角形是最简单的多边形,任何复杂的多边形都可以拆成n个三角形的形式。将一个矩阵拆成两个三角形,分别进行绘制,得到由两个线框三角形合成的线框矩形。