LitScene Phong Lighting Complete
Now, LitScene allows for simple lighting. (Shadows still to come). Ambient, specular, and diffuse lighting available and each mesh's vertex can define a material that defines its reflectivity. An example scene was added to the MyApplication as the scene for the 6 button.
This commit is contained in:
parent
5200ba4dbe
commit
1eea92a3af
@ -16,10 +16,60 @@ namespace charcoal
|
|||||||
typedef vec4 ColorRGBA;
|
typedef vec4 ColorRGBA;
|
||||||
typedef vec3 ColorRGB;
|
typedef vec3 ColorRGB;
|
||||||
typedef vec2 UV;
|
typedef vec2 UV;
|
||||||
typedef float SpecularExponent;
|
|
||||||
|
|
||||||
typedef unsigned int Index;
|
typedef unsigned int Index;
|
||||||
|
|
||||||
|
// Shader Data Types
|
||||||
|
|
||||||
|
struct Light
|
||||||
|
{
|
||||||
|
typedef vec3 Power;
|
||||||
|
typedef vec3 Fade;
|
||||||
|
|
||||||
|
Light(
|
||||||
|
const Position& position,
|
||||||
|
const Power& power,
|
||||||
|
const ColorRGB& ambient,
|
||||||
|
const ColorRGB& diffuse,
|
||||||
|
const ColorRGB& specular,
|
||||||
|
const Fade& fade
|
||||||
|
)
|
||||||
|
: position(position),
|
||||||
|
power(power),
|
||||||
|
ambient(ambient),
|
||||||
|
diffuse(diffuse),
|
||||||
|
specular(specular),
|
||||||
|
fade(fade)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Position position;
|
||||||
|
Power power;
|
||||||
|
ColorRGB ambient;
|
||||||
|
ColorRGB diffuse;
|
||||||
|
ColorRGB specular;
|
||||||
|
Fade fade;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Material
|
||||||
|
{
|
||||||
|
Material(
|
||||||
|
float ambient = 1.0f,
|
||||||
|
float diffuse = 1.0f,
|
||||||
|
float specular = 0.0f,
|
||||||
|
float specular_exponent = 1.0f
|
||||||
|
)
|
||||||
|
: ambient(ambient),
|
||||||
|
diffuse(diffuse),
|
||||||
|
specular(specular),
|
||||||
|
specular_exponent(specular_exponent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
float ambient;
|
||||||
|
float diffuse;
|
||||||
|
float specular;
|
||||||
|
float specular_exponent;
|
||||||
|
};
|
||||||
|
|
||||||
// Generic Vertices
|
// Generic Vertices
|
||||||
|
|
||||||
struct PVertex
|
struct PVertex
|
||||||
@ -38,34 +88,15 @@ namespace charcoal
|
|||||||
Normal normal;
|
Normal normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PNSVertex
|
struct PNMVertex
|
||||||
{
|
{
|
||||||
void set_position(const Position& position) { this->position = position; }
|
void set_position(const Position& position) { this->position = position; }
|
||||||
void set_normal(const Normal& normal) { this->normal = normal; }
|
void set_normal(const Normal& normal) { this->normal = normal; }
|
||||||
void set_specular_exponent(const SpecularExponent& specular_exponent) { this->specular_exponent = specular_exponent; }
|
void set_material(const Material& material) { this->material = material; }
|
||||||
|
|
||||||
Position position;
|
Position position;
|
||||||
Normal normal;
|
Normal normal;
|
||||||
SpecularExponent specular_exponent;
|
Material material;
|
||||||
};
|
|
||||||
|
|
||||||
// Other Data Types
|
|
||||||
|
|
||||||
struct Light
|
|
||||||
{
|
|
||||||
Light(
|
|
||||||
const Position& position,
|
|
||||||
const ColorRGB& ambient,
|
|
||||||
const ColorRGB& diffuse
|
|
||||||
)
|
|
||||||
: position(position),
|
|
||||||
ambient(ambient),
|
|
||||||
diffuse(diffuse)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Position position;
|
|
||||||
ColorRGB ambient;
|
|
||||||
ColorRGB diffuse;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// typedefs for builtin types
|
// typedefs for builtin types
|
||||||
@ -74,7 +105,7 @@ namespace charcoal
|
|||||||
typedef Index BasicIndex;
|
typedef Index BasicIndex;
|
||||||
typedef Renderable<BasicVertex, BasicIndex> BasicRenderable;
|
typedef Renderable<BasicVertex, BasicIndex> BasicRenderable;
|
||||||
|
|
||||||
typedef PNSVertex LitVertex;
|
typedef PNMVertex LitVertex;
|
||||||
typedef Index LitIndex;
|
typedef Index LitIndex;
|
||||||
typedef Renderable<LitVertex, LitIndex> LitRenderable;
|
typedef Renderable<LitVertex, LitIndex> LitRenderable;
|
||||||
}
|
}
|
||||||
|
@ -40,19 +40,14 @@ namespace charcoal
|
|||||||
|
|
||||||
void uniform_lights(int uniform_index, const std::vector<Light>& lights)
|
void uniform_lights(int uniform_index, const std::vector<Light>& lights)
|
||||||
{
|
{
|
||||||
const int position_size = 1;
|
|
||||||
const int ambient_size = 1;
|
|
||||||
const int diffuse_size = 1;
|
|
||||||
const int specular_exponent_size = 1;
|
|
||||||
int current_location = uniform_index;
|
|
||||||
for (std::vector<Light>::size_type i = 0; i < lights.size(); ++i)
|
for (std::vector<Light>::size_type i = 0; i < lights.size(); ++i)
|
||||||
{
|
{
|
||||||
glUniform3fv(current_location, 1, &lights[i].position[0]);
|
glUniform3fv(uniform_index++, 1, &lights[i].position[0]);
|
||||||
current_location += position_size;
|
glUniform3fv(uniform_index++, 1, &lights[i].power[0]);
|
||||||
glUniform3fv(current_location, 1, &lights[i].ambient[0]);
|
glUniform3fv(uniform_index++, 1, &lights[i].ambient[0]);
|
||||||
current_location += ambient_size;
|
glUniform3fv(uniform_index++, 1, &lights[i].diffuse[0]);
|
||||||
glUniform3fv(current_location, 1, &lights[i].diffuse[0]);
|
glUniform3fv(uniform_index++, 1, &lights[i].specular[0]);
|
||||||
current_location += diffuse_size;
|
glUniform3fv(uniform_index++, 1, &lights[i].fade[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace charcoal
|
|||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, position)));
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, position)));
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, normal)));
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, normal)));
|
||||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, specular_exponent)));
|
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(LitVertex), (void*)(offsetof(LitVertex, material)));
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]);
|
glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]);
|
||||||
glEnableVertexAttribArray(3);
|
glEnableVertexAttribArray(3);
|
||||||
glEnableVertexAttribArray(4);
|
glEnableVertexAttribArray(4);
|
||||||
|
@ -1,43 +1,58 @@
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
|
struct Fragment
|
||||||
|
{
|
||||||
|
vec3 position;
|
||||||
|
vec3 normal;
|
||||||
|
vec4 material;
|
||||||
|
};
|
||||||
|
|
||||||
struct Light
|
struct Light
|
||||||
{
|
{
|
||||||
vec3 position;
|
vec3 position;
|
||||||
|
vec3 power; // x = ambient, y = diffuse, z = specular
|
||||||
vec3 ambient;
|
vec3 ambient;
|
||||||
vec3 diffuse;
|
vec3 diffuse;
|
||||||
|
vec3 specular;
|
||||||
|
vec3 fade; // x = constant, y = linear, z = quadratic
|
||||||
};
|
};
|
||||||
|
|
||||||
in vec3 fragment_position;
|
in Fragment fragment;
|
||||||
in vec3 fragment_normal;
|
|
||||||
in float fragment_specular_exponent;
|
|
||||||
|
|
||||||
#define MAX_LIGHTS 16
|
#define MAX_LIGHTS 16
|
||||||
layout(location = 4) uniform Light lights[MAX_LIGHTS];
|
layout(location = 4) uniform vec3 eye_position;
|
||||||
layout(location = 68) uniform uint num_lights;
|
layout(location = 5) uniform uint num_lights;
|
||||||
layout(location = 69) uniform vec3 eye_position;
|
layout(location = 6) uniform Light lights[MAX_LIGHTS];
|
||||||
|
|
||||||
out vec4 frag_color;
|
out vec4 frag_color;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 hard_eye_position = vec3(0.0f, 0.0f, -5.0f);
|
vec3 accumulator = vec3(0.0);
|
||||||
vec3 norm_normal = normalize(fragment_normal);
|
|
||||||
vec3 norm_eye_vector = normalize(eye_position - fragment_position);
|
|
||||||
|
|
||||||
vec3 accum = vec3(0.0);
|
vec3 normal = normalize(fragment.normal);
|
||||||
|
|
||||||
float diffuse_multiplier;
|
for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i)
|
||||||
float specular_multiplier;
|
{
|
||||||
vec3 light_vector;
|
vec3 to_eye = eye_position - fragment.position;
|
||||||
vec3 reflected_light_vector;
|
vec3 to_light = lights[i].position - fragment.position;
|
||||||
for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) {
|
|
||||||
light_vector = normalize(lights[i].position - fragment_position);
|
float dist = length(to_light);
|
||||||
reflected_light_vector = reflect(-light_vector, norm_normal);
|
vec3 to_light_norm = to_light / dist; // normalize(to_light);
|
||||||
diffuse_multiplier = clamp(dot(light_vector, norm_normal), 0.0, 1.0);
|
|
||||||
specular_multiplier = pow(clamp(dot(reflected_light_vector, norm_eye_vector), 0.0, 1.0), fragment_specular_exponent);
|
vec3 reflected = reflect(-to_light_norm, normal);
|
||||||
accum += lights[i].ambient;
|
|
||||||
accum += diffuse_multiplier * lights[i].diffuse;
|
float fade = lights[i].fade.x + lights[i].fade.y * dist + lights[i].fade.z * dist * dist;
|
||||||
accum += specular_multiplier * lights[i].diffuse;
|
|
||||||
|
// Multipliers
|
||||||
|
// a = ambient, d = diffuse, s = specular
|
||||||
|
float a = lights[i].power.x * fragment.material.x / fade;
|
||||||
|
float d = lights[i].power.y * fragment.material.y / fade * clamp(dot(to_light_norm, normal), 0.0, 1.0);
|
||||||
|
float s = lights[i].power.z * fragment.material.z / fade * pow(clamp(dot(reflected, normal), 0.0, 1.0), clamp(fragment.material.w, 1.0, 1000.0)); // Seems like weird things happen if w is set to 0 and not clamped (maybe it is not exactly 0)
|
||||||
|
|
||||||
|
vec3 color = a * lights[i].ambient + d * lights[i].diffuse + s * lights[i].specular;
|
||||||
|
accumulator += color;
|
||||||
}
|
}
|
||||||
frag_color = vec4(accum, 1.0);
|
|
||||||
|
frag_color = vec4(accumulator, 1.0);
|
||||||
}
|
}
|
@ -35,22 +35,15 @@ namespace charcoal
|
|||||||
void LitScene::render()
|
void LitScene::render()
|
||||||
{
|
{
|
||||||
glutil::clear_screen();
|
glutil::clear_screen();
|
||||||
CHECK_GL_ERR();
|
|
||||||
m_shader_program.use();
|
m_shader_program.use();
|
||||||
CHECK_GL_ERR();
|
|
||||||
glutil::uniform_matrix(0, m_p_camera->get_world_to_view_matrix());
|
glutil::uniform_matrix(0, m_p_camera->get_world_to_view_matrix());
|
||||||
CHECK_GL_ERR();
|
glutil::uniform_vec3(4, m_p_camera->get_position());
|
||||||
glutil::uniform_lights(4, m_lights);
|
glutil::uniform_uint(5, (unsigned int)m_lights.size());
|
||||||
CHECK_GL_ERR();
|
glutil::uniform_lights(6, m_lights);
|
||||||
glutil::uniform_uint(68, (unsigned int)m_lights.size());
|
|
||||||
CHECK_GL_ERR();
|
|
||||||
glutil::uniform_vec3(69, m_p_camera->get_position());
|
|
||||||
CHECK_GL_ERR();
|
|
||||||
for (auto iter = m_batches.begin(); iter != m_batches.end(); ++iter)
|
for (auto iter = m_batches.begin(); iter != m_batches.end(); ++iter)
|
||||||
{
|
{
|
||||||
iter->render();
|
iter->render();
|
||||||
}
|
}
|
||||||
CHECK_GL_ERR();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ namespace charcoal
|
|||||||
{
|
{
|
||||||
namespace builtin
|
namespace builtin
|
||||||
{
|
{
|
||||||
|
// A scene lit by the Phong Reflection Model (See https://en.wikipedia.org/wiki/Phong_reflection_model )
|
||||||
class LitScene : public AutoPrerenderingScene, public Batched<LitRenderable, LitBatch>
|
class LitScene : public AutoPrerenderingScene, public Batched<LitRenderable, LitBatch>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -30,13 +31,17 @@ namespace charcoal
|
|||||||
protected:
|
protected:
|
||||||
void set_camera(const Camera* p_camera) { m_p_camera = p_camera; }
|
void set_camera(const Camera* p_camera) { m_p_camera = p_camera; }
|
||||||
|
|
||||||
void add_light(
|
Light& add_light(
|
||||||
const Position& position,
|
const Position& position,
|
||||||
const ColorRGB& ambient,
|
const Light::Power& power,
|
||||||
const ColorRGB& diffuse
|
const ColorRGB ambient,
|
||||||
|
const ColorRGB diffuse,
|
||||||
|
const ColorRGB specular,
|
||||||
|
const Light::Fade& fade
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_lights.emplace_back(position, ambient, diffuse);
|
m_lights.emplace_back(position, power, ambient, diffuse, specular, fade);
|
||||||
|
return m_lights.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,21 +1,32 @@
|
|||||||
#version 430
|
#version 430
|
||||||
layout(location = 0) in vec3 vertex_position;
|
|
||||||
layout(location = 1) in vec3 vertex_normal;
|
struct Vertex
|
||||||
layout(location = 2) in float vertex_specular_exponent;
|
{
|
||||||
|
vec3 position;
|
||||||
|
vec3 normal;
|
||||||
|
vec4 material;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Fragment
|
||||||
|
{
|
||||||
|
vec3 position;
|
||||||
|
vec3 normal;
|
||||||
|
vec4 material;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) in Vertex vertex;
|
||||||
layout(location = 3) in mat4 model_to_world;
|
layout(location = 3) in mat4 model_to_world;
|
||||||
|
|
||||||
layout(location = 0) uniform mat4 world_to_projection;
|
layout(location = 0) uniform mat4 world_to_projection;
|
||||||
|
|
||||||
out vec3 fragment_position;
|
out Fragment fragment;
|
||||||
out vec3 fragment_normal;
|
|
||||||
out float fragment_specular_exponent;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 model_position = model_to_world * vec4(vertex_position, 1.0);
|
vec4 model_position = model_to_world * vec4(vertex.position, 1.0);
|
||||||
vec4 model_normal = model_to_world * vec4(vertex_normal, 0.0);
|
vec4 model_normal = model_to_world * vec4(vertex.normal, 0.0);
|
||||||
gl_Position = world_to_projection * model_position;
|
gl_Position = world_to_projection * model_position;
|
||||||
fragment_position = model_position.xyz;
|
fragment.position = model_position.xyz;
|
||||||
fragment_normal = model_normal.xyz;
|
fragment.normal = model_normal.xyz;
|
||||||
fragment_specular_exponent = vertex_specular_exponent;
|
fragment.material = vertex.material;
|
||||||
}
|
}
|
@ -16,11 +16,11 @@ namespace charcoal
|
|||||||
namespace meshgenerator
|
namespace meshgenerator
|
||||||
{
|
{
|
||||||
template <typename VertexType, typename IndexType>
|
template <typename VertexType, typename IndexType>
|
||||||
Mesh<VertexType, IndexType>* apply_specular_exponent(Mesh<VertexType, IndexType>* mesh, const SpecularExponent& specular_exponent)
|
Mesh<VertexType, IndexType>* set_material(Mesh<VertexType, IndexType>* mesh, const Material& material)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < mesh->vertex_count; ++i)
|
for (unsigned int i = 0; i < mesh->vertex_count; ++i)
|
||||||
{
|
{
|
||||||
mesh->vertices[i].set_specular_exponent(specular_exponent);
|
mesh->vertices[i].set_material(material);
|
||||||
}
|
}
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
MyBuiltinLitScene::MyBuiltinLitScene(Application& application)
|
MyBuiltinLitScene::MyBuiltinLitScene(Application& application)
|
||||||
: LitScene(application),
|
: LitScene(application),
|
||||||
m_shape(
|
m_shape(
|
||||||
meshgenerator::apply_specular_exponent<LitVertex, LitIndex>(
|
meshgenerator::set_material<LitVertex, LitIndex>(
|
||||||
meshgenerator::gen_cube_pn<LitVertex, LitIndex>(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f),
|
meshgenerator::gen_cube_pn<LitVertex, LitIndex>(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f),
|
||||||
2
|
Material(1.0f, 1.0f, 0.2f, 1.0f)
|
||||||
), DrawMode::DRAW_TRIANGLES
|
), DrawMode::DRAW_TRIANGLES
|
||||||
),
|
),
|
||||||
m_camera((float)TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f)),
|
m_camera((float)TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f)),
|
||||||
@ -18,8 +18,14 @@ MyBuiltinLitScene::MyBuiltinLitScene(Application& application)
|
|||||||
add_prerenderable(&m_camera);
|
add_prerenderable(&m_camera);
|
||||||
set_camera(&m_camera);
|
set_camera(&m_camera);
|
||||||
|
|
||||||
// Something is off here... The light seems to be rotating...
|
add_light(
|
||||||
add_light(Position(0.0f, 2.0f, -2.0f), ColorRGB(0.2f, 0.2f, 0.2f), ColorRGB(1.0f, 1.0f, 1.0f));
|
Position(0.0f, 2.0f, -2.0f),
|
||||||
|
Light::Power(0.2f, 1.0f, 1.0f),
|
||||||
|
ColorRGB(1.0f, 1.0f, 1.0f),
|
||||||
|
ColorRGB(1.0f, 1.0f, 1.0f),
|
||||||
|
ColorRGB(1.0f, 1.0f, 1.0f),
|
||||||
|
Light::Fade(1.0f, 0.1f, 0.01f)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyBuiltinLitScene::update(float delta_time, clock_t clock)
|
void MyBuiltinLitScene::update(float delta_time, clock_t clock)
|
||||||
@ -40,7 +46,7 @@ void MyBuiltinLitScene::update(float delta_time, clock_t clock)
|
|||||||
|
|
||||||
{
|
{
|
||||||
Poseable& pose = m_batch.get_pose(0);
|
Poseable& pose = m_batch.get_pose(0);
|
||||||
pose.rotate(glm::normalize(vec3(1.0f, 1.0f, 0.0f)), (float)TAU_1_2 * delta_time);
|
pose.rotate(glm::normalize(vec3(1.0f, 1.0f, 0.0f)), (float)TAU_1_8 * delta_time);
|
||||||
pose.update_position(vec3(3 * (float)cos(radians), 0.0f, 0.0f));
|
pose.update_position(vec3(3 * (float)cos(radians), 0.0f, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user