Implement sorting blending
This commit is contained in:
parent
19d116ef65
commit
6944d0ac6d
|
@ -51,6 +51,8 @@ else()
|
||||||
target_link_libraries(simpleengine PUBLIC assimp)
|
target_link_libraries(simpleengine PUBLIC assimp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Link resources
|
||||||
|
target_link_libraries(simpleengine PUBLIC cmrc::base)
|
||||||
target_link_libraries(simpleengine PRIVATE simpleengine_resources)
|
target_link_libraries(simpleengine PRIVATE simpleengine_resources)
|
||||||
|
|
||||||
# Include some dependencies' include directories
|
# Include some dependencies' include directories
|
||||||
|
|
2
cmrc
2
cmrc
|
@ -1 +1 @@
|
||||||
Subproject commit a64bea50c05594c8e7cf1f08e441bb9507742e2e
|
Subproject commit e386a629eb537d384811e598a3c96b9ca928f65e
|
|
@ -9,17 +9,17 @@ target_sources(dev_testing PRIVATE ${source_list})
|
||||||
target_include_directories(dev_testing PUBLIC include)
|
target_include_directories(dev_testing PUBLIC include)
|
||||||
|
|
||||||
# Embed shaders
|
# Embed shaders
|
||||||
file(GLOB_RECURSE shaders_list resources/shaders/*.glsl)
|
#file(GLOB_RECURSE shaders_list resources/shaders/*.glsl)
|
||||||
cmrc_add_resource_library(
|
#cmrc_add_resource_library(
|
||||||
resource_shaders
|
# resource_shaders
|
||||||
WHENCE resources/shaders
|
# WHENCE resources/shaders
|
||||||
PREFIX shaders
|
# PREFIX shaders
|
||||||
${shaders_list}
|
# ${shaders_list}
|
||||||
)
|
#)
|
||||||
|
|
||||||
# Link simpleengine
|
# Link simpleengine
|
||||||
target_link_libraries(dev_testing PUBLIC simpleengine)
|
target_link_libraries(dev_testing PUBLIC simpleengine)
|
||||||
target_link_libraries(dev_testing PRIVATE resource_shaders)
|
#target_link_libraries(dev_testing PRIVATE resource_shaders)
|
||||||
|
|
||||||
# Set standard to C++20
|
# Set standard to C++20
|
||||||
set_target_properties(dev_testing PROPERTIES CXX_STANDARD 20 CXX_EXTENSIONS OFF)
|
set_target_properties(dev_testing PROPERTIES CXX_STANDARD 20 CXX_EXTENSIONS OFF)
|
|
@ -1,46 +0,0 @@
|
||||||
#version 440
|
|
||||||
|
|
||||||
in vec3 vs_position;
|
|
||||||
in mat4 vs_transform;
|
|
||||||
in vec2 vs_texcoord;
|
|
||||||
in vec3 vs_normal;
|
|
||||||
in vec3 vs_to_light;
|
|
||||||
in vec3 vs_to_camera;
|
|
||||||
|
|
||||||
uniform bool texture_is_set;
|
|
||||||
uniform sampler2D vs_texture;
|
|
||||||
uniform vec3 light_color;
|
|
||||||
uniform float shine_damper;
|
|
||||||
uniform float reflectivity;
|
|
||||||
|
|
||||||
out vec4 fs_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// Lighting
|
|
||||||
vec3 unit_normal = normalize(vs_normal);
|
|
||||||
vec3 unit_light_vector = normalize(vs_to_light);
|
|
||||||
|
|
||||||
float dot_prod = dot(unit_normal, unit_light_vector);
|
|
||||||
float brightness = max(dot_prod, 0.f);
|
|
||||||
vec3 diffuse = brightness * light_color;
|
|
||||||
|
|
||||||
// Specular lighting
|
|
||||||
// only do all this math is reflectivity is > 0
|
|
||||||
vec3 final_specular = vec3(0.f);
|
|
||||||
if (reflectivity > 0) {
|
|
||||||
vec3 unit_vector_to_camera = normalize(vs_to_camera);
|
|
||||||
vec3 light_direction = -unit_vector_to_camera;
|
|
||||||
vec3 reflected_light_dir = reflect(light_direction, unit_normal);
|
|
||||||
float specular_factor = dot(reflected_light_dir, unit_vector_to_camera);
|
|
||||||
specular_factor = max(specular_factor, 0.f);
|
|
||||||
float damped_specular = pow(specular_factor, shine_damper);
|
|
||||||
final_specular = damped_specular * reflectivity * light_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture_is_set) {
|
|
||||||
//fs_color = vec4(0.5 * unit_normal + vec3(0.5), 1.f); // Visualize normals
|
|
||||||
fs_color = vec4(diffuse, 1.f) * texture(vs_texture, vs_texcoord) + vec4(final_specular, 1.f);
|
|
||||||
} else {
|
|
||||||
fs_color = vec4(diffuse, 1.f) + vec4(final_specular, 1.f);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
#version 440
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 vertex_position;
|
|
||||||
layout (location = 1) in vec2 vertex_texcoord;
|
|
||||||
layout (location = 2) in vec3 vertex_normal;
|
|
||||||
|
|
||||||
out vec3 vs_position;
|
|
||||||
out vec2 vs_texcoord;
|
|
||||||
out mat4 vs_transform;
|
|
||||||
out vec3 vs_normal;
|
|
||||||
out vec3 vs_to_light;
|
|
||||||
out vec3 vs_to_camera;
|
|
||||||
|
|
||||||
uniform mat4 transform_matrix;
|
|
||||||
uniform mat4 view_matrix;
|
|
||||||
uniform mat4 projection_matrix;
|
|
||||||
uniform vec3 light_position;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 world_pos = (transform_matrix * vec4(vertex_position, 1.f));
|
|
||||||
|
|
||||||
vs_position = world_pos.xyz;
|
|
||||||
vs_transform = transform_matrix;
|
|
||||||
vs_texcoord = vertex_texcoord;
|
|
||||||
|
|
||||||
gl_Position = projection_matrix * view_matrix * world_pos;
|
|
||||||
|
|
||||||
vs_normal = (transform_matrix * vec4(vertex_normal, 0.f)).xyz;
|
|
||||||
vs_to_light = light_position - world_pos.xyz;
|
|
||||||
vs_to_camera = (inverse(view_matrix) * vec4(0.f, 0.f, 0.f, 1.f)).xyz - world_pos.xyz;
|
|
||||||
}
|
|
|
@ -31,9 +31,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <cmrc/cmrc.hpp>
|
|
||||||
CMRC_DECLARE(resource_shaders);
|
|
||||||
|
|
||||||
namespace se = simpleengine;
|
namespace se = simpleengine;
|
||||||
|
|
||||||
class FPSCounterEvent : public se::Event {
|
class FPSCounterEvent : public se::Event {
|
||||||
|
@ -61,141 +58,43 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string read_resource_shader(const std::string &path) {
|
|
||||||
auto fs = cmrc::resource_shaders::get_filesystem();
|
|
||||||
cmrc::file vertex_file = fs.open(path);
|
|
||||||
|
|
||||||
return std::string(vertex_file.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
se::Game game(640, 480, "SimpleEngine 3D OpenGL - Developer Testing", GLFW_OPENGL_CORE_PROFILE, 4, 4, false);
|
se::Game game(640, 480, "SimpleEngine 3D OpenGL - Developer Testing", GLFW_OPENGL_CORE_PROFILE, 4, 4, false);
|
||||||
|
|
||||||
/* se::gfx::Texture wall_texture("resources/wall.jpg");
|
|
||||||
se::gfx::Texture crate_texture("resources/container.jpg", true, true); */
|
|
||||||
|
|
||||||
// Load core shaders from SimpleEngine resources
|
// Load core shaders from SimpleEngine resources
|
||||||
se::gfx::shaders::Core3dShader core_shader;
|
se::gfx::shaders::Core3dShader core_shader;
|
||||||
|
|
||||||
auto white_texture = se::gfx::Texture::white_texture();
|
auto camera = std::make_shared<se::Camera>(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0));
|
||||||
// white_texture.shine_damper = 10;
|
game.add_event(camera);
|
||||||
// white_texture.reflectivity = 1;
|
|
||||||
/* auto dragon = std::make_shared<se::objects_3d::Mesh>(game.get_window(), core_shader, white_texture,
|
|
||||||
"examples/dev_testing/resources/dragon.obj"); dragon->translate(0.f, -5.f, -15.f); game.add_event(dragon); */
|
|
||||||
|
|
||||||
/* auto cube = std::make_shared<se::objects_3d::Mesh>(game.get_window(), core_shader, white_texture,
|
|
||||||
"examples/dev_testing/resources/cube.obj"); cube->translate(0.f, -5.f, -15.f); game.add_event(cube);
|
|
||||||
|
|
||||||
se::gfx::Texture grass("examples/dev_testing/resources/grass.png");
|
|
||||||
auto terrain = std::make_shared<se::objects_3d::Terrain>(game.get_window(), core_shader, grass, 0, 0);
|
|
||||||
terrain->translate(0.f, -5.f, -15.f);
|
|
||||||
game.add_event(terrain); */
|
|
||||||
|
|
||||||
/* se::gfx::Texture stall_texture("examples/dev_testing/resources/stallTextureb.png");
|
|
||||||
auto stall = std::make_shared<se::objects_3d::Mesh>(game.get_window(), core_shader, stall_texture,
|
|
||||||
"examples/dev_testing/resources/stall.obj"); stall->translate(10.f, -5.f, 0.f); stall->rotate_y(90.f);
|
|
||||||
game.add_event(stall); */
|
|
||||||
|
|
||||||
/* std::vector<se::Vertex> square_vertices = {
|
|
||||||
{ se::Vectorf(0.5f, 0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right
|
|
||||||
{ se::Vectorf(0.5f, -0.5f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, // bottom right
|
|
||||||
{ se::Vectorf(-0.5f, -0.5f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.5f, 1.0f) }, // bottom left
|
|
||||||
{ se::Vectorf(-0.5f, 0.5f, -1.f), glm::vec3(.5f, 0.5f, 0.f), glm::vec2(0.5f, 1.0f) }, // top left
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<GLuint> indicies = {
|
|
||||||
0, 1, 3,
|
|
||||||
1, 2, 3
|
|
||||||
};
|
|
||||||
|
|
||||||
auto square = std::make_shared<se::gfx::Model>(game.get_window(), core_shader, square_vertices, indicies);
|
|
||||||
square->translate(1.25f, 0.f, -1.f);
|
|
||||||
//square->rotate_y(90.f);
|
|
||||||
//square->scale(.75f);
|
|
||||||
game.add_event(square); */
|
|
||||||
|
|
||||||
/* se::gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png");
|
|
||||||
auto cube = std::make_shared<se::objects_3d::Mesh>(game.get_window(), core_shader, white_texture,
|
|
||||||
"examples/dev_testing/resources/cube.obj"); cube->translate(-1.25f, 0.f, -1.f); game.add_event(cube); */
|
|
||||||
|
|
||||||
/* std::vector<se::Vertex> tri_vertices = {
|
|
||||||
{ se::Vectorf(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right
|
|
||||||
{ se::Vectorf(0.5f, -0.5f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, // bottom right
|
|
||||||
{ se::Vectorf(0.f, 0.5f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.5f, 1.0f) }, // bottom left
|
|
||||||
};
|
|
||||||
|
|
||||||
auto tri = std::make_shared<se::gfx::Model>(game.get_window(), core_shader, tri_vertices);
|
|
||||||
tri->translate(-1.25f, 0.f, -1.f);
|
|
||||||
tri->scale(.75f);
|
|
||||||
game.add_event(tri); */
|
|
||||||
|
|
||||||
std::vector<se::LitVertex> cube_vertices = {
|
|
||||||
{se::Vectorf(-1.f, -1.f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f)},
|
|
||||||
{se::Vectorf(1.f, -1.f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f)},
|
|
||||||
{se::Vectorf(1.f, 1.f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 0.f)},
|
|
||||||
{se::Vectorf(-1.f, 1.f, -1.f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 0.f)},
|
|
||||||
{se::Vectorf(-1, -1, -1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 0.f)},
|
|
||||||
|
|
||||||
{se::Vectorf(-1, -1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 1.f)},
|
|
||||||
{se::Vectorf(1, -1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 1.f)},
|
|
||||||
{se::Vectorf(1, 1, 1), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 1.f)},
|
|
||||||
{se::Vectorf(-1, 1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 1.f)},
|
|
||||||
{se::Vectorf(-1, -1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 1.f)},
|
|
||||||
|
|
||||||
{se::Vectorf(-1, 1, -1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, -1.f)},
|
|
||||||
{se::Vectorf(1, 1, -1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, -1.f)},
|
|
||||||
|
|
||||||
{se::Vectorf(-1, 1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 2.f)},
|
|
||||||
{se::Vectorf(1, 1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 2.f)},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<GLuint> cube_indicies = {0, 1, 5, 5, 1, 6, 1, 2, 6, 6, 2, 7, 2, 3, 7, 7, 3, 8,
|
|
||||||
3, 4, 8, 8, 4, 9, 10, 11, 0, 0, 11, 1, 5, 6, 12, 12, 6, 13};
|
|
||||||
|
|
||||||
// Create a renderer
|
// Create a renderer
|
||||||
auto renderer = std::make_shared<se::gfx::Renderer>(game.get_window(), core_shader);
|
auto renderer = std::make_shared<se::gfx::Renderer>(game.get_window(), core_shader, camera);
|
||||||
|
renderer->initialize();
|
||||||
game.add_renderable(renderer);
|
game.add_renderable(renderer);
|
||||||
|
|
||||||
// Create a Scene and give it the renderer
|
// Create a Scene and give it the renderer
|
||||||
auto scene = std::make_shared<se::Scene>(renderer);
|
auto scene = std::make_shared<se::Scene>(renderer);
|
||||||
game.add_event(scene);
|
game.add_event(scene);
|
||||||
|
|
||||||
|
se::ecs::Entity other_e = scene->create_entity();
|
||||||
|
other_e.add_component<se::ModelComponent>("examples/dev_testing/resources/transparent_window.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE | simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_TRANSPARENT);
|
||||||
|
auto &other_transform = other_e.add_component<se::TransformComponent>();
|
||||||
|
other_transform.translate(5.f, 0.5f, 1.f);
|
||||||
|
|
||||||
// Create an Entity in the Scene and add components to it.
|
// Create an Entity in the Scene and add components to it.
|
||||||
se::ecs::Entity entity = scene->create_entity();
|
se::ecs::Entity entity = scene->create_entity();
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/dragon.obj");
|
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/stall.obj");
|
|
||||||
|
|
||||||
// Backpack model required vertically flipped texture coords.
|
|
||||||
/* auto& model_comp =
|
|
||||||
entity.add_component<se::ModelComponent>("examples/dev_testing/resources/backpack/backpack.obj");
|
|
||||||
model_comp.model.vertically_flip_tex_coords(); */
|
|
||||||
|
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/viper/viper.obj");
|
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/halot/chief.fbx");
|
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/planks/planks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE);
|
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/planks/planks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE);
|
||||||
entity.add_component<se::ModelComponent>("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE);
|
//entity.add_component<se::ModelComponent>("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE);
|
||||||
|
entity.add_component<se::ModelComponent>("examples/dev_testing/resources/transparent_window.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE | simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_TRANSPARENT);
|
||||||
|
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/scientist/scientist.fbx");
|
|
||||||
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/paradigm/paradigm.fbx");
|
|
||||||
// entity.add_component<se::RotatingComponent>();
|
|
||||||
auto &transform_comp = entity.add_component<se::TransformComponent>();
|
auto &transform_comp = entity.add_component<se::TransformComponent>();
|
||||||
transform_comp.translate(4.f, 0.f, 0.f);
|
transform_comp.translate(4.f, 0.f, 0.f);
|
||||||
// transform_comp.scale(0.05f);
|
|
||||||
// transform_comp.rotate_z(-90.f);
|
|
||||||
// transform_comp.rotate_y(-90.f);
|
|
||||||
// transform_comp.rotate_x(-90.f);
|
|
||||||
|
|
||||||
// Create the entity and add the model component to it.
|
se::ecs::Entity brick_e = scene->create_entity();
|
||||||
/* auto entity = std::make_shared<simpleengine::Entity>();
|
brick_e.add_component<se::ModelComponent>("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE);
|
||||||
entity->add_component<se::MeshComponent>(cube_vertices, cube_indicies, white_material, true);
|
auto &brick_transf = brick_e.add_component<se::TransformComponent>();
|
||||||
entity->translate(3.5f, 0.f, 0.f); */
|
brick_transf.translate(6.f, -0.5f, 1.f);
|
||||||
|
|
||||||
/* auto entity = std::make_shared<simpleengine::Entity>();
|
|
||||||
entity->add_component<se::ModelComponent>("examples/dev_testing/resources/dragon.obj");
|
|
||||||
entity->translate(12.f, -4.f, 0.f); */
|
|
||||||
|
|
||||||
auto camera = std::make_shared<se::Camera>(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0));
|
|
||||||
game.add_event(camera);
|
|
||||||
|
|
||||||
auto light = std::make_shared<se::gfx::Light>(core_shader, glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f));
|
auto light = std::make_shared<se::gfx::Light>(core_shader, glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f));
|
||||||
game.add_event(light);
|
game.add_event(light);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "rendering_type.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
#include <assimp/material.h>
|
#include <assimp/material.h>
|
||||||
|
@ -10,6 +11,9 @@
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
class Material {
|
class Material {
|
||||||
public:
|
public:
|
||||||
|
RenderingType rendering_type;
|
||||||
|
|
||||||
|
// TODO: Only one of each texture type.
|
||||||
std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> textures;
|
std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> textures;
|
||||||
|
|
||||||
float ambient_strength;
|
float ambient_strength;
|
||||||
|
@ -32,9 +36,9 @@ namespace simpleengine::gfx {
|
||||||
*/
|
*/
|
||||||
float shine_factor;
|
float shine_factor;
|
||||||
|
|
||||||
Material(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> textures, float shine = 1.f, float specular_scalar = 1.f, float ambient_scalar = 1.f, float diffuse_scalar = 1.f) :
|
Material(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> textures, RenderingType rendering_type, float shine = 1.f,
|
||||||
textures(textures), ambient_strength(ambient_scalar), diffuse_strength(diffuse_scalar), specular_strength(specular_scalar),
|
float specular_scalar = 1.f, float ambient_scalar = 1.f, float diffuse_scalar = 1.f) : textures(textures), rendering_type(rendering_type),
|
||||||
shine_factor(shine) {
|
ambient_strength(ambient_scalar), diffuse_strength(diffuse_scalar), specular_strength(specular_scalar), shine_factor(shine) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace simpleengine::gfx {
|
||||||
MdlProcFlag_FLIP_TEX_COORDS_VERTICALLY = 0b00000001,
|
MdlProcFlag_FLIP_TEX_COORDS_VERTICALLY = 0b00000001,
|
||||||
MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY = 0b00000010,
|
MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY = 0b00000010,
|
||||||
MdlProcFlag_CALCULATE_TANGENT_SPACE = 0b00000100,
|
MdlProcFlag_CALCULATE_TANGENT_SPACE = 0b00000100,
|
||||||
|
MdlProcFlag_TRANSPARENT = 0b00001000,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +41,7 @@ namespace simpleengine::gfx {
|
||||||
gfx::Mesh process_mesh(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMesh* mesh, const aiScene* scene);
|
gfx::Mesh process_mesh(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMesh* mesh, const aiScene* scene);
|
||||||
|
|
||||||
std::unordered_map<aiTextureType, std::vector<Texture>> load_all_textures(aiMaterial* material);
|
std::unordered_map<aiTextureType, std::vector<Texture>> load_all_textures(aiMaterial* material);
|
||||||
std::vector<std::shared_ptr<Texture>> load_material_texture(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color);
|
std::vector<std::shared_ptr<Texture>> load_material_texture(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMaterial* material, aiTextureType type);
|
||||||
protected:
|
protected:
|
||||||
void post_process();
|
void post_process();
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,36 +1,45 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../camera.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "simpleengine/gfx/mesh.h"
|
#include "../renderable.h"
|
||||||
|
#include "rendering_type.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
|
class Mesh;
|
||||||
|
|
||||||
class RenderingJob {
|
class RenderingJob {
|
||||||
public:
|
public:
|
||||||
gfx::Mesh& rendering_mesh;
|
RenderingType rendering_type;
|
||||||
|
gfx::Mesh* rendering_mesh;
|
||||||
glm::mat4 transform_mat;
|
glm::mat4 transform_mat;
|
||||||
|
|
||||||
RenderingJob(gfx::Mesh& mesh, glm::mat4 position) : rendering_mesh(mesh), transform_mat(position) {
|
RenderingJob(RenderingType rendering_type, gfx::Mesh& mesh, glm::mat4 position);
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Renderer : public simpleengine::Renderable {
|
class Renderer : public simpleengine::Renderable {
|
||||||
private:
|
private:
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
protected:
|
||||||
public:
|
public:
|
||||||
|
std::queue<RenderingJob> transparent_render_queue;
|
||||||
|
std::queue<RenderingJob> other_render_queue;
|
||||||
|
|
||||||
std::queue<RenderingJob> rendering_queue;
|
|
||||||
gfx::Shader shader;
|
gfx::Shader shader;
|
||||||
|
std::shared_ptr<Camera> camera;
|
||||||
|
|
||||||
Renderer(GLFWwindow* window, gfx::Shader shader);
|
Renderer(GLFWwindow* window, gfx::Shader shader, std::shared_ptr<Camera> camera);
|
||||||
Renderer(GLFWwindow* window, GLuint shader_program);
|
Renderer(GLFWwindow* window, GLuint shader_program, std::shared_ptr<Camera> camera);
|
||||||
|
|
||||||
void enable_debug();
|
void enable_debug();
|
||||||
|
|
||||||
|
virtual void sort_jobs();
|
||||||
|
virtual void queue_job(RenderingType rendering_type, gfx::Mesh& mesh, glm::mat4 position);
|
||||||
virtual void queue_job(RenderingJob job);
|
virtual void queue_job(RenderingJob job);
|
||||||
virtual void create_job_buffers(RenderingJob& job);
|
virtual void create_job_buffers(RenderingJob& job);
|
||||||
|
|
||||||
|
@ -40,5 +49,16 @@ namespace simpleengine::gfx {
|
||||||
virtual void update(const float& delta_time) override;
|
virtual void update(const float& delta_time) override;
|
||||||
|
|
||||||
virtual void render() override;
|
virtual void render() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Renders a single job.
|
||||||
|
*
|
||||||
|
* @param job The job that will be rendered.
|
||||||
|
* @return true if the job was rendered successfully.
|
||||||
|
* @return false if there was an error when trying to render the job.
|
||||||
|
*/
|
||||||
|
virtual bool render_job(const RenderingJob& job);
|
||||||
|
virtual void render_job_queue(std::queue<RenderingJob>& queue);
|
||||||
|
virtual void render_job_queue(std::map<float, RenderingJob, std::greater<>>& queue);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace simpleengine::gfx {
|
||||||
|
enum RenderingType {
|
||||||
|
RendType_OPAQUE = 0,
|
||||||
|
RendType_TRANSPARENT = 1,
|
||||||
|
};
|
||||||
|
}
|
|
@ -23,39 +23,29 @@ namespace simpleengine::gfx {
|
||||||
TexFlags_FLIP_VERTICALLY = 0b00000010,
|
TexFlags_FLIP_VERTICALLY = 0b00000010,
|
||||||
TexFlags_FLIP_HORIZONTALLY = 0b00000100,
|
TexFlags_FLIP_HORIZONTALLY = 0b00000100,
|
||||||
TexFlags_MIPMAP = 0b00001000,
|
TexFlags_MIPMAP = 0b00001000,
|
||||||
TexFlags_NO_COLOR = 0b00010000,
|
/* TexFlags_NO_COLOR = 0b00010000,
|
||||||
TexFlags_RGB = 0b00100000,
|
TexFlags_RGB = 0b00100000,
|
||||||
TexFlags_RGBA = 0b01000000,
|
TexFlags_RGBA = 0b01000000, */
|
||||||
};
|
};
|
||||||
|
|
||||||
class Texture {
|
class Texture {
|
||||||
private:
|
private:
|
||||||
unsigned char* img_data; // TODO Free this if its not used anymore
|
//unsigned char* img_data; // TODO Free this if its not used anymore
|
||||||
unsigned int texture_id;
|
unsigned int texture_id;
|
||||||
|
|
||||||
unsigned int image_type_gl;
|
unsigned int image_type_gl;
|
||||||
|
|
||||||
Texture() = default;
|
Texture() = default;
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief The default Texture flags not including the color.
|
|
||||||
*
|
|
||||||
* The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP`
|
|
||||||
*
|
|
||||||
* @see simpleengine::gfx::Texture::default_flags
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static constexpr int default_flags_no_color = TexFlags_IMG_2D | TexFlags_MIPMAP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The default Texture flags including the color.
|
* @brief The default Texture flags including the color.
|
||||||
*
|
*
|
||||||
* The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP | TexFlags_RGBA`
|
* The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP`
|
||||||
*
|
*
|
||||||
* @see simpleengine::gfx::Texture::default_flags_no_color
|
* @see simpleengine::gfx::Texture::default_flags_no_color
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static constexpr int default_flags = default_flags_no_color | TexFlags_RGBA;
|
static constexpr int default_flags = TexFlags_IMG_2D | TexFlags_MIPMAP;
|
||||||
|
|
||||||
int height;
|
int height;
|
||||||
int width;
|
int width;
|
||||||
|
|
|
@ -47,8 +47,13 @@ out vec4 fs_color;
|
||||||
vec3 calculate_lighting();
|
vec3 calculate_lighting();
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 lighting = calculate_lighting();
|
// Skip completely transparent fragments.
|
||||||
|
/* vec4 diffuse = texture(u_material.diffuse, vs_texcoord);
|
||||||
|
if (diffuse.a < 0.1) {
|
||||||
|
discard;
|
||||||
|
} */
|
||||||
|
|
||||||
|
vec3 lighting = calculate_lighting();
|
||||||
|
|
||||||
fs_color = vec4(lighting, 1.f) * texture(u_material.diffuse, vs_texcoord);
|
fs_color = vec4(lighting, 1.f) * texture(u_material.diffuse, vs_texcoord);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,7 @@ simpleengine::Game::Game(int w, int h, const std::string& window_name, const int
|
||||||
}
|
}
|
||||||
|
|
||||||
void simpleengine::Game::enable_default_gl_options() const {
|
void simpleengine::Game::enable_default_gl_options() const {
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
//glFrontFace(GL_CW);
|
//glFrontFace(GL_CW);
|
||||||
|
|
||||||
update_enabled_vsync();
|
update_enabled_vsync();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "gfx/model.h"
|
#include "gfx/model.h"
|
||||||
#include "gfx/material.h"
|
#include "gfx/material.h"
|
||||||
|
#include "gfx/rendering_type.h"
|
||||||
#include "gfx/texture.h"
|
#include "gfx/texture.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
|
@ -107,11 +108,17 @@ namespace simpleengine::gfx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the rendering type
|
||||||
|
RenderingType rendering_type = RenderingType::RendType_OPAQUE;
|
||||||
|
if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_TRANSPARENT) {
|
||||||
|
rendering_type = RenderingType::RendType_TRANSPARENT;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a default material and white texture.
|
// Create a default material and white texture.
|
||||||
auto white_texture = gfx::Texture::white_texture();
|
auto white_texture = gfx::Texture::white_texture();
|
||||||
std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> default_textures;
|
std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> default_textures;
|
||||||
default_textures.emplace(white_texture.type, std::vector<std::shared_ptr<Texture>>{ std::make_shared<Texture>(white_texture) });
|
default_textures.emplace(white_texture.type, std::vector<std::shared_ptr<Texture>>{ std::make_shared<Texture>(white_texture) });
|
||||||
gfx::Material mat(default_textures);
|
gfx::Material mat(default_textures, rendering_type);
|
||||||
|
|
||||||
if (mesh->mMaterialIndex >= 0) {
|
if (mesh->mMaterialIndex >= 0) {
|
||||||
std::cout << "TODO: Process model materials!" << std::endl;
|
std::cout << "TODO: Process model materials!" << std::endl;
|
||||||
|
@ -121,17 +128,17 @@ namespace simpleengine::gfx {
|
||||||
|
|
||||||
// Load Diffuse texture maps
|
// Load Diffuse texture maps
|
||||||
aiTextureType loading_type = aiTextureType_DIFFUSE;
|
aiTextureType loading_type = aiTextureType_DIFFUSE;
|
||||||
std::vector<std::shared_ptr<Texture>> diffuse_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_RGBA);
|
std::vector<std::shared_ptr<Texture>> diffuse_maps = load_material_texture(processed_textures, material, loading_type);
|
||||||
if (!diffuse_maps.empty()) textures.emplace(loading_type, diffuse_maps);
|
if (!diffuse_maps.empty()) textures.emplace(loading_type, diffuse_maps);
|
||||||
|
|
||||||
// Load specular texture maps
|
// Load specular texture maps
|
||||||
loading_type = aiTextureType_SPECULAR;
|
loading_type = aiTextureType_SPECULAR;
|
||||||
std::vector<std::shared_ptr<Texture>> spec_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_NO_COLOR);
|
std::vector<std::shared_ptr<Texture>> spec_maps = load_material_texture(processed_textures, material, loading_type);
|
||||||
if (!spec_maps.empty()) textures.emplace(loading_type, spec_maps);
|
if (!spec_maps.empty()) textures.emplace(loading_type, spec_maps);
|
||||||
|
|
||||||
// Load normals texture maps
|
// Load normals texture maps
|
||||||
loading_type = aiTextureType_NORMALS;
|
loading_type = aiTextureType_NORMALS;
|
||||||
std::vector<std::shared_ptr<Texture>> normal_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_RGB);
|
std::vector<std::shared_ptr<Texture>> normal_maps = load_material_texture(processed_textures, material, loading_type);
|
||||||
if (!normal_maps.empty()) {
|
if (!normal_maps.empty()) {
|
||||||
textures.emplace(loading_type, normal_maps);
|
textures.emplace(loading_type, normal_maps);
|
||||||
|
|
||||||
|
@ -143,7 +150,7 @@ namespace simpleengine::gfx {
|
||||||
|
|
||||||
if (!textures.empty()) {
|
if (!textures.empty()) {
|
||||||
// TODO: Find a way to let the user set the scalars.
|
// TODO: Find a way to let the user set the scalars.
|
||||||
mat = Material(textures);
|
mat = Material(textures, rendering_type);
|
||||||
|
|
||||||
// Add `textures` into the `processed_textures` list.
|
// Add `textures` into the `processed_textures` list.
|
||||||
for (const auto& pair : textures) {
|
for (const auto& pair : textures) {
|
||||||
|
@ -189,7 +196,7 @@ namespace simpleengine::gfx {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Texture>> Model::load_material_texture(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color) {
|
std::vector<std::shared_ptr<Texture>> Model::load_material_texture(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMaterial* material, aiTextureType type) {
|
||||||
std::vector<std::shared_ptr<Texture>> textures;
|
std::vector<std::shared_ptr<Texture>> textures;
|
||||||
|
|
||||||
for (int i = 0; i < material->GetTextureCount(type); i++) {
|
for (int i = 0; i < material->GetTextureCount(type); i++) {
|
||||||
|
@ -216,7 +223,7 @@ namespace simpleengine::gfx {
|
||||||
ss << model_directory << "/" << texture_path;
|
ss << model_directory << "/" << texture_path;
|
||||||
std::string full_path = ss.str();
|
std::string full_path = ss.str();
|
||||||
|
|
||||||
Texture texture(full_path.c_str(), type, Texture::default_flags_no_color | texture_color);
|
Texture texture(full_path.c_str(), type);
|
||||||
texture.path = texture_path;
|
texture.path = texture_path;
|
||||||
textures.emplace_back(std::make_shared<Texture>(texture));
|
textures.emplace_back(std::make_shared<Texture>(texture));
|
||||||
|
|
||||||
|
|
|
@ -9,25 +9,27 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assimp/material.h>
|
#include <assimp/material.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <glm/geometric.hpp>
|
||||||
|
|
||||||
|
// TODO: Check if initialized before trying to do stuff
|
||||||
namespace simpleengine::gfx {
|
namespace simpleengine::gfx {
|
||||||
void create_mesh_buffers(simpleengine::gfx::Mesh& mesh);
|
void create_mesh_buffers(simpleengine::gfx::Mesh &mesh);
|
||||||
|
|
||||||
Renderer::Renderer(GLFWwindow* window, gfx::Shader shader): window(window), shader(shader) {
|
RenderingJob::RenderingJob(RenderingType rendering_type, gfx::Mesh &mesh, glm::mat4 position)
|
||||||
|
: rendering_type(rendering_type), rendering_mesh(&mesh), transform_mat(position) {}
|
||||||
|
|
||||||
}
|
Renderer::Renderer(GLFWwindow *window, gfx::Shader shader, std::shared_ptr<Camera> camera)
|
||||||
|
: window(window), shader(shader), camera(camera)/* , transparent_render_queue(CameraDistanceComparator(camera)) */ {}
|
||||||
|
|
||||||
Renderer::Renderer(GLFWwindow* window, GLuint shader_program): Renderer(window,
|
Renderer::Renderer(GLFWwindow *window, GLuint shader_program, std::shared_ptr<Camera> camera)
|
||||||
gfx::Shader(shader_program)) {
|
: Renderer(window, gfx::Shader(shader_program), camera) {}
|
||||||
|
|
||||||
}
|
void debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
|
||||||
|
const GLchar *message, const void *userParam) {
|
||||||
void debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity,
|
|
||||||
GLsizei length, const GLchar* message, const void* userParam) {
|
|
||||||
|
|
||||||
fprintf(stderr, "%s type = 0x%x, severity = 0x%x, message = %s\n",
|
fprintf(stderr, "%s type = 0x%x, severity = 0x%x, message = %s\n",
|
||||||
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
|
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message);
|
||||||
type, severity, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::enable_debug() {
|
void Renderer::enable_debug() {
|
||||||
|
@ -35,24 +37,49 @@ namespace simpleengine::gfx {
|
||||||
glDebugMessageCallback(debug_message_callback, 0);
|
glDebugMessageCallback(debug_message_callback, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::queue_job(RenderingJob job) {
|
void Renderer::sort_jobs() {
|
||||||
RenderingJob& emplace = rendering_queue.emplace(job);
|
// Sort transparents
|
||||||
create_job_buffers(emplace);
|
|
||||||
|
// std::sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::create_job_buffers(RenderingJob& job) {
|
void Renderer::queue_job(RenderingType rendering_type, gfx::Mesh &mesh, glm::mat4 position) {
|
||||||
Mesh& rendering_mesh = job.rendering_mesh;
|
RenderingJob job(rendering_type, mesh, position);
|
||||||
|
|
||||||
if (!rendering_mesh.are_buffers_created) {
|
this->queue_job(job);
|
||||||
gfx::VBO& vbo = rendering_mesh.vbo;
|
}
|
||||||
gfx::VBO& ebo = rendering_mesh.ebo;
|
|
||||||
gfx::VAO& vao = rendering_mesh.vao;
|
void Renderer::queue_job(RenderingJob job) {
|
||||||
|
create_job_buffers(job);
|
||||||
|
|
||||||
|
switch (job.rendering_type) {
|
||||||
|
case RenderingType::RendType_TRANSPARENT: {
|
||||||
|
/* glm::vec3 pos = job.transform_mat[3];
|
||||||
|
float distance = glm::distance(pos, camera->position); */
|
||||||
|
this->transparent_render_queue.emplace(job);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
this->other_render_queue.emplace(job);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_jobs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::create_job_buffers(RenderingJob &job) {
|
||||||
|
Mesh *rendering_mesh = job.rendering_mesh;
|
||||||
|
|
||||||
|
if (!rendering_mesh->are_buffers_created) {
|
||||||
|
gfx::VBO &vbo = rendering_mesh->vbo;
|
||||||
|
gfx::VBO &ebo = rendering_mesh->ebo;
|
||||||
|
gfx::VAO &vao = rendering_mesh->vao;
|
||||||
|
|
||||||
vao.bind();
|
vao.bind();
|
||||||
vbo.buffer(rendering_mesh.vertices.data(), 0, sizeof(LitVertex) * rendering_mesh.vertices.size());
|
vbo.buffer(rendering_mesh->vertices.data(), 0, sizeof(LitVertex) * rendering_mesh->vertices.size());
|
||||||
|
|
||||||
if (!rendering_mesh.indicies.empty()) {
|
if (!rendering_mesh->indicies.empty()) {
|
||||||
ebo.buffer(rendering_mesh.indicies.data(), 0, rendering_mesh.indicies.size() * sizeof(GLuint));
|
ebo.buffer(rendering_mesh->indicies.data(), 0, rendering_mesh->indicies.size() * sizeof(GLuint));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable VAO attributes
|
// Enable VAO attributes
|
||||||
|
@ -61,23 +88,29 @@ namespace simpleengine::gfx {
|
||||||
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false);
|
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false);
|
||||||
vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false);
|
vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false);
|
||||||
|
|
||||||
rendering_mesh.tangent_vbo.buffer(rendering_mesh.tangents.data(), 0, rendering_mesh.tangents.size() * sizeof(Vectorf));
|
rendering_mesh->tangent_vbo.buffer(rendering_mesh->tangents.data(), 0,
|
||||||
vao.enable_attrib(rendering_mesh.tangent_vbo, 4, 3, GL_FLOAT, sizeof(Vectorf), 0, false);
|
rendering_mesh->tangents.size() * sizeof(Vectorf));
|
||||||
|
vao.enable_attrib(rendering_mesh->tangent_vbo, 4, 3, GL_FLOAT, sizeof(Vectorf), 0, false);
|
||||||
|
|
||||||
vbo.unbind();
|
vbo.unbind();
|
||||||
vao.unbind();
|
vao.unbind();
|
||||||
|
|
||||||
rendering_mesh.are_buffers_created = true;
|
rendering_mesh->are_buffers_created = true;
|
||||||
|
|
||||||
std::cout << "Created render job buffers" << std::endl;
|
std::cout << "Created render job buffers" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::update(const float& delta_time) {
|
void Renderer::update(const float &delta_time) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::initialize() {
|
void Renderer::initialize() {
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
std::cout << "Base Renderer initialized" << std::endl;
|
std::cout << "Base Renderer initialized" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,73 +122,112 @@ namespace simpleengine::gfx {
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render() {
|
bool Renderer::render_job(const RenderingJob &job) {
|
||||||
|
Mesh *mesh = job.rendering_mesh;
|
||||||
|
|
||||||
|
shader.set_uniform_matrix_4f("u_transform_matrix", job.transform_mat, false);
|
||||||
|
|
||||||
|
std::optional<Material> &material = mesh->material;
|
||||||
|
|
||||||
|
if (material.has_value()) {
|
||||||
|
shader.set_uniform_float("u_material.ambient_strength", material->ambient_strength, false);
|
||||||
|
shader.set_uniform_float("u_material.diffuse_strength", material->diffuse_strength, false);
|
||||||
|
shader.set_uniform_float("u_material.specular_strength", material->specular_strength, false);
|
||||||
|
shader.set_uniform_float("u_material.shine_factor", material->shine_factor, false);
|
||||||
|
// shader.set_uniform_float("u_material.reflect_factor", .1f, false);
|
||||||
|
|
||||||
|
auto diffuse_maps = material->textures.find(aiTextureType_DIFFUSE);
|
||||||
|
auto diffuse_map = diffuse_maps->second.front();
|
||||||
|
|
||||||
|
shader.set_uniform_int("u_material.diffuse", 0, false);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
diffuse_map->bind();
|
||||||
|
|
||||||
|
// Apply the specular map if it exists
|
||||||
|
auto specular_maps = material->textures.find(aiTextureType_SPECULAR);
|
||||||
|
if (specular_maps != material->textures.end()) {
|
||||||
|
auto spec = specular_maps->second.front();
|
||||||
|
|
||||||
|
shader.set_uniform_int("u_material.has_specular_map", 1, false);
|
||||||
|
shader.set_uniform_int("u_material.specular_map", 1, false);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
spec->bind();
|
||||||
|
} else {
|
||||||
|
shader.set_uniform_int("u_material.has_specular_map", 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the normal map if it exists
|
||||||
|
auto normal_maps = material->textures.find(aiTextureType_NORMALS);
|
||||||
|
if (normal_maps != material->textures.end()) {
|
||||||
|
auto normal = normal_maps->second.front();
|
||||||
|
|
||||||
|
shader.set_uniform_int("u_material.has_normal_map", 1, false);
|
||||||
|
shader.set_uniform_int("u_material.normal_map", 2, false);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
normal->bind();
|
||||||
|
} else {
|
||||||
|
shader.set_uniform_int("u_material.has_normal_map", 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh->vao.bind();
|
||||||
|
if (mesh->indicies.empty()) {
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, mesh->vertices.size());
|
||||||
|
} else {
|
||||||
|
glDrawElements(GL_TRIANGLES, mesh->indicies.size(), GL_UNSIGNED_INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::render_job_queue(std::queue<RenderingJob> &rendering_queue) {
|
||||||
shader.use();
|
shader.use();
|
||||||
|
|
||||||
while (!rendering_queue.empty()) {
|
while (!rendering_queue.empty()) {
|
||||||
// Get the job from the queue, we'll remove it after we render.
|
// Get the job from the queue, we'll remove it after we render.
|
||||||
RenderingJob& job = rendering_queue.front();
|
RenderingJob &job = rendering_queue.front();
|
||||||
Mesh& mesh = job.rendering_mesh;
|
|
||||||
|
|
||||||
shader.set_uniform_matrix_4f("u_transform_matrix", job.transform_mat, false);
|
bool res = this->render_job(job);
|
||||||
|
|
||||||
std::optional<Material>& material = mesh.material;
|
if (res) {
|
||||||
|
// Now we'll remove the job from the queue.
|
||||||
if (material.has_value()) {
|
rendering_queue.pop();
|
||||||
shader.set_uniform_float("u_material.ambient_strength", material->ambient_strength, false);
|
|
||||||
shader.set_uniform_float("u_material.diffuse_strength", material->diffuse_strength, false);
|
|
||||||
shader.set_uniform_float("u_material.specular_strength", material->specular_strength, false);
|
|
||||||
shader.set_uniform_float("u_material.shine_factor", material->shine_factor, false);
|
|
||||||
//shader.set_uniform_float("u_material.reflect_factor", .1f, false);
|
|
||||||
|
|
||||||
auto diffuse_maps = material->textures.find(aiTextureType_DIFFUSE);
|
|
||||||
auto diffuse_map = diffuse_maps->second.front();
|
|
||||||
|
|
||||||
shader.set_uniform_int("u_material.diffuse", 0, false);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
diffuse_map->bind();
|
|
||||||
|
|
||||||
// Apply the specular map if it exists
|
|
||||||
auto specular_maps = material->textures.find(aiTextureType_SPECULAR);
|
|
||||||
if (specular_maps != material->textures.end()) {
|
|
||||||
auto spec = specular_maps->second.front();
|
|
||||||
|
|
||||||
shader.set_uniform_int("u_material.has_specular_map", 1, false);
|
|
||||||
shader.set_uniform_int("u_material.specular_map", 1, false);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
|
||||||
spec->bind();
|
|
||||||
} else {
|
|
||||||
shader.set_uniform_int("u_material.has_specular_map", 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the normal map if it exists
|
|
||||||
auto normal_maps = material->textures.find(aiTextureType_NORMALS);
|
|
||||||
if (normal_maps != material->textures.end()) {
|
|
||||||
auto normal = normal_maps->second.front();
|
|
||||||
|
|
||||||
shader.set_uniform_int("u_material.has_normal_map", 1, false);
|
|
||||||
shader.set_uniform_int("u_material.normal_map", 2, false);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
normal->bind();
|
|
||||||
} else {
|
|
||||||
shader.set_uniform_int("u_material.has_normal_map", 0, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.vao.bind();
|
|
||||||
if (mesh.indicies.empty()) {
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size());
|
|
||||||
} else {
|
|
||||||
glDrawElements(GL_TRIANGLES, mesh.indicies.size(), GL_UNSIGNED_INT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we'll remove the job from the queue.
|
|
||||||
rendering_queue.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.unuse();
|
shader.unuse();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void Renderer::render_job_queue(std::map<float, RenderingJob, std::greater<>>& rendering_queue) {
|
||||||
|
shader.use();
|
||||||
|
|
||||||
|
// Render each job then clear the queue
|
||||||
|
for (const auto& it : rendering_queue) {
|
||||||
|
this->render_job(it.second);
|
||||||
|
}
|
||||||
|
rendering_queue.clear();
|
||||||
|
|
||||||
|
shader.unuse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::render() {
|
||||||
|
// Render other (opaque) objects first
|
||||||
|
this->render_job_queue(other_render_queue);
|
||||||
|
|
||||||
|
// Render transparent objects
|
||||||
|
std::map<float, RenderingJob, std::greater<>> transparent_jobs;
|
||||||
|
while (!transparent_render_queue.empty()) {
|
||||||
|
RenderingJob& job = transparent_render_queue.front();
|
||||||
|
|
||||||
|
glm::vec3 pos = job.transform_mat[3];
|
||||||
|
float distance = glm::distance(pos, camera->position);
|
||||||
|
transparent_jobs.emplace(distance, job);
|
||||||
|
|
||||||
|
transparent_render_queue.pop();
|
||||||
|
}
|
||||||
|
this->render_job_queue(transparent_jobs);
|
||||||
|
}
|
||||||
|
} // namespace simpleengine::gfx
|
|
@ -10,24 +10,6 @@ namespace simpleengine::gfx {
|
||||||
bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY;
|
bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY;
|
||||||
bool mipmap = flags & TextureFlags::TexFlags_MIPMAP;
|
bool mipmap = flags & TextureFlags::TexFlags_MIPMAP;
|
||||||
|
|
||||||
// Get the color channel type for opengl, and get
|
|
||||||
// the channel count for loading the texture with stb_image
|
|
||||||
int gl_color_channels;
|
|
||||||
int channel_count;
|
|
||||||
if (flags & TexFlags_RGBA) {
|
|
||||||
channel_count = 4;
|
|
||||||
gl_color_channels = GL_RGBA;
|
|
||||||
} else if (flags & TexFlags_RGB) {
|
|
||||||
channel_count = 3;
|
|
||||||
gl_color_channels = GL_RGB;
|
|
||||||
} else if (flags & TexFlags_NO_COLOR) {
|
|
||||||
channel_count = 1;
|
|
||||||
gl_color_channels = GL_RED;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Texture color flag is missing!! Specify TexFlags_RGBA" << std::endl;
|
|
||||||
throw std::runtime_error("Texture color flag is missing!! Specify TexFlags_RGBA");
|
|
||||||
}
|
|
||||||
|
|
||||||
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||||
|
|
||||||
glGenTextures(1, &texture_id);
|
glGenTextures(1, &texture_id);
|
||||||
|
@ -42,7 +24,7 @@ namespace simpleengine::gfx {
|
||||||
|
|
||||||
stbi_set_flip_vertically_on_load(flip_vertically);
|
stbi_set_flip_vertically_on_load(flip_vertically);
|
||||||
|
|
||||||
img_data = stbi_load(path, &width, &height, &channels, channel_count);
|
unsigned char*img_data = stbi_load(path, &width, &height, &channels, 0);
|
||||||
if(!img_data) {
|
if(!img_data) {
|
||||||
const char* failure = stbi_failure_reason();
|
const char* failure = stbi_failure_reason();
|
||||||
std::cerr << "Failed to load texture! (" << failure << ")" << std::endl;
|
std::cerr << "Failed to load texture! (" << failure << ")" << std::endl;
|
||||||
|
@ -50,13 +32,27 @@ namespace simpleengine::gfx {
|
||||||
}
|
}
|
||||||
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
||||||
|
|
||||||
glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data);
|
// Get the color type
|
||||||
|
int color_format = 0;
|
||||||
|
if (channels == 1) {
|
||||||
|
color_format = GL_RED;
|
||||||
|
} else if (channels == 3) {
|
||||||
|
color_format = GL_RGB;
|
||||||
|
} else if (channels == 4) {
|
||||||
|
color_format = GL_RGBA;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Unknown texture color format with " << channels << " channels!" << std::endl;
|
||||||
|
throw std::runtime_error("Unknown texture color format!");
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexImage2D(image_type_gl, 0, color_format, width, height, 0, color_format, GL_UNSIGNED_BYTE, img_data);
|
||||||
|
|
||||||
if (mipmap) {
|
if (mipmap) {
|
||||||
glGenerateMipmap(image_type_gl);
|
glGenerateMipmap(image_type_gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
stbi_set_flip_vertically_on_load(false);
|
stbi_set_flip_vertically_on_load(false);
|
||||||
|
stbi_image_free(img_data);
|
||||||
|
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
@ -66,24 +62,6 @@ namespace simpleengine::gfx {
|
||||||
bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY;
|
bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY;
|
||||||
bool mipmap = flags & TextureFlags::TexFlags_MIPMAP;
|
bool mipmap = flags & TextureFlags::TexFlags_MIPMAP;
|
||||||
|
|
||||||
// Get the color channel type for opengl, and get
|
|
||||||
// the channel count for loading the texture with stb_image
|
|
||||||
int gl_color_channels;
|
|
||||||
int channel_count;
|
|
||||||
if (flags & TexFlags_RGBA) {
|
|
||||||
channel_count = 4;
|
|
||||||
gl_color_channels = GL_RGBA;
|
|
||||||
} else if (flags & TexFlags_RGB) {
|
|
||||||
channel_count = 3;
|
|
||||||
gl_color_channels = GL_RGB;
|
|
||||||
} else if (flags & TexFlags_NO_COLOR) {
|
|
||||||
channel_count = 1;
|
|
||||||
gl_color_channels = GL_RED;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Texture color flag is missing!! Specify TexFlags_RGBA" << std::endl;
|
|
||||||
throw std::runtime_error("Texture color flag is missing!! Specify TexFlags_RGBA");
|
|
||||||
}
|
|
||||||
|
|
||||||
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||||
|
|
||||||
glGenTextures(1, &texture_id);
|
glGenTextures(1, &texture_id);
|
||||||
|
@ -98,7 +76,7 @@ namespace simpleengine::gfx {
|
||||||
|
|
||||||
stbi_set_flip_vertically_on_load(flip_vertically);
|
stbi_set_flip_vertically_on_load(flip_vertically);
|
||||||
|
|
||||||
img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, channel_count);
|
unsigned char* img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, 0);
|
||||||
if(!img_data) {
|
if(!img_data) {
|
||||||
const char* failure = stbi_failure_reason();
|
const char* failure = stbi_failure_reason();
|
||||||
std::cerr << "Failed to load texture! (" << failure << ")" << std::endl;
|
std::cerr << "Failed to load texture! (" << failure << ")" << std::endl;
|
||||||
|
@ -106,13 +84,27 @@ namespace simpleengine::gfx {
|
||||||
}
|
}
|
||||||
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl;
|
||||||
|
|
||||||
glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data);
|
// Get the color type
|
||||||
|
int color_format = 0;
|
||||||
|
if (channels == 1) {
|
||||||
|
color_format = GL_RED;
|
||||||
|
} else if (channels == 3) {
|
||||||
|
color_format = GL_RGB;
|
||||||
|
} else if (channels == 4) {
|
||||||
|
color_format = GL_RGBA;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Unknown texture color format with " << channels << " channels!" << std::endl;
|
||||||
|
throw std::runtime_error("Unknown texture color format!");
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexImage2D(image_type_gl, 0, color_format, width, height, 0, color_format, GL_UNSIGNED_BYTE, img_data);
|
||||||
|
|
||||||
if (mipmap) {
|
if (mipmap) {
|
||||||
glGenerateMipmap(image_type_gl);
|
glGenerateMipmap(image_type_gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
stbi_set_flip_vertically_on_load(false);
|
stbi_set_flip_vertically_on_load(false);
|
||||||
|
stbi_image_free(img_data);
|
||||||
|
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
@ -138,7 +130,6 @@ namespace simpleengine::gfx {
|
||||||
texture.height = height;
|
texture.height = height;
|
||||||
texture.channels = 4;
|
texture.channels = 4;
|
||||||
texture.type = aiTextureType::aiTextureType_DIFFUSE;
|
texture.type = aiTextureType::aiTextureType_DIFFUSE;
|
||||||
texture.img_data = data;
|
|
||||||
|
|
||||||
glGenTextures(1, &texture.texture_id);
|
glGenTextures(1, &texture.texture_id);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
|
@ -148,10 +139,12 @@ namespace simpleengine::gfx {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.img_data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
texture.unbind();
|
texture.unbind();
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,22 @@ namespace simpleengine {
|
||||||
// Is there a way these can be grouped?
|
// Is there a way these can be grouped?
|
||||||
registry.view<const TransformComponent, ModelComponent>().each([this](const TransformComponent& transform, ModelComponent& model_component) {
|
registry.view<const TransformComponent, ModelComponent>().each([this](const TransformComponent& transform, ModelComponent& model_component) {
|
||||||
for (auto& mesh : model_component.model.meshes) {
|
for (auto& mesh : model_component.model.meshes) {
|
||||||
renderer->queue_job(gfx::RenderingJob(mesh, transform.transform_matrix));
|
auto rendering_type = gfx::RenderingType::RendType_OPAQUE;
|
||||||
|
if (mesh.material) {
|
||||||
|
rendering_type = mesh.material->rendering_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->queue_job(gfx::RenderingJob(rendering_type, mesh, transform.transform_matrix));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
registry.view<const TransformComponent, MeshComponent>().each([this](const TransformComponent& transform, MeshComponent& mesh_component) {
|
registry.view<const TransformComponent, MeshComponent>().each([this](const TransformComponent& transform, MeshComponent& mesh_component) {
|
||||||
renderer->queue_job(gfx::RenderingJob(mesh_component.mesh, transform.transform_matrix));
|
auto rendering_type = gfx::RenderingType::RendType_OPAQUE;
|
||||||
|
if (mesh_component.mesh.material) {
|
||||||
|
rendering_type = mesh_component.mesh.material->rendering_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->queue_job(gfx::RenderingJob(rendering_type, mesh_component.mesh, transform.transform_matrix));
|
||||||
});
|
});
|
||||||
|
|
||||||
registry.view<TransformComponent, RotatingComponent>().each([this, &delta_time](TransformComponent& transform, RotatingComponent& rotating) {
|
registry.view<TransformComponent, RotatingComponent>().each([this, &delta_time](TransformComponent& transform, RotatingComponent& rotating) {
|
||||||
|
|
Loading…
Reference in New Issue