Skip to content

OpenGL-Graphics/first-person-shooter

Repository files navigation

Screenshot

Screenshot

How to run

# 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

Dependencies

To install the needed dependencies on Ubuntu:

$ apt install libglm-dev libglfw3-dev libassimp-dev

Requirements

  • OpenGL/GLSL 3.3+ GLSL 4.6 to support array indexing using non-consts (i.e. id-instance)

Audio

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.

Contols

  • Mouse: Orbit camera & shoot with LMB
  • WASD keys: Move camera

Resources


Tutorials

Useful tutorials:

Docs


Program

  • 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).

OpenGL

  • 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

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.

Texture image

  • Images used as textures are loaded using stb-image then sent to the GPU.
  • Brick and building texture images downloaded from textures.com.

Lights

According to this blog post, we distinguish three types of colors when constructing a surface material:

  1. Ambient: Object's color when under the shadow of an ambient light (e.g. moon).
  2. Diffuse: Object's color when illuminated by a directed light, and is often perceived as the true color of the object.
  3. 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.

OpenGL objects

  • 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.

Loading 3D models

  • 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.

Profiling with gprof

  • 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

Valgrind

  • 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)

Detecting memory leaks

$ valgrind --tool=memcheck ./main

Memory usage

With massif

$ 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.

Massif-visualizer

For a better visualization on a gui:

$ pacman -S massif-visualizer
$ massif-visualizer ./massif.out.12345

Programmatic snapshots

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