差分
このページの2つのバージョン間の差分を表示します。
| 次のリビジョン | 前のリビジョン | ||
| cgfs:shaded_triangles [2024/06/11 11:13] – 作成 freemikan | cgfs:shaded_triangles [2025/12/12 15:57] (現在) – Replace overused back_inserters freemikan | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | < | + | ====== DrawPixelだけで三角形を描く (3) 明暗をつける ====== |
| + | |||
| + | {{: | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | <file cpp> | ||
| #include < | #include < | ||
| + | #include < | ||
| #include < | #include < | ||
| #include < | #include < | ||
| 行 26: | 行 33: | ||
| } | } | ||
| - | | + | |
| - | | + | |
| for (int i = i0; i <= i1; ++i) { | for (int i = i0; i <= i1; ++i) { | ||
| - | *out++ = d; | + | *out = d; |
| + | ++out; | ||
| d += a; | d += a; | ||
| } | } | ||
| } | } | ||
| - | void DrawLine(vec2 const &p0, vec2 const &p1, Color const &color) { | + | struct VertexPositionIntensity |
| - | auto x0 = p0.x; | + | |
| - | auto y0 = p0.y; | + | |
| - | auto x1 = p1.x; | + | |
| - | auto y1 = p1.y; | + | |
| - | + | ||
| - | if (std::abs(x1 - x0) > std::abs(y1 - y0)) { | + | |
| - | if (x0 > x1) { | + | |
| - | std:: | + | |
| - | std:: | + | |
| - | } | + | |
| - | auto i0 = static_cast< | + | |
| - | auto i1 = static_cast< | + | |
| - | auto ys = std:: | + | |
| - | Interpolate(i0, | + | |
| - | for (int i = i0; i <= i1; ++i) { | + | |
| - | PutPixel(i, ys[i - i0], color); | + | |
| - | } | + | |
| - | } else { | + | |
| - | if (y0 > y1) { | + | |
| - | std:: | + | |
| - | std:: | + | |
| - | } | + | |
| - | auto i0 = static_cast< | + | |
| - | auto i1 = static_cast< | + | |
| - | auto xs = std:: | + | |
| - | Interpolate(i0, | + | |
| - | for (int i = i0; i <= i1; ++i) { | + | |
| - | PutPixel(xs[i - i0], i, color); | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | void DrawWireframeTriangle(vec2 const &p0, | + | |
| - | vec2 const &p1, | + | |
| - | vec2 const &p2, | + | |
| - | Color const &color) { | + | |
| - | DrawLine(p0, | + | |
| - | DrawLine(p1, | + | |
| - | DrawLine(p2, | + | |
| - | } | + | |
| - | + | ||
| - | void DrawFilledTriangle(vec2 const &p0, | + | |
| - | vec2 const &p1, | + | |
| - | vec2 const &p2, | + | |
| - | Color const &color) { | + | |
| - | vec2 P0{p0}, P1{p1}, P2{p2}; | + | |
| - | if (P1.y < P0.y) { | + | |
| - | std:: | + | |
| - | } | + | |
| - | if (P2.y < P0.y) { | + | |
| - | std:: | + | |
| - | } | + | |
| - | if (P2.y < P1.y) { | + | |
| - | std:: | + | |
| - | } | + | |
| - | + | ||
| - | auto i0 = static_cast< | + | |
| - | auto i1 = static_cast< | + | |
| - | auto i2 = static_cast< | + | |
| - | auto x01 = std:: | + | |
| - | auto x12 = std:: | + | |
| - | auto x02 = std:: | + | |
| - | + | ||
| - | Interpolate(i0, | + | |
| - | Interpolate(i1, | + | |
| - | Interpolate(i0, | + | |
| - | + | ||
| - | x01.pop_back(); | + | |
| - | + | ||
| - | auto x012 = std:: | + | |
| - | assert(x012.size() == x02.size()); | + | |
| - | + | ||
| - | auto corner = std:: | + | |
| - | std:: | + | |
| - | + | ||
| - | auto x_left = x012; | + | |
| - | auto x_right = x02; | + | |
| - | auto m = x012.size() / 2; | + | |
| - | if (x02[m] < x012[m]) { | + | |
| - | x_left = x02; | + | |
| - | x_right = x012; | + | |
| - | } | + | |
| - | + | ||
| - | for (int y = i0; y < i2; ++y) { | + | |
| - | auto x_begin = static_cast< | + | |
| - | auto x_end = static_cast< | + | |
| - | for (int x = x_begin; x < x_end; ++x) { | + | |
| - | PutPixel(x, y, color); | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | struct IntensiveVertex | + | |
| - | float x, y; | + | |
| float h; | float h; | ||
| - | | + | |
| - | | + | |
| - | : x{p.x}, y{p.y}, h{intensity} {} | + | : vec2{x, y}, h{intensity} {} |
| }; | }; | ||
| Color color_scaled(Color const &color, float scale) { | Color color_scaled(Color const &color, float scale) { | ||
| auto r = static_cast< | auto r = static_cast< | ||
| - | std::min(static_cast< | + | std::clamp(static_cast< |
| auto g = static_cast< | auto g = static_cast< | ||
| - | std::min(static_cast< | + | std::clamp(static_cast< |
| auto b = static_cast< | auto b = static_cast< | ||
| - | std::min(static_cast< | + | std::clamp(static_cast< |
| return {r, g, b, color.a}; | return {r, g, b, color.a}; | ||
| } | } | ||
| - | void DrawShadedTriangle(IntensiveVertex | + | void DrawShadedTriangle(VertexPositionIntensity |
| - | | + | |
| - | | + | |
| Color const &color) { | Color const &color) { | ||
| - | IntensiveVertex | + | using std:: |
| - | if (p1.y < p0.y) { | + | |
| - | | + | VertexPositionIntensity |
| + | if (P1.y < P0.y) { | ||
| + | swap(P1, P0); | ||
| } | } | ||
| - | if (p2.y < p0.y) { | + | if (P2.y < P0.y) { |
| - | | + | swap(P2, P0); |
| } | } | ||
| - | if (p2.y < p1.y) { | + | if (P2.y < P1.y) { |
| - | | + | swap(P2, P1); |
| } | } | ||
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | std:: |
| - | | + | std:: |
| Interpolate(yi0, | Interpolate(yi0, | ||
| Interpolate(yi0, | Interpolate(yi0, | ||
| - | | + | std:: |
| - | | + | std:: |
| Interpolate(yi1, | Interpolate(yi1, | ||
| Interpolate(yi1, | Interpolate(yi1, | ||
| - | | + | std:: |
| - | | + | std:: |
| Interpolate(yi0, | Interpolate(yi0, | ||
| Interpolate(yi0, | Interpolate(yi0, | ||
| + | // remove an overlapping point at x01.back and x12.front | ||
| x01.pop_back(); | x01.pop_back(); | ||
| assert(x01.size() + x12.size() == x02.size()); | assert(x01.size() + x12.size() == x02.size()); | ||
| + | // remove an overlapping point at h01.back and h12.front | ||
| h01.pop_back(); | h01.pop_back(); | ||
| assert(h01.size() + h12.size() == h02.size()); | assert(h01.size() + h12.size() == h02.size()); | ||
| - | | + | std:: |
| - | | + | std::merge(x01.begin(), |
| - | std::copy(x12.begin(), x12.end(), corner_x012); | + | |
| - | | + | std:: |
| - | | + | std::merge(h01.begin(), |
| - | | + | |
| + | | ||
| + | assert(h012.size() == h02.size()); | ||
| + | assert(x012.size() == h012.size()); | ||
| auto m = x012.size() / 2; | auto m = x012.size() / 2; | ||
| 行 202: | 行 122: | ||
| if (x02[m] < x012[m]) { | if (x02[m] < x012[m]) { | ||
| - | | + | swap(x_left, |
| - | | + | swap(h_left, |
| } | } | ||
| - | | + | std:: |
| for (int y = yi0; y <= yi2; ++y) { | for (int y = yi0; y <= yi2; ++y) { | ||
| - | | + | |
| - | | + | |
| - | h_segment.resize(x_r - x_l + 1); | + | h_segment.clear(); |
| Interpolate(x_l, | Interpolate(x_l, | ||
| - | | + | |
| for (int x = x_l; x <= x_r; ++x) { | for (int x = x_l; x <= x_r; ++x) { | ||
| - | | + | |
| - | PutPixel(x, y, shaded_color); | + | PutPixel(x, y, color_scaled(color, |
| } | } | ||
| } | } | ||
| 行 224: | 行 144: | ||
| int main() { | int main() { | ||
| - | InitWindow(Cw, | + | InitWindow(Cw, |
| - | | + | |
| - | | + | |
| - | | + | |
| while (!WindowShouldClose()) { | while (!WindowShouldClose()) { | ||
| 行 234: | 行 154: | ||
| ClearBackground(RAYWHITE); | ClearBackground(RAYWHITE); | ||
| - | |||
| - | //~ PutPixel(p0.x, | ||
| - | //~ PutPixel(p1.x, | ||
| - | //~ PutPixel(p2.x, | ||
| DrawShadedTriangle(p0, | DrawShadedTriangle(p0, | ||
| 行 244: | 行 160: | ||
| } | } | ||
| } | } | ||
| - | </codeprism> | + | </file> |
