KOS OpenGL: maximum triangles on-screen?

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
User avatar
bbmario
DCEmu Freak
DCEmu Freak
Posts: 88
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Wed Feb 05, 2014 5:58 am
Has thanked: 9 times
Been thanked: 3 times

KOS OpenGL: maximum triangles on-screen?

Post by bbmario »

Based on your tests, what is the maximum amount of triangles on-screen that the DC can handle, in order to achieve a decent FPS? I'm asking this because i'm currently setting the limits for game artists in our project, and i'm trying to find a good balance. Also, does anyone know any benchmark demos for the latest KOS OpenGL code?
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: KOS OpenGL: maximum triangles on-screen?

Post by BlueCrab »

There's a big difference between the maximum amount of triangles on the screen and what you'll actually get in practice. After all, you're going to have other things going in a real game that you wouldn't have in a benchmark (audio, physics, etc).

There are benchmark programs included with KOS that you can mess around with (examples/kgl/benchmarks) to give yourself an idea, but like I said, ideal conditions (nothing but rendering) and realistic conditions are two very different things...
User avatar
bbmario
DCEmu Freak
DCEmu Freak
Posts: 88
Joined: Wed Feb 05, 2014 5:58 am
Has thanked: 9 times
Been thanked: 3 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by bbmario »

I agree. It depends on the game, your culling algorithm, etc. And i understand that a lot of testing will be involved and art will have to change a lot during the course of development. But i wanted to get a rough idea of the power, so i can have some rules of thumb: 1000 polys for a first-person gun model + hands is OK, 2000 for a character is too much, should be 500. Etc.
User avatar
bogglez
Moderator
Moderator
Posts: 578
Joined: Sun Apr 20, 2014 9:45 am
Has thanked: 0
Been thanked: 0

Re: KOS OpenGL: maximum triangles on-screen?

Post by bogglez »

This is something ph3nom is going through right now as well. He's making a game together with an artist. Maybe you want to send him a private message and draw his attention to this thread
Wiki & tutorials: http://dcemulation.org/?title=Development
Wiki feedback: viewtopic.php?f=29&t=103940
My libgl playground (not for production): https://bitbucket.org/bogglez/libgl15
My lxdream fork (with small fixes): https://bitbucket.org/bogglez/lxdream
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by PH3NOM »

Truth is, the example benchmarks, are poor examples of a best case scenario.
Look at the benchmarks, calling rand() for each component of every vertex is a worst case scenario.
And those examples use immediate mode, not glDrawArrays. So, things can be optimized from those examples.

Using glDrawArrays you can easily hit some several thousand vertices per frame at 60-30 fps.
It all depends on how you arrange your render engine.
111
DCEmu Junior
DCEmu Junior
Posts: 42
Joined: Thu Jul 07, 2016 7:11 pm
Has thanked: 0
Been thanked: 6 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by 111 »

I made some tests recently with this model:
Spoiler!
Image
do note though that number of vertices is "optimized" and actually there are almost 6 times more of them (considering unique normals, uvs and colors) i.e. 2299*3 = 6897.
... and here is what I got:

1. Immediate mode, single model with interpolated animation + dynamic lighting:
Spoiler!
Image
(60fps without lighting)
2. Immediate mode, 5 models with interpolated animation + dynamic lighting:
Spoiler!
Image
3. Immediate mode, 5 models with interpolated animation, NO lighting:
Spoiler!
Image

4. Arrays, 5 models with interpolated animation + dynamic lighting:
Spoiler!
Image
5. Arrays, 5 models with interpolated animation, NO lighting:
Spoiler!
Image
So I guess glNormalPointer() is kinda broken. I got the same artifacts with a single static model and it only happens with arrays.

Anyway, I decided to avoid using lighting and swithed to "baked" vertex colors, so

6. Arrays, 5 models with interpolated animation + vertex colors:
Spoiler!
Image

I'm not sure if everything was compiled with optimizations, since I have no clue how to switch between "debug" and "release" modes or whatever it is called in gcc\makefiles etc (anyone willing to explain, please? From what I've read, it is something to do with "-o" flag, but where exactly am I supposed to specify it?), and whether or not switching to triangle strips worth the effort, but so far I'm glad with the result.

And I'd like to thank PH3NOM for all the hard work he put into improving KGL.

ps: sorry for bad english, if any.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: KOS OpenGL: maximum triangles on-screen?

Post by BlueCrab »

111 wrote:I'm not sure if everything was compiled with optimizations, since I have no clue how to switch between "debug" and "release" modes or whatever it is called in gcc\makefiles etc (anyone willing to explain, please? From what I've read, it is something to do with "-o" flag, but where exactly am I supposed to specify it?), and whether or not switching to triangle strips worth the effort, but so far I'm glad with the result.
By default, KOS compiles things with the -O2 flag (so, optimization level 2) and with frame pointers turned off. Unless you changed things in the default setup, you've got normal optimizations turned on. :wink:
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by PH3NOM »

111 wrote:And I'd like to thank PH3NOM for all the hard work he put into improving KGL.
You are welcome my friend! It is good to see people trying to do things with it 8-)

A question, what model format is that? I can probably help with some ideas to optimize things a bit if you dont mind sharing your render routine code.

And do you unpack / interpolate all 5 models each frame?
Because that consumes a large amount of CPU time that is not being used by OpenGL.
What I am getting at is that to really test the speed of OpenGL rendering, a raw throughput benchmark would be to unpack / interpolate that model 1x and then render that 1 model 5x each frame ( simply adjust the translation matrix each render pass to render the model at a given position )

And it will be hard to determine your issues with dynamic lighting without looking at your code...
111
DCEmu Junior
DCEmu Junior
Posts: 42
Joined: Thu Jul 07, 2016 7:11 pm
Has thanked: 0
Been thanked: 6 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by 111 »

thanks, BlueCrab.
===================
PH3NOM wrote: A question, what model format is that?
it's a simple custom format. Nothing fancy - just a list or vertices, normals, uvs, colors, indices and keyframes, one after another, so I can fread() everything.
I can probably help with some ideas to optimize things a bit if you dont mind sharing your render routine code.
thanks, but I don't really aim for the best possible optimization (at least right now), I just needed something simple to work with.
But here is part of the code:
Spoiler!

Code: Select all

void amh_render_IM (S_AMH *amh, int kf_1, int kf_2, float t)
{
	int i,j,  fa, fb, fc, tfa, tfb, tfc, cfa, cfb, cfc;
	kmVec3 v1, _v1, v2, _v2, v3, _v3;
	kmMat4 m_cur_obj;
	kmQuaternion q_cur_obj, q_next_obj, q_final;

	for (i = 0; i < amh->num_objs; i++)
	{
		kmMat4Identity(&m_cur_obj);

		kmQuaternionFill(&q_cur_obj, amh->mdl_objs[i].keys[kf_1].q_x, amh->mdl_objs[i].keys[kf_1].q_y,
			amh->mdl_objs[i].keys[kf_1].q_z, amh->mdl_objs[i].keys[kf_1].q_w);
		kmQuaternionFill(&q_next_obj, amh->mdl_objs[i].keys[kf_2].q_x, amh->mdl_objs[i].keys[kf_2].q_y,
			amh->mdl_objs[i].keys[kf_2].q_z, amh->mdl_objs[i].keys[kf_2].q_w);

		kmQuaternionSlerp(&q_final, &q_cur_obj, &q_next_obj, t);

		kmMat4RotationQuaternion(&m_cur_obj, &q_final);
		m_cur_obj.mat[12] = amh->mdl_objs[i].keys[kf_1].pos_x + (amh->mdl_objs[i].keys[kf_2].pos_x - amh->mdl_objs[i].keys[kf_1].pos_x)*t;
		m_cur_obj.mat[13] = amh->mdl_objs[i].keys[kf_1].pos_y + (amh->mdl_objs[i].keys[kf_2].pos_y - amh->mdl_objs[i].keys[kf_1].pos_y)*t;
		m_cur_obj.mat[14] = amh->mdl_objs[i].keys[kf_1].pos_z + (amh->mdl_objs[i].keys[kf_2].pos_z - amh->mdl_objs[i].keys[kf_1].pos_z)*t;


		for (j = 0; j < amh->mdl_objs[i].f_count; j++)
		{

			fa = amh->mdl_objs[i].ar_faces[j].a;
			fb = amh->mdl_objs[i].ar_faces[j].b;
			fc = amh->mdl_objs[i].ar_faces[j].c;

			tfa = amh->mdl_objs[i].ar_tfaces[j].a;
			tfb = amh->mdl_objs[i].ar_tfaces[j].b;
			tfc = amh->mdl_objs[i].ar_tfaces[j].c;

			cfa = amh->mdl_objs[i].ar_cfaces[j].a;
			cfb = amh->mdl_objs[i].ar_cfaces[j].b;
			cfc = amh->mdl_objs[i].ar_cfaces[j].c;

			v1.x = amh->mdl_objs[i].ar_verts[fa].x;
			v1.y = amh->mdl_objs[i].ar_verts[fa].y;
			v1.z = amh->mdl_objs[i].ar_verts[fa].z;
			kmVec3Transform(&_v1, &v1, &m_cur_obj);


			v2.x = amh->mdl_objs[i].ar_verts[fb].x;
			v2.y = amh->mdl_objs[i].ar_verts[fb].y;
			v2.z = amh->mdl_objs[i].ar_verts[fb].z;
			kmVec3Transform(&_v2, &v2, &m_cur_obj);


			v3.x = amh->mdl_objs[i].ar_verts[fc].x;
			v3.y = amh->mdl_objs[i].ar_verts[fc].y;
			v3.z = amh->mdl_objs[i].ar_verts[fc].z;
			kmVec3Transform(&_v3, &v3, &m_cur_obj);

			

			glTexCoord2f( amh->mdl_objs[i].ar_uvs[tfa].u, amh->mdl_objs[i].ar_uvs[tfa].v );
			glColor4ub( amh->mdl_objs[i].ar_colors[cfa].argb[0], amh->mdl_objs[i].ar_colors[cfa].argb[1],
						amh->mdl_objs[i].ar_colors[cfa].argb[2], amh->mdl_objs[i].ar_colors[cfa].argb[3]);
			glNormal3f ( amh->mdl_objs[i].ar_norms[fa].x, amh->mdl_objs[i].ar_norms[fa].y, amh->mdl_objs[i].ar_norms[fa].z );
			glVertex3f (_v1.x, _v1.y, _v1.z );

			glTexCoord2f( amh->mdl_objs[i].ar_uvs[tfb].u, amh->mdl_objs[i].ar_uvs[tfb].v );
			glColor4ub( amh->mdl_objs[i].ar_colors[cfb].argb[0], amh->mdl_objs[i].ar_colors[cfb].argb[1],
						amh->mdl_objs[i].ar_colors[cfb].argb[2], amh->mdl_objs[i].ar_colors[cfb].argb[3]);
			glNormal3f ( amh->mdl_objs[i].ar_norms[fb].x, amh->mdl_objs[i].ar_norms[fb].y, amh->mdl_objs[i].ar_norms[fb].z );
			glVertex3f (_v2.x, _v2.y, _v2.z );

			glTexCoord2f( amh->mdl_objs[i].ar_uvs[tfc].u, amh->mdl_objs[i].ar_uvs[tfc].v );
			glColor4ub( amh->mdl_objs[i].ar_colors[cfc].argb[0], amh->mdl_objs[i].ar_colors[cfc].argb[1],
						amh->mdl_objs[i].ar_colors[cfc].argb[2], amh->mdl_objs[i].ar_colors[cfc].argb[3]);
			glNormal3f ( amh->mdl_objs[i].ar_norms[fc].x, amh->mdl_objs[i].ar_norms[fc].y, amh->mdl_objs[i].ar_norms[fc].z );
			glVertex3f (_v3.x, _v3.y, _v3.z );

		}
	}
}
arrays version is mostly the same, but instead of immediate mode calls, I loop through entire vertex array and apply interpolated matrix. Then I call this:

Code: Select all

void amh_render_arrays_Keyframe(S_AMH *amh, S_AMH_ARRAYS *msh_parts)
{
	int i;
	for (i = 0; i < amh->num_objs; i++)
	{
		glEnableClientState (GL_VERTEX_ARRAY);
		glEnableClientState (GL_COLOR_ARRAY);
		glEnableClientState (GL_NORMAL_ARRAY);
		glEnableClientState (GL_TEXTURE_COORD_ARRAY);

		glVertexPointer(3, GL_FLOAT, 0, msh_parts->msh_objs[i].out_verts);
		glNormalPointer(GL_FLOAT, 0, msh_parts->msh_objs[i].out_norms);
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, msh_parts->msh_objs[i].out_colors);
		glTexCoordPointer(2, GL_FLOAT, 0, msh_parts->msh_objs[i].out_uvs);

		glDrawArrays(GL_TRIANGLES, 0, amh->mdl_objs[i].f_count*3);

		glDisableClientState (GL_VERTEX_ARRAY);
		glDisableClientState (GL_COLOR_ARRAY);
		glDisableClientState (GL_NORMAL_ARRAY);
		glDisableClientState (GL_TEXTURE_COORD_ARRAY);
	}
}
I set up arrays once during initializations.
What I am getting at is that to really test the speed of OpenGL rendering, a raw throughput benchmark would be to unpack / interpolate that model 1x and then render that 1 model 5x each frame ( simply adjust the translation matrix each render pass to render the model at a given position )
that is exactly what I am doing. Like this:
Spoiler!

Code: Select all

render()
{
/*...*/
        /* transform vertices of every object\model part */
	amh_transform_arrays(&amh_01, &amh_arr_01, g_current_frame, g_next_frame, lerp_t);


	glPushMatrix();
		glTranslatef(-10.0f, -2.0f, z);
		glRotatef(xrot, 1.0f, 0.0f, 0.0f);
		glRotatef(yrot, 0.0f, 1.0f, 0.0f);
		amh_render_arrays_Keyframe(&amh_01, &amh_arr_01);
	glPopMatrix();
/* ...
    ^ amh_render_arrays_keyframe() repeats five times with different x offset */
}
And it will be hard to determine your issues with dynamic lighting without looking at your code...
well, everything works just fine on Windows. I checked exported normals manually in a hex editor and during debug, so I'm sure everything is correct there. All arrays have the same size i.e. 1 vertex = 1 normal = 1 uv = 1 color.

As I said before, lightning is more or less fine in immediate mode.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by PH3NOM »

I see you are using a skeletal mesh format - these are much more efficient in memory usage but much more demanding on CPU usage on DC since it has no GPU T&L.

I am curious how much of your frame time is spent on preparing the mesh for render?

Frame Interpolations are especially taxing on the DC's CPU, as you have to transform the mesh to the skeleton in 2 positions and interpolate between the 2...
A simple optimization I have done is keep 2 frame buffers for your model, one for each frame of animation being interpolated.
This way can save some real CPU time ( in a best case scenario, you only have to interpolate between the 2 prepared meshes and can avoid all quaternion math transforms per vertex each frame ), but then consumes more memory, so we need to understand the tradeoffs here...

You do not post the code for your kmVec3, kmMat4, or kmQuaternion math functions.
These are all functions that can be easily optimized using the SH4 SIMD FPU fast vector math operations...
111
DCEmu Junior
DCEmu Junior
Posts: 42
Joined: Thu Jul 07, 2016 7:11 pm
Has thanked: 0
Been thanked: 6 times

Re: KOS OpenGL: maximum triangles on-screen?

Post by 111 »

No, this is not exactly a skeletal animation (I almost implemented it first, but I had some troubles with exporting\assigning skinning data the way I wanted (only 1 bone per vertex with weight = 1), so I went for a simpler approach). It's an "object transform" animation (used in games like resident evil 1-3, gta3 etc) I think it is pretty obvious (looking at the character's knees and elbows) that model is split into several parts, so keyframes only hold transforms of those objects. Which is good, compared to morphing (i.e. MD2 etc).
The model is WIP and left unoptimized specially for testing purposes. The final one (and others) will have around 1000-1200 triangles.
I am curious how much of your frame time is spent on preparing the mesh for render?
I have not checked this yet (not that I know how to use profiling tools).
Still, it is a temporary solution i.e. I won't build arrays at run time later.
You do not post the code for your kmVec3, kmMat4, or kmQuaternion math functions.
it's from kazmath lib.
These are all functions that can be easily optimized using the SH4 SIMD FPU fast vector math operations...
I'll consider that, thanks.


Perhaps I should do more tests with static meshes only (we'll see, once that clipping issue is gone).
Post Reply