Jump to content
  • Advertisement
Sign in to follow this  
Drey

glDrawRangeElement issue.

This topic is 4520 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i'm not coding in C++. Instead i'm using blitzmax. However, i doubt it's the source of the problem. Case Key_1 does as expected and renders the quad. Case Key_2 does as expected and renders the top corner. However case Key_3 only renders the left upper half. Instead it's suppost to render the bottom right corner of the quad. Can someone help me out here?
GLGraphics 800,600
glewInit()

	
Local	fltVertex#[] =[ -1.0 , 1.0 , 0.0 ,    1.0 , 1.0,  0.0 ,    -1.0, -1.0, 0.0 ,    1.0, -1.0, 0.0 ]
Local	fltColor#[] = [ 1.0 ,  0.0 , 0.0 ,    0.0 , 1.0,  0.0 ,     0.0,  0.0, 1.0 ,    1.0,  1.0, 0.0 ]
		'              Red                      Green              Blue                  Yellow
Local	shtElements:Short[] = [ 0:Short,  1:Short, 2:Short, 1:Short, 3:Short , 2:Short ]	



	glMatrixMode(GL_PROJECTION);				'		// Select The Projection Matrix
	glLoadIdentity();							'// Reset The Projection Matrix

	'// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0 ,Float(GraphicsWidth())/GraphicsHeight(),0.1 ,100.0 );

	glMatrixMode(GL_MODELVIEW);						'// Select The Modelview Matrix
	glLoadIdentity();	
	
	glShadeMOdel(GL_SMOOTH);
	glClearColor( 0.0, 0.0 , 0.0 , 0.0 )
	
		
	
	glEnable(GL_DEPTH_TEST);					'	// Enables Depth Testing	
	
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);		
	
			
glEnableClientState(GL_VERTEX_ARRAY)
glEnableCLientState(GL_Color_Array)
glVertexPointer(3, GL_FLOAT , 0 , Varptr(fltVertex[0]) )
glColorPointer(3,  GL_FLOAT , 0 , Varptr(fltColor[0]) )

Local KeyInput = KEY_1
While Not KeyHit(KEY_A)

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			'// Clear The Screen And The Depth Buffer
	glLoadIdentity();							'// Reset The Current Modelview Matrix
	
	glTranslatef( 0.0 , 0.0, -5.0 )

	
	If KeyHit(KEY_1)
		Keyinput = KEY_1
	ElseIf KeyHit(Key_2)
		keyinput = KEY_2
	ElseIf KeyHit(Key_3)
		keyinput = KEY_3
	EndIf
	
	Select KeyInput
	
		Case KEY_1
			glDrawRangeElements(GL_TRIANGLES, 0,5,6, GL_UNSIGNED_SHORT , Varptr(shtElements[0]) )
		Case Key_2
			glDrawRangeElements(GL_TRIANGLES, 0,2,3, GL_UNSIGNED_SHORT , Varptr(shtElements[0]) ) 
		Case Key_3
			glDrawRangeElements(GL_TRIANGLES, 3,5,3, GL_UNSIGNED_SHORT , Varptr(shtElements[0]) )
					
	End Select
	
		
	Flip()
	
Wend 

gldisableClientState(GL_VERTEX_ARRAY)
gldisableCLientState(GL_Color_Array)


Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Drey

Case KEY_1
glDrawRangeElements(GL_TRIANGLES, 0,5,6, GL_UNSIGNED_SHORT , Varptr(shtElements[0]) )
Case Key_2
glDrawRangeElements(GL_TRIANGLES, 0,2,3, GL_UNSIGNED_SHORT , Varptr(shtElements[0]) )
Case Key_3
glDrawRangeElements(GL_TRIANGLES, 3,5,3, GL_UNSIGNED_SHORT , Varptr(shtElements[0]) )

Well I don't know the language, but shouldn't the last parameter to glDrawRangeElements in case Key_3 be Varptr(shtElements[3])?

Remember, glDraw*Elements will start dereferncing from the pointer you provide irrespective of the range.

Share this post


Link to post
Share on other sites
First, your call for case 3 is identical to that of case 2, except the range of index values. So if case 2 draws the top half then so should case 3.

Second, you start and end values are the maximum and minimum values in the index array. For case 3, you say that no indices are outside the range [3, 5]. But clearly every index except the second last index is outside this range. I assume the call for case 3 would looks something like this (adjust the syntax for your language).

glDrawRangeElements(GL_TRIANGLES,
1, // Smallest value in the range of interest (index 3 to 5, see below) is 1.
3, // Largest index in the range of interest is 3.
3, // Draw 3 indices, making one triangle.
GL_UNSIGNED_SHORT,
Varptr(shtElements[3]) // Start drawing at index 3, which means index 3 to 5 since the number of indices to draw is 3.
);

For the same reason, case 1 and 2, while not wrong in the sense that you're lying to OpenGL about the smallest and largest index value, are not really correct. Case 1 should have smallest and largest index set to 0 and 3, respectively, and case 2, 0 and 2.

Now while writing mu reply it seems like you misunderstand the start and end values. Seems like you think these values are represent what part of the index array to use, but they are not. OpenGL is perfectly capable of calculating those values itself from the start pointer and the number of indices to draw. What it's not capable of is to determine what the values of those indices are, i.e. the content of the index array.

Share this post


Link to post
Share on other sites
OK, but changing the pointers like that isn't an good idea for VBOs though or should i use gBufferSubData for every range change? Kinda kills the purpose though. How will i control regions with VBO?

Share this post


Link to post
Share on other sites
Quote:
Original post by Drey
OK, but changing the pointers like that isn't an good idea for VBOs though ...

Why do you thisnk that?

You are just providing an offset from the start of your index array basically. There is no additional cost in providing &indices[n] and &indices[0] ... the GPU just starts reading from a different memory address.

Share this post


Link to post
Share on other sites
because my orginal design idea was to have prepare the VBO once ( with glbindbuffer ) and then call on regions of the array as needed. So the array loaded was going to be the WHOLE mesh, and i was giong to call on glDraw"Range"Elements to render different parts under different matrices. It would have only taken one command before for VBO..now it seems like i have to do a few..which defeats the purpose somewhat.

Share this post


Link to post
Share on other sites
But you don't have to change any arrays, and what we're telling you to do is what you want to do. If you want OpenGL to draw 3 vertices, starting at the 3:rd index, then you pass a pointer (or offset, since you use VBO) to the 3:rd index, and set the size to 3.

Range in glDrawRangeElements does not refer to drawing a sub range of the index array. It tells OpenGL what the range of the index values, the values in the index array, is. For the purpose of only drawing certain parts of the object, then glDrawElements is just fine. glDrawRangeElements doesn't provide anything but the chance of a more optimized rendering. It doesn't provide anything that can't be done with glDrawElements.

Share this post


Link to post
Share on other sites
Oh, i understand that. I'm just worried about my VBOs working correctly now.


glGenBuffers 1, Varptr(intVertexBuffer)
glBindBuffer(GL_ARRAY_BUFFER, intVertexBuffer)
glBufferData(GL_ARRAY_BUFFER, SizeOf(fltVertex), Varptr(fltVertex[0]), GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0 )


in bufferdata i'll have to change to Varptr(fltVertex[3]) for this example. I was trying to avoid calling bindbuffer again. The idea was to do something like this.

Mesh.BeginRender() //if in VBO mode, binds buffers. If in VA mode, sets pointers

Loops for Num Of RefMesh
Loops for RefMesh.SegementUpdateList
// Model Transform matrix
Segement.Position.toMatrixLoad() //
Mesh.Render( Segement.ElementRange ) // Range object containing starting and ending in the array
End Loop

Mesh.EndRender()


It's rough peusocode, but it conveys the idea mostly.
I know it's not a big deal in VA(change pointers) but it is in VBO. Is there a way to get the same effect without rebinding?

Share this post


Link to post
Share on other sites
Unless what you're telling us is not whta you actually want, then the answer we have given you is the solution to your problem.

Create the VBO by uploading the mesh data once, and only once. No need to touch it any more. When drawing sub parts of the mesh, adjust the starting address passed to glDraw(Range)Elements.

That's all there is. Really.

Share this post


Link to post
Share on other sites
I had a post typed up but now i really understand what's goin on now. I can bind everything like normal except the indices array. I was binding that as well. That's where all this confusion came from. I guess it isn't really too bad a bottleneck to have the indice array stream from the RAM and nothing else.

I was passing a null as a pointer once i had the indice array loaded




glGenBuffers 1, Varptr(intVertexBuffer)
glBindBuffer(GL_ARRAY_BUFFER, intVertexBuffer)
glBufferData(GL_ARRAY_BUFFER, SizeOf(fltVertex), Varptr(fltVertex[0]), GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0 )

glGenBuffers(1, Varptr(intElementBuffer) )
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, intElementBuffer)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, SizeOf(shtElements), Varptr(shtElements[0]), GL_STATIC_DRAW)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 )



Then i will have 3 modes. ALL VBO(including indices, non animated or non seperatable items), Partical VBO mode(likely excluding indice binding), and a VA mode. (if i'm understanding this correctly)

Thanks guys! :-D


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!