Skip to content

Commit 190eda4

Browse files
committed
TODO Lab: 1.02 Implement
1 parent decf8e1 commit 190eda4

File tree

5 files changed

+367
-79
lines changed

5 files changed

+367
-79
lines changed

src/renderer/rasterizer/rasterizer.h

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
#include <functional>
66
#include <iostream>
7-
#include <linalg.h>
87
#include <limits>
8+
#include <linalg.h>
99
#include <memory>
1010

1111

@@ -19,8 +19,8 @@ namespace cg::renderer
1919
class rasterizer
2020
{
2121
public:
22-
rasterizer(){};
23-
~rasterizer(){};
22+
rasterizer() {};
23+
~rasterizer() {};
2424
void set_render_target(
2525
std::shared_ptr<resource<RT>> in_render_target,
2626
std::shared_ptr<resource<float>> in_depth_buffer = nullptr);
@@ -46,7 +46,7 @@ namespace cg::renderer
4646
size_t width = 1920;
4747
size_t height = 1080;
4848

49-
int edge_function(int2 a, int2 b, int2 c);
49+
float edge_function(float2 a, float2 b, float2 c);
5050
bool depth_test(float z, size_t x, size_t y);
5151
};
5252

@@ -55,22 +55,31 @@ namespace cg::renderer
5555
std::shared_ptr<resource<RT>> in_render_target,
5656
std::shared_ptr<resource<float>> in_depth_buffer)
5757
{
58-
// TODO Lab: 1.02 Implement `set_render_target`, `set_viewport`, `clear_render_target` methods of `cg::renderer::rasterizer` class
59-
// TODO Lab: 1.06 Adjust `set_render_target`, and `clear_render_target` methods of `cg::renderer::rasterizer` class to consume a depth buffer
58+
if (in_render_target) {
59+
render_target = in_render_target;
60+
}
61+
if (in_depth_buffer) {
62+
depth_buffer = in_depth_buffer;
63+
}
6064
}
6165

6266
template<typename VB, typename RT>
6367
inline void rasterizer<VB, RT>::set_viewport(size_t in_width, size_t in_height)
6468
{
65-
// TODO Lab: 1.02 Implement `set_render_target`, `set_viewport`, `clear_render_target` methods of `cg::renderer::rasterizer` class
69+
width = in_width;
70+
height = in_height;
6671
}
6772

6873
template<typename VB, typename RT>
6974
inline void rasterizer<VB, RT>::clear_render_target(
7075
const RT& in_clear_value, const float in_depth)
7176
{
72-
// TODO Lab: 1.02 Implement `set_render_target`, `set_viewport`, `clear_render_target` methods of `cg::renderer::rasterizer` class
73-
// TODO Lab: 1.06 Adjust `set_render_target`, and `clear_render_target` methods of `cg::renderer::rasterizer` class to consume a depth buffer
77+
for (size_t i = 0; i < depth_buffer->count(); i++) {
78+
render_target->item(i) = in_clear_value;
79+
}
80+
for (size_t i = 0; i < depth_buffer->count(); i++) {
81+
depth_buffer->item(i) = in_depth;
82+
}
7483
}
7584

7685
template<typename VB, typename RT>
@@ -90,17 +99,72 @@ namespace cg::renderer
9099
template<typename VB, typename RT>
91100
inline void rasterizer<VB, RT>::draw(size_t num_vertexes, size_t vertex_offset)
92101
{
93-
// TODO Lab: 1.04 Implement `cg::world::camera` class
94-
// TODO Lab: 1.05 Add `Rasterization` and `Pixel shader` stages to `draw` method of `cg::renderer::rasterizer`
95-
// TODO Lab: 1.06 Add `Depth test` stage to `draw` method of `cg::renderer::rasterizer`
102+
size_t vertex_id = vertex_offset;
103+
while (vertex_id < vertex_offset + num_vertexes) {
104+
std::vector<VB> vertices(3);
105+
vertices[0] = vertex_buffer->item(index_buffer->item(vertex_id++));
106+
vertices[1] = vertex_buffer->item(index_buffer->item(vertex_id++));
107+
vertices[2] = vertex_buffer->item(index_buffer->item(vertex_id++));
108+
109+
for (auto& vertex: vertices) {
110+
float4 coords{vertex.x, vertex.y, vertex.z, 1.f};
111+
auto processed_vertex = vertex_shader(coords, vertex);
112+
113+
vertex.x = processed_vertex.first.x / processed_vertex.first.w;
114+
vertex.y = processed_vertex.first.y / processed_vertex.first.w;
115+
vertex.z = processed_vertex.first.z / processed_vertex.first.w;
116+
117+
vertex.x = (vertex.x + 1.f) * width / 2.f;
118+
vertex.y = (-vertex.y + 1.f) * height / 2.f;
119+
}
120+
float2 vertex_a = float2{vertices[0].x, vertices[0].y};
121+
float2 vertex_b = float2{vertices[1].x, vertices[1].y};
122+
float2 vertex_c = float2{vertices[2].x, vertices[2].y};
123+
124+
float2 min_vertex = min(vertex_a, min(vertex_b, vertex_c));
125+
float2 bounding_box_begin = round(clamp(
126+
min_vertex, float2{0.f, 0.f},
127+
float2{static_cast<float>(width - 1), static_cast<float>(height - 1)}));
128+
129+
float2 max_vertex = max(vertex_a, max(vertex_b, vertex_c));
130+
float2 bounding_box_end = round(clamp(
131+
max_vertex, float2{0.f, 0.f},
132+
float2{static_cast<float>(width - 1), static_cast<float>(height - 1)}));
133+
134+
float edge = edge_function(vertex_a, vertex_b, vertex_c);
135+
136+
for (float x = bounding_box_begin.x; x <= bounding_box_end.x; x += 1.f) {
137+
for (float y = bounding_box_begin.y; y <= bounding_box_end.y; y += 1.f) {
138+
float2 point{x, y};
139+
float edge0 = edge_function(vertex_a, vertex_b, point);
140+
float edge1 = edge_function(vertex_b, vertex_c, point);
141+
float edge2 = edge_function(vertex_c, vertex_a, point);
142+
if (edge0 >= 0.f && edge1 >= 0.f && edge2 >= 0.f) {
143+
size_t u_x = static_cast<float>(x);
144+
size_t u_y = static_cast<float>(y);
145+
146+
float u = edge1 / edge;
147+
float v = edge2 / edge;
148+
float w = edge0 / edge;
149+
150+
float z = u * vertices[0].z + v * vertices[1].z + w * vertices[2].z;
151+
152+
if (depth_test(z, u_x, u_y)) {
153+
auto pixel_result = pixel_shader(vertices[0], 0);
154+
render_target->item(u_x, u_y) = RT::from_color(pixel_result);
155+
depth_buffer->item(u_x, u_y) = z;
156+
}
157+
}
158+
}
159+
}
160+
}
96161
}
97162

98163
template<typename VB, typename RT>
99-
inline int
100-
rasterizer<VB, RT>::edge_function(int2 a, int2 b, int2 c)
164+
inline float
165+
rasterizer<VB, RT>::edge_function(float2 a, float2 b, float2 c)
101166
{
102-
// TODO Lab: 1.05 Implement `cg::renderer::rasterizer::edge_function` method
103-
return 0;
167+
return (c.x - a.x) * (b.y - a.y) - (c.y - a.y) * (b.x - a.x);
104168
}
105169

106170
template<typename VB, typename RT>

src/renderer/rasterizer/rasterizer_renderer.cpp

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,66 @@
55

66
void cg::renderer::rasterization_renderer::init()
77
{
8-
// TODO Lab: 1.02 Implement image clearing & saving in `cg::renderer::rasterization_renderer` class
9-
// TODO Lab: 1.03 Adjust `cg::renderer::rasterization_renderer` class to consume `cg::world::model`
10-
// TODO Lab: 1.04 Setup an instance of camera `cg::world::camera` class in `cg::renderer::rasterization_renderer`
11-
// TODO Lab: 1.06 Add depth buffer in `cg::renderer::rasterization_renderer`
8+
rasterizer = std::make_shared<cg::renderer::rasterizer<cg::vertex, cg::unsigned_color>>();
9+
rasterizer->set_viewport(settings->width, settings->height);
10+
render_target = std::make_shared<cg::resource<cg::unsigned_color>>(
11+
settings->width, settings->height);
12+
rasterizer->set_render_target(render_target);
13+
model = std::make_shared<cg::world::model>();
14+
model->load_obj(settings->model_path);
15+
camera = std::make_shared<cg::world::camera>();
16+
camera->set_height(static_cast<float>(settings->height));
17+
camera->set_width(static_cast<float>(settings->width));
18+
camera->set_position(float3{
19+
settings->camera_position[0],
20+
settings->camera_position[1],
21+
settings->camera_position[2]
22+
});
23+
camera->set_theta(settings->camera_theta);
24+
camera->set_phi(settings->camera_phi);
25+
camera->set_angle_of_view(settings->camera_angle_of_view);
26+
camera->set_z_near(settings->camera_z_near);
27+
camera->set_z_far(settings->camera_z_far);
28+
29+
depth_buffer = std::make_shared<cg::resource<float>>(settings->width, settings->height);
30+
31+
rasterizer->set_render_target(render_target, depth_buffer);
1232
}
1333
void cg::renderer::rasterization_renderer::render()
1434
{
15-
// TODO Lab: 1.02 Implement image clearing & saving in `cg::renderer::rasterization_renderer` class
16-
// TODO Lab: 1.04 Implement `vertex_shader` lambda for the instance of `cg::renderer::rasterizer`
17-
// TODO Lab: 1.05 Implement `pixel_shader` lambda for the instance of `cg::renderer::rasterizer`
18-
// TODO Lab: 1.03 Adjust `cg::renderer::rasterization_renderer` class to consume `cg::world::model`
35+
float4x4 matrix = mul(
36+
camera->get_projection_matrix(),
37+
camera->get_view_matrix(),
38+
model->get_world_matrix()
39+
);
40+
rasterizer->vertex_shader = [&](float4 vertex, cg::vertex data){
41+
auto processed = mul(matrix, vertex);
42+
return std::make_pair(processed, data);
43+
};
44+
rasterizer->pixel_shader = [](cg::vertex data, float z){
45+
return cg::color{
46+
data.ambient_r,
47+
data.ambient_g,
48+
data.ambient_b};
49+
};
50+
51+
auto start = std::chrono::high_resolution_clock::now();
52+
rasterizer->clear_render_target({0,0,0});
53+
auto stop = std::chrono::high_resolution_clock::now();
54+
std::chrono::duration<float, std::milli> clear_duration = stop-start;
55+
std::cout<<"Clearing took "<<clear_duration.count()<<"ms\n";
56+
57+
start = std::chrono::high_resolution_clock::now();
58+
for(size_t shape_id=0; shape_id<model->get_index_buffers().size(); shape_id++){
59+
rasterizer->set_vertex_buffer(model->get_vertex_buffers()[shape_id]);
60+
rasterizer->set_index_buffer(model->get_index_buffers()[shape_id]);
61+
rasterizer->draw(model->get_index_buffers()[shape_id]->count(), 0);
62+
}
63+
stop = std::chrono::high_resolution_clock::now();
64+
std::chrono::duration<float, std::milli> rendering_duration = stop-start;
65+
std::cout<<"Rendering took "<<rendering_duration.count()<<"ms\n";
66+
67+
utils::save_resource(*render_target, settings->result_path);
1968
}
2069

2170
void cg::renderer::rasterization_renderer::destroy() {}

src/resource.h

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,14 @@ namespace cg
3636
template<typename T>
3737
inline resource<T>::resource(size_t size)
3838
{
39-
// TODO Lab: 1.02 Implement `cg::resource` class
39+
data.resize(size);
40+
stride = 0;
4041
}
4142
template<typename T>
4243
inline resource<T>::resource(size_t x_size, size_t y_size)
4344
{
44-
// TODO Lab: 1.02 Implement `cg::resource` class
45+
data.resize(x_size * y_size);
46+
stride = x_size;
4547
}
4648
template<typename T>
4749
inline resource<T>::~resource()
@@ -50,52 +52,44 @@ namespace cg
5052
template<typename T>
5153
inline const T* resource<T>::get_data()
5254
{
53-
// TODO Lab: 1.02 Implement `cg::resource` class
54-
return nullptr;
55+
return data.data();
5556
}
5657
template<typename T>
5758
inline T& resource<T>::item(size_t item)
5859
{
59-
// TODO Lab: 1.02 Implement `cg::resource` class
60-
return T();
60+
return data.at(item);
6161
}
6262
template<typename T>
6363
inline T& resource<T>::item(size_t x, size_t y)
6464
{
65-
// TODO Lab: 1.02 Implement `cg::resource` class
66-
return T();
65+
return data.at(stride*y + x);
6766
}
6867
template<typename T>
6968
inline size_t resource<T>::size_bytes() const
7069
{
71-
// TODO Lab: 1.02 Implement `cg::resource` class
72-
return 0;
70+
return data.size() * item_size;
7371
}
7472
template<typename T>
7573
inline size_t resource<T>::count() const
7674
{
77-
// TODO Lab: 1.02 Implement `cg::resource` class
78-
return 0;
75+
return data.size();
7976
}
8077

8178
template<typename T>
8279
inline size_t resource<T>::get_stride() const
8380
{
84-
// TODO Lab: 1.02 Implement `cg::resource` class
85-
return 0;
81+
return stride;
8682
}
8783

8884
struct color
8985
{
9086
static color from_float3(const float3& in)
9187
{
92-
// TODO Lab: 1.02 Implement `cg::color` and `cg::unsigned_color` structs
93-
return color{};
88+
return color{in.x, in.y, in.z};
9489
};
9590
float3 to_float3() const
9691
{
97-
// TODO Lab: 1.02 Implement `cg::color` and `cg::unsigned_color` structs
98-
return float3{};
92+
return float3{r,g,b};
9993
}
10094
float r;
10195
float g;
@@ -106,18 +100,28 @@ namespace cg
106100
{
107101
static unsigned_color from_color(const color& color)
108102
{
109-
// TODO Lab: 1.02 Implement `cg::color` and `cg::unsigned_color` structs
110-
return unsigned_color{};
103+
return unsigned_color{
104+
static_cast<uint8_t>(std::clamp(color.r*255.f,0.f,255.f)),
105+
static_cast<uint8_t>(std::clamp(color.g*255.f,0.f,255.f)),
106+
static_cast<uint8_t>(std::clamp(color.b*255.f,0.f,255.f)),
107+
};
111108
};
112109
static unsigned_color from_float3(const float3& color)
113110
{
114-
// TODO Lab: 1.02 Implement `cg::color` and `cg::unsigned_color` structs
115-
return unsigned_color{};
111+
float3 clamped = clamp(255.f * color, 0.f, 255.f);
112+
return unsigned_color{
113+
static_cast<uint8_t>(clamped.x),
114+
static_cast<uint8_t>(clamped.y),
115+
static_cast<uint8_t>(clamped.z),
116+
};
116117
};
117118
float3 to_float3() const
118119
{
119-
// TODO Lab: 1.02 Implement `cg::color` and `cg::unsigned_color` structs
120-
return float3{};
120+
return float3{
121+
static_cast<float>(r),
122+
static_cast<float>(g),
123+
static_cast<float>(b),
124+
}/255.f;
121125
};
122126
uint8_t r;
123127
uint8_t g;
@@ -127,7 +131,23 @@ namespace cg
127131

128132
struct vertex
129133
{
130-
// TODO Lab: 1.03 Implement `cg::vertex` struct
134+
float x;
135+
float y;
136+
float z;
137+
float nx;
138+
float ny;
139+
float nz;
140+
float u;
141+
float v;
142+
float ambient_r;
143+
float ambient_g;
144+
float ambient_b;
145+
float diffuse_r;
146+
float diffuse_g;
147+
float diffuse_b;
148+
float emissive_r;
149+
float emissive_g;
150+
float emissive_b;
131151
};
132152

133153
}// namespace cg

0 commit comments

Comments
 (0)