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 vec3 ColorRGB;
|
||||
typedef vec2 UV;
|
||||
typedef float SpecularExponent;
|
||||
|
||||
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
|
||||
|
||||
struct PVertex
|
||||
@ -38,34 +88,15 @@ namespace charcoal
|
||||
Normal normal;
|
||||
};
|
||||
|
||||
struct PNSVertex
|
||||
struct PNMVertex
|
||||
{
|
||||
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; }
|
||||
void set_material(const Material& material) { this->material = material; }
|
||||
|
||||
Position position;
|
||||
Normal normal;
|
||||
SpecularExponent specular_exponent;
|
||||
};
|
||||
|
||||
// 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;
|
||||
Material material;
|
||||
};
|
||||
|
||||
// typedefs for builtin types
|
||||
@ -74,7 +105,7 @@ namespace charcoal
|
||||
typedef Index BasicIndex;
|
||||
typedef Renderable<BasicVertex, BasicIndex> BasicRenderable;
|
||||
|
||||
typedef PNSVertex LitVertex;
|
||||
typedef PNMVertex LitVertex;
|
||||
typedef Index LitIndex;
|
||||
typedef Renderable<LitVertex, LitIndex> LitRenderable;
|
||||
}
|
||||
|
@ -40,19 +40,14 @@ namespace charcoal
|
||||
|
||||
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)
|
||||
{
|
||||
glUniform3fv(current_location, 1, &lights[i].position[0]);
|
||||
current_location += position_size;
|
||||
glUniform3fv(current_location, 1, &lights[i].ambient[0]);
|
||||
current_location += ambient_size;
|
||||
glUniform3fv(current_location, 1, &lights[i].diffuse[0]);
|
||||
current_location += diffuse_size;
|
||||
glUniform3fv(uniform_index++, 1, &lights[i].position[0]);
|
||||
glUniform3fv(uniform_index++, 1, &lights[i].power[0]);
|
||||
glUniform3fv(uniform_index++, 1, &lights[i].ambient[0]);
|
||||
glUniform3fv(uniform_index++, 1, &lights[i].diffuse[0]);
|
||||
glUniform3fv(uniform_index++, 1, &lights[i].specular[0]);
|
||||
glUniform3fv(uniform_index++, 1, &lights[i].fade[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace charcoal
|
||||
glEnableVertexAttribArray(2);
|
||||
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(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]);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(4);
|
||||
|
@ -1,43 +1,58 @@
|
||||
#version 430
|
||||
|
||||
struct Fragment
|
||||
{
|
||||
vec3 position;
|
||||
vec3 normal;
|
||||
vec4 material;
|
||||
};
|
||||
|
||||
struct Light
|
||||
{
|
||||
vec3 position;
|
||||
vec3 power; // x = ambient, y = diffuse, z = specular
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
vec3 fade; // x = constant, y = linear, z = quadratic
|
||||
};
|
||||
|
||||
in vec3 fragment_position;
|
||||
in vec3 fragment_normal;
|
||||
in float fragment_specular_exponent;
|
||||
in Fragment fragment;
|
||||
|
||||
#define MAX_LIGHTS 16
|
||||
layout(location = 4) uniform Light lights[MAX_LIGHTS];
|
||||
layout(location = 68) uniform uint num_lights;
|
||||
layout(location = 69) uniform vec3 eye_position;
|
||||
layout(location = 4) uniform vec3 eye_position;
|
||||
layout(location = 5) uniform uint num_lights;
|
||||
layout(location = 6) uniform Light lights[MAX_LIGHTS];
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 hard_eye_position = vec3(0.0f, 0.0f, -5.0f);
|
||||
vec3 norm_normal = normalize(fragment_normal);
|
||||
vec3 norm_eye_vector = normalize(eye_position - fragment_position);
|
||||
vec3 accumulator = vec3(0.0);
|
||||
|
||||
vec3 accum = vec3(0.0);
|
||||
vec3 normal = normalize(fragment.normal);
|
||||
|
||||
for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i)
|
||||
{
|
||||
vec3 to_eye = eye_position - fragment.position;
|
||||
vec3 to_light = lights[i].position - fragment.position;
|
||||
|
||||
float diffuse_multiplier;
|
||||
float specular_multiplier;
|
||||
vec3 light_vector;
|
||||
vec3 reflected_light_vector;
|
||||
for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) {
|
||||
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);
|
||||
specular_multiplier = pow(clamp(dot(reflected_light_vector, norm_eye_vector), 0.0, 1.0), fragment_specular_exponent);
|
||||
accum += lights[i].ambient;
|
||||
accum += diffuse_multiplier * lights[i].diffuse;
|
||||
accum += specular_multiplier * lights[i].diffuse;
|
||||
float dist = length(to_light);
|
||||
vec3 to_light_norm = to_light / dist; // normalize(to_light);
|
||||
|
||||
vec3 reflected = reflect(-to_light_norm, normal);
|
||||
|
||||
float fade = lights[i].fade.x + lights[i].fade.y * dist + lights[i].fade.z * dist * dist;
|
||||
|
||||
// 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()
|
||||
{
|
||||
glutil::clear_screen();
|
||||
CHECK_GL_ERR();
|
||||
m_shader_program.use();
|
||||
CHECK_GL_ERR();
|
||||
glutil::uniform_matrix(0, m_p_camera->get_world_to_view_matrix());
|
||||
CHECK_GL_ERR();
|
||||
glutil::uniform_lights(4, m_lights);
|
||||
CHECK_GL_ERR();
|
||||
glutil::uniform_uint(68, (unsigned int)m_lights.size());
|
||||
CHECK_GL_ERR();
|
||||
glutil::uniform_vec3(69, m_p_camera->get_position());
|
||||
CHECK_GL_ERR();
|
||||
glutil::uniform_vec3(4, m_p_camera->get_position());
|
||||
glutil::uniform_uint(5, (unsigned int)m_lights.size());
|
||||
glutil::uniform_lights(6, m_lights);
|
||||
for (auto iter = m_batches.begin(); iter != m_batches.end(); ++iter)
|
||||
{
|
||||
iter->render();
|
||||
}
|
||||
CHECK_GL_ERR();
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ namespace charcoal
|
||||
{
|
||||
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>
|
||||
{
|
||||
public:
|
||||
@ -30,13 +31,17 @@ namespace charcoal
|
||||
protected:
|
||||
void set_camera(const Camera* p_camera) { m_p_camera = p_camera; }
|
||||
|
||||
void add_light(
|
||||
Light& add_light(
|
||||
const Position& position,
|
||||
const ColorRGB& ambient,
|
||||
const ColorRGB& diffuse
|
||||
const Light::Power& power,
|
||||
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:
|
||||
|
@ -1,21 +1,32 @@
|
||||
#version 430
|
||||
layout(location = 0) in vec3 vertex_position;
|
||||
layout(location = 1) in vec3 vertex_normal;
|
||||
layout(location = 2) in float vertex_specular_exponent;
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
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 = 0) uniform mat4 world_to_projection;
|
||||
|
||||
out vec3 fragment_position;
|
||||
out vec3 fragment_normal;
|
||||
out float fragment_specular_exponent;
|
||||
out Fragment fragment;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 model_position = model_to_world * vec4(vertex_position, 1.0);
|
||||
vec4 model_normal = model_to_world * vec4(vertex_normal, 0.0);
|
||||
vec4 model_position = model_to_world * vec4(vertex.position, 1.0);
|
||||
vec4 model_normal = model_to_world * vec4(vertex.normal, 0.0);
|
||||
gl_Position = world_to_projection * model_position;
|
||||
fragment_position = model_position.xyz;
|
||||
fragment_normal = model_normal.xyz;
|
||||
fragment_specular_exponent = vertex_specular_exponent;
|
||||
fragment.position = model_position.xyz;
|
||||
fragment.normal = model_normal.xyz;
|
||||
fragment.material = vertex.material;
|
||||
}
|
@ -16,11 +16,11 @@ namespace charcoal
|
||||
namespace meshgenerator
|
||||
{
|
||||
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)
|
||||
{
|
||||
mesh->vertices[i].set_specular_exponent(specular_exponent);
|
||||
mesh->vertices[i].set_material(material);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
@ -7,9 +7,9 @@
|
||||
MyBuiltinLitScene::MyBuiltinLitScene(Application& application)
|
||||
: LitScene(application),
|
||||
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),
|
||||
2
|
||||
Material(1.0f, 1.0f, 0.2f, 1.0f)
|
||||
), 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)),
|
||||
@ -18,8 +18,14 @@ MyBuiltinLitScene::MyBuiltinLitScene(Application& application)
|
||||
add_prerenderable(&m_camera);
|
||||
set_camera(&m_camera);
|
||||
|
||||
// Something is off here... The light seems to be rotating...
|
||||
add_light(Position(0.0f, 2.0f, -2.0f), ColorRGB(0.2f, 0.2f, 0.2f), ColorRGB(1.0f, 1.0f, 1.0f));
|
||||
add_light(
|
||||
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)
|
||||
@ -40,7 +46,7 @@ void MyBuiltinLitScene::update(float delta_time, clock_t clock)
|
||||
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user