Forráskód Böngészése

added opengl wrappers and glfw window wrapper

Zoadian 12 éve
szülő
commit
e2987f4b6b

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
 aurora
 ======
 
-Aurora is a 3D Graphic Engine written in the D Programming Language. http://www.boost.org/LICENSE_1_0.txt
+Aurora is a 3D Graphic Engine written in the D Programming Language. GPLv3

+ 17 - 0
package.json

@@ -0,0 +1,17 @@
+{
+	"name": "aurora",
+	"license": "GPLv3",
+	"description": "A 3D Graphics Engine.",
+	"copyright": "Copyright © 2014, Felix 'Zoadian' Hufnagel",
+	"authors": ["Felix 'Zoadian' Hufnagel"],
+	
+	"targetPath": "bin",
+    "targetType": "library",
+	
+	"dependencies": {
+		"derelict-util" : "~master",
+		"derelict-gl3" : "~master",
+		"derelict-glfw3" : "~master",
+		"derelict-ft" : "~master"
+	}
+}

+ 116 - 0
source/aurora/gl/framebuffer.d

@@ -0,0 +1,116 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.framebuffer;
+
+import derelict.opengl3.gl3;
+import aurora.gl.util;
+
+
+//==============================================================================
+///
+enum FramebufferTarget : GLenum {
+	Write = GL_DRAW_FRAMEBUFFER,
+	Read = GL_READ_FRAMEBUFFER
+}
+
+
+//==============================================================================
+///
+enum FramebufferStatus : GLenum {
+	Complete = GL_FRAMEBUFFER_COMPLETE,
+	Error = 0,
+	Undefines = GL_FRAMEBUFFER_UNDEFINED,
+	IncompleteAttachment = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+	IncompleteMissingAttachment = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+	IncompleteDrawBuffer = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER,
+	IncompleteReadBuffer = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
+	Unsupported = GL_FRAMEBUFFER_UNSUPPORTED,
+	IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,        
+	IncompleteLayerTargets = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
+}
+
+
+//==============================================================================
+///
+enum FramebufferAttachment {
+	Color = GL_COLOR_ATTACHMENT0, 
+	Depth = GL_DEPTH_ATTACHMENT, 
+	Stencil = GL_STENCIL_ATTACHMENT,
+	DepthStencil = GL_DEPTH_STENCIL_ATTACHMENT
+}
+
+
+//==============================================================================
+///
+final class Framebuffer {
+private:
+	GLuint _id;
+
+public:	   
+	///
+	this() {
+		check!glGenFramebuffers(1, &this._id); 
+	}
+
+	///
+	~this() {
+		check!glDeleteFramebuffers(1, &this._id);
+	}
+	
+public:	   
+	///
+	void bind(FramebufferTarget target) { 
+		check!glBindFramebuffer(target, this._id);
+	}    
+
+	///
+	static void unbind(FramebufferTarget target) { 
+		check!glBindFramebuffer(target, 0);
+	}
+		
+	
+	//~ version(OpenGL4) {
+		//~ void defaultWidth(Target target, uint width) { check!glFramebufferParameteri(target, GL_FRAMEBUFFER_DEFAULT_WIDTH, width); }
+		//~ uint defaultWidth(Target target) { GLint width; check!glGetFramebufferParameteriv(target, GL_FRAMEBUFFER_DEFAULT_WIDTH, &width); }
+		
+		//~ void defaultHeight(Target target, uint height) { check!glFramebufferParameteri(target, GL_FRAMEBUFFER_DEFAULT_HEIGHT, height); }
+		//~ uint defaultWidth(Target target) { GLint height; check!glGetFramebufferParameteriv(target, GL_FRAMEBUFFER_DEFAULT_HEIGHT, &height); }
+		
+		//~ void defaultLayers(Target target, uint layers) { check!glFramebufferParameteri(target, GL_FRAMEBUFFER_DEFAULT_LAYERS, layers); }
+		//~ uint defaultWidth(Target target) { GLint layers; check!glGetFramebufferParameteriv(target, GL_FRAMEBUFFER_DEFAULT_LAYERS, &layers); }
+		
+		//~ void defaultSamles(Target target, uint samples) { check!glFramebufferParameteri(target, GL_FRAMEBUFFER_DEFAULT_SAMPLES, samples); }
+		//~ uint defaultWidth(Target target) { GLint samples; check!glGetFramebufferParameteriv(target, GL_FRAMEBUFFER_DEFAULT_SAMPLES, &samples); }
+		
+		//~ void defaultFixedSampleLocations(Target target, uint fixedSampleLocations) { check!glFramebufferParameteri(target, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, fixedSampleLocations); }
+		//~ uint defaultFixedSampleLocations(Target target) { GLint fixedSampleLocations; check!glGetFramebufferParameteriv(target, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, &fixedSampleLocations); }
+	//~ }
+	
+	//~ void attach(Target target, Attachment attachment, Texture texture, uint location) {
+		//~ debug{assert(this.db_isBound(target), "framebuffer not bound");}
+		//~ switch(attachment) {
+			//~ case Attachment.Color:
+				//~ check!glFramebufferTexture2D(target, attachment + location, GL_TEXTURE_2D, texture.id, 0);
+				//~ break;
+			//~ default:
+				//~ check!glFramebufferTexture2D(target, attachment, GL_TEXTURE_2D, texture.id, 0);
+		//~ }
+	//~ }
+	
+public:		
+	///
+	@property bool isValid() const @safe nothrow {
+		return (this._id > 0);
+	}
+		
+	///
+	static FramebufferStatus status(FramebufferTarget target) {
+		return cast(FramebufferStatus) check!glCheckFramebufferStatus(target);
+	}    
+}

+ 17 - 0
source/aurora/gl/package.d

@@ -0,0 +1,17 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl;
+				   
+public import aurora.gl.framebuffer;
+public import aurora.gl.renderbuffer;
+public import aurora.gl.shader;
+public import aurora.gl.texture;
+public import aurora.gl.util;
+public import aurora.gl.vao;	  
+public import aurora.gl.vbo;

+ 48 - 0
source/aurora/gl/renderbuffer.d

@@ -0,0 +1,48 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.renderbuffer;
+
+import derelict.opengl3.gl3;
+import aurora.gl.util;
+
+
+//==============================================================================
+///
+final class Renderbuffer {
+private:
+	GLuint _id;
+
+public:	   
+	///
+	this() {
+		check!glGenRenderbuffers(1, &this._id);
+	}
+
+	///
+	~this() {
+		check!glDeleteRenderbuffers(1, &this._id); 
+	}
+	
+public:	  
+	///
+	void bind() { 
+		check!glBindRenderbuffer(GL_RENDERBUFFER, this._id);
+	}
+
+	///
+	static void unbind(){ 
+		check!glBindRenderbuffer(GL_RENDERBUFFER, 0);
+	}  
+	
+public:	  
+	///
+	@property bool isValid() const @safe nothrow {
+		return (this._id > 0);
+	}
+}

+ 153 - 0
source/aurora/gl/shader.d

@@ -0,0 +1,153 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.shader;
+
+import derelict.opengl3.gl3;
+import aurora.gl.util;
+
+
+//==============================================================================
+///
+enum ShaderType {
+	Vertex      			= GL_VERTEX_SHADER,
+	Fragment    			= GL_FRAGMENT_SHADER,
+	Geometry    			= GL_GEOMETRY_SHADER,
+	TesselationControl 		= GL_TESS_CONTROL_SHADER, 
+	TesselationEvaluation 	= GL_TESS_EVALUATION_SHADER
+}
+
+
+//==============================================================================
+///
+final class Shader(ShaderType TYPE) {		
+private:
+	uint _id;
+
+public:	   
+	///
+	this(string source) {
+		auto szSource = [source.toStringz()];
+		this._id = check!glCreateShaderProgramv(TYPE, 1, szSource.ptr);
+	}
+
+	///
+	~this() {
+		check!glDeleteProgram(this._id);
+	}
+
+public:	  
+	///
+	@property bool isValid() const {
+		return (this._id > 0 && this.isLinked);
+	}
+
+	///
+	@property bool isLinked() const {
+		GLint linked;
+		check!glGetProgramiv(this._id, GL_LINK_STATUS, &linked);
+		return linked != 0;
+	}
+	
+public:	  
+	///
+	int getUniformLocation(string name) {
+		int* px = (name in this._uniformLocationCache);
+		if(px !is null) return *px;
+		auto szName = name.toStringz();
+		assert(this._id > 0);
+		int x = check!glGetUniformLocation(this._id, &szName[0]);
+		//assert(x != -1, "wrong uniform location : " ~ name);
+		try{if(x == -1) "wrong uniform location : ".writeln(name);}catch(Exception e){}
+		
+		this._uniformLocationCache[name] = x;
+		//if(x == -1) throw new Exception("uniform location "~name~" not found");
+		return x;
+	}	
+
+	///
+	string infoLog() {
+		int len;
+		check!glGetProgramiv(this._id, GL_INFO_LOG_LENGTH , &len);
+		if (len > 1) {
+			char[] msg = new char[len];
+			check!glGetProgramInfoLog(this._id, len, null, cast(char*) msg);
+			return cast(string)msg;
+		}
+		return "";
+	}
+}
+
+
+//==============================================================================
+///
+final class ShaderPipeline {
+private:
+	GLuint _id;
+	uint[ShaderType] _currentlyUsed;
+	
+public:	 
+	///
+	this() { 
+		glGenProgramPipelines(1, &this._id); 
+	}
+
+	///
+	~this() { 
+		glDeleteProgramPipelines(1, &this._id);
+	}
+	
+public:			
+	///
+	@property bool isValid() const {
+		return (this._id > 0 && this.isValidProgramPipeline);
+	}
+
+	///
+	@property bool isValidProgramPipeline() const { 
+		glValidateProgramPipeline(this._id); 
+		GLint status;
+		glGetProgramPipelineiv(this._id, GL_VALIDATE_STATUS, &status);
+		return status != 0;
+	}
+	
+public:    
+	/// 
+	void bind()  { 
+		glBindProgramPipeline(this._id); 
+	}
+
+	///
+	static void unbind()  { 
+		glBindProgramPipeline(0);
+	}
+
+	///
+	void activate(T)(T shaderProgram) { // TODO: add check if it is a shaderProgram
+		glActiveShaderProgram(this._id, shaderProgram._id);
+	}
+
+	///
+	void use(T)(T shaderProgram) { // TODO: add check if it is a shaderProgram
+		//check if shaderProgram is already in use by this pipeline
+		if(_currentlyUsed.get(T.type, 0) == shaderProgram._id) return;
+		glUseProgramStages(this._id, shaderTypeBitIdentifier!(shaderProgram.type), shaderProgram._id);
+	}
+
+	///
+	string infoLog() {
+		int len;
+		glGetProgramiv(this._id, GL_INFO_LOG_LENGTH , &len);
+		if (len > 1) {
+			char[] msg = new char[len];
+			glGetProgramPipelineInfoLog(this._id, len, null, cast(char*) msg);
+			return cast(string)msg;
+		}
+		return "";
+	}
+}

+ 53 - 0
source/aurora/gl/texture.d

@@ -0,0 +1,53 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.texture;
+
+import derelict.opengl3.gl3;
+import aurora.gl.util;
+
+
+//==============================================================================
+///
+final class Texture {
+private:
+	uint _id;
+
+public:		 
+	///
+	this() {
+		check!glGenTextures(1, &this._id);
+	}
+
+	///
+	~this() {
+		check!glDeleteTextures(1, &this._id);
+	}
+	
+public:		  
+	///
+	void activate(uint location) {
+		check!glActiveTexture(GL_TEXTURE0 + location);
+	}
+
+	///
+	void bind() {
+		check!glBindTexture(GL_TEXTURE_2D, this._id);
+	}
+
+	///
+	static void unbind() { 
+		check!glBindTexture(GL_TEXTURE_2D, 0); 
+	}
+	
+public:				
+	///
+	@property bool isValid() const @safe nothrow {
+		return (this._id > 0);
+	}
+}

+ 298 - 0
source/aurora/gl/util.d

@@ -0,0 +1,298 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.util;
+
+import std.algorithm;
+import std.stdio;
+import std.stdio : stderr;
+import std.array : join;
+import std.range : repeat;
+import std.string : format;
+import std.traits : ReturnType;
+import derelict.opengl3.gl3;
+
+
+//==============================================================================
+///
+enum BlendMode {
+	Replace,
+	Blend,
+	Add,
+	AddBlended,
+	Mult
+}
+
+
+//==============================================================================
+///
+enum DepthTestMode {
+	None,
+	Always,
+	Equal,
+	Less,
+	Greater,
+	LessEqual,
+	GreaterEqual
+}		 
+
+
+//==============================================================================
+///
+enum CullMode {
+	None,
+	Back,
+	Front
+}
+
+
+//==============================================================================
+///
+void setCullMode(CullMode cm) {
+	final switch(cm) {
+		case CullMode.Back:
+			check!glEnable(GL_CULL_FACE);
+			check!glCullFace(GL_BACK);
+			break;
+		case CullMode.Front:
+			check!glEnable(GL_CULL_FACE);
+			check!glCullFace(GL_FRONT);
+			break;
+		case CullMode.None:
+			check!glDisable(GL_CULL_FACE);
+			break;
+	}
+}
+
+
+//==============================================================================
+///
+void setBlendMode(BlendMode bm) {
+	final switch(bm) {
+		case BlendMode.Replace:
+			glDisable(GL_BLEND);
+			break;
+		case BlendMode.Blend:
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+			break;
+		case BlendMode.Add:
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_ONE, GL_ONE);
+			break;
+		case BlendMode.AddBlended:
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+			break;
+		case BlendMode.Mult:
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_DST_COLOR, GL_ZERO);
+			break;
+	}
+}			 
+
+
+//==============================================================================
+///
+void setDepthTestMode(DepthTestMode dt) {	
+	glDepthMask(dt == DepthTestMode.None ? GL_FALSE : GL_TRUE);
+	final switch(dt) {
+		case DepthTestMode.None:
+			glDisable(GL_DEPTH_TEST);
+			break;
+		case DepthTestMode.Always:
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_ALWAYS);
+			break;
+		case DepthTestMode.Equal:
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_EQUAL);
+			break;
+		case DepthTestMode.Less:
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_LESS);
+			break;
+		case DepthTestMode.Greater:
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_GREATER);
+			break;
+		case DepthTestMode.LessEqual:
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_LEQUAL);
+			break;
+		case DepthTestMode.GreaterEqual:
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_GEQUAL);
+			break;
+	}
+}
+
+		  
+//==============================================================================
+///
+int maxDrawBuffers() {
+	int maxDrawBuffers;
+	glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
+	return maxDrawBuffers;
+}
+
+
+//==============================================================================
+///
+int maxColorBuffers() {
+	int maxColorBuffers;
+	glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorBuffers);
+	return maxColorBuffers;
+}
+
+
+//==============================================================================
+///
+int maxTextureImageUnits() {
+	int maxTextureImageUnits;
+	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
+	return maxTextureImageUnits;
+}
+
+
+//==============================================================================
+///
+ReturnType!func check(alias func, Args...)(Args args) {
+	try{
+		debug scope(exit) {
+			GLenum err = glGetError();
+			if(err != GL_NO_ERROR) {
+				stderr.writefln(`OpenGL function "%s(%s)" failed: "%s."`,
+				func.stringof, format("%s".repeat(Args.length).join(", "), args), gl_error_string(err));
+				assert(false);
+			}
+		}
+	}
+	catch(Exception e){
+	}
+	
+	debug if(func is null) {
+		try{
+			stderr.writefln("%s is null! OpenGL loaded? Required OpenGL version not supported?".format(func.stringof));
+		}
+		catch(Exception e){
+			assert(false);
+		}
+		assert(false);
+	}	
+	return func(args);
+}
+
+
+//==============================================================================
+///
+string gl_error_string(GLenum error) {
+	final switch(error) {
+		case GL_NO_ERROR: return "no error";
+		case GL_INVALID_ENUM: return "invalid enum";
+		case GL_INVALID_VALUE: return "invalid value";
+		case GL_INVALID_OPERATION: return "invalid operation";
+			//case GL_STACK_OVERFLOW: return "stack overflow";
+			//case GL_STACK_UNDERFLOW: return "stack underflow";
+		case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffer operation";
+		case GL_OUT_OF_MEMORY: return "out of memory";
+	}
+	assert(false, "invalid enum");
+}
+
+
+
+
+//~ bool glCheck(string file = __FILE__, int line = __LINE__) @trusted  
+//~ {
+//~ debug{
+	//~ try{
+		//~ int error = glGetError();
+		//~ if (error == GL_NO_ERROR) return true;
+		
+		//~ "[[ %s:%s ]]".writef(file, line);
+		
+		//~ while(error != GL_NO_ERROR) {
+			//~ switch (error) {
+				//~ case GL_INVALID_ENUM:
+					//~ writeln("GL_INVALID_ENUM: an unacceptable value has been specified for an enumerated argument");
+					//~ break;
+				//~ case GL_INVALID_VALUE:
+					//~ writeln("GL_INVALID_VALUE: a numeric argument is out of range");
+					//~ break;
+				//~ case GL_INVALID_OPERATION:
+					//~ writeln("GL_INVALID_OPERATION: the specified operation is not allowed in the current state");
+					//~ break;
+				//~ case GL_OUT_OF_MEMORY:
+					//~ writeln("GL_OUT_OF_MEMORY: there is not enough memory left to execute the command");
+					//~ break;
+				//~ case GL_INVALID_FRAMEBUFFER_OPERATION:
+					//~ writeln("GL_INVALID_FRAMEBUFFER_OPERATION_EXT: the object bound to FRAMEBUFFER_BINDING_EXT is not \"framebuffer complete\"");
+					//~ break;
+				//~ default:
+					//~ writeln("Error not listed. Value: ", error);
+					//~ break;
+			//~ }
+			//~ error = glGetError();
+		//~ }
+	//~ }catch(Exception e)
+	//~ {}
+	//~ return false;
+	//~ }
+	//~ return true;
+//~ }
+
+
+//==============================================================================
+///
+template toGlType(T) {
+	static if(is(T == byte)) {
+		enum toGlType = GL_BYTE;
+	} else static if(is(T == ubyte)) {
+		enum toGlType = GL_UNSIGNED_BYTE;
+	} else static if(is(T == short)) {
+		enum toGlType = GL_SHORT;
+	} else static if(is(T == ushort)) {
+		enum toGlType = GL_UNSIGNED_SHORT;
+	} else static if(is(T == int)) {
+		enum toGlType = GL_INT;
+	} else static if(is(T == uint)) {
+		enum toGlType = GL_UNSIGNED_INT;
+	} else static if(is(T == float)) {
+		enum toGlType = GL_FLOAT;
+	} else static if(is(T == double)) {
+		enum toGlType = GL_DOUBLE;
+	} else {
+		static assert(false, T.stringof ~ " cannot be represented as GLenum");
+	}
+}
+
+
+//==============================================================================
+///
+template sizeofGlType(GLenum t) {
+	static if(t == GL_BYTE) {
+		enum sizeofGlType = byte.sizeof;
+	} else static if(t == GL_UNSIGNED_BYTE) {
+		enum sizeofGlType = ubyte.sizeof;
+	} else static if(t == GL_SHORT) {
+		enum sizeofGlType = short.sizeof;
+	} else static if(t == GL_UNSIGNED_SHORT) {
+		enum sizeofGlType = ushort.sizeof;
+	} else static if(t == GL_INT) {
+		enum sizeofGlType = int.sizeof;
+	} else static if(t == GL_UNSIGNED_INT) {
+		enum sizeofGlType = uint.sizeof;
+	} else static if(t == GL_FLOAT) {
+		enum sizeofGlType = float.sizeof;
+	} else static if(t == GL_DOUBLE) {
+		enum sizeofGlType = double.sizeof;
+	} else {
+		static assert(false, T.stringof ~ " cannot be represented as D-Type");
+	}
+}

+ 48 - 0
source/aurora/gl/vao.d

@@ -0,0 +1,48 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.vao;
+
+import derelict.opengl3.gl3;
+import aurora.gl.util;
+
+
+//==============================================================================
+///
+final class VertexArrayObject {
+private:
+	uint _id;
+
+public:	   
+	///
+	this() {
+		check!glGenVertexArrays(1, &this._id);
+	}
+
+	///
+	~this() {
+		check!glDeleteVertexArrays(1, &this._id);
+	}
+	
+public:		   
+	///
+	void bind() { 
+		check!glBindVertexArray(this._id);
+	}
+
+	///
+	static void unbind() { 
+		check!glBindVertexArray(0);
+	}  
+	
+public:	  
+	///
+	@property bool isValid() const @safe nothrow {
+		return (this._id > 0);
+	}
+}

+ 67 - 0
source/aurora/gl/vbo.d

@@ -0,0 +1,67 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+module aurora.gl.vbo;
+
+import derelict.opengl3.gl3;
+import aurora.gl.util;
+
+
+//==============================================================================
+///
+enum VertexBufferObjectTarget {
+	Array = GL_ARRAY_BUFFER, 
+	AtomicCounter = GL_ATOMIC_COUNTER_BUFFER, 
+	CopyRead= GL_COPY_READ_BUFFER, 
+	CopyWrite = GL_COPY_WRITE_BUFFER, 
+	DrawIndirect = GL_DRAW_INDIRECT_BUFFER, 
+	DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
+	ElementArray = GL_ELEMENT_ARRAY_BUFFER, 
+	PixelPack = GL_PIXEL_PACK_BUFFER, 
+	PixelUnpack = GL_PIXEL_UNPACK_BUFFER, 
+	ShaderStorage = GL_SHADER_STORAGE_BUFFER,
+	Texture = GL_TEXTURE_BUFFER, 
+	TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
+	Uniform = GL_UNIFORM_BUFFER
+}
+
+
+//==============================================================================
+///
+final class VertexBufferObject {
+private:
+	uint _id;
+
+public:		   
+	///
+	this() {
+		check!glGenBuffers(1, &this._id);
+	}
+
+	///
+	~this() {
+		check!glDeleteBuffers(1, &this._id);
+	}
+	
+public:		 
+	///
+	void bind(VertexBufferObjectTarget target) { 
+		check!glBindBuffer(target, this._id);
+	}
+
+	///
+	static unbind(VertexBufferObjectTarget target = VertexBufferObjectTarget.Array) { 
+		check!glBindBuffer(target, 0);
+	}  
+	
+public:			
+	///
+	@property bool isValid() const @safe nothrow {
+		return (this._id > 0);
+	}
+}

+ 421 - 0
source/aurora/glfw/window.d

@@ -0,0 +1,421 @@
+/*******************************************************************************
+ * Authors: $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)                       /
+ * Copyright: $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)                    /
+ ***************************************************************************/
+module aurora.glfw.window;
+
+import derelict.opengl3.gl3;
+import derelict.glfw3.glfw3;
+
+import std.string;
+import stdx.signals;
+
+
+//==============================================================================
+///
+alias WindowRect = uint[4];
+
+
+//==============================================================================
+///
+void updateWindows() {
+	glfwPollEvents();
+}
+
+
+//==============================================================================
+///
+final class Window {
+package:
+	GLFWwindow* _glfwWindow = null;	
+	uint _x, _y, _w, _h;
+	string _title;					 
+	KeyAction[int] _keyStates;
+	ButtonAction[int] _buttonStates;
+
+public:			 
+	///
+	this(string title, uint width, uint height) {
+		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+
+		glfwDefaultWindowHints();
+		glfwWindowHint(GLFW_RED_BITS, 8);
+		glfwWindowHint(GLFW_GREEN_BITS, 8);
+		glfwWindowHint(GLFW_BLUE_BITS, 8);
+		glfwWindowHint(GLFW_ALPHA_BITS, 0);
+		glfwWindowHint(GLFW_DEPTH_BITS, 24);
+		glfwWindowHint(GLFW_STENCIL_BITS, 8);
+		//~ glfwWindowHint(GLFW_FSAA_SAMPLES, 0); 
+		
+		this._glfwWindow = glfwCreateWindow(width, height, title.toStringz(), null, null);
+		assert(this._glfwWindow !is null);
+
+		glfwSetWindowUserPointer(this._glfwWindow, cast(void*)this);
+		glfwSetWindowPosCallback(this._glfwWindow, cast(GLFWwindowposfun)&_GLFWwindowposfun);
+		glfwSetWindowSizeCallback(this._glfwWindow, cast(GLFWwindowsizefun)&_GLFWwindowsizefun);
+		glfwSetWindowCloseCallback(this._glfwWindow, cast(GLFWwindowclosefun)&_GLFWwindowclosefun);
+		glfwSetWindowRefreshCallback(this._glfwWindow, cast(GLFWwindowrefreshfun)&_GLFWwindowrefreshfun);
+		glfwSetWindowIconifyCallback(this._glfwWindow, cast(GLFWwindowiconifyfun)&_GLFWwindowiconifyfun);
+		glfwSetMouseButtonCallback(this._glfwWindow, cast(GLFWmousebuttonfun)&_GLFWmousebuttonfun);
+		glfwSetCursorPosCallback(this._glfwWindow, cast(GLFWcursorposfun)&_GLFWcursorposfun);
+		//glfwSetCursorEnterCallback(this._glfwWindow, cast(GLFWcursorenterfunfun)&_GLFWcursorenterfunfun);
+		glfwSetScrollCallback(this._glfwWindow, cast(GLFWscrollfun)&_GLFWscrollfun);
+		glfwSetKeyCallback(this._glfwWindow, cast(GLFWkeyfun)&_GLFWkeyfun);
+		glfwSetCharCallback(this._glfwWindow, cast(GLFWcharfun)&_GLFWcharfun);
+
+		this.makeAktiveRenderWindow();
+		this.clear(1,0,0,1);
+	}
+
+	///
+	~this() {
+		glfwSetWindowPosCallback(this._glfwWindow, null);
+		glfwSetWindowSizeCallback(this._glfwWindow, null);
+		glfwSetWindowCloseCallback(this._glfwWindow, null);
+		glfwSetWindowRefreshCallback(this._glfwWindow, null);
+		glfwSetWindowIconifyCallback(this._glfwWindow, null);
+		glfwSetMouseButtonCallback(this._glfwWindow, null);
+		glfwSetCursorPosCallback(this._glfwWindow, null);
+		//glfwSetCursorEnterCallback(this._glfwWindow, null);
+		glfwSetScrollCallback(this._glfwWindow, null);
+		glfwSetKeyCallback(this._glfwWindow, null);
+		glfwSetCharCallback(this._glfwWindow, null);
+
+		glfwDestroyWindow(this._glfwWindow);
+	}
+
+public:		  
+	///
+	KeyAction keyState(int key) const {
+		return _keyStates.get(key, KeyAction.Released);
+	}
+
+	///
+	ButtonAction buttonState(int button) const {
+		return _buttonStates.get(button, ButtonAction.Released);
+	}
+
+public:			
+	///
+	void clear(float r, float g, float b, float a, float depth = 1.0f, GLenum bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) {
+		glClearColor(r, g, b, a);
+		glClearDepth(depth);
+		glClear(bits);
+	}
+
+	///
+	void swapBuffers() {
+		glfwSwapBuffers(this._glfwWindow);	
+	}
+
+	///
+	void makeAktiveRenderWindow() {
+		glfwMakeContextCurrent(this._glfwWindow);
+	}
+
+	///
+	WindowRect getBounds() const @safe nothrow {
+		return [_x, _y, _w, _h];
+	}
+
+	///
+	@property void title(string title) {
+		glfwSetWindowTitle(this._glfwWindow, title.toStringz());
+	}
+
+public:								 
+	///
+	Signal!(Window, int, int) onPosition;	 
+	///
+	Signal!(Window, int, int) onSize;	  
+	///
+	Signal!(Window) onClose;			 
+	///
+	Signal!(Window) onRefresh;			
+	///
+	Signal!(Window, FocusAction) onFocus;	  
+	///
+	Signal!(Window, IconifyAction) onIconify;	
+	///
+	Signal!(Window, bool) onCursorEnter;		
+	///
+	Signal!(Window, int, ButtonAction) onButton;	
+	/// 
+	Signal!(Window, double, double) onCursorPos; 
+	///
+	Signal!(Window, double, double) onScroll;	
+	///
+	Signal!(Window, Key, ScanCode, KeyAction, KeyMod) onKey;   
+	///
+	Signal!(Window, int) onChar;
+}
+
+
+//==============================================================================
+///
+alias ScanCode = int;
+
+
+//==============================================================================
+///
+enum IconifyAction {
+	Iconified,
+	Restored
+}
+
+
+//==============================================================================
+///
+enum FocusAction {
+	Focused,
+	Defocused
+}
+
+
+//==============================================================================
+///
+enum CursorAction {
+	Entered,
+	Leaved
+}
+
+
+//==============================================================================
+///
+enum ButtonAction {
+	Pressed,
+	Released
+}
+
+
+//==============================================================================
+///
+enum KeyAction {
+	Pressed,
+	Released,
+	Repeated
+}
+
+
+//==============================================================================
+///
+enum KeyMod {
+	Shift = 0x0001,
+	Control = 0x0002,
+	Alt = 0x0004,
+	Super = 0x0008,
+}
+
+
+//==============================================================================
+///
+enum Key {
+	Unknown = -1,
+	Space = 32,
+	Apostrophe = 39,
+	Comma = 44,
+	Minus = 45,
+	Period = 46,
+	Slash = 47,
+	Key0 = 48,
+	Key1 = 49,
+	Key2 = 50,
+	Key3 = 51,
+	Key4 = 52,
+	Key5 = 53,
+	Key6 = 54,
+	Key7 = 55,
+	Key8 = 56,
+	Key9 = 57,
+	Semicolon = 59,
+	Equal = 61,
+	KeyA = 65,
+	KeyB = 66,
+	KeyC = 67,
+	KeyD = 68,
+	KeyE = 69,
+	KeyF = 70,
+	KeyG = 71,
+	KeyH = 72,
+	KeyI = 73,
+	KeyJ = 74,
+	KeyK = 75,
+	Keyl = 76,
+	KeyM = 77,
+	KeyN = 78,
+	KeyO = 79,
+	KeyP = 80,
+	KeyQ = 81,
+	KeyR = 82,
+	KeyS = 83,
+	KeyT = 84,
+	KeyU = 85,
+	KeyV = 86,
+	KeyW = 87,
+	KeyX = 88,
+	KeyY = 89,
+	KeyZ = 90,
+	LeftBracket = 91,
+	Backslash = 92,
+	RightBracket = 93,
+	GraveAccent = 96,
+	World1 = 161,
+	World2 = 162,
+	Escape = 256,
+	Enter = 257,
+	Tab = 258,
+	Backspace = 259,
+	Insert = 260,
+	Delete = 261,
+	Right = 262,
+	Left = 263,
+	Down = 264,
+	Up = 265,
+	PageUp = 266,
+	PageDown = 267,
+	Home = 268,
+	End = 269,
+	CapsLock = 280,
+	ScrollLock = 281,
+	NumLock = 282,
+	PrintScreen = 283,
+	Pause = 284,
+	F1 = 290,
+	F2 = 291,
+	F3 = 292,
+	F4 = 293,
+	F5 = 294,
+	F6 = 295,
+	F7 = 296,
+	F8 = 297,
+	F9 = 298,
+	F10 = 299,
+	F11 = 300,
+	F12 = 301,
+	F13 = 302,
+	F14 = 303,
+	F15 = 304,
+	F16 = 305,
+	F17 = 306,
+	F18 = 307,
+	F19 = 308,
+	F20 = 309,
+	F21 = 310,
+	F22 = 311,
+	F23 = 312,
+	F24 = 313,
+	F25 = 314,
+	NumBlock0 = 320,
+	NumBlock1 = 321,
+	NumBlock2 = 322,
+	NumBlock3 = 323,
+	NumBlock4 = 324,
+	NumBlock5 = 325,
+	NumBlock6 = 326,
+	NumBlock7 = 327,
+	NumBlock8 = 328,
+	NumBlock9 = 329,
+	KpDecimal = 330,
+	KpDivide = 331,
+	KpMultiply = 332,
+	KpSubtract = 333,
+	KpAdd = 334,
+	KpEnter = 335,
+	KpEqual = 336,
+	LeftShift = 340,
+	LeftControl = 341,
+	LeftAlt = 342,
+	LeftSuper = 343,
+	RightShift = 344,
+	RightControl = 345,
+	RightAlt = 346,
+	RightSuper = 347,
+	Menu = 348
+}
+
+
+
+
+private Window _castWindow(GLFWwindow* window)
+out (result) { assert(result !is null, "glfwGetWindowUserPointer returned null"); }
+body {
+	void* user_ptr = glfwGetWindowUserPointer(window);
+	return cast(Window)user_ptr;
+}
+
+
+private extern(C) void _GLFWwindowposfun(GLFWwindow* glfwWindow, int x, int y) {							  
+	Window window = _castWindow(glfwWindow);
+	auto monitor = glfwGetPrimaryMonitor();
+	if(monitor is null) return;
+	auto videoMode = glfwGetVideoMode(monitor);
+	y = videoMode.height - y;
+	int w,h;
+	glfwGetWindowSize(glfwWindow, &w, &h);
+	window._x = x;
+	window._y = y;
+	window._w = w;
+	window._h = h;
+	window.onPosition.emit(window, x, y);
+}
+
+private extern(C) void _GLFWwindowsizefun(GLFWwindow* glfwWindow, int width, int height) {												 
+	Window window = _castWindow(glfwWindow);
+	window._w = width;
+	window._h = height;
+	window.onSize.emit(window, width, height);
+}
+
+private extern(C) void _GLFWwindowclosefun(GLFWwindow* glfwWindow) {				  
+	Window window = _castWindow(glfwWindow);
+	window.onClose.emit(window);
+}
+
+private extern(C) void _GLFWwindowrefreshfun(GLFWwindow* glfwWindow) {													 
+	Window window = _castWindow(glfwWindow);
+	window.onRefresh.emit(window);
+}
+
+private extern(C) void _GLFWwindowfocusfun(GLFWwindow* glfwWindow, int focused) {													 
+	Window window = _castWindow(glfwWindow);
+	window.onFocus.emit(window, (focused == GL_TRUE) ? FocusAction.Focused : FocusAction.Defocused);
+}
+
+private extern(C) void _GLFWwindowiconifyfun(GLFWwindow* glfwWindow, int iconified) {												 
+	Window window = _castWindow(glfwWindow);
+	window.onIconify.emit(window, (iconified == GL_TRUE) ? IconifyAction.Iconified : IconifyAction.Restored);
+}
+
+private extern(C) void _GLFWcursorenterfun(GLFWwindow* glfwWindow, int entered) {
+	Window window = _castWindow(glfwWindow);
+	window.onCursorEnter.emit(window, (entered == GL_TRUE) ? CursorAction.Entered : CursorAction.Leaved);
+}
+
+private extern(C) void _GLFWmousebuttonfun(GLFWwindow* glfwWindow, int button, int action) { 
+	Window window = _castWindow(glfwWindow);
+	window._buttonStates[button] = (action == GLFW_PRESS) ? ButtonAction.Pressed : ButtonAction.Released;
+	window.onButton.emit(window, button, (action == GLFW_PRESS) ? ButtonAction.Pressed : ButtonAction.Released);
+}
+
+private extern(C) void _GLFWcursorposfun(GLFWwindow* glfwWindow, double x, double y) {
+	Window window = _castWindow(glfwWindow);
+	window.onCursorPos.emit(window, x, window._h - y);
+}
+
+private extern(C) void _GLFWscrollfun(GLFWwindow* glfwWindow, double x, double y) {	
+	Window window = _castWindow(glfwWindow);
+	window.onScroll.emit(window, x, y);
+}
+
+private extern(C) void _GLFWkeyfun(GLFWwindow* glfwWindow, int key, int scancode, int action, int mods) {  
+	Window window = _castWindow(glfwWindow);
+	window._keyStates[key] = (action == GLFW_PRESS || action == GLFW_REPEAT) ? KeyAction.Pressed : KeyAction.Released;
+	window.onKey.emit(window, cast(Key)key, cast(ScanCode)scancode, cast(KeyAction)action, cast(KeyMod)mods);
+}
+
+private extern(C) void _GLFWcharfun(GLFWwindow* glfwWindow, uint character) { 
+	Window window = _castWindow(glfwWindow);
+	window.onChar.emit(window, character);
+}