Thread overview
Derelict, SDL, and OpenGL3: Triangle Tribulations
Aug 12, 2015
DarthCthulhu
Aug 12, 2015
JN
Aug 12, 2015
DarthCthulhu
Aug 12, 2015
BBasile
Aug 12, 2015
Mike Parker
Aug 12, 2015
BBasile
Aug 12, 2015
JN
Aug 12, 2015
Mike Parker
Aug 12, 2015
Mike Parker
Aug 12, 2015
Mike Parker
August 12, 2015
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?
August 12, 2015
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.
August 12, 2015
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.
August 12, 2015
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.
August 12, 2015
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.
August 12, 2015
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.
August 12, 2015
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
August 12, 2015
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.
August 12, 2015
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!

August 12, 2015
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.