# clone repo with its submodules
$ git clone --recursive https://github.com/OpenGL-Graphics/first-person-shooter
# build & run
$ cd first-person-shooter
$ mkdir build && cd build
$ cmake .. && make -j && ./main
# to get new commits from submodules
$ git submodule update --init --recursive --remote
To install the needed dependencies on Ubuntu:
$ apt install libglm-dev libglfw3-dev libassimp-dev
OpenGL/GLSL 3.3+GLSL 4.6 to support array indexing using non-consts (i.e. id-instance)
MP3 audio sound is played with FMOD, which is bundled with this project (Linux x86_64 headers & libs). irrKlang was used before, but it caused audio glitches when music was played while the game was running.
- Mouse: Orbit camera & shoot with LMB
- WASD keys: Move camera
- Health bar made by Daniel Zhang (APEXOUS) and available under the CC0 license.
- Textures (incl. skybox) downloaded from textures.com.
- Low poly sniper
- Samurai
- Gun shot sound effect
Useful tutorials:
- Getting started with GLFW: GLFW tutorial
- Learn OpenGL tutorial: learnopengl.com
- Opengl-tutorial: opengl-tutorial.org
- OpenGL tutorial series on Youtube: TheCherno
- Similarly to this tutorial, an older version of GLSL was used: open.gl
- src/main.cpp: Draws player's gun, scene from tilemap, and colored 3D cubes targets with OpenGL shaders on a window generated with GLFW, with the possibility to navigate in the scene using WASD keys and the mouse (LMB is for shooting).
- GLFW (Graphics Library Framework): Library for creating windows with OpenGL context and for handling mouse and keyboard interactions. Read this GLFW tutorial.
- Glad: Loader for OpenGL functions. Following this tutorial from learnopengl.com, glad files can be generated using this webservice then copied inside include and src folders.
Shaders are written in GLSL (OpenGL Shading Language). The following two shaders (GPU programs) are needed to draw with OpenGL:
- Vertex shader: for each vertex, determines its position on the scene.
- Fragment shader: for each pixel, determines its color on the screen.
- Images used as textures are loaded using stb-image then sent to the GPU.
- Brick and building texture images downloaded from textures.com.
According to this blog post, we distinguish three types of colors when constructing a surface material:
- Ambient: Object's color when under the shadow of an ambient light (e.g. moon).
- Diffuse: Object's color when illuminated by a directed light, and is often perceived as the true color of the object.
- Specular: Reflection of the directed light on the object's surface. It depends on the shininess which makes the surface reflects (instead of scattering) the light, as its value increases. This therefore makes the highlight area become smaller, brighter, and more concentrated.
A table of these components values for different materials can be found on this site.
- VBO (Vertex Buffer Object):
- Holds vertices data.
- Needs to be bound before attaching vertexes data to it with
glBufferData
.
- VAO (Vertex Array Object):
- Linked to VBO when attributes are defined using
glVertexAttribPointer
(both VAO and VBO being bound). - Then inside the main loop, we'll only need to bind the VAO (and to use the appropriate shaders program) before drawing the vertexes.
- Linked to VBO when attributes are defined using
- Assimp was used to load 3D models in
\*.obj
format in OpenGL:
sudo apt install assimp-utils
- 3D models in *.obj format are ASCII text files that can be exported with Blender.
- Install gprof:
$ apt-get install binutils
- Compile program with profiling support:
$ cc -pg script.cpp -o app
- Run with gprof and look for function to profile:
$ gprof -p app | less
- Install
valgrind
from source following its official webpage or with package manager:
$ pacman -S valgrind
- Build project with debug symbols (
-g
in gcc,set(CMAKE_BUILD_TYPE Debug)
in cmake)
$ valgrind --tool=memcheck ./main
$ valgrind --tool=massif ./main
$ ms_print ./massif.out.12345
In the graph:
- Snapshot: Vertical bar (memory usage at time = t).
:
: Normal snapshot.@
: Detailed snapshot.#
: Peak snapshot.
For a better visualization on a gui:
$ pacman -S massif-visualizer
$ massif-visualizer ./massif.out.12345
To take a snapshot at a specific time, add to your source code:
#include "valgrind/valgrind.h"
int main() {
...
VALGRIND_MONITOR_COMMAND("detailed_snapshot");
...
}
And run program with massif:
$ valgrind --tool=massif ./main
$ massif-visualizer massif.vgdb.out