Handmade Hero»Forums»Code
107 posts
Least amount of steps from 2D to 3D
Edited by C_Worm on


My engine is currently setup for 2D rendering and now I just wanted to add the 3D feature so that by only adding the z-value could determine what object is infront or behind another one, instead of sorting the spritebuffer based on some layers.

So i thought that by giving the vertexattribs an extra float for z, make the sprite have a V3f instead of V2f for pos and glEnable(GL_DEPTH_TEST); and glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); I would then only be able to change the z-coordinate to make SPRITE zooom in/out.

It didn't work, so i wonder what are the minimal steps necesary to go from 2D -> 3D.

Must I use matrices here??

the vertex-shader im using is this:


#version 330 core

layout (location = 0) in vec3 pos;
layout (location = 1) in vec4 col;
layout (location = 2) in vec2 texCoord;

out vec4 VS_col_out;
out vec2 VS_texCoord_out;

uniform vec2 winDim;
uniform vec2 ballPos;

void main()
	vec4 v4_pos;
	v4_pos.x = pos.x - 1.0f;
	v4_pos.y = pos.y - 1.0f;
	v4_pos.z = pos.z;
	v4_pos.w = 1.0f;
	gl_Position = v4_pos;
	VS_col_out = col;
	VS_texCoord_out = texCoord;

Mārtiņš Možeiko
2561 posts / 2 projects
Least amount of steps from 2D to 3D

Changing z coordinate like you do won't do "zoom in/out". All it will is to change "layer" where it is drawn - in front/back of others.

To change size depending on distance, you need to use some kind of projection matrix, or explicitly change width/height of object you're rendering depending on z value.

107 posts
Least amount of steps from 2D to 3D
Edited by C_Worm on
Replying to mmozeiko (#25903)

Okay i see, but nothing happends when I change the Z value, all my tiles have z = 1.0f and my ship have a z = -1.0f but the tiles are "closer" to the camera and ship doesn't show. And also when i enable Depth-test and clear the depth-buffer-bit the transparent blending stops.


		for(int y = 0; y < tm_dim.y; y++)
			for(int x = 0; x < tm_dim.x; x++)
				u32 i = x + (tm_dim.x * y);
				int rx = CJ_RandIRange(7, 9, CJ_RAND_INCLUDE);
				int ry = CJ_RandIRange(8, 10, CJ_RAND_INCLUDE);
				game->tilemap[i].pos 			= v3f(0.0f + (tp.x * x), 0.0f + (tp.y * y), 1.0f); 
				game->tilemap[i].size 			= v3f(tp.x, tp.y, 0.0f); 
				game->tilemap[i].col 			= v4f(1.0f, 1.0f, 1.0f, 1.0f); 
				game->tilemap[i].tcoord_p 		= game->texture_map[0][i];//v2f(rx * tp.x, 1.0f - (ry * tp.y));
				game->tilemap[i].tcoord_sz		= v2f(1.0f * tp.x, 1.0f * tp.y);
		game->ship.sprite		= Push(game, SPRITE, 1);
		game->ship.sprite->pos 		= v3f(0.5f, 0.5f, -1.0f); 
		game->ship.sprite->size 	= v3f(0.1f, 0.15f, 0.0f); 
		game->ship.sprite->col 		= v4f(1.0f, 1.0f, 1.0f, 1.0f); 
		game->ship.sprite->tcoord_p 	= v2f(5.0f * tp.x, 1.0f - (2.0f * tp.y));
		game->ship.sprite->tcoord_sz	= v2f(1.0f * tp.x, 1.0f * tp.y);
		game->ship.hitpoints		= 10;

Updating the vbo

void UpdateVBO_SPRITE(CJ_VBO *vbo, GAME_HANDLER *game)
	CJ_VTX_SPRITE *pVertex = (CJ_VTX_SPRITE*)vbo->base;
	SPRITE *spr = (SPRITE*)game->sprite_batch.data;
	// Updating the data that's sent to the VBO
	for(u32 i = 0; i < game->sprite_batch.count; i++)
		//V2f pos 		= spr[i].pos;
		V3f pos 		= spr[i].pos;
		V3f size 		= spr[i].size;
		V4f col 		= spr[i].col;
		V2f tCoord_p		= spr[i].tcoord_p;
		V2f tCoord_sz		= spr[i].tcoord_sz;

		pVertex[(i * 4) + 0].pos = v3f(pos.x, 		pos.y, pos.z);
		pVertex[(i * 4) + 1].pos = v3f(pos.x, 		pos.y + size.y, pos.z);
		pVertex[(i * 4) + 2].pos = v3f(pos.x + size.x,  pos.y + size.y, pos.z);
		pVertex[(i * 4) + 3].pos = v3f(pos.x + size.x,  pos.y, pos.z);
		pVertex[(i * 4) + 0].col = col;
		pVertex[(i * 4) + 1].col = col;
		pVertex[(i * 4) + 2].col = col;
		pVertex[(i * 4) + 3].col = col;
		pVertex[(i * 4) + 0].tCoord = v2f(tCoord_p.x, 		    tCoord_p.y);
		pVertex[(i * 4) + 1].tCoord = v2f(tCoord_p.x, 		    tCoord_p.y + tCoord_sz.y);
		pVertex[(i * 4) + 2].tCoord = v2f(tCoord_p.x + tCoord_sz.x, tCoord_p.y + tCoord_sz.y);
		pVertex[(i * 4) + 3].tCoord = v2f(tCoord_p.x + tCoord_sz.y, tCoord_p.y);

Mārtiņš Možeiko
2561 posts / 2 projects
Least amount of steps from 2D to 3D
Replying to C_Worm (#25908)

-1 and +1 values are right on the border of clipping. Use something that is between -1 and +1. For example, Like -0.1 and +0.1

Typically you use transformation matrix, to transform arbitrary z range you want to -1..+1 interval.

For alpha blending to work properly you will need to render in back-to-front order. Regardless of zbuffer. Because alpha blending is not commutative operation.

107 posts
Least amount of steps from 2D to 3D
Replying to mmozeiko (#25910)

I looked at the wrong shader...

But let's say you want an explosion sprite to take place over an enemy ship. The Explosion sprite has transparency in it but since the explosion has a smaller z-value (closer to the camera) the transparency will block the enemy ship anyway.

How do you solve that problem usually?

Mārtiņš Možeiko
2561 posts / 2 projects
Least amount of steps from 2D to 3D
Edited by Mārtiņš Možeiko on
Replying to C_Worm (#25911)

Classically you solve it by sorting your sprites on cpu, and then drawing them in back-to-front order. Usually you don't have so many sprites that this would be a problem.

For complex 3d applications there are some more complex ways to render order independent transparency from arbitrary polygon rendering order - for example, by storing all overlapping source pixels for every framebuffer pixel in linked list, then sorting everything per pixel in correct order and resolving blended transparency in back-to-front with special compute shader.
https://on-demand.gputechconf.com/gtc/2014/presentations/S4385-order-independent-transparency-opengl.pdf https://github.com/gangliao/Order-Independent-Transparency-GPU

107 posts
Least amount of steps from 2D to 3D
Replying to mmozeiko (#25912)

Okay Thanks!