Advertisement
Guest User

Untitled

a guest
Jan 17th, 2019
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.36 KB | None | 0 0
  1. #include "software_renderer.h"
  2.  
  3. #include <cmath>
  4. #include <vector>
  5. #include <iostream>
  6. #include <algorithm>
  7.  
  8. #include "triangulation.h"
  9.  
  10. using namespace std;
  11.  
  12. namespace CS248 {
  13.  
  14.  
  15. // Implements SoftwareRenderer //
  16.  
  17. // fill a sample location with color
  18. void SoftwareRendererImp::fill_sample(int sx, int sy, const Color &color) {
  19. // cerr << "in fill sample\n";
  20. if (sx < 0 || sx >= target_w * sample_rate) return;
  21. if (sy < 0 || sy >= target_h * sample_rate) return;
  22.  
  23. Color pixel_color;
  24. float inv255 = 1.0 / 255.0;
  25. pixel_color.r = sample_buffer[4 * (sx + sy * target_w * sample_rate)] * inv255;
  26. pixel_color.g = sample_buffer[4 * (sx + sy * target_w * sample_rate) + 1] * inv255;
  27. pixel_color.b = sample_buffer[4 * (sx + sy * target_w * sample_rate) + 2] * inv255;
  28. pixel_color.a = sample_buffer[4 * (sx + sy * target_w * sample_rate) + 3] * inv255;
  29. //cerr << pixel_color << endl;
  30.  
  31. pixel_color = ref->alpha_blending_helper(pixel_color, color);
  32. //cerr << "original pixel color" << pixel_color << endl;
  33.  
  34. // cerr << "sx " << sx << "sy " << sy << "target_w" << target_w << "sample rate " << sample_rate << endl;
  35. // cerr << "index " << 4 * (sx + sy * target_w * sample_rate) << endl;
  36. sample_buffer[4 * (sx + sy * target_w * sample_rate)] = (uint8_t)(pixel_color.r * 255);
  37. // cerr << "doen with r\n";
  38. sample_buffer[4 * (sx + sy * target_w * sample_rate) + 1] = (uint8_t)(pixel_color.g * 255);
  39. // cerr << "doen with g\n";
  40. sample_buffer[4 * (sx + sy * target_w * sample_rate) + 2] = (uint8_t)(pixel_color.b * 255);
  41. // cerr << "doen with b\n";
  42. sample_buffer[4 * (sx + sy * target_w * sample_rate) + 3] = (uint8_t)(pixel_color.a * 255);
  43. }
  44.  
  45. // fill samples in the entire pixel specified by pixel coordinates
  46. void SoftwareRendererImp::fill_pixel(int x, int y, const Color &color) {
  47.  
  48. // Task 2: Re-implement this function
  49.  
  50. // check bounds
  51. if (x < 0 || x >= target_w) return;
  52. if (y < 0 || y >= target_h) return;
  53.  
  54. for (size_t sx = 0; sx < sample_rate; sx++)
  55. {
  56. for (size_t sy = 0; sy < sample_rate; sy++)
  57. {
  58. fill_sample(x * sample_rate + sx, y * sample_rate + sy, color);
  59. }
  60. }
  61. }
  62.  
  63. void SoftwareRendererImp::draw_svg( SVG& svg ) {
  64.  
  65. // set top level transformation
  66. transformation = canvas_to_screen;
  67.  
  68. // draw all elements
  69. for ( size_t i = 0; i < svg.elements.size(); ++i ) {
  70. draw_element(svg.elements[i]);
  71. }
  72.  
  73. // draw canvas outline
  74. Vector2D a = transform(Vector2D( 0 , 0 )); a.x--; a.y--;
  75. Vector2D b = transform(Vector2D(svg.width, 0 )); b.x++; b.y--;
  76. Vector2D c = transform(Vector2D( 0 ,svg.height)); c.x--; c.y++;
  77. Vector2D d = transform(Vector2D(svg.width,svg.height)); d.x++; d.y++;
  78.  
  79. rasterize_line(a.x, a.y, b.x, b.y, Color::Black);
  80. rasterize_line(a.x, a.y, c.x, c.y, Color::Black);
  81. rasterize_line(d.x, d.y, b.x, b.y, Color::Black);
  82. rasterize_line(d.x, d.y, c.x, c.y, Color::Black);
  83.  
  84. // resolve and send to render target
  85. resolve();
  86. }
  87.  
  88. void SoftwareRendererImp::set_sample_rate( size_t sample_rate ) {
  89. cerr << "set sampler ate called" << endl << endl << endl << endl << endl;
  90. this->sample_rate = sample_rate;
  91. size_t sample_buffer_size = 4 * target_h * target_w * sample_rate * sample_rate;
  92. this->sample_buffer.reserve(sample_buffer_size);
  93.  
  94. for (size_t i = 0; i < sample_buffer_size; i++) sample_buffer[i] = (uint8_t) 255;
  95. }
  96.  
  97. void SoftwareRendererImp::set_render_target( unsigned char* render_target,
  98. size_t width, size_t height ) {
  99.  
  100. this->render_target = render_target;
  101. this->target_w = width;
  102. this->target_h = height;
  103. size_t sample_buffer_size = 4 * target_h * target_w * sample_rate * sample_rate;
  104. this->sample_buffer.reserve(sample_buffer_size);
  105.  
  106. for (size_t i = 0; i < sample_buffer_size; i++) sample_buffer[i] = (uint8_t) 255;
  107. }
  108.  
  109. void SoftwareRendererImp::draw_element( SVGElement* element ) {
  110.  
  111. // Task 3 (part 1):
  112. // Modify this to implement the transformation stack
  113. Matrix3x3 oldTrans = transformation;
  114. transformation = transformation * element->transform;
  115. switch (element->type) {
  116. case POINT:
  117. draw_point(static_cast<Point&>(*element));
  118. break;
  119. case LINE:
  120. draw_line(static_cast<Line&>(*element));
  121. break;
  122. case POLYLINE:
  123. draw_polyline(static_cast<Polyline&>(*element));
  124. break;
  125. case RECT:
  126. draw_rect(static_cast<Rect&>(*element));
  127. break;
  128. case POLYGON:
  129. draw_polygon(static_cast<Polygon&>(*element));
  130. break;
  131. case ELLIPSE:
  132. draw_ellipse(static_cast<Ellipse&>(*element));
  133. break;
  134. case IMAGE:
  135. draw_image(static_cast<Image&>(*element));
  136. break;
  137. case GROUP:
  138. draw_group(static_cast<Group&>(*element));
  139. break;
  140. default:
  141. break;
  142. }
  143. transformation = oldTrans;
  144. }
  145.  
  146.  
  147. // Primitive Drawing //
  148.  
  149. void SoftwareRendererImp::draw_point( Point& point ) {
  150.  
  151. Vector2D p = transform(point.position);
  152. rasterize_point( p.x, p.y, point.style.fillColor );
  153.  
  154. }
  155.  
  156. void SoftwareRendererImp::draw_line( Line& line ) {
  157.  
  158. Vector2D p0 = transform(line.from);
  159. Vector2D p1 = transform(line.to);
  160. rasterize_line( p0.x, p0.y, p1.x, p1.y, line.style.strokeColor );
  161.  
  162. }
  163.  
  164. void SoftwareRendererImp::draw_polyline( Polyline& polyline ) {
  165.  
  166. Color c = polyline.style.strokeColor;
  167.  
  168. if( c.a != 0 ) {
  169. int nPoints = polyline.points.size();
  170. for( int i = 0; i < nPoints - 1; i++ ) {
  171. Vector2D p0 = transform(polyline.points[(i+0) % nPoints]);
  172. Vector2D p1 = transform(polyline.points[(i+1) % nPoints]);
  173. rasterize_line( p0.x, p0.y, p1.x, p1.y, c );
  174. }
  175. }
  176. }
  177.  
  178. void SoftwareRendererImp::draw_rect( Rect& rect ) {
  179.  
  180. Color c;
  181.  
  182. // draw as two triangles
  183. float x = rect.position.x;
  184. float y = rect.position.y;
  185. float w = rect.dimension.x;
  186. float h = rect.dimension.y;
  187.  
  188. Vector2D p0 = transform(Vector2D( x , y ));
  189. Vector2D p1 = transform(Vector2D( x + w , y ));
  190. Vector2D p2 = transform(Vector2D( x , y + h ));
  191. Vector2D p3 = transform(Vector2D( x + w , y + h ));
  192.  
  193. // draw fill
  194. c = rect.style.fillColor;
  195. if (c.a != 0 ) {
  196. rasterize_triangle( p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, c );
  197. rasterize_triangle( p2.x, p2.y, p1.x, p1.y, p3.x, p3.y, c );
  198. }
  199.  
  200. // draw outline
  201. c = rect.style.strokeColor;
  202. if( c.a != 0 ) {
  203. rasterize_line( p0.x, p0.y, p1.x, p1.y, c );
  204. rasterize_line( p1.x, p1.y, p3.x, p3.y, c );
  205. rasterize_line( p3.x, p3.y, p2.x, p2.y, c );
  206. rasterize_line( p2.x, p2.y, p0.x, p0.y, c );
  207. }
  208.  
  209. }
  210.  
  211. void SoftwareRendererImp::draw_polygon( Polygon& polygon ) {
  212.  
  213. Color c;
  214.  
  215. // draw fill
  216. c = polygon.style.fillColor;
  217. if( c.a != 0 ) {
  218.  
  219. // triangulate
  220. vector<Vector2D> triangles;
  221. triangulate( polygon, triangles );
  222.  
  223. // draw as triangles
  224. for (size_t i = 0; i < triangles.size(); i += 3) {
  225. Vector2D p0 = transform(triangles[i + 0]);
  226. Vector2D p1 = transform(triangles[i + 1]);
  227. Vector2D p2 = transform(triangles[i + 2]);
  228. rasterize_triangle( p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, c );
  229. }
  230. }
  231.  
  232. // draw outline
  233. c = polygon.style.strokeColor;
  234. if( c.a != 0 ) {
  235. int nPoints = polygon.points.size();
  236. for( int i = 0; i < nPoints; i++ ) {
  237. Vector2D p0 = transform(polygon.points[(i+0) % nPoints]);
  238. Vector2D p1 = transform(polygon.points[(i+1) % nPoints]);
  239. rasterize_line( p0.x, p0.y, p1.x, p1.y, c );
  240. }
  241. }
  242. }
  243.  
  244. void SoftwareRendererImp::draw_ellipse( Ellipse& ellipse ) {
  245.  
  246. // Extra credit
  247.  
  248. }
  249.  
  250. void SoftwareRendererImp::draw_image( Image& image ) {
  251.  
  252. Vector2D p0 = transform(image.position);
  253. Vector2D p1 = transform(image.position + image.dimension);
  254.  
  255. rasterize_image( p0.x, p0.y, p1.x, p1.y, image.tex );
  256. }
  257.  
  258. void SoftwareRendererImp::draw_group( Group& group ) {
  259.  
  260. for ( size_t i = 0; i < group.elements.size(); ++i ) {
  261. draw_element(group.elements[i]);
  262. }
  263.  
  264. }
  265.  
  266. // Rasterization //
  267.  
  268. // The input arguments in the rasterization functions
  269. // below are all defined in screen space coordinates
  270.  
  271. void SoftwareRendererImp::rasterize_point( float x, float y, Color color ) {
  272.  
  273. // fill in the nearest pixel
  274. int sx = (int)floor(x);
  275. int sy = (int)floor(y);
  276.  
  277. // check bounds
  278. if (sx < 0 || sx >= target_w) return;
  279. if (sy < 0 || sy >= target_h) return;
  280.  
  281. fill_pixel(sx, sy, color);
  282.  
  283. }
  284.  
  285. void SoftwareRendererImp::rasterize_line( float x0, float y0,
  286. float x1, float y1,
  287. Color color) {
  288.  
  289. // Extra credit (delete the line below and implement your own)
  290. ref->rasterize_line_helper(x0, y0, x1, y1, target_w, target_h, color, this);
  291.  
  292. }
  293.  
  294. int findMaxIdx(const float vals[]) {
  295. int numElems = 3;
  296. int maxSoFar = 0;
  297.  
  298. for (int i = 0; i < numElems; i++)
  299. if (vals[maxSoFar] < vals[i]) maxSoFar = i;
  300.  
  301. return maxSoFar;
  302. }
  303.  
  304. int findMinIdx(const float vals[]) {
  305. int numElems = 3;
  306. int minSoFar = 0;
  307.  
  308. for (int i = 0; i < numElems; i++)
  309. if (vals[minSoFar] > vals[i]) minSoFar = i;
  310.  
  311. return minSoFar;
  312. }
  313.  
  314. void getCounterCPoints(const float xVals[], const float yVals[], float xCCW[], float yCCW[])
  315. {
  316. int lIdx = findMinIdx(xVals);
  317. int rIdx = findMaxIdx(xVals);
  318. int oIdx = 3 - lIdx - rIdx;
  319.  
  320. Vector2D normalVec = Vector2D(yVals[rIdx] - yVals[lIdx], - (xVals[rIdx] - xVals[lIdx]));
  321. Vector2D toCheckVec = Vector2D(xVals[oIdx] - xVals[lIdx], yVals[oIdx] - yVals[lIdx]);
  322.  
  323. double d = dot(toCheckVec.unit(), normalVec.unit());
  324. if (d > 0) {
  325. xCCW[0] = xVals[lIdx];
  326. xCCW[1] = xVals[rIdx];
  327. xCCW[2] = xVals[oIdx];
  328.  
  329. yCCW[0] = yVals[lIdx];
  330. yCCW[1] = yVals[rIdx];
  331. yCCW[2] = yVals[oIdx];
  332. } else {
  333. xCCW[0] = xVals[lIdx];
  334. xCCW[1] = xVals[oIdx];
  335. xCCW[2] = xVals[rIdx];
  336.  
  337. yCCW[0] = yVals[lIdx];
  338. yCCW[1] = yVals[oIdx];
  339. yCCW[2] = yVals[rIdx];
  340. }
  341. }
  342.  
  343. // http://totologic.blogspot.com/2014/01/accurate-point-in-triangle-test.html
  344. bool isInsideTri(const double &x, const double &y, const float xCCW[], const float yCCW[])
  345. {
  346. Vector2D v0 = (Vector2D(yCCW[1] - yCCW[0], -xCCW[1] + xCCW[0])).unit();
  347. Vector2D v1 = (Vector2D(yCCW[2] - yCCW[1], -xCCW[2] + xCCW[1])).unit();
  348. Vector2D v2 = (Vector2D(yCCW[0] - yCCW[2], -xCCW[0] + xCCW[2])).unit();
  349.  
  350. Vector2D v0p = (Vector2D(x - xCCW[0], y - yCCW[0])).unit();
  351. Vector2D v1p = (Vector2D(x - xCCW[1], y - yCCW[1])).unit();
  352. Vector2D v2p = (Vector2D(x - xCCW[2], y - yCCW[2])).unit();
  353.  
  354. double d0 = dot(v0, v0p);
  355. double d1 = dot(v1, v1p);
  356. double d2 = dot(v2, v2p);
  357.  
  358. return (d0 >= 0 && d1 >= 0 && d2 >= 0);
  359. }
  360.  
  361. void SoftwareRendererImp::rasterize_triangle( float x0, float y0,
  362. float x1, float y1,
  363. float x2, float y2,
  364. Color color ) {
  365. float xVals[3] = {x0, x1, x2};
  366. float yVals[3] = {y0, y1, y2};
  367. float xCCW[3], yCCW[3];
  368.  
  369. // Get points in counter clockwise order
  370. getCounterCPoints(xVals, yVals, xCCW, yCCW);
  371.  
  372. // Get bounding box
  373. int minX = floor(min({x0, x1, x2}));
  374. int maxX = floor(max({x0, x1, x2}));
  375. int minY = floor(min({y0, y1, y2}));
  376. int maxY = floor(max({y0, y1, y2}));
  377.  
  378. for (int sx = minX * sample_rate; sx <= maxX * sample_rate; sx++)
  379. {
  380. for (int sy = minY * sample_rate; sy <= maxY * sample_rate; sy++)
  381. {
  382. if (isInsideTri((double)sx / (double)sample_rate + 1.0 / (double) (2 * sample_rate), (double)sy / (double)sample_rate + 1.0 / (double) (2 * sample_rate), xCCW, yCCW))
  383. fill_sample(sx, sy, color);
  384. }
  385. }
  386. }
  387.  
  388. void SoftwareRendererImp::rasterize_image( float x0, float y0,
  389. float x1, float y1,
  390. Texture& tex ) {
  391. // Task 4:
  392. // Implement image rasterization (you may want to call fill_sample here)
  393. int minx = floor(x0);
  394. int maxx = floor(x1);
  395. int miny = floor(y0);
  396. int maxy = floor(y1);
  397.  
  398. float width = x1 - x0;
  399. float height = y1 - y0;
  400.  
  401. for (float x = minx; x < maxx; x++)
  402. {
  403. for (floor y = miny; y < maxy; y++)
  404. {
  405. sampler->sample_nearest(tex, x / wdith, y / height);
  406. }
  407. }
  408. }
  409.  
  410. // resolve samples to render target
  411. void SoftwareRendererImp::resolve( void ) {
  412. for (unsigned x = 0; x < target_w; x++)
  413. {
  414. for (unsigned y = 0; y < target_h; y++)
  415. {
  416. Color total(0.0, 0.0, 0.0, 0.0);
  417. for (unsigned sx = x * sample_rate; sx < (x + 1) * sample_rate; sx++)
  418. {
  419. for (unsigned sy = y * sample_rate; sy < (y + 1) * sample_rate; sy++)
  420. {
  421. Color c;
  422. float inv255 = 1.0 / 255.0;
  423. c.r = sample_buffer[4 * (sx + sy * target_w * sample_rate)] * inv255;
  424. c.g = sample_buffer[4 * (sx + sy * target_w * sample_rate) + 1] * inv255;
  425. c.b = sample_buffer[4 * (sx + sy * target_w * sample_rate) + 2] * inv255;
  426. c.a = sample_buffer[4 * (sx + sy * target_w * sample_rate) + 3] * inv255;
  427.  
  428. total += c;
  429. //cerr << "temp total" << total << endl;
  430. }
  431. }
  432. total *= 1.0 / ((float) (sample_rate * sample_rate));
  433. //if(total.r > 0.1) cerr << "total " << total << endl;
  434. render_target[4 * (x + y * target_w)] = (uint8_t)(total.r * 255);
  435. render_target[4 * (x + y * target_w) + 1] = (uint8_t)(total.g * 255);
  436. render_target[4 * (x + y * target_w) + 2] = (uint8_t)(total.b * 255);
  437. render_target[4 * (x + y * target_w) + 3] = (uint8_t)(total.a * 255);
  438. }
  439. }
  440. size_t sample_buffer_size = 4 * target_h * target_w * sample_rate * sample_rate;
  441.  
  442. for (size_t i = 0; i < sample_buffer_size; i++)
  443. {
  444. sample_buffer[i] = (uint8_t) 255;
  445. }
  446. }
  447.  
  448.  
  449. } // namespace CS248
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement