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 函数来绘制该三角形。运行程序,我们可以看到一个带有渐变色的三角形。

gouraud-triangle

C++ 实现 Gouraud 着色算法

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

免费AI点我,无需注册和登录