这篇着重光栅化2D直线的算法实现

一、数据结构设置

//************************基本数据结构*******************
typedef struct { float x, y; } vector_t;
typedef vector_t point_t;//顶点

typedef struct { float r, g, b,a; } color_t;//颜色

目前还是2d,也不需要3d变换,暂时只需要x,y2个坐标数据

二、DDA画线算法

void DrawLineDDA2d(point_t v1, point_t v2,color_t c)//DDA画线算法
{

glColor4d(c.r, c.g, c.b,c.a);
float x1 = v1.x;
float y1 = v1.y;
float x2 =v2.x;
float y2 = v2.y;
float length = __max(abs(x1 - x2), abs(y1 - y2));
float dx = (x2 - x1) / length;
float dy = (y2 - y1) / length;
float x = x1 + 0.5;
float y = y1 + 0.5;
int i = 0;
while (i <= length)
{
glVertex2i((int)x, (int)y);
x += dx;
y += dy;
i++;
}

}

此算法参考《计算机图形学的算法基础》

光栅渲染器(二)画线_#include

利用光栅渲染器(二)画线_2d_02公式完成绘制

三、中点画线算法

void DrawLineMid(point_t v1, point_t v2,color_t c)//中点画线算法
{

glColor4d(c.r, c.g, c.b, c.a);
float x1 = v1.x;
float y1 = v1.y;
float x2 = v2.x;
float y2 = v2.y;
float dx = x2 - x1;
float dy = y2 - y1;
float d = dy - dx;
int x = x1+0.5;
int y = y1+0.5;
glVertex2i((int)x1, (int)y1);
while (x < x2)
{
if (d >= 0)
{
glVertex2i(x++, y);
d -= dy;
}
else if (d < 0)
{
glVertex2i(x++, y++);
d += dy - dx;
}
}
}

这个算法仅限第一象限

四、Bresenham算法

void DrawLineBre(point_t v1, point_t v2, color_t c)//Bresenham算法
{
glColor4d(c.r, c.g, c.b, c.a);
float x1 = v1.x;
float y1 = v1.y;
float x2 = v2.x;
float y2 = v2.y;
int x = x1;
int y = y1;
float dx =abs(x1-x2);
float dy = abs(y2 - y1);
int s1 = Sgn(x2 - x1);
int s2 = Sgn(y2 - y1);
bool IntChange = false;
if (dy > dx)
{
swap(dy, dx);
IntChange = true;
}
float e = 2 * dy - dx;
for (int i = 0; i < dx; i++)
{
glVertex2i(x, y);
if(e>0)
{
if (IntChange)x += s1;
else x += s2;
e =e- 2*dx;
}
if (IntChange) y += s2;
else y += s1;
e += 2 * dy;
}
}

五、测试画线案例

完整代码如下:

#include "pch.h"

#include <iostream>
#include <string>
using namespace std;

const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const char* SCREEN_TITLE = "光栅渲染器";


//************************基本数据结构*******************
typedef struct { float x, y; } vector_t;
typedef vector_t point_t;//顶点

typedef struct { float r, g, b, a; } color_t;//颜色

int Sgn(float d)//符号判断
{
if (d < 0) return -1;
else if (d == 0) return 0;
else return 1;
}

void DrawLineDDA2d(point_t v1, point_t v2, color_t c)//DDA画线算法
{

glColor4d(c.r, c.g, c.b, c.a);
float x1 = v1.x;
float y1 = v1.y;
float x2 = v2.x;
float y2 = v2.y;
float length = __max(abs(x1 - x2), abs(y1 - y2));
float dx = (x2 - x1) / length;
float dy = (y2 - y1) / length;
float x = x1 + 0.5;
float y = y1 + 0.5;
int i = 0;
while (i <= length)
{
glVertex2i((int)x, (int)y);
x += dx;
y += dy;
i++;
}

}

void DrawLineMid(point_t v1, point_t v2, color_t c)//中点画线算法
{

glColor4d(c.r, c.g, c.b, c.a);
float x1 = v1.x;
float y1 = v1.y;
float x2 = v2.x;
float y2 = v2.y;
float dx = x2 - x1;
float dy = y2 - y1;
float d = dy - dx;
int x = x1 + 0.5;
int y = y1 + 0.5;
glVertex2i((int)x1, (int)y1);
while (x < x2)
{
if (d >= 0)
{
glVertex2i(x++, y);
d -= dy;
}
else if (d < 0)
{
glVertex2i(x++, y++);
d += dy - dx;
}
}
}

void DrawLineBre(point_t v1, point_t v2, color_t c)//Bresenham算法
{
glColor4d(c.r, c.g, c.b, c.a);
float x1 = v1.x;
float y1 = v1.y;
float x2 = v2.x;
float y2 = v2.y;
int x = x1;
int y = y1;
float dx = abs(x1 - x2);
float dy = abs(y2 - y1);
int s1 = Sgn(x2 - x1);
int s2 = Sgn(y2 - y1);
bool IntChange = false;
if (dy > dx)
{
swap(dy, dx);
IntChange = true;
}
float e = 2 * dy - dx;
for (int i = 0; i < dx; i++)
{
glVertex2i(x, y);
if (e > 0)
{
if (IntChange)x += s1;
else x += s2;
e = e - 2 * dx;
}
if (IntChange) y += s2;
else y += s1;
e += 2 * dy;
}
}


//<<<<<<<<<<<<<<<<<<<<<<< myInit >>>>>>>>>>>>>>>>>>>>
void myInit(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0); // 设置背景颜色为亮白
glColor3f(1.0f, 1.0f, 1.0f); // 设置绘制颜色为黑
glPointSize(4.0); //设置点的大小为4*4像素
glMatrixMode(GL_PROJECTION);// 设置合适的投影矩阵-以后解释
glLoadIdentity();
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
}

//<<<<<<<<<<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>>
// 重绘函数
void myDisplay(void)
{


glClear(GL_COLOR_BUFFER_BIT); // 清屏幕
glPointSize(1);
glBegin(GL_POINTS);
point_t v1{ 10,15 };
point_t v2{ 400,200 };
point_t v3{ 10,15 };
point_t v4{ 400,300 };
color_t c{ 1.0,1.0,0,1.0 };//黄色
color_t c2{ 1.0,0.0,0,1.0 };//黄色
DrawLineDDA2d(v1, v2, c);
DrawLineMid(v3, v4, c2);
DrawLineBre(v2, v4, c2);
glEnd();
glFlush(); // 将所有输出到显示屏上

}

//<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>
int main(int argc, char **argv)
{
glutInit(&argc, argv); // 初始化工具包
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 设置显式模式
glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT); // 设置窗口大小
glutInitWindowPosition(100, 150); // 设置窗口位置
glutCreateWindow(SCREEN_TITLE); // 打开屏幕窗口
glutDisplayFunc(myDisplay); // 注册绘制函数
myInit();
glutMainLoop(); // 进入主循环

return 0;
}

光栅渲染器(二)画线_i++_03