Add floor and point lights

This commit is contained in:
Nathan Chapman 2025-07-06 21:30:29 -06:00
parent 908232c31e
commit c6ae576289
7 changed files with 240 additions and 69 deletions

View File

@ -7,42 +7,85 @@ in vec3 frag_pos;
out vec4 color;
struct Directional_Light {
// Must match the same as in math.h
const int MAX_POINT_LIGHTS = 3;
struct Light {
vec3 color;
float ambient_intensity;
vec3 direction;
float diffuse_intensity;
};
struct Directional_Light {
Light base;
vec3 direction;
};
struct Point_Light {
Light base;
vec3 position;
float constant;
float linear;
float exponent;
};
struct Material {
float shininess;
float specular_intensity;
};
uniform sampler2D tex;
uniform Directional_Light sun;
uniform Point_Light point_lights[MAX_POINT_LIGHTS];
uniform int point_light_count;
uniform sampler2D tex;
uniform Material material;
uniform vec3 eye_position;
vec4 calculate_light_by_direction(Light light, vec3 direction) {
vec4 ambient_color = vec4(light.color, 1.0f) * light.ambient_intensity;
void main() {
vec4 ambient_color = vec4(sun.color, 1.0f) * sun.ambient_intensity;
float diffuse_factor = max(dot(normalize(normal), normalize(sun.direction)), 0.0f);
vec4 diffuse_color = vec4(sun.color, 1.0f) * sun.diffuse_intensity * diffuse_factor;
float diffuse_factor = max(dot(normalize(normal), normalize(direction)), 0.0f);
vec4 diffuse_color = vec4(light.color * light.diffuse_intensity * diffuse_factor, 1.0f);
vec4 specular_color = vec4(0, 0, 0, 0);
if (diffuse_factor > 0.0f) {
vec3 frag_to_eye = normalize(eye_position - frag_pos);
vec3 reflected_vertex = normalize(reflect(sun.direction, normalize(normal)));
vec3 reflected_vertex = normalize(reflect(direction, normalize(normal)));
float specular_factor = dot(frag_to_eye, reflected_vertex);
if (specular_factor > 0) {
if (specular_factor > 0.0f) {
specular_factor = pow(specular_factor, material.shininess);
specular_color = vec4(sun.color * material.specular_intensity * specular_factor, 1.0f);
specular_color = vec4(light.color * material.specular_intensity * specular_factor, 1.0f);
}
}
color = texture(tex, texture_coord) * (ambient_color + diffuse_color + specular_color);
return ambient_color + diffuse_color + specular_color;
}
vec4 calculate_point_lights() {
vec4 final_color = vec4(0, 0, 0, 0);
for (int i=0; i<point_light_count; i++) {
vec3 direction = frag_pos - point_lights[i].position;
float distance = length(direction);
direction = normalize(direction);
vec4 light_color = calculate_light_by_direction(point_lights[i].base, direction);
float attentuation = point_lights[i].exponent * distance * distance + point_lights[i].linear * distance + point_lights[i].constant;
final_color += (light_color / attentuation);
}
return final_color;
}
void main() {
vec4 final_color = calculate_light_by_direction(sun.base, sun.direction);
final_color += calculate_point_lights();
color = texture(tex, texture_coord) * final_color;
}

View File

@ -1,10 +1,2 @@
#include "light.h"
void use_light(Directional_Light *light, f32 color_location, f32 ambient_intensity_location, f32 diffuse_intensity_location, f32 direction_location) {
glUniform3f(color_location, light->color.x, light->color.y, light->color.z);
glUniform1f(ambient_intensity_location, light->ambient_intensity);
glUniform3f(direction_location, light->direction.x, light->direction.y, light->direction.z);
glUniform1f(diffuse_intensity_location, light->diffuse_intensity);
}

View File

@ -14,5 +14,10 @@ struct Directional_Light : public Light {
Vector3 direction = Vector3(0.0f, -1.0f, 0.0f); // Default to down
};
// Some of these should be u32
void use_light(Directional_Light *light, f32 color_location, f32 ambient_intensity_location, f32 diffuse_intensity_location, f32 direction_location);
struct Point_Light : public Light {
Vector3 position = Vector3(0.0f, 0.0f, 0.0f);
f32 constant = 1.0f;
f32 linear = 0.0f;
f32 exponent = 0.0f;
};

View File

@ -30,6 +30,26 @@ int main() {
f32 dt = 0.0f;
f32 last_dt = 0.f;
{
// Create a floor
f32 vertices[] = {
// x y z u v nx ny nz
-10.0f, 0.0f, -10.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f,
10.0f, 0.0f, -10.0f, 10.0f, 0.0f, 0.0f, -1.0f, 0.0f,
-10.0f, 0.0f, 10.0f, 0.0f, 10.0f, 0.0f, -1.0f, 0.0f,
10.0f, 0.0f, 10.0f, 10.0f, 10.0f, 0.0f, -1.0f, 0.0f,
};
u32 indices[] {
0, 2, 1,
1, 2, 3
};
Mesh *floor = new Mesh();
create_mesh(floor, vertices, indices, 32, 6);
meshes[0] = floor;
}
{
// Create a mesh
f32 vertices[] = {
@ -51,11 +71,11 @@ int main() {
Mesh *pyramid1 = new Mesh();
create_mesh(pyramid1, vertices, indices, 32, 12);
meshes[0] = pyramid1;
meshes[1] = pyramid1;
Mesh *pyramid2 = new Mesh();
create_mesh(pyramid2, vertices, indices, 32, 12);
meshes[1] = pyramid2;
meshes[2] = pyramid2;
}
{
@ -73,14 +93,47 @@ int main() {
plaster_texture.file_path = (char *)"assets/textures/plaster_texture_1k.png";
load_texture(&plaster_texture);
Material shiny_material{32.0f, 1.0f};
Material dull_material{4.0f, 0.3f};
Material shiny_material;
shiny_material.shininess = 256.0f;
shiny_material.specular_intensity = 4.0f;
Material dull_material;
dull_material.shininess = 4.0f;
dull_material.specular_intensity = 0.3f;
Directional_Light sun_light;
sun_light.ambient_intensity = 0.2f;
sun_light.diffuse_intensity = 1.0f;
sun_light.ambient_intensity = 0.0f;
sun_light.diffuse_intensity = 0.0f;
sun_light.direction = Vector3(2.0f, -1.0, -2.0f);
Point_Light point_lights[MAX_POINT_LIGHTS];
{
Point_Light point_light;
point_light.color = Vector3(1.0f, 1.0f, 1.0f);
point_light.ambient_intensity = 0.0f;
point_light.diffuse_intensity = 0.3f;
point_light.position = Vector3(10.0, 10.0f, 0.0f);
point_light.constant = 0.3f;
point_light.linear = 0.1f;
point_light.exponent = 0.1f;
point_lights[0] = point_light;
}
{
Point_Light point_light;
point_light.color = Vector3(1.0f, 0.6f, 0.0f);
point_light.ambient_intensity = 0.00f;
point_light.diffuse_intensity = 0.3f;
point_light.position = Vector3(-10.0, 0.0f, 0.0f);
point_light.constant = 0.3f;
point_light.linear = 0.1f;
point_light.exponent = 0.1f;
point_lights[1] = point_light;
}
u32 point_light_count = 2;
Matrix4 projection = glm::perspective(45.0f, (f32)window.buffer_width / (f32)window.buffer_height, 0.1f, 100.0f);
Camera camera;
@ -107,38 +160,46 @@ int main() {
glUseProgram(shaders[0].id);
use_light(
&sun_light,
shaders[0].uniform_ambient_color, shaders[0].uniform_ambient_intensity,
shaders[0].uniform_diffuse_intensity, shaders[0].uniform_diffuse_direction
);
use_light(&shaders[0], &sun_light);
use_light(&shaders[0], point_lights, point_light_count);
glUniformMatrix4fv(shaders[0].uniform_projection, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(shaders[0].projection, 1, GL_FALSE, glm::value_ptr(projection));
Matrix4 view = calculate_view_matrix(&camera);
glUniformMatrix4fv(shaders[0].uniform_view, 1, GL_FALSE, glm::value_ptr(view));
glUniform3f(shaders[0].uniform_eye_position, camera.position.x, camera.position.y, camera.position.z);
glUniformMatrix4fv(shaders[0].view, 1, GL_FALSE, glm::value_ptr(view));
glUniform3f(shaders[0].eye_position, camera.position.x, camera.position.y, camera.position.z);
{
Matrix4 model(1.0f);
model = glm::translate(model, Vector3(0.0f, 3.0f, 2.5f));
// model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f));
model = glm::translate(model, Vector3(0.0f, -2.0f, 0.0f));
glUniformMatrix4fv(shaders[0].uniform_model, 1, GL_FALSE, glm::value_ptr(model));
use_texture(&clay_texture);
use_material(&shiny_material, shaders[0].uniform_shininess, shaders[0].uniform_specular_intensity);
glUniformMatrix4fv(shaders[0].model, 1, GL_FALSE, glm::value_ptr(model));
use_texture(&plaster_texture);
use_material(&dull_material, shaders[0].shininess, shaders[0].specular_intensity);
render_mesh(meshes[0]);
}
{
Matrix4 model(1.0f);
model = glm::translate(model, Vector3(0.0f, 0.0f, 3.5f));
model = glm::translate(model, Vector3(-2.0f, 0.0f, -4.0f));
// model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(shaders[0].uniform_model, 1, GL_FALSE, glm::value_ptr(model));
use_texture(&plaster_texture);
use_material(&dull_material, shaders[0].uniform_shininess, shaders[0].uniform_specular_intensity);
glUniformMatrix4fv(shaders[0].model, 1, GL_FALSE, glm::value_ptr(model));
use_texture(&clay_texture);
use_material(&shiny_material, shaders[0].shininess, shaders[0].specular_intensity);
render_mesh(meshes[1]);
}
{
Matrix4 model(1.0f);
model = glm::translate(model, Vector3(2.0f, 0.0f, -4.0f));
glUniformMatrix4fv(shaders[0].model, 1, GL_FALSE, glm::value_ptr(model));
use_texture(&clay_texture);
use_material(&dull_material, shaders[0].shininess, shaders[0].specular_intensity);
render_mesh(meshes[2]);
}
glUseProgram(0);
// We usually have two buffers, the first is hidden and that's

View File

@ -38,4 +38,4 @@ using Vector3 = glm::vec3;
using string = std::string;
const f32 RADIAN_FACTOR = 3.14159265f / 180.0f;
const u32 MAX_POINT_LIGHTS = 3;

View File

@ -1,4 +1,5 @@
#include "shader.h"
#include "file.h"
Shader::~Shader() {
@ -56,18 +57,39 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f
return false;
}
shader->uniform_projection = glGetUniformLocation(shader->id, "projection");
shader->uniform_model = glGetUniformLocation(shader->id, "model");
shader->uniform_view = glGetUniformLocation(shader->id, "view");
shader->uniform_eye_position = glGetUniformLocation(shader->id, "eye_position");
shader->projection = glGetUniformLocation(shader->id, "projection");
shader->model = glGetUniformLocation(shader->id, "model");
shader->view = glGetUniformLocation(shader->id, "view");
shader->eye_position = glGetUniformLocation(shader->id, "eye_position");
shader->uniform_ambient_color = glGetUniformLocation(shader->id, "sun.color");
shader->uniform_ambient_intensity = glGetUniformLocation(shader->id, "sun.ambient_intensity");
shader->uniform_diffuse_direction = glGetUniformLocation(shader->id, "sun.direction");
shader->uniform_diffuse_intensity = glGetUniformLocation(shader->id, "sun.diffuse_intensity");
shader->directional_light.color = glGetUniformLocation(shader->id, "sun.base.color");
shader->directional_light.ambient_intensity = glGetUniformLocation(shader->id, "sun.base.ambient_intensity");
shader->directional_light.diffuse_intensity = glGetUniformLocation(shader->id, "sun.base.diffuse_intensity");
shader->directional_light.direction = glGetUniformLocation(shader->id, "sun.direction");
shader->uniform_shininess = glGetUniformLocation(shader->id, "material.shininess");
shader->uniform_specular_intensity = glGetUniformLocation(shader->id, "material.specular_intensity");
shader->shininess = glGetUniformLocation(shader->id, "material.shininess");
shader->specular_intensity = glGetUniformLocation(shader->id, "material.specular_intensity");
shader->point_light_count = glGetUniformLocation(shader->id, "point_light_count");
for (size_t i=0; i<MAX_POINT_LIGHTS; i++) {
char location_buffer[100] = {"\0"};
// Common
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].base.color", i);
shader->point_lights[i].color = glGetUniformLocation(shader->id, location_buffer);
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].base.ambient_intensity", i);
shader->point_lights[i].ambient_intensity = glGetUniformLocation(shader->id, location_buffer);
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].base.diffuse_intensity", i);
shader->point_lights[i].diffuse_intensity = glGetUniformLocation(shader->id, location_buffer);
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].position", i);
shader->point_lights[i].position = glGetUniformLocation(shader->id, location_buffer);
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].constant", i);
shader->point_lights[i].constant = glGetUniformLocation(shader->id, location_buffer);
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].constant", i);
shader->point_lights[i].constant = glGetUniformLocation(shader->id, location_buffer);
}
return true;
}
@ -105,7 +127,32 @@ void clear_shader(Shader *shader) {
shader->id = 0;
}
shader->uniform_model = 0;
shader->uniform_projection = 0;
shader->model = 0;
shader->projection = 0;
}
void use_light(Shader *shader, Directional_Light *light) {
glUniform3f(shader->directional_light.color, light->color.x, light->color.y, light->color.z);
glUniform1f(shader->directional_light.ambient_intensity, light->ambient_intensity);
glUniform3f(shader->directional_light.direction, light->direction.x, light->direction.y, light->direction.z);
glUniform1f(shader->directional_light.diffuse_intensity, light->diffuse_intensity);
}
void use_light(Shader *shader, Point_Light *point_lights, u32 point_light_count) {
if (point_light_count > MAX_POINT_LIGHTS) point_light_count = MAX_POINT_LIGHTS;
glUniform1i(shader->point_light_count, point_light_count);
for (size_t i = 0; i < point_light_count; i++) {
glUniform3f(shader->point_lights[i].color, point_lights[i].color.x, point_lights[i].color.y, point_lights[i].color.z);
glUniform1f(shader->point_lights[i].ambient_intensity, point_lights[i].ambient_intensity);
glUniform1f(shader->point_lights[i].diffuse_intensity, point_lights[i].diffuse_intensity);
glUniform3f(shader->point_lights[i].position, point_lights[i].position.x, point_lights[i].position.y, point_lights[i].position.z);
glUniform1f(shader->point_lights[i].constant, point_lights[i].constant);
glUniform1f(shader->point_lights[i].linear, point_lights[i].linear);
glUniform1f(shader->point_lights[i].exponent, point_lights[i].exponent);
}
}

View File

@ -3,7 +3,7 @@
#include <GL/glew.h>
#include <GL/gl.h>
#include "math.h"
#include "file.h"
#include "light.h"
enum Shader_Type : u32 {
VERTEX = GL_VERTEX_SHADER,
@ -12,19 +12,38 @@ enum Shader_Type : u32 {
struct Shader {
u32 id = 0;
u32 uniform_projection = 0;
u32 uniform_model = 0;
u32 uniform_view = 0;
u32 uniform_eye_position = 0;
u32 uniform_ambient_color = 0;
u32 uniform_ambient_intensity = 0;
u32 projection = 0;
u32 model = 0;
u32 view = 0;
u32 eye_position = 0;
u32 shininess = 0;
u32 specular_intensity = 0;
u32 position = 0;
u32 constant = 0;
u32 linear = 0;
u32 exponent = 0;
u32 uniform_diffuse_direction = 0;
u32 uniform_diffuse_intensity = 0;
struct {
u32 color;
u32 ambient_intensity;
u32 diffuse_intensity;
u32 uniform_shininess = 0;
u32 uniform_specular_intensity = 0;
u32 direction;
} directional_light;
u32 point_light_count = 0;
struct {
u32 color;
u32 ambient_intensity;
u32 diffuse_intensity;
u32 position;
u32 constant;
u32 linear;
u32 exponent;
} point_lights[MAX_POINT_LIGHTS];
~Shader();
};
@ -32,3 +51,7 @@ struct Shader {
bool create_shader(Shader *shader, const char *vertex_shader_path, const char *fragment_shader_path);
bool add_shader(Shader *shader, const char *shader_code, Shader_Type type);
void clear_shader(Shader *shader);
// Some of these should be u32
void use_light(Shader *shader, Directional_Light *light);
void use_light(Shader *shader, Point_Light *light, u32 point_light_count);