karl2d.odin 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. package karl2d
  2. import "base:runtime"
  3. import "core:mem"
  4. import "core:log"
  5. import "core:math"
  6. import "core:math/linalg"
  7. import "core:slice"
  8. import "core:strings"
  9. import "core:image"
  10. import "core:image/bmp"
  11. import "core:image/png"
  12. import "core:image/tga"
  13. import hm "handle_map"
  14. _ :: bmp
  15. _ :: png
  16. _ :: tga
  17. Handle :: hm.Handle
  18. Texture_Handle :: distinct Handle
  19. TEXTURE_NONE :: Texture_Handle {}
  20. // Opens a window and initializes some internal state. The internal state will use `allocator` for
  21. // all dynamically allocated memory. The return value can be ignored unless you need to later call
  22. // `set_state`.
  23. init :: proc(window_width: int, window_height: int, window_title: string,
  24. allocator := context.allocator, loc := #caller_location) -> ^State {
  25. s = new(State, allocator, loc)
  26. s.allocator = allocator
  27. s.custom_context = context
  28. s.width = window_width
  29. s.height = window_height
  30. s.win = WINDOW_INTERFACE_WIN32
  31. win = s.win
  32. window_state_alloc_error: runtime.Allocator_Error
  33. s.window_state, window_state_alloc_error = mem.alloc(win.state_size())
  34. log.assertf(window_state_alloc_error == nil, "Failed allocating memory for window state: %v", window_state_alloc_error)
  35. win.init(s.window_state, window_width, window_height, window_title, allocator)
  36. s.window = win.window_handle()
  37. s.rb = BACKEND_D3D11
  38. rb = s.rb
  39. rb_alloc_error: runtime.Allocator_Error
  40. s.rb_state, rb_alloc_error = mem.alloc(rb.state_size())
  41. log.assertf(rb_alloc_error == nil, "Failed allocating memory for rendering backend: %v", rb_alloc_error)
  42. s.proj_matrix = make_default_projection(window_width, window_height)
  43. s.view_matrix = 1
  44. rb.init(s.rb_state, s.window, window_width, window_height, allocator)
  45. s.vertex_buffer_cpu = make([]u8, VERTEX_BUFFER_MAX, allocator, loc)
  46. white_rect: [16*16*4]u8
  47. slice.fill(white_rect[:], 255)
  48. s.shape_drawing_texture = rb.load_texture(white_rect[:], 16, 16)
  49. s.default_shader = load_shader(string(DEFAULT_SHADER_SOURCE))
  50. return s
  51. }
  52. VERTEX_BUFFER_MAX :: 1000000
  53. make_default_projection :: proc(w, h: int) -> matrix[4,4]f32 {
  54. return linalg.matrix_ortho3d_f32(0, f32(w), f32(h), 0, 0.001, 2)
  55. }
  56. DEFAULT_SHADER_SOURCE :: #load("shader.hlsl")
  57. // Closes the window and cleans up the internal state.
  58. shutdown :: proc() {
  59. rb.destroy_texture(s.shape_drawing_texture)
  60. destroy_shader(s.default_shader)
  61. rb.shutdown()
  62. delete(s.vertex_buffer_cpu, s.allocator)
  63. win.shutdown()
  64. a := s.allocator
  65. free(s.window_state, a)
  66. free(s.rb_state, a)
  67. free(s, a)
  68. s = nil
  69. }
  70. // Clear the backbuffer with supplied color.
  71. clear :: proc(color: Color) {
  72. rb.clear(color)
  73. }
  74. // Present the backbuffer. Call at end of frame to make everything you've drawn appear on the screen.
  75. present :: proc() {
  76. draw_current_batch()
  77. rb.present()
  78. }
  79. // Call at start or end of frame to process all events that have arrived to the window.
  80. //
  81. // WARNING: Not calling this will make your program impossible to interact with.
  82. process_events :: proc() {
  83. s.keys_went_up = {}
  84. s.keys_went_down = {}
  85. s.mouse_delta = {}
  86. s.mouse_wheel_delta = 0
  87. win.process_events()
  88. events := win.get_events()
  89. for &event in events {
  90. switch &e in event {
  91. case Window_Event_Close_Wanted:
  92. s.shutdown_wanted = true
  93. case Window_Event_Key_Went_Down:
  94. s.keys_went_down[e.key] = true
  95. s.keys_is_held[e.key] = true
  96. case Window_Event_Key_Went_Up:
  97. s.keys_is_held[e.key] = false
  98. s.keys_went_up[e.key] = true
  99. case Window_Event_Mouse_Move:
  100. prev_pos := s.mouse_position
  101. s.mouse_position = e.position
  102. s.mouse_delta = prev_pos - s.mouse_position
  103. case Window_Event_Mouse_Wheel:
  104. s.mouse_wheel_delta = e.delta
  105. }
  106. }
  107. win.clear_events()
  108. }
  109. /* Flushes the current batch. This sends off everything to the GPU that has been queued in the
  110. current batch. Normally, you do not need to do this manually. It is done automatically when these
  111. procedures run:
  112. present
  113. set_camera
  114. set_shader
  115. TODO: complete this list and motivate why it needs to happen on those procs (or do that in the
  116. docs for those procs).
  117. */
  118. draw_current_batch :: proc() {
  119. shader := s.batch_shader.? or_else s.default_shader
  120. rb.draw(shader, s.batch_texture, s.proj_matrix * s.view_matrix, s.vertex_buffer_cpu[:s.vertex_buffer_cpu_used])
  121. s.vertex_buffer_cpu_used = 0
  122. }
  123. // Can be used to restore the internal state using the pointer returned by `init`. Useful after
  124. // reloading the library (for example, when doing code hot reload).
  125. set_internal_state :: proc(state: ^State) {
  126. s = state
  127. rb = s.rb
  128. win = s.win
  129. rb.set_internal_state(s.rb_state)
  130. win.set_internal_state(s.window_state)
  131. }
  132. get_screen_width :: proc() -> int {
  133. return rb.get_swapchain_width()
  134. }
  135. get_screen_height :: proc() -> int {
  136. return rb.get_swapchain_height()
  137. }
  138. key_went_down :: proc(key: Keyboard_Key) -> bool {
  139. return s.keys_went_down[key]
  140. }
  141. key_went_up :: proc(key: Keyboard_Key) -> bool {
  142. return s.keys_went_up[key]
  143. }
  144. key_is_held :: proc(key: Keyboard_Key) -> bool {
  145. return s.keys_is_held[key]
  146. }
  147. shutdown_wanted :: proc() -> bool {
  148. return s.shutdown_wanted
  149. }
  150. set_window_position :: proc(x: int, y: int) {
  151. win.set_position(x, y)
  152. }
  153. set_window_size :: proc(width: int, height: int) {
  154. panic("Not implemented")
  155. }
  156. set_camera :: proc(camera: Maybe(Camera)) {
  157. if camera == s.batch_camera {
  158. return
  159. }
  160. draw_current_batch()
  161. s.batch_camera = camera
  162. s.proj_matrix = make_default_projection(s.width, s.height)
  163. if c, c_ok := camera.?; c_ok {
  164. origin_trans := linalg.matrix4_translate(vec3_from_vec2(-c.origin))
  165. translate := linalg.matrix4_translate(vec3_from_vec2(c.target))
  166. scale := linalg.matrix4_scale(Vec3{1/c.zoom, 1/c.zoom, 1})
  167. rot := linalg.matrix4_rotate_f32(c.rotation * math.RAD_PER_DEG, {0, 0, 1})
  168. camera_matrix := translate * scale * rot * origin_trans
  169. s.view_matrix = linalg.inverse(camera_matrix)
  170. } else {
  171. s.view_matrix = 1
  172. }
  173. }
  174. load_texture_from_file :: proc(filename: string) -> Texture {
  175. img, img_err := image.load_from_file(filename, options = {.alpha_add_if_missing}, allocator = context.temp_allocator)
  176. if img_err != nil {
  177. log.errorf("Error loading texture %v: %v", filename, img_err)
  178. return {}
  179. }
  180. backend_tex := rb.load_texture(img.pixels.buf[:], img.width, img.height)
  181. return {
  182. handle = backend_tex,
  183. width = img.width,
  184. height = img.height,
  185. }
  186. }
  187. destroy_texture :: proc(tex: Texture) {
  188. rb.destroy_texture(tex.handle)
  189. }
  190. draw_rect :: proc(r: Rect, c: Color) {
  191. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
  192. draw_current_batch()
  193. }
  194. s.batch_texture = s.shape_drawing_texture
  195. _batch_vertex({r.x, r.y}, {0, 0}, c)
  196. _batch_vertex({r.x + r.w, r.y}, {1, 0}, c)
  197. _batch_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
  198. _batch_vertex({r.x, r.y}, {0, 0}, c)
  199. _batch_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
  200. _batch_vertex({r.x, r.y + r.h}, {0, 1}, c)
  201. }
  202. draw_rect_ex :: proc(r: Rect, origin: Vec2, rot: f32, c: Color) {
  203. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
  204. draw_current_batch()
  205. }
  206. s.batch_texture = s.shape_drawing_texture
  207. tl, tr, bl, br: Vec2
  208. // Rotation adapted from Raylib's "DrawTexturePro"
  209. if rot == 0 {
  210. x := r.x - origin.x
  211. y := r.y - origin.y
  212. tl = { x, y }
  213. tr = { x + r.w, y }
  214. bl = { x, y + r.h }
  215. br = { x + r.w, y + r.h }
  216. } else {
  217. sin_rot := math.sin(rot * math.RAD_PER_DEG)
  218. cos_rot := math.cos(rot * math.RAD_PER_DEG)
  219. x := r.x
  220. y := r.y
  221. dx := -origin.x
  222. dy := -origin.y
  223. tl = {
  224. x + dx * cos_rot - dy * sin_rot,
  225. y + dx * sin_rot + dy * cos_rot,
  226. }
  227. tr = {
  228. x + (dx + r.w) * cos_rot - dy * sin_rot,
  229. y + (dx + r.w) * sin_rot + dy * cos_rot,
  230. }
  231. bl = {
  232. x + dx * cos_rot - (dy + r.h) * sin_rot,
  233. y + dx * sin_rot + (dy + r.h) * cos_rot,
  234. }
  235. br = {
  236. x + (dx + r.w) * cos_rot - (dy + r.h) * sin_rot,
  237. y + (dx + r.w) * sin_rot + (dy + r.h) * cos_rot,
  238. }
  239. }
  240. _batch_vertex(tl, {0, 0}, c)
  241. _batch_vertex(tr, {1, 0}, c)
  242. _batch_vertex(br, {1, 1}, c)
  243. _batch_vertex(tl, {0, 0}, c)
  244. _batch_vertex(br, {1, 1}, c)
  245. _batch_vertex(bl, {0, 1}, c)
  246. }
  247. draw_rect_outline :: proc(r: Rect, thickness: f32, color: Color) {
  248. t := thickness
  249. // Based on DrawRectangleLinesEx from Raylib
  250. top := Rect {
  251. r.x,
  252. r.y,
  253. r.w,
  254. t,
  255. }
  256. bottom := Rect {
  257. r.x,
  258. r.y + r.h - t,
  259. r.w,
  260. t,
  261. }
  262. left := Rect {
  263. r.x,
  264. r.y + t,
  265. t,
  266. r.h - t * 2,
  267. }
  268. right := Rect {
  269. r.x + r.w - t,
  270. r.y + t,
  271. t,
  272. r.h - t * 2,
  273. }
  274. draw_rect(top, color)
  275. draw_rect(bottom, color)
  276. draw_rect(left, color)
  277. draw_rect(right, color)
  278. }
  279. draw_circle :: proc(center: Vec2, radius: f32, color: Color, segments := 16) {
  280. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
  281. draw_current_batch()
  282. }
  283. s.batch_texture = s.shape_drawing_texture
  284. prev := center + {radius, 0}
  285. for s in 1..=segments {
  286. sr := (f32(s)/f32(segments)) * 2*math.PI
  287. rot := linalg.matrix2_rotate(sr)
  288. p := center + rot * Vec2{radius, 0}
  289. _batch_vertex(prev, {0, 0}, color)
  290. _batch_vertex(p, {1, 0}, color)
  291. _batch_vertex(center, {1, 1}, color)
  292. prev = p
  293. }
  294. }
  295. draw_line :: proc(start: Vec2, end: Vec2, thickness: f32, color: Color) {
  296. p := Vec2{start.x, start.y + thickness*0.5}
  297. s := Vec2{linalg.length(end - start), thickness}
  298. origin := Vec2 {0, thickness*0.5}
  299. r := Rect {p.x, p.y, s.x, s.y}
  300. rot := math.atan2(end.y - start.y, end.x - start.x)
  301. draw_rect_ex(r, origin, rot * math.DEG_PER_RAD, color)
  302. }
  303. draw_texture :: proc(tex: Texture, pos: Vec2, tint := WHITE) {
  304. draw_texture_ex(
  305. tex,
  306. {0, 0, f32(tex.width), f32(tex.height)},
  307. {pos.x, pos.y, f32(tex.width), f32(tex.height)},
  308. {},
  309. 0,
  310. tint,
  311. )
  312. }
  313. draw_texture_rect :: proc(tex: Texture, rect: Rect, pos: Vec2, tint := WHITE) {
  314. draw_texture_ex(
  315. tex,
  316. rect,
  317. {pos.x, pos.y, rect.w, rect.h},
  318. {},
  319. 0,
  320. tint,
  321. )
  322. }
  323. draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotation: f32, tint := WHITE) {
  324. if tex.width == 0 || tex.height == 0 {
  325. return
  326. }
  327. if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.handle {
  328. draw_current_batch()
  329. }
  330. flip_x, flip_y: bool
  331. src := src
  332. dst := dst
  333. if src.w < 0 {
  334. flip_x = true
  335. src.w = -src.w
  336. }
  337. if src.h < 0 {
  338. flip_y = true
  339. src.h = -src.h
  340. }
  341. if dst.w < 0 {
  342. dst.w *= -1
  343. }
  344. if dst.h < 0 {
  345. dst.h *= -1
  346. }
  347. s.batch_texture = tex.handle
  348. tl, tr, bl, br: Vec2
  349. // Rotation adapted from Raylib's "DrawTexturePro"
  350. if rotation == 0 {
  351. x := dst.x - origin.x
  352. y := dst.y - origin.y
  353. tl = { x, y }
  354. tr = { x + dst.w, y }
  355. bl = { x, y + dst.h }
  356. br = { x + dst.w, y + dst.h }
  357. } else {
  358. sin_rot := math.sin(rotation * math.RAD_PER_DEG)
  359. cos_rot := math.cos(rotation * math.RAD_PER_DEG)
  360. x := dst.x
  361. y := dst.y
  362. dx := -origin.x
  363. dy := -origin.y
  364. tl = {
  365. x + dx * cos_rot - dy * sin_rot,
  366. y + dx * sin_rot + dy * cos_rot,
  367. }
  368. tr = {
  369. x + (dx + dst.w) * cos_rot - dy * sin_rot,
  370. y + (dx + dst.w) * sin_rot + dy * cos_rot,
  371. }
  372. bl = {
  373. x + dx * cos_rot - (dy + dst.h) * sin_rot,
  374. y + dx * sin_rot + (dy + dst.h) * cos_rot,
  375. }
  376. br = {
  377. x + (dx + dst.w) * cos_rot - (dy + dst.h) * sin_rot,
  378. y + (dx + dst.w) * sin_rot + (dy + dst.h) * cos_rot,
  379. }
  380. }
  381. ts := Vec2{f32(tex.width), f32(tex.height)}
  382. up := Vec2{src.x, src.y} / ts
  383. us := Vec2{src.w, src.h} / ts
  384. c := tint
  385. uv0 := up
  386. uv1 := up + {us.x, 0}
  387. uv2 := up + us
  388. uv3 := up
  389. uv4 := up + us
  390. uv5 := up + {0, us.y}
  391. if flip_x {
  392. uv0.x += us.x
  393. uv1.x -= us.x
  394. uv2.x -= us.x
  395. uv3.x += us.x
  396. uv4.x -= us.x
  397. uv5.x += us.x
  398. }
  399. if flip_y {
  400. uv0.y += us.y
  401. uv1.y += us.y
  402. uv2.y -= us.y
  403. uv3.y += us.y
  404. uv4.y -= us.y
  405. uv5.y -= us.y
  406. }
  407. _batch_vertex(tl, uv0, c)
  408. _batch_vertex(tr, uv1, c)
  409. _batch_vertex(br, uv2, c)
  410. _batch_vertex(tl, uv3, c)
  411. _batch_vertex(br, uv4, c)
  412. _batch_vertex(bl, uv5, c)
  413. }
  414. load_shader :: proc(shader_source: string, layout_formats: []Shader_Input_Format = {}) -> Shader {
  415. handle, desc := rb.load_shader(shader_source, context.temp_allocator, layout_formats)
  416. if handle == SHADER_NONE {
  417. log.error("Failed loading shader")
  418. return {}
  419. }
  420. shd := Shader {
  421. handle = handle,
  422. constant_buffers = make([]Shader_Constant_Buffer, len(desc.constant_buffers), s.allocator),
  423. constant_lookup = make(map[string]Shader_Constant_Location, s.allocator),
  424. inputs = slice.clone(desc.inputs, s.allocator),
  425. input_overrides = make([]Shader_Input_Value_Override, len(desc.inputs), s.allocator),
  426. }
  427. for &input in shd.inputs {
  428. input.name = strings.clone(input.name, s.allocator)
  429. }
  430. for cb_idx in 0..<len(desc.constant_buffers) {
  431. cb_desc := &desc.constant_buffers[cb_idx]
  432. shd.constant_buffers[cb_idx] = {
  433. cpu_data = make([]u8, desc.constant_buffers[cb_idx].size, s.allocator),
  434. }
  435. for &v in cb_desc.variables {
  436. if v.name == "" {
  437. continue
  438. }
  439. shd.constant_lookup[strings.clone(v.name, s.allocator)] = v.loc
  440. switch v.name {
  441. case "mvp":
  442. shd.constant_builtin_locations[.MVP] = v.loc
  443. }
  444. }
  445. }
  446. for &d in shd.default_input_offsets {
  447. d = -1
  448. }
  449. input_offset: int
  450. for &input in shd.inputs {
  451. default_format := get_shader_input_default_type(input.name, input.type)
  452. if default_format != .Unknown {
  453. shd.default_input_offsets[default_format] = input_offset
  454. }
  455. input_offset += shader_input_format_size(input.format)
  456. }
  457. shd.vertex_size = input_offset
  458. return shd
  459. }
  460. get_shader_input_default_type :: proc(name: string, type: Shader_Input_Type) -> Shader_Default_Inputs {
  461. if name == "POS" && type == .Vec2 {
  462. return .Position
  463. } else if name == "UV" && type == .Vec2 {
  464. return .UV
  465. } else if name == "COL" && type == .Vec4 {
  466. return .Color
  467. }
  468. return .Unknown
  469. }
  470. get_shader_input_format :: proc(name: string, type: Shader_Input_Type) -> Shader_Input_Format {
  471. default_type := get_shader_input_default_type(name, type)
  472. if default_type != .Unknown {
  473. switch default_type {
  474. case .Position: return .RG32_Float
  475. case .UV: return .RG32_Float
  476. case .Color: return .RGBA8_Norm
  477. case .Unknown: unreachable()
  478. }
  479. }
  480. switch type {
  481. case .F32: return .R32_Float
  482. case .Vec2: return .RG32_Float
  483. case .Vec3: return .RGB32_Float
  484. case .Vec4: return .RGBA32_Float
  485. }
  486. return .Unknown
  487. }
  488. destroy_shader :: proc(shader: Shader) {
  489. rb.destroy_shader(shader.handle)
  490. for c in shader.constant_buffers {
  491. delete(c.cpu_data)
  492. }
  493. delete(shader.constant_buffers)
  494. for k, _ in shader.constant_lookup {
  495. delete(k)
  496. }
  497. delete(shader.constant_lookup)
  498. for i in shader.inputs {
  499. delete(i.name)
  500. }
  501. delete(shader.inputs)
  502. delete(shader.input_overrides)
  503. }
  504. set_shader :: proc(shader: Maybe(Shader)) {
  505. if maybe_handle_equal(shader, s.batch_shader) {
  506. return
  507. }
  508. draw_current_batch()
  509. s.batch_shader = shader
  510. }
  511. maybe_handle_equal :: proc(m1: Maybe($T), m2: Maybe(T)) -> bool {
  512. if m1 == nil && m2 == nil {
  513. return true
  514. }
  515. m1v, m1v_ok := m1.?
  516. m2v, m2v_ok := m2.?
  517. if !m1v_ok || !m2v_ok {
  518. return false
  519. }
  520. return m1v.handle == m2v.handle
  521. }
  522. set_shader_constant :: proc(shd: Shader, loc: Shader_Constant_Location, val: $T) {
  523. draw_current_batch()
  524. if int(loc.buffer_idx) >= len(shd.constant_buffers) {
  525. log.warnf("Constant buffer idx %v is out of bounds", loc.buffer_idx)
  526. return
  527. }
  528. b := &shd.constant_buffers[loc.buffer_idx]
  529. if int(loc.offset) + size_of(val) > len(b.cpu_data) {
  530. log.warnf("Constant buffer idx %v is trying to be written out of bounds by at offset %v with %v bytes", loc.buffer_idx, loc.offset, size_of(val))
  531. return
  532. }
  533. dst := (^T)(&b.cpu_data[loc.offset])
  534. dst^ = val
  535. }
  536. set_shader_constant_mat4 :: proc(shader: Shader, loc: Shader_Constant_Location, val: matrix[4,4]f32) {
  537. set_shader_constant(shader, loc, val)
  538. }
  539. set_shader_constant_f32 :: proc(shader: Shader, loc: Shader_Constant_Location, val: f32) {
  540. set_shader_constant(shader, loc, val)
  541. }
  542. set_shader_constant_vec2 :: proc(shader: Shader, loc: Shader_Constant_Location, val: Vec2) {
  543. set_shader_constant(shader, loc, val)
  544. }
  545. get_default_shader :: proc() -> Shader {
  546. return s.default_shader
  547. }
  548. set_scissor_rect :: proc(scissor_rect: Maybe(Rect)) {
  549. panic("not implemented")
  550. }
  551. screen_to_world :: proc(pos: Vec2, camera: Camera) -> Vec2 {
  552. panic("not implemented")
  553. }
  554. draw_text :: proc(text: string, pos: Vec2, font_size: f32, color: Color) {
  555. }
  556. mouse_button_went_down :: proc(button: Mouse_Button) -> bool {
  557. panic("not implemented")
  558. }
  559. mouse_button_went_up :: proc(button: Mouse_Button) -> bool {
  560. panic("not implemented")
  561. }
  562. mouse_button_is_held :: proc(button: Mouse_Button) -> bool {
  563. panic("not implemented")
  564. }
  565. get_mouse_wheel_delta :: proc() -> f32 {
  566. return s.mouse_wheel_delta
  567. }
  568. get_mouse_position :: proc() -> Vec2 {
  569. return s.mouse_position
  570. }
  571. _batch_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
  572. v := v
  573. if s.vertex_buffer_cpu_used == len(s.vertex_buffer_cpu) {
  574. panic("Must dispatch here")
  575. }
  576. shd := s.batch_shader.? or_else s.default_shader
  577. base_offset := s.vertex_buffer_cpu_used
  578. pos_offset := shd.default_input_offsets[.Position]
  579. uv_offset := shd.default_input_offsets[.UV]
  580. color_offset := shd.default_input_offsets[.Color]
  581. mem.set(&s.vertex_buffer_cpu[base_offset], 0, shd.vertex_size)
  582. if pos_offset != -1 {
  583. (^Vec2)(&s.vertex_buffer_cpu[base_offset + pos_offset])^ = {v.x, v.y}
  584. }
  585. if uv_offset != -1 {
  586. (^Vec2)(&s.vertex_buffer_cpu[base_offset + uv_offset])^ = uv
  587. }
  588. if color_offset != -1 {
  589. (^Color)(&s.vertex_buffer_cpu[base_offset + color_offset])^ = color
  590. }
  591. override_offset: int
  592. for &o, idx in shd.input_overrides {
  593. input := &shd.inputs[idx]
  594. sz := shader_input_format_size(input.format)
  595. if o.used != 0 {
  596. mem.copy(&s.vertex_buffer_cpu[base_offset + override_offset], raw_data(&o.val), o.used)
  597. }
  598. override_offset += sz
  599. }
  600. s.vertex_buffer_cpu_used += shd.vertex_size
  601. }
  602. shader_input_format_size :: proc(f: Shader_Input_Format) -> int {
  603. switch f {
  604. case .Unknown: return 0
  605. case .RGBA32_Float: return 32
  606. case .RGBA8_Norm: return 4
  607. case .RGBA8_Norm_SRGB: return 4
  608. case .RGB32_Float: return 12
  609. case .RG32_Float: return 8
  610. case .R32_Float: return 4
  611. }
  612. return 0
  613. }
  614. State :: struct {
  615. allocator: runtime.Allocator,
  616. custom_context: runtime.Context,
  617. win: Window_Interface,
  618. window_state: rawptr,
  619. rb: Rendering_Backend_Interface,
  620. rb_state: rawptr,
  621. shutdown_wanted: bool,
  622. mouse_position: Vec2,
  623. mouse_delta: Vec2,
  624. mouse_wheel_delta: f32,
  625. keys_went_down: #sparse [Keyboard_Key]bool,
  626. keys_went_up: #sparse [Keyboard_Key]bool,
  627. keys_is_held: #sparse [Keyboard_Key]bool,
  628. window: Window_Handle,
  629. width: int,
  630. height: int,
  631. shape_drawing_texture: Texture_Handle,
  632. batch_camera: Maybe(Camera),
  633. batch_shader: Maybe(Shader),
  634. batch_texture: Texture_Handle,
  635. view_matrix: Mat4,
  636. proj_matrix: Mat4,
  637. vertex_buffer_cpu: []u8,
  638. vertex_buffer_cpu_used: int,
  639. default_shader: Shader,
  640. }
  641. @(private="file")
  642. s: ^State
  643. win: Window_Interface
  644. rb: Rendering_Backend_Interface
  645. Shader_Input_Format :: enum {
  646. Unknown,
  647. RGBA32_Float,
  648. RGBA8_Norm,
  649. RGBA8_Norm_SRGB,
  650. RGB32_Float,
  651. RG32_Float,
  652. R32_Float,
  653. }
  654. Color :: [4]u8
  655. Vec2 :: [2]f32
  656. Vec3 :: [3]f32
  657. Mat4 :: matrix[4,4]f32
  658. Vec2i :: [2]int
  659. Rect :: struct {
  660. x, y: f32,
  661. w, h: f32,
  662. }
  663. Texture :: struct {
  664. handle: Texture_Handle,
  665. width: int,
  666. height: int,
  667. }
  668. Shader_Constant_Buffer :: struct {
  669. cpu_data: []u8,
  670. }
  671. Shader :: struct {
  672. handle: Shader_Handle,
  673. constant_buffers: []Shader_Constant_Buffer,
  674. constant_lookup: map[string]Shader_Constant_Location,
  675. constant_builtin_locations: [Shader_Builtin_Constant]Maybe(Shader_Constant_Location),
  676. inputs: []Shader_Input,
  677. input_overrides: []Shader_Input_Value_Override,
  678. default_input_offsets: [Shader_Default_Inputs]int,
  679. vertex_size: int,
  680. }
  681. Shader_Input_Value_Override :: struct {
  682. val: [256]u8,
  683. used: int,
  684. }
  685. Shader_Input_Type :: enum {
  686. F32,
  687. Vec2,
  688. Vec3,
  689. Vec4,
  690. }
  691. Shader_Builtin_Constant :: enum {
  692. MVP,
  693. }
  694. Shader_Default_Inputs :: enum {
  695. Unknown,
  696. Position,
  697. UV,
  698. Color,
  699. }
  700. Shader_Input :: struct {
  701. name: string,
  702. register: int,
  703. type: Shader_Input_Type,
  704. format: Shader_Input_Format,
  705. }
  706. Shader_Constant_Location :: struct {
  707. buffer_idx: u32,
  708. offset: u32,
  709. }
  710. Camera :: struct {
  711. target: Vec2,
  712. origin: Vec2,
  713. rotation: f32,
  714. zoom: f32,
  715. }
  716. // Support for up to 255 mouse buttons. Cast an int to type `Mouse_Button` to use things outside the
  717. // options presented here.
  718. Mouse_Button :: enum {
  719. Left,
  720. Right,
  721. Middle,
  722. Max = 255,
  723. }
  724. // TODO: These are just copied from raylib, we probably want a list of our own "default colors"
  725. WHITE :: Color { 255, 255, 255, 255 }
  726. BLACK :: Color { 0, 0, 0, 255 }
  727. GRAY :: Color{ 130, 130, 130, 255 }
  728. RED :: Color { 230, 41, 55, 255 }
  729. YELLOW :: Color { 253, 249, 0, 255 }
  730. BLUE :: Color { 0, 121, 241, 255 }
  731. MAGENTA :: Color { 255, 0, 255, 255 }
  732. DARKGRAY :: Color{ 80, 80, 80, 255 }
  733. GREEN :: Color{ 0, 228, 48, 255 }
  734. Shader_Handle :: distinct Handle
  735. SHADER_NONE :: Shader_Handle {}
  736. // Based on Raylib / GLFW
  737. Keyboard_Key :: enum {
  738. None = 0,
  739. // Alphanumeric keys
  740. Apostrophe = 39,
  741. Comma = 44,
  742. Minus = 45,
  743. Period = 46,
  744. Slash = 47,
  745. Zero = 48,
  746. One = 49,
  747. Two = 50,
  748. Three = 51,
  749. Four = 52,
  750. Five = 53,
  751. Six = 54,
  752. Seven = 55,
  753. Eight = 56,
  754. Nine = 57,
  755. Semicolon = 59,
  756. Equal = 61,
  757. A = 65,
  758. B = 66,
  759. C = 67,
  760. D = 68,
  761. E = 69,
  762. F = 70,
  763. G = 71,
  764. H = 72,
  765. I = 73,
  766. J = 74,
  767. K = 75,
  768. L = 76,
  769. M = 77,
  770. N = 78,
  771. O = 79,
  772. P = 80,
  773. Q = 81,
  774. R = 82,
  775. S = 83,
  776. T = 84,
  777. U = 85,
  778. V = 86,
  779. W = 87,
  780. X = 88,
  781. Y = 89,
  782. Z = 90,
  783. Left_Bracket = 91,
  784. Backslash = 92,
  785. Right_Bracket = 93,
  786. Grave = 96,
  787. // Function keys
  788. Space = 32,
  789. Escape = 256,
  790. Enter = 257,
  791. Tab = 258,
  792. Backspace = 259,
  793. Insert = 260,
  794. Delete = 261,
  795. Right = 262,
  796. Left = 263,
  797. Down = 264,
  798. Up = 265,
  799. Page_Up = 266,
  800. Page_Down = 267,
  801. Home = 268,
  802. End = 269,
  803. Caps_Lock = 280,
  804. Scroll_Lock = 281,
  805. Num_Lock = 282,
  806. Print_Screen = 283,
  807. Pause = 284,
  808. F1 = 290,
  809. F2 = 291,
  810. F3 = 292,
  811. F4 = 293,
  812. F5 = 294,
  813. F6 = 295,
  814. F7 = 296,
  815. F8 = 297,
  816. F9 = 298,
  817. F10 = 299,
  818. F11 = 300,
  819. F12 = 301,
  820. Left_Shift = 340,
  821. Left_Control = 341,
  822. Left_Alt = 342,
  823. Left_Super = 343,
  824. Right_Shift = 344,
  825. Right_Control = 345,
  826. Right_Alt = 346,
  827. Right_Super = 347,
  828. Menu = 348,
  829. // Keypad keys
  830. KP_0 = 320,
  831. KP_1 = 321,
  832. KP_2 = 322,
  833. KP_3 = 323,
  834. KP_4 = 324,
  835. KP_5 = 325,
  836. KP_6 = 326,
  837. KP_7 = 327,
  838. KP_8 = 328,
  839. KP_9 = 329,
  840. KP_Decimal = 330,
  841. KP_Divide = 331,
  842. KP_Multiply = 332,
  843. KP_Subtract = 333,
  844. KP_Add = 334,
  845. KP_Enter = 335,
  846. KP_Equal = 336,
  847. }
  848. vec3_from_vec2 :: proc(v: Vec2) -> Vec3 {
  849. return {
  850. v.x, v.y, 0,
  851. }
  852. }
  853. create_vertex_input_override :: proc(val: $T) -> Shader_Input_Value_Override {
  854. assert(size_of(T) < 256)
  855. res: Shader_Input_Value_Override
  856. ((^T)(raw_data(&res.val)))^ = val
  857. res.used = size_of(T)
  858. return res
  859. }
  860. temp_cstring :: proc(str: string, loc := #caller_location) -> cstring {
  861. return strings.clone_to_cstring(str, context.temp_allocator, loc)
  862. }