Specular Lighting

Next up is attenuation
This commit is contained in:
elipzer 2018-09-14 23:30:14 -04:00
parent 9920dfc25b
commit 5200ba4dbe
13 changed files with 89 additions and 16 deletions

View File

@ -16,6 +16,7 @@ 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;
@ -37,12 +38,30 @@ namespace charcoal
Normal normal; Normal normal;
}; };
struct PNSVertex
{
void set_position(const Position& position) { this->position = position; }
void set_normal(const Normal& normal) { this->normal = normal; }
void set_specular_exponent(const SpecularExponent& specular_exponent) { this->specular_exponent = specular_exponent; }
Position position;
Normal normal;
SpecularExponent specular_exponent;
};
// Other Data Types // Other Data Types
struct Light struct Light
{ {
Light(const Position& position, const ColorRGB& ambient, const ColorRGB& diffuse) Light(
: position(position), ambient(ambient), diffuse(diffuse) {} const Position& position,
const ColorRGB& ambient,
const ColorRGB& diffuse
)
: position(position),
ambient(ambient),
diffuse(diffuse)
{}
Position position; Position position;
ColorRGB ambient; ColorRGB ambient;
@ -55,7 +74,7 @@ namespace charcoal
typedef Index BasicIndex; typedef Index BasicIndex;
typedef Renderable<BasicVertex, BasicIndex> BasicRenderable; typedef Renderable<BasicVertex, BasicIndex> BasicRenderable;
typedef PNVertex LitVertex; typedef PNSVertex LitVertex;
typedef Index LitIndex; typedef Index LitIndex;
typedef Renderable<LitVertex, LitIndex> LitRenderable; typedef Renderable<LitVertex, LitIndex> LitRenderable;
} }

View File

@ -15,11 +15,14 @@ namespace charcoal
mat4 get_world_to_view_matrix() const { return m_projection_matrix * m_view_matrix; } mat4 get_world_to_view_matrix() const { return m_projection_matrix * m_view_matrix; }
const vec3& get_position() const { return m_position; }
const mat4& get_view_matrix() const { return m_view_matrix; } const mat4& get_view_matrix() const { return m_view_matrix; }
const mat4& get_projection_matrix() const { return m_projection_matrix; } const mat4& get_projection_matrix() const { return m_projection_matrix; }
protected: protected:
vec3 m_position;
mat4 m_view_matrix; mat4 m_view_matrix;
mat4 m_projection_matrix; mat4 m_projection_matrix;
}; };

View File

@ -29,6 +29,5 @@ namespace charcoal
void update_scale(); void update_scale();
vec3 m_size; vec3 m_size;
vec3 m_position;
}; };
} }

View File

@ -42,7 +42,6 @@ namespace charcoal
vec3 get_right() const { return vec3(m_right); } vec3 get_right() const { return vec3(m_right); }
private: private:
vec3 m_position;
vec4 m_forward; vec4 m_forward;
vec4 m_up; vec4 m_up;
vec4 m_right; vec4 m_right;

View File

@ -23,6 +23,16 @@ namespace charcoal
glUniform1ui(uniform_index, value); glUniform1ui(uniform_index, value);
} }
void uniform_float(int uniform_index, float value)
{
glUniform1f(uniform_index, value);
}
void uniform_vec3(int uniform_index, const vec3& value)
{
glUniform3fv(uniform_index, 1, &value[0]);
}
void uniform_matrix(int uniform_index, const mat4& matrix, bool transpose) void uniform_matrix(int uniform_index, const mat4& matrix, bool transpose)
{ {
glUniformMatrix4fv(uniform_index, 1, transpose ? GL_TRUE : GL_FALSE, &matrix[0][0]); glUniformMatrix4fv(uniform_index, 1, transpose ? GL_TRUE : GL_FALSE, &matrix[0][0]);
@ -33,6 +43,7 @@ namespace charcoal
const int position_size = 1; const int position_size = 1;
const int ambient_size = 1; const int ambient_size = 1;
const int diffuse_size = 1; const int diffuse_size = 1;
const int specular_exponent_size = 1;
int current_location = uniform_index; 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)
{ {

View File

@ -16,6 +16,8 @@ namespace charcoal
void clear_screen(); void clear_screen();
void uniform_int(int uniform_index, int value); void uniform_int(int uniform_index, int value);
void uniform_uint(int uniform_index, unsigned int value); void uniform_uint(int uniform_index, unsigned int value);
void uniform_float(int uniform_index, float value);
void uniform_vec3(int uniform_index, const vec3& value);
void uniform_matrix(int uniform_index, const mat4& matrix, bool transpose = false); void uniform_matrix(int uniform_index, const mat4& matrix, bool transpose = false);
void uniform_lights(int uniform_index, const std::vector<Light>& lights); // TODO: This may want to be moved somewhere else void uniform_lights(int uniform_index, const std::vector<Light>& lights); // TODO: This may want to be moved somewhere else
} }

View File

@ -9,24 +9,27 @@ namespace charcoal
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
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)));
glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]); glBindBuffer(GL_ARRAY_BUFFER, m_element_buffers[0]);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3); glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4); glEnableVertexAttribArray(4);
glEnableVertexAttribArray(5); glEnableVertexAttribArray(5);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(0 * sizeof(vec4))); glEnableVertexAttribArray(6);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(1 * sizeof(vec4))); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(0 * sizeof(vec4)));
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(2 * sizeof(vec4))); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(1 * sizeof(vec4)));
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(3 * sizeof(vec4))); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(2 * sizeof(vec4)));
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Poseable), (void*)(3 * sizeof(vec4)));
glVertexAttribDivisor(0, 0); // Send the mesh data once glVertexAttribDivisor(0, 0); // Send the mesh data once
glVertexAttribDivisor(1, 0); // Send the mesh data once glVertexAttribDivisor(1, 0); // Send the mesh data once
glVertexAttribDivisor(2, 1); // Send the offset data for each instance drawn glVertexAttribDivisor(2, 0); // Send the mesh data once
glVertexAttribDivisor(3, 1); // Send the offset data for each instance drawn glVertexAttribDivisor(3, 1); // Send the offset data for each instance drawn
glVertexAttribDivisor(4, 1); // Send the offset data for each instance drawn glVertexAttribDivisor(4, 1); // Send the offset data for each instance drawn
glVertexAttribDivisor(5, 1); // Send the offset data for each instance drawn glVertexAttribDivisor(5, 1); // Send the offset data for each instance drawn
glVertexAttribDivisor(6, 1); // Send the offset data for each instance drawn
} }
} }
} }

View File

@ -9,23 +9,35 @@ struct Light
in vec3 fragment_position; in vec3 fragment_position;
in vec3 fragment_normal; 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 Light lights[MAX_LIGHTS];
layout(location = 52) uniform uint num_lights; layout(location = 68) uniform uint num_lights;
layout(location = 69) uniform vec3 eye_position;
out vec4 frag_color; out vec4 frag_color;
void main() void main()
{ {
vec3 hard_eye_position = vec3(0.0f, 0.0f, -5.0f);
vec3 norm_normal = normalize(fragment_normal); vec3 norm_normal = normalize(fragment_normal);
vec3 norm_eye_vector = normalize(eye_position - fragment_position);
vec3 accum = vec3(0.0); vec3 accum = vec3(0.0);
float diffuse_multiplier; float diffuse_multiplier;
float specular_multiplier;
vec3 light_vector; vec3 light_vector;
vec3 reflected_light_vector;
for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) { for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) {
light_vector = normalize(lights[i].position - fragment_position); light_vector = normalize(lights[i].position - fragment_position);
reflected_light_vector = reflect(-light_vector, norm_normal);
diffuse_multiplier = clamp(dot(light_vector, norm_normal), 0.0, 1.0); 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);
accum += lights[i].ambient; accum += lights[i].ambient;
accum += diffuse_multiplier * lights[i].diffuse; accum += diffuse_multiplier * lights[i].diffuse;
accum += specular_multiplier * lights[i].diffuse;
} }
frag_color = vec4(accum, 1.0); frag_color = vec4(accum, 1.0);
} }

View File

@ -42,7 +42,9 @@ namespace charcoal
CHECK_GL_ERR(); CHECK_GL_ERR();
glutil::uniform_lights(4, m_lights); glutil::uniform_lights(4, m_lights);
CHECK_GL_ERR(); CHECK_GL_ERR();
glutil::uniform_uint(52, (unsigned int)m_lights.size()); glutil::uniform_uint(68, (unsigned int)m_lights.size());
CHECK_GL_ERR();
glutil::uniform_vec3(69, m_p_camera->get_position());
CHECK_GL_ERR(); 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)
{ {

View File

@ -30,7 +30,11 @@ 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(const Position& position, const ColorRGB& ambient, const ColorRGB& diffuse) void add_light(
const Position& position,
const ColorRGB& ambient,
const ColorRGB& diffuse
)
{ {
m_lights.emplace_back(position, ambient, diffuse); m_lights.emplace_back(position, ambient, diffuse);
} }

View File

@ -1,12 +1,14 @@
#version 430 #version 430
layout(location = 0) in vec3 vertex_position; layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_normal; layout(location = 1) in vec3 vertex_normal;
layout(location = 2) in mat4 model_to_world; layout(location = 2) in float vertex_specular_exponent;
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 vec3 fragment_position;
out vec3 fragment_normal; out vec3 fragment_normal;
out float fragment_specular_exponent;
void main() void main()
{ {
@ -15,4 +17,5 @@ void main()
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;
} }

View File

@ -4,6 +4,7 @@
#include "MeshFactory.h" #include "MeshFactory.h"
#include "Mesh.h" #include "Mesh.h"
#include "BuiltinTypes.h"
// TODO: Consider a mesh generator for every render type (i.e. basic::meshgenerator, lit::meshgenerator, etc.) // TODO: Consider a mesh generator for every render type (i.e. basic::meshgenerator, lit::meshgenerator, etc.)
@ -14,6 +15,16 @@ namespace charcoal
// Uses MeshFactory to generate meshes for the builtin vertex types. // Uses MeshFactory to generate meshes for the builtin vertex types.
namespace meshgenerator namespace meshgenerator
{ {
template <typename VertexType, typename IndexType>
Mesh<VertexType, IndexType>* apply_specular_exponent(Mesh<VertexType, IndexType>* mesh, const SpecularExponent& specular_exponent)
{
for (unsigned int i = 0; i < mesh->vertex_count; ++i)
{
mesh->vertices[i].set_specular_exponent(specular_exponent);
}
return mesh;
}
template <typename VertexType, typename IndexType> template <typename VertexType, typename IndexType>
Mesh<VertexType, IndexType>* gen_cube_p(const DrawMode& draw_mode, float width, float height, float depth) Mesh<VertexType, IndexType>* gen_cube_p(const DrawMode& draw_mode, float width, float height, float depth)
{ {

View File

@ -6,7 +6,12 @@
MyBuiltinLitScene::MyBuiltinLitScene(Application& application) MyBuiltinLitScene::MyBuiltinLitScene(Application& application)
: LitScene(application), : LitScene(application),
m_shape(meshgenerator::gen_cube_pn<LitVertex, LitIndex>(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f), DrawMode::DRAW_TRIANGLES), m_shape(
meshgenerator::apply_specular_exponent<LitVertex, LitIndex>(
meshgenerator::gen_cube_pn<LitVertex, LitIndex>(DRAW_TRIANGLES, 2.0f, 2.0f, 2.0f),
2
), 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)),
m_batch(add_batch(&m_shape, 1)) m_batch(add_batch(&m_shape, 1))
{ {