From: Daniel Karbach Date: Sun, 12 Nov 2017 19:18:38 +0000 (+0100) Subject: multiple light sources X-Git-Url: http://git.localhorst.tv/?p=blobs.git;a=commitdiff_plain;h=64d455cba09900ef6ad19d1f60b72908153bae00 multiple light sources --- diff --git a/src/app/states.cpp b/src/app/states.cpp index b9fc57a..86b2e82 100644 --- a/src/app/states.cpp +++ b/src/app/states.cpp @@ -56,10 +56,35 @@ void MasterState::OnKeyDown(const SDL_KeyboardEvent &e) { } void MasterState::OnRender(graphics::Viewport &viewport) { - glm::dmat4 ppos = cam.Model(**sim.Suns().begin()); assets.shaders.planet_surface.Activate(); assets.shaders.planet_surface.SetTexture(assets.textures.tiles); - assets.shaders.planet_surface.SetLight(glm::vec3(cam.View() * ppos[3]), glm::vec3(1.0f, 1.0f, 1.0f), 1.0e6f); + + int num_lights = 0; + for (auto sun : sim.Suns()) { + // TODO: source sun's light color and strength + assets.shaders.planet_surface.SetLight( + num_lights, + glm::vec3(cam.View() * cam.Model(*sun)[3]), + glm::vec3(1.0f, 1.0f, 1.0f), + 1.0e6f); + ++num_lights; + if (num_lights >= graphics::PlanetSurface::MAX_LIGHTS) { + break; + } + } + for (auto planet : sim.Planets()) { + // TODO: indirect light from planets, calculate strength and get color somehow + assets.shaders.planet_surface.SetLight( + num_lights, + glm::vec3(cam.View() * cam.Model(*planet)[3]), + glm::vec3(1.0f, 1.0f, 1.0f), + 10.0f); + ++num_lights; + if (num_lights >= graphics::PlanetSurface::MAX_LIGHTS) { + break; + } + } + assets.shaders.planet_surface.SetNumLights(num_lights); for (auto planet : sim.Planets()) { assets.shaders.planet_surface.SetMVP(cam.Model(*planet), cam.View(), cam.Projection()); diff --git a/src/graphics/PlanetSurface.hpp b/src/graphics/PlanetSurface.hpp index 2482703..8e98875 100644 --- a/src/graphics/PlanetSurface.hpp +++ b/src/graphics/PlanetSurface.hpp @@ -13,6 +13,9 @@ class ArrayTexture; class PlanetSurface { +public: + static constexpr int MAX_LIGHTS = 8; + public: PlanetSurface(); ~PlanetSurface(); @@ -29,7 +32,8 @@ public: void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept; void SetNormal(const glm::vec3 &) noexcept; void SetTexture(ArrayTexture &) noexcept; - void SetLight(const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept; + void SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept; + void SetNumLights(int n) noexcept; const glm::mat4 &M() const noexcept { return m; } const glm::mat4 &V() const noexcept { return v; } @@ -40,6 +44,8 @@ public: private: Program prog; + int num_lights; + glm::mat4 m; glm::mat4 v; glm::mat4 p; @@ -52,9 +58,8 @@ private: GLuint sampler_handle; GLuint normal_handle; - GLuint light_position_handle; - GLuint light_color_handle; - GLuint light_strength_handle; + GLuint num_lights_handle; + GLuint light_handle[MAX_LIGHTS * 3]; }; diff --git a/src/graphics/Program.hpp b/src/graphics/Program.hpp index 7e0e93b..2add96c 100644 --- a/src/graphics/Program.hpp +++ b/src/graphics/Program.hpp @@ -5,6 +5,7 @@ #include #include +#include #include @@ -29,7 +30,9 @@ public: void Log(std::ostream &) const; GLint AttributeLocation(const GLchar *name) const noexcept; + GLint AttributeLocation(const std::string &name) const noexcept; GLint UniformLocation(const GLchar *name) const noexcept; + GLint UniformLocation(const std::string &name) const noexcept; void Uniform(GLint, GLint) noexcept; void Uniform(GLint, float) noexcept; diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index d771d9f..573e90c 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -142,10 +142,18 @@ GLint Program::AttributeLocation(const GLchar *name) const noexcept { return glGetAttribLocation(handle, name); } +GLint Program::AttributeLocation(const std::string &name) const noexcept { + return AttributeLocation(name.c_str()); +} + GLint Program::UniformLocation(const GLchar *name) const noexcept { return glGetUniformLocation(handle, name); } +GLint Program::UniformLocation(const std::string &name) const noexcept { + return UniformLocation(name.c_str()); +} + void Program::Uniform(GLint loc, GLint val) noexcept { glUniform1i(loc, val); @@ -168,6 +176,8 @@ void Program::Uniform(GLint loc, const glm::mat4 &val) noexcept { } +constexpr int PlanetSurface::MAX_LIGHTS; + PlanetSurface::PlanetSurface() : prog() { prog.LoadShader( @@ -205,24 +215,28 @@ PlanetSurface::PlanetSurface() "uniform sampler2DArray tex_sampler;\n" "uniform vec3 normal;\n" - "uniform LightSource light;\n" + "uniform int num_lights;\n" + "uniform LightSource light[8];\n" "out vec3 color;\n" "void main() {\n" "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n" - "vec3 to_light = light.position - vtx_viewspace;\n" - "float distance = length(to_light);\n" - "vec3 light_dir = normalize(to_light);\n" - "float attenuation = light.strength / (distance * distance);\n" - "vec3 ambient = tex_color * vec3(0.01, 0.01, 0.01);\n" - "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light.color * tex_color;\n" - "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n" - "vec3 specular = vec3(0.0, 0.0, 0.0);\n" - "if (dot(normal, light_dir) >= 0.0) {\n" - "attenuation * light.color * pow(max(0.0, dot(reflect(-light_dir, normal), view_dir)), 25.0);\n" + "vec3 total_light = tex_color * vec3(0.01, 0.01, 0.01);\n" + "for (int i = 0; i < num_lights; ++i) {\n" + "vec3 to_light = light[i].position - vtx_viewspace;\n" + "float distance = length(to_light) + length(vtx_viewspace);\n" + "vec3 light_dir = normalize(to_light);\n" + "float attenuation = light[i].strength / (distance * distance);\n" + "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * tex_color;\n" + "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n" + "vec3 specular = vec3(0.0, 0.0, 0.0);\n" + "if (dot(normal, light_dir) >= 0.0) {\n" + "attenuation * light[i].color * pow(max(0.0, dot(reflect(-light_dir, normal), view_dir)), 25.0);\n" + "}\n" + "total_light = total_light + diffuse + specular;\n" "}\n" - "color = ambient + diffuse + specular;\n" + "color = total_light;\n" "}\n" ); prog.Link(); @@ -235,9 +249,12 @@ PlanetSurface::PlanetSurface() mvp_handle = prog.UniformLocation("MVP"); sampler_handle = prog.UniformLocation("tex_sampler"); normal_handle = prog.UniformLocation("normal"); - light_position_handle = prog.UniformLocation("light.position"); - light_color_handle = prog.UniformLocation("light.color"); - light_strength_handle = prog.UniformLocation("light.strength"); + num_lights_handle = prog.UniformLocation("num_lights"); + for (int i = 0; i < MAX_LIGHTS; ++i) { + light_handle[3 * i + 0] = prog.UniformLocation("light[" + std::to_string(i) + "].position"); + light_handle[3 * i + 1] = prog.UniformLocation("light[" + std::to_string(i) + "].color"); + light_handle[3 * i + 2] = prog.UniformLocation("light[" + std::to_string(i) + "].strength"); + } } PlanetSurface::~PlanetSurface() { @@ -272,10 +289,14 @@ void PlanetSurface::SetTexture(ArrayTexture &tex) noexcept { prog.Uniform(sampler_handle, GLint(0)); } -void PlanetSurface::SetLight(const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept { - prog.Uniform(light_position_handle, pos); - prog.Uniform(light_color_handle, color); - prog.Uniform(light_strength_handle, strength); +void PlanetSurface::SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept { + prog.Uniform(light_handle[3 * n + 0], pos); + prog.Uniform(light_handle[3 * n + 1], color); + prog.Uniform(light_handle[3 * n + 2], strength); +} + +void PlanetSurface::SetNumLights(int n) noexcept { + prog.Uniform(num_lights_handle, std::min(MAX_LIGHTS, n)); }