Skip to content

Latest commit

 

History

79 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

image image

This project is a Physically Based Rendering (PBR) graphics engine, which uses the principles of PBR to render realistic looking materials based on the Cook-Torrence BRDF (Bidirectional Reflectance Distribution Function).

How to Build (Windows)

This project was built using JDK 23, using prior JDK versions may cause unexpected behavior

  1. First clone the repository using the command below in the terminal
git clone https://github.com/Daschle-Newberry/PBR-Lighting-Engine
  1. Once within the project directory, run the following command. This will create an jar file for the project that contains all the necessary resources
.\gradlew.bat shadowjar
  1. Locate the jar file, it should be in the build\libs folder

  2. Copy the jar location and run this command in the terminal

java -jar C:\Users\...\path\to\the\jar

Important!

This project currently has no GUI and it purely a proof of concept for a bigger project. There is a high likelihood of graphical issues and poor performance as well! These issues will be addressed in a later version of the project.

Theory

The BRDF is used to approximate the specular and diffuse portion of the reflectance equation, which is the following:

The function, fr(), is the BRDF part of the reflectance equation. Li() is the incident radiance, and alters the outgoing radiance (Lo) depending on the light intensity and color. The dot product of the normal (n) and the incident light direction (wi) scales the outgoing radiance depending on if the point (or fragment in our case) is facing the light source.

Let's look at the BRDF and how it is calculated

PBR works based on the core principle that a surface is made up of micro-facets, which are very small reflective surfaces. Depending on the roughness of the surface, these micro-facets will be aligned in different directions, which changes how the surface interacts with light.

For our cases we will break down the BRDF into two parts, diffuse light and specular light.

The Specular portion is calculated by the following equation:



The Normal Distribution Function (D):



The Normal Distribution Function (NDF) represents the amount of surface area that is aligned with the half-vector between the incident light direction and the view direction. Using the surface normal, the half-vector, and the roughness parameter (alpha) we can calculate the D term.

The Geometry Function (G):



Similarly to the NDF, the Geometry function represents the amount of surface area that is self shadowed. Since micro-facets can either obstruct light from reaching the viewer or reflect the light away from the viewer, we must calculate the geometry term once using the light vector and once using the view vector:


Fresnel equation (F)


The Fresnel equation is perhaps one of the most import parts of the BRDF, and it represents the ratio of light that is reflected over the portion that is refracted. It is calculated using the following equation:

F0 represents the base reflectivity of an object, which determines how reflective each color of a surface albedo is. For example, a gold reflective surface may have a F0 of (1.00, 0.71, 0.29). The Fresnel equation takes the base reflectivity, and increases it by a portion of its complement. How large the compliment is is dependent on the angle between the half vector and the view vector. This calculation causes surfaces to be more reflective when they are observed at grazing angles, similar to real life.

To finalize the specular term, we divide by 4 times the dot product of the outgoing light direction (view direction) and the normal times the dot product of the incident light direction and the normal. We do this to ensure that the outgoing light does not exceed the incoming light (law of conservation of energy).

The diffuse portion is much simpler than the specular portion and only involves two steps:


First, we compute the ratio of light that is diffuse by first finding what portion of the light is specular (reflected). Since the Fresnel term determines the magnitude of the specular portion, we can use its compliment to determine the magnitude of the diffuse portion:


We use the kd term to scale the color of the surface, but we must divide the surface albedo by pi. The division by pi is to ensure that the outgoing light energy is not greater than the incoming light energy as we integrate over the entire hemisphere (As seen in the BRDF):

With that, we can finally calculate the BRDF


Note

While the previous calculations are used to calculate the lighting of an object with respect to a single light source, they do NOT include the image based lighting calculations, which are responsible for the majority of the specular reflections in the scene. The image based lighting is calculated using the same reflectance equation, plus some optimizations to make it possible to compute it over an entire hemisphere of infinite view angles. The primary optimization we make it precomputing the image based lighting, which then utilizes optimizations like the split-sum approximation and importance sampling. Unfortunately, these concepts exceed what can be explained over a github page.

If you would like to learn more about image based lighting:
Diffuse
Specular

Resources

learnopengl.com : This website is an amazing resource for learning not only OpenGL, but other graphics programming concepts. I used the PBR section to learn essentially everything in this project, and you will see them referenced in my code in some areas.

OGLDev on YouTube : OGLDev is an amazing YouTube channel for learning all things computer graphics. He has helped me learn a lot of shadow mapping specifically, which is a bit of a pain.

GamesWithGabe GamesWithGabe is another amazing YouTube channel for learning all sorts of programming concepts. This channel specifically helped me in my early CGI journey to learn how to use LWJGL for GLFW and OpenGL bindings. I also used this channel when creating some of the basic engine architecture, such as the window class and key listeners.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages