0
点赞
收藏
分享

微信扫一扫

OpenGL之彩色线段(CR)

代码小姐 2022-05-01 阅读 40
c++算法

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	2  //计数器

struct Vector3f {
	GLfloat x;
	GLfloat y;
	GLfloat z;
};

struct Color {
	GLubyte r;
	GLubyte g;
	GLubyte b;
	GLubyte a;
};

Color interp_color(Color c0, Color c1, float i) 
{
	Color c;
	c.r = (1 - i) * c0.r + i * c1.r;
	c.g = (1 - i) * c0.g + i * c1.g;
	c.b = (1 - i) * c0.b + i * c1.b;
	c.a = (1 - i) * c0.a + i * c1.a;
	return c;
}

GLubyte image[height][width][4];
void initLines()
{
	//定义NDC下的顶点数据
	Vector3f points[num]{
		{0.0f,0.5f,0.0f},
		{0.5f,0.0f,0.0f},
	};
	//定义颜色数据
	Color color[num]{
		{255,0,0,0},
		{0,255,0,0}
	};

	//将NDC坐标转换成屏幕坐标
	for (int i = 0; i < num; i++)
	{
		points[i].x = (points[i].x + 1.0f) * (width / 2 - 1);
		points[i].y = (points[i].y + 1.0f) * (height / 2 - 1);
		points[i].z = 0;	//zbuffer统一设置为0
	}

	for (int i = 0; i < num; i += 2) { //num=2 启用GL_LINES
		//定义线的起点
		int start = i;
		int start_x = (int)points[start].x;
		int start_y = (int)points[start].y;
		Color c0 = color[start];
		//定义线的终点 两两相邻取点
		int end;
		int end_x;
		int end_y;
		Color c1;
		if (i == num - 1) {	
			end_x = (int)points[0].x;
			end_y = (int)points[0].y;
			c1 = color[0];
		}
		else {
			end = i + 1;
			end_x = (int)points[end].x;
			end_y = (int)points[end].y;
			c1 = color[end];
		}

		//对点进行x轴排序
		if (start_x > end_x) {
			swap(start_x, end_x);
			swap(start_y, end_y);
			swap(c0, c1);
		}

		//斜率法画线
		float delta_x = end_x - start_x;
		float delta_y = end_y - start_y;
		float lineWidth = 1.0f;//线宽设置为1
		//颜色插值画线	
		if (delta_x == 0) {
			if (delta_y < 0) {
				swap(start_y, end_y);
				swap(c0, c1);
			}
			for (int y = start_y, x = start_x; y <= end_y; y++) {
				//插值系数i根据y轴计算
				float i = (float)(y - start_y) / (end_y - start_y);
				Color icolor = interp_color(c0,c1,i);
				image[y][x][0] = icolor.r;
				image[y][x][1] = icolor.g;
				image[y][x][2] = icolor.b;
				image[y][x][3] = icolor.a;

			}
		}
		else {
			float gradient = (float)delta_y / delta_x;
			for (int x = start_x; x <= end_x; x++) {
				//插值系数i根据x轴计算
				float i = (float)(x-start_x) /(end_x - start_x);
				Color icolor = interp_color(c0, c1, i);
				//直线斜率公式
				int y = (int)(gradient * (x - start_x) + start_y);		
				image[y][x][0] = icolor.r;
				image[y][x][1] = icolor.g;
				image[y][x][2] = icolor.b;
				image[y][x][3] = icolor.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;
	}

	initLines();
	glutDisplayFunc(render);
	glutMainLoop();

	return 0;
}

部分二

代码分析

1、在initLines()函数中,利用顶点索引坐标start和end在color[num]中进行顶点颜色的采样,得到点对{start:end}对应的颜色属性{c0:c1}。在根据x轴对顶点进行排序时,颜色属性同步处理。在“delta_x == 0”时,如果“delta_y < 0”,颜色属性亦同步处理,否则根据y轴坐标获取插值系数“i”。又因为已经采样出点对{start:end}对应的颜色属性{c0:c1},故可以利用颜色属性{c0:c1}、插值系数“i”,在函数interp_color( , , )中完成颜色的插值interp_color(c0, c1, i),得到不同像素点对应的颜色属性icolor,将线段覆盖的像素对应的颜色属性icolor写入image[height][width][4]。

2、在render()中,利用glDrawPixels(, , , , image)完成对image[height][width][4]中像素信息的绘制,之后SwapBuffer显示到屏幕。

举报

相关推荐

0 条评论