more lighting

This commit is contained in:
hippoz 2023-08-21 17:43:31 +03:00
parent 28c4f16d71
commit 954075bd4f
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
9 changed files with 171 additions and 27 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
builddir/ builddir/
.cache/

BIN
assets/container2.qoi Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -31,11 +31,27 @@ struct DirectionalLight {
vec3 specular; vec3 specular;
}; };
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
#define POINT_LIGHTS_COUNT 4 #define POINT_LIGHTS_COUNT 4
uniform Material material; uniform Material material;
uniform vec3 viewPos; uniform vec3 viewPos;
uniform SpotLight spotLight;
uniform DirectionalLight directionalLight; uniform DirectionalLight directionalLight;
uniform PointLight pointLights[POINT_LIGHTS_COUNT]; uniform PointLight pointLights[POINT_LIGHTS_COUNT];
@ -55,12 +71,12 @@ vec3 ComputeDirectionalLight(DirectionalLight light, vec3 norm, vec3 viewDir)
return (ambient + diffuse + specular); return (ambient + diffuse + specular);
} }
vec3 ComputePointLight(PointLight light, vec3 norm, vec3 viewDir) vec3 ComputePointLight(PointLight light, vec3 norm, vec3 viewDir, vec3 fragPos)
{ {
float distance = length(light.position - FragPos); float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 lightDir = normalize(light.position - FragPos); vec3 lightDir = normalize(light.position - fragPos);
vec3 reflectDir = reflect(-lightDir, norm); vec3 reflectDir = reflect(-lightDir, norm);
float diff = max(dot(norm, lightDir), 0.0); float diff = max(dot(norm, lightDir), 0.0);
@ -73,16 +89,40 @@ vec3 ComputePointLight(PointLight light, vec3 norm, vec3 viewDir)
return (ambient * attenuation + diffuse * attenuation + specular * attenuation); return (ambient * attenuation + diffuse * attenuation + specular * attenuation);
} }
vec3 ComputeSpotLight(SpotLight light, vec3 norm, vec3 viewDir, vec3 fragPos) {
vec3 lightDir = normalize(light.position - fragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
float diff = max(dot(norm, lightDir), 0.0);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
// we leave ambient alone so there's always a little light
return ((ambient * attenuation) + (diffuse * intensity * attenuation) + (specular * intensity * attenuation));
}
void main() void main()
{ {
vec3 norm = normalize(Normal); vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos);
vec3 result = vec3(0.0); vec3 result = vec3(0.0);
result += ComputeDirectionalLight(directionalLight, norm, viewDir); result += ComputeDirectionalLight(directionalLight, norm, viewDir);
for (int i = 0; i < POINT_LIGHTS_COUNT; i++) { for (int i = 0; i < POINT_LIGHTS_COUNT; i++) {
result += ComputePointLight(pointLights[i], norm, viewDir); result += ComputePointLight(pointLights[i], norm, viewDir, FragPos);
} }
result += ComputeSpotLight(spotLight, norm, viewDir, FragPos);
FragColor = vec4(result, 1.0); FragColor = vec4(result, 1.0);
} }

View file

@ -24,10 +24,10 @@ std::function<void(double x, double y)> cursor_position_callback = nullptr;
int main() int main()
{ {
qoi_desc fish_desc; qoi_desc fish_desc;
void *fish_rgba = qoi_read("assets/fish.qoi", &fish_desc, 4); void *fish_rgba = qoi_read("assets/container2.qoi", &fish_desc, 4);
qoi_desc fish_map_desc; qoi_desc fish_map_desc;
void *fish_map_rgba = qoi_read("assets/fish-map.qoi", &fish_map_desc, 4); void *fish_map_rgba = qoi_read("assets/container2_specular.qoi", &fish_map_desc, 4);
if (!glfwInit()) { if (!glfwInit()) {
@ -107,6 +107,27 @@ int main()
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
}; };
// positions all containers
glm::vec3 cube_positions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
// positions of the point lights
glm::vec3 point_light_positions[] = {
glm::vec3( 0.7f, 0.2f, 2.0f),
glm::vec3( 2.3f, -3.3f, -4.0f),
glm::vec3(-4.0f, 2.0f, -12.0f),
glm::vec3( 0.0f, 0.0f, -3.0f)
};
unsigned int fish_texture; unsigned int fish_texture;
glGenTextures(1, &fish_texture); glGenTextures(1, &fish_texture);
glBindTexture(GL_TEXTURE_2D, fish_texture); glBindTexture(GL_TEXTURE_2D, fish_texture);
@ -131,6 +152,8 @@ int main()
glGenVertexArrays(1, &object_vao); glGenVertexArrays(1, &object_vao);
glBindVertexArray(object_vao); glBindVertexArray(object_vao);
glBindBuffer(GL_ARRAY_BUFFER, cube_buffer);
// position // position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
@ -145,6 +168,8 @@ int main()
glGenVertexArrays(1, &light_source_vao); glGenVertexArrays(1, &light_source_vao);
glBindVertexArray(light_source_vao); glBindVertexArray(light_source_vao);
glBindBuffer(GL_ARRAY_BUFFER, cube_buffer);
// position // position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
@ -165,8 +190,6 @@ int main()
float delta_time = 0.0f; float delta_time = 0.0f;
float last_frame_time = 0.0f; float last_frame_time = 0.0f;
glm::vec3 light_position(1.2f, 1.0f, 2.0f);
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
float current_frame_time = glfwGetTime(); float current_frame_time = glfwGetTime();
delta_time = current_frame_time - last_frame_time; delta_time = current_frame_time - last_frame_time;
@ -195,7 +218,7 @@ int main()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
{ {
/* lit object */ /* lit objects */
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fish_texture); glBindTexture(GL_TEXTURE_2D, fish_texture);
@ -203,33 +226,81 @@ int main()
glBindTexture(GL_TEXTURE_2D, fish_map_texture); glBindTexture(GL_TEXTURE_2D, fish_map_texture);
glUseProgram(lighting_program); glUseProgram(lighting_program);
glBindVertexArray(object_vao); glBindVertexArray(object_vao);
glUniformMatrix4fv(glGetUniformLocation(lighting_program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(lighting_program, "view"), 1, GL_FALSE, glm::value_ptr(camera.view));
glUniformMatrix4fv(glGetUniformLocation(lighting_program, "model"), 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
glUniform3fv(glGetUniformLocation(lighting_program, "viewPos"), 1, glm::value_ptr(camera.position));
glUniform1i(glGetUniformLocation(lighting_program, "material.diffuse"), 0); program_set(lighting_program, "projection", projection);
glUniform1i(glGetUniformLocation(lighting_program, "material.specular"), 1); program_set(lighting_program, "view", camera.view);
glUniform1f(glGetUniformLocation(lighting_program, "material.shininess"), 32.0f); program_set(lighting_program, "viewPos", camera.position);
glUniform3fv(glGetUniformLocation(lighting_program, "light.position"), 1, glm::value_ptr(light_position)); program_set(lighting_program, "material.shininess", 32.0f);
glUniform3f(glGetUniformLocation(lighting_program, "light.ambient"), 0.2f, 0.2f, 0.2f);
glUniform3f(glGetUniformLocation(lighting_program, "light.diffuse"), 0.5f, 0.5f, 0.5f); program_set(lighting_program, "directionalLight.direction", -0.2f, -1.0f, -0.3f);
glUniform3f(glGetUniformLocation(lighting_program, "light.specular"), 1.0f, 1.0f, 1.0f); program_set(lighting_program, "directionalLight.ambient", 0.05f, 0.05f, 0.05f);
glDrawArrays(GL_TRIANGLES, 0, 36); program_set(lighting_program, "directionalLight.diffuse", 0.4f, 0.4f, 0.4f);
program_set(lighting_program, "directionalLight.specular", 0.5f, 0.5f, 0.5f);
// point light 1
program_set(lighting_program, "pointLights[0].position", point_light_positions[0]);
program_set(lighting_program, "pointLights[0].ambient", 0.05f, 0.05f, 0.05f);
program_set(lighting_program, "pointLights[0].diffuse", 0.8f, 0.8f, 0.8f);
program_set(lighting_program, "pointLights[0].specular", 1.0f, 1.0f, 1.0f);
program_set(lighting_program, "pointLights[0].constant", 1.0f);
program_set(lighting_program, "pointLights[0].linear", 0.09f);
program_set(lighting_program, "pointLights[0].quadratic", 0.032f);
// point light 2
program_set(lighting_program, "pointLights[1].position", point_light_positions[1]);
program_set(lighting_program, "pointLights[1].ambient", 0.05f, 0.05f, 0.05f);
program_set(lighting_program, "pointLights[1].diffuse", 0.8f, 0.8f, 0.8f);
program_set(lighting_program, "pointLights[1].specular", 1.0f, 1.0f, 1.0f);
program_set(lighting_program, "pointLights[1].constant", 1.0f);
program_set(lighting_program, "pointLights[1].linear", 0.09f);
program_set(lighting_program, "pointLights[1].quadratic", 0.032f);
// point light 3
program_set(lighting_program, "pointLights[2].position", point_light_positions[2]);
program_set(lighting_program, "pointLights[2].ambient", 0.05f, 0.05f, 0.05f);
program_set(lighting_program, "pointLights[2].diffuse", 0.8f, 0.8f, 0.8f);
program_set(lighting_program, "pointLights[2].specular", 1.0f, 1.0f, 1.0f);
program_set(lighting_program, "pointLights[2].constant", 1.0f);
program_set(lighting_program, "pointLights[2].linear", 0.09f);
program_set(lighting_program, "pointLights[2].quadratic", 0.032f);
// point light 4
program_set(lighting_program, "pointLights[3].position", point_light_positions[3]);
program_set(lighting_program, "pointLights[3].ambient", 0.05f, 0.05f, 0.05f);
program_set(lighting_program, "pointLights[3].diffuse", 0.8f, 0.8f, 0.8f);
program_set(lighting_program, "pointLights[3].specular", 1.0f, 1.0f, 1.0f);
program_set(lighting_program, "pointLights[3].constant", 1.0f);
program_set(lighting_program, "pointLights[3].linear", 0.09f);
program_set(lighting_program, "pointLights[3].quadratic", 0.032f);
// spot light
program_set(lighting_program, "spotLight.position", camera.position);
program_set(lighting_program, "spotLight.direction", camera.front);
program_set(lighting_program, "spotLight.ambient", 0.0f, 0.0f, 0.0f);
program_set(lighting_program, "spotLight.diffuse", 1.0f, 1.0f, 1.0f);
program_set(lighting_program, "spotLight.specular", 1.0f, 1.0f, 1.0f);
program_set(lighting_program, "spotLight.constant", 1.0f);
program_set(lighting_program, "spotLight.linear", 0.09f);
program_set(lighting_program, "spotLight.quadratic", 0.032f);
program_set(lighting_program, "spotLight.cutOff", glm::cos(glm::radians(12.5f)));
program_set(lighting_program, "spotLight.outerCutOff", glm::cos(glm::radians(15.0f)));
for (int i = 0; i < 10; i++) {
program_set(lighting_program, "model", glm::rotate(glm::translate(glm::mat4(1.0f), cube_positions[i]), glm::radians(20.0f * i), glm::vec3(1.0f, 0.3f, 0.5f)));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
} }
/* lamp object */ /* lamp object */
{ {
glUseProgram(light_cube_program); glUseProgram(light_cube_program);
glBindVertexArray(light_source_vao); glBindVertexArray(light_source_vao);
glUniformMatrix4fv(glGetUniformLocation(light_cube_program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(light_cube_program, "view"), 1, GL_FALSE, glm::value_ptr(camera.view));
glUniformMatrix4fv(glGetUniformLocation(light_cube_program, "model"), 1, GL_FALSE, glm::value_ptr(glm::scale(glm::translate(glm::mat4(1.0f), light_position), glm::vec3(0.2f))));
glDrawArrays(GL_TRIANGLES, 0, 36);
program_set(light_cube_program, "view", camera.view);
program_set(light_cube_program, "projection", projection);
for (int i = 0; i < 4; i++) {
program_set(light_cube_program, "model", glm::scale(glm::translate(glm::mat4(1.0f), point_light_positions[i]), glm::vec3(0.2f)));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
} }
} }

View file

@ -103,3 +103,28 @@ done:
if (fragment_shader_source) free(fragment_shader_source); if (fragment_shader_source) free(fragment_shader_source);
return ret; return ret;
} }
void program_set(unsigned int program, const char *uniform, int value)
{
glUniform1i(glGetUniformLocation(program, uniform), value);
}
void program_set(unsigned int program, const char *uniform, float value)
{
glUniform1f(glGetUniformLocation(program, uniform), value);
}
void program_set(unsigned int program, const char *uniform, glm::vec3 vec)
{
glUniform3fv(glGetUniformLocation(program, uniform), 1, &vec[0]);
}
void program_set(unsigned int program, const char *uniform, float x, float y, float z)
{
glUniform3f(glGetUniformLocation(program, uniform), x, y, z);
}
void program_set(unsigned int program, const char *uniform, const glm::mat4 &mat)
{
glUniformMatrix4fv(glGetUniformLocation(program, uniform), 1, GL_FALSE, &mat[0][0]);
}

View file

@ -1,4 +1,11 @@
#pragma once #pragma once
#include "vendor/glm/glm/mat4x4.hpp"
#include "vendor/glm/glm/vec3.hpp"
unsigned int create_program(const char *vertex_shader_path, const char *fragment_shader_path); unsigned int create_program(const char *vertex_shader_path, const char *fragment_shader_path);
void program_set(unsigned int program, const char *uniform, int value);
void program_set(unsigned int program, const char *uniform, float value);
void program_set(unsigned int program, const char *uniform, glm::vec3 vec);
void program_set(unsigned int program, const char *uniform, float x, float y, float z);
void program_set(unsigned int program, const char *uniform, const glm::mat4 &mat);