Thread overview
Derelict2 openGL3 issues
Apr 20, 2012
Stephen Jones
Apr 21, 2012
David
Apr 21, 2012
David
Apr 21, 2012
Stephen Jones
Apr 21, 2012
David
Apr 24, 2012
Denis Shelomovskij
May 01, 2012
Stephen Jones
April 20, 2012
David suggested I start a new thread rather than asking on an old existing one (probably wants to get rid of me). So what I have done is created the most parred back, hello world type program that could run under the GL3 enforcement policies dictated by Derelict2. Fixed function pipeline is out. The vertex positions fit within clip space so there is no need to be sending projection, view or model matricies to the vertex shader, nor any need therein to be altering the vertex positions; they simply get set to gl_Position. The fragment shader assigns red to gl_FragColor. I have read somewhere that vaos are required for GL3 and that vbos hang pointlessly without the chaperone of a vao, regardless, the code can draw either vao or vbo depending on which draw function is not commented out in the loop. The problem is, however, that neither function draws anything. Yet all the initializations are returning true; the SDL window pops up and gets cleared to black. Is there a problem with Derelict2?


import std.stdio;
import std.string;
import std.conv;
import derelict.sdl2.sdl;
import derelict.opengl3.gl3;

pragma(lib, "DerelictUtil.lib");
pragma(lib, "DerelictSDL2.lib");
pragma(lib, "DerelictGL3.lib");

SDL_Window *win;
SDL_GLContext context;
int w=800, h=600;
bool running=true;
int shader = 0;
uint vao=0, vbo=0;

bool loadLibs(){
    try{
        DerelictSDL2.load();
    }catch(Exception e){
        writeln("Error loading SDL2 lib");
	return false;
    }
    try{
        DerelictGL3.load();
    }catch(Exception e){
        writeln("Error loading GL3 lib");
	return false;
    }

    return true;
}
bool initSDL(){
	if(SDL_Init(SDL_INIT_VIDEO) < 0){
		writefln("Error initializing SDL");
		return false;
	}
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	win=SDL_CreateWindow("3Doodle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
 	if(!win){
  		writefln("Error creating SDL window");
		SDL_Quit();
		return false;
  	}

    context=SDL_GL_CreateContext(win);
    SDL_GL_SetSwapInterval(1);

    DerelictGL3.reload();

    return true;
}
bool initGL(){
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glViewport(0, 0, w, h);

	return true;
}
bool initShaders(){
	const string vshader="
	#version 330
	layout(location = 0) in vec4 pos;
	void main(void)
	{
    gl_Position = pos;
	}
	";
	const string fshader="
	#version 330
	void main(void)
	{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
	}
	";

	shader=glCreateProgram();
	if(shader == 0){
		writeln("Error: GL did not assigh main shader program id");
		return false;
	}
	int vshad=glCreateShader(GL_VERTEX_SHADER);
	const char *vptr=toStringz(vshader);
	glShaderSource(vshad, 1, &vptr, null);
	glCompileShader(vshad);	
	int status, len;
	glGetShaderiv(vshad, GL_COMPILE_STATUS, &status);
	if(status==GL_FALSE){
		glGetShaderiv(vshad, GL_INFO_LOG_LENGTH, &len);
		char[] error=new char[len];
		glGetShaderInfoLog(vshad, len, null, cast(char*)error);
		writeln(error);
		return false;
	}
	int fshad=glCreateShader(GL_FRAGMENT_SHADER);
	const char *fptr=toStringz(fshader);
	glShaderSource(fshad, 1, &fptr, null);
	glCompileShader(fshad);	
	glGetShaderiv(vshad, GL_COMPILE_STATUS, &status);
	if(status==GL_FALSE){
		glGetShaderiv(fshad, GL_INFO_LOG_LENGTH, &len);
		char[] error=new char[len];
		glGetShaderInfoLog(fshad, len, null, cast(char*)error);
		writeln(error);
		return false;
	}
	glAttachShader(shader, vshad);
	glAttachShader(shader, fshad);
	glLinkProgram(shader);
	glGetShaderiv(shader, GL_LINK_STATUS, &status);
	if(status==GL_FALSE){
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
		char[] error=new char[len];
		glGetShaderInfoLog(shader, len, null, cast(char*)error);
		writeln(error);
		return false;
	}

	return true;
}
bool initVAO(){
	const float[] v = [	0.75f, 0.75f, 0.0f, 1.0f,
				0.75f, -0.75f, 0.0f, 1.0f,
				-0.75f, -0.75f, 0.0f, 1.0f];
	glGenVertexArrays(1, &vao);
	if(vao<1){
		writeln("Error: GL failed to assign vao id");
		return false;
	}

	glBindVertexArray(vao);

	glGenBuffers(1, &vbo);
	if(vbo<1){
		writeln("Error: GL failed to assign vbo id");
		return false;
	}
	
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);//is this right casting a void pointer for 0 offset?	
			
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);	

	return true;
}

void drawVao(){
	glUseProgram(shader);

	glBindVertexArray(vao);
	glDrawArrays(GL_TRIANGLES, 0, 6);

	glBindVertexArray(0);
	glUseProgram(0);
}
void drawVbo(){
	glUseProgram(shader);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);
	glDrawArrays(GL_TRIANGLES, 0, 6);
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glUseProgram(0);
}


int main()
{
	writeln("Load libs: ", loadLibs());//true
	writeln("Init sdl: ", initSDL());//true
	writeln("Init gl: ", initGL());//true
	writeln("Init shaders: ", initShaders());//true
	writeln("Init vao: ", initVAO());//true

	while(running){
		SDL_Event e;
		while(SDL_PollEvent(&e)){
			switch(e.type){
				case SDL_KEYDOWN:
				running=false;
				break;
				default:
				break;
			}
		}
		glClear(GL_COLOR_BUFFER_BIT);

		//drawVao();
		drawVbo();

		SDL_GL_SwapWindow(win);
	}
	SDL_GL_DeleteContext(context);
	SDL_DestroyWindow(win);
	SDL_Quit();
	

	return 0;
}

April 21, 2012
Am 21.04.2012 01:16, schrieb Stephen Jones:
>      glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v, GL_STATIC_DRAW);

Error spotted!

This has to be:

glBufferData(GL_ARRAY_BUFFER, v.length * float.sizeof, v.ptr, GL_STATIC_DRAW);

float.sizeof is just cosmetic, the important thing is v.ptr, &v returns a pointer to a D array not the raw data in memory.
April 21, 2012
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);//is this right casting a void pointer for 0 offset?


I do it like this: cast(void*)OFFSET; e.g.
cast(void*)12;
April 21, 2012
On Saturday, 21 April 2012 at 11:02:51 UTC, David wrote:
> glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);//is this right casting a void pointer for 0 offset?
>
>
> I do it like this: cast(void*)OFFSET; e.g.
> cast(void*)12;

Thankyou David. Just to complete the code for those who follow: it works if you change the above as follows:

glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v,
GL_STATIC_DRAW);

to:

glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v[0],
GL_STATIC_DRAW);


The null value in:

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);

can be replaced with cast(void*)0 as David suggests, but the code runs either way.

I don't quite understand the sizeof comment as writeln(GL_FLOAT.sizeof) gives me 4 which is what I expect.

Although this is not the place for it, I would just like to plug Pelles C ide:

http://my.opera.com/run3/blog/2012/02/09/d-programming-in-pelles-c

Simple to set up.
April 21, 2012
Am 21.04.2012 23:49, schrieb Stephen Jones:
> On Saturday, 21 April 2012 at 11:02:51 UTC, David wrote:
>> glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);//is this
>> right casting a void pointer for 0 offset?
>>
>>
>> I do it like this: cast(void*)OFFSET; e.g.
>> cast(void*)12;
>
> Thankyou David. Just to complete the code for those who follow: it works
> if you change the above as follows:
>
> glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v,
> GL_STATIC_DRAW);
>
> to:
>
> glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v[0],
> GL_STATIC_DRAW);
>
>
> The null value in:
>
> glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);
>
> can be replaced with cast(void*)0 as David suggests, but the code runs
> either way.
>
> I don't quite understand the sizeof comment as writeln(GL_FLOAT.sizeof)
> gives me 4 which is what I expect.
>
> Although this is not the place for it, I would just like to plug Pelles
> C ide:
>
> http://my.opera.com/run3/blog/2012/02/09/d-programming-in-pelles-c
>
> Simple to set up.
null is cast(void*)0, but sometimes you need differen offsets, that's why I showed you the cast(void*)-way.

GL_FLOAT is an alias to float, it's just a personal thing, that I like to use the type (not an alias) of the array directly (to make things clearer)

PS: &v[0] works, but you should use v.ptr, it is exactly what you want and it's the D-way.
April 24, 2012
One day I'll finish my OpenGL wrapper for D. It will give you better abilities in creating OpenGL 3 contexts than most C++ frameworks (SDL, GLFW etc.) and, I hope, will get rid of passing pointers to functions.

It will be done soon after I'll finish Scintilla wrapper for D.

And it will be done soon after I'll conquer the world (or a bit earlier).

Dreams, dreams...

P.S.
OpenGL context creating has been done a long time ago but then I decided to create full wrapper to supersede Derelict's one and it still not finished because that I decided to create general wrapping back-end. And I've done it (CWrap), but than I decided to create Scintilla wrapper...

P.P.S.
Sorry for the flood...

--
Денис В. Шеломовский
Denis V. Shelomovskij
May 01, 2012
On Tuesday, 24 April 2012 at 08:45:44 UTC, Denis Shelomovskij wrote:
> One day I'll finish my OpenGL wrapper for D. It will give you better abilities in creating OpenGL 3 contexts than most C++ frameworks (SDL, GLFW etc.) and, I hope, will get rid of passing pointers to functions.
>
> It will be done soon after I'll finish Scintilla wrapper for D.
>
> And it will be done soon after I'll conquer the world (or a bit earlier).
>
> Dreams, dreams...
>
> P.S.
> OpenGL context creating has been done a long time ago but then I decided to create full wrapper to supersede Derelict's one and it still not finished because that I decided to create general wrapping back-end. And I've done it (CWrap), but than I decided to create Scintilla wrapper...
>
> P.P.S.
> Sorry for the flood...
>
> --
> Денис В. Шеломовский
> Denis V. Shelomovskij


One of the reasons I came to D is because I can feed and read data from openGL using pointers rather than having to duplicate (Marshal) data from the stack to the managed heap before I can interact with openGL (C#). It is redundant to be reading vertex attribute data from a file into managed memory when the destination of that data is the graphics card. It is better to be reading the file data into a stack based struct, handing the pointer to this data to the vbo, securing the vao id and then dropping the stack at function exit. If for no other reason it reduces the work required by the garbage collector continuously reorganizing the heap as vertex data transits through it.