Jump to content
  • Advertisement
  • entries
  • comments
  • views

My C++ Game Engine from scratch



Hello there.  I'm not really the blogging type.  This is my first ever blog.  So I'll do my best. 


I've been trying to showcase my video game engine from scratch in different professional forums with scant mixed results. 


I’m currently a happily employed 3D Graphics Programmer in the medical device field who also loves creating graphics programs as a side hobby.


It's been my experience that most people who aren't graphics programmers simply don't appreciate how much learning goes into simply being able to code a small fraction of this from scratch.  Most viewers will simply compare this to the most amazing video game they’ve ever seen (developed by teams of engineers) and simply dismiss this without considering that I’m a one-man show.

What I’m hoping to accomplish with this:  I’m not totally sure.  I spent a lot of my own personal time creating this from the ground up using only my own code (without downloading any existing make-my-game-for-me SDKs), so I figured it’s worth showing off.

My design: Oct Tree for scene/game management (optimized collision-detection and scene rendering path) from scratch in C++. 


1.      All math (linear algebra, trig, quaternion, vectors), containers, sorting, searching from scratch in C++.

2.      Sound system (DirectSound, DirectMusic, OpenAL) from scratch in C++.

3.      Latest OpenGL 4.0 and above mechanism (via GLEW on win32/win64) (GLSL 4.4).  Very heavy usage of GLSL.


Unusual/skilled special effects/features captured in video worth mentioning:

1.       Volumetric Explosions via vertex-shader deformed sphere into shock-wave animation further enhanced with bloom post-processing (via compute shader).

2.       Lens Flare generator, which projects variable edge polygon shapes projected along screen-space vector from center of screen to light-position (again, in screen-space: size and number of flares based on intensity and size of light source).

2.      Real-time animated procedural light ray texture (via fragment shader) additively blended with Volumetric explosions.

3.      Active camouflage (aka Predator camouflage).

4.      Vibrating shield bubble (with same sphere data in Volumetric explosion) accomplished using a technique very similar to active camouflage

5.      Exploding mesh: When I first started creating this, I started out using fixed-function pipeline (years ago).  I used one vertex buffer, one optimized index buffer, then another special unoptimized index buffer that traces through all geometry one volume box at a time.  And each spaceship “piece” was represented with a starting and ending index offset into this unoptimized index buffer.  Unfortunately, the lower the poly-resolution, the more obvious it is what I was doing.  Unfortunately, as a result, when the ship explodes you see the triangle jaggies on the mesh edges.  My engine is currently unfortunately somewhat married to this design—which is why I haven’t redesigned that part yet (It’s on the list, but priorities).  If I were to design this over again, I’d simply represent each piece with a different transform depending upon whether or not the interpolated object-space vertex (input to the pixel shader) was in-front of or behind an arbitrary “breaking plane”.  If the position was beyond the breaking point boundary planes, discard the fragment.  This way, I can use one vertex buffer + one optimized index buffer and achieve better looking results with faster code.



Recommended Comments

Love reading about this sort of thing - we have a few community members who do lower level development and should appreciate your effort here!

Share this comment

Link to comment
On ‎12‎/‎23‎/‎2017 at 10:45 AM, Spencer Lockhart said:

Wow that's awesome, Frank! Please keep us updated

Better cloaking transitions, improved light rays and lens flares.  Upcoming: working on way to guarantee light rays render ontop of occluding opaque fragments if vector from eye to light source is unobstructed (TBD).

Share this comment

Link to comment

Many subtle improvements.  Light Ray occlusion fix:  If Center of light source is occluded by foreground object, will not render light ray.  If light center is not occluded, will render light rays on-top of opaque fragments.  How to do this: render light rays into separate render target.  In addition to standard color output, encode light source center screen-space fragment coord into every output pixel in separate render target (every single light ray pixel for the current light ray will have the same screen-space encoded light center coord: pos_light=g_mProj*g_mView*light_world.  encoded_color=(pos_light.xyz/pos_light.w+1.0)/2.0).  Also, do the same with other opaque fragments for space-ships and such in another separate render target (or make sure you have access to depth buffer).  After rendering standard scene into final color output buffer, render the final light ray texture like so (must have access to standard light ray color buffer and encoded light center fragment positions.  Next, render light-ray texture in screen-space (fill up entire viewport with texture: use standard identity normalized screen coordinates: i.e. (-1,1) (1,1),(1,-1),(-1,-1) to fill up viewport with quad, and use these same coordinates as texture coordinates (i.e. (coord+1.0)/2.0 ).  For every texture coord, lookup the encoded screen-space light position, then use that encoded screen-space light position as a texture coord (already stored as texture coordinate) to look up the foreground space-ship fragment at the screen space light center position.  Do a depth comparison of the encoded screen-space light position to the encoded screen-space opaque fragment position (or do depth lookup into depth buffer)  (i.e. use the looked up screens-space light center fragment coordinate as a texture coordinate lookup into the opaque color-encoded screen-space position buffer).  if center light depth is greater than current opaque fragment depth, then discard the current light-ray fragment (will discard all light ray fragments in light ray image corresponding to this center light position): if(decoded_light_ray_screenspace.z (already z/w) > opaque_fragment_pos.z (also already z/w)) discard;

Edited by frankoguy

Share this comment

Link to comment

These might get a bit more attention as new blog entries rather than just adding comments. :)

Share this comment

Link to comment

@frankoguy thanks a lot for this post is really cool an very interesting, please continue writing i have much of learn with your knowledge and experience


Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By somedev
      Hey guys, I'm pretty new to Direct3D and I try to generate a png image file to disk from a already loaded initialized image from `LPDIRECT3DTEXTURE9` object.
      Basically I'm creating a function that get's an std::string for the file destination path and get the pixels from the existing LPDIRECT3DTEXTURE9 object and save them to disk.
      Any help would be much appreciated!
      Thanks in advance!
      I though I should add a sample code of how I do it with BitMap format to get the idea of what I'm trying to do.
      Note that this code works, but I try to do something similar with PNG format.
      int Width = 128; int Height = 128; LPDIRECT3DTEXTURE9 m_lpTexture; LPDIRECT3DDEVICE9 s_lpD3DDev = NULL; bool SaveToBitmapFile(const std::string & szPath) { LPDIRECT3DSURFACE9 lpSurfSrc = NULL; LPDIRECT3DSURFACE9 lpSurfDst = NULL; m_lpTexture->GetSurfaceLevel(0, &lpSurfSrc); s_lpD3DDev->CreateOffscreenPlainSurface(Width, Height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &lpSurfDst, NULL); if (D3D_OK != D3DXLoadSurfaceFromSurface(lpSurfDst, NULL, NULL, lpSurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0)) { lpSurfDst->Release(); lpSurfDst = NULL; lpSurfSrc->Release(); lpSurfSrc = NULL; } CBitMapFile myBmp; myBmp.Create(Width, Height); D3DLOCKED_RECT LR; lpSurfDst->LockRect(&LR, NULL, 0); for (int y = 0; y < Height; y++) { BYTE* pPixelsSrc = ((BYTE*)LR.pBits) + y * LR.Pitch; BYTE* pPixelsDst = (BYTE*)(myBmp.Pixels(0, y)); for (int x = 0; x < Width; x++) { pPixelsDst[0] = pPixelsSrc[0]; pPixelsDst[1] = pPixelsSrc[1]; pPixelsDst[2] = pPixelsSrc[2]; pPixelsSrc += 4; pPixelsDst += 3; } } lpSurfDst->UnlockRect(); lpSurfDst->Release(); lpSurfDst = NULL; lpSurfSrc->Release(); lpSurfSrc = NULL; HANDLE hFile = ::CreateFile(szPath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwRWC = 0; WriteFile(hFile, &myBmp.m_Header, sizeof(myBmp.m_Header), &dwRWC, NULL); WriteFile(hFile, &myBmp.m_InfoHeader, sizeof(myBmp.m_InfoHeader), &dwRWC, NULL); int iWidth = myBmp.Pitch(); for (int y = myBmp.m_InfoHeader.biHeight - 1; y >= 0; y--) WriteFile(hFile, (BYTE*)myBmp.m_pPixels + y * iWidth, iWidth, &dwRWC, NULL); CloseHandle(hFile); }  
    • By _Flame_
      I'm tring to implement opencl/opengl interop via clCreateFromGLTexture (texture sharing)
          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
      With such texture I expected that write_imagei and write_imageui would work but they don't. Only write_imagef works. This behaviour is same for intel and nvidia gpus on my laptop. Why is it and why there is no such information in any documentation and in the entire internet? This pitfall cost me several hours and probably same for many developers.
    • By Hashbrown
      When importing sprites in Unity, we get a Pixels Per Unit option. The smaller the value, the larger it looks on screen. This is great for very small (50x32px) sprites I download.
      My question is, how can I accomplish this with OpenGL? Should I make the sprite larger in the frag shader? I don't want to scale the game object, I'd like the image to be rendered at the size I need without changing the scale, similar to Unity.
      No code needed, just some suggestions that put me in the right direction. Thanks!
    • By Michael Barth
      Hello there!
      So I want to understand this better. With OpenGL 4.6, support was added to be able to run SPIR-V compiled shaders. I've messed around with it, gotten it to work. It's a little bit more complicated to have to use UBOs for most things now. What I mainly want to know is what the benefits are. So I understand SPIR-V is bytecode, and that it's used by Vulkan and that because it's bytecode, there isn't any worry about wild inconsistencies across GPU vendors. When OpenGL is using SPIR-V, does it also benefit from this?
      Also, does this deal with micro-stutter that's caused by shaders being loaded for the first time using traditional GLSL and shader caching?
      I have some application that uses some really old version of GLSL, like GLSL 120, and I'd been thinking about updating it and properly supporting GLSL 460 compiled to SPIR-V. The application also uses DX9, so I was just curious how updating and using these new techniques with OpenGL 4.6 would stack up against the old GLSL or DX9 methods. I'm not expecting some magic performance benefit, I'm just legitimately curious if it'd be worth it to try.
    • By mako737
      Mário Pauko 1 Hello, when i create a project with UE4 and c++ i get this error
      LINK : fatal error LNK1181: cannot open input file 'C:\Users\Admin\Desktop\Môj Život\UE_4.20\Engine\Intermediate\Build\Win64\UE4Editor\Development\Core\UE4Editor-Core.lib' Error executing C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\bin\HostX64\x64\link.exe (tool returned code: 1181) UE4Editor-akNejdeMamPici.lib (0:02.31 at +1:27)    Creating library C:\Users\Admin\Documents\Unreal Projects\akNejdeMamPici\Intermediate\Build\Win64\UE4Editor\Development\akNejdeMamPici\UE4Editor-akNejdeMamPici.lib and object C:\Users\Admin\Documents\Unreal Projects\akNejdeMamPici\Intermediate\Build\Win64\UE4Editor\Development\akNejdeMamPici\UE4Editor-akNejdeMamPici.exp ---------------------- Done ----------------------     Rebuild All: 0 succeeded, 1 failed, 0 skipped ERROR: UBT ERROR: Failed to produce item: C:\Users\Admin\Documents\Unreal Projects\akNejdeMamPici\Binaries\Win64\UE4Editor-akNejdeMamPici.dll        (see ../Programs/UnrealBuildTool/Log.txt for full exception trace) Total build time: 118,54 seconds (XGE executor: 0,00 seconds)  
      Pls tell me every step i have to do for this problem 

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!