mirror of
				https://git.shylie.info/shylie/glerminal.git
				synced 2025-10-31 09:10:13 +00:00 
			
		
		
		
	Add sub-cell offsets
This commit is contained in:
		| @@ -1,12 +1,14 @@ | ||||
| #include <glerminal.h> | ||||
|  | ||||
| #include <cstdlib> | ||||
|  | ||||
| namespace | ||||
| { | ||||
| 	void init() | ||||
| 	{ | ||||
| 		glerminal_update_palette(0, 0x00000000); | ||||
| 		glerminal_update_palette(1, 0xFF00001F); | ||||
| 		glerminal_update_palette(2, 0x00FF001F); | ||||
| 		glerminal_update_palette(1, 0xFF00007F); | ||||
| 		glerminal_update_palette(2, 0x00FF007F); | ||||
|  | ||||
| 		glerminal_update_sprite(1, { | ||||
| 			2, 2, 2, 2, 2, 2, 2, 2, | ||||
| @@ -18,17 +20,35 @@ namespace | ||||
| 			2, 1, 1, 1, 1, 1, 1, 2, | ||||
| 			2, 2, 2, 2, 2, 2, 2, 2 | ||||
| 		}); | ||||
|  | ||||
| 		glerminal_set(0, 0, 0, 1); | ||||
| 		glerminal_set(1, 0, 0, 1); | ||||
| 		glerminal_set(1, 0, 1, 1); | ||||
| 		glerminal_set(2, 0, 0, 1); | ||||
| 		glerminal_set(2, 0, 1, 1); | ||||
| 		glerminal_set(2, 0, 2, 1); | ||||
| 	} | ||||
|  | ||||
| 	void mainloop(float dt) | ||||
| 	{ | ||||
| 		static float time = 1; | ||||
|  | ||||
| 		time += dt; | ||||
|  | ||||
| 		if (time < 0.2f) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			time = 0; | ||||
| 		} | ||||
|  | ||||
| 		for (int i = 0; i < 32; i++) | ||||
| 		{ | ||||
| 			for (int j = 0; j < 20; j++) | ||||
| 			{ | ||||
| 				for (int k = 0; k < 16; k++) | ||||
| 				{ | ||||
| 					glerminal_set(i, j, k, 1); | ||||
| 					glerminal_offset(i, j, k, (rand() * rand()) % 256 - 128, (rand() * rand()) % 256 - 128); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		glerminal_flush(); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -35,7 +35,7 @@ void glerminal_flush(); | ||||
|  * @brief Set a cell's sprite | ||||
|  * @param x position of the cell in the range [0, 32) | ||||
|  * @param y position of the cell in the range [0, 20) | ||||
|  * @param layer layer of the cell in the range [0, 16) | ||||
|  * @param layer layer of the cell in the range [0, 8) | ||||
|  * @param sprite sprite's index in the range [0, 256) | ||||
|  */ | ||||
| void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite); | ||||
| @@ -43,10 +43,19 @@ void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsign | ||||
|  * @brief Get a cell's sprite | ||||
|  * @param x position of the cell in the range [0, 32) | ||||
|  * @param y position of the cell in the range [0, 20) | ||||
|  * @param layer layer of the cell in the range [0, 16) | ||||
|  * @param layer layer of the cell in the range [0, 8) | ||||
|  * @return sprite index currently assigned to the cell | ||||
|  */ | ||||
| unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char layer); | ||||
| /** | ||||
|  * @brief Set a cell's offset | ||||
|  * @param x position of the cell in the range [0, 32) | ||||
|  * @param y position of the cell in the range [0, 20) | ||||
|  * @param layer layer of the cell in the range [0, 8) | ||||
|  * @param x_offset offset of the cell on the x axis in the range [-128, 127], where 0 is no offset | ||||
|  * @param y_offset offset of the cell on the y axis in the range [-128, 127], where 0 is no offset | ||||
|  */ | ||||
| void glerminal_offset(unsigned char x, unsigned char y, unsigned char layer, char x_offset, char y_offset); | ||||
|  | ||||
| /** | ||||
|  * @brief Upload sprite to the given sprite ID | ||||
|   | ||||
| @@ -20,7 +20,7 @@ namespace glerminal | ||||
| 	constexpr unsigned int GRID_WIDTH = SCREEN_WIDTH / (CELL_SIZE * CELL_SCALE); | ||||
| 	constexpr unsigned int GRID_HEIGHT = SCREEN_HEIGHT / (CELL_SIZE * CELL_SCALE); | ||||
| 	constexpr unsigned int GRID_AREA = GRID_WIDTH * GRID_HEIGHT; | ||||
| 	constexpr unsigned int LAYER_COUNT = 16; | ||||
| 	constexpr unsigned int LAYER_COUNT = 8; | ||||
|  | ||||
| 	class glerminal | ||||
| 	{ | ||||
| @@ -40,6 +40,7 @@ namespace glerminal | ||||
|  | ||||
| 		void set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite); | ||||
| 		unsigned char get(unsigned char x, unsigned char y, unsigned char layer) const; | ||||
| 		void offset(unsigned char x, unsigned char y, unsigned char layer, char x_offset, char y_offset); | ||||
|  | ||||
| 		void update_sprite(unsigned char id, glerminal_sprite sprite); | ||||
| 		void update_palette_color(unsigned char id, unsigned int color); | ||||
| @@ -48,7 +49,8 @@ namespace glerminal | ||||
| 		GLFWwindow* m_window; | ||||
|  | ||||
| 		unsigned int m_vbo; | ||||
| 		unsigned int m_instance_vbo; | ||||
| 		unsigned int m_sprites_instance_vbo; | ||||
| 		unsigned int m_offsets_instance_vbo; | ||||
| 		unsigned int m_vao; | ||||
| 		unsigned int m_program; | ||||
| 		unsigned int m_screen_vao; | ||||
| @@ -60,6 +62,7 @@ namespace glerminal | ||||
| 		unsigned int m_palette_uniform_location; | ||||
|  | ||||
| 		unsigned char m_cells[GRID_AREA * LAYER_COUNT]; | ||||
| 		char m_offsets[GRID_AREA * LAYER_COUNT * 2]; | ||||
| 		unsigned char m_sprites[CELL_SIZE * CELL_SIZE * 256]; | ||||
| 		float m_palette[64]; | ||||
|  | ||||
|   | ||||
| @@ -25,15 +25,21 @@ namespace | ||||
| 	constexpr char* VERTEX_SHADER_SOURCE = | ||||
| 		"#version 400 core\n" | ||||
| 		"layout (location = 0) in vec2 position;\n" | ||||
| 		"layout (location = 1) in ivec4 sprite[4];\n" | ||||
| 		"layout (location = 1) in vec2 offset[8];\n" | ||||
| 		"layout (location = 9) in ivec4 sprite[2];\n" | ||||
| 		"uniform vec4 " SCREEN_SIZE_UNIFORM_NAME ";\n" | ||||
| 		"out VS_OUT {\n" | ||||
| 		"	flat ivec4 sprite[4];\n" | ||||
| 		"   flat vec2 offset[8];\n" | ||||
| 		"	flat ivec4 sprite[2];\n" | ||||
| 		"	vec2 texcoord;\n" | ||||
| 		"} vs_out;\n" | ||||
| 		"void main()\n" | ||||
| 		"{\n" | ||||
| 		"	vs_out.sprite = sprite;\n" | ||||
| 		"	for (int i = 0; i < 8; i++)\n" | ||||
| 		"	{\n" | ||||
| 		"		vs_out.offset[i] = offset[i] * " SCREEN_SIZE_UNIFORM_NAME ".zw;\n" | ||||
| 		"	}\n" | ||||
| 		"	vs_out.texcoord = vec2(position.x + 1, -position.y);\n" | ||||
| 		"	vec2 cell_position = vec2(1 + gl_InstanceID - " SCREEN_SIZE_UNIFORM_NAME ".x * floor(gl_InstanceID * " SCREEN_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID) * " SCREEN_SIZE_UNIFORM_NAME ".z));\n" | ||||
| 		"	vec2 temp = vec2((position + cell_position) * " SCREEN_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1));\n" | ||||
| @@ -43,10 +49,11 @@ namespace | ||||
| 	constexpr char* GEOMETRY_SHADER_SOURCE = | ||||
| 		"#version 400 core\n" | ||||
| 		"layout (triangles) in;\n" | ||||
| 		"layout (triangle_strip, max_vertices = 48) out;\n" | ||||
| 		"layout (invocations = 16) in;\n" | ||||
| 		"layout (triangle_strip, max_vertices = 24) out;\n" | ||||
| 		"layout (invocations = 8) in;\n" | ||||
| 		"in VS_OUT {\n" | ||||
| 		"	flat ivec4 sprite[4];\n" | ||||
| 		"   flat vec2 offset[8];\n" | ||||
| 		"	flat ivec4 sprite[2];\n" | ||||
| 		"	vec2 texcoord;\n" | ||||
| 		"} gs_in[];\n" | ||||
| 		"flat out int sprite;\n" | ||||
| @@ -54,18 +61,18 @@ namespace | ||||
| 		"void main()\n" | ||||
| 		"{\n" | ||||
| 		"	gl_Layer = gl_InvocationID;\n" | ||||
| 		"	gl_Position = gl_in[0].gl_Position;\n" | ||||
| 		"	sprite = gs_in[0].sprite[gl_InvocationID / 16][gl_InvocationID % 16];\n" | ||||
| 		"	gl_Position = vec4(gl_in[0].gl_Position.xy + gs_in[0].offset[gl_InvocationID], 0, 1);\n" | ||||
| 		"	sprite = gs_in[0].sprite[gl_InvocationID / 8][gl_InvocationID % 8];\n" | ||||
| 		"	texcoord = gs_in[0].texcoord;\n" | ||||
| 		"	EmitVertex();\n" | ||||
| 		"	gl_Layer = gl_InvocationID;\n" | ||||
| 		"	gl_Position = gl_in[1].gl_Position;\n" | ||||
| 		"	sprite = gs_in[1].sprite[gl_InvocationID / 16][gl_InvocationID % 16];\n" | ||||
| 		"	gl_Position = vec4(gl_in[1].gl_Position.xy + gs_in[0].offset[gl_InvocationID], 0, 1);\n" | ||||
| 		"	sprite = gs_in[1].sprite[gl_InvocationID / 8][gl_InvocationID % 8];\n" | ||||
| 		"	texcoord = gs_in[1].texcoord;\n" | ||||
| 		"	EmitVertex();\n" | ||||
| 		"	gl_Layer = gl_InvocationID;\n" | ||||
| 		"	gl_Position = gl_in[2].gl_Position;\n" | ||||
| 		"	sprite = gs_in[2].sprite[gl_InvocationID / 16][gl_InvocationID % 16];\n" | ||||
| 		"	gl_Position = vec4(gl_in[2].gl_Position.xy + gs_in[0].offset[gl_InvocationID], 0, 1);\n" | ||||
| 		"	sprite = gs_in[2].sprite[gl_InvocationID / 8][gl_InvocationID % 8];\n" | ||||
| 		"	texcoord = gs_in[2].texcoord;\n" | ||||
| 		"	EmitVertex();\n" | ||||
| 		"	EndPrimitive();\n" | ||||
| @@ -101,7 +108,7 @@ namespace | ||||
| 		"void main()\n" | ||||
| 		"{\n" | ||||
| 		"	vec3 current_color = vec3(0);\n" | ||||
| 		"	for (int i = 0; i < 16; i++)\n" | ||||
| 		"	for (int i = 0; i < 8; i++)\n" | ||||
| 		"	{\n" | ||||
| 		"		vec4 texsample = texture(" LAYERS_UNIFORM_NAME ", vec3(texcoord, i));\n" | ||||
| 		"		current_color = mix(current_color, texsample.rgb, texsample.a);\n" | ||||
| @@ -115,6 +122,7 @@ namespace glerminal | ||||
| 	glerminal::glerminal(glerminal_init_cb init, glerminal_main_cb main) : | ||||
| 		m_main(main), | ||||
| 		m_cells{ }, | ||||
| 		m_offsets{ }, | ||||
| 		m_sprites{ }, | ||||
| 		m_palette{ } | ||||
| #ifdef _DEBUG | ||||
| @@ -171,7 +179,8 @@ namespace glerminal | ||||
| 	void glerminal::flush() | ||||
| 	{ | ||||
| 		// use dirty flag later | ||||
| 		glNamedBufferData(m_instance_vbo, sizeof(m_cells), m_cells, GL_STREAM_DRAW); | ||||
| 		glNamedBufferData(m_sprites_instance_vbo, sizeof(m_cells), m_cells, GL_STREAM_DRAW); | ||||
| 		glNamedBufferData(m_offsets_instance_vbo, sizeof(m_offsets), m_offsets, GL_STREAM_DRAW); | ||||
| 		update_sprites(); | ||||
| 		update_palette(); | ||||
|  | ||||
| @@ -212,6 +221,15 @@ namespace glerminal | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void glerminal::offset(unsigned char x, unsigned char y, unsigned char layer, char x_offset, char y_offset) | ||||
| 	{ | ||||
| 		if (x < GRID_WIDTH && y < GRID_HEIGHT && layer < LAYER_COUNT) | ||||
| 		{ | ||||
| 			m_offsets[2 * (layer + x * LAYER_COUNT + y * LAYER_COUNT * GRID_WIDTH) + 0] = x_offset; | ||||
| 			m_offsets[2 * (layer + x * LAYER_COUNT + y * LAYER_COUNT * GRID_WIDTH) + 1] = y_offset; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void glerminal::update_sprite(unsigned char id, glerminal_sprite sprite) | ||||
| 	{ | ||||
| 		// does this work? | ||||
| @@ -331,11 +349,14 @@ namespace glerminal | ||||
|  | ||||
| 		glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | ||||
| 		glDisable(GL_DEPTH_TEST); | ||||
| 		glEnable(GL_BLEND); | ||||
| 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
|  | ||||
| 		// -- setup vertex data -- | ||||
| 		// create vertex buffer object | ||||
| 		glGenBuffers(1, &m_vbo); | ||||
| 		glGenBuffers(1, &m_instance_vbo); | ||||
| 		glGenBuffers(1, &m_sprites_instance_vbo); | ||||
| 		glGenBuffers(1, &m_offsets_instance_vbo); | ||||
|  | ||||
| 		// create vertex array object | ||||
| 		glGenVertexArrays(1, &m_vao); | ||||
| @@ -348,20 +369,42 @@ namespace glerminal | ||||
| 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(*VBO_VERTICES), reinterpret_cast<void*>(0)); | ||||
|  | ||||
| 		// set up instanced vertex attributes | ||||
| 		glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo); | ||||
| 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_cells), m_cells, GL_STREAM_DRAW); | ||||
| 		glBindBuffer(GL_ARRAY_BUFFER, m_offsets_instance_vbo); | ||||
| 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_offsets), m_offsets, GL_STREAM_DRAW); | ||||
| 		glEnableVertexAttribArray(1); | ||||
| 		glVertexAttribIPointer(1, 4, GL_UNSIGNED_BYTE, 16 * sizeof(*m_cells), reinterpret_cast<void*>(0)); | ||||
| 		glVertexAttribPointer(1, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(0 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(1, 1); | ||||
| 		glEnableVertexAttribArray(2); | ||||
| 		glVertexAttribIPointer(2, 4, GL_UNSIGNED_BYTE, 16 * sizeof(*m_cells), reinterpret_cast<void*>(4)); | ||||
| 		glVertexAttribPointer(2, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(2 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(2, 1); | ||||
| 		glEnableVertexAttribArray(3); | ||||
| 		glVertexAttribIPointer(3, 4, GL_UNSIGNED_BYTE, 16 * sizeof(*m_cells), reinterpret_cast<void*>(8)); | ||||
| 		glVertexAttribPointer(3, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(4 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(3, 1); | ||||
| 		glEnableVertexAttribArray(4); | ||||
| 		glVertexAttribIPointer(4, 4, GL_UNSIGNED_BYTE, 16 * sizeof(*m_cells), reinterpret_cast<void*>(12)); | ||||
| 		glVertexAttribPointer(4, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(6 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(4, 1); | ||||
| 		glEnableVertexAttribArray(5); | ||||
| 		glVertexAttribPointer(5, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(8 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(5, 1); | ||||
| 		glEnableVertexAttribArray(6); | ||||
| 		glVertexAttribPointer(6, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(10 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(6, 1); | ||||
| 		glEnableVertexAttribArray(7); | ||||
| 		glVertexAttribPointer(7, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(12 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(7, 1); | ||||
| 		glEnableVertexAttribArray(8); | ||||
| 		glVertexAttribPointer(8, 2, GL_BYTE, GL_TRUE, 16 * sizeof(*m_offsets), reinterpret_cast<void*>(14 * sizeof(*m_offsets))); | ||||
| 		glVertexAttribDivisor(8, 1); | ||||
|  | ||||
| 		glBindBuffer(GL_ARRAY_BUFFER, m_sprites_instance_vbo); | ||||
| 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_cells), m_cells, GL_STREAM_DRAW); | ||||
| 		glEnableVertexAttribArray(9); | ||||
| 		glVertexAttribIPointer(9, 4, GL_UNSIGNED_BYTE, 8 * sizeof(*m_cells), reinterpret_cast<void*>(0 * sizeof(*m_cells))); | ||||
| 		glVertexAttribDivisor(9, 1); | ||||
| 		glEnableVertexAttribArray(10); | ||||
| 		glVertexAttribIPointer(10, 4, GL_UNSIGNED_BYTE, 8 * sizeof(*m_cells), reinterpret_cast<void*>(4 * sizeof(*m_cells))); | ||||
| 		glVertexAttribDivisor(10, 1); | ||||
| 		 | ||||
|  | ||||
| 		// set up static vertex attributes | ||||
| 		glGenVertexArrays(1, &m_screen_vao); | ||||
| @@ -548,7 +591,8 @@ namespace glerminal | ||||
| 		glDeleteVertexArrays(1, &m_vao); | ||||
| 		glDeleteVertexArrays(1, &m_screen_vao); | ||||
| 		glDeleteBuffers(1, &m_vbo); | ||||
| 		glDeleteBuffers(1, &m_instance_vbo); | ||||
| 		glDeleteBuffers(1, &m_sprites_instance_vbo); | ||||
| 		glDeleteBuffers(1, &m_offsets_instance_vbo); | ||||
| 		glDeleteProgram(m_program); | ||||
| 	} | ||||
|  | ||||
| @@ -597,6 +641,13 @@ unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char laye | ||||
| 	return GLERMINAL_G->get(x, y, layer); | ||||
| } | ||||
|  | ||||
| void glerminal_offset(unsigned char x, unsigned char y, unsigned char layer, char x_offset, char y_offset) | ||||
| { | ||||
| 	if (!GLERMINAL_G) { return; } | ||||
|  | ||||
| 	GLERMINAL_G->offset(x, y, layer, x_offset, y_offset); | ||||
| } | ||||
|  | ||||
| void glerminal_update_sprite(unsigned char id, glerminal_sprite sprite) | ||||
| { | ||||
| 	if (!GLERMINAL_G) { return; } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Shylie
					Shylie