Jelajahi Sumber

Merge branch 'master' of https://github.com/karl-zylinski/karl2d

Karl Zylinski 5 bulan lalu
induk
melakukan
f0a4e708e0

+ 100 - 0
examples/raylib_ports/bunnymark/bunnymark.odin

@@ -0,0 +1,100 @@
+// This is a port of https://www.raylib.com/examples/textures/loader.html?name=textures_bunnymark
+
+package karl2d_bunnymark
+
+import k2 "../../.."
+import "core:math/rand"
+import "core:log"
+import "core:fmt"
+import "core:time"
+
+MAX_BUNNIES :: 50000
+
+Bunny :: struct {
+	position: k2.Vec2,
+	speed: k2.Vec2,
+	rot: f32,
+	rot_speed: f32,
+	color: k2.Color,
+}
+
+main :: proc() {
+	context.logger = log.create_console_logger()
+
+	SCREEN_WIDTH :: 800
+	SCREEN_HEIGHT :: 450
+
+	k2.init(SCREEN_WIDTH, SCREEN_HEIGHT, "bunnymark (raylib port)", window_creation_flags = { .Resizable })
+
+	tex_bunny := k2.load_texture_from_file("wabbit_alpha.png")
+
+	bunnies: [dynamic]Bunny
+	prev_time := time.now()
+
+	for !k2.shutdown_wanted() {
+		cur_time := time.now()
+		dt := f32(time.duration_seconds(time.diff(prev_time, cur_time)))
+		prev_time = cur_time
+
+		if k2.mouse_button_is_held(.Left) {
+			for _ in 0..<100 {
+				append(&bunnies, Bunny {
+					position = k2.get_mouse_position(),
+					speed = {
+						rand.float32_range(-250, 250)/60,
+						rand.float32_range(-250, 250)/60,
+					},
+					rot_speed = rand.float32_range(-5, 5),
+					color = {
+						u8(rand.int_max(190) + 50),
+						u8(rand.int_max(160) + 80),
+						u8(rand.int_max(140) + 100),
+						255,
+					},
+				})
+			}
+		}
+
+		for &b in bunnies {
+			b.position += b.speed
+			b.rot += b.rot_speed
+
+			if b.position.x > f32(k2.get_screen_width()) || b.position.x < 0 {
+				b.speed.x *= -1
+				b.rot_speed = rand.float32_range(-5, 5)
+			}
+
+			if b.position.y > f32(k2.get_screen_height()) || b.position.y < 0 {
+				b.speed.y *= -1
+				b.rot_speed = rand.float32_range(-5, 5)
+			}
+		}
+
+		k2.process_events()
+		k2.clear(k2.RL_WHITE)
+
+		src := k2.Rect {
+			0, 0,
+			f32(tex_bunny.width), f32(tex_bunny.height),
+		}
+
+		for &b in bunnies {
+			dest := src
+			dest.x = b.position.x 
+			dest.y = b.position.y
+			k2.draw_texture_ex(tex_bunny, src, dest, {dest.w/2, dest.h/2}, b.rot, b.color)
+		}
+		
+		if k2.key_went_down(.B) {
+			fmt.println(len(bunnies))
+			fmt.println(1/dt)
+		}
+
+		k2.present()
+	}
+
+	delete(bunnies)
+	k2.destroy_texture(tex_bunny)
+
+	k2.shutdown()
+}

TEMPAT SAMPAH
examples/raylib_ports/bunnymark/wabbit_alpha.png


+ 41 - 31
karl2d.odin

@@ -62,6 +62,7 @@ init :: proc(window_width: int, window_height: int, window_title: string,
 	s.shape_drawing_texture = rb.load_texture(white_rect[:], 16, 16)
 
 	s.default_shader = load_shader(string(DEFAULT_SHADER_SOURCE))
+	s.batch_shader = s.default_shader
 
 	return s
 }
@@ -209,8 +210,9 @@ set_window_flags :: proc(flags: Window_Flags) {
 // - set_camera
 // - set_shader
 // - set_shader_constant
+// - set_scissor_rect
 // - draw_texture_* IF previous draw did not use the same texture (1)
-// - draw_rect_*, draw_circle_* IF previous draw did not use the shapes drawing texture (2)
+// - draw_rect_*, draw_circle_*, draw_line IF previous draw did not use the shapes drawing texture (2)
 // 
 // (1) When drawing textures, the current texture is fed into the active shader. Everything within
 //     the same batch must use the same texture. So drawing with a new texture will draw the current
@@ -221,10 +223,11 @@ set_window_flags :: proc(flags: Window_Flags) {
 //     before drawing a shape will break up the batches. TODO: Add possibility to customize shape
 //     drawing texture so that you can put it into an atlas.
 //
-// TODO: Name of this proc? submit_current_batch, flush_current_batch, draw_current_batch
+// The batch has maximum size of VERTEX_BUFFER_MAX bytes. The shader dictates how big a vertex is
+// so the maximum number of vertices that can be drawn in each batch is
+// VERTEX_BUFFER_MAX / shader.vertex_size
 draw_current_batch :: proc() {
-	shader := s.batch_shader.? or_else s.default_shader
-	rb.draw(shader, s.batch_texture, s.proj_matrix * s.view_matrix, s.batch_scissor, s.vertex_buffer_cpu[:s.vertex_buffer_cpu_used])
+	rb.draw(s.batch_shader, s.batch_texture, s.proj_matrix * s.view_matrix, s.batch_scissor, s.vertex_buffer_cpu[:s.vertex_buffer_cpu_used])
 	s.vertex_buffer_cpu_used = 0
 }
 
@@ -310,7 +313,11 @@ set_gamepad_vibration :: proc(gamepad: Gamepad_Index, left: f32, right: f32) {
 //---------//
 
 draw_rect :: proc(r: Rect, c: Color) {
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 6 > len(s.vertex_buffer_cpu) {
+		draw_current_batch()
+	}
+
+	if s.batch_texture != s.shape_drawing_texture {
 		draw_current_batch()
 	}
 
@@ -329,7 +336,11 @@ draw_rect_vec :: proc(pos: Vec2, size: Vec2, c: Color) {
 }
 
 draw_rect_ex :: proc(r: Rect, origin: Vec2, rot: f32, c: Color) {
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 6 > len(s.vertex_buffer_cpu) {
+		draw_current_batch()
+	}
+
+	if s.batch_texture != s.shape_drawing_texture {
 		draw_current_batch()
 	}
 
@@ -421,7 +432,11 @@ draw_rect_outline :: proc(r: Rect, thickness: f32, color: Color) {
 }
 
 draw_circle :: proc(center: Vec2, radius: f32, color: Color, segments := 16) {
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 3 * segments > len(s.vertex_buffer_cpu) {
+		draw_current_batch()
+	}
+
+	if s.batch_texture != s.shape_drawing_texture {
 		draw_current_batch()
 	}
 
@@ -432,7 +447,6 @@ draw_circle :: proc(center: Vec2, radius: f32, color: Color, segments := 16) {
 		sr := (f32(s)/f32(segments)) * 2*math.PI
 		rot := linalg.matrix2_rotate(sr)
 		p := center + rot * Vec2{radius, 0}
-			
 
 		batch_vertex(prev, {0, 0}, color)
 		batch_vertex(p, {1, 0}, color)
@@ -492,10 +506,16 @@ draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotati
 		return
 	}
 
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.handle {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 6 > len(s.vertex_buffer_cpu) {
 		draw_current_batch()
 	}
 
+	if s.batch_texture != tex.handle {
+		draw_current_batch()
+	}
+	
+	s.batch_texture = tex.handle
+
 	flip_x, flip_y: bool
 	src := src
 	dst := dst
@@ -518,7 +538,6 @@ draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotati
 		dst.h *= -1
 	}
 
-	s.batch_texture = tex.handle
 	tl, tr, bl, br: Vec2
 
 	// Rotation adapted from Raylib's "DrawTexturePro"
@@ -717,12 +736,18 @@ get_default_shader :: proc() -> Shader {
 }
 
 set_shader :: proc(shader: Maybe(Shader)) {
-	if maybe_handle_equal(shader, s.batch_shader) {
-		return
+	if shd, shd_ok := shader.?; shd_ok {
+		if shd.handle == s.batch_shader.handle {
+			return
+		}
+	} else {
+		if s.batch_shader.handle == s.default_shader.handle {
+			return
+		}
 	}
 
 	draw_current_batch()
-	s.batch_shader = shader
+	s.batch_shader = shader.? or_else s.default_shader
 }
 
 set_shader_constant :: proc(shd: Shader, loc: Shader_Constant_Location, val: any) {
@@ -1044,7 +1069,7 @@ State :: struct {
 
 	shape_drawing_texture: Texture_Handle,
 	batch_camera: Maybe(Camera),
-	batch_shader: Maybe(Shader),
+	batch_shader: Shader,
 	batch_scissor: Maybe(Rect),
 	batch_texture: Texture_Handle,
 
@@ -1232,10 +1257,10 @@ batch_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
 	v := v
 
 	if s.vertex_buffer_cpu_used == len(s.vertex_buffer_cpu) {
-		panic("Must dispatch here")
+		draw_current_batch()
 	}
 
-	shd := s.batch_shader.? or_else s.default_shader
+	shd := s.batch_shader
 
 	base_offset := s.vertex_buffer_cpu_used
 	pos_offset := shd.default_input_offsets[.Position]
@@ -1282,21 +1307,6 @@ frame_allocator: runtime.Allocator
 win: Window_Interface
 rb: Render_Backend_Interface
 
-maybe_handle_equal :: proc(m1: Maybe($T), m2: Maybe(T)) -> bool {
-	if m1 == nil && m2 == nil {
-		return true
-	}
-
-	m1v, m1v_ok := m1.?
-	m2v, m2v_ok := m2.?
-
-	if !m1v_ok || !m2v_ok {
-		return false
-	}
-
-	return m1v.handle == m2v.handle
-}
-
 get_shader_input_default_type :: proc(name: string, type: Shader_Input_Type) -> Shader_Default_Inputs {
 	if name == "POS" && type == .Vec2 {
 		return .Position

+ 2 - 12
render_backend_d3d11.odin

@@ -184,10 +184,6 @@ d3d11_clear :: proc(color: Color) {
 
 d3d11_present :: proc() {
 	ch(s.swapchain->Present(1, {}))
-	if s.odd_frame {
-		s.vertex_buffer_offset = 0
-	}
-	s.odd_frame = !s.odd_frame
 }
 
 d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scissor: Maybe(Rect), vertex_buffer: []u8) {
@@ -214,7 +210,7 @@ d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scisso
 	{
 		gpu_map := slice.from_ptr((^u8)(vb_data.pData), VERTEX_BUFFER_MAX)
 		copy(
-			gpu_map[s.vertex_buffer_offset:s.vertex_buffer_offset+len(vertex_buffer)],
+			gpu_map,
 			vertex_buffer,
 		)
 	}
@@ -223,7 +219,7 @@ d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scisso
 	dc->IASetPrimitiveTopology(.TRIANGLELIST)
 
 	dc->IASetInputLayout(d3d_shd.input_layout)
-	vertex_buffer_offset := u32(s.vertex_buffer_offset)
+	vertex_buffer_offset: u32
 	vertex_buffer_stride := u32(shd.vertex_size)
 	dc->IASetVertexBuffers(0, 1, &s.vertex_buffer_gpu, &vertex_buffer_stride, &vertex_buffer_offset)
 
@@ -293,7 +289,6 @@ d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scisso
 	dc->OMSetBlendState(s.blend_state, nil, ~u32(0))
 
 	dc->Draw(u32(len(vertex_buffer)/shd.vertex_size), 0)
-	s.vertex_buffer_offset += len(vertex_buffer)
 	log_messages()
 }
 
@@ -576,16 +571,11 @@ D3D11_State :: struct {
 	blend_state: ^d3d11.IBlendState,
 	sampler_state: ^d3d11.ISamplerState,
 
-	// 0 or 1
-	odd_frame: bool,
-
 	textures: hm.Handle_Map(D3D11_Texture, Texture_Handle, 1024*10),
 	shaders: hm.Handle_Map(D3D11_Shader, Shader_Handle, 1024*10),
 
 	info_queue: ^d3d11.IInfoQueue,
 	vertex_buffer_gpu: ^d3d11.IBuffer,
-
-	vertex_buffer_offset: int,
 }
 
 create_swapchain :: proc(w, h: int) {