Advertisement
topkedi

lab3.cpp

Feb 27th, 2025 (edited)
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.61 KB | None | 0 0
  1. #define _USE_MATH_DEFINES
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include <optional>
  6. #define NOMINMAX
  7. #include <d3d12.h>
  8. #include "SimpleMath.h"
  9. #include "tgaimage.h"
  10. #include "model.h"
  11. #include "Camera.h"
  12. #include "string"
  13. using namespace DirectX::SimpleMath;
  14.  
  15. std::ostream& operator<< (std::ostream& a, Vector3& v) {
  16.     return a << v.x << " " << v.y << " " << v.z << "  ";
  17. }
  18.  
  19. std::ostream& operator<< (std::ostream& a, Vector4& v) {
  20.     return a << v.x << " " << v.y << " " << v.z << " " << v.w << "  ";
  21. }
  22.  
  23. const TGAColor white = TGAColor(255, 255, 255, 255);
  24. const TGAColor red = TGAColor(255, 0, 0, 255);
  25.  
  26. Vector3 barycentric(Vector2 A, Vector2 B, Vector2 C, Vector2 P) {
  27.     Vector3 s[2];
  28.     s[0].x = C.x - A.x;
  29.     s[0].y = B.x - A.x;
  30.     s[0].z = A.x - P.x;
  31.     s[1].x = C.y - A.y;
  32.     s[1].y = B.y - A.y;
  33.     s[1].z = A.y - P.y;
  34.     Vector3 u = s[0].Cross(s[1]);
  35.     if (std::abs(u.z) > 1e-2) return Vector3(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
  36.     return Vector3(-1, 1, 1);
  37. }
  38.  
  39. Model* model = NULL;
  40. Vector3 light_dir(1, 0, 1);
  41. Camera camera;
  42.  
  43. struct IShader {
  44.     virtual ~IShader() {};
  45.     virtual Vector3 vertex(int iface, int nthvert, Matrix world) = 0;
  46.     virtual bool fragment(Vector3 bar, TGAColor& color) = 0;
  47. };
  48.  
  49. struct Shader : public IShader {
  50.     Vector3 varying_intensity;
  51.     mat<2, 3, float> varying_uv;
  52.  
  53.     virtual Vector3 vertex(int iface, int nthvert, Matrix world) {
  54.         varying_uv.set_col(nthvert, model->uv(iface, nthvert));
  55.         float light_coeff = model->normal(iface, nthvert).Dot(light_dir);
  56.         float val = std::max(0.f, light_coeff);
  57.         if (nthvert == 0) varying_intensity.x = val;
  58.         else if (nthvert == 1) varying_intensity.y = val;
  59.         else if (nthvert == 2) varying_intensity.z = val;
  60.         Vector3 vert = model->vert(iface, nthvert);
  61.         Vector4 gl_Vertex(vert);
  62.         gl_Vertex.w = 1;
  63.         gl_Vertex = Vector4::Transform(gl_Vertex, world);
  64.         Vector4 camera_coordinates = camera.ProjectToCamera(gl_Vertex);
  65.         return Vector3(camera_coordinates.x / camera_coordinates.w,
  66.             camera_coordinates.y / camera_coordinates.w,
  67.             camera_coordinates.z / camera_coordinates.w);
  68.     }
  69.  
  70.     virtual bool fragment(Vector3 bar, TGAColor& color) {
  71.         auto uv = varying_uv * vec<3, float>(bar.x, bar.y, bar.z);
  72.         float intensity = varying_intensity.Dot(bar);
  73.         intensity = std::max(0.f, std::min(intensity, 1.f));
  74.         color = model->diffuse(uv) * intensity;
  75.         return false;
  76.     }
  77. };
  78.  
  79. void line(int x0, int y0, int x1, int y1, TGAImage& image, TGAColor color) {
  80.     bool steep = false;
  81.     if (std::abs(x0 - x1) < std::abs(y0 - y1)) {
  82.         std::swap(x0, y0);
  83.         std::swap(x1, y1);
  84.         steep = true;
  85.     }
  86.     if (x0 > x1) {
  87.         std::swap(x0, x1);
  88.         std::swap(y0, y1);
  89.     }
  90.     int dx = x1 - x0;
  91.     int dy = y1 - y0;
  92.     float derror = std::abs(dy / float(dx));
  93.     float error = 0;
  94.     int y = y0;
  95.     for (int x = x0; x <= x1; x++) {
  96.         if (steep) image.set(y, x, color);
  97.         else image.set(x, y, color);
  98.         error += derror;
  99.         if (error > .5) {
  100.             y += (y1 > y0 ? 1 : -1);
  101.             error -= 1.;
  102.         }
  103.     }
  104. }
  105.  
  106.  
  107.  
  108. void triangle(Vector3* pts, IShader& shader, TGAImage& image, TGAImage& zbuffer) {
  109.     Vector2 bboxmin(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
  110.     Vector2 bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
  111.     for (int i = 0; i < 3; i++) {
  112.         bboxmin.x = std::min(bboxmin.x, pts[i].x);
  113.         bboxmax.x = std::max(bboxmax.x, pts[i].x);
  114.         bboxmin.y = std::min(bboxmin.y, pts[i].y);
  115.         bboxmax.y = std::max(bboxmax.y, pts[i].y);
  116.     }
  117.     Vec2i P;
  118.     TGAColor color;
  119.     for (P.x = bboxmin.x; P.x <= bboxmax.x; P.x++) {
  120.         for (P.y = bboxmin.y; P.y <= bboxmax.y; P.y++) {
  121.             Vector3 c = barycentric(Vector2(pts[0].x, pts[0].y),
  122.                 Vector2(pts[1].x, pts[1].y),
  123.                 Vector2(pts[2].x, pts[2].y),
  124.                 Vector2(static_cast<float>(P.x), static_cast<float>(P.y)));
  125.             float z = pts[0].z * c.x + pts[1].z * c.y + pts[2].z * c.z;
  126.             int frag_depth = std::max(0, std::min(255, int(z + .5)));
  127.             if (c.x < 0 || c.y < 0 || c.z < 0) continue;
  128.             if (zbuffer.get(P.x, P.y)[0] >= frag_depth) continue;
  129.             bool discard = shader.fragment(c, color);
  130.             if (!discard) {
  131.                 zbuffer.set(P.x, P.y, TGAColor(frag_depth));
  132.                 image.set(P.x, P.y, color);
  133.             }
  134.         }
  135.     }
  136. }
  137.  
  138. void drawImage() {
  139.     int width = 1000;
  140.     int height = 1000;
  141.  
  142.     for (int a = 0;a <= 10;a++)
  143.     {
  144.         TGAImage image(width, height, TGAImage::RGB);
  145.         TGAImage* zbuffer = new TGAImage(width, height, TGAImage::Format::GRAYSCALE);
  146.         light_dir.Normalize();
  147.  
  148.         Vector3 eye(0, 0, 3);
  149.         Vector3 center(0, 0, 0);
  150.         Vector3 up(0, 1, 0);
  151.         camera = Camera(eye, center, up, 1, 0.5, width, height);
  152.         Shader shader;
  153.         Matrix world = Matrix::Identity;
  154.         model = new Model(R"(african_head.obj)");
  155.         for (int i = 0; i < model->nfaces(); i++) {
  156.             if (i % 100 == 0) {
  157.                 std::cout << i << '\r' << std::flush;
  158.             }
  159.             std::vector<int> face = model->face(i);
  160.             Vector3 screen_coords[3];
  161.             Vector3 model_coords[3];
  162.             for (int j = 0; j < 3; j++) {
  163.                 Vector3 v = model->vert(face[j]);
  164.                 model_coords[j] = v;
  165.                 screen_coords[j] = shader.vertex(i, j, world);
  166.             }
  167.             triangle(screen_coords, shader, image, *zbuffer);
  168.         }
  169.  
  170.         model = new Model(R"(african_head_eye_inner.obj)");
  171.         for (int i = 0; i < model->nfaces(); i++) {
  172.             if (i % 100 == 0) {
  173.                 std::cout << i << '\r' << std::flush;
  174.             }
  175.             std::vector<int> face = model->face(i);
  176.             Vector3 screen_coords[3];
  177.             Vector3 model_coords[3];
  178.             for (int j = 0; j < 3; j++) {
  179.                 Vector3 v = model->vert(face[j]);
  180.                 model_coords[j] = v;
  181.                 screen_coords[j] = shader.vertex(i, j, Matrix::CreateRotationZ(a * 6.28 / 10));
  182.             }
  183.             triangle(screen_coords, shader, image, *zbuffer);
  184.  
  185.         }
  186.  
  187.         std::string name = "output" + std::to_string(a) + ".tga";
  188.         image.flip_vertically();
  189.         image.write_tga_file(name.c_str());
  190.         system(name.c_str());
  191.     }
  192. }
  193.  
  194. int main() {
  195.     drawImage();
  196.     return 0;
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement