Get specular maps working and make them optional

This commit is contained in:
SeanOMik 2022-09-28 21:21:47 -04:00
parent 3a61b8495e
commit dbc12e422c
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
11 changed files with 198 additions and 103 deletions

37
.clang-tidy Normal file
View File

@ -0,0 +1,37 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,-modernize-use-trailing-return-type'
WarningsAsErrors: true
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: google
CheckOptions:
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0'
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: '1'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
...

13
CMake/Getassimp.cmake Normal file
View File

@ -0,0 +1,13 @@
include(ExternalProject)
ExternalProject_Add(external_assimp
GIT_REPOSITORY https://github.com/assimp/assimp.git
GIT_TAG v5.2.5
GIT_SUBMODULES_RECURSE true
GIT_PROGRESS true
CMAKE_ARGS
-D CMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}
-D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-D ASSIMP_INSTALL=NO
-D ASSIMP_BUILD_TESTS=NO
)
message("Downloaded assimp library")

View File

@ -21,7 +21,7 @@ find_package(GLEW REQUIRED)
find_package(glfw3 CONFIG REQUIRED)
find_package(glm CONFIG REQUIRED)
find_package(OpenGL REQUIRED)
find_package(assimp REQUIRED)
find_package(assimp CONFIG REQUIRED)
# Link sources
file(GLOB_RECURSE source_list src/*.cpp)
@ -45,7 +45,12 @@ target_link_libraries(simpleengine PUBLIC GLEW::GLEW)
target_link_libraries(simpleengine PUBLIC glfw)
target_link_libraries(simpleengine PUBLIC ${GLM_LIBRARIES})
target_link_libraries(simpleengine PUBLIC ${OPENGL_LIBRARIES})
if(WIN32)
target_link_libraries(simpleengine PUBLIC assimp::assimp)
else()
target_link_libraries(simpleengine PUBLIC assimp)
endif()
target_link_libraries(simpleengine PRIVATE simpleengine_resources)
# Include some dependencies' include directories

2
cmrc

@ -1 +1 @@
Subproject commit e386a629eb537d384811e598a3c96b9ca928f65e
Subproject commit a64bea50c05594c8e7cf1f08e441bb9507742e2e

View File

@ -1,8 +1,6 @@
#include "simpleengine/camera.h"
#include "simpleengine/ecs/component/mesh_component.h"
#include <simpleengine/ecs/component/model_component.h>
#include "simpleengine/ecs/component/transform_component.h"
#include <simpleengine/ecs/component/rotating_component.h>
#include "simpleengine/ecs/entity.h"
#include "simpleengine/gfx/light.h"
#include "simpleengine/gfx/material.h"
@ -11,23 +9,25 @@
#include "simpleengine/gfx/renderer.h"
#include "simpleengine/gfx/texture.h"
#include "simpleengine/vector.h"
#include <simpleengine/gfx/shader.h>
#include <simpleengine/renderable.h>
#include <simpleengine/ecs/component/model_component.h>
#include <simpleengine/ecs/component/rotating_component.h>
#include <simpleengine/event/event.h>
#include <simpleengine/shader_program.h>
#include <simpleengine/game.h>
#include <simpleengine/vertex.h>
#include <simpleengine/gfx/shaders/core_3d_shader.h>
#include <simpleengine/gfx/model.h>
#include <simpleengine/gfx/shader.h>
#include <simpleengine/gfx/shaders/core_3d_shader.h>
#include <simpleengine/renderable.h>
#include <simpleengine/scene.h>
#include <simpleengine/shader_program.h>
#include <simpleengine/vertex.h>
#include <assimp/material.h>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/fwd.hpp>
#include <assimp/material.h>
#include <memory>
#include <chrono>
#include <iostream>
#include <memory>
#include <sstream>
#include <stdint.h>
@ -80,13 +80,11 @@ int main(int argc, char *argv[]) {
auto white_texture = se::gfx::Texture::white_texture();
// white_texture.shine_damper = 10;
// 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 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);
/* 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);
@ -94,9 +92,8 @@ int main(int argc, char *argv[]) {
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);
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 = {
@ -118,9 +115,8 @@ int main(int argc, char *argv[]) {
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); */
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
@ -153,14 +149,8 @@ int main(int argc, char *argv[]) {
{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
};
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
auto renderer = std::make_shared<se::gfx::Renderer>(game.get_window(), core_shader);
@ -176,22 +166,23 @@ int main(int argc, char *argv[]) {
// 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");
/* 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/halot/chief.fbx");
entity.add_component<se::ModelComponent>("examples/dev_testing/resources/planks/planks.fbx");
// 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>();
transform_comp.translate(7.f, -4.f, 0.f);
transform_comp.scale(0.05f);
// transform_comp.scale(0.05f);
// transform_comp.rotate_z(-90.f);
transform_comp.rotate_y(-90.f);
transform_comp.rotate_x(-90.f);
// transform_comp.rotate_y(-90.f);
// transform_comp.rotate_x(-90.f);
// Create the entity and add the model component to it.
/* auto entity = std::make_shared<simpleengine::Entity>();

View File

@ -38,7 +38,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);
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);
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);
protected:
void post_process();

View File

@ -23,6 +23,9 @@ namespace simpleengine::gfx {
TexFlags_FLIP_VERTICALLY = 0b00000010,
TexFlags_FLIP_HORIZONTALLY = 0b00000100,
TexFlags_MIPMAP = 0b00001000,
TexFlags_NO_COLOR = 0b00010000,
TexFlags_RGB = 0b00100000,
TexFlags_RGBA = 0b01000000,
};
class Texture {
@ -34,6 +37,26 @@ namespace simpleengine::gfx {
Texture() = default;
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.
*
* The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP | TexFlags_RGBA`
*
* @see simpleengine::gfx::Texture::default_flags_no_color
*
*/
static constexpr int default_flags = default_flags_no_color | TexFlags_RGBA;
int height;
int width;
int channels;
@ -47,8 +70,7 @@ namespace simpleengine::gfx {
* @param img_2d Whether or not the texture is 2D.
* @param mipmap Whether or not to generate mipmaps for this texture.
*/
Texture(const char* path, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = TextureFlags::TexFlags_IMG_2D |
TextureFlags::TexFlags_MIPMAP);
Texture(const char* path, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = Texture::default_flags);
/**
* @brief Construct a new Texture object from the loaded file buffer.
@ -58,8 +80,7 @@ namespace simpleengine::gfx {
* @param img_2d Whether or not the texture is 2D.
* @param mipmap Whether or not to generate mipmaps for this texture.
*/
Texture(const unsigned char *const buffer, int buffer_length, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = TextureFlags::TexFlags_IMG_2D |
TextureFlags::TexFlags_MIPMAP);
Texture(const unsigned char *const buffer, int buffer_length, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = Texture::default_flags);
/**
* @brief Construct a new Texture object from the loaded file buffer.
@ -68,8 +89,7 @@ namespace simpleengine::gfx {
* @param img_2d Whether or not the texture is 2D.
* @param mipmap Whether or not to generate mipmaps for this texture.
*/
Texture(std::vector<unsigned char> buffer, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = TextureFlags::TexFlags_IMG_2D |
TextureFlags::TexFlags_MIPMAP);
Texture(std::vector<unsigned char> buffer, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = Texture::default_flags);
static Texture white_texture();

View File

@ -17,6 +17,8 @@ const int SAMP_SPECULAR = 1;
struct Material {
sampler2D diffuse;
bool has_specular_map;
sampler2D specular_map;
float ambient_strength;
@ -63,7 +65,10 @@ vec3 calculate_lighting() {
float spec = pow(max(dot(view_dir, reflect_dir), -0.f), 32 * u_material.shine_factor);
vec3 specular = specular_strength * (spec * u_material.specular_strength) * u_light_color;
//specular = specular * vec3(texture(u_material.specular_map, vs_texcoord)); // TODO check if its set before applying it.
// Check if the specular map is set before trying to set it
if (u_material.has_specular_map) {
specular = specular * texture(u_material.specular_map, vs_texcoord).r;
}
return ambient + diffuse + specular;
}

View File

@ -111,17 +111,17 @@ namespace simpleengine::gfx {
// Load Diffuse texture maps
aiTextureType loading_type = aiTextureType_DIFFUSE;
std::vector<std::shared_ptr<Texture>> diffuse_maps = load_material_texture(processed_textures, material, loading_type);
std::vector<std::shared_ptr<Texture>> diffuse_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_RGBA);
if (!diffuse_maps.empty()) textures.emplace(loading_type, diffuse_maps);
// Load specular texture maps
loading_type = aiTextureType_SPECULAR;
std::vector<std::shared_ptr<Texture>> spec_maps = load_material_texture(processed_textures, material, loading_type);
std::vector<std::shared_ptr<Texture>> spec_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_NO_COLOR);
if (!spec_maps.empty()) textures.emplace(loading_type, spec_maps);
// Load normals texture maps
loading_type = aiTextureType_NORMALS;
std::vector<std::shared_ptr<Texture>> normal_maps = load_material_texture(processed_textures, material, loading_type);
std::vector<std::shared_ptr<Texture>> normal_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_NO_COLOR);
if (!normal_maps.empty()) textures.emplace(loading_type, normal_maps);
// TODO Handle other types of texture maps
@ -170,7 +170,7 @@ namespace simpleengine::gfx {
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) {
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>> textures;
for (int i = 0; i < material->GetTextureCount(type); i++) {
@ -197,7 +197,7 @@ namespace simpleengine::gfx {
ss << model_directory << "/" << texture_path;
std::string full_path = ss.str();
Texture texture(full_path.c_str(), type, TextureFlags::TexFlags_IMG_2D | TextureFlags::TexFlags_MIPMAP);
Texture texture(full_path.c_str(), type, Texture::default_flags_no_color | texture_color);
texture.path = texture_path;
textures.emplace_back(std::make_shared<Texture>(texture));

View File

@ -112,28 +112,19 @@ namespace simpleengine::gfx {
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);
}
//diffuse_map
/* for (const auto& texture : diffuse_maps->second) {
// We can only bind to 16 textures at a time (indexes are 0-15)
if (texture_count >= 16) break;
glActiveTexture(GL_TEXTURE0 + texture_count);
glBindTextureUnit(texture_count, texture->get_texture_id());
texture_count++;
} */
}
mesh.vao.bind();

View File

@ -1,4 +1,5 @@
#include "gfx/texture.h"
#include <stdexcept>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
@ -9,6 +10,24 @@ namespace simpleengine::gfx {
bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY;
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;
glGenTextures(1, &texture_id);
@ -23,8 +42,7 @@ namespace simpleengine::gfx {
stbi_set_flip_vertically_on_load(flip_vertically);
// Read 4 channels (RGBA)
img_data = stbi_load(path, &width, &height, &channels, 4);
img_data = stbi_load(path, &width, &height, &channels, channel_count);
if(!img_data) {
const char* failure = stbi_failure_reason();
std::cerr << "Failed to load texture! (" << failure << ")" << std::endl;
@ -32,7 +50,7 @@ namespace simpleengine::gfx {
}
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_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data);
glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data);
if (mipmap) {
glGenerateMipmap(image_type_gl);
@ -48,6 +66,24 @@ namespace simpleengine::gfx {
bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY;
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;
glGenTextures(1, &texture_id);
@ -62,8 +98,7 @@ namespace simpleengine::gfx {
stbi_set_flip_vertically_on_load(flip_vertically);
// Read 4 channels (RGBA)
img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, 4);
img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, channel_count);
if(!img_data) {
const char* failure = stbi_failure_reason();
std::cerr << "Failed to load texture! (" << failure << ")" << std::endl;
@ -71,7 +106,7 @@ namespace simpleengine::gfx {
}
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_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data);
glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data);
if (mipmap) {
glGenerateMipmap(image_type_gl);
@ -117,8 +152,6 @@ namespace simpleengine::gfx {
texture.unbind();
return texture;
}