sr.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. #include <stdlib.h>
  2. #include "sr.h"
  3. #include "mat.h"
  4. #include "state.h"
  5. /**
  6. * api.c
  7. * --------
  8. * an easy interface with a fixed subset of the sr pipeline
  9. * for your average use case
  10. *
  11. * provides a uniform with model view projection matrix,
  12. * and matrix stack-like operations to build it
  13. *
  14. */
  15. /*********************************************************************
  16. * *
  17. * global variables that control pipeline state *
  18. * *
  19. *********************************************************************/
  20. /* identity matrix */
  21. static const struct mat4 identity = {
  22. 1, 0, 0, 0,
  23. 0, 1, 0, 0,
  24. 0, 0, 1, 0,
  25. 0, 0, 0, 1
  26. };
  27. /* model matrix */
  28. static struct mat4 model = {
  29. 1, 0, 0, 0,
  30. 0, 1, 0, 0,
  31. 0, 0, 1, 0,
  32. 0, 0, 0, 1
  33. };
  34. /* normal transform matrix */
  35. static struct mat4 normal_transform = {
  36. 1, 0, 0, 0,
  37. 0, 1, 0, 0,
  38. 0, 0, 1, 0,
  39. 0, 0, 0, 1
  40. };
  41. /* camera view matrix */
  42. static struct mat4 view = {
  43. 1, 0, 0, 0,
  44. 0, 1, 0, 0,
  45. 0, 0, 1, 0,
  46. 0, 0, 0, 1
  47. };
  48. /* projection matrix */
  49. static struct mat4 proj = {
  50. 1, 0, 0, 0,
  51. 0, 1, 0, 0,
  52. 0, 0, 1, 0,
  53. 0, 0, 0, 1
  54. };
  55. /* model view projection matrix */
  56. static struct mat4 mvp = {
  57. 1, 0, 0, 0,
  58. 0, 1, 0, 0,
  59. 0, 0, 1, 0,
  60. 0, 0, 0, 1
  61. };
  62. static struct light g_lights[SR_MAX_LIGHT_COUNT];
  63. static struct material g_material;
  64. static struct mat4* cur_mat; /* points to whichever matrix stack is being used */
  65. static struct sr_texture g_texture = {
  66. .colors = 0,
  67. .width = 0,
  68. .height = 0
  69. };
  70. /* framebuffer */
  71. static struct sr_framebuffer g_fbuf = {
  72. .width = 0,
  73. .height = 0,
  74. .colors = 0,
  75. .depths = 0
  76. };
  77. /* uniform */
  78. static struct sr_uniform g_uniform = {
  79. .model = &model,
  80. .normal_transform = &normal_transform,
  81. .mvp = &mvp,
  82. .has_texture = 0,
  83. .material = &g_material,
  84. .texture = &g_texture,
  85. .lights = g_lights,
  86. .ka = 1,
  87. .kd = 1,
  88. .ks = 1
  89. };
  90. /* pipeline state */
  91. static struct sr_pipeline g_pipe = {
  92. .fbuf = &g_fbuf,
  93. .uniform = (void*)(&g_uniform),
  94. .vs = 0,
  95. .fs = 0,
  96. .pts_in = 0,
  97. .n_pts = 0,
  98. .n_attr_in = 0,
  99. .n_attr_out = 0,
  100. .winding = SR_WINDING_ORDER_CCW
  101. };
  102. /*********************************************************************
  103. * *
  104. * render interface *
  105. * *
  106. *********************************************************************/
  107. /**************
  108. * sr_renderl *
  109. **************/
  110. /* builds the mvp and renders the global state */
  111. extern void
  112. sr_renderl(int* indices, int n_indices, enum sr_primitive prim_type)
  113. {
  114. /* create mvp */
  115. mvp = identity;
  116. matmul(&mvp, &proj);
  117. matmul(&mvp, &view);
  118. matmul(&mvp, &model);
  119. /* create normal transform matrix */
  120. normal_transform = model;
  121. upper_3x3(&normal_transform);
  122. transpose(&normal_transform);
  123. invert(&normal_transform);
  124. /* camera position */
  125. float origin[4] = {0, 0, 0, 1};
  126. float tmp[4];
  127. struct mat4 view_inverse = view;
  128. invert(&view_inverse);
  129. vec4_matmul(tmp, &view_inverse, origin);
  130. memcpy(g_uniform.cam_pos, tmp, 3 * sizeof(float));
  131. /* send down the pipeline */
  132. sr_render(&g_pipe, indices, n_indices, prim_type);
  133. }
  134. /*********************************************************************
  135. * *
  136. * pipeline and uniform bindings *
  137. * *
  138. *********************************************************************/
  139. /***************
  140. * sr_bind_pts *
  141. ***************/
  142. /* sets points */
  143. extern void
  144. sr_bind_pts(float* pts, int n_pts, int n_attr)
  145. {
  146. g_pipe.pts_in = pts;
  147. g_pipe.n_pts = n_pts;
  148. g_pipe.n_attr_in = n_attr;
  149. }
  150. /***********************
  151. * sr_bind_framebuffer *
  152. ***********************/
  153. /* attaches color and depth buffers to global framebuffer */
  154. extern void
  155. sr_bind_framebuffer(int width, int height, uint32_t* colors, float* depths)
  156. {
  157. g_fbuf.width = width;
  158. g_fbuf.height = height;
  159. g_fbuf.colors = colors;
  160. g_fbuf.depths = depths;
  161. }
  162. /*******************
  163. * sr_bind_uniform *
  164. *******************/
  165. /* loads a custom uniform */
  166. extern void
  167. sr_bind_uniform(void* uniform)
  168. {
  169. g_pipe.uniform = uniform;
  170. }
  171. /**********************
  172. * sr_restore_uniform *
  173. **********************/
  174. /* loads default uniform */
  175. extern void
  176. sr_restore_uniform()
  177. {
  178. g_pipe.uniform = &g_uniform;
  179. }
  180. /**************
  181. * sr_bind_vs *
  182. **************/
  183. /* sets the vertex shader */
  184. extern void
  185. sr_bind_vs(vs_f vs, int n_attr_out)
  186. {
  187. g_pipe.vs = vs;
  188. g_pipe.n_attr_out = n_attr_out;
  189. }
  190. /**************
  191. * sr_bind_fs *
  192. **************/
  193. /* sets the fragment shader */
  194. extern void
  195. sr_bind_fs(fs_f fs)
  196. {
  197. g_pipe.fs = fs;
  198. }
  199. /*******************
  200. * sr_bind_texture *
  201. *******************/
  202. /* binds a texture to pipeline */
  203. extern void
  204. sr_bind_texture(uint32_t* colors, int width, int height)
  205. {
  206. g_uniform.has_texture = 1;
  207. g_texture.colors = colors;
  208. g_texture.width = width;
  209. g_texture.height = height;
  210. }
  211. /*********************************************************************
  212. * *
  213. * light slot *
  214. * *
  215. *********************************************************************/
  216. /************
  217. * sr_light *
  218. ************/
  219. /* binds a light to pipeline */
  220. extern void
  221. sr_light(enum sr_light slot, enum sr_light_attr attr, float* data)
  222. {
  223. /* split attribute data */
  224. switch(attr) {
  225. case SR_POSITION:
  226. memcpy(g_lights[slot].pos, data, 3 * sizeof(float));
  227. break;
  228. case SR_DIRECTION:
  229. memcpy(g_lights[slot].dir, data, 3 * sizeof(float));
  230. break;
  231. case SR_COLOR:
  232. memcpy(g_lights[slot].color, data, 4 * sizeof(float));
  233. break;
  234. case SR_SPOT_ANGLE:
  235. g_lights[slot].spot_angle = *data;
  236. break;
  237. case SR_SPOT_PENUMBRA:
  238. g_lights[slot].spot_penumbra = *data;
  239. break;
  240. case SR_CONSTANT_ATTENUATION:
  241. g_lights[slot].attn_const = *data;
  242. break;
  243. case SR_LINEAR_ATTENUATION:
  244. g_lights[slot].attn_lin = *data;
  245. break;
  246. case SR_QUADRATIC_ATTENUATION:
  247. g_lights[slot].attn_quad = *data;
  248. break;
  249. default:
  250. return;
  251. }
  252. }
  253. /*************
  254. * sr_glight *
  255. *************/
  256. /* binds global light data to uniform */
  257. extern void
  258. sr_glight(enum sr_light_attr attr, float* data)
  259. {
  260. /* split attribute data */
  261. switch(attr) {
  262. case SR_AMBIENT:
  263. g_uniform.ka = *data;
  264. break;
  265. case SR_DIFFUSE:
  266. g_uniform.kd = *data;
  267. break;
  268. case SR_SPECULAR:
  269. g_uniform.ks = *data;
  270. break;
  271. default:
  272. return;
  273. }
  274. }
  275. /*****************
  276. * sr_light_type *
  277. *****************/
  278. /* binds light type to slot */
  279. extern void
  280. sr_light_type(enum sr_light slot, enum sr_light_type type)
  281. {
  282. int idx = split_light(slot);
  283. switch (type) {
  284. case SR_DIRECTIONAL:
  285. g_lights[idx].type = 1 << 0;
  286. break;
  287. case SR_POINT:
  288. g_lights[idx].type = 1 << 1;
  289. break;
  290. case SR_SPOT:
  291. g_lights[idx].type = 1 << 2;
  292. break;
  293. }
  294. }
  295. /*******************
  296. * sr_light_enable *
  297. *******************/
  298. /* enables light at specified slot */
  299. extern void
  300. sr_light_enable(enum sr_light slot)
  301. {
  302. g_uniform.light_state |= 1 << slot;
  303. }
  304. /********************
  305. * sr_light_disable *
  306. ********************/
  307. /* disables light at specified slot */
  308. extern void
  309. sr_light_disable(enum sr_light slot)
  310. {
  311. g_uniform.light_state &= ~(1 << slot);
  312. }
  313. /***************
  314. * sr_material *
  315. ***************/
  316. /* binds a material to pipeline */
  317. extern void
  318. sr_material(enum sr_light_attr attr, float* data)
  319. {
  320. switch(attr) {
  321. case SR_AMBIENT:
  322. memcpy(g_material.ambient, data, 4 * sizeof(float));
  323. break;
  324. case SR_DIFFUSE:
  325. memcpy(g_material.diffuse, data, 4 * sizeof(float));
  326. break;
  327. case SR_SPECULAR:
  328. memcpy(g_material.specular, data, 4 * sizeof(float));
  329. break;
  330. case SR_BLEND:
  331. g_material.blend = *data;
  332. break;
  333. case SR_SHININESS:
  334. g_material.shininess = *data;
  335. break;
  336. default:
  337. return;
  338. }
  339. }
  340. /*********************************************************************
  341. * *
  342. * matrix stack operations *
  343. * *
  344. *********************************************************************/
  345. /******************
  346. * sr_matrix_mode *
  347. ******************/
  348. /* sets current matrix stack */
  349. extern void
  350. sr_matrix_mode(enum sr_matrix_mode mode)
  351. {
  352. switch (mode) {
  353. case SR_MODEL_MATRIX:
  354. cur_mat = &model;
  355. break;
  356. case SR_VIEW_MATRIX:
  357. cur_mat = &view;
  358. break;
  359. case SR_PROJECTION_MATRIX:
  360. cur_mat = &proj;
  361. break;
  362. case SR_MVP_MATRIX:
  363. cur_mat = &mvp;
  364. break;
  365. }
  366. }
  367. /***************
  368. * sr_dump_mat *
  369. ***************/
  370. /* dumps contents of current matrix to given buffer in row major order */
  371. extern void
  372. sr_dump_matrix(float* dest)
  373. {
  374. dest[0] = cur_mat->e00;
  375. dest[1] = cur_mat->e01;
  376. dest[2] = cur_mat->e02;
  377. dest[3] = cur_mat->e03;
  378. dest[4] = cur_mat->e10;
  379. dest[5] = cur_mat->e11;
  380. dest[6] = cur_mat->e12;
  381. dest[7] = cur_mat->e13;
  382. dest[8] = cur_mat->e20;
  383. dest[9] = cur_mat->e21;
  384. dest[10] = cur_mat->e22;
  385. dest[11] = cur_mat->e23;
  386. dest[12] = cur_mat->e30;
  387. dest[13] = cur_mat->e31;
  388. dest[14] = cur_mat->e32;
  389. dest[15] = cur_mat->e33;
  390. }
  391. /******************
  392. * sr_load_matrix *
  393. ******************/
  394. /* loads the entries in a 16 length row major float array to current matrix */
  395. extern void
  396. sr_load_matrix(float* src)
  397. {
  398. cur_mat->e00 = src[0];
  399. cur_mat->e01 = src[1];
  400. cur_mat->e02 = src[2];
  401. cur_mat->e03 = src[3];
  402. cur_mat->e10 = src[4];
  403. cur_mat->e11 = src[5];
  404. cur_mat->e12 = src[6];
  405. cur_mat->e13 = src[7];
  406. cur_mat->e20 = src[8];
  407. cur_mat->e21 = src[9];
  408. cur_mat->e22 = src[10];
  409. cur_mat->e23 = src[11];
  410. cur_mat->e30 = src[12];
  411. cur_mat->e31 = src[13];
  412. cur_mat->e32 = src[14];
  413. cur_mat->e33 = src[15];
  414. }
  415. /********************
  416. * sr_load_identity *
  417. ********************/
  418. /* sets current matrix to the identity */
  419. extern void
  420. sr_load_identity()
  421. {
  422. *cur_mat = identity;
  423. }
  424. /*********************************************************************
  425. * *
  426. * model *
  427. * *
  428. *********************************************************************/
  429. /****************
  430. * sr_translate *
  431. ****************/
  432. /* pushes an affine transformation with translation of x, y, z */
  433. extern void
  434. sr_translate(float x, float y, float z)
  435. {
  436. struct mat4 t = {
  437. 1, 0, 0, x,
  438. 0, 1, 0, y,
  439. 0, 0, 1, z,
  440. 0, 0, 0, 1
  441. };
  442. matmul(cur_mat, &t);
  443. }
  444. /***************
  445. * sr_rotate_x *
  446. ***************/
  447. /* pushes a matrix rotating about the x axis by t radians */
  448. extern void
  449. sr_rotate_x(float t)
  450. {
  451. float c = cos(t);
  452. float s = sin(t);
  453. struct mat4 x = {
  454. 1, 0, 0, 0,
  455. 0, c, -s, 0,
  456. 0, s, c, 0,
  457. 0, 0, 0, 1
  458. };
  459. matmul(cur_mat, &x);
  460. }
  461. /***************
  462. * sr_rotate_y *
  463. ***************/
  464. /* pushes a matrix rotating about the y axis by t radians */
  465. void
  466. sr_rotate_y(float t)
  467. {
  468. float c = cos(t);
  469. float s = sin(t);
  470. struct mat4 y = {
  471. c, 0, s, 0,
  472. 0, 1, 0, 0,
  473. -s, 0, c, 0,
  474. 0, 0, 0, 1
  475. };
  476. matmul(cur_mat, &y);
  477. }
  478. /***************
  479. * sr_rotate_z *
  480. ***************/
  481. /* pushes a matrix rotating about the z axis by t radians */
  482. void
  483. sr_rotate_z(float t)
  484. {
  485. float c = cos(t);
  486. float s = sin(t);
  487. struct mat4 z = {
  488. c, -s, 0, 0,
  489. s, c, 0, 0,
  490. 0, 0, 1, 0,
  491. 0, 0, 0, 1
  492. };
  493. matmul(cur_mat, &z);
  494. }
  495. /************
  496. * sr_scale *
  497. ************/
  498. /* pushes a scale matrix by sx, sy, sz */
  499. void
  500. sr_scale(float sx, float sy, float sz)
  501. {
  502. struct mat4 s = {
  503. sx, 0, 0, 0,
  504. 0, sy, 0, 0,
  505. 0, 0, sz, 0,
  506. 0, 0, 0, 1
  507. };
  508. matmul(cur_mat, &s);
  509. }
  510. /*********************************************************************
  511. * *
  512. * view *
  513. * *
  514. *********************************************************************/
  515. /**************
  516. * sr_look_at *
  517. **************/
  518. /**
  519. * constructs a view matrix from three vectors :
  520. * the eye vector, camera position in world space
  521. * the target vector, the position of view target in world space
  522. * the up vector, pointing to whats generally above the camera
  523. */
  524. void
  525. sr_look_at(float ex, float ey, float ez,
  526. float lx, float ly, float lz,
  527. float ux, float uy, float uz)
  528. {
  529. /* eye vector */
  530. float eye[3] = {
  531. ex, ey, ez
  532. };
  533. /* look vector */
  534. float look[3] = {
  535. lx, ly, lz
  536. };
  537. /* up vector */
  538. float up[3] = {
  539. ux, uy, uz
  540. };
  541. /* backward vector, w */
  542. float w[3];
  543. vec3_sub(w, eye, look);
  544. normalize(w);
  545. /* side vector, u */
  546. float u[3];
  547. cross(u, up, w);
  548. normalize(u);
  549. /* new up vector, v */
  550. float v[3];
  551. float up_proj_w[3]; /* up projected onto w */
  552. vec3_scale(up_proj_w, w, dot(up, w));
  553. vec3_sub(v, up, up_proj_w);
  554. normalize(v);
  555. struct mat4 m = {
  556. u[0], u[1], u[2], 0,
  557. v[0], v[1], v[2], 0,
  558. w[0], w[1], w[2], 0,
  559. 0, 0, 0, 1
  560. };
  561. matmul(cur_mat, &m);
  562. sr_translate(-ex, -ey, -ez);
  563. }
  564. /*********************************************************************
  565. * *
  566. * projection *
  567. * *
  568. *********************************************************************/
  569. /******************
  570. * sr_perspective *
  571. ******************/
  572. /* pushes a perspective matrix specified by fov */
  573. void
  574. sr_perspective(float fovy, float aspect, float near, float far)
  575. {
  576. float f = 1 / (tan(fovy / 2));
  577. float e22 = (far + near) / (near - far);
  578. float e23 = (2 * far * near) / (near - far);
  579. float a = aspect;
  580. struct mat4 p = {
  581. f/a, 0, 0, 0,
  582. 0, f, 0, 0,
  583. 0, 0, e22, e23,
  584. 0, 0, -1, 0
  585. };
  586. matmul(cur_mat, &p);
  587. }
  588. /**************
  589. * sr_frustum *
  590. **************/
  591. /* pushes a projection matrix based on frustum */
  592. void
  593. sr_frustum(float left, float right, float bottom,
  594. float top, float near, float far)
  595. {
  596. float e00 = (2 * near) / (right - left);
  597. float e11 = (2 * near) / (top - bottom);
  598. float e02 = (right + left) / (right - left);
  599. float e12 = (top + bottom) / (top - bottom);
  600. float e22 = -(far + near) / (near - far);
  601. float e23 = -(2 * far * near) / (near - far);
  602. struct mat4 p = {
  603. e00, 0, e02, 0,
  604. 0, e11, e12, 0,
  605. 0, 0, e22, e23,
  606. 0, 0, -1, 0
  607. };
  608. matmul(cur_mat, &p);
  609. }