Add spot lights
This commit is contained in:
parent
c6ae576289
commit
62a4b739dd
BIN
assets/krita/plaster_texture_1k.png
Normal file
BIN
assets/krita/plaster_texture_1k.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
@ -1,4 +1,4 @@
|
||||
#version 330
|
||||
#version 460 core
|
||||
|
||||
in vec4 vertex_color;
|
||||
in vec2 texture_coord;
|
||||
@ -9,6 +9,7 @@ out vec4 color;
|
||||
|
||||
// Must match the same as in math.h
|
||||
const int MAX_POINT_LIGHTS = 3;
|
||||
const int MAX_SPOT_LIGHTS = 3;
|
||||
|
||||
struct Light {
|
||||
vec3 color;
|
||||
@ -17,18 +18,25 @@ struct Light {
|
||||
};
|
||||
|
||||
struct Directional_Light {
|
||||
Light base;
|
||||
Light light;
|
||||
vec3 direction;
|
||||
};
|
||||
|
||||
struct Point_Light {
|
||||
Light base;
|
||||
Light light;
|
||||
vec3 position;
|
||||
float constant;
|
||||
float linear;
|
||||
float exponent;
|
||||
};
|
||||
|
||||
struct Spot_Light {
|
||||
Point_Light point_light;
|
||||
|
||||
vec3 direction;
|
||||
float edge;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
float shininess;
|
||||
float specular_intensity;
|
||||
@ -37,8 +45,10 @@ struct Material {
|
||||
|
||||
uniform Directional_Light sun;
|
||||
uniform Point_Light point_lights[MAX_POINT_LIGHTS];
|
||||
uniform Spot_Light spot_lights[MAX_SPOT_LIGHTS];
|
||||
|
||||
uniform int point_light_count;
|
||||
uniform int spot_light_count;
|
||||
uniform sampler2D tex;
|
||||
uniform Material material;
|
||||
uniform vec3 eye_position;
|
||||
@ -65,27 +75,55 @@ vec4 calculate_light_by_direction(Light light, vec3 direction) {
|
||||
return ambient_color + diffuse_color + specular_color;
|
||||
}
|
||||
|
||||
vec4 calculate_point_light(Point_Light point_light) {
|
||||
vec3 direction = frag_pos - point_light.position;
|
||||
float distance = length(direction);
|
||||
direction = normalize(direction);
|
||||
|
||||
vec4 light_color = calculate_light_by_direction(point_light.light, direction);
|
||||
float attentuation = point_light.exponent * distance * distance + point_light.linear * distance + point_light.constant;
|
||||
|
||||
return (light_color / attentuation);
|
||||
}
|
||||
|
||||
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);
|
||||
final_color += calculate_point_light(point_lights[i]);
|
||||
}
|
||||
|
||||
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;
|
||||
return final_color;
|
||||
}
|
||||
|
||||
final_color += (light_color / attentuation);
|
||||
vec4 calculate_spot_light(Spot_Light spot_light) {
|
||||
vec3 ray_direction = normalize(frag_pos - spot_light.point_light.position);
|
||||
float spot_light_factor = dot(ray_direction, spot_light.direction);
|
||||
|
||||
if (spot_light_factor > spot_light.edge) {
|
||||
vec4 light_color = calculate_point_light(spot_light.point_light);
|
||||
|
||||
return light_color * (1.0f - (1.0f - spot_light_factor)*(1.0f/(1.0f - spot_light.edge)));
|
||||
}
|
||||
|
||||
return vec4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
vec4 calculate_spot_lights() {
|
||||
vec4 final_color = vec4(0, 0, 0, 0);
|
||||
|
||||
for (int i=0; i<spot_light_count; i++) {
|
||||
final_color += calculate_spot_light(spot_lights[i]);
|
||||
}
|
||||
|
||||
return final_color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 final_color = calculate_light_by_direction(sun.base, sun.direction);
|
||||
vec4 final_color = calculate_light_by_direction(sun.light, sun.direction);
|
||||
|
||||
final_color += calculate_point_lights();
|
||||
final_color += calculate_spot_lights();
|
||||
|
||||
color = texture(tex, texture_coord) * final_color;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#version 330
|
||||
#version 460 core
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 tex;
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
#include "light.h"
|
||||
|
||||
10
src/light.h
10
src/light.h
@ -21,3 +21,13 @@ struct Point_Light : public Light {
|
||||
f32 exponent = 0.0f;
|
||||
};
|
||||
|
||||
struct Spot_Light : public Light {
|
||||
Vector3 direction = Vector3(0.0f, -1.0f, 0.0f);
|
||||
Vector3 position = Vector3(0.0f, 0.0f, 0.0f);
|
||||
f32 constant = 1.0f;
|
||||
f32 linear = 0.0f;
|
||||
f32 exponent = 0.0f;
|
||||
f32 edge = 0.0f;
|
||||
f32 processed_edge = 0.0f; // Don't forget to glm::radians(edge)
|
||||
};
|
||||
|
||||
|
||||
49
src/main.cpp
49
src/main.cpp
@ -107,36 +107,60 @@ int main() {
|
||||
sun_light.direction = Vector3(2.0f, -1.0, -2.0f);
|
||||
|
||||
Point_Light point_lights[MAX_POINT_LIGHTS];
|
||||
u32 point_light_count = 0;
|
||||
|
||||
{
|
||||
Point_Light point_light;
|
||||
point_light.color = Vector3(1.0f, 1.0f, 1.0f);
|
||||
point_light.color = Vector3(1.0f, 0.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.position = Vector3(10.0f, 2.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_count++;
|
||||
}
|
||||
|
||||
{
|
||||
Point_Light point_light;
|
||||
point_light.color = Vector3(1.0f, 0.6f, 0.0f);
|
||||
point_light.ambient_intensity = 0.00f;
|
||||
point_light.color = Vector3(0.0f, 1.0f, 0.0f);
|
||||
point_light.ambient_intensity = 0.0f;
|
||||
point_light.diffuse_intensity = 0.3f;
|
||||
point_light.position = Vector3(-10.0, 0.0f, 0.0f);
|
||||
point_light.position = Vector3(-10.0f, 2.0f, 0.0f);
|
||||
point_light.constant = 0.3f;
|
||||
point_light.linear = 0.1f;
|
||||
point_light.exponent = 0.1f;
|
||||
|
||||
point_lights[1] = point_light;
|
||||
point_light_count++;
|
||||
}
|
||||
|
||||
u32 point_light_count = 2;
|
||||
Spot_Light spot_lights[MAX_SPOT_LIGHTS];
|
||||
u32 spot_light_count = 0;
|
||||
|
||||
{
|
||||
Spot_Light spot_light;
|
||||
spot_light.color = Vector3(0.0f, 0.0f, 1.0f);
|
||||
spot_light.direction = glm::normalize(Vector3(0.0f, -1.0f, 0.0f));
|
||||
spot_light.ambient_intensity = 5.0f;
|
||||
spot_light.diffuse_intensity = 2.0f;
|
||||
spot_light.position = Vector3(0.0f, 10.0f, 0.0f);
|
||||
spot_light.constant = 1.0f;
|
||||
spot_light.linear = 0.0f;
|
||||
spot_light.exponent = 0.0f;
|
||||
spot_light.edge = 20.0f;
|
||||
spot_light.processed_edge = cosf(glm::radians(20.0f));
|
||||
|
||||
spot_lights[0] = spot_light;
|
||||
spot_light_count++;
|
||||
}
|
||||
|
||||
Matrix4 projection = glm::perspective(45.0f, (f32)window.buffer_width / (f32)window.buffer_height, 0.1f, 100.0f);
|
||||
|
||||
Camera camera;
|
||||
camera.position.y = 2.0f;
|
||||
update_camera(&camera);
|
||||
|
||||
|
||||
@ -162,6 +186,7 @@ int main() {
|
||||
|
||||
use_light(&shaders[0], &sun_light);
|
||||
use_light(&shaders[0], point_lights, point_light_count);
|
||||
use_light(&shaders[0], spot_lights, spot_light_count);
|
||||
|
||||
glUniformMatrix4fv(shaders[0].projection, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
Matrix4 view = calculate_view_matrix(&camera);
|
||||
@ -169,9 +194,9 @@ int main() {
|
||||
glUniform3f(shaders[0].eye_position, camera.position.x, camera.position.y, camera.position.z);
|
||||
|
||||
|
||||
{
|
||||
{ // Floor
|
||||
Matrix4 model(1.0f);
|
||||
model = glm::translate(model, Vector3(0.0f, -2.0f, 0.0f));
|
||||
model = glm::translate(model, Vector3(0.0f, 0.0f, 0.0f));
|
||||
|
||||
glUniformMatrix4fv(shaders[0].model, 1, GL_FALSE, glm::value_ptr(model));
|
||||
use_texture(&plaster_texture);
|
||||
@ -179,9 +204,9 @@ int main() {
|
||||
render_mesh(meshes[0]);
|
||||
}
|
||||
|
||||
{
|
||||
{ // Prism
|
||||
Matrix4 model(1.0f);
|
||||
model = glm::translate(model, Vector3(-2.0f, 0.0f, -4.0f));
|
||||
model = glm::translate(model, Vector3(0.0f, 1.0f, 0.0f));
|
||||
// model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f));
|
||||
|
||||
glUniformMatrix4fv(shaders[0].model, 1, GL_FALSE, glm::value_ptr(model));
|
||||
@ -190,9 +215,9 @@ int main() {
|
||||
render_mesh(meshes[1]);
|
||||
}
|
||||
|
||||
{
|
||||
{ // Prism
|
||||
Matrix4 model(1.0f);
|
||||
model = glm::translate(model, Vector3(2.0f, 0.0f, -4.0f));
|
||||
model = glm::translate(model, Vector3(2.0f, 1.0f, -4.0f));
|
||||
|
||||
glUniformMatrix4fv(shaders[0].model, 1, GL_FALSE, glm::value_ptr(model));
|
||||
use_texture(&clay_texture);
|
||||
|
||||
@ -39,3 +39,4 @@ using string = std::string;
|
||||
|
||||
const f32 RADIAN_FACTOR = 3.14159265f / 180.0f;
|
||||
const u32 MAX_POINT_LIGHTS = 3;
|
||||
const u32 MAX_SPOT_LIGHTS = 3;
|
||||
|
||||
@ -62,25 +62,27 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f
|
||||
shader->view = glGetUniformLocation(shader->id, "view");
|
||||
shader->eye_position = glGetUniformLocation(shader->id, "eye_position");
|
||||
|
||||
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.color = glGetUniformLocation(shader->id, "sun.light.color");
|
||||
shader->directional_light.ambient_intensity = glGetUniformLocation(shader->id, "sun.light.ambient_intensity");
|
||||
shader->directional_light.diffuse_intensity = glGetUniformLocation(shader->id, "sun.light.diffuse_intensity");
|
||||
shader->directional_light.direction = glGetUniformLocation(shader->id, "sun.direction");
|
||||
|
||||
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");
|
||||
shader->spot_light_count = glGetUniformLocation(shader->id, "spot_light_count");
|
||||
|
||||
// Point lights
|
||||
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);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].light.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);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].light.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);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].light.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);
|
||||
@ -91,6 +93,31 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f
|
||||
shader->point_lights[i].constant = glGetUniformLocation(shader->id, location_buffer);
|
||||
}
|
||||
|
||||
// Spot lights
|
||||
for (size_t i=0; i<MAX_SPOT_LIGHTS; i++) {
|
||||
char location_buffer[100] = {"\0"};
|
||||
|
||||
// Common
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.light.color", i);
|
||||
shader->spot_lights[i].color = glGetUniformLocation(shader->id, location_buffer);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.light.ambient_intensity", i);
|
||||
shader->spot_lights[i].ambient_intensity = glGetUniformLocation(shader->id, location_buffer);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.light.diffuse_intensity", i);
|
||||
shader->spot_lights[i].diffuse_intensity = glGetUniformLocation(shader->id, location_buffer);
|
||||
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.position", i);
|
||||
shader->spot_lights[i].position = glGetUniformLocation(shader->id, location_buffer);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.constant", i);
|
||||
shader->spot_lights[i].constant = glGetUniformLocation(shader->id, location_buffer);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.constant", i);
|
||||
shader->spot_lights[i].constant = glGetUniformLocation(shader->id, location_buffer);
|
||||
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].direction", i);
|
||||
shader->spot_lights[i].direction = glGetUniformLocation(shader->id, location_buffer);
|
||||
snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].edge", i);
|
||||
shader->spot_lights[i].edge = glGetUniformLocation(shader->id, location_buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -156,3 +183,23 @@ void use_light(Shader *shader, Point_Light *point_lights, u32 point_light_count)
|
||||
}
|
||||
}
|
||||
|
||||
void use_light(Shader *shader, Spot_Light *spot_lights, u32 spot_light_count) {
|
||||
if (spot_light_count > MAX_SPOT_LIGHTS) spot_light_count = MAX_SPOT_LIGHTS;
|
||||
|
||||
glUniform1i(shader->spot_light_count, spot_light_count);
|
||||
|
||||
for (size_t i = 0; i < spot_light_count; i++) {
|
||||
glUniform3f(shader->spot_lights[i].color, spot_lights[i].color.x, spot_lights[i].color.y, spot_lights[i].color.z);
|
||||
glUniform1f(shader->spot_lights[i].ambient_intensity, spot_lights[i].ambient_intensity);
|
||||
glUniform1f(shader->spot_lights[i].diffuse_intensity, spot_lights[i].diffuse_intensity);
|
||||
|
||||
glUniform3f(shader->spot_lights[i].position, spot_lights[i].position.x, spot_lights[i].position.y, spot_lights[i].position.z);
|
||||
glUniform1f(shader->spot_lights[i].constant, spot_lights[i].constant);
|
||||
glUniform1f(shader->spot_lights[i].linear, spot_lights[i].linear);
|
||||
glUniform1f(shader->spot_lights[i].exponent, spot_lights[i].exponent);
|
||||
|
||||
glUniform3f(shader->spot_lights[i].direction, spot_lights[i].direction.x, spot_lights[i].direction.y, spot_lights[i].direction.z);
|
||||
glUniform1f(shader->spot_lights[i].edge, spot_lights[i].processed_edge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
src/shader.h
18
src/shader.h
@ -45,6 +45,22 @@ struct Shader {
|
||||
u32 exponent;
|
||||
} point_lights[MAX_POINT_LIGHTS];
|
||||
|
||||
u32 spot_light_count = 0;
|
||||
|
||||
struct {
|
||||
u32 color;
|
||||
u32 ambient_intensity;
|
||||
u32 diffuse_intensity;
|
||||
|
||||
u32 position;
|
||||
u32 constant;
|
||||
u32 linear;
|
||||
u32 exponent;
|
||||
|
||||
u32 direction;
|
||||
u32 edge;
|
||||
} spot_lights[MAX_SPOT_LIGHTS];
|
||||
|
||||
~Shader();
|
||||
};
|
||||
|
||||
@ -52,6 +68,6 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f
|
||||
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);
|
||||
void use_light(Shader *shader, Spot_Light *light, u32 point_light_count);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user