4
4
5
5
#include < functional>
6
6
#include < iostream>
7
- #include < linalg.h>
8
7
#include < limits>
8
+ #include < linalg.h>
9
9
#include < memory>
10
10
11
11
@@ -19,8 +19,8 @@ namespace cg::renderer
19
19
class rasterizer
20
20
{
21
21
public:
22
- rasterizer (){};
23
- ~rasterizer (){};
22
+ rasterizer () {};
23
+ ~rasterizer () {};
24
24
void set_render_target (
25
25
std::shared_ptr<resource<RT>> in_render_target,
26
26
std::shared_ptr<resource<float >> in_depth_buffer = nullptr );
@@ -46,7 +46,7 @@ namespace cg::renderer
46
46
size_t width = 1920 ;
47
47
size_t height = 1080 ;
48
48
49
- int edge_function (int2 a, int2 b, int2 c);
49
+ float edge_function (float2 a, float2 b, float2 c);
50
50
bool depth_test (float z, size_t x, size_t y);
51
51
};
52
52
@@ -55,22 +55,31 @@ namespace cg::renderer
55
55
std::shared_ptr<resource<RT>> in_render_target,
56
56
std::shared_ptr<resource<float >> in_depth_buffer)
57
57
{
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
+ }
60
64
}
61
65
62
66
template <typename VB, typename RT>
63
67
inline void rasterizer<VB, RT>::set_viewport(size_t in_width, size_t in_height)
64
68
{
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;
66
71
}
67
72
68
73
template <typename VB, typename RT>
69
74
inline void rasterizer<VB, RT>::clear_render_target(
70
75
const RT& in_clear_value, const float in_depth)
71
76
{
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
+ }
74
83
}
75
84
76
85
template <typename VB, typename RT>
@@ -90,17 +99,72 @@ namespace cg::renderer
90
99
template <typename VB, typename RT>
91
100
inline void rasterizer<VB, RT>::draw(size_t num_vertexes, size_t vertex_offset)
92
101
{
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
+ }
96
161
}
97
162
98
163
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)
101
166
{
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 );
104
168
}
105
169
106
170
template <typename VB, typename RT>
0 commit comments