July 10, 2022

Experience

A full 3D engine in C++ and OpenGL

By Brett Hickman, Lucas Li, Alex Hartford

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 forest. This area is intended to evoke feelings of a fresh start. Secrets are found around every corner, and the world is new and interesting.








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.








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.








Nothing else to do, then, than to start a new journey!

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.

Instanced Rendering

									for(int i = 0; i < entry.model->meshes.size(); i++)
{
	glBindVertexArray(entry.model->meshes[i].VAO);
	glDrawElementsInstanced(GL_TRIANGLES,
	static_cast(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.

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;
}
								







It's hard to see, but the drawn objects decreases from 14616, to 3123 after culling. 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.

Level Editor

We developed a full level editor complete with an object, lighting, shadow, audio, and particle editor. We achieved this by saving files to an ASCII format and loading them into our game. It allows you to tweak every aspect of the levels, from particles to distance fog.

Retrospective

Overall, I learned an incredible about from this project. It was my first attempt at creating a full 3D engine so there were plenty of issues and bad code. The whole time it felt like I was sprinting a marathon and learning 10 new things everyday but I enjoyed the whole process.