Coding update: new libraries, graphics and input


I’m still coding my way back to where I was before I decided to switch to C instead of C++. I updated the documentation with the new libs (I have to write hundreds of comments though…sigh…).

Graphics

The graphics library is a wrapper for OpenGL. A lot of functions are not doing much more than OpenGL does, but here a a few features that are really helpful:

  • minimize OpenGL calls by saving active ids for buffers, textures, states, blending functions, etc. into a general state
  • push / pop state
  • GfxAttributeFormat struct to help with attributes enabling in vertex arrays
  • helper to link shader attributes (parsing shader, specify attributes locations, automatic binding, …)
  • helper to create different types of framebuffers (like for render to texture)

I still have a lot of C++ code to convert, like a direct 2D API, but one of the thing I like the most is a shader generator (doing things from simple texturing to Phong lighting).

I have been following LearnOpenGL for a while, and it helped me a lot building my C++ code. Now my objective is to go through each tutorial and make a sample out of it, using my own tools.

The four images above are actually the first few tutorials.

I probably won’t try PBR but I’m determined to get as far as the deferred renderer.

That will give me solid tools for rendering cool stuff later on.

In parallel I think of starting to implement a GUI, I had one before in C++ but I ended up hating it, as it was persistent and events-based. I’m really interested in the immediate mode GUI paradigm so I’ll venture that way.


Input

For the input library, I decided to beef up the previous C++ code to now support multiple devices. I used RAWINPUT and managed to get it working pretty quickly, but now I’m dreading the day I have to implement this part on Linux or Android. It’s still a work in progress but I have a a few features:

  • support up to 4 mouse/keyboard (and soon gamepads too?)
  • abstraction of input devices, events and virtual keys to avoid dealing with platform specific code
  • read current input state for each mouse / keyboard (+active keyboard layout, active keyboard locks)
  • subscribe to input event callbacks
  • detect if devices are added / removed

Code Example

Below is an example of code for the triangle test:

/*
 * basic_triangle.c
 * Another Memory Ends - <amedevcentral@gmail.com>
 */
#include "graphics.h"

const size_t gc_core_memory_size = 0;

bool quit = false;

LRESULT CALLBACK WndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_QUIT)
		quit = true;
	if (message == WM_CLOSE)
		quit = true;
	return DefWindowProc(hwnd, message, wParam, lParam);
}

typedef struct {
	vec2 pos;
	vec4 color;
} Vertex;

int main(int argc, char** argv)
{
	c_core_init(C_OUTPUT_FULL, 0);
	(void)argc;
	(void)argv;

	Window window;
	gfx_initialize();
	c_window_initialize(&window, "basic triangle", 320, 240, c_window_style_default(), WndProc);

	gfx_win32_set_pixel_format(window.hDC, 24, 16, 8);

	gfx_id context = gfx_context_create_win32(window.hDC);
	gfx_context_set(context);

	ColorVec4 clear_color = i_color_to_vec4(&gc_color_transparent);
	gfx_clear_color_set(&clear_color);

	bstr vertex_shader = bstr_init(
		"#version 330 core\n"
		"in vec2 pos;\n"
		"in vec4 color;\n"
		"out vec4 frag_color;\n"
		"void main()\n"
		"{\n"
		"  frag_color = color;\n"
		"  gl_Position = vec4(pos, 0, 1);\n"
		"}\n");

	bstr fragment_shader = bstr_init(
		"#version 330 core\n"
		"out vec4 color;\n"
		"in vec4 frag_color;\n"
		"void main()\n"
		"{\n"
		"  color = frag_color;\n"
		"}\n");

	GfxShaderLink link;
	link.link_type = GFX_SHADER_LINK_DEFAULT_BINDING;
	gfx_id shader = gfx_shader_program_create(&vertex_shader, &fragment_shader, &link);

	GfxAttributeFormat format = gfx_attribute_format_init();
	gfx_attribute_format_add(&format, "pos", GFX_ATTRIBUTE_VEC2);
	gfx_attribute_format_add(&format, "color", GFX_ATTRIBUTE_VEC4);

	gfx_id vertex_array = gfx_vertex_array_create();
	gfx_id vertex_buffer = gfx_vertex_buffer_create();

	gfx_vertex_array_bind(vertex_array);
	gfx_vertex_buffer_bind(vertex_buffer);
	gfx_attributes_enable_interleaved(&format);

	Vertex vertex[3];
	vertex[0].pos.x = -0.5f;
	vertex[0].pos.y = -0.5f;
	vertex[0].color = i_color_to_vec4(&gc_color_red);

	vertex[1].pos.x = 0.0f;
	vertex[1].pos.y = 0.5f;
	vertex[1].color = i_color_to_vec4(&gc_color_green);

	vertex[2].pos.x = 0.5f;
	vertex[2].pos.y = -0.5f;
	vertex[2].color = i_color_to_vec4(&gc_color_blue);

	gfx_vertex_buffer_copy_data((const uint8*)&vertex, sizeof(Vertex) * 3, GFX_BUFFER_STATIC);

	gfx_vertex_array_bind(0);

	c_window_show(&window);

	while (quit == false)
	{
		c_window_process_messages(&window);
		gfx_framebuffer_bind(0);
		gfx_viewport_set_values(0, 0, 320, 240);
		gfx_clear(true, false, false);
		gfx_shader_program_use(shader);
		gfx_vertex_array_bind(vertex_array);
		gfx_draw_vertices(GFX_VERTEX_TRIANGLE, 3);
		c_window_swap_buffers(&window);
	}

	gfx_shader_program_delete(shader);
	gfx_vertex_array_delete(vertex_array);
	gfx_vertex_buffer_delete(vertex_buffer);

	gfx_context_release();
	gfx_context_delete(context);
	c_window_terminate(&window);
	gfx_terminate();

	c_core_terminate();
	c_pause_program();
	return 0;
}


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: