Add diffuse lighting

This commit is contained in:
Nathan Chapman 2025-07-05 12:13:42 -06:00
parent 5adc6e80e6
commit c746f1d8eb
15 changed files with 149 additions and 26 deletions

View File

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.19)
project(OpenGLTest CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
@ -11,6 +12,7 @@ find_package(glfw3 REQUIRED)
file(GLOB SOURCES src/*.h src/*.cpp)
add_executable(opengl_test ${SOURCES})
target_include_directories(opengl_test PUBLIC include)
target_link_libraries(opengl_test
OpenGL::GL
GLEW::GLEW

View File

@ -2,11 +2,25 @@
in vec4 vertex_color;
in vec2 texture_coord;
in vec3 normal;
out vec4 color;
struct Directional_Light {
vec3 color;
float ambient_intensity;
vec3 direction;
float diffuse_intensity;
};
uniform sampler2D tex;
uniform Directional_Light sun;
void main() {
color = texture(tex, texture_coord);
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;
color = texture(tex, texture_coord) * (ambient_color + diffuse_color);
}

View File

@ -2,9 +2,11 @@
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 tex;
layout (location = 2) in vec3 norm;
out vec4 vertex_color;
out vec2 texture_coord;
out vec3 normal;
uniform mat4 projection;
uniform mat4 model;
@ -14,4 +16,5 @@ void main() {
gl_Position = projection * view * model * vec4(pos, 1.0);
vertex_color = vec4(clamp(pos, 0.0f, 1.0f), 1.0f);
texture_coord = tex;
normal = mat3(transpose(inverse(model))) * norm;
}

View File

@ -1,7 +1,7 @@
#include "file.h"
std::string read_entire_file(const char *path) {
std::string content;
string read_entire_file(const char *path) {
string content;
std::ifstream file_stream(path, std::ios::in);
if (!file_stream.is_open()) {
@ -9,7 +9,7 @@ std::string read_entire_file(const char *path) {
return "";
}
std::string line = "";
string line = "";
while (!file_stream.eof())
{
std::getline(file_stream, line);

View File

@ -1,7 +1,6 @@
#pragma once
#include <string>
#include <iostream>
#include <fstream>
#include "math.h"
std::string read_entire_file(const char *path);
string read_entire_file(const char *path);

12
src/light.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "light.h"
Light::Light(Vector3 color, f32 ambient_intensity, Vector3 direction, f32 diffuse_intensity) : color(color), ambient_intensity(ambient_intensity), direction(direction), diffuse_intensity(diffuse_intensity) {}
void use_light(Light *light, f32 color_location, f32 ambient_intensity_location, f32 direction_location, f32 diffuse_intensity_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);
}

19
src/light.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "math.h"
struct Light {
Vector3 color = Vector3(1.0f, 1.0f, 1.0f);
f32 ambient_intensity = 1.0f;
// For a directional light
Vector3 direction = Vector3(0.0f, -1.0f, 0.0f); // Default to down
f32 diffuse_intensity = 0.0f;
Light(Vector3 color, f32 ambient_intensity, Vector3 direction, f32 diffuse_intensity);
~Light() = default;
};
void use_light(Light *light, f32 color_location, f32 ambient_intensity_location, f32 direction_location, f32 diffuse_intensity_location);

View File

@ -5,6 +5,7 @@
#include "window.h"
#include "camera.h"
#include "texture.h"
#include "light.h"
static const char *vertex_shader_code = "shaders/shader.vert";
@ -24,11 +25,11 @@ int main() {
{
// Create a mesh
f32 vertices[] = {
// x y z u v
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f
// x y z u v nx ny nz
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f
};
u32 indices[] = {
@ -38,12 +39,14 @@ int main() {
0, 1, 2
};
calculate_normals_avg(vertices, 32, 8, indices, 12, 5);
Mesh *pyramid1 = new Mesh();
create_mesh(pyramid1, vertices, indices, 20, 12);
create_mesh(pyramid1, vertices, indices, 32, 12);
meshes[0] = pyramid1;
Mesh *pyramid2 = new Mesh();
create_mesh(pyramid2, vertices, indices, 20, 12);
create_mesh(pyramid2, vertices, indices, 32, 12);
meshes[1] = pyramid2;
}
@ -60,9 +63,9 @@ int main() {
Texture plaster_texture = Texture((char *)"assets/textures/plaster_texture_1k.png");
load_texture(&plaster_texture);
Matrix4 projection = glm::perspective(
45.0f, (f32)window.buffer_width / (f32)window.buffer_height, 0.1f,
100.0f);
Light sun_light(Vector3(1.0f, 1.0f, 1.0f), 0.2f, Vector3(2.0f, -1.0, -2.0f), 1.0f);
Matrix4 projection = glm::perspective(45.0f, (f32)window.buffer_width / (f32)window.buffer_height, 0.1f, 100.0f);
Camera camera(Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f), 90.0f, 0.0f, 5.0f, 1.0f);
@ -74,9 +77,6 @@ int main() {
dt = now - last_dt;
last_dt = now;
// Get and handle user input events
glfwPollEvents();
key_control(&camera, window.ascii_keys, dt);
mouse_control(&camera, window.x_change_position, window.y_change_position);
@ -90,6 +90,12 @@ int main() {
glUseProgram(shaders[0].id);
use_light(
&sun_light,
shaders[0].uniform_ambient_color, shaders[0].uniform_ambient_intensity,
shaders[0].uniform_diffuse_direction, shaders[0].uniform_diffuse_intensity
);
{
Matrix4 model(1.0f);
model = glm::translate(model, Vector3(0.0f, 0.0f, -2.5f));
@ -125,6 +131,9 @@ int main() {
// that it now shows. We then can start drawing on the other
// buffer.
glfwSwapBuffers(window.gl_window);
// Get and handle user input events
glfwPollEvents();
}
return 0;

View File

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
// #include <cstdint>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
@ -34,5 +35,7 @@ typedef double f64;
using Matrix4 = glm::mat4;
using Vector3 = glm::vec3;
using string = std::string;
const f32 RADIAN_FACTOR = 3.14159265f / 180.0f;

View File

@ -32,13 +32,16 @@ void create_mesh(
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices_count, vertices, GL_STATIC_DRAW);
// Position vertices
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 5, 0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, 0);
glEnableVertexAttribArray(0);
// Texture coordinates
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 5, (void *)(sizeof(vertices[0]) * 3));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void *)(sizeof(vertices[0]) * 3));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void *)(sizeof(vertices[0]) * 5));
glEnableVertexAttribArray(2);
// Unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@ -73,3 +76,51 @@ void clear_mesh(Mesh *mesh) {
mesh->index_count = 0;
}
void calculate_normals_avg(f32 *vertices, u32 vertices_count, u32 vertices_length, u32 *indices, u32 indices_count, u32 normal_offset) {
for (size_t i = 0; i< indices_count; i+=3) {
u32 in0 = indices[i] * vertices_length;
u32 in1 = indices[i+1] * vertices_length;
u32 in2 = indices[i+2] * vertices_length;
Vector3 v1;
v1.x = vertices[in1] - vertices[in0];
v1.y = vertices[in1+1] - vertices[in0+1];
v1.z = vertices[in1+2] - vertices[in0+2];
Vector3 v2;
v2.x = vertices[in2] - vertices[in0];
v2.y = vertices[in2+1] - vertices[in0+1];
v2.z = vertices[in2+2] - vertices[in0+2];
Vector3 normal = glm::cross(v1, v2);
normal = glm::normalize(normal);
in0 += normal_offset;
in1 += normal_offset;
in2 += normal_offset;
vertices[in0] += normal.x;
vertices[in0+1] += normal.y;
vertices[in0+2] += normal.z;
vertices[in1] += normal.x;
vertices[in1+1] += normal.y;
vertices[in1+2] += normal.z;
vertices[in2] += normal.x;
vertices[in2+1] += normal.y;
vertices[in2+2] += normal.z;
}
for(size_t i=0; i<vertices_count/vertices_length; i++) {
u32 n_offset = i * vertices_length + normal_offset;
Vector3 vector(vertices[n_offset], vertices[n_offset+1], vertices[n_offset+2]);
vector = glm::normalize(vector);
vertices[n_offset] = vector.x;
vertices[n_offset+1] = vector.y;
vertices[n_offset+2] = vector.z;
}
}

View File

@ -14,4 +14,5 @@ struct Mesh {
void create_mesh(Mesh *mesh, f32 *vertices, u32 *indices, u32 vertices_count, u32 indices_count);
void render_mesh(Mesh *mesh);
void clear_mesh(Mesh *mesh);
void calculate_normals_avg(f32 *vertices, u32 vertices_count, u32 vertices_length, u32 *indices, u32 indices_count, u32 normal_offset);

View File

@ -11,8 +11,8 @@ Shader::~Shader() {
}
bool create_shader(Shader *shader, const char *vertex_shader_path, const char *fragment_shader_path) {
std::string vertex_shader_code = read_entire_file(vertex_shader_path);
std::string fragment_shader_code = read_entire_file(fragment_shader_path);
string vertex_shader_code = read_entire_file(vertex_shader_path);
string fragment_shader_code = read_entire_file(fragment_shader_path);
shader->id = glCreateProgram();
@ -65,6 +65,12 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f
shader->uniform_model = glGetUniformLocation(shader->id, "model");
shader->uniform_view = glGetUniformLocation(shader->id, "view");
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");
return true;
}

View File

@ -15,6 +15,10 @@ struct Shader {
u32 uniform_projection;
u32 uniform_model;
u32 uniform_view;
u32 uniform_ambient_color;
u32 uniform_ambient_intensity;
u32 uniform_diffuse_direction;
u32 uniform_diffuse_intensity;
Shader();
~Shader();

View File

@ -1,8 +1,8 @@
#pragma once
#include <GL/glew.h>
#include <stb_image.h>
#include "math.h"
#include "../lib/stb_image.h"
struct Texture {
u32 id = 0;