Day 1 – Boilerplate

The last couple of blog posts have been about my ventures into game dev with Unity and Unreal rather than what I first set to do with this blog to document my journey programming a small engine and games with it.

I wanted to do this to brush up my C++ and get more into low-level programming again. A couple of days I started where I left off (mostly due to me not having a lot of time as stated in the last blog post).

As I said this is more of a documentation about me learning stuff rather than some sort of tutorial.

I started out with DX12 but quickly realised that a lot has changed from DX11. A lot changed that it makes it harder to even get something simple up and running.

I decided to ditch DX12 in favor of OpenGL in order to be able to focus on implementing things fast instead of having to deal with an API for the next couple of months.

Someday I want to definitely pick up DX12 again and implement it as a renderer api, but for now I will stay with OpenGL and might integrate DX11 later on.

So what I’m doing at the moment is moving all OpenGL related code into a layer I call GDI (Graphics Device Interface). This layer contains all low-level graphics api calls. I mostly followed the tutorial series of Cherno (https://www.youtube.com/watch?v=BwCqRqqbB1Y) here. The reason I added an abstraction between the renderer and the gdi is mostly due to me being stupid and wanting to support multiple APIs.

auto Shader = ResourceTable::GetShader(CommonShaderHandles::Debug);
		assert(Shader != nullptr);

		auto ShaderResource = shader->GetResource();
		if (ShaderResource )
		{
			ShaderResource->Bind();

			//glActiveTexture(GL_TEXTURE0);

			ShaderResource->SetInt("ourTexture", 0);

			glBindTexture(GL_TEXTURE_2D, diffuseTexture->GDI_TextureId);

			// set pojection
			ShaderResource->SetMat4("model", Model);
			ShaderResource->SetMat4("view", g_camera->GetView());
			ShaderResource->SetMat4("projection", g_camera->GetProjection());
			
			GfxGDI::Get()->DrawIndexed(usedMesh->VertexArray);

			glBindTexture(GL_TEXTURE_2D, 0);

			ShaderResource->Unbind();
		}

The above sample shows the current rendering code I refactored into the GDI-Layer which renders a simple cube mesh. Once I got the renderer up and running this will of course be moved to individual render commands.

This is an example of how a vertex array with associated index buffer and vertex buffer can be created and be uploaded to the GPU.

{
			GfxVertexArray* GridArray;
			GridVertexArrayId = GfxGDI::Get()->CreateVertexArray(&GridArray);

			GfxBufferLayout Layout = 
			{
				{ GfxShaderDataType::Float3, "aPos" },
				{ GfxShaderDataType::Float2, "aUV0" }
			};

			GfxVertexBuffer* VertexBuffer;

			GfxGDI::Get()->CreateVertexBuffer(vertices, sizeof(vertices), &VertexBuffer);
			VertexBuffer->SetLayout(Layout);
			GridArray->AttachVertexBuffer(VertexBuffer);

			GfxIndexBuffer* IndexBuffer;
			GfxGDI::Get()->CreateIndexBuffer(indices, sizeof(indices) / sizeof(u16), &IndexBuffer);

			GridArray->SetIndexBuffer(IndexBuffer);
		}

This is mostly the same as the youtube video suggest to do it, but with some adjustments I decided todo.

Every Graphics Resource has an handle assigned to identify them. I decided to use handles a lot in order to decouple stuff. Handles in my opinion have the benefit that they can be passed very easily without having to worry about nullpointers, smart pointers and the like.

struct DAWN_API GenericHandle
{
	u32 Index = 0;
	u32 Generation = 0;
	bool IsValid = false;
};

This is a simple handle that can be passed around and be used to access any Graphics Resource from the GDI by the set index.

Eventhough it’s a lot of work to support multiple graphics apis I will still do it since this is only a learning experience for me.

Unfortunately, I’m not quite happy yet, how the abstraction is handled since I think adding a lot of abstraction / layers a) adds more complexity to the code and b) has a certain performance impact to the overall application.

However, in the past I saw some engines doing it in a similar fashion. For Example as far as I know and have seen from the source code Unreal Engine 4 does it in a very similar fashion, yet on a totally different scale of course.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s