www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Derelict, SDL, and OpenGL3: Triangle Tribulations

reply "DarthCthulhu" <spam spam.com> writes:
So I decided to try some OGL3 stuff in D utilizing the Derelict 
bindings and SDL. Creating an SDL-OGL window worked fine, but I'm 
having trouble with doing the most basic thing of rendering a 
triangle. I get the window just fine and the screen is being 
properly cleared and buffered, but no triangle.

Code:

GLuint initVAO () {

		// An array of 3 vectors which represents 3 vertices
	static const GLfloat g_vertex_buffer_data[] = [
	  -1.0f, -1.0f, 0.0f,
	   1.0f, -1.0f, 0.0f,
	   0.0f, 1.0f, 0.0f,
	];

	// This will identify our vertex buffer
	GLuint vertexbuffer;

	// Generate 1 buffer, put the resulting identifier in 
vertexbuffer
	glGenBuffers(1, &vertexbuffer);

	// The following commands will talk about our 'vertexbuffer' 
buffer
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

	// Give our vertices to OpenGL.
	glBufferData(GL_ARRAY_BUFFER, g_vertex_buffer_data.length * 
GL_FLOAT.sizeof, g_vertex_buffer_data.ptr, GL_STATIC_DRAW);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,  null);			
	glBindBuffer(GL_ARRAY_BUFFER, 0);
		
	return vertexbuffer;
}

void main() {

	string title = "Hello, world! With SDL2 OpenGL3.3!";
	writefln(title);

	// Create a new OGL Window
	Window win = new SDL_OGL_Window(title);

	GLuint vertexbuffer = initVAO();

	// Main loop flag
	bool quit = false;

	//Event handler
	SDL_Event e;

	glClearColor(0,0,0.4,0);

	do {
		
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glBindVertexArray(vertexbuffer);

		// Draw the triangle
		glDrawArrays(GL_TRIANGLES, 0, 3);

		glDisableVertexAttribArray(vertexbuffer);
		glBindVertexArray(0);
		
		SDL_GL_SwapWindow(win.window);

		// Handle events on queue
		while( SDL_PollEvent( &e ) != 0 ) {
			//User requests quit
			if( e.type == SDL_QUIT ) {
				quit = true;
			}
		}

		const Uint8* currentKeyStates = SDL_GetKeyboardState( null );

		// Escape to quit as well.
		if( currentKeyStates[ SDL_SCANCODE_ESCAPE ] ) {
			quit = true;;
		}

	} while ( !quit );

	glDeleteBuffers(1, &vertexbuffer);

}

The SDL_OGL_Window is an object that creates an SDL window and 
binds a OpenGL context to it; I don't think it's relevant for 
what's going on, but if anyone thinks it might be the culprit, 
I'll post it.

So, any ideas what I'm doing wrong?
Aug 11 2015
next sibling parent reply "JN" <666total wp.pl> writes:
On Wednesday, 12 August 2015 at 03:32:47 UTC, DarthCthulhu wrote:
 So I decided to try some OGL3 stuff in D utilizing the Derelict 
 bindings and SDL. Creating an SDL-OGL window worked fine, but 
 I'm having trouble with doing the most basic thing of rendering 
 a triangle. I get the window just fine and the screen is being 
 properly cleared and buffered, but no triangle.

 [...]
You need a vertex and a fragment shader. You can't render anything in OGL3 without shaders. Also, you seem to be confusing Vertex Array Objects and Vertex Buffer Objects. You are creating a VBO and try to bind it as a VAO. You should put a glGenVertexArrays somewhere there.
Aug 11 2015
parent "DarthCthulhu" <spam spam.com> writes:
On Wednesday, 12 August 2015 at 05:26:33 UTC, JN wrote:
 You need a vertex and a fragment shader. You can't render 
 anything in OGL3 without shaders.
I thought that was the case, but the tutorial I was looking at didn't have any shaders at that point. I added a shader program.
 Also, you seem to be confusing Vertex Array Objects and Vertex 
 Buffer Objects. You are creating a VBO and try to bind it as a 
 VAO. You should put a glGenVertexArrays somewhere there.
Aha! Yes, that's it, thanks! Once I understood the difference between VAO and VBOs, it was easy to fix. Thanks! On Wednesday, 12 August 2015 at 05:35:30 UTC, Mike Parker wrote:
 On Wednesday, 12 August 2015 at 03:32:47 UTC, DarthCthulhu 
 wrote:
 So, any ideas what I'm doing wrong?
Too much to list. I suggest you get going with a good tutorial. One of the best I've seen is by Anton Gerdelan [1]. The four basic tutorials he has on his site will be enough to get you up and running. He used to have a lot more there, but he's published them all in a book. Even though there are numerous free resources online, I think Anton's ebook is well worth the ~$9.00 you pay for it. His tutorials are quite detailed and do a lot more than showing you a bunch of code to copy and paste. Work your way through that book and you'll know your way around well enough to do what you need to do for any basic OpenGL renderer.
On Wednesday, 12 August 2015 at 05:54:13 UTC, Mike Parker wrote:
 On Wednesday, 12 August 2015 at 05:35:30 UTC, Mike Parker wrote:

 One of the best I've seen is by Anton Gerdelan [1]. The four
[1] http://antongerdelan.net/opengl/index.html
Thanks very much for the resource! I had already looked at about a dozen different OGL3.x tutorials online, but this was the one which clicked for me. I'll definitely look into getting his book. Thanks again!
Aug 11 2015
prev sibling next sibling parent reply "BBasile" <bb.temp gmx.com> writes:
On Wednesday, 12 August 2015 at 03:32:47 UTC, DarthCthulhu wrote:
 So I decided to try some OGL3 stuff in D utilizing the Derelict 
 bindings and SDL. Creating an SDL-OGL window worked fine, but 
 I'm having trouble with doing the most basic thing of rendering 
 a triangle. I get the window just fine and the screen is being 
 properly cleared and buffered, but no triangle.

 So, any ideas what I'm doing wrong?
For me the following code works: --- import derelict.sdl2.sdl; import derelict.opengl3.gl3; import derelict.opengl3.gl; import std.stdio; static this() { DerelictGL3.load; DerelictGL.load; DerelictSDL2.load; SDL_Init(SDL_INIT_VIDEO); } static ~this() { SDL_Quit(); DerelictGL3.unload; DerelictSDL2.unload; } GLuint initVAO () { // An array of 3 vectors which represents 3 vertices static const GLfloat[] g_vertex_buffer_data = [ -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, ]; // This will identify our vertex buffer GLuint vertexbuffer; // Generate 1 buffer, put the resulting identifier in vertexbuffer glGenBuffers(1, &vertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // Give our vertices to OpenGL. glBufferData(GL_ARRAY_BUFFER, g_vertex_buffer_data.length * GL_FLOAT.sizeof, g_vertex_buffer_data.ptr, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, null); glBindBuffer(GL_ARRAY_BUFFER, 0); return vertexbuffer; } void main(string[] args) { auto flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; auto win = SDL_CreateWindow( null, 50, 50, 800, 600, flags); auto ctxt = SDL_GL_CreateContext(win); DerelictGL3.reload; GLuint vertexbuffer = initVAO(); SDL_Event ev; while (true) { if (SDL_WaitEvent(&ev)) { glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindVertexArray(vertexbuffer); // Draw the triangle glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(vertexbuffer); glBindVertexArray(0); SDL_GL_SwapWindow(SDL_GL_GetCurrentWindow()); } if (ev.type == SDL_QUIT) break; } SDL_DestroyWindow(win); SDL_GL_DeleteContext(ctxt); } --- It looks like it's the window/context creation that fail for you because the OpenGL code is 100% the same.
Aug 11 2015
next sibling parent reply "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 12 August 2015 at 05:34:22 UTC, BBasile wrote:
 For me the following code works:

 ---
 import derelict.sdl2.sdl;
 import derelict.opengl3.gl3;
 import derelict.opengl3.gl;

 import std.stdio;

 static this()
 {
     DerelictGL3.load;
     DerelictGL.load;
     DerelictSDL2.load;
     SDL_Init(SDL_INIT_VIDEO);
 }

 static ~this()
 {
     SDL_Quit();
     DerelictGL3.unload;
     DerelictSDL2.unload;
 }

 GLuint initVAO () {

 		// An array of 3 vectors which represents 3 vertices
 	static const GLfloat[] g_vertex_buffer_data = [
 	  -1.0f, -1.0f, 0.0f,
 	   1.0f, -1.0f, 0.0f,
 	   0.0f, 1.0f, 0.0f,
 	];

 	// This will identify our vertex buffer
 	GLuint vertexbuffer;

 	// Generate 1 buffer, put the resulting identifier in 
 vertexbuffer
 	glGenBuffers(1, &vertexbuffer);

 	// The following commands will talk about our 'vertexbuffer' 
 buffer
 	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

 	// Give our vertices to OpenGL.
 	glBufferData(GL_ARRAY_BUFFER, g_vertex_buffer_data.length * 
 GL_FLOAT.sizeof, g_vertex_buffer_data.ptr, GL_STATIC_DRAW);

 	glEnableVertexAttribArray(0);
 	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,  null);			
 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 		
 	return vertexbuffer;
 }

 void main(string[] args)
 {

     auto flags =  SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | 
 SDL_WINDOW_RESIZABLE;
     auto win = SDL_CreateWindow( null, 50, 50, 800, 600, flags);
     auto ctxt = SDL_GL_CreateContext(win);

     DerelictGL3.reload;

     GLuint vertexbuffer = initVAO();

     SDL_Event ev;
     while (true)
     {
         if (SDL_WaitEvent(&ev))
         {
             glClear(GL_COLOR_BUFFER_BIT);

             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 	        glBindVertexArray(vertexbuffer);

 	        // Draw the triangle
 	        glDrawArrays(GL_TRIANGLES, 0, 3);

 	        glDisableVertexAttribArray(vertexbuffer);
 	        glBindVertexArray(0);

             SDL_GL_SwapWindow(SDL_GL_GetCurrentWindow());
         }
         if (ev.type == SDL_QUIT)
             break;
     }

     SDL_DestroyWindow(win);
     SDL_GL_DeleteContext(ctxt);
 }
 ---

 It looks like it's the window/context creation that fail for 
 you because the OpenGL code is 100% the same.
It seems to me that your driver is doing things it isn't actually supposed to do. This code is binding a vertex buffer object with a function which is supposed to bind a vertex array object. The only reason the vbo is bound at all is because of the call to glBindBuffer in the misnamed initVAO -- a function which never even initializes a vao. The spec actually requires a vao to be created and a shader program to be bound, so I would expect a conforming driver to show nothing. I expect a couple of calls to glError will not come up empty.
Aug 11 2015
parent reply "BBasile" <bb.temp gmx.com> writes:
On Wednesday, 12 August 2015 at 05:46:27 UTC, Mike Parker wrote:
 On Wednesday, 12 August 2015 at 05:34:22 UTC, BBasile wrote:
 [...]
It seems to me that your driver is doing things it isn't actually supposed to do. This code is binding a vertex buffer object with a function which is supposed to bind a vertex array object. The only reason the vbo is bound at all is because of the call to glBindBuffer in the misnamed initVAO -- a function which never even initializes a vao. The spec actually requires a vao to be created and a shader program to be bound, so I would expect a conforming driver to show nothing. I expect a couple of calls to glError will not come up empty.
Right, the triangle is well drawn but glGetError returns 1282. Maybe the OP has a different OGL implementation. At least NVidia driver renders a triangle for this code.
Aug 11 2015
parent "JN" <666total wp.pl> writes:
On Wednesday, 12 August 2015 at 05:58:23 UTC, BBasile wrote:
 On Wednesday, 12 August 2015 at 05:46:27 UTC, Mike Parker wrote:
 On Wednesday, 12 August 2015 at 05:34:22 UTC, BBasile wrote:
 [...]
It seems to me that your driver is doing things it isn't actually supposed to do. This code is binding a vertex buffer object with a function which is supposed to bind a vertex array object. The only reason the vbo is bound at all is because of the call to glBindBuffer in the misnamed initVAO -- a function which never even initializes a vao. The spec actually requires a vao to be created and a shader program to be bound, so I would expect a conforming driver to show nothing. I expect a couple of calls to glError will not come up empty.
Right, the triangle is well drawn but glGetError returns 1282. Maybe the OP has a different OGL implementation. At least NVidia driver renders a triangle for this code.
Depends on what context gets created in this case. A core profile context shouldn't render anything without a bound shader. NVidia likes backwards compatibility, so it's possible this code works, it's just using fixed function pipeline rendering, which isn't typically what people want when they mention "GL3". Might as well use glBegin/glEnd, and it would work too.
Aug 12 2015
prev sibling parent "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 12 August 2015 at 05:34:22 UTC, BBasile wrote:
 static this()
 {
     DerelictGL3.load;
     DerelictGL.load;
     DerelictSDL2.load;
     SDL_Init(SDL_INIT_VIDEO);
 }
I should point out that *either* DerelictGL3 *or* DerelictGL should be loaded, but never both. DerelictGL actually extends DerelictGL3. When you call load on it, it calls super.load (ditto for reload), with the net effect that you're loading all of the DerelictGL3 stuff twice. If you need the deprecated stuff, just use DerelictGL; if you don't, just use DerelictGL3.
Aug 11 2015
prev sibling parent reply "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 12 August 2015 at 03:32:47 UTC, DarthCthulhu wrote:
 So, any ideas what I'm doing wrong?
Too much to list. I suggest you get going with a good tutorial. One of the best I've seen is by Anton Gerdelan [1]. The four basic tutorials he has on his site will be enough to get you up and running. He used to have a lot more there, but he's published them all in a book. Even though there are numerous free resources online, I think Anton's ebook is well worth the ~$9.00 you pay for it. His tutorials are quite detailed and do a lot more than showing you a bunch of code to copy and paste. Work your way through that book and you'll know your way around well enough to do what you need to do for any basic OpenGL renderer.
Aug 11 2015
parent "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 12 August 2015 at 05:35:30 UTC, Mike Parker wrote:

 One of the best I've seen is by Anton Gerdelan [1]. The four
[1] http://antongerdelan.net/opengl/index.html
Aug 11 2015