Răsfoiți Sursa

Work on getting textured rects to work

Karl Zylinski 7 luni în urmă
părinte
comite
eb0d4a3b6b
3 a modificat fișierele cu 112 adăugiri și 27 ștergeri
  1. 3 4
      karl2d.odin
  2. 103 22
      karl2d_windows.odin
  3. 6 1
      shader.hlsl

+ 3 - 4
karl2d.odin

@@ -38,7 +38,8 @@ set_window_position: proc(x: int, y: int) : _set_window_position
 get_screen_width: proc() -> int : _get_screen_width
 get_screen_width: proc() -> int : _get_screen_width
 get_screen_height: proc() -> int : _get_screen_height
 get_screen_height: proc() -> int : _get_screen_height
 
 
-load_texture_from_file: proc(filename: string) -> Texture : _load_texture
+load_texture_from_file: proc(filename: string) -> Texture : _load_texture_from_file
+load_texture_from_memory: proc(data: []u8, width: int, height: int) -> Texture : _load_texture_from_memory
 // load_texture_from_bytes or buffer or something ()
 // load_texture_from_bytes or buffer or something ()
 destroy_texture: proc(tex: Texture) : _destroy_texture
 destroy_texture: proc(tex: Texture) : _destroy_texture
 
 
@@ -95,10 +96,8 @@ Rect :: struct {
 	w, h: f32,
 	w, h: f32,
 }
 }
 
 
-Texture_Handle :: distinct int
-
 Texture :: struct {
 Texture :: struct {
-	id: Texture_Handle,
+	id: _Texture_Type,
 	width: int,
 	width: int,
 	height: int,
 	height: int,
 }
 }

+ 103 - 22
karl2d_windows.odin

@@ -12,6 +12,15 @@ import "core:math/linalg"
 import "core:slice"
 import "core:slice"
 import "core:mem"
 import "core:mem"
 import "core:math"
 import "core:math"
+import "core:image"
+
+import "core:image/bmp"
+import "core:image/png"
+import "core:image/tga"
+
+_ :: bmp
+_ :: png
+_ :: tga
 
 
 _init :: proc(width: int, height: int, title: string,
 _init :: proc(width: int, height: int, title: string,
               allocator := context.allocator, loc := #caller_location) -> ^State {
               allocator := context.allocator, loc := #caller_location) -> ^State {
@@ -123,8 +132,9 @@ _init :: proc(width: int, height: int, title: string,
 	ch(s.device->CreateVertexShader(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), nil, &s.vertex_shader))
 	ch(s.device->CreateVertexShader(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), nil, &s.vertex_shader))
 
 
 	input_element_desc := [?]d3d11.INPUT_ELEMENT_DESC{
 	input_element_desc := [?]d3d11.INPUT_ELEMENT_DESC{
-		{ "POS", 0, .R32G32_FLOAT, 0, 0, .VERTEX_DATA, 0 },
-		{ "COL", 0, .R8G8B8A8_UNORM , 0, d3d11.APPEND_ALIGNED_ELEMENT, .VERTEX_DATA, 0 },
+		{ "POS", 0, .R32G32_FLOAT,   0, 0,                            .VERTEX_DATA, 0 },
+		{ "UV",  0, .R32G32_FLOAT,   0, d3d11.APPEND_ALIGNED_ELEMENT, .VERTEX_DATA, 0 },
+		{ "COL", 0, .R8G8B8A8_UNORM, 0, d3d11.APPEND_ALIGNED_ELEMENT, .VERTEX_DATA, 0 },
 	}
 	}
 
 
 	ch(s.device->CreateInputLayout(&input_element_desc[0], len(input_element_desc), vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &s.input_layout))
 	ch(s.device->CreateInputLayout(&input_element_desc[0], len(input_element_desc), vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &s.input_layout))
@@ -189,6 +199,17 @@ _init :: proc(width: int, height: int, title: string,
 
 
 	s.proj_matrix = make_default_projection(s.width, s.height)
 	s.proj_matrix = make_default_projection(s.width, s.height)
 	s.view_matrix = 1
 	s.view_matrix = 1
+
+
+	sampler_desc := d3d11.SAMPLER_DESC{
+		Filter         = .MIN_MAG_MIP_POINT,
+		AddressU       = .WRAP,
+		AddressV       = .WRAP,
+		AddressW       = .WRAP,
+		ComparisonFunc = .NEVER,
+	}
+	s.device->CreateSamplerState(&sampler_desc, &s.sampler_state)
+
 	return s
 	return s
 }
 }
 
 
@@ -196,6 +217,7 @@ shader_hlsl :: #load("shader.hlsl")
 
 
 Vertex :: struct {
 Vertex :: struct {
 	pos: Vec2,
 	pos: Vec2,
+	uv: Vec2,
 	color: Color,
 	color: Color,
 }
 }
 
 
@@ -219,6 +241,11 @@ State :: struct {
 	framebuffer: ^d3d11.ITexture2D,
 	framebuffer: ^d3d11.ITexture2D,
 	blend_state: ^d3d11.IBlendState,
 	blend_state: ^d3d11.IBlendState,
 
 
+	// these need to be generalized
+	sampler_state: ^d3d11.ISamplerState,
+
+	set_tex: Texture,
+
 	info_queue: ^d3d11.IInfoQueue,
 	info_queue: ^d3d11.IInfoQueue,
 	vertex_buffer_gpu: ^d3d11.IBuffer,
 	vertex_buffer_gpu: ^d3d11.IBuffer,
 	vertex_buffer_cpu: []Vertex,
 	vertex_buffer_cpu: []Vertex,
@@ -350,8 +377,55 @@ _clear :: proc(color: Color) {
 	s.device_context->ClearDepthStencilView(s.depth_buffer_view, {.DEPTH}, 1, 0)
 	s.device_context->ClearDepthStencilView(s.depth_buffer_view, {.DEPTH}, 1, 0)
 }
 }
 
 
-_load_texture :: proc(filename: string) -> Texture {
-	return {}
+_Texture_Type :: struct {
+	tex: ^d3d11.ITexture2D,
+	view: ^d3d11.IShaderResourceView,
+}
+
+
+
+_load_texture_from_file :: proc(filename: string) -> Texture {
+	img, img_err := image.load_from_file(filename, allocator = context.temp_allocator)
+
+	if img_err != nil {
+		log.errorf("Error loading texture %v: %v", filename, img_err)
+		return {}
+	}
+
+	return _load_texture_from_memory(img.pixels.buf[:], img.width, img.height)
+}
+
+_load_texture_from_memory :: proc(data: []u8, width: int, height: int) -> Texture {
+	texture_desc := d3d11.TEXTURE2D_DESC{
+		Width      = u32(width),
+		Height     = u32(height),
+		MipLevels  = 1,
+		ArraySize  = 1,
+		// TODO: _SRGB or not?
+		Format     = .R8G8B8A8_UNORM_SRGB,
+		SampleDesc = {Count = 1},
+		Usage      = .IMMUTABLE,
+		BindFlags  = {.SHADER_RESOURCE},
+	}
+
+	texture_data := d3d11.SUBRESOURCE_DATA{
+		pSysMem     = raw_data(data),
+		SysMemPitch = u32(width * 4),
+	}
+
+	texture: ^d3d11.ITexture2D
+	s.device->CreateTexture2D(&texture_desc, &texture_data, &texture)
+
+	texture_view: ^d3d11.IShaderResourceView
+	s.device->CreateShaderResourceView(texture, nil, &texture_view)
+	return {
+		id = {
+			tex = texture,
+			view = texture_view,
+		},
+		width = width,
+		height = height,
+	}
 }
 }
 
 
 _destroy_texture :: proc(tex: Texture) {
 _destroy_texture :: proc(tex: Texture) {
@@ -380,13 +454,14 @@ _draw_texture_rect :: proc(tex: Texture, rect: Rect, pos: Vec2, tint := WHITE) {
 	)
 	)
 }
 }
 
 
-add_vertex :: proc(v: Vec2, color: Color) {
+add_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
 	if s.vertex_buffer_cpu_count == len(s.vertex_buffer_cpu) {
 	if s.vertex_buffer_cpu_count == len(s.vertex_buffer_cpu) {
 		panic("Must dispatch here")
 		panic("Must dispatch here")
 	}
 	}
 
 
 	s.vertex_buffer_cpu[s.vertex_buffer_cpu_count] = {
 	s.vertex_buffer_cpu[s.vertex_buffer_cpu_count] = {
 		pos = v,
 		pos = v,
+		uv = uv,
 		color = color,
 		color = color,
 	}
 	}
 
 
@@ -394,27 +469,31 @@ add_vertex :: proc(v: Vec2, color: Color) {
 }
 }
 
 
 _draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rot: f32, tint := WHITE) {
 _draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rot: f32, tint := WHITE) {
-	p := Vec2 {
-		dst.x, dst.y,
+	if s.set_tex.id.tex != nil && s.set_tex.id.tex != tex.id.tex {
+		maybe_draw_current_batch()
 	}
 	}
 
 
-	p -= origin
+	r := dst
+
+	r.x -= origin.x
+	r.y -= origin.y
+
+	s.set_tex = tex
+	add_rect(r, tint)
+}
 
 
-	add_vertex({p.x, p.y}, tint)
-	add_vertex({p.x + dst.w, p.y}, tint)
-	add_vertex({p.x + dst.w, p.y + dst.h}, tint)
-	add_vertex({p.x, p.y}, tint)
-	add_vertex({p.x + dst.w, p.y + dst.h}, tint)
-	add_vertex({p.x, p.y + dst.h}, tint)
+add_rect :: proc(r: Rect, color: Color) {
+	c := color
+	add_vertex({r.x, r.y}, {0, 0}, c)
+	add_vertex({r.x + r.w, r.y}, {1, 0}, c)
+	add_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
+	add_vertex({r.x, r.y}, {0, 0}, c)
+	add_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
+	add_vertex({r.x, r.y + r.h}, {0, 1}, c)
 }
 }
 
 
 _draw_rectangle :: proc(r: Rect, color: Color) {
 _draw_rectangle :: proc(r: Rect, color: Color) {
-	add_vertex({r.x, r.y}, color)
-	add_vertex({r.x + r.w, r.y}, color)
-	add_vertex({r.x + r.w, r.y + r.h}, color)
-	add_vertex({r.x, r.y}, color)
-	add_vertex({r.x + r.w, r.y + r.h}, color)
-	add_vertex({r.x, r.y + r.h}, color)
+	add_rect(r, color)
 }
 }
 
 
 _draw_rectangle_outline :: proc(r: Rect, thickness: f32, color: Color) {
 _draw_rectangle_outline :: proc(r: Rect, thickness: f32, color: Color) {
@@ -626,13 +705,15 @@ _draw_current_batch :: proc() {
 	dc->RSSetState(s.rasterizer_state)
 	dc->RSSetState(s.rasterizer_state)
 
 
 	dc->PSSetShader(s.pixel_shader, nil, 0)
 	dc->PSSetShader(s.pixel_shader, nil, 0)
+	dc->PSSetShaderResources(0, 1, &s.set_tex.id.view)
+	dc->PSSetSamplers(0, 1, &s.sampler_state)
 
 
 	dc->OMSetRenderTargets(1, &s.framebuffer_view, s.depth_buffer_view)
 	dc->OMSetRenderTargets(1, &s.framebuffer_view, s.depth_buffer_view)
 	dc->OMSetDepthStencilState(s.depth_stencil_state, 0)
 	dc->OMSetDepthStencilState(s.depth_stencil_state, 0)
 	dc->OMSetBlendState(s.blend_state, nil, ~u32(0))
 	dc->OMSetBlendState(s.blend_state, nil, ~u32(0))
 
 
 	dc->Draw(u32(s.vertex_buffer_cpu_count), u32(s.vertex_buffer_offset))
 	dc->Draw(u32(s.vertex_buffer_cpu_count), u32(s.vertex_buffer_offset))
-	s.vertex_buffer_offset += s.vertex_buffer_cpu_count
+	s.vertex_buffer_offset = s.vertex_buffer_cpu_count
 	log_messages()
 	log_messages()
 }
 }
 
 
@@ -669,7 +750,7 @@ _set_shader_value_vec2 :: proc(shader: Shader, loc: int, val: Vec2) {
 }
 }
 
 
 temp_cstring :: proc(str: string, loc := #caller_location) -> cstring {
 temp_cstring :: proc(str: string, loc := #caller_location) -> cstring {
-	return strings.clone_to_cstring(str, context.temp_allocator)
+	return strings.clone_to_cstring(str, context.temp_allocator, loc)
 }
 }
 
 
 // CHeck win errors and print message log if there is any error
 // CHeck win errors and print message log if there is any error

+ 6 - 1
shader.hlsl

@@ -3,18 +3,23 @@ cbuffer constants : register(b0) {
 }
 }
 struct vs_in {
 struct vs_in {
 	float2 position : POS;
 	float2 position : POS;
+	float2 uv       : UV;
 	float4 color    : COL;
 	float4 color    : COL;
 };
 };
 struct vs_out {
 struct vs_out {
 	float4 position : SV_POSITION;
 	float4 position : SV_POSITION;
+	float2 uv       : UV;
 	float4 color    : COL;
 	float4 color    : COL;
 };
 };
+Texture2D    tex : register(t0);
+SamplerState smp : register(s0);
 vs_out vs_main(vs_in input) {
 vs_out vs_main(vs_in input) {
 	vs_out output;
 	vs_out output;
 	output.position = mul(mvp, float4(input.position, 0, 1.0f));
 	output.position = mul(mvp, float4(input.position, 0, 1.0f));
+	output.uv = input.uv;
 	output.color = input.color;
 	output.color = input.color;
 	return output;
 	return output;
 }
 }
 float4 ps_main(vs_out input) : SV_TARGET {
 float4 ps_main(vs_out input) : SV_TARGET {
-	return input.color;
+	return tex.Sample(smp, input.uv) * input.color;
 }
 }