Skip to content

Lab2 #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 76 additions & 13 deletions src/renderer/rasterizer/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#include <functional>
#include <iostream>
#include <linalg.h>
#include <limits>
#include <memory>


Expand Down Expand Up @@ -55,22 +53,32 @@ namespace cg::renderer
std::shared_ptr<resource<RT>> in_render_target,
std::shared_ptr<resource<float>> in_depth_buffer)
{
// TODO Lab: 1.02 Implement `set_render_target`, `set_viewport`, `clear_render_target` methods of `cg::renderer::rasterizer` class
// TODO Lab: 1.06 Adjust `set_render_target`, and `clear_render_target` methods of `cg::renderer::rasterizer` class to consume a depth buffer
if (in_render_target) {
render_target = in_render_target;
}
if (in_depth_buffer) {
depth_buffer = in_depth_buffer;
}
}

template<typename VB, typename RT>
inline void rasterizer<VB, RT>::set_viewport(size_t in_width, size_t in_height)
{
// TODO Lab: 1.02 Implement `set_render_target`, `set_viewport`, `clear_render_target` methods of `cg::renderer::rasterizer` class
width = in_width;
height = in_height;
}

template<typename VB, typename RT>
inline void rasterizer<VB, RT>::clear_render_target(
const RT& in_clear_value, const float in_depth)
{
// TODO Lab: 1.02 Implement `set_render_target`, `set_viewport`, `clear_render_target` methods of `cg::renderer::rasterizer` class
// TODO Lab: 1.06 Adjust `set_render_target`, and `clear_render_target` methods of `cg::renderer::rasterizer` class to consume a depth buffer
for (size_t i = 0; i < render_target->get_number_of_elements(); ++i) {
render_target->item(i) = in_clear_value;
}

for (size_t i = 0; i < depth_buffer->get_number_of_elements(); ++i) {
depth_buffer->item(i) = in_depth;
}
}

template<typename VB, typename RT>
Expand All @@ -90,23 +98,78 @@ namespace cg::renderer
template<typename VB, typename RT>
inline void rasterizer<VB, RT>::draw(size_t num_vertexes, size_t vertex_offset)
{
// TODO Lab: 1.04 Implement `cg::world::camera` class
// TODO Lab: 1.05 Add `Rasterization` and `Pixel shader` stages to `draw` method of `cg::renderer::rasterizer`
// TODO Lab: 1.06 Add `Depth test` stage to `draw` method of `cg::renderer::rasterizer`
size_t vertex_id = vertex_offset;
while (vertex_id < vertex_offset + num_vertexes) {
std::vector<VB> vertices(3);
vertices[0] = vertex_buffer->item(index_buffer->item(vertex_id++));
vertices[1] = vertex_buffer->item(index_buffer->item(vertex_id++));
vertices[2] = vertex_buffer->item(index_buffer->item(vertex_id++));

for (auto& vertex: vertices) {
float4 coords{vertex.x, vertex.y, vertex.z, 1.f};
auto processed_vertex = vertex_shader(coords, vertex);

vertex.x = processed_vertex.first.x / processed_vertex.first.w;
vertex.y = processed_vertex.first.y / processed_vertex.first.w;
vertex.z = processed_vertex.first.z / processed_vertex.first.w;

vertex.x = (vertex.x + 1.f) * width / 2.f;
vertex.y = (-vertex.y + 1.f) * height / 2.f;
}

float2 vertex_a = float2{vertices[0].x, vertices[0].y};
float2 vertex_b = float2{vertices[1].x, vertices[1].y};
float2 vertex_c = float2{vertices[2].x, vertices[2].y};

float2 min_vertex = min(vertex_a, min(vertex_b, vertex_c));
float2 bounding_box_begin = round(clamp(min_vertex, float2{0.f, 0.f},
float2{static_cast<float>(width - 1), static_cast<float>(height - 1)}));

float2 max_vertex = max(vertex_a, max(vertex_b, vertex_c));
float2 bounding_box_end = round(clamp(max_vertex, float2{0.f, 0.f},
float2{static_cast<float>(width - 1), static_cast<float>(height - 1)}));

float edge = edge_function(vertex_a, vertex_b, vertex_c);

for (float x = bounding_box_begin.x; x <= bounding_box_end.x; x += 1.f) {
for (float y = bounding_box_begin.y; y <= bounding_box_end.y; y += 1.f) {
float2 point{x, y};
float edge0 = edge_function(vertex_a, vertex_b, point);
float edge1 = edge_function(vertex_b, vertex_c, point);
float edge2 = edge_function(vertex_c, vertex_a, point);
if (edge0 >= 0.f && edge1 >= 0.f && edge2 >= 0.f) {
size_t u_x = static_cast<size_t>(x);
size_t u_y = static_cast<size_t>(y);

float u = edge1 / edge;
float v = edge2 / edge;
float w = edge0 / edge;

float z = u * vertices[0].z +
v * vertices[1].z +
w * vertices[2].z;

if (depth_test(z, u_x, u_y)) {
auto pixel_result = pixel_shader(vertices[0], z);
render_target->item(u_x, u_y) = RT::from_color(pixel_result);
depth_buffer->item(u_x, u_y) = z;
}
}
}
}
}
}

template<typename VB, typename RT>
inline float
rasterizer<VB, RT>::edge_function(float2 a, float2 b, float2 c)
{
// TODO Lab: 1.05 Implement `cg::renderer::rasterizer::edge_function` method
return 0.f;
return (c.x - a.x) * (b.y - a.y) - (c.y - a.y) * (b.x - a.x);
}

template<typename VB, typename RT>
inline bool rasterizer<VB, RT>::depth_test(float z, size_t x, size_t y)
{
// TODO Lab: 1.06 Implement `depth_test` function of `cg::renderer::rasterizer` class
if (!depth_buffer)
{
return true;
Expand Down
73 changes: 65 additions & 8 deletions src/renderer/rasterizer/rasterizer_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,74 @@

void cg::renderer::rasterization_renderer::init()
{
// TODO Lab: 1.02 Implement image clearing & saving in `cg::renderer::rasterization_renderer` class
// TODO Lab: 1.03 Adjust `cg::renderer::rasterization_renderer` class to consume `cg::world::model`
// TODO Lab: 1.04 Setup an instance of camera `cg::world::camera` class in `cg::renderer::rasterization_renderer`
// TODO Lab: 1.06 Add depth buffer in `cg::renderer::rasterization_renderer`
rasterizer = std::make_shared<
cg::renderer::rasterizer<cg::vertex, cg::unsigned_color>>();
rasterizer->set_viewport(settings->width, settings->height);

render_target = std::make_shared<cg::resource<cg::unsigned_color>>(
settings->width, settings->height);

rasterizer->set_render_target(render_target);

model = std::make_shared<cg::world::model>();
model->load_obj(settings->model_path);

camera = std::make_shared<cg::world::camera>();
camera->set_height(static_cast<float>(settings->height));
camera->set_width(static_cast<float>(settings->width));
camera->set_position(float3{
settings->camera_position[0],
settings->camera_position[1],
settings->camera_position[2],
});

camera->set_theta(settings->camera_theta);
camera->set_phi(settings->camera_phi);
camera->set_angle_of_view(settings->camera_angle_of_view);
camera->set_z_near(settings->camera_z_near);
camera->set_z_far(settings->camera_z_far);

depth_buffer = std::make_shared<cg::resource<float>>(
settings->width, settings->height);
rasterizer->set_render_target(render_target, depth_buffer);
}
void cg::renderer::rasterization_renderer::render()
{
// TODO Lab: 1.02 Implement image clearing & saving in `cg::renderer::rasterization_renderer` class
// TODO Lab: 1.04 Implement `vertex_shader` lambda for the instance of `cg::renderer::rasterizer`
// TODO Lab: 1.05 Implement `pixel_shader` lambda for the instance of `cg::renderer::rasterizer`
// TODO Lab: 1.03 Adjust `cg::renderer::rasterization_renderer` class to consume `cg::world::model`
float4x4 matrix = mul(
camera->get_projection_matrix(),
camera->get_view_matrix(),
model->get_world_matrix());
rasterizer->vertex_shader = [&](float4 vertex, cg::vertex data) {
auto processed = mul(matrix, vertex);
return std::make_pair(processed, data);
};
rasterizer->pixel_shader = [](cg::vertex data, float z) {
return cg::color{
data.ambient_r,
data.ambient_g,
data.ambient_b,
};
};

auto start = std::chrono::high_resolution_clock::now();
rasterizer->clear_render_target({111, 5, 243});
auto stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<float, std::milli> clear_duration = stop - start;
std::cout << "Clearing took " << clear_duration.count() << "ms\n";

start = std::chrono::high_resolution_clock::now();
for (size_t shape_id = 0; shape_id < model->get_index_buffers().size(); ++shape_id) {
rasterizer->set_vertex_buffer(model->get_vertex_buffers()[shape_id]);
rasterizer->set_index_buffer(model->get_index_buffers()[shape_id]);
rasterizer->draw(
model->get_index_buffers()[shape_id]->get_number_of_elements(),
0);
}
stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<float, std::milli> rendering_duration = stop - start;
std::cout << "Rendering took " << rendering_duration.count() << "ms\n";

utils::save_resource(*render_target, settings->result_path);
}

void cg::renderer::rasterization_renderer::destroy() {}
Expand Down
Loading