Basic lighting

This commit is contained in:
MrLetsplay 2022-10-11 17:27:22 +02:00
parent b31d9129e2
commit c02d34227a
11 changed files with 189 additions and 66 deletions

View File

@ -152,7 +152,7 @@ int init() {
glfwSetInputMode(kekData.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(kekData.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glClearColor(0.1f, 0.3f, 0.1f, 0.0f); glClearColor(0.1f, 0.3f, 0.1f, 0.0f);
//glfwSwapInterval(0); // glfwSwapInterval(0);
stbi_set_flip_vertically_on_load(true); stbi_set_flip_vertically_on_load(true);
@ -217,6 +217,38 @@ int start() {
glUniformMatrix4fv(glGetUniformLocation(kekData.shader->id, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(kekData.shader->id, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniform3fv(glGetUniformLocation(kekData.shader->id, "cameraPos"), 1, glm::value_ptr(position)); glUniform3fv(glGetUniformLocation(kekData.shader->id, "cameraPos"), 1, glm::value_ptr(position));
LightList *lights = kekData.activeScene->lights;
std::vector<Light *> shaderLights;
for(PointLight *light : lights->point) {
if(glm::abs(light->getPosition() - kekData.activeCamera->getPosition()).length() < 10) {
shaderLights.push_back(light);
}
}
glUniform1i(glGetUniformLocation(kekData.shader->id, "numPointLights"), 1);
unsigned int i = 0;
for(Light *light : shaderLights) {
std::string prefix = "lights[" + std::to_string(i) + "].";
switch(light->getType()) {
case LightType::POINT:
{
PointLight *l = (PointLight *) light;
glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "position").c_str()), 1, glm::value_ptr(l->getPosition()));
glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "color").c_str()), 1, glm::value_ptr(l->color));
glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "attenuation").c_str()), 1, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic)));
}
case LightType::DIRECTIONAL:
case LightType::SPOT:
break;
}
i++;
}
if(kekData.activeScene) kekData.activeScene->draw(kekData.shader); if(kekData.activeScene) kekData.activeScene->draw(kekData.shader);
// Swap buffers and poll window events // Swap buffers and poll window events
@ -225,8 +257,8 @@ int start() {
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> secsTaken = end - start; std::chrono::duration<float> secsTaken = end - start;
//std::cout << "FT: " << secsTaken.count() * 1000 << std::endl; // std::cout << "FT: " << secsTaken.count() * 1000 << std::endl;
//std::cout << "FR: " << (1.0f / secsTaken.count()) << std::endl; // std::cout << "FR: " << (1.0f / secsTaken.count()) << std::endl;
} }
return KEK_SUCCESS; return KEK_SUCCESS;

View File

@ -0,0 +1,44 @@
#include <vector>
#include "light.h"
#include "constants.h"
namespace kek {
Light::Light(glm::vec3 color) {
this->color = color;
}
Light::~Light() {
}
PointLight::PointLight(glm::vec3 color, float constantFalloff, float linearFalloff, float quadraticFalloff): Light(color) {
this->constant = constantFalloff;
this->linear = linearFalloff;
this->quadratic = quadraticFalloff;
}
PointLight::~PointLight() {
}
LightType PointLight::getType() {
return LightType::POINT;
}
LightList::LightList() {
point = std::vector<PointLight *>();
//directional = std::vector<DirectionalLight *>();
//spot = std::vector<SpotLight *>();
}
void LightList::add(Light *light) {
switch(light->getType()) {
case LightType::POINT: point.push_back((PointLight *) light); break;
//case LightType::DIRECTIONAL: directional.push_back((DirectionalLight *) light); break;
//case LightType::SPOT: spot.push_back((SpotLight *) light); break;
}
}
}

View File

@ -24,30 +24,30 @@ Mesh::Mesh(std::vector<Vertex> vertices, std::vector<uint32_t> indices, Material
this->indices = indices; this->indices = indices;
this->material = material; this->material = material;
glGenVertexArrays(1, &vao); glCreateVertexArrays(1, &vao);
glGenBuffers(1, &vbo); glCreateBuffers(1, &vbo);
glGenBuffers(1, &ebo); glCreateBuffers(1, &ebo);
glBindVertexArray(vao); //glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo); glNamedBufferData(vbo, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); glNamedBufferData(ebo, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(Vertex));
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glVertexAttribPointer(KEK_VERTEX_SHADER_IN_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); glEnableVertexArrayAttrib(vao, KEK_VERTEX_SHADER_IN_POSITION);
glEnableVertexAttribArray(KEK_VERTEX_SHADER_IN_POSITION); glVertexArrayAttribFormat(vao, KEK_VERTEX_SHADER_IN_POSITION, sizeof(float), GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_POSITION, 0);
glVertexAttribPointer(KEK_VERTEX_SHADER_IN_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, normal)); glEnableVertexArrayAttrib(vao, KEK_VERTEX_SHADER_IN_NORMAL);
glEnableVertexAttribArray(KEK_VERTEX_SHADER_IN_NORMAL); glVertexArrayAttribFormat(vao, KEK_VERTEX_SHADER_IN_NORMAL, sizeof(float), GL_FLOAT, GL_FALSE, offsetof(Vertex, normal));
glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_NORMAL, 0);
glVertexAttribPointer(KEK_VERTEX_SHADER_IN_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, texCoords)); glEnableVertexArrayAttrib(vao, KEK_VERTEX_SHADER_IN_TEXCOORD);
glEnableVertexAttribArray(KEK_VERTEX_SHADER_IN_TEXCOORD); glVertexArrayAttribFormat(vao, KEK_VERTEX_SHADER_IN_TEXCOORD, sizeof(float), GL_FLOAT, GL_FALSE, offsetof(Vertex, texCoords));
glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_TEXCOORD, 0);
glBindVertexArray(0); glVertexArrayElementBuffer(vao, ebo);
GLenum err = glGetError(); GLenum err = glGetError();
if(err != GL_NO_ERROR) { if(err != GL_NO_ERROR) {

View File

@ -3,11 +3,13 @@
namespace kek { namespace kek {
Scene::Scene() { Scene::Scene() {
this->lights = new LightList();
} }
Scene::~Scene() { Scene::~Scene() {
for(GameObject *obj : objects) delete obj; for(GameObject *obj : objects) delete obj;
for(Light *l : lights->point) delete l;
delete lights;
} }
void Scene::addObject(GameObject *object) { void Scene::addObject(GameObject *object) {

View File

@ -9,3 +9,8 @@
#define KEK_CAMERA_NEAR 0.1f #define KEK_CAMERA_NEAR 0.1f
#define KEK_CAMERA_FAR 100.0f #define KEK_CAMERA_FAR 100.0f
#define KEK_LIGHT_LIMIT 8 // Also in shader/mesh/fragment.glsl
#define KEK_LIGHT_DEFAULT_AMBIENT_STRENGTH 0.05f
#define KEK_LIGHT_DEFAULT_SPECULAR_STRENGTH 0.1f

View File

@ -0,0 +1,55 @@
#pragma once
#include <glm/glm.hpp>
#include <vector>
#include "object.h"
namespace kek {
enum class LightType {
POINT,
DIRECTIONAL,
SPOT
};
class Light {
public:
glm::vec3 color;
Light(glm::vec3 color);
virtual ~Light();
virtual LightType getType() = 0;
};
class PointLight: public Light, public DefaultObject {
public:
float constant, linear, quadratic;
PointLight(glm::vec3 color, float constant, float linear, float quadratic);
~PointLight();
LightType getType();
};
class LightList {
public:
std::vector<PointLight *> point;
//std::vector<DirectionalLight *> directional;
//std::vector<SpotLight *> spot;
LightList();
void add(Light *light);
};
}

View File

@ -3,15 +3,16 @@
#include <vector> #include <vector>
#include "gameobject.h" #include "gameobject.h"
#include "light.h"
namespace kek { namespace kek {
class Scene { class Scene {
protected:
std::vector<GameObject *> objects;
public: public:
std::vector<GameObject *> objects;
LightList *lights;
Scene(); Scene();
~Scene(); ~Scene();

View File

@ -1,21 +1,21 @@
vec3 calcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir, vec2 texCoord, float shadow) { vec3 calcPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir, vec2 texCoord, float shadow) {
vec3 lightDir = normalize(light.position - fragPos); vec3 lightDir = normalize(light.position - fragPos);
vec3 halfwayDir = normalize(lightDir + viewDir); vec3 halfwayDir = normalize(lightDir + viewDir);
// Ambient // Ambient
vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord)); vec3 ambient = light.color * vec3(texture(material.ambient, texCoord));
// Diffuse // Diffuse
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, texCoord)); vec3 diffuse = light.color * diff * vec3(texture(material.diffuse, texCoord));
// Specular // Specular
float spec = pow(max(dot(normal, halfwayDir), 0.0), material.shininess); float spec = pow(max(dot(normal, halfwayDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * vec3(texture(material.specular, texCoord)); vec3 specular = light.color * spec * vec3(texture(material.specular, texCoord));
// Attenuation // Attenuation
float dist = length(light.position - fragPos); float dist = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * dist + light.quadratic * (dist * dist)); float attenuation = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * (dist * dist));
ambient *= attenuation; ambient *= attenuation;
diffuse *= attenuation; diffuse *= attenuation;

View File

@ -5,41 +5,11 @@ struct Material {
float shininess; float shininess;
}; };
struct PointLight { struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct DirectionalLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
mat4 lightSpaceMatrix;
};
struct SpotLight {
vec3 position; vec3 position;
vec3 direction; vec3 direction;
float innerCutOff; vec3 color;
float outerCutOff; vec3 attenuation;
vec2 cutoff;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
mat4 lightSpaceMatrix; mat4 lightSpaceMatrix;
}; };

View File

@ -8,21 +8,32 @@ in VS_OUT {
!include types.glsl !include types.glsl
uniform Light lights[8];
uniform int numPointLights;
uniform Material material; uniform Material material;
uniform vec3 cameraPos; uniform vec3 cameraPos;
out vec4 color; out vec4 color;
const float gamma = 2.2;
!include lightcalc.glsl !include lightcalc.glsl
void main() { void main() {
vec3 norm = normalize(fs_in.normal); vec3 normal = normalize(fs_in.normal);
vec3 viewDir = normalize(cameraPos - fs_in.fragmentPosition); vec3 viewDir = normalize(cameraPos - fs_in.fragmentPosition);
//color = length(fs_in.fragmentPosition) / 2 * vec4(1.0); //color = length(fs_in.fragmentPosition) / 2 * vec4(1.0);
//color = vec4(norm, 1.0); //color = vec4(norm, 1.0);
color = texture(material.diffuse, fs_in.textureCoordinate); color = texture(material.diffuse, fs_in.textureCoordinate);
//PointLight light = {}; vec3 result = vec3(0.0);
for(int i = 0; i < numPointLights; i++) {
result += calcPointLight(lights[i], normal, fs_in.fragmentPosition, viewDir, fs_in.textureCoordinate, 0.0);
}
color = vec4(pow(result, vec3(1.0 / gamma)), 1.0);
} }

View File

@ -19,13 +19,16 @@ int main(int argc, char **argv) {
Scene *scene = new Scene(); Scene *scene = new Scene();
scene->addObject(test); scene->addObject(test);
for(int i = 0; i < 1; i++) { for(int i = 0; i < 10; i++) {
GameObject *test2 = new GameObject(); GameObject *test2 = new GameObject();
test2->addMesh(ObjParser::loadMesh("object/cube_colored/Cube.obj")); test2->addMesh(ObjParser::loadMesh("object/cube_colored/Cube.obj"));
test2->moveTo(glm::vec3(0.0f, 5.0f, 3 * i)); test2->moveTo(glm::vec3(0.0f, 5.0f, 3 * i));
scene->addObject(test2); scene->addObject(test2);
} }
PointLight *light = new PointLight(glm::vec3(1), 1, 1, 1);
scene->lights->add(light);
Engine::setActiveScene(scene); Engine::setActiveScene(scene);
Engine::start(); Engine::start();