Experience
By Lucas Li, Alex Hartford, Brett Hickman
Experience is a small expressive game made in 10 weeks about the process of trying to improve at something. The game involves walking through various environments which evoke feelings like those experienced when learning something new.
Gameplay
The game takes place from a first-person perspective. The gameplay is as simple as walking and observing. The player can interact with their environment, reading notes strewn about the environment and talking with animals.
Environment
The environments of the game are threefold. To travel between the environments, the player can simply walk into the fog at the edge of each environment whenever they choose.
Forest - A new beginning!
At first, the player will find themselves in a quiet wood. This area is intended to evoke feelings of a fresh start. Secrets are found around every corner, and the world is new and interesting.
Third Person View | First Person View |
---|---|
Desert - Arduous Journey
Next, the player will find themselves in a desert wasteland, with long stretches of empty land and steep sand dunes. Bloom and Blur effects make the journey feel arduous. Deep in the desert you may find secrets, but they are few and far between, and this area evokes the feeling of being overwhelmed by your task.
Third Person View | First Person View |
---|---|
Street - Completion and Loneliness
Finally, the player will find themselves on a dark street in the middle of the night. No stars in the sky, just loneliness. streetlamps light the path. You have completed your journey, and overcome much, and have seen the fleeting beauty of the journey you’ve traveled, but now you find yourself alone. Only you know what you have learned.
Third Person View | First Person View |
---|---|
Nothing else to do, then, than to start a new journey!
Credit - With Secret Ending
Collect all the notes and messages to find out!
Technical Details
The game was developed within 10 weeks from scratch in C++ and OpenGL, aside from using libraries to open windows, load meshes, and audio. We started the development with creating a world loader:
World Loading
To start the development process, I made a world loader to read and save the world per level. Since the world is a combination of objects, we decided to build the level from a single text file that contains all the information we need for each of the objects.
The custom Object class contains the following information:
int id;
vec3 position;
float angleX;
float angleY;
float angleZ;
float scaleFactor;
vec3 velocity;
float view_radius;
float collision_radius;
float selection_radius;
mat4 matrix;
Material material;
bool interactible;
bool disappearing;
int noteNum;
int sound;
and a sample generated text file can be as such:
COM Next Level: <NXT path>
NXT ../levels/forest.txt
COM Camera Setup: <POV pos.x pos.y pos.z>
POV 40.229 0 103.111
COM Object: <OBJ id pos.x pos.y pos.z angleX angleY angleZ vel.x vel.y vel.z rad_v rad_c rad_s scale inter? disap? noteN sound>
OBJ 0 -54.0641 1.34955 -35.4378 -1.6 0 0 1 1 1 5.31453 1.69885 1 3.75851 0 0 0 1
OBJ 0 75.0108 -2.2981 -94.1649 -1.6 0 0 1 1 1 6.04608 1.93269 1 4.27587 0 0 0 1
Instanced Rendering
for(int i = 0; i < entry.model->meshes.size(); i++)
{
glBindVertexArray(entry.model->meshes[i].VAO);
glDrawElementsInstanced(GL_TRIANGLES,
static_cast<unsigned int>(entry.model->meshes[i].indices.size()),
GL_UNSIGNED_INT, 0,
modelMatrices.size());
glBindVertexArray(0);
}
Models and particles are rendered using Instancing, increasing the maximum render cap by a sizable margin.
Shadow Mapping
void render()
{
shader.use();
glUniformMatrix4fv(lightSpaceMatrixLocation, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
RenderScene(shader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Our game makes a first render pass to a depth buffer, which is then used later in the pipeline to calculate dynamic shadows.
High Dynamic Range
High Dynamic Range, in conjunction with Bloom/Blur, creates a very vibrant and lively scene. We calculate excess color above the standard white maximum, and we perform gamma correction to ensure that the scene fits within a certain exposure.
Bloom and Blur
The game also uses a Bloom effect to simulate bright lights. We find bright segments (above a certain threshold), and we render these to their own Framebuffer. We then perform a Gaussian Blur on that framebuffer, which we merge with the original image to get our bloomed result.
View Frustum Culling
bool ViewFrustCull(vec3 center, float radius)
{
float dist;
for(int i=0; i < 6; i++){
dist = DistToPlane(planes[i].x, planes[i].y, planes[i].z, planes[i].w, center);
if(dist < 0 && fabs(dist) > radius){
return true;
}
}
return false;
}
- Notice that the drawn objects decrease from 14616 to 3123
The game needs to be as performant as possible, especially considering the amount of models that we render. For this to be feasible, we implemented View Frustum Culling. It calculates the area that can be viewed, and performs spatial queries to determine if a given object should be drawn.
Distance Fog
Our game includes distance fog to simulate depth more accurately. It can be tweaked in the editor.
Level Editor
We achieved a rich, detailed set of environments by constructing a level editor. We save files to an ASCII format and load them into our game. It allows you to tweak every aspect of the levels, from particles to distance fog.
visualize seletion visualize collision visualize view frustum
Getting Started
Built With
The CMake is not tested on Windows or Linux. It uses find-package to search for libraries, which I believe searches the source tree as well as some places on your computer, but definitely some expertise will be required if encountering any bugs.
I would recommend installing each library using a package manager like Brew if you can, and otherwise putting them in a usual spot on your system where CMake is likely to find them.
References
LearnOpenGL: The best resource - CGTrader - Sketchfab
Dependencies
GLFW - GLM - Assimp - Freetype
Included
GLAD - ImGui - tinyobjloader - miniaudio - stbimage
Contact
Lucas Li - lucasli010410@gmail.com
Alex Hartford - alexanderhartford@gmail.com
Brett Hickman - bahickma@calpoly.edu