-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathz_buffering.cpp
More file actions
145 lines (116 loc) · 5.63 KB
/
Copy pathz_buffering.cpp
File metadata and controls
145 lines (116 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//
// Created by kobedb on 20.05.22.
//
#include "z_buffering.h"
#include <iostream>
#include <algorithm>
#include <cassert>
#include <memory>
using namespace std;
namespace KDBRenderUtils
{
Vector3D projectPoint(const Vector3D& A, double d, double dx, double dy)
{
return Vector3D::point((d * A.x / -A.z) + dx, (d * A.y / -A.z)+dy, 0);
}
void calculateXLAndXR(double yI, const Vector3D& P, const Vector3D& Q, double& xL_PQ, double& xR_PQ)
{
if((yI - P.y) * (yI - Q.y) <= 0 && P.y != Q.y) {
double xI = Q.x + (P.x - Q.x) * (yI - Q.y) / (P.y - Q.y);
xL_PQ = xI;
xR_PQ = xI;
}
else {
return;
}
}
void drawZBufTriangle(ZBuffer& zBuffer, img::EasyImage& image,
const Vector3D& A, const Vector3D& B, const Vector3D& C,
double d, double dx, double dy,
NormColor ambientReflection, NormColor diffuseReflection, NormColor specularReflection,
double reflectionCoeff,
const vector<AmbientLight>& ambientLights, const vector<InfLight>& infLights, const vector<unique_ptr<PointLight>>& pointLights)
{
Vector3D projA = projectPoint(A, d, dx, dy);
Vector3D projB = projectPoint(B, d, dx, dy);
Vector3D projC = projectPoint(C, d, dx, dy);
vector<double> ys {projA.y, projB.y, projC.y};
int yMin = (int)std::round(*std::min_element(ys.begin(), ys.end()) + 0.5);
int yMax = (int)std::round(*std::max_element(ys.begin(), ys.end()) - 0.5);
Vector3D G = Vector3D::point((projA.x+projB.x+projC.x)/3.0, (projA.y+projB.y+projC.y)/3.0, 0);
double reciprocal_zG = 1.0/(3*A.z) + 1.0/(3*B.z) + 1.0/(3*C.z);
Vector3D W = crossProduct(B-A , C-A);
double k = dotProduct(W, A);
double dzdx = W.x/(-d*k);
double dzdy = W.y/(-d*k);
NormColor triangleColor{};
Vector3D surfaceNormal = Vector3D::normalise(W);
if(k > 0) {
surfaceNormal = -surfaceNormal;
}
for(const auto& ambientLight : ambientLights) {
triangleColor += applyAmbientLight(ambientReflection, ambientLight.ambientIntensity);
}
for(const auto& infLight : infLights) {
double cos_alpha;
triangleColor += applyDiffuseLight(diffuseReflection, infLight.diffuseIntensity, infLight.lightDirection, surfaceNormal);
triangleColor += applyAmbientLight(ambientReflection, infLight.ambientIntensity);
}
for(int yI = yMin; yI <= yMax; yI++) {
if((yI-yMin)*(yI-yMax) > 0) continue;
double xL_AB = std::numeric_limits<double>::infinity();
double xL_AC = std::numeric_limits<double>::infinity();
double xL_BC = std::numeric_limits<double>::infinity();
double xR_AB = -std::numeric_limits<double>::infinity();
double xR_AC = -std::numeric_limits<double>::infinity();
double xR_BC = -std::numeric_limits<double>::infinity();
calculateXLAndXR(yI, projA, projB, xL_AB, xR_AB);
calculateXLAndXR(yI, projB, projC, xL_BC, xR_BC);
calculateXLAndXR(yI, projA, projC, xL_AC, xR_AC);
vector<double> xLs {xL_AB, xL_AC, xL_BC};
int xL = (int)std::round(*std::min_element(xLs.begin(), xLs.end()) + 0.5);
vector<double> xRs {xR_AB, xR_AC, xR_BC};
int xR = (int)std::round(*std::max_element(xRs.begin(), xRs.end()) - 0.5);
for(unsigned xCur = xL; xCur <= xR; xCur++) {
double reciprocal_zPixel = 1.0001 * reciprocal_zG + ((double)xCur - G.x) * dzdx + ((double)yI-G.y)*dzdy;
NormColor pixelColor{};
for(const auto& pointLight : pointLights) {
double zPixel = 1/reciprocal_zPixel;
double xPixel = (xCur-dx) * -zPixel / d;
double yPixel = (yI-dy) * -zPixel / d;
Vector3D pixelPositionOnTriangle = Vector3D::point(xPixel, yPixel, zPixel);
//Vector3D lightToSurface = Vector3D::normalise(pixelPositionOnTriangle - pointLight->position);
//pixelColor += applyDiffuseLight(diffuseReflection, pointLight.diffuseIntensity, lightToSurface, surfaceNormal );
pixelColor += pointLight->calculateDiffuseLight(diffuseReflection, pixelPositionOnTriangle, surfaceNormal);
pixelColor += applyAmbientLight(ambientReflection, pointLight->ambientIntensity);
}
drawAndUpdateZBuffer(image, zBuffer, xCur, yI, reciprocal_zPixel, toEasyImgColor(triangleColor + pixelColor));
}
}
}
double &ZBuffer::operator()(unsigned int row, unsigned int col)
{
int i = row * width + col;
int bufferSize = buffer.size();
if(i < 0 || i >= buffer.size()) {
std::cerr << "ZBuffer: index out of bounds: row: "<< row << " col: " << col << "\n";
}
return buffer[i];
}
double ZBuffer::operator()(unsigned row, unsigned col) const
{
int i = row * width + col;
int bufferSize = buffer.size();
if(i < 0 || i >= buffer.size()) {
std::cerr << "ZBuffer: index out of bounds: row: "<< row << " col: " << col << "\n";
}
return buffer[i];
}
void drawAndUpdateZBuffer(img::EasyImage& image, ZBuffer& zBuffer, unsigned pix_X, unsigned pix_Y, double reciprocal_z_I, img::Color c)
{
if(reciprocal_z_I < zBuffer(pix_Y, pix_X)) {
image(pix_X, pix_Y) = c;
zBuffer(pix_Y, pix_X) = reciprocal_z_I;
}
}
}