Zoadian преди 11 години
родител
ревизия
3db9f20bb9
променени са 8 файла, в които са добавени 279 реда и са изтрити 489 реда
  1. 5 10
      source/app.d
  2. 0 45
      source/gl/draw.d
  3. 68 46
      source/gl/renderer.d
  4. 0 87
      source/three/mesh.d
  5. 0 2
      source/three/package.d
  6. 0 288
      source/three/renderer_.d
  7. 206 2
      source/three/scene.d
  8. 0 9
      source/three/viewport.d

+ 5 - 10
source/app.d

@@ -6,7 +6,6 @@ import three;
 
 import std.experimental.logger;
 
-
 public import derelict.opengl3.gl3;
 public import derelict.glfw3.glfw3;
 public import derelict.anttweakbar.anttweakbar;
@@ -16,13 +15,9 @@ public import derelict.assimp3.assimp;
 
 public import std.experimental.logger;
 
-
 import three.gl.renderer;
 
-
-
 import three.window;
-import three.viewport;
 import three.camera;
 import three.scene;
 
@@ -72,11 +67,11 @@ void main() {
 	//------------------------------------------------
 	// Create Scene
 	//------------------------------------------------
-	scene.modelData = loadModelData("C:/Coding/models/Collada/duck.dae");
-	log("Model: ", scene.modelData.filePath);
-	log("vertexCount: ", scene.modelData.vertexCount);
-	log("indexCount: ", scene.modelData.indexCount);
-	log("meshCount: ", scene.modelData.meshCount);
+	scene.loadModel("C:/Coding/models/Collada/duck.dae");
+	log("vertexCount: ", scene.vertexCount, " (", scene.vertexCount * VertexData.sizeof / 1024," KiB)");
+	log("indexCount: ", scene.indexCount, " (", scene.indexCount * IndexData.sizeof / 1024," KiB)");
+	log("meshCount: ", scene.meshCount);
+	log("modelCount: ", scene.modelCount);
 
 	//------------------------------------------------
 	// Generate TweakBar

+ 0 - 45
source/gl/draw.d

@@ -1,45 +0,0 @@
-module three.gl.draw;
-
-public import derelict.opengl3.gl3;
-import three.mesh;
-
-struct GlDrawCommand {
-	GLuint vertexCount;
-	GLuint instanceCount;
-	GLuint firstIndex;
-	GLuint baseVertex;
-	GLuint baseInstance;
-}
-
-struct GlDrawParameter {
-	Matrix4 transformationMatrix;
-}
-
-struct Position {
-	float x, y, z;
-}
-
-struct Normal {
-	float x, y, z;
-}
-
-struct Color {
-	float r, g, b, a;
-}
-
-struct TextureCoordinate {
-	float u, v;
-}
-
-struct Matrix4 {
-	float[4*4] data;
-}
-
-struct VertexData {
-	Position position;
-	Normal normal;
-	Color color;
-	TextureCoordinate textureCoordinate;
-}
-
-alias IndexData = uint;

+ 68 - 46
source/gl/renderer.d

@@ -2,8 +2,6 @@
 
 import three.scene;
 import three.camera;
-import three.viewport;
-import three.mesh;
 
 import std.string : toStringz;
 import std.exception : collectException;
@@ -11,7 +9,6 @@ import std.exception : collectException;
 import std.experimental.logger;
 
 import three.gl.buffer;
-import three.gl.draw;
 import three.gl.sync;
 import three.gl.util;
 public import three.gl.renderTarget;
@@ -22,7 +19,34 @@ enum maxPerInstanceParams = 1024;
 enum maxIndirectCommands = 3*1;
 
 
+//======================================================================================================================
+// 
+//======================================================================================================================
+struct GlDrawCommand {
+	GLuint indexCount;
+	GLuint instanceCount;
+	GLuint indexBufferOffset;
+	GLuint vertexBufferOffset;
+	GLuint instanceBufferOffset;
+}
 
+struct GlDrawParameter {
+	Matrix4 transformationMatrix;
+}
+struct Matrix4 {
+	float[4*4] data;
+}
+
+//======================================================================================================================
+// 
+//======================================================================================================================
+struct Viewport {
+	void construct() pure @safe nothrow @nogc {
+	}
+	
+	void destruct() pure @safe nothrow @nogc {
+	}
+}
 
 //======================================================================================================================
 // 
@@ -256,43 +280,45 @@ struct Renderer {
 	}
 
 	void renderOneFrame(ref Scene scene, ref Camera camera, ref GlRenderTarget renderTarget, ref Viewport viewport)  {
-		assert(vertexBuffer.length >= 3 * scene.modelData.vertexCount);
-		assert(indexBuffer.length >= 3 * scene.modelData.indexCount);
-		assert(drawCommandBuffer.length >= 3 * scene.modelData.meshCount);
+		// Assert that we are tripple buffering
+		assert(vertexBuffer.length >= 3 * scene.vertexCount);
+		assert(indexBuffer.length >= 3 * scene.indexCount);
+		assert(drawCommandBuffer.length >= 3 * scene.meshCount);
 
-		// calc if we have to wrap our buffer
-		if(vertexRingbufferIndex + scene.modelData.vertexCount > this.vertexBuffer.length) {
+		// Calc if we have to wrap our buffer
+		if(vertexRingbufferIndex + scene.vertexCount > this.vertexBuffer.length) {
 			vertexRingbufferIndex = 0;
 		}
 		
-		if(indexRingbufferIndex + scene.modelData.indexCount > this.indexBuffer.length) {
+		if(indexRingbufferIndex + scene.indexCount > this.indexBuffer.length) {
 			indexRingbufferIndex = 0;
 		}
 		
-		if(drawCommandRingbufferIndex + scene.modelData.meshCount > this.drawCommandBuffer.length) {
+		if(drawCommandRingbufferIndex + scene.meshCount > this.drawCommandBuffer.length) {
 			drawCommandRingbufferIndex = 0;
 		}
 
-		// wait until GPU has finished rendereing from our desired buffer destination
-		this.vertexSyncManager.waitForLockedRange(vertexRingbufferIndex, scene.modelData.vertexCount);
-//		log("vertexSyncManager: ", vertexRingbufferIndex, " ", scene.modelData.vertexCount);
-		this.indexSyncManager.waitForLockedRange(indexRingbufferIndex, scene.modelData.indexCount);
-//		log("indexSyncManager: ", indexRingbufferIndex, " ", scene.modelData.indexCount);
-		this.drawIndirectCommandSyncManager.waitForLockedRange(drawCommandRingbufferIndex, scene.modelData.meshCount);
-//		log("drawIndirectCommandSyncManager: ", drawCommandRingbufferIndex, " ", scene.modelData.meshCount);
+		// Wait until GPU has finished rendereing from our desired buffer destination
+		log("vertexSyncManager: ", vertexRingbufferIndex, " ", scene.vertexCount);
+		log("indexSyncManager: ", indexRingbufferIndex, " ", scene.indexCount);
+		log("drawIndirectCommandSyncManager: ", drawCommandRingbufferIndex, " ", scene.meshCount);
+		this.vertexSyncManager.waitForLockedRange(vertexRingbufferIndex, scene.vertexCount);
+		this.indexSyncManager.waitForLockedRange(indexRingbufferIndex, scene.indexCount);
+		this.drawIndirectCommandSyncManager.waitForLockedRange(drawCommandRingbufferIndex, scene.meshCount);
 
-		// bind buffers
+		// Bind buffers
 		this.vertexBuffer.bind(); scope(exit) this.vertexBuffer.unbind();
 		this.indexBuffer.bind(); scope(exit) this.indexBuffer.unbind();
 		this.perInstanceParamBuffer.bind(); scope(exit) this.perInstanceParamBuffer.unbind();
 		this.drawCommandBuffer.bind(); scope(exit) this.drawCommandBuffer.unbind();
 
-		//bind gbuffer
+		// Bind gbuffer
 		glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gbuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 
 		GLenum[] drawBuffers = [GL_COLOR_ATTACHMENT0 + 0, GL_COLOR_ATTACHMENT0 + 1, GL_COLOR_ATTACHMENT0 + 2];
 		glCheck!glDrawBuffers(drawBuffers.length, drawBuffers.ptr); scope(exit) glCheck!glDrawBuffer(GL_NONE);
-				
-		// clear scene
+
+		// Clear scene and configure draw settings
+		glCheck!glCullFace(GL_BACK); 
 		glCheck!glEnable(GL_DEPTH_TEST);
 		glCheck!glDepthFunc(GL_LEQUAL);
 		glCheck!glDisable(GL_SCISSOR_TEST);
@@ -305,44 +331,40 @@ struct Renderer {
 		
 		glCheck!glViewport(0, 0, this.gbuffer.width, this.gbuffer.height);
 
-		// backup the indices, we'll need it for our draw command and locking
+		// Backup the indices, we'll need it for our draw command and locking
 		auto curVertexRingbufferIndex = vertexRingbufferIndex;
 		auto curIndexRingbufferIndex = indexRingbufferIndex;
 		auto curDrawCommandRingbufferIndex = drawCommandRingbufferIndex;
 
-		// upload data to our buffers
-//		foreach(model; scene.modelData) {
-		//			foreach(meshData; model.meshData) {
-		foreach(meshData; scene.modelData.meshData) {
-			// upload vertex data
-			this.vertexBuffer.data[vertexRingbufferIndex .. vertexRingbufferIndex + meshData.vertexData.length] = meshData.vertexData[0 .. meshData.vertexData.length];
+		// Upload data to our buffers
+		foreach(modelDescriptor; scene.modelDescriptors) {
+			foreach(meshIndex; 0..modelDescriptor.meshDescriptorCount) {
+				auto meshDesciptor = scene.meshDescriptors[modelDescriptor.meshDescriptorOffset + meshIndex];
 
-			// upload index data
-			this.indexBuffer.data[indexRingbufferIndex .. indexRingbufferIndex + meshData.indexData.length] = meshData.indexData[0 .. meshData.indexData.length];
+				this.vertexBuffer.data[vertexRingbufferIndex .. vertexRingbufferIndex + meshDesciptor.vertexCount] = scene.vertexData[meshDesciptor.vertexOffset .. meshDesciptor.vertexOffset + meshDesciptor.vertexCount];
+				this.indexBuffer.data[indexRingbufferIndex .. indexRingbufferIndex + meshDesciptor.indexCount] = scene.indexData[meshDesciptor.indexOffset .. meshDesciptor.indexOffset + meshDesciptor.indexCount];
 
-			// draw command data
-			this.drawCommandBuffer.data[drawCommandRingbufferIndex] = GlDrawCommand(meshData.indexData.length, 1, indexRingbufferIndex, vertexRingbufferIndex, 0);
+				this.drawCommandBuffer.data[drawCommandRingbufferIndex] = GlDrawCommand(meshDesciptor.indexCount, 1, indexRingbufferIndex, vertexRingbufferIndex, 0);
 
-			log(this.drawCommandBuffer.data[drawCommandRingbufferIndex]);
+				log(this.drawCommandBuffer.data[drawCommandRingbufferIndex]);
 
-			// advance ringbuffers
-			vertexRingbufferIndex += meshData.vertexData.length;
-			indexRingbufferIndex += meshData.indexData.length;
-			++drawCommandRingbufferIndex;
+				// Advance ringbuffers
+				vertexRingbufferIndex += meshDesciptor.vertexCount;
+				indexRingbufferIndex += meshDesciptor.indexCount;
+				++drawCommandRingbufferIndex;
+			}
 		}
-//			}
-//		}
-			
+		
 		// bind pipeline
 		glCheck!glBindProgramPipeline(shaderPipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
-
+		
 		// draw
-		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), cast(const void*)(curDrawCommandRingbufferIndex * GlDrawCommand.sizeof), scene.modelData.meshCount, 0);
-
+		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), cast(const void*)(curDrawCommandRingbufferIndex * GlDrawCommand.sizeof), scene.meshCount, 0);
+		
 		// lock ranges
-		this.vertexSyncManager.lockRange(curVertexRingbufferIndex, scene.modelData.vertexCount);
-		this.indexSyncManager.lockRange(curIndexRingbufferIndex, scene.modelData.indexCount);
-		this.drawIndirectCommandSyncManager.lockRange(curDrawCommandRingbufferIndex, scene.modelData.meshCount);
+		this.vertexSyncManager.lockRange(curVertexRingbufferIndex, scene.vertexCount);
+		this.indexSyncManager.lockRange(curIndexRingbufferIndex, scene.indexCount);
+		this.drawIndirectCommandSyncManager.lockRange(curDrawCommandRingbufferIndex, scene.meshCount);
 	}
 	
 	debug {

+ 0 - 87
source/three/mesh.d

@@ -1,87 +0,0 @@
-module three.mesh;
-
-public import derelict.assimp3.assimp;
-
-public import std.experimental.logger;
-
-import three.gl.draw;
-
-
-
-struct MeshData {
-	VertexData[] vertexData;
-	IndexData[] indexData;
-}
-
-struct ModelData {
-	string filePath;
-	MeshData[] meshData;
-
-	size_t vertexCount() const @safe {
-		import std.algorithm : map, reduce;
-
-		return meshData.length == 0 ? 0 : meshData.map!("a.vertexData.length").reduce!("a + b");
-	}
-	
-	size_t indexCount() const @safe {
-		import std.algorithm : map, reduce;
-		return meshData.length == 0 ? 0 : meshData.map!("a.indexData.length").reduce!("a + b");
-	}
-
-	size_t meshCount() const @safe {
-		return meshData.length;
-	}
-}
-
-ModelData loadModelData(string filePath) {
-	import std.traits;
-	import std.string : toStringz;
-	auto scene = aiImportFile(filePath.toStringz(),	aiProcess_Triangulate); scope(exit) aiReleaseImport(scene);
-
-	ModelData modelData;
-	modelData.filePath = filePath;
-	modelData.meshData.length = scene.mNumMeshes;
-
-	for(uint m = 0; m < scene.mNumMeshes; ++m) {	
-		const(aiMesh*) meshData = scene.mMeshes[m];
-		assert(meshData !is null);
-
-		size_t cntIndices = 0;
-		foreach(f; 0..meshData.mNumFaces) {
-			cntIndices += meshData.mFaces[f].mNumIndices;
-		}
-
-		modelData.meshData[m].vertexData.length = meshData.mNumVertices;
-		modelData.meshData[m].indexData.length = cntIndices;
-
-		foreach(v; 0..meshData.mNumVertices) {
-			modelData.meshData[m].vertexData[v].position = Position(meshData.mVertices[v].x, meshData.mVertices[v].y, meshData.mVertices[v].z);
-
-			modelData.meshData[m].vertexData[v].normal = Normal(meshData.mNormals[v].x, meshData.mNormals[v].y, meshData.mNormals[v].z);
-
-			if(meshData.mColors[0] !is null) {
-				modelData.meshData[m].vertexData[v].color = Color(meshData.mColors[0][v].r, meshData.mColors[0][v].g, meshData.mColors[0][v].b, meshData.mColors[0][v].a);
-			}
-			else {
-				modelData.meshData[m].vertexData[v].color = Color(0, 0, 0, 1);
-			}
-
-			if(meshData.mTextureCoords[0] !is null) {
-				modelData.meshData[m].vertexData[v].textureCoordinate = TextureCoordinate(meshData.mTextureCoords[0][v].x, meshData.mTextureCoords[0][v].y);
-			}
-			else {
-				modelData.meshData[m].vertexData[v].textureCoordinate = TextureCoordinate(0, 0);
-			}
-		}
-
-		size_t curIndexDataIdx = 0;
-		foreach(f; 0..meshData.mNumFaces) {
-			assert(meshData.mFaces !is null);
-			foreach(i; 0..meshData.mFaces[f].mNumIndices) {
-				assert(meshData.mFaces[f].mIndices !is null);
-				modelData.meshData[m].indexData[curIndexDataIdx++] = meshData.mFaces[f].mIndices[i];		
-			}
-		}
-	}
-	return modelData;
-}

+ 0 - 2
source/three/package.d

@@ -1,7 +1,5 @@
 module three;
 
 public import three.camera;
-public import three.mesh;
 public import three.scene;
-public import three.viewport;
 public import three.window;

+ 0 - 288
source/three/renderer_.d

@@ -1,288 +0,0 @@
-module three.rendererx;
-
-version(none) {
-
-import three.common;
-import three.scene;
-import three.camera;
-import three.renderTarget;
-import three.viewport;
-
-import std.string : toStringz;
-import std.exception : collectException;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-enum deferredRendererVertexShaderSource = "
-	#version 420 core
-
-	layout(location = 0) in vec3 in_position;
-	layout(location = 1) in vec3 in_normal;
-	layout(location = 2) in vec2 in_texcoord;
-	layout(location = 3) in vec4 in_color;
-
-	//==============
-	out vec2 _normal;
-	out vec2 _texture;
-	out vec3 _color;
-	//==============
-
-	out gl_PerVertex 
-	{
-    	vec4 gl_Position;
- 	};
-
-	vec2 encode(vec3 n)
-	{
-	    float f = sqrt(8*n.z+8);
-	    return n.xy / f + 0.5;
-	}
-	
-	void main() 
-	{        				
-		gl_Position = vec4(0.005 * in_position.x, 0.005 * in_position.y, 0.005* in_position.z, 1.0);
-		_normal = encode(in_normal);
-		_texture = in_texcoord;
-		_color = in_color.xyz;
-	};
-";
-
-enum deferredRendererFragmentShaderSource = "
-	#version 420 core
-
-	//==============
-	in vec2 _normal;
-	in vec2 _texture;
-	in vec3 _color;
-	//==============
-
-	layout(location = 0) out float depth;
-	layout(location = 1) out vec4 normal;
-	layout(location = 2) out vec4 color;
-
-	void main()
-	{
-		depth = gl_FragCoord.z;
-		normal.xy = _normal.xy;
-		color.xyz = _color;
-	}
-";
-
-struct GBuffer {
-	uint width;
-	uint height;
-	GLuint texturePosition;
-	GLuint textureNormal;
-	GLuint textureColor;
-	GLuint textureDepthStencil;
-	GLuint fbo;
-}
-
-void construct(out GBuffer gBuffer, uint width, uint height) nothrow {
-	gBuffer.width = width;
-	gBuffer.height = height;
-	
-	glCheck!glGenTextures(1, &gBuffer.texturePosition);		
-	glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.texturePosition);
-	glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	//	glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-	//	glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-	//	glCheck!glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
-	glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, width, height);
-	glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, null);	
-	glCheck!glBindTexture(GL_TEXTURE_2D, 0);
-	
-	glCheck!glGenTextures(1, &gBuffer.textureNormal);
-	glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureNormal);
-	glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	
-	//	glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-	//	glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-	glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB10_A2, width, height);
-	glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);	
-	glCheck!glBindTexture(GL_TEXTURE_2D, 0);
-	
-	glCheck!glGenTextures(1, &gBuffer.textureColor);
-	glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureColor);
-	glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
-	glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);	
-	glCheck!glBindTexture(GL_TEXTURE_2D, 0);
-	
-	glCheck!glGenTextures(1, &gBuffer.textureDepthStencil);
-	glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepthStencil);
-	glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, width, height);
-	glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);	
-	glCheck!glBindTexture(GL_TEXTURE_2D, 0);
-	
-	glCheck!glGenFramebuffers(1, &gBuffer.fbo);
-	glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBuffer.fbo);
-	
-	glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, gBuffer.texturePosition, 0);
-	glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 1, GL_TEXTURE_2D, gBuffer.textureNormal, 0);
-	glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 2, GL_TEXTURE_2D, gBuffer.textureColor, 0);
-	glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, gBuffer.textureDepthStencil, 0);
-	
-	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-}
-
-void destruct(ref GBuffer gBuffer) nothrow {
-	glCheck!glDeleteFramebuffers(1, &gBuffer.fbo);
-	glCheck!glDeleteTextures(1, &gBuffer.textureDepthStencil);
-	glCheck!glDeleteTextures(1, &gBuffer.textureColor);
-	glCheck!glDeleteTextures(1, &gBuffer.textureNormal);
-	glCheck!glDeleteTextures(1, &gBuffer.texturePosition);
-	gBuffer = GBuffer.init;
-}
-
-struct Pipeline {
-	GLuint pipeline;
-	GLuint vertexShaderGeometryPass;
-	GLuint fragmentShaderGeometryPass;
-}
-
-void construct(out Pipeline pipeline) nothrow {
-	glCheck!glGenProgramPipelines(1, &pipeline.pipeline); 
-
-	auto szVertexSource = [deferredRendererVertexShaderSource.toStringz()];
-	pipeline.vertexShaderGeometryPass = glCheck!glCreateShaderProgramv(GL_VERTEX_SHADER, 1, szVertexSource.ptr);
-	int len;
-	glCheck!glGetProgramiv(pipeline.vertexShaderGeometryPass, GL_INFO_LOG_LENGTH , &len);
-	if (len > 1) {
-		char[] msg = new char[len];
-		glCheck!glGetProgramInfoLog(pipeline.vertexShaderGeometryPass, len, null, cast(char*) msg);
-		log(cast(string)msg).collectException;
-	}
-
-	auto szFragmentSource = [deferredRendererFragmentShaderSource.toStringz()];
-	pipeline.fragmentShaderGeometryPass = glCheck!glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, szFragmentSource.ptr);
-//	int len;
-	glCheck!glGetProgramiv(pipeline.fragmentShaderGeometryPass, GL_INFO_LOG_LENGTH , &len);
-	if (len > 1) {
-		char[] msg = new char[len];
-		glCheck!glGetProgramInfoLog(pipeline.fragmentShaderGeometryPass, len, null, cast(char*) msg);
-		log(cast(string)msg).collectException;
-	}
-
-	glCheck!glUseProgramStages(pipeline.pipeline, GL_VERTEX_SHADER_BIT, pipeline.vertexShaderGeometryPass);
-	glCheck!glUseProgramStages(pipeline.pipeline, GL_FRAGMENT_SHADER_BIT, pipeline.fragmentShaderGeometryPass);
-
-	glCheck!glValidateProgramPipeline(pipeline.pipeline);
-	GLint status;
-	glCheck!glGetProgramPipelineiv(pipeline.pipeline, GL_VALIDATE_STATUS, &status);
-	//TODO: add error handling
-	assert(status != 0);
-}
-
-void destruct(ref Pipeline pipeline) nothrow {
-	glDeleteProgramPipelines(1, &pipeline.pipeline);
-	pipeline = Pipeline.init;
-}
-
-
-struct OpenGlTiledDeferredRenderer {
-	GBuffer gBuffer;
-	Pipeline pipeline;
-}
-
-void construct(out OpenGlTiledDeferredRenderer deferredRenderer, uint width, uint height) nothrow {
-	deferredRenderer.gBuffer.construct(width, height);
-	deferredRenderer.pipeline.construct();
-}
-
-void destruct(ref OpenGlTiledDeferredRenderer deferredRenderer) nothrow {
-	deferredRenderer.pipeline.destruct();
-	deferredRenderer.gBuffer.destruct();
-	deferredRenderer = OpenGlTiledDeferredRenderer.init;
-}
-
-// draw the scene supersampled with renderer's with+height onto renderTarget at position+size of viewport
-void renderOneFrame(ref OpenGlTiledDeferredRenderer renderer, ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) {
-	// 1. Render the (opaque) geometry into the G-Buffers.	
-	// 2. Construct a screen space grid, covering the frame buffer, with some fixed tile
-	//    size, t = (x, y), e.g. 32 × 32 pixels.	
-	// 3. For each light: find the screen space extents of the light volume and append the
-	//    light ID to each affected grid cell.	
-	// 4. For each fragment in the frame buffer, with location f = (x, y).
-	//    (a) sample the G-Buffers at f.
-	//    (b) accumulate light contributions from all lights in tile at ⌊f /t⌋
-	//    (c) output total light contributions to frame buffer at f
-
-	with(renderer.gBuffer) glCheck!glViewport(0, 0, width, height);
-	
-	//enable depth mask _before_ glClear ing the depth buffer!
-	glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
-	glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
-	glCheck!glDepthFunc(GL_LEQUAL);
-	
-	//bind gBuffer
-	glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderer.gBuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 
-	GLenum[] drawBuffers = [GL_COLOR_ATTACHMENT0 + 0, GL_COLOR_ATTACHMENT0 + 1, GL_COLOR_ATTACHMENT0 + 2];
-	glCheck!glDrawBuffers(drawBuffers.length, drawBuffers.ptr); scope(exit) glCheck!glDrawBuffer(GL_NONE);
-	glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-//	glCheck!glClearColor(0, 0, 0.3, 1);
-	//bind pipeline
-	glCheck!glBindProgramPipeline(renderer.pipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
-	
-	{// Draw Geometry
-		scope(exit) glCheck!glBindVertexArray(0);
-		scope(exit) glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
-		
-		for(size_t meshIdx = 0; meshIdx < scene.mesh.cnt; ++meshIdx) {
-			glCheck!glBindVertexArray(scene.mesh.vao[meshIdx]); 
-			
-			glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene.mesh.vboIndices[meshIdx]); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
-
-//			DrawElementsIndirectCommand
-
-//			glCheck!glcommand
-
-			version(none) { //inefficient. use glMultiDrawElementsIndirect instead
-				glCheck!glDrawElements(GL_TRIANGLES, scene.mesh.cntIndices[meshIdx], GL_UNSIGNED_INT, null);
-			}
-		}
-
-//		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, null, scene.mesh.cnt, 0);
-	}
-}
-
-
-debug {
-	void blitGBufferToScreen(ref OpenGlTiledDeferredRenderer renderer) {
-		glCheck!glBindFramebuffer(GL_READ_FRAMEBUFFER, renderer.gBuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 
-
-		GLsizei width = renderer.gBuffer.width;
-		GLsizei height = renderer.gBuffer.height;
-
-		scope(exit) glCheck!glReadBuffer(GL_NONE);
-
-		glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 0);
-		glCheck!glBlitFramebuffer(0, 0, width, height, 0, height-300, 400, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
-		glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 1);
-		glCheck!glBlitFramebuffer(0, 0, width, height, 0, 0, 400, 300, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
-		glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 2);
-		glCheck!glBlitFramebuffer(0, 0, width, height, width-400, height-300, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-	}
-}
-
-
-}

+ 206 - 2
source/three/scene.d

@@ -1,13 +1,217 @@
 module three.scene;
 
-import three.mesh;
+public import derelict.assimp3.assimp;
+
+public import std.experimental.logger;
+
+struct Position {
+	float x, y, z;
+}
+
+struct Normal {
+	float x, y, z;
+}
+
+struct Color {
+	float r, g, b, a;
+}
+
+struct TextureCoordinate {
+	float u, v;
+}
+
+struct VertexData {
+	Position position;
+	Normal normal;
+	Color color;
+	TextureCoordinate textureCoordinate;
+}
+
+alias IndexData = uint;
+
+struct MeshDescriptor {
+	size_t vertexOffset;
+	size_t vertexCount;
+	size_t indexOffset;
+	size_t indexCount;
+}
+
+struct ModelDescriptor {
+	size_t meshDescriptorOffset;
+	size_t meshDescriptorCount;
+}
 
 struct Scene {
-	ModelData modelData;
+	//TODO: use page allocator
+	VertexData[] vertexData; 
+	IndexData[] indexData;
+	MeshDescriptor[] meshDescriptors;
+	ModelDescriptor[] modelDescriptors;
+
+public:
+	void construct() pure @safe nothrow @nogc {
+	}
+	
+	void destruct() pure @safe nothrow @nogc {
+	}
+
+public:
+	size_t vertexCount() @property {
+		return vertexData.length;
+	}
+
+	size_t indexCount() @property {
+		return indexData.length;
+	}
+	
+	size_t meshCount() @property {
+		return meshDescriptors.length;
+	}
+
+	size_t modelCount() @property {
+		return modelDescriptors.length;
+	}
+
+public:
+	void loadModel(string filePath) {
+		import std.traits;
+		import std.string : toStringz;
+		auto importedScene = aiImportFile(filePath.toStringz(), aiProcess_Triangulate); scope(exit) aiReleaseImport(importedScene);
+
+		this.modelDescriptors ~= ModelDescriptor(this.meshCount, importedScene.mNumMeshes);
+		
+		for(uint m = 0; m < importedScene.mNumMeshes; ++m) {	
+			const(aiMesh*) meshData = importedScene.mMeshes[m];
+			assert(meshData !is null);
+			
+			size_t numIndices = 0;
+			foreach(f; 0..meshData.mNumFaces) {
+				numIndices += meshData.mFaces[f].mNumIndices;
+			}
+
+			this.meshDescriptors ~= MeshDescriptor(this.vertexCount, meshData.mNumVertices, this.indexCount, numIndices);
+
+			foreach(v; 0..meshData.mNumVertices) {
+				this.vertexData ~= VertexData(
+					Position(meshData.mVertices[v].x, meshData.mVertices[v].y, meshData.mVertices[v].z),
+					Normal(meshData.mNormals[v].x, meshData.mNormals[v].y, meshData.mNormals[v].z),
+					(meshData.mColors[0] !is null) ? Color(meshData.mColors[0][v].r, meshData.mColors[0][v].g, meshData.mColors[0][v].b, meshData.mColors[0][v].a) : Color(0, 0, 0, 1),
+					(meshData.mTextureCoords[0] !is null) ? TextureCoordinate(meshData.mTextureCoords[0][v].x, meshData.mTextureCoords[0][v].y) : TextureCoordinate(0, 0)
+				);
+			}
+			
+			size_t curIndexDataIdx = 0;
+			foreach(f; 0..meshData.mNumFaces) {
+				assert(meshData.mFaces !is null);
+				foreach(i; 0..meshData.mFaces[f].mNumIndices) {
+					assert(meshData.mFaces[f].mIndices !is null);
+					this.indexData ~= IndexData(meshData.mFaces[f].mIndices[i]);		
+				}
+			}
+		}
+	}
+}
+
 
+
+
+
+
+
+
+
+
+
+version(none) {
+
+struct Scene {
+	ModelData modelData;
+	
 	void construct() pure @safe nothrow @nogc {
 	}
 	
 	void destruct() pure @safe nothrow @nogc {
 	}
 }
+
+struct MeshData {
+	VertexData[] vertexData;
+	IndexData[] indexData;
+}
+
+struct ModelData {
+	string filePath;
+	MeshData[] meshData;
+
+	size_t vertexCount() const @safe {
+		import std.algorithm : map, reduce;
+
+		return meshData.length == 0 ? 0 : meshData.map!("a.vertexData.length").reduce!("a + b");
+	}
+	
+	size_t indexCount() const @safe {
+		import std.algorithm : map, reduce;
+		return meshData.length == 0 ? 0 : meshData.map!("a.indexData.length").reduce!("a + b");
+	}
+
+	size_t meshCount() const @safe {
+		return meshData.length;
+	}
+}
+
+//ModelData createCubeModel() {
+//}
+
+ModelData loadModelData(string filePath) {
+	import std.traits;
+	import std.string : toStringz;
+	auto scene = aiImportFile(filePath.toStringz(),	aiProcess_Triangulate); scope(exit) aiReleaseImport(scene);
+
+	ModelData modelData;
+	modelData.filePath = filePath;
+	modelData.meshData.length = scene.mNumMeshes;
+
+	for(uint m = 0; m < scene.mNumMeshes; ++m) {	
+		const(aiMesh*) meshData = scene.mMeshes[m];
+		assert(meshData !is null);
+
+		size_t cntIndices = 0;
+		foreach(f; 0..meshData.mNumFaces) {
+			cntIndices += meshData.mFaces[f].mNumIndices;
+		}
+
+		modelData.meshData[m].vertexData.length = meshData.mNumVertices;
+		modelData.meshData[m].indexData.length = cntIndices;
+
+		foreach(v; 0..meshData.mNumVertices) {
+			modelData.meshData[m].vertexData[v].position = Position(meshData.mVertices[v].x, meshData.mVertices[v].y, meshData.mVertices[v].z);
+
+			modelData.meshData[m].vertexData[v].normal = Normal(meshData.mNormals[v].x, meshData.mNormals[v].y, meshData.mNormals[v].z);
+
+			if(meshData.mColors[0] !is null) {
+				modelData.meshData[m].vertexData[v].color = Color(meshData.mColors[0][v].r, meshData.mColors[0][v].g, meshData.mColors[0][v].b, meshData.mColors[0][v].a);
+			}
+			else {
+				modelData.meshData[m].vertexData[v].color = Color(0, 0, 0, 1);
+			}
+
+			if(meshData.mTextureCoords[0] !is null) {
+				modelData.meshData[m].vertexData[v].textureCoordinate = TextureCoordinate(meshData.mTextureCoords[0][v].x, meshData.mTextureCoords[0][v].y);
+			}
+			else {
+				modelData.meshData[m].vertexData[v].textureCoordinate = TextureCoordinate(0, 0);
+			}
+		}
+
+		size_t curIndexDataIdx = 0;
+		foreach(f; 0..meshData.mNumFaces) {
+			assert(meshData.mFaces !is null);
+			foreach(i; 0..meshData.mFaces[f].mNumIndices) {
+				assert(meshData.mFaces[f].mIndices !is null);
+				modelData.meshData[m].indexData[curIndexDataIdx++] = meshData.mFaces[f].mIndices[i];		
+			}
+		}
+	}
+	return modelData;
+}
+}

+ 0 - 9
source/three/viewport.d

@@ -1,9 +0,0 @@
-module three.viewport;
-
-struct Viewport {
-	void construct() pure @safe nothrow @nogc {
-	}
-	
-	void destruct() pure @safe nothrow @nogc {
-	}
-}