Commit cb5fd0f7 authored by Sadman Kazi's avatar Sadman Kazi 🎸

Add ambient and directional light

parent 444e7f1e
Pipeline #161 passed with stage
in 3 minutes and 30 seconds
......@@ -12,7 +12,7 @@ void main () {
vec4 totalLight = vec4(u_ambientLight, 1);
vec4 textureColor = texture2D(u_diffuse, texCoord0.xy) * clamp(dot(-vec3(1,1,1), normal0), 0.2, 1.0);
if (textureColor == vec4(0))
if (textureColor == vec4(0,0,0,0))
fragColor = vec4(u_color, 1);
else
fragColor = textureColor * vec4(u_color, 1);
......
#version 330
in vec2 texCoord0;
in vec3 normal0;
out vec4 frag_color;
struct BaseLight {
vec3 color;
float intensity;
};
struct DirectionalLight {
BaseLight base;
vec3 direction;
};
uniform vec3 u_base_color;
uniform vec3 u_ambient_light;
uniform sampler2D u_sampler;
uniform DirectionalLight u_dir_light;
vec4 calcLight(BaseLight base, vec3 dir, vec3 normal) {
//calculate attentuation
float diffuseFactor = dot(normal, -dir);
vec4 diffuseColor = vec4(0, 0, 0, 0);
if (diffuseFactor > 0) {
diffuseColor = vec4(base.color, 1.0) * base.intensity * diffuseFactor;
}
return diffuseColor;
}
vec4 calcDirectionalLight(DirectionalLight dir_light, vec3 normal) {
return calcLight(dir_light.base, -dir_light.direction, normal);
}
void main() {
vec4 total_light = vec4(u_ambient_light, 1);
vec4 color = vec4(u_base_color, 1);
vec4 texture_color = texture(u_sampler, texCoord0.xy);
if (texture_color != vec4(0, 0, 0, 0)) {
color *= texture_color;
}
vec3 normal = normalize(normal0);
total_light += calcDirectionalLight(u_dir_light, normal);
frag_color = color * total_light;
}
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 normal;
out vec2 texCoord0;
out vec3 normal0;
uniform mat4 u_transform;
uniform mat4 u_proj_transform;
void main () {
gl_Position = u_proj_transform * vec4(position, 1.0);
texCoord0 = texCoord;
normal0 = (u_transform * vec4(normal, 0.0)).xyz;
}
......@@ -14,7 +14,8 @@ BasicShader::BasicShader() :
addUniform("u_color");
}
void BasicShader::updateUniforms(const glm::mat4& proj_matrix,
void BasicShader::updateUniforms(const glm::mat4& world_matrix,
const glm::mat4& proj_matrix,
const Material* material) {
if (material->getTexture()) {
......
......@@ -6,7 +6,8 @@
class BasicShader : public Shader {
public:
static BasicShader* getInstance();
virtual void updateUniforms(const glm::mat4& proj_matrix,
virtual void updateUniforms(const glm::mat4& world_matrix,
const glm::mat4& proj_matrix,
const Material* material);
private:
......
#ifndef DIRECTIONAL_LIGHT_H_
#define DIRECTIONAL_LIGHT_H_
#include <glm/glm.hpp>
#include <iostream>
struct BaseLight {
glm::vec3 color;
float intensity;
BaseLight(const glm::vec3& c, float i) :
color(c), intensity(i) { }
};
struct DirectionalLight {
BaseLight base;
glm::vec3 dir;
inline DirectionalLight(const BaseLight& b, const glm::vec3& d) :
base(b), dir(glm::normalize(d)) {}
};
#endif // DIRECTIONAL_LIGHT_H_
......@@ -17,7 +17,7 @@
#include "input.h"
#include <iostream>
#include "time.h"
#include "basic_shader.h"
#include "phong_shader.h"
Game::Game()
{
......@@ -31,7 +31,7 @@ Game::Game()
2, 1, 0,
0, 2, 3};
m_shader = BasicShader::getInstance();
m_shader = PhongShader::getInstance();
//m_mesh = new Mesh(data, sizeof(data)/sizeof(data[0]), indices, sizeof(indices)/sizeof(indices[0]));
......@@ -43,8 +43,6 @@ Game::Game()
m_camera = new Camera(glm::vec3(0.0f, 0.0f, -2.0f), 70.0f, (float)WIDTH/HEIGHT, 1.0f, 100.0f);
m_transform->setScale(glm::vec3(0.5f, 0.5f, 0.5f));
//m_shader->addUniform("u_ambientLight");
//m_shader->setUniformVec3("u_ambientLight", glm::vec3(1,1,1));
m_counter = 0;
}
......@@ -87,10 +85,11 @@ void Game::update() {
float absSinCounter = abs(sinCounter);
//transform->GetPos().x = sinCounter;
//m_transform->getRot().y = sinCounter;
m_transform->setPos(glm::vec3(0,0,5));
m_transform->getRot().y = sinCounter;
//transform->GetRot().z = sinCounter;
m_shader->updateUniforms(m_transform->getProjectedModel(m_camera), m_material);
m_shader->updateUniforms(m_transform->getModel(), m_transform->getProjectedModel(m_camera), m_material);
}
void Game::loadMesh(const std::string& model_path) {
......
#include "mesh.h"
#include <vector>
Mesh::Mesh(const std::string& fileName) {
IndexedModel model = OBJModel(fileName).ToIndexedModel();
InitMesh(model);
}
Mesh::Mesh(Vertex* vertices, unsigned int numVertices, unsigned int* indices, unsigned int numIndices)
{
m_drawCount = numVertices; //binding the vertex array object
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
// retrieve the data from the vertices
std::vector<glm::vec3*> posCoords;
std::vector<glm::vec2*> texCoords;
std::vector<glm::vec3*> normals;
posCoords.reserve(numVertices);
texCoords.reserve(numVertices);
normals.reserve(numVertices);
for (unsigned int i = 0; i < numVertices; i++) {
posCoords.push_back(vertices[i].getPos());
texCoords.push_back(vertices[i].getTexCoord());
normals.push_back(vertices[i].getNormal());
}
//writing it to the GPU using buffers
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(posCoords[0]), &posCoords[0], GL_STATIC_DRAW);
//assigning the data a location in the GPU memory
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers[INDEX_VB]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(indices[0]), indices, GL_STATIC_DRAW);
/*
//glEnableVertexAttribArray(1);
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(1); //unbind the ARRAY from the GL handler
*/
glBindVertexArray(0);
//writing it to the GPU using buffers
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
//assigning the data a location in the GPU memory
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(1);
}
void Mesh::draw() {
glBindVertexArray(m_vertexArrayObject);
//glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glDrawElements(GL_TRIANGLES, m_drawCount, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
void Mesh::InitMesh(const IndexedModel& model) {
m_drawCount = model.positions.size();
//binding the vertex array object
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
//writing it to the GPU using buffers
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, model.positions.size() * sizeof(model.positions[0]), &model.positions[0], GL_STATIC_DRAW);
//need a vertex attribute for every vertex member, tells where in the sequence to look at in the GPU memory
glEnableVertexAttribArray(0); //look at it as an array
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
//for the texture coordinates
//get some buffers to work with
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
//interprete the data as an array and bind it
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
//take data and put it in the buffer, from program to GPU memory
glBufferData(GL_ARRAY_BUFFER, model.positions.size() * sizeof(model.texCoords[0]), &model.texCoords[0], GL_STATIC_DRAW); //static draw means that the data is not gonna change
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[NORMAL_VB]);
//take data and put it in the buffer, from program to GPU memory
glBufferData(GL_ARRAY_BUFFER, model.normals.size() * sizeof(model.normals[0]), &model.normals[0], GL_STATIC_DRAW); //static draw means that the data is not gonna change
//need a vertex attribute for every vertex member, tells where in the sequence to look at in the GPU memory
glEnableVertexAttribArray(2); //look at it as an array
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
//get some buffers to work with
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
//interprete the data as an array and bind it
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers[INDEX_VB]);
//take data and put it in the buffer, from program to GPU memory
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model.indices.size() * sizeof(model.indices[0]), &model.indices[0], GL_STATIC_DRAW); //static draw means that the data is not gonna change
glBindVertexArray(0);
}
#include "mesh.h"
#include <vector>
Mesh::Mesh(const std::string& fileName) {
IndexedModel model = OBJModel(fileName).ToIndexedModel();
InitMesh(model);
}
Mesh::Mesh(Vertex* vertices, unsigned int numVertices, unsigned int* indices, unsigned int numIndices)
{
m_drawCount = numVertices; //binding the vertex array object
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
// retrieve the data from the vertices
std::vector<glm::vec3*> posCoords;
std::vector<glm::vec2*> texCoords;
std::vector<glm::vec3*> normals;
posCoords.reserve(numVertices);
texCoords.reserve(numVertices);
normals.reserve(numVertices);
for (unsigned int i = 0; i < numVertices; i++) {
posCoords.push_back(vertices[i].getPos());
texCoords.push_back(vertices[i].getTexCoord());
normals.push_back(vertices[i].getNormal());
}
//writing it to the GPU using buffers
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(posCoords[0]), &posCoords[0], GL_STATIC_DRAW);
//assigning the data a location in the GPU memory
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers[INDEX_VB]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(indices[0]), indices, GL_STATIC_DRAW);
/*
//glEnableVertexAttribArray(1);
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(1); //unbind the ARRAY from the GL handler
*/
glBindVertexArray(0);
//writing it to the GPU using buffers
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
//assigning the data a location in the GPU memory
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(1);
}
void Mesh::draw() {
glBindVertexArray(m_vertexArrayObject);
//glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glDrawElements(GL_TRIANGLES, m_drawCount, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
void Mesh::InitMesh(const IndexedModel& model) {
m_drawCount = model.positions.size();
//binding the vertex array object
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
//writing it to the GPU using buffers
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, model.positions.size() * sizeof(model.positions[0]), &model.positions[0], GL_STATIC_DRAW);
//need a vertex attribute for every vertex member, tells where in the sequence to look at in the GPU memory
glEnableVertexAttribArray(0); //look at it as an array
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
//for the texture coordinates
//get some buffers to work with
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
//interprete the data as an array and bind it
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
//take data and put it in the buffer, from program to GPU memory
glBufferData(GL_ARRAY_BUFFER, model.positions.size() * sizeof(model.texCoords[0]), &model.texCoords[0], GL_STATIC_DRAW); //static draw means that the data is not gonna change
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[NORMAL_VB]);
//take data and put it in the buffer, from program to GPU memory
glBufferData(GL_ARRAY_BUFFER, model.normals.size() * sizeof(model.normals[0]), &model.normals[0], GL_STATIC_DRAW); //static draw means that the data is not gonna change
//need a vertex attribute for every vertex member, tells where in the sequence to look at in the GPU memory
glEnableVertexAttribArray(2); //look at it as an array
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
//get some buffers to work with
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
//interprete the data as an array and bind it
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers[INDEX_VB]);
//take data and put it in the buffer, from program to GPU memory
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model.indices.size() * sizeof(model.indices[0]), &model.indices[0], GL_STATIC_DRAW); //static draw means that the data is not gonna change
glBindVertexArray(0);
}
#include "phong_shader.h"
const std::string PhongShader::PHONG_SHADER_FILE = "../res/phongShader";
glm::vec3 PhongShader::m_ambient_light = glm::vec3(0.1f, 0.1f, 0.1f);
DirectionalLight PhongShader::m_dir_light = DirectionalLight(
BaseLight(glm::vec3(1,1,1), 0.8f),
glm::vec3(1,1,1));
PhongShader* PhongShader::getInstance() {
static PhongShader instance;
return &instance;
}
PhongShader::PhongShader() :
Shader(PHONG_SHADER_FILE) {
addUniform("u_transform");
addUniform("u_proj_transform");
addUniform("u_base_color");
addUniform("u_ambient_light");
addUniform("u_dir_light.base.color");
addUniform("u_dir_light.base.intensity");
addUniform("u_dir_light.direction");
}
void PhongShader::updateUniforms(const glm::mat4& world_matrix,
const glm::mat4& proj_matrix,
const Material* material) {
if (material->getTexture()) {
material->bindTexture();
} else {
Texture::unbindAll();
}
setUniformMat4("u_transform", world_matrix);
setUniformMat4("u_proj_transform", proj_matrix);
setUniformVec3("u_base_color", *material->getColor());
setUniformVec3("u_ambient_light", PhongShader::m_ambient_light);
setUniformDirectionalLight("u_dir_light", PhongShader::m_dir_light);
}
void PhongShader::setAmbientLight(const glm::vec3& amb_light) {
PhongShader::m_ambient_light = amb_light;
}
void PhongShader::setDirectionalLight(const DirectionalLight& dir_light) {
PhongShader::m_dir_light = dir_light;
}
void PhongShader::setUniformBaseLight(const std::string& name, const BaseLight& base) {
setUniformVec3(name + ".color", base.color);
setUniformI(name + ".intensity", base.intensity);
}
void PhongShader::setUniformDirectionalLight(const std::string& name, const DirectionalLight& dir_light) {
setUniformBaseLight(name + ".base", dir_light.base);
setUniformVec3(name + ".direction", dir_light.dir);
}
#ifndef PHONG_SHADER_H_
#define PHONG_SHADER_H_
#include "shader.h"
#include "directional_light.h"
class PhongShader : public Shader {
public:
static PhongShader* getInstance();
virtual void updateUniforms(const glm::mat4&, const glm::mat4&, const Material*);
void setUniformBaseLight(const std::string&, const BaseLight&);
void setUniformDirectionalLight(const std::string&, const DirectionalLight&);
static void setAmbientLight(const glm::vec3&);
static void setDirectionalLight(const DirectionalLight&);
private:
PhongShader();
static const std::string PHONG_SHADER_FILE;
static glm::vec3 m_ambient_light;
static DirectionalLight m_dir_light;
};
#endif // PHONG_SHADER_H_
......@@ -20,7 +20,7 @@ public:
void setUniformF(const std::string& name, float value);
void setUniformVec3(const std::string& name, const glm::vec3& value);
void setUniformMat4(const std::string& name, const glm::mat4& value);
virtual void updateUniforms(const glm::mat4&, const Material*) = 0;
virtual void updateUniforms(const glm::mat4&, const glm::mat4&, const Material*) = 0;
virtual ~Shader();
private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment