www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Derelict2 openGL3 issues

reply "Stephen Jones" <siwenjo gmail.com> writes:
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;
}
Apr 20 2012
next sibling parent reply David <d dav1d.de> writes:
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.
Apr 21 2012
parent reply David <d dav1d.de> writes:
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;
Apr 21 2012
parent David <d dav1d.de> writes:
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.

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.
Apr 21 2012
prev sibling next sibling parent "Stephen Jones" <siwenjo gmail.com> writes:
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.
Apr 21 2012
prev sibling next sibling parent "Denis Shelomovskij" <verylonglogin.reg gmail.com> writes:
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
Apr 24 2012
prev sibling parent "Stephen Jones" <siwenjo gmail.com> writes:
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.
Apr 30 2012