Materials.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m18s
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m18s
This commit is contained in:
@@ -13,14 +13,17 @@ namespace JGL {
|
||||
|
||||
class JGL::LightBase {
|
||||
protected:
|
||||
/* The 4th number represents whether the light is a positional light.
|
||||
* In OpenGL, You can have positional lights, Like Point Lights or Spot Lights,
|
||||
* Or global lights, Like the sun. */
|
||||
Vector4 position = {0, 0, 0, 1};
|
||||
Color4 ambient = {0, 0, 0, 0};
|
||||
Color4 diffuse = {0, 0, 0, 0};
|
||||
Color4 specular = {0, 0, 0, 0};
|
||||
|
||||
float constant_attenuation;
|
||||
float linear_attenuation;
|
||||
float quadratic_attenuation;
|
||||
float constant_attenuation = 1;
|
||||
float linear_attenuation = 0;
|
||||
float quadratic_attenuation = 0;
|
||||
public:
|
||||
[[nodiscard]] Vector4 GetPosition() const;
|
||||
[[nodiscard]] Color4 GetAmbient() const;
|
||||
|
@@ -1,4 +1,19 @@
|
||||
/// A simple wrapper for OpenGL materials. Lets you set things such as the "shininess" of your elements.
|
||||
class Material {
|
||||
|
||||
#include <Color4.hpp>
|
||||
#include <glad/glad.h>
|
||||
namespace JGL {
|
||||
class Material;
|
||||
}
|
||||
class JGL::Material {
|
||||
public:
|
||||
Color4 ambient_ref;
|
||||
Color4 diffuse_ref;
|
||||
Color4 specular_ref;
|
||||
Color4 emission;
|
||||
float shininess;
|
||||
public:
|
||||
Material(const Color4& ambient_reflection, const Color4& diffuse_reflection, const Color4& specular_reflection, const Color4& light_emission, float& shine);
|
||||
/// @param material Material to use.
|
||||
static void SetActiveMaterial(const Material& material);
|
||||
};
|
54
src/internals/internals.cpp
Normal file
54
src/internals/internals.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "internals.h"
|
||||
#include <J3ML/LinearAlgebra/Vector4.hpp>
|
||||
#include <JGL/types/Light.h>
|
||||
|
||||
// TODO handle the case that a required light is in the list of optional lights.
|
||||
void JGL::J3D::SelectLights(const Vector3& position) {
|
||||
std::array<const LightBase*, 8> result = required_lights;
|
||||
|
||||
unsigned int required_light_count = 0;
|
||||
for (const auto& i : result)
|
||||
if (i) required_light_count++;
|
||||
|
||||
// If there is optional lights.
|
||||
if (!optional_lights.empty()) {
|
||||
// The number of lights we need to solve for
|
||||
unsigned int remaining_lights = 8 - required_light_count;
|
||||
|
||||
std::vector<std::pair<float, const LightBase*>> light_influence;
|
||||
for (const auto* light: optional_lights)
|
||||
light_influence.emplace_back(light->GetAttenuationAtPosition(position), light);
|
||||
|
||||
// Sort by biggest influence.
|
||||
std::sort(light_influence.begin(), light_influence.end(),
|
||||
[](const auto &a, const auto &b) { return a.first > b.first; });
|
||||
|
||||
// Add in optional lights.
|
||||
for (unsigned int i = 0; i < remaining_lights && i < light_influence.size(); i++)
|
||||
result[required_light_count++] = light_influence[i].second;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < result.size(); i++) {
|
||||
// Terminate early if we have less than 8 lights.
|
||||
if (!result[i])
|
||||
break;
|
||||
|
||||
Vector4 ambient = { result[i]->GetAmbient().RN(), result[i]->GetAmbient().BN(), result[i]->GetAmbient().GN(), result[i]->GetAmbient().AN() };
|
||||
Vector4 diffuse = { result[i]->GetDiffuse().RN(), result[i]->GetDiffuse().BN(), result[i]->GetDiffuse().GN(), result[i]->GetDiffuse().AN() };
|
||||
Vector4 specular = { result[i]->GetSpecular().RN(), result[i]->GetSpecular().BN(), result[i]->GetSpecular().GN(), result[i]->GetSpecular().AN() };
|
||||
GLenum current_light = GL_LIGHT0 + i;
|
||||
|
||||
glEnable(GL_LIGHT0 + i);
|
||||
|
||||
// How the light will affect different materials.
|
||||
glLightfv(current_light, GL_POSITION, result[i]->GetPosition().ptr());
|
||||
glLightfv(current_light, GL_AMBIENT, ambient.ptr());
|
||||
glLightfv(current_light, GL_DIFFUSE, diffuse.ptr());
|
||||
glLightfv(current_light, GL_SPECULAR, specular.ptr());
|
||||
|
||||
// How far the light goes.
|
||||
glLightf(current_light, GL_CONSTANT_ATTENUATION, result[i]->GetConstantAttenuation());
|
||||
glLightf(current_light, GL_LINEAR_ATTENUATION, result[i]->GetLinearAttenuation());
|
||||
glLightf(current_light, GL_QUADRATIC_ATTENUATION, result[i]->GetQuadraticAttenuation());
|
||||
}
|
||||
}
|
@@ -1,9 +1,11 @@
|
||||
/// Things used in J2D and J3D that should not be exposed to the user of the library.
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <JGL/types/RenderTarget.h>
|
||||
#include <JGL/types/Light.h>
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace JGL {
|
||||
inline constexpr std::array<const LightBase*, 8> empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
@@ -45,64 +47,5 @@ namespace JGL::J3D {
|
||||
inline std::vector<const LightBase*> optional_lights;
|
||||
inline float far_plane = 0;
|
||||
inline float fov = 0;
|
||||
|
||||
|
||||
// TODO handle the case that a required light is in the list of optional lights.
|
||||
inline void SelectLights(const Vector3& position) {
|
||||
std::array<const LightBase*, 8> result = {};
|
||||
|
||||
unsigned int required_light_count = 0;
|
||||
for (const auto* light : required_lights)
|
||||
if (light)
|
||||
result[required_light_count++] = light;
|
||||
else
|
||||
break;
|
||||
|
||||
// If there is optional lights.
|
||||
if (!optional_lights.empty()) {
|
||||
// The number of lights we need to solve for
|
||||
unsigned int remaining_lights = 8 - required_light_count;
|
||||
|
||||
std::vector<std::pair<float, const LightBase*>> light_influence;
|
||||
for (const auto* light: optional_lights) {
|
||||
float influence = 0.0f;
|
||||
if (auto *point_light = dynamic_cast<const PointLight*>(light))
|
||||
influence = point_light->GetAttenuationAtPosition(position);
|
||||
|
||||
else if (auto *spot_light = dynamic_cast<const SpotLight*>(light))
|
||||
influence = spot_light->GetAttenuationAtPosition(position);
|
||||
else
|
||||
Logger::Warning("Couldn't determine the light type.");
|
||||
|
||||
light_influence.emplace_back(influence, light);
|
||||
}
|
||||
|
||||
// Sort by biggest influence.
|
||||
std::sort(light_influence.begin(), light_influence.end(),
|
||||
[](const auto &a, const auto &b) { return a.first > b.first; });
|
||||
|
||||
// Add in optional lights.
|
||||
for (unsigned int i = 0; i < remaining_lights && i < light_influence.size(); i++)
|
||||
result[required_light_count++] = light_influence[i].second;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < result.size(); i++) {
|
||||
// If we've reached the end of an array with less than 8 lights.
|
||||
if (i > required_light_count)
|
||||
break;
|
||||
|
||||
Vector4 ambient = { result[i]->GetAmbient().RN(), result[i]->GetAmbient().BN(), result[i]->GetAmbient().GN(), result[i]->GetAmbient().AN() };
|
||||
Vector4 diffuse = { result[i]->GetDiffuse().RN(), result[i]->GetDiffuse().BN(), result[i]->GetDiffuse().GN(), result[i]->GetDiffuse().AN() };
|
||||
Vector4 specular = { result[i]->GetSpecular().RN(), result[i]->GetSpecular().BN(), result[i]->GetSpecular().GN(), result[i]->GetSpecular().AN() };
|
||||
GLenum current_light = GL_LIGHT0 + i;
|
||||
|
||||
glEnable(GL_LIGHT0 + i);
|
||||
glLightfv(current_light, GL_POSITION, result[i]->GetPosition().ptr());
|
||||
glLightfv(current_light, GL_AMBIENT, ambient.ptr());
|
||||
glLightfv(current_light, GL_DIFFUSE, diffuse.ptr());
|
||||
glLightfv(current_light, GL_SPECULAR, specular.ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SelectLights(const Vector3& position);
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
#include <JGL/types/Material.h>
|
||||
#include <J3ML/LinearAlgebra/Vector4.hpp>
|
||||
|
||||
JGL::Material::Material(const Color4& ambient_reflection, const Color4& diffuse_reflection, const Color4& specular_reflection, const Color4& light_emission, float& shine) {
|
||||
ambient_ref = ambient_reflection;
|
||||
diffuse_ref = diffuse_reflection;
|
||||
specular_ref = specular_reflection;
|
||||
emission = light_emission;
|
||||
shininess = shine;
|
||||
}
|
||||
|
||||
void JGL::Material::SetActiveMaterial(const Material& material) {
|
||||
Vector4 ambient = { material.ambient_ref.RN(), material.ambient_ref.BN(), material.ambient_ref.GN(), material.ambient_ref.AN() };
|
||||
Vector4 diffuse = { material.diffuse_ref.RN(), material.diffuse_ref.BN(), material.diffuse_ref.GN(), material.diffuse_ref.AN() };
|
||||
Vector4 specular = { material.specular_ref.RN(), material.specular_ref.BN(), material.specular_ref.GN(), material.specular_ref.AN() };
|
||||
Vector4 emission = { material.emission.RN(), material.emission.BN(), material.emission.GN(), material.emission.AN() };
|
||||
|
||||
// Determine which faces we're going to apply this material to.
|
||||
GLenum face = GL_FRONT;
|
||||
if (glIsEnabled(GL_CULL_FACE)) {
|
||||
GLint current; glGetIntegerv(GL_CULL_FACE_MODE, ¤t);
|
||||
if (current == GL_FRONT)
|
||||
face = GL_BACK;
|
||||
}
|
||||
|
||||
glMaterialfv(face, GL_AMBIENT, ambient.ptr());
|
||||
glMaterialfv(face, GL_DIFFUSE, diffuse.ptr());
|
||||
glMaterialfv(face, GL_SPECULAR, specular.ptr());
|
||||
glMaterialfv(face, GL_EMISSION, emission.ptr());
|
||||
glMaterialf(face, GL_SHININESS, material.shininess);
|
||||
}
|
||||
|
Reference in New Issue
Block a user