Array member by index

Didn’t see anything in the search that seemed to resemble what I’m gonna ask so just starting a new topic for it, I’d like to do something like the below in my vertex crafter.

struct MOD
{
	vec3 pos;
	vec3 dye;
	vec3 rot;
};

in int object_index;
in int member_index;
in MOD vertex;
uniform MOD *objects;
uniform MOD *members;

void main()
{
	MOD object = objects[object_index];
	MOD member = members[member_index];
	...
}

If this is possible could someone give me a quick and dirty pseudo example in the form of:

create_objects(vao)
{
	...
	glGen*()
	...
}
create_members(count)
{
	...
	glGen*
	...
}
use_opengl()
{
	...
	create_objects(vao)
	create_members(count)
	...
	while(...)
	{
		focus_objects(vao)
		focus_members(n)
		for ( m = 0; m < count; ++m )
		{
			focus_member(m)
		}
	}
}

As you can see I don’t need you to fill in the variables, I just need to know what functions I’m calling and roughly where

GLSL doesn’t have pointers. So you’re going to have to declare arrays. Depending on how big these arrays are, you’ll likely want to use UBOs or SSBOs.

Also, vertex shader inputs cannot be structs. So that isn’t going to work.

It’s not clear what these functions are supposed to do, so it’s rather hard to fill anything in. You use the word “focus” a lot; what does that mean?

That’s disappointing :expressionless:

This minimum 30 character requirement is annoying and wasteful, all these extra bytes for a post that would’ve been fine without it.

Consider this: if you find that it is important to convey your “disappointment”, clearly specifying which thing you find to be “disappointing” would be helpful in adequately conveying this. Are you talking about the pointer/array business or that someone asked you to explain what the other code was trying to do?

Alternatively, explaining why you find it to be disappointing would also be more useful than just conveying what you feel. It would be something that could be useful to more than just yourself, as it could allow someone to explain something to you.

The point of the 30 character minimum is to get you to make more meaningful posts. “That’s disappointing” is hardly the best, most useful thing you could say.

I didn’t even notice you asked what I was trying to do, simply put each vertex was to be from a member of an object, could think of each object as a model of something, each member of the model would be some joint of it, and then there’s the vertices of said joint, so calculations would be vertex effected by joint effected by model.

Kept thinking of objects and parts, until this post I didn’t think to call them models and joints.

Welp, in the process of converting to using allocated arrays I managed to break something because I don’t even get a window, since debugging isn’t pulling anything up I’ll just have to dump code here and ask if anyone sees something wrong with it, the first dump will be of code that initialises the models and joint (IDs are generated at the time of array creation so only need to have details explained to opengl at this point:

	void init_model( MODEL *model )
	{
		JOINT *joints = model->joints->addr, *joint = joints + 1;

		glExec( NULL, glBindVertexArray( model->id ) );
			glExec( NULL, glBindBuffer( GL_ARRAY_BUFFER, joint->id ) );
			glExec
			(
				NULL
				, glBufferData
				(
					GL_ARRAY_BUFFER
					, sizeof(ALTER)
					, joints->points->addr
					, GL_STATIC_DRAW
				)
			);

			//glVertexAttribDivisor( model->self_id, sizeof(TRIANGLE) / sizeof(VERTEX) );
			glExec( NULL, glEnableVertexAttribArray( app.loc_point ) );
			glExec( NULL, glVertexAttribPointer
			(
			   app.loc_point,			// attribute 0. No particular reason for 0, but must match the layout in the shader.
			   3,						// size
			   GL_FLOAT,				// type
			   GL_FALSE,				// normalized?
			   sizeof(ALTER),				// stride
			   (void*)offsetof(ALTER,pos) // array buffer offset
			) );

			glExec( NULL, glEnableVertexAttribArray( app.loc_color ) );
			glExec( NULL, glVertexAttribPointer
			(
			   app.loc_color,			// attribute 0. No particular reason for 0, but must match the layout in the shader.
			   3,						// size
			   GL_FLOAT,				// type
			   GL_FALSE,				// normalized?
			   sizeof(ALTER),				// stride
			   (void*)offsetof(ALTER,dye) // array buffer offset
			) );

		glBindVertexArray(0);
	}

	glExec( NULL, glUseProgram( program->id ) );
	init_model( empty_model );
	init_model( char0_model );
	init_model( char1_model );

And just in case it held any relevance, the vertex crafter code:

#version 330

varying vec4 pigment;

struct ALTER
{
	vec3 pos;
	vec3 dye;
	vec3 rot;
};

uniform ALTER model;
uniform ALTER joint;

in vec3 point;
in vec3 color;
in vec3 alter; // Position of rot member, currently has no purpose

vec3 rotate( vec3 pos, ALTER o )
{
	return (pos * o.rot) + o.pos;
}

vec3 colour( vec3 dye, ALTER o )
{
	return dye * o.dye;
}

void main()
{
	gl_Position = vec4( rotate( rotate( point, joint ), model ), 1.0);
	pigment = vec4( colour( colour( color, joint ), model ), 1.0);
}

Just got outa bed, since I see neither responses nor if there is a problem in the previous code posted I’ll post the initiation code now:

LIST* new_model_list
(
	INDEX want_models
	, INDEX want_joints_per_model
	, INDEX want_points_per_joint
)
{
	LIST* list = new_list( MODEL, want_models );
	MODEL *models;

	if ( !list )
		return NULL;

	models = list->addr;

	for ( INDEX m = 0; m < want_models; m++ )
	{
		MODEL *model = models + m;
		JOINT *joints;

		model->joints = new_list( JOINT, want_joints_per_model );

		if ( !(model->joints) )
			return term_model_list( list, m );

		joints = model->joints->addr;

		for ( INDEX	j = 0; j < want_joints_per_model; ++j )
		{
			JOINT *joint = joints + j;

			joint->points = new_list( ALTER, want_points_per_joint );

			if ( !(joint->points) )
				return term_model_list( list, m + 1 );
		}
	}

	return list;
}

LIST* init_opengl
(
	INDEX want_models
	, INDEX want_joints_per_model
	, INDEX want_points_per_joint
)
{
	CRAFTER *program;
	MODEL *models1, *models2;

#ifndef RELEASE
    glEnable( GL_DEBUG_OUTPUT );
#endif

	app.crafters = load_and_init_crafters
	(
		2,
		GL_VERTEX_SHADER, "builder.glsl",
		GL_FRAGMENT_SHADER, "painter.glsl"
	);

	if ( !(app.crafters) )
		return NULL;

	program = app.crafters->addr;

	app.loc_model = glGetUniformLocation( program->id, "model" );
	app.loc_joint = glGetUniformLocation( program->id, "joint" );
    app.loc_point = glGetAttribLocation( program->id, "point");
    app.loc_color = glGetAttribLocation( program->id, "color");
    app.loc_alter = glGetAttribLocation( program->id, "alter");

    app.models1 =
		new_model_list
		(
			want_models
			, want_joints_per_model
			, want_points_per_joint
		)
	;

	app.models2 =
		new_model_list
		(
			want_models
			, want_joints_per_model
			, want_points_per_joint
		)
	;

	if ( !(app.models) )
	{
		app.crafters = term_crafters
		(
			&(program->code)
			, app.crafters
			, app.crafters->used
			, false
		);
		return NULL;
	}

	models1 = app.models1->addr;
	models2 = app.models2->addr;

	for ( INDEX m = 0; m < want_models; ++m )
	{
		MODEL *model1 = models1 + m, *model2 = models2 + m;
		JOINT
			*joints1 = model1->joints->addr
			, *joints2 = model2->joints->addr;

		glExec( NULL, glGenVertexArrays( 1, &(model1->id) ) );
		model1->generated = true;
		model2->generated = true;
		model2->id = model1->id;

		for ( INDEX j = 0; j < want_joints_per_model; ++j )
		{
			JOINT *joint1 = joints1 + j, *joint2 = joints2 + j;

			glGenBuffers( 1, &(joint1->id) );
			joint1->generated = true;
			joint2->generated = true;
			joint2->id = joint1->id;
		}
	}

	app.models = app.models1;

	return app.models;
}

If anyone sees anything off please let me know so I can either explain or investigate (depends what it is)

Managed to get some debug output once I ran under the gede debugger, problem is the output wasn’t informative enough so I went and wrote some functions to convert the numbers into more meaningful details but when I did that all the lines using debug defines wouldn’t compile because apparently the defines don’t exist, could someone tell me what header to include for them is a simple google search is not bringing it up for me, instead it just brings up how to use them.

char const * glSourceToString( GLenum source )
{
	switch ( source )
	{
	case DEBUG_SOURCE_API:				return "DEBUG_SOURCE_API";
	case DEBUG_SOURCE_WINDOW_SYSTEM:	return "DEBUG_SOURCE_WINDOW_SYSTEM";
	case DEBUG_SOURCE_SHADER_COMPILER:	return "DEBUG_SOURCE_SHADER_COMPILER";
	case DEBUG_SOURCE_THIRD_PARTY:		return "DEBUG_SOURCE_THIRD_PARTY";
	case DEBUG_SOURCE_APPLICATION:		return "DEBUG_SOURCE_APPLICATION";
	case DEBUG_SOURCE_OTHER:			return "DEBUG_SOURCE_OTHER";
	}

	return "GL_SOURCE_UNKNOWN";
}

char const * glReportToString( GLuint report )
{
	switch ( report )
	{
		case 0:							return "GL_REPORT";
		case DEBUG_TYPE_DEPRECATED_BEHAVIOR:
			return "DEBUG_TYPE_DEPRECATED_BEHAVIOR";
		case DEBUG_TYPE_ERROR:			return "DEBUG_TYPE_ERROR";
		case DEBUG_TYPE_MARKER:			return "DEBUG_TYPE_MARKER";
		case DEBUG_TYPE_OTHER:			return "DEBUG_TYPE_OTHER";
		case DEBUG_TYPE_PERFORMANCE:	return "DEBUG_TYPE_PERFORMANCE";
		case DEBUG_TYPE_PORTABILITY:	return "DEBUG_TYPE_PORTABILITY";
		case DEBUG_TYPE_PUSH_GROUP:		return "DEBUG_TYPE_PUSH_GROUP";
		case DEBUG_TYPE_POP_GROUP:		return "DEBUG_TYPE_POP_GROUP";
		case DEBUG_TYPE_UNDEFINED_BEHAVIOR:
			return "DEBUG_TYPE_UNDEFINED_BEHAVIOR";
		case GL_CONTEXT_LOST:			return "GL_CONTEXT_LOST";
		case GL_INVALID_ENUM:			return "GL_INVALID_ENUM";
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			return "GL_INVALID_FRAMEBUFFER_OPERATION";
		case GL_INVALID_OPERATION:		return "GL_INVALID_OPERATION";
		case GL_INVALID_VALUE:			return "GL_INVALID_VALUE";
		case GL_STACK_OVERFLOW:			return "GL_STACK_OVERFLOW";
		case GL_STACK_UNDERFLOW:		return "GL_STACK_UNDERFLOW";
		case GL_OUT_OF_MEMORY:			return "GL_OUT_OF_MSEMORY";
		case GL_TABLE_TOO_LARGE:		return "GL_TABLE_TOO_LARGE";
	}

	return "GL_ERROR_UNKNOWN";
}

char const * glWeightToString( GLenum weight )
{
	switch ( weight )
	{
	case DEBUG_SEVERITY_HIGH:			return "DEBUG_SEVERITY_HIGH";
	case DEBUG_SEVERITY_MEDIUM:			return "DEBUG_SEVERITY_MEDIUM";
	case DEBUG_SEVERITY_LOW:			return "DEBUG_SEVERITY_LOW";
	case DEBUG_SEVERITY_NOTIFICATION:	return "DEBUG_SEVERITY_NOTIFICATION";
	}

	return "GL_SEVERITY_UNKNOWN";
}

https://www.khronos.org/opengl/wiki/Debug_Output
The tables in the above document are confusing, they should have the GL_ prefix on them, didn’t find out until a while ago. If someone here has access to that then please correct them, I ended up creating a pointless post based on incorrect information.

Well I managed to track the cause of the window not appearing, my error catching was doing it’s job, preventing the worst case scenario, it just failed to be verbose about it. Now putting aside the black screen I get in the window that is now appearing I’m getting an error with the uniforms and I can’t see why. I screenshoted what gede is showing me but I still can’t see why the uniform is producing an error (might have uploaded the wrong screenshot, I’ll leave an edit after I check what screen shot shows up)

Edit: Yeah it’s the right screenshot

For starters, run down this list, and verify that none of these apply. My guess is that one will point you to your problem:

Thanks, turns out I misunderstood the function, instead of referring to offsets it’s referring to the index of members, at least that’s how it seems to be behave because when I switched to using + 0, + 1 etc instead of +0, +3 etc it stopped complaining. There was another issue that cropped up after but I was also getting a segfault that I didn’t understand how I reached so I ran valgrind only to discover there’s a problem with malloc & co, so I wrote my own bunch using mmap(), seems to work fine and I got past some segfaults that I couldn’t before, now I’m trying to figured out why it fails to get memory for functions that worked before, I’m thinking it’s just an inefficiency with how I allocate space from the pages that I acquired, I also gotta get round to making it thread safe with page locks

Done with segfault checking, now I’m having trouble getting my triangles to draw, atm I can only verify that the values in the CPU side vertex array are being filled correctly, I know I’m overlooking something but I just don’t know what. here’s the output of checking the vertex contents:

./d.out
[OPENGL ERROR 0x8251 (33361)] GL_DEBUG_TYPE_OTHER hunt empty_model from GL_DEBUG_SOURCE_SHADER_COMPILER, weight GL_DEBUG_SEVERITY_NOTIFICATION:
Shader Stats: SGPRS: 8 VGPRS: 28 Code Size: 32 LDS: 0 Scratch: 0 Max Waves: 8 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
[OPENGL ERROR 0x8251 (33361)] GL_DEBUG_TYPE_OTHER hunt empty_model from GL_DEBUG_SOURCE_SHADER_COMPILER, weight GL_DEBUG_SEVERITY_NOTIFICATION:
Shader Stats: SGPRS: 16 VGPRS: 8 Code Size: 64 LDS: 0 Scratch: 0 Max Waves: 8 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
Memory leak in crafters list!
main.c:143: desc = char0_model, rot = { 0, 0 }
main.c:150: pos = { 0.000000, 0.000000, 0.000000 }, dye = { 0.000000, 0.000000, 0.000000 }, rot = { 1.000000, 1.000000, 0.000000 }
main.c:172: pos0 = { 0.000000, 0.500000, 0.000000 }, dye0 = { 0.500000, 0.500000, 1.000000 }
main.c:172: pos1 = { 0.250000, 0.000000, 0.000000 }, dye1 = { 0.500000, 1.000000, 1.000000 }
main.c:172: pos2 = { 0.750000, 0.000000, 0.000000 }, dye2 = { 1.000000, 1.000000, 1.000000 }
main.c:143: desc = view0_model, rot = { 0, 0 }
main.c:150: pos = { 0.000000, 0.000000, 0.000000 }, dye = { 0.000000, 0.000000, 0.000000 }, rot = { 1.000000, 1.000000, 0.000000 }
main.c:172: pos0 = { 0.000000, 0.000000, 0.000000 }, dye0 = { 0.000000, 0.000000, 0.000000 }
main.c:172: pos1 = { 0.000000, 0.000000, 0.000000 }, dye1 = { 0.000000, 0.000000, 0.000000 }
main.c:172: pos2 = { 0.000000, 0.000000, 0.000000 }, dye2 = { 0.000000, 0.000000, 0.000000 }
main.c:143: desc = char1_model, rot = { 0, 0 }
main.c:150: pos = { 0.000000, 0.000000, 0.000000 }, dye = { 0.000000, 0.000000, 0.000000 }, rot = { 1.000000, 1.000000, 0.000000 }
main.c:172: pos0 = { 0.000000, 0.500000, 0.000000 }, dye0 = { 0.500000, 1.000000, 0.500000 }
main.c:172: pos1 = { 0.250000, 1.000000, 0.000000 }, dye1 = { 0.500000, 1.000000, 1.000000 }
main.c:172: pos2 = { 0.750000, 1.000000, 0.000000 }, dye2 = { 1.000000, 1.000000, 1.000000 }
main.c:143: desc = char0_model, rot = { 0, 0 }
main.c:150: pos = { 0.000000, 0.000000, 0.000000 }, dye = { 0.000000, 0.000000, 0.000000 }, rot = { 1.000000, 1.000000, 0.000000 }
main.c:172: pos0 = { 0.000000, 0.500000, 0.000000 }, dye0 = { 0.500000, 0.500000, 1.000000 }
main.c:172: pos1 = { 0.250000, 0.000000, 0.000000 }, dye1 = { 0.500000, 1.000000, 1.000000 }
main.c:172: pos2 = { 0.750000, 0.000000, 0.000000 }, dye2 = { 1.000000, 1.000000, 1.000000 }

And here’s the function that deals with everything after the crafters/shaders have been compiled, linked, buffer IDs generated and variable locations from them retrieved

int draw_opengl()
{
	CRAFTER *program = app.crafters->addr
		, *builder = program + 1
		, *painter = program + 2;
	MODEL
		*models = app.models->addr,
		*empty_model = models
		, *char0_model = empty_model + 1
		, *view0_model = char0_model + 1
		, *char1_model = view0_model + 1
	;
	JOINT
		*empty_joint = nth_joint( empty_model, 1 )
		, *char0_joint = nth_joint( char0_model, 1 )
		, *view0_joint = nth_joint( view0_model, 1 )
		, *char1_joint = nth_joint( char1_model, 1 )
	;
	ALTER
		*empty_triad = empty_joint->points->addr
		, *char0_triad = char0_joint->points->addr
		, *view0_triad = view0_joint->points->addr
		, *char1_triad = char1_joint->points->addr;

	empty_model->desc = "empty_model";
	char0_model->desc = "char0_model";
	view0_model->desc = "view0_model";
	char1_model->desc = "char1_model";

	empty_joint->desc = "empty_joint";
	char0_joint->desc = "char0_joint";
	view0_joint->desc = "view0_joint";
	char1_joint->desc = "char1_joint";

	memcpy( empty_triad, &empty_triangle, sizeof(empty_triangle) );
	memcpy( char0_triad, &char0_triangle, sizeof(char0_triangle) );
	memcpy( char1_triad, &char1_triangle, sizeof(char1_triangle) );

	void update_altered( uint loc, ALTER *o )
	{
		if ( loc < (uint)-1 )
		{
			uint off = 1;
			glExec( NULL, glUniform3fv( loc + off + 0, 1, o->pos ) );
			glExec( NULL, glUniform3fv( loc + off + 1, 1, o->dye ) );
			glExec( NULL, glUniform3fv( loc + off + 2, 1, o->rot ) );
		}
	}

	void init_model( MODEL *model )
	{
		JOINT *joints = model->joints->addr, *joint = joints + 1;

		glExec( NULL, glBindVertexArray( model->id ) );
			glExec( NULL, glBindBuffer( GL_ARRAY_BUFFER, joint->id ) );
			glExec
			(
				NULL
				, glBufferData
				(
					GL_ARRAY_BUFFER
					, sizeof(ALTER)
					, joints->points->addr
					, GL_STATIC_DRAW
				)
			);

			//glVertexAttribDivisor( model->self_id, sizeof(TRIANGLE) / sizeof(VERTEX) );
			glExec( NULL, glEnableVertexAttribArray( app.loc_point ) );
			glExec( NULL, glVertexAttribPointer
			(
			   app.loc_point,				// location
			   3,							// size
			   GL_FLOAT,					// type
			   GL_FALSE,					// normalized?
			   sizeof(ALTER),				// stride
			   (void*)offsetof(ALTER,pos)	// vertex offset
			) );

			glExec( NULL, glEnableVertexAttribArray( app.loc_color ) );
			glExec( NULL, glVertexAttribPointer
			(
			   app.loc_color,				// location
			   3,							// size
			   GL_FLOAT,					// type
			   GL_FALSE,					// normalized?
			   sizeof(ALTER),				// stride
			   (void*)offsetof(ALTER,dye) 	// vertex offset
			) );

		glBindVertexArray(0);
	}

	glExec( NULL, glUseProgram( program->id ) );
	init_model( empty_model );
	init_model( char0_model );
	init_model( char1_model );

	fill_model( char0_model, 0, 0, 0, 0, 0, char0_triad );
	fill_model( view0_model, 0, 0, 0, 0, 0, view0_triad );
	fill_model( char1_model, 0, 0, 0, 0, 0, char1_triad );

	update_altered( app.loc_model, &(char0_model->mod) );
	update_altered( app.loc_joint, &(char0_joint->mod) );

	void draw_model( MODEL *model )
	{
		LIST *list = model->joints;
		JOINT *joints = list->addr, *joint;
		//glExec( NULL, glEnableVertexAttribArray( model->self_id ) );
		glExec( NULL, glBindVertexArray( model->id ) );

		update_altered( app.loc_model, &(model->mod) );

		for ( INDEX n = 1; n < list->used; ++n )
		{
			joint = joints + n;
			update_altered( app.loc_joint, &(joint->mod) );
			glExec( NULL, glDrawArrays( GL_TRIANGLES, 0, 3 ) );
		}

		//glVertexAttrib3fv( model->self_id, (float*)(&user_trirot) );
		glExec( NULL, glBindVertexArray( empty_model->id ) );
		//glExec( NULL, glDisableVertexAttribArray( model->self_id ) );
	}

	while ( !glfwWindowShouldClose( app.window ) )
	{
		float ratio = (float)(app.span[VEC_X]) / (float)(app.span[VEC_Y]);
		FMAT4X4 m = {0}, p = {0}, mvp = {0};

		app.frame = glfwGetTime();
		app.deltaFrame = app.frame - app.lastFrame;
		app.lastFrame = app.frame;

		/* Make sure GFX card or GPU knows which of it's programs it's using */
		glExec( NULL, glUseProgram( program->id ) );

		/* Clear the screen */
		glExec( NULL, glViewport( 0, 0, app.span[VEC_X], app.span[VEC_Y] ) );
		glExec( NULL, glClearColor( 0, 0, 0, 0 ) );
		glExec( NULL, glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) );

#ifdef USE_MATRIX
		fmat4x4_identify( m );
		fmat4x4_rotate_Z( m, m, app.frame );
		fmat4x4_ortho( p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f );
		fmat4x4_mul( mvp, p, m );

		glExec
		(
			NULL
			, glUniformMatrix4fv
			(
				app.mvp_location
				, 1
				, GL_FALSE
				, (float*)mvp
			)
		);
#endif

		draw_model( char0_model );

		/* Hand over to the GFX card or GPU */
		glExec( NULL, glfwSwapBuffers( app.window ) );

		/* Get any new position data before constructing the next frame */
		glExec( NULL, glfwPollEvents() );
	}

	return 0;
}

Can anyone see what I’ve overlooked?

Kay, started a fresh, went through the effort of setting up buffers for vertices and indices, the only code my draw loop calls is poll events & this:

void glfwRefreshCB( GLFWwindow *window )
{
	// Clear the screen
	glClearColor( 0, 0, 0, 0 );
	glClear( GL_COLOR_BUFFER_BIT );

	for ( uint attr = 0; attr < SPOT_COUNT; ++attr )
	{
		BUFF *Buff = &(core.SpotIndexBuffers[attr]);
		uint values;

		if ( attr != SPOT_PLACE && attr != SPOT_COLOR )
			continue;

		if ( attr == SPOT_COLOR )
		{
			values = 4;
			glBindVertexArray( core.QuadsID );
		}
		else if ( attr == SPOT_COORD )
		{
			values = 2;
			glBindVertexArray( core.PairsID );
		}
		else
		{
			values = 3;
			glBindVertexArray( core.TriosID );
		}

		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.SpotIDs[attr] );
		glBufferData
		(
			GL_ELEMENT_ARRAY_BUFFER,
			Buff->size,
			Buff->addr,
			GL_DYNAMIC_DRAW
		);
		glVertexAttribPointer
		(
			core.SpotAttribLocations[attr],
			values,
			GL_ELEMENT_ARRAY_BUFFER,
			GL_FLOAT,
			GL_FALSE,
			NULL
		);
	}

	glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL );
	glfwSwapBuffers(window);
}

Currently getting a black screen, while I’m checking for anything I may have forgot (like actually adding the indices to the index buffers) could someone check the above for anything they think is handled wrong, I’m hoping it’s correct because while an easy to understand concept it is difficult to actually use index buffers for the first time, it’s like multi-threaded memory handling, once you got it right the first time you’re fine thereafter but until you do you’re tearing your hair out (not literally). FYI Currently the only two values used by the vertex crafter/shader is SPOT_PLACE & SPOT_COLOR, everything else has an attribute but no content to the index buffer hence filter at the top of the loop.

Forgot to setup the buffers, when I tried just now I got errors and no matter how much I re-order and try different values I can’t get the attribute functions to stop thowing an INVALID_OPERATION error, someone mind using the previous code I posted to tell me how I should be laying this out (btw I renamed *ID to *BufferID for the vector holding buffers)

/* Setup vec4 buffer */
	glX( NULL, glGenVertexArrays( 1, &(core.QuadsArrayID) ) );
	glX( NULL, glGenBuffers( 1, &(core.QuadsBufferID) ) );
	glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.QuadsBufferID ) );
	glX( NULL, glBufferData
	(
		GL_ARRAY_BUFFER,
		core.Quads.size,
		core.Quads.addr,
		GL_STATIC_DRAW
	) );
	glX( NULL, glVertexAttribPointer
	(
		core.SpotAttribLocations[SPOT_COLOR],
		4,
		GL_ARRAY_BUFFER,
		GL_FLOAT,
		GL_FALSE,
		NULL
	) );
	glX( NULL, glGenBuffers( 1, &(core.SpotIDs[SPOT_COLOR]) ) );
	glX( NULL, glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.SpotIDs[SPOT_COLOR] ) );

	/* Setup vec3 buffer */
	glX( NULL, glGenVertexArrays( 1, &(core.TriosArrayID) ) );
	glX( NULL, glGenBuffers( 1, &(core.TriosBufferID) ) );
	glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.TriosBufferID ) );
	for ( uint buff = SPOT_PLACE; buff < SPOT_COUNT; ++buff )
	{
		glX( NULL, glVertexAttribPointer
		(
			core.SpotAttribLocations[buff],
			3,
			GL_ELEMENT_ARRAY_BUFFER,
			GL_FLOAT,
			GL_FALSE,
			NULL
		) );
	}
	glX( NULL, glGenBuffers( SPOT_COUNT - SPOT_PLACE, &(core.SpotIDs[SPOT_PLACE]) ) );
	for ( uint buff = SPOT_PLACE; buff < SPOT_COUNT; ++buff )
		glX( NULL, glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.SpotIDs[buff] ) );
	//glGenVertexArray( 1, &(core.PairsArrayID) );
	//glGenBuffers( 1, &(core.PairsBufferID) );

Switched to using a single buffer for all floats, now I just need advice on how to use index buffers with it to fill my crafter/shader attributes.

Vertex Crafter/Shader GLSL

#version 330

in vec4 Color;
in vec2 Coord;
in vec3 Place;
in vec3 Normal;
in vec3 Tangent;
in vec3 BiNormal;

varying vec4 Pigment;

void main()
{
	gl_Position = vec4( Place, 1.0 );
	Pigment = Color;
}

Initiation code:

glX( NULL, glGenVertexArrays( 1, &(core.FloatsArrayID) ) );
glX( NULL, glGenBuffers( 1, &(core.FloatsBufferID) ) );
glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.FloatsBufferID ) );
glX( NULL, glBufferData
(
	GL_ARRAY_BUFFER,
	core.Floats.size,
	core.Floats.addr,
	GL_STATIC_DRAW
));
glX( NULL, glGenBuffers( SPOT_COUNT, core.SpotIDs ) );
/* Setup vec4 index buffer */
glX( NULL, glBindBuffer
(
	GL_ELEMENT_ARRAY_BUFFER,
	core.SpotIDs[SPOT_COLOR]
));
glX( NULL, glBufferData
(
	GL_ARRAY_BUFFER,
	core.SpotIndexBuffers[SPOT_COLOR].used * sizeof(float),
	core.SpotIndexBuffers[SPOT_COLOR].addr,
	GL_STATIC_DRAW
));
/* Setup vec3 buffers */
for ( uint buff = SPOT_PLACE; buff < SPOT_COUNT; ++buff )
{
	glX( NULL, glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.SpotIDs[buff] ) );
	glX( NULL, glBufferData
	(
		GL_ARRAY_BUFFER,
		core.SpotIndexBuffers[buff].used * sizeof(float),
		core.SpotIndexBuffers[buff].addr,
		GL_STATIC_DRAW
	));
}
...
while ( !glfwWindowShouldClose( window ) )
{
	glfwRefreshCB(window);
	glfwPollEvents();
}

Drawing code:

void glfwRefreshCB( GLFWwindow *window )
{
	LIST *Trigons = &(core.Trigons);
	TRIGON *trigons = get_list_addr(Trigons);

	for ( uint trigon = 0; get_list_used(Trigons); ++trigon )
	{
		if ( list_is_taken( Trigons, trigon, -1 ) )
			continue;
		add_trigon_to_index_buffers( &core, trigons + trigon );
	}

	// Clear the screen
	glX( NULL, glUseProgram( core.Proc->ID ));
	glX( NULL, glClearColor( 0, 0, 0, 0 ));
	glX( NULL, glClear( GL_COLOR_BUFFER_BIT ));

	glX( NULL, glEnableVertexAttribArray( core.FloatsArrayID ));

	glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.FloatsBufferID ) );
	glX( NULL, glBufferData
	(
		GL_ARRAY_BUFFER,
		core.Floats.size,
		core.Floats.addr,
		GL_STATIC_DRAW
	) );

	for ( uint attr = 0; attr < SPOT_COUNT; ++attr )
	{
		BUFF *Indices = &(core.SpotIndexBuffers[attr]);
		uint values;

		if ( attr != SPOT_PLACE && attr != SPOT_COLOR )
			continue;

		if ( attr == SPOT_COLOR )
		{
			values = 4;
			//glX( NULL, glBindVertexArray( core.QuadsArrayID ) );
			//glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.QuadsBufferID ) );
		}
		else if ( attr == SPOT_COORD )
		{
			values = 2;
			//glX( NULL, glBindVertexArray( core.PairsArrayID ) );
			//glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.PairsBufferID ) );
		}
		else
		{
			values = 3;
			//glX( NULL, glBindVertexArray( core.TriosArrayID ) );
			//glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.TriosBufferID ) );
		}

		glX( NULL, glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.SpotIDs[attr] ) );
		glX( NULL, glBufferData
		(
			GL_ELEMENT_ARRAY_BUFFER,
			Indices->size,
			Indices->addr,
			GL_DYNAMIC_DRAW
		));
		glX( NULL, glVertexAttribPointer
		(
			core.SpotAttribLocations[attr],
			values,
			GL_FLOAT,
			GL_FALSE,
			0,
			NULL
		));
	}

	glX( NULL, glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL ) );
	glX( NULL, glDisableVertexAttribArray( core.FloatsArrayID ));
	glfwSwapBuffers(window);
	set_index_buffers_count( &core, 0 );
}

First, stop trying to make “crafter” happen; it’s not going to happen.

Second:

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.SpotIDs[buff] )

The element array buffer binding is a bit weird, in that it isn’t technically context state. It’s VAO state. That means that, if you want to bind a buffer to that binding target, you have to have a VAO bound. However since you’re only binding it to stick some data in it, there’s no need to bind it to the element array buffer binding point. You could easily just bind it to GL_ARRAY_BUFFER just to modify it, then when it comes time to associate it with the VAO, you can bind the VAO and bind the buffer to the element array buffer binding.

Indeed, that would fix the next bug:

glBufferData
	(
		GL_ARRAY_BUFFER,

If you had successfully bound the buffer to the element array buffer binding, you would need to modify it through that binding, not the GL_ARRAY_BUFFER binding. That is, what you bound it to has to match the one you’re using.

Tried your suggestion (made me notice I forgot to edit the type after a copy-paste), did not resolve the black screen issue, I even made sure to check the floats expected by the reported indices, there’s no issue I see with them so in theory I should have 2 static triangles on screen (which I don’t). Despite trying with both GL_ARRAY_BUFFER & GL_ELEMENTS_ARRAY_BUFFER (which from what I’ve read seems contextually correct since only the 1st buffer is holding floats, the rest are buffers holding indices referring to those floats), I cannot seem to get either triangle to show up, I’m assuming I handled the indices wrong, problem is OpenGL is not complaining of misusage so I can’t think of a potential cause.

How would you normally use index buffers given the above scenario I’ve show myself to be trying to use?

At this stage I’d go one further and say get rid of your entire abstraction layer because you’re only confusing yourself.

Where you’re at is that you don’t yet understand how OpenGL works, you’re building (or trying to build) an abstraction layer around it, you’re making a mess, and you’re making it very difficult for people to help you because they’ve first got to try unpick that mess.

I’m not even sure what it is you’re trying to do any more, but you seem to have gone down some kind of rabbit hole with buffer objects and confusion about their intended use, and that seems to have led you to trying to use a single GL_ARRAY_BUFFER with multiple GL_ELEMENT_ARRAY_BUFFERs. If you had proper error checking in, that would be caught, so the glX thing you’re doing - whatever on earth that is - is at least not helping you in this regard.

So clean up the mess first, and just use simple, direct procedural GL calls. At least that way people stand a chance of being able to understand your code.

1 Like

I’m not confusing myself, I’m using a single float array to hold every combination of vec4, vec3 & vec2, the index buffers hold the index of 1st found instance of the desired vectors, those indices are supposed to tell the gpu/card where in the 1st array to copy from into the desired attribute, that concept is clear in my head, it’s just the understanding how to do it that’s the problem, I just about get how to pass the buffers into the gpu/card but I don’t understand how to tell it to use them the way I intend them to be used, all the abstraction on CPU side I can understand perfectly because I understand how to pass the data around and ensure that it is used correctly, but when it comes to passing data to the card/gpu & telling it how to use it, that is where I get stumped, the current floats that are in the vertex buffer are fixed, I know exactly where the triangles should appear and roughly what colours they should be, the whole abstraction layer for them is so that after I finally can get their indices used correctly I can then experiment with meshes which will use those layers of abstraction, when I can get meshes to work correctly I then will go to the next layer, models & scenes (which I will treat as mostly the same thing), then onto maps (which will hold scenes which hold models), before I ever learnt that BotW used a grid system I had a similar thought in mind, that’s the point I’m aiming for and to do that I have to understand how to pass the data and tell the card/gpu how I want to use it, that’s what this code is for, the abstraction calls hold no OpenGL calls, they merely meddle with the data before it is passed along and used by this call, the trigon (I chose that name instead of triangle because I keep mistyping the ia as ai, trigon I don’t) calls at the top of the refresh function are where I overwrite the entire index buffer with new indices, the crafter/shader (btw you can’t speak for the entire human race, there may be others who like the name better and use it in their code, as long as everyone knows what I’m referring to then it doesn’t matter if I call them crafters) is not going to care what model & mesh it’s working with besides what the uniforms (which I can now use properly knowing they’re the same across every crafter/shader instance) I will later be adding tell them, so to summerise all I’m trying to tell the card/gpu at this point is load 1 vertex buffer and load SPOT_COUNT index buffers and use those index buffers to load from the vertex buffer and fill the appropriate attributes in the vertex crafter/shader calls