diff options
author | Mateja <mail@matejamaric.com> | 2020-08-18 00:54:56 +0200 |
---|---|---|
committer | Mateja <mail@matejamaric.com> | 2020-08-18 00:54:56 +0200 |
commit | 75e65ec0763bd74b89bfcb4d7c44d68999839329 (patch) | |
tree | bd781ec299f29ce64864d9a974546f4827a8ba00 | |
download | barycentric-render-75e65ec0763bd74b89bfcb4d7c44d68999839329.tar.gz barycentric-render-75e65ec0763bd74b89bfcb4d7c44d68999839329.zip |
first commit
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | main.cpp | 178 | ||||
-rw-r--r-- | makefile | 10 |
3 files changed, 190 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..99b716d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.ppm +srender diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ba88ceb --- /dev/null +++ b/main.cpp @@ -0,0 +1,178 @@ +#include<fstream> +#include<cmath> + +class Vertice +{ +public: + float x, y, z; + float u, v; + Vertice(float x, float y, float z, float u, float v) + { + this->x = x; + this->y = y; + this->z = z; + + this->u = u; + this->v = v; + } + void project() + { + x /= z; + y /= z; + u /= z; + v /= z; + z = 1.0f / z; + } + void fitToImage(int imageWidth, int imageHeight) + { + x = (x * (imageWidth / 2)) + (imageWidth / 2); + y = (-y * (imageHeight / 2)) + (imageHeight / 2); + } +}; + +class Image +{ +public: + int imageWidth, imageHeight; + unsigned char* pixels; + float* zbuffer; + Image(int imageWidth, int imageHeight) + { + this->imageWidth = imageWidth; + this->imageHeight = imageHeight; + pixels = new unsigned char[imageWidth * imageHeight * 3]; + zbuffer = new float[imageWidth * imageHeight]; + for (int i = 0; i < imageWidth * imageHeight; i++) + zbuffer[i] = 1000.0f; + } + ~Image() + { + delete[] pixels; + delete[] zbuffer; + } + void setPixel(int x, int y, int red, int green, int blue) + { + int help_var = ((y * imageWidth) + x) * 3; + pixels[help_var + 0] = (unsigned char)red; + pixels[help_var + 1] = (unsigned char)green; + pixels[help_var + 2] = (unsigned char)blue; + } + void fillPixels(int red, int green, int blue) + { + int help_var = imageWidth * imageHeight * 3; + for (int i = 0; i < help_var; i += 3) { + pixels[i + 0] = (unsigned char)red; + pixels[i + 1] = (unsigned char)green; + pixels[i + 2] = (unsigned char)blue; + } + } + void setZBufferAt(int x, int y, float value) + { + int hlp_var = ((y * imageWidth) + x); + zbuffer[hlp_var] = value; + } + float getZBufferAt(int x, int y) + { + int hlp_var = ((y * imageWidth) + x); + return zbuffer[hlp_var]; + } + + float edgeFunction(const Vertice& A, const Vertice& B, const Vertice& P) + { + return ((P.x - A.x)*(B.y - A.y) - (P.y - A.y)*(B.x - A.x)); + } + + void fillTriangleBarycentric(const Vertice& v0, const Vertice& v1, const Vertice& v2) + { + Vertice p(0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + float area = edgeFunction(v0, v1, v2); + float edge0[2] = {v2.x - v1.x, v2.y - v1.y}; + float edge1[2] = {v0.x - v2.x, v0.y - v2.y}; + float edge2[2] = {v1.x - v0.x, v1.y - v0.y}; + for (int x = 0; x < imageWidth; x++) { + for (int y = 0; y < imageHeight; y++) { + p.x = x + 0.5f; p.y = y + 0.5f; + float w0 = edgeFunction(v1, v2, p); + float w1 = edgeFunction(v2, v0, p); + float w2 = edgeFunction(v0, v1, p); + bool inside = true; + inside &= ((w0 == 0) ? ((edge0[1] == 0 && edge0[0] > 0) || edge0[1] > 0) : (w0 > 0)); + inside &= ((w1 == 0) ? ((edge1[1] == 0 && edge1[0] > 0) || edge1[1] > 0) : (w1 > 0)); + inside &= ((w2 == 0) ? ((edge2[1] == 0 && edge2[0] > 0) || edge2[1] > 0) : (w2 > 0)); + if (inside) { + w0 /= area; + w1 /= area; + w2 /= area; + float z = 1.0f / (w0 * v0.z + w1 * v1.z + w2 * v2.z); + + if (z < getZBufferAt(x, y)) { + setZBufferAt(x, y, z); + + float u = (w0 * v0.u + w1 * v1.u + w2 * v2.u) * z; + float v = (w0 * v0.v + w1 * v1.v + w2 * v2.v) * z; + + const float M = 8; + float p = (fmod(u * M, 1.0f) > 0.5f) ^ (fmod(v * M, 1.0f) < 0.5f); + + int red = (int)(255.0f * p); + int green = (int)(255.0f * p); + int blue = (int)(255.0f * p); + setPixel(x, y, red, green, blue); + } + } + } + } + } +}; + +int main() +{ + Image image(800, 600); + //image.fillPixels(255, 255, 255); + float sr = 90.0f, sg = 90.0f, sb = 130.0f; + float er = 0.0f, eg = 0.0f, eb = 80.0f; + float dr = ((er - sr) / 600.0f); + float dg = ((eg - sg) / 600.0f); + float db = ((eb - sb) / 600.0f); + for (int y = 0; y < 600; y++) { + sr += dr; sg += dg; sb += db; + for (int x = 0; x < 800; x++) + image.setPixel(x, y, (int)sr, (int)sg, (int)sb); + } + + + Vertice a(0.2f, 3.5f, 4.0f, 0.0f, 1.0f); + Vertice b(-0.8f, 0.0f, 1.0f, 0.0f, 0.0f); + Vertice c(1.6f, -1.6f, 2.0f, 1.0f, 0.0f); + + Vertice d(2.0f, 2.0f, 3.0f, 0.0f, 1.0f); + Vertice e(-2.0f, -2.0f, 3.0f, 1.0f, 0.0f); + Vertice f(2.0f, -2.0f, 3.0f, 0.0f, 0.0f); + + a.project(); + b.project(); + c.project(); + + d.project(); + e.project(); + f.project(); + + a.fitToImage(image.imageWidth, image.imageHeight); + b.fitToImage(image.imageWidth, image.imageHeight); + c.fitToImage(image.imageWidth, image.imageHeight); + + d.fitToImage(image.imageWidth, image.imageHeight); + e.fitToImage(image.imageWidth, image.imageHeight); + f.fitToImage(image.imageWidth, image.imageHeight); + + image.fillTriangleBarycentric(a, b, c); + image.fillTriangleBarycentric(d, e, f); + + std::ofstream imageFile; + imageFile.open("./image.ppm"); + imageFile << "P6\n" << image.imageWidth << " " << image.imageHeight << "\n255\n"; + imageFile.write((char*)image.pixels, image.imageWidth * image.imageHeight * 3); + imageFile.close(); + + return 0; +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..02d5d7c --- /dev/null +++ b/makefile @@ -0,0 +1,10 @@ +srender: main.cpp + g++ -o srender main.cpp +image.ppm: srender + ./srender +run: srender + ./srender +view: image.ppm + feh -. image.ppm +clean: + rm image.ppm |