Guest User

Untitled

a guest
Jul 26th, 2026
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.73 KB | None | 0 0
  1. #include <renderkid/rasterization.hpp>
  2. #include <renderkid/vertex_stage.hpp>
  3.  
  4. #define GLM_ENABLE_EXPERIMENTAL
  5.  
  6. #include <glm/gtx/string_cast.hpp>
  7. #include <glm/ext/scalar_common.hpp>
  8. #include <glm/vec4.hpp>
  9. #include <raylib.h>
  10. #include <utility>
  11. #include <cstdint>
  12. #include <memory>
  13. #include <vector>
  14. #include <cmath>
  15. #include <map>
  16.  
  17. std::allocator<float> depth_buffer_allocator;
  18. std::allocator<uint8_t> texture_allocator;
  19.  
  20.  
  21. inline float determinant(const glm::vec4 &a, const glm::vec4 &b, const glm::vec4 &c) {
  22. glm::vec4 ab = glm::vec4(b);
  23. glm::vec4 ac = glm::vec4(c);
  24.  
  25. ab -= a;
  26. ac -= a;
  27.  
  28. return ab.y * ac.x - ab.x * ac.y;
  29. }
  30.  
  31.  
  32. _raster::Rasterizer::Rasterizer(int width, int height) {
  33. this->width = width;
  34. this->height = height;
  35. textures = std::map<uint8_t, _raster::UserTexture>();
  36.  
  37. int depth_buffer_size = width * height;
  38.  
  39. depth_buffer = depth_buffer_allocator.allocate(depth_buffer_size);
  40.  
  41. for (int i = 0; i < depth_buffer_size; ++i) {
  42. depth_buffer[i] = INFINITY;
  43. }
  44.  
  45. next_texture_id = 0;
  46. framebuffer = GenImageColor(width, height, BLACK);
  47. framebuffer_texture = LoadTextureFromImage(framebuffer);
  48. SetTextureFilter(framebuffer_texture, TEXTURE_FILTER_POINT);
  49. }
  50.  
  51.  
  52. uint8_t _raster::Rasterizer::create_texture(int width, int height, int n_channels) {
  53. _raster::UserTexture new_texture;
  54. new_texture.width = width;
  55. new_texture.height = height;
  56. new_texture.channels = n_channels;
  57. new_texture.data = texture_allocator.allocate(width * height * n_channels);
  58.  
  59. textures[next_texture_id] = new_texture;
  60.  
  61. return next_texture_id++;
  62. }
  63.  
  64.  
  65. void _raster::Rasterizer::destroy_texture(uint8_t id) {
  66. int texture_size = textures[id].width * textures[id].height * textures[id].channels;
  67. texture_allocator.deallocate(textures[id].data, texture_size);
  68. textures.erase(id);
  69. }
  70.  
  71.  
  72. void _raster::Rasterizer::load_data_to_texture(uint8_t *data) {
  73. _raster::UserTexture texture = textures[current_texture];
  74. int texture_size = texture.width * texture.height * texture.channels;
  75.  
  76. memcpy(textures[current_texture].data, data, texture_size);
  77. }
  78.  
  79.  
  80. inline bool is_left_or_top_edge(const glm::vec4 &start, const glm::vec4 &end) {
  81. glm::vec4 edge = end;
  82. edge -= start;
  83.  
  84. return (edge.y > 0) || (edge.y == 0 && edge.x < 0);
  85. }
  86.  
  87.  
  88. glm::vec4 _gen_frag_color_from_vertex_color(const glm::vec4 &frag_coord,
  89. const glm::vec4 &a_color,
  90. const glm::vec4 &b_color,
  91. const glm::vec4 &c_color) {
  92. glm::vec4 color = a_color * frag_coord.x + b_color * frag_coord.y + c_color * frag_coord.z;
  93.  
  94. float color_a = glm::max(0, glm::min(255, (int)glm::floor(color.x * 256.0f)));
  95. float color_b = glm::max(0, glm::min(255, (int)glm::floor(color.y * 256.0f)));
  96. float color_c = glm::max(0, glm::min(255, (int)glm::floor(color.z * 256.0f)));
  97.  
  98. return glm::vec4(color_a, color_b, color_c, 255.0);
  99. }
  100.  
  101.  
  102. glm::vec4 _raster::Rasterizer::gen_frag_color_from_texture(const glm::vec4 &frag_coord,
  103. const glm::vec4 &a_coord,
  104. const glm::vec4 &b_coord,
  105. const glm::vec4 &c_coord) {
  106. glm::vec4 interpolated_uv = frag_coord.x * a_coord + frag_coord.y * b_coord + frag_coord.z * c_coord;
  107. float interpolated_w = frag_coord.x * a_coord.w + frag_coord.y * b_coord.w + frag_coord.z * c_coord.w;
  108.  
  109. _raster::UserTexture texture = textures[current_texture];
  110. int texture_size = texture.width * texture.height * texture.channels;
  111.  
  112. int coord_x = (int)((interpolated_uv.x / interpolated_w) * texture.width) % texture.width;
  113. int coord_y = (int)((interpolated_uv.y / interpolated_w) * texture.height) % texture.height;
  114. int idx = (coord_y * texture.width + coord_x) * texture.channels;
  115.  
  116. return glm::vec4(texture.data[idx], texture.data[idx + 1], texture.data[idx + 2], texture.data[idx + 3]);
  117. }
  118.  
  119.  
  120. glm::vec4 _raster::Rasterizer::gen_frag_color_from_attributes(const glm::vec4 &frag_coord, const _vertex::Vertex &a,
  121. const _vertex::Vertex &b, const _vertex::Vertex &c) {
  122. glm::vec4 result = glm::vec4(1.0f);
  123.  
  124. for (size_t i = 0; i < MAX_ATTRIBS; ++i) {
  125. switch (a.attribs[i].type) {
  126. case 0:
  127. return result;
  128. case COLOR_RGB_ATTRIBUTE:
  129. case COLOR_RGBA_ATTRIBUTE:
  130. result *= _gen_frag_color_from_vertex_color(frag_coord, a.attribs[i].data,
  131. b.attribs[i].data, c.attribs[i].data);
  132. break;
  133. case TEXTURE_COORD_ATTRIBUTE:
  134. result *= gen_frag_color_from_texture(frag_coord, a.attribs[i].data,
  135. b.attribs[i].data, c.attribs[i].data);
  136. break;
  137. }
  138. }
  139.  
  140. return result;
  141. }
  142.  
  143.  
  144. void _raster::Rasterizer::raster_triangle(const _vertex::Primitive &triangle) {
  145. glm::vec4 a = triangle.vertices[0].coords;
  146. glm::vec4 b = triangle.vertices[1].coords;
  147. glm::vec4 c = triangle.vertices[2].coords;
  148.  
  149. const float xmin = glm::fmin(a.x, b.x, c.x);
  150. const float ymin = glm::fmin(a.y, b.y, c.y);
  151. const float xmax = glm::fmax(a.x, b.x, c.x);
  152. const float ymax = glm::fmax(a.y, b.y, c.y);
  153.  
  154. for (float y = ymin; y <= ymax; ++y) {
  155. if (y < 0 || y > height) {
  156. continue;
  157. }
  158.  
  159. for (float x = xmin; x <= xmax; ++x) {
  160. if (x < 0 || x > width) {
  161. continue;
  162. }
  163.  
  164. glm::vec4 pixel = glm::vec4(x, y, 0.0f, 0.0f);
  165.  
  166. float area = determinant(a, b, c);
  167. bool clockwise = false;
  168.  
  169. if (area < 0) {
  170. std::swap(b, c);
  171. area = -area;
  172. clockwise = true;
  173. }
  174.  
  175. float w0 = determinant(b, c, pixel);
  176. float w1 = determinant(c, a, pixel);
  177. float w2 = determinant(a, b, pixel);
  178.  
  179. if (is_left_or_top_edge(b, c)) {
  180. --w0;
  181. }
  182.  
  183. if (is_left_or_top_edge(c, a)) {
  184. --w1;
  185. }
  186.  
  187. if (is_left_or_top_edge(a, b)) {
  188. --w2;
  189. }
  190.  
  191. if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
  192. glm::vec4 bary_coords = glm::vec4((w0 + 1) / area, (w1 + 1) / area, (w2 + 1) / area, 0.0f);
  193.  
  194. float frag_z = 1 / (a.z * bary_coords.x + b.z * bary_coords.y + c.z * bary_coords.z);
  195. glm::vec4 frag_color;
  196.  
  197. frag_color = gen_frag_color_from_attributes(
  198. bary_coords,
  199. triangle.vertices[0],
  200. triangle.vertices[1],
  201. triangle.vertices[2]
  202. );
  203.  
  204. int buffer_index = ((int)y) * width + ((int)x);
  205. float previous_z = depth_buffer[buffer_index];
  206.  
  207. if (frag_z < previous_z) {
  208. depth_buffer[buffer_index] = frag_z;
  209.  
  210. ImageDrawPixel(&framebuffer, x, y, (Color){
  211. static_cast<uint8_t>(frag_color.x),
  212. static_cast<uint8_t>(frag_color.y),
  213. static_cast<uint8_t>(frag_color.z),
  214. static_cast<uint8_t>(frag_color.w)
  215. });
  216. }
  217. }
  218. }
  219. }
  220. }
  221.  
  222.  
  223. void _raster::Rasterizer::draw_framebuffer() {
  224. UpdateTexture(framebuffer_texture, framebuffer.data);
  225. DrawTexture(framebuffer_texture, 0, 0, WHITE);
  226. }
  227.  
  228.  
  229. void _raster::Rasterizer::clear_framebuffer() {
  230. ImageClearBackground(&framebuffer, BLACK);
  231. }
  232.  
  233.  
  234. void _raster::Rasterizer::draw_primitives(uint8_t primitive_type, std::vector<_vertex::Primitive> &primitives) {
  235. BeginDrawing();
  236. clear_framebuffer();
  237. int depth_buffer_size = width * height;
  238.  
  239. for (int i = 0; i < depth_buffer_size; ++i) {
  240. depth_buffer[i] = INFINITY;
  241. }
  242.  
  243. for (const _vertex::Primitive &primitive : primitives) {
  244. raster_triangle(primitive);
  245. }
  246.  
  247. primitives.clear();
  248. draw_framebuffer();
  249. EndDrawing();
  250. }
Add Comment
Please, Sign In to add comment