Add point lights
This commit is contained in:
parent
c80696320b
commit
135b075aa1
@ -74,8 +74,6 @@ Light *Light::Create() {
|
|||||||
|
|
||||||
Name Light::GetType() const {return "Light";}
|
Name Light::GetType() const {return "Light";}
|
||||||
|
|
||||||
Name DirectionalLight::GetType() const {return "DirectionalLight";}
|
|
||||||
|
|
||||||
DirectionalLight::DirectionalLight() {
|
DirectionalLight::DirectionalLight() {
|
||||||
this->direction = Vector3(0.0f);
|
this->direction = Vector3(0.0f);
|
||||||
this->color = Vector3(0.0f);
|
this->color = Vector3(0.0f);
|
||||||
@ -114,3 +112,46 @@ DirectionalLight *DirectionalLight::Duplicate() {
|
|||||||
DirectionalLight *DirectionalLight::Instance() {
|
DirectionalLight *DirectionalLight::Instance() {
|
||||||
return static_cast<DirectionalLight*>(Node::Instance());
|
return static_cast<DirectionalLight*>(Node::Instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Name DirectionalLight::GetType() const {return "DirectionalLight";}
|
||||||
|
|
||||||
|
PointLight::PointLight() {
|
||||||
|
this->radius = 0.0f;
|
||||||
|
this->color = Vector3(0.0f);
|
||||||
|
this->ambient = 0.0f;
|
||||||
|
this->diffuse = 0.0f;
|
||||||
|
this->specular = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointLight::PointLight(float radius, Vector3 color, float ambient, float diffuse, float specular) {
|
||||||
|
this->radius = radius;
|
||||||
|
this->color = color;
|
||||||
|
this->ambient = ambient;
|
||||||
|
this->diffuse = diffuse;
|
||||||
|
this->specular = specular;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PointLight::GetRadius() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointLight::SetRadius(float radius) {
|
||||||
|
this->radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointLight *PointLight::Create() {
|
||||||
|
return new PointLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointLight *PointLight::Duplicate() {
|
||||||
|
PointLight *pointLight = static_cast<PointLight*>(Light::Duplicate());
|
||||||
|
pointLight->radius = radius;
|
||||||
|
|
||||||
|
return pointLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointLight *PointLight::Instance() {
|
||||||
|
return static_cast<PointLight*>(Node::Instance());
|
||||||
|
}
|
||||||
|
|
||||||
|
Name PointLight::GetType() const {return "PointLight";}
|
||||||
|
31
core/Light.h
31
core/Light.h
@ -24,6 +24,8 @@
|
|||||||
#ifndef LIGHT_H
|
#ifndef LIGHT_H
|
||||||
#define LIGHT_H
|
#define LIGHT_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Spatial.h"
|
#include "Spatial.h"
|
||||||
|
|
||||||
@ -117,4 +119,33 @@ private:
|
|||||||
Vector3 direction;
|
Vector3 direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Point lights are omnidirectional lights that have a limited range.
|
||||||
|
*/
|
||||||
|
class PointLight : public Light {
|
||||||
|
public:
|
||||||
|
PointLight();
|
||||||
|
PointLight(float radius, Vector3 color, float ambient, float diffuse, float specular);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The radius of which the light will shine.
|
||||||
|
@returns The light radius.
|
||||||
|
*/
|
||||||
|
float GetRadius();
|
||||||
|
/**
|
||||||
|
Sets the light radius.
|
||||||
|
@param radius The desired radius
|
||||||
|
*/
|
||||||
|
void SetRadius(float radius);
|
||||||
|
|
||||||
|
virtual Name GetType() const;
|
||||||
|
virtual PointLight *Create();
|
||||||
|
virtual PointLight *Duplicate();
|
||||||
|
virtual PointLight *Instance();
|
||||||
|
private:
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<PointLight*> PointLightList;
|
||||||
|
|
||||||
#endif /* LIGHT_H */
|
#endif /* LIGHT_H */
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
Shader::Shader(const char* vertexCode, const char* fragmentCode) {
|
Shader::Shader(const char* vertexCode, const char* fragmentCode) {
|
||||||
Id vertex, fragment;
|
Id vertex, fragment;
|
||||||
int success;
|
int success;
|
||||||
@ -82,6 +84,16 @@ void Shader::UpdateDirectionalLight(DirectionalLight directionalLight) {
|
|||||||
glUniform1f(glGetUniformLocation(id, "directionalLight.specular"), directionalLight.GetSpecular());
|
glUniform1f(glGetUniformLocation(id, "directionalLight.specular"), directionalLight.GetSpecular());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::UpdatePointLights(PointLightList pointLights) {
|
||||||
|
for (int i = 0; i < pointLights.size() and i < NUM_POINT_LIGHTS; i++) {
|
||||||
|
glUniform3fv(glGetUniformLocation(id, Util::ShaderArrayName("pointLights", i, "pos").c_str()), 1, glm::value_ptr(pointLights[i]->GetTransform().position));
|
||||||
|
glUniform3fv(glGetUniformLocation(id, Util::ShaderArrayName("pointLights", i, "color").c_str()), 1, glm::value_ptr(pointLights[i]->GetColor()));
|
||||||
|
|
||||||
|
glUniform1f(glGetUniformLocation(id, Util::ShaderArrayName("pointLights", i, "radius").c_str()), pointLights[i]->GetRadius());
|
||||||
|
glUniform1f(glGetUniformLocation(id, Util::ShaderArrayName("pointLights", i, "ambient").c_str()), pointLights[i]->GetAmbient());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Name Shader::GetName() const {
|
Name Shader::GetName() const {
|
||||||
return "Unnamed Shader";
|
return "Unnamed Shader";
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "../Material.h"
|
#include "../Material.h"
|
||||||
#include "../Light.h"
|
#include "../Light.h"
|
||||||
|
|
||||||
|
#define NUM_POINT_LIGHTS 4
|
||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
public:
|
public:
|
||||||
Id id;
|
Id id;
|
||||||
@ -21,6 +23,7 @@ public:
|
|||||||
void UpdateMaterial(Material material);
|
void UpdateMaterial(Material material);
|
||||||
|
|
||||||
void UpdateDirectionalLight(DirectionalLight directionalLight);
|
void UpdateDirectionalLight(DirectionalLight directionalLight);
|
||||||
|
void UpdatePointLights(PointLightList pointLights);
|
||||||
|
|
||||||
virtual Name GetName() const;
|
virtual Name GetName() const;
|
||||||
};
|
};
|
||||||
|
@ -14,3 +14,9 @@ void Util::Die(std::string msg) {
|
|||||||
std::cerr << msg << std::endl;
|
std::cerr << msg << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Util::ShaderArrayName(const char* arrName, int index, const char* memberName) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << arrName << "[" << index << "]." << memberName;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
16
core/Util.h
16
core/Util.h
@ -2,7 +2,9 @@
|
|||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -28,6 +30,20 @@ namespace Util {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
template<class T>
|
||||||
|
std::vector<T*> FindNodesByType(Node *&root, const Name &type) {
|
||||||
|
std::vector<T*> nodes;
|
||||||
|
if (root->GetType() == type) {
|
||||||
|
nodes.push_back(dynamic_cast<T*>(root));
|
||||||
|
}
|
||||||
|
for (Node *child : root->GetChildren()) {
|
||||||
|
std::vector<T*> childs = FindNodesByType<T>(child, type);
|
||||||
|
nodes.insert(nodes.begin(), childs.begin(), childs.end());
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ShaderArrayName(const char* arrName, int index, const char* memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* UTIL_H */
|
#endif /* UTIL_H */
|
||||||
|
@ -141,6 +141,9 @@ int main() {
|
|||||||
shader->UpdateDirectionalLight(DirectionalLight());
|
shader->UpdateDirectionalLight(DirectionalLight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PointLightList pointLights = Util::FindNodesByType<PointLight>(root, "PointLight");
|
||||||
|
shader->UpdatePointLights(pointLights);
|
||||||
|
|
||||||
// Render the scene tree
|
// Render the scene tree
|
||||||
render(root, shader, Matrix(1.0f));
|
render(root, shader, Matrix(1.0f));
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ function init()
|
|||||||
light:SetSpecular(0.1)
|
light:SetSpecular(0.1)
|
||||||
couch.Node.GetRoot():AddChild(light:Instance())
|
couch.Node.GetRoot():AddChild(light:Instance())
|
||||||
|
|
||||||
|
init_point_lights()
|
||||||
|
|
||||||
local skybox = couch.Skybox.FromFiles(
|
local skybox = couch.Skybox.FromFiles(
|
||||||
"../resources/skybox/px.png",
|
"../resources/skybox/px.png",
|
||||||
"../resources/skybox/nx.png",
|
"../resources/skybox/nx.png",
|
||||||
@ -176,6 +178,22 @@ function update(delta)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function init_point_lights()
|
||||||
|
local colors = {couch.Vector3(1.0, 0.0, 0.0), couch.Vector3(0.0, 1.0, 0.0), couch.Vector3(0.0, 0.0, 1.0)}
|
||||||
|
for i, color in ipairs(colors) do
|
||||||
|
local pointLight = couch.PointLight();
|
||||||
|
pointLight:Translate(couch.Vector3(i * -10.0, 0, -10))
|
||||||
|
pointLight:SetRadius(10.0)
|
||||||
|
pointLight:SetColor(color)
|
||||||
|
pointLight:SetAmbient(1.0)
|
||||||
|
pointLight:SetSpecular(0.1)
|
||||||
|
local lightBox = couch.Mesh.FromFile("../resources/cube.obj")
|
||||||
|
lightBox:UniformScale(0.5);
|
||||||
|
pointLight:AddChild(lightBox);
|
||||||
|
couch.Node.GetRoot():AddChild(pointLight:Instance())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function action_dir(key, action, pos, neg, curr)
|
function action_dir(key, action, pos, neg, curr)
|
||||||
if key == pos and action == couch.ACTION_PRESS then
|
if key == pos and action == couch.ACTION_PRESS then
|
||||||
return 1.0
|
return 1.0
|
||||||
|
@ -27,6 +27,17 @@ struct DirectionalLight {
|
|||||||
float specular;
|
float specular;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PointLight {
|
||||||
|
vec3 pos;
|
||||||
|
float radius;
|
||||||
|
vec3 color;
|
||||||
|
float ambient;
|
||||||
|
float diffuse;
|
||||||
|
float specular;
|
||||||
|
};
|
||||||
|
#define NUM_POINT_LIGHTS 4
|
||||||
|
uniform PointLight pointLights[NUM_POINT_LIGHTS];
|
||||||
|
|
||||||
struct Material {
|
struct Material {
|
||||||
sampler2D tex;
|
sampler2D tex;
|
||||||
bool usesTex;
|
bool usesTex;
|
||||||
@ -44,6 +55,29 @@ struct Material {
|
|||||||
uniform DirectionalLight directionalLight;
|
uniform DirectionalLight directionalLight;
|
||||||
uniform Material material;
|
uniform Material material;
|
||||||
|
|
||||||
|
void calcDirectionalLight(in vec3 normal) {
|
||||||
|
AMBIENT += directionalLight.ambient * directionalLight.color * material.ambient;
|
||||||
|
|
||||||
|
vec3 direction = -(VIEW * vec4(directionalLight.direction, 0.0)).xyz;
|
||||||
|
float diff = dot(normalize(direction), normalize(normal));
|
||||||
|
diff = max(diff, 0.0);
|
||||||
|
DIFFUSE += directionalLight.diffuse * diff * directionalLight.color * material.diffuse;
|
||||||
|
|
||||||
|
vec3 viewDir = normalize((VIEW * MODEL * vec4(pos, 1.0)).xyz);
|
||||||
|
vec3 reflectionDir = reflect(normalize(direction), normalize(normal));
|
||||||
|
float spec = dot(viewDir, reflectionDir);
|
||||||
|
spec = max(spec, 0.0);
|
||||||
|
spec = pow(spec, material.shininess);
|
||||||
|
SPECULAR += directionalLight.color * (spec * material.specular);
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcPointLight(in vec3 normal, in PointLight pointLight) {
|
||||||
|
vec4 ray = VIEW * MODEL * vec4(pos, 1.0) - VIEW * vec4(pointLight.pos, 1.0);
|
||||||
|
float dist = length(ray);
|
||||||
|
float attenuation = max(1.0 - dist * dist / pointLight.radius / pointLight.radius, 0.0);
|
||||||
|
AMBIENT += pointLight.color * material.ambient * pointLight.ambient * attenuation;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 vertex = PROJECTION * VIEW * MODEL * vec4(pos, 1.0);
|
vec4 vertex = PROJECTION * VIEW * MODEL * vec4(pos, 1.0);
|
||||||
gl_Position = vertex;
|
gl_Position = vertex;
|
||||||
@ -58,17 +92,14 @@ void main() {
|
|||||||
vec3 my_normal = (VIEW * mat4(NORMAL) * vec4(normal, 0.0)).xyz;
|
vec3 my_normal = (VIEW * mat4(NORMAL) * vec4(normal, 0.0)).xyz;
|
||||||
|
|
||||||
// Flat shading, we compute light per vertex
|
// Flat shading, we compute light per vertex
|
||||||
AMBIENT = directionalLight.ambient * directionalLight.color * material.ambient;
|
AMBIENT = vec3(0.0);
|
||||||
|
DIFFUSE = vec3(0.0);
|
||||||
|
SPECULAR = vec3(0.0);
|
||||||
|
|
||||||
vec3 direction = -(VIEW * vec4(directionalLight.direction, 0.0)).xyz;
|
calcDirectionalLight(my_normal);
|
||||||
float diff = dot(normalize(direction), normalize(my_normal));
|
|
||||||
diff = max(diff, 0.0);
|
|
||||||
DIFFUSE = directionalLight.diffuse * diff * directionalLight.color * material.diffuse;
|
|
||||||
|
|
||||||
vec3 viewDir = normalize((VIEW * MODEL * vec4(pos, 1.0)).xyz);
|
// PointLights
|
||||||
vec3 reflectionDir = reflect(normalize(direction), normalize(my_normal));
|
for(int i = 0; i < NUM_POINT_LIGHTS; i++) {
|
||||||
float spec = dot(viewDir, reflectionDir);
|
calcPointLight(my_normal, pointLights[i]);
|
||||||
spec = max(spec, 0.0);
|
}
|
||||||
spec = pow(spec, material.shininess);
|
|
||||||
SPECULAR = directionalLight.color * (spec * material.specular);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user