C++ 实现 Gouraud 着色算法
Gouraud 着色算法是一种用于计算 3D 图形的光照和阴影的算法。该算法根据多边形的顶点颜色插值计算每个像素的颜色,从而实现渐变的效果。以下是 C++ 实现 Gouraud 着色算法的代码:
#include <iostream>
#include <graphics.h>
#include <math.h>
using namespace std;
struct Point {
int x, y;
int r, g, b;
};
struct Edge {
Point start, end;
float slope;
float r_slope, g_slope, b_slope;
};
void DrawLine(Point start, Point end, float r_slope, float g_slope, float b_slope) {
float x = start.x, y = start.y;
float r = start.r, g = start.g, b = start.b;
float dx = end.x - start.x;
float dy = end.y - start.y;
float steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy);
r_slope /= steps;
g_slope /= steps;
b_slope /= steps;
dx /= steps;
dy /= steps;
for (int i = 0; i < steps; i++) {
putpixel(x, y, RGB(r, g, b));
x += dx;
y += dy;
r += r_slope;
g += g_slope;
b += b_slope;
}
}
void GouraudTriangle(Point p1, Point p2, Point p3) {
Edge edges[3] = {
{ p1, p2, (float)(p2.y - p1.y) / (p2.x - p1.x), (float)(p2.r - p1.r) / (p2.x - p1.x), (float)(p2.g - p1.g) / (p2.x - p1.x), (float)(p2.b - p1.b) / (p2.x - p1.x) },
{ p2, p3, (float)(p3.y - p2.y) / (p3.x - p2.x), (float)(p3.r - p2.r) / (p3.x - p2.x), (float)(p3.g - p2.g) / (p3.x - p2.x), (float)(p3.b - p2.b) / (p3.x - p2.x) },
{ p3, p1, (float)(p1.y - p3.y) / (p1.x - p3.x), (float)(p1.r - p3.r) / (p1.x - p3.x), (float)(p1.g - p3.g) / (p1.x - p3.x), (float)(p1.b - p3.b) / (p1.x - p3.x) }
};
int startY = min(min(p1.y, p2.y), p3.y);
int endY = max(max(p1.y, p2.y), p3.y);
for (int y = startY; y <= endY; y++) {
float xl = 0, xr = 0, rl = 0, gl = 0, bl = 0, rr = 0, gr = 0, br = 0;
bool setLeft = false, setRight = false;
for (int i = 0; i < 3; i++) {
if (y >= edges[i].start.y && y <= edges[i].end.y) {
float x = edges[i].start.x + edges[i].slope * (y - edges[i].start.y);
float r = edges[i].start.r + edges[i].r_slope * (y - edges[i].start.y);
float g = edges[i].start.g + edges[i].g_slope * (y - edges[i].start.y);
float b = edges[i].start.b + edges[i].b_slope * (y - edges[i].start.y);
if (!setLeft) {
xl = x;
rl = r;
gl = g;
bl = b;
setLeft = true;
}
else {
if (x < xl) {
xr = xl;
rr = rl;
gr = gl;
br = bl;
xl = x;
rl = r;
gl = g;
bl = b;
}
else {
xr = x;
rr = r;
gr = g;
br = b;
}
setRight = true;
}
}
}
if (setLeft && setRight) {
float r_slope = (rr - rl) / (xr - xl);
float g_slope = (gr - gl) / (xr - xl);
float b_slope = (br - bl) / (xr - xl);
DrawLine({ xl, y, rl, gl, bl }, { xr, y, rr, gr, br }, r_slope, g_slope, b_slope);
}
}
}
int main() {
initwindow(640, 480, 'Gouraud Triangle');
setbkcolor(WHITE);
cleardevice();
Point p1 = { 150, 200, 255, 0, 0 };
Point p2 = { 300, 100, 0, 255, 0 };
Point p3 = { 450, 200, 0, 0, 255 };
GouraudTriangle(p1, p2, p3);
getch();
closegraph();
return 0;
}
在此代码中,我们首先定义了 Point 和 Edge 结构体来表示点和边。然后,我们定义 DrawLine 函数来绘制两个点之间的线段,并在每个像素上插值颜色值。最后,我们定义 GouraudTriangle 函数来绘制三角形,并计算每个像素的颜色值。在 GouraudTriangle 函数中,我们首先找到三角形的最高点和最低点,并在其之间绘制所有像素。然后,我们遍历每个边,并计算每个像素的颜色值。最后,我们使用 DrawLine 函数绘制每个像素之间的线段。
在主函数中,我们定义了 3 个点来绘制一个彩色三角形,并调用 GouraudTriangle 函数来绘制该三角形。运行程序,我们可以看到一个带有渐变色的三角形。

原文地址: https://www.cveoy.top/t/topic/lRuP 著作权归作者所有。请勿转载和采集!