Skip to content

Commit

Permalink
Implemented a resource manager functionality, which can be used to em…
Browse files Browse the repository at this point in the history
…bed internal resources inside the library binary file, by setting EMBED_RESOURCES option in CMake configuration. Updated documentation.
  • Loading branch information
patrykcieslak committed Jan 19, 2021
1 parent 897f56e commit fd755de
Show file tree
Hide file tree
Showing 16 changed files with 520 additions and 77 deletions.
42 changes: 30 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
cmake_minimum_required(VERSION 3.10)
project(Stonefish VERSION 1.2.0)
project(Stonefish VERSION 1.3.0)

# Automatic configuration
configure_file(version.h.in version.h)
configure_file(stonefish.pc.in stonefish.pc)

# Options
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

option(BUILD_TESTS "Build applications testing different features of the Stonefish library" OFF)
option(EMBED_RESOURCES "Embed internal resources in the library executable" OFF)

# Set up CMAKE flags
# Compile flags
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "-DBT_EULER_DEFAULT_ZYX -DBT_USE_DOUBLE_PRECISION")
Expand All @@ -24,6 +25,17 @@ find_package(OpenGL REQUIRED)
find_package(SDL2 REQUIRED)
find_package(Freetype REQUIRED)

# Generate C++ code from all resource files (optional)
set(RESOURCES) # This variable stores array of generated resource files
if(EMBED_RESOURCES)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ResourceManager) # Build resource manager
file(GLOB_RECURSE RESOURCE_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/Library/shaders/*.*") # Find resource files
rm_embed_resources(RESOURCES ${RESOURCE_FILES}) # Generate C++ code
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEMBEDDED_RESOURCES -DRM_NO_EXCEPTIONS")
add_definitions(-DSHADER_DIR_PATH=\"Library/shaders/\") #Sets shader path for resources
include_directories(${RESOURCE_MANAGER_INCLUDE_DIRS})
endif()

# Add include directories
include_directories(
${PROJECT_BINARY_DIR}
Expand All @@ -34,22 +46,26 @@ include_directories(
${FREETYPE_INCLUDE_DIRS}
)

# Build list of library source files
# Find library source files
file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Library/src/*.cpp")
file(GLOB_RECURSE SOURCES_3RD "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/*.cpp")

# Define targets
if(BUILD_TESTS)
# Create tests and use library locally (has to be disabled when installing system-wide!)
add_library(Stonefish_test SHARED ${SOURCES} ${SOURCES_3RD})
add_library(Stonefish_test SHARED ${SOURCES} ${SOURCES_3RD} ${RESOURCES})
target_link_libraries(Stonefish_test ${FREETYPE_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL2_LIBRARIES})
add_definitions(-DSHADER_DIR_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/Library/shaders/\") #Sets shader path for the library
if(NOT EMBED_RESOURCES)
add_definitions(-DSHADER_DIR_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/Library/shaders/\") #Sets shader path for the library
endif()
add_subdirectory(Tests)
else()
# Create shared library to be installed system-wide
add_library(Stonefish SHARED ${SOURCES} ${SOURCES_3RD})
add_library(Stonefish SHARED ${SOURCES} ${SOURCES_3RD} ${RESOURCES})
target_link_libraries(Stonefish ${FREETYPE_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL2_LIBRARIES})
add_definitions(-DSHADER_DIR_PATH=\"${CMAKE_INSTALL_PREFIX}/share/Stonefish/shaders/\") #Sets shader path for the library
if(NOT EMBED_RESOURCES)
add_definitions(-DSHADER_DIR_PATH=\"${CMAKE_INSTALL_PREFIX}/share/Stonefish/shaders/\") #Sets shader path for the library
endif()

# Install library in the system
install(
Expand All @@ -69,7 +85,9 @@ else()
endforeach()

#Install other files
install(DIRECTORY Library/shaders/ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/Stonefish/shaders)
install(FILES ${PROJECT_BINARY_DIR}/version.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/Stonefish)
install(FILES ${PROJECT_BINARY_DIR}/stonefish.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
endif()
install(FILES ${PROJECT_BINARY_DIR}/version.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/Stonefish) # Version header
install(FILES ${PROJECT_BINARY_DIR}/stonefish.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig) # Pkg-config configuration
if(NOT EMBED_RESOURCES)
install(DIRECTORY Library/shaders/ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/Stonefish/shaders) # Resources
endif()
endif()
3 changes: 2 additions & 1 deletion Library/include/graphics/OpenGLContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,10 @@ namespace sf
\param filename the path to the texture file
\param hasAlphaChannel a flag to indicate if the texture has transparency
\param anisotropy defines maximum anisotropic filtering
\param internal a flag to indicate if the texture is an internal resource
\return the id of the loaded texture
*/
static GLuint LoadTexture(std::string filename, bool hasAlphaChannel = false, GLfloat anisotropy = 0.f);
static GLuint LoadTexture(std::string filename, bool hasAlphaChannel = false, GLfloat anisotropy = 0.f, bool internal = false);

//! A static method to load an internal texture.
/*!
Expand Down
65 changes: 49 additions & 16 deletions Library/src/graphics/GLSLShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#include "core/SimulationApp.h"
#include "graphics/OpenGLState.h"
#include "utils/SystemUtil.hpp"
#ifdef EMBEDDED_RESOURCES
#include <sstream>
#include "ResourceHandle.h"
#endif

namespace sf
{
Expand Down Expand Up @@ -438,24 +442,34 @@ void GLSLShader::Verbose()
GLuint GLSLShader::LoadShader(GLenum shaderType, const std::string& filename, const std::string& header, GLint *shaderCompiled)
{
GLuint shader = 0;

std::string basePath = GetShaderPath();
std::string sourcePath = basePath + filename;

std::string sourcePath = GetShaderPath() + filename;
#ifdef EMBEDDED_RESOURCES
ResourceHandle rh(sourcePath);
if(!rh.isValid())
{
cCritical("Shader resource not found: %s", sourcePath.c_str());
return 0;
}
std::istringstream sourceString(rh.string());
std::istream& sourceBuf(sourceString);
#else
std::ifstream sourceFile(sourcePath);
if(!sourceFile.is_open())
if(!sourceFile.is_open())
{
cCritical("Shader file not found: %s", sourcePath.c_str());

std::string source = header + "\n";
std::string line;

return 0;
}
std::istream& sourceBuf(sourceFile);
#endif
#ifdef DEBUG
if(verbose)
cInfo("Loading shader from: %s", sourcePath.c_str());
#endif
while(!sourceFile.eof())
std::string source = header + "\n";
std::string line;
while(!sourceBuf.eof())
{
std::getline(sourceFile, line);
std::getline(sourceBuf, line);

if(line.find("#inject") == std::string::npos)
source.append(line + "\n");
Expand All @@ -466,38 +480,57 @@ GLuint GLSLShader::LoadShader(GLenum shaderType, const std::string& filename, co

if(pos1 > 0 && pos2 > pos1)
{
std::string injectedPath = basePath + line.substr(pos1+1, pos2-pos1-1);
std::string injectedPath = GetShaderPath() + line.substr(pos1+1, pos2-pos1-1);
#ifdef EMBEDDED_RESOURCES
ResourceHandle rh2(injectedPath);
if(!rh2.isValid())
{
cCritical("Shader include resource not found: %s", injectedPath.c_str());
return 0;
}
std::istringstream injectedString(rh2.string());
std::istream& injectedBuf(injectedString);
#else

std::ifstream injectedFile(injectedPath);
if(!injectedFile.is_open())
{
sourceFile.close();
cCritical("Shader include file not found: %s", injectedPath.c_str());
return 0;
}
std::istream& injectedBuf(injectedFile);
#endif
#ifdef DEBUG
if(verbose)
cInfo("--> Injecting source from: %s", injectedPath.c_str());
#endif
while(!injectedFile.eof())
while(!injectedBuf.eof())
{
std::getline(injectedFile, line);
std::getline(injectedBuf, line);
source.append(line + "\n");
}
#ifndef EMBEDDED_RESOURCES
injectedFile.close();
#endif
}
}
}
#ifndef EMBEDDED_RESOURCES
sourceFile.close();

#endif
const char* shaderSource = source.c_str();

if(shaderSource != NULL)
{
shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar**)&shaderSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, shaderCompiled);
if(*shaderCompiled == 0)
{
cError("Failed to compile shader: %s", shaderSource);
shader = 0;
}
#ifdef DEBUG
GLint infoLogLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
Expand Down
38 changes: 24 additions & 14 deletions Library/src/graphics/OpenGLAtmosphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
#include "graphics/OpenGLCamera.h"
#include "graphics/OpenGLContent.h"
#include "utils/SystemUtil.hpp"
#ifdef EMBEDDED_RESOURCES
#include <sstream>
#include "ResourceHandle.h"
#endif

namespace sf
{
Expand Down Expand Up @@ -243,37 +247,43 @@ void OpenGLAtmosphere::LoadAtmosphereData(const std::string& filename)
glm::uvec3 scatteringSize;
GLfloat lengthUnitInMeters;
GLfloat bottomRadius;

#ifdef EMBEDDED_RESOURCES
ResourceHandle rh(filename);
std::istringstream dataString(rh.string());
std::istream& data(dataString);
#else
std::ifstream dataFile(filename, std::ios::binary | std::ios::in);
dataFile.read((char*)&transmittanceSize, sizeof(transmittanceSize));
dataFile.read((char*)&irradianceSize, sizeof(irradianceSize));
dataFile.read((char*)&scatteringSize, sizeof(scatteringSize));
dataFile.read((char*)&lengthUnitInMeters, sizeof(lengthUnitInMeters));
dataFile.read((char*)&bottomRadius, sizeof(bottomRadius));
dataFile.read((char*)&sunSkyUBOData.whitePoint, sizeof(sunSkyUBOData.whitePoint));
dataFile.read((char*)&nPrecomputedWavelengths, sizeof(nPrecomputedWavelengths));
dataFile.read((char*)&nScatteringOrders, sizeof(nScatteringOrders));
std::istream& data(dataFile);
#endif
data.read((char*)&transmittanceSize, sizeof(transmittanceSize));
data.read((char*)&irradianceSize, sizeof(irradianceSize));
data.read((char*)&scatteringSize, sizeof(scatteringSize));
data.read((char*)&lengthUnitInMeters, sizeof(lengthUnitInMeters));
data.read((char*)&bottomRadius, sizeof(bottomRadius));
data.read((char*)&sunSkyUBOData.whitePoint, sizeof(sunSkyUBOData.whitePoint));
data.read((char*)&nPrecomputedWavelengths, sizeof(nPrecomputedWavelengths));
data.read((char*)&nScatteringOrders, sizeof(nScatteringOrders));

sunSkyUBOData.atmLengthUnitInMeters = lengthUnitInMeters;
sunSkyUBOData.planetRadiusInUnits = bottomRadius/lengthUnitInMeters;

//Load atmosphere textures
glm::vec4* pixels;
pixels = new glm::vec4[transmittanceSize.x * transmittanceSize.y];
dataFile.read((char*)pixels, sizeof(glm::vec4) * transmittanceSize.x * transmittanceSize.y);
data.read((char*)pixels, sizeof(glm::vec4) * transmittanceSize.x * transmittanceSize.y);
textures[AtmosphereTextures::TRANSMITTANCE] = OpenGLContent::GenerateTexture(GL_TEXTURE_2D, transmittanceSize, GL_RGBA32F, GL_RGBA, GL_FLOAT, pixels, FilteringMode::BILINEAR, false);
delete [] pixels;
pixels = new glm::vec4[irradianceSize.x * irradianceSize.y];
dataFile.read((char*)pixels, sizeof(glm::vec4) * irradianceSize.x * irradianceSize.y);
data.read((char*)pixels, sizeof(glm::vec4) * irradianceSize.x * irradianceSize.y);
textures[AtmosphereTextures::IRRADIANCE] = OpenGLContent::GenerateTexture(GL_TEXTURE_2D, irradianceSize, GL_RGBA32F, GL_RGBA, GL_FLOAT, pixels, FilteringMode::BILINEAR, false);
delete [] pixels;
pixels = new glm::vec4[scatteringSize.x * scatteringSize.y * scatteringSize.z];
dataFile.read((char*)pixels, sizeof(glm::vec4) * scatteringSize.x * scatteringSize.y * scatteringSize.z);
data.read((char*)pixels, sizeof(glm::vec4) * scatteringSize.x * scatteringSize.y * scatteringSize.z);
textures[AtmosphereTextures::SCATTERING] = OpenGLContent::GenerateTexture(GL_TEXTURE_3D, scatteringSize, GL_RGBA16F, GL_RGBA, GL_FLOAT, pixels, FilteringMode::BILINEAR, false);
delete [] pixels;
#ifndef EMBEDDED_RESOURCES
dataFile.close();

#endif
cInfo("Loaded precomputed atmosphere model (%u wavelengths, %u scattering orders)",
nPrecomputedWavelengths, nScatteringOrders);
}
Expand Down
18 changes: 16 additions & 2 deletions Library/src/graphics/OpenGLContent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#ifdef EMBEDDED_RESOURCES
#include "ResourceHandle.h"
#endif

#define clamp(x,min,max) (x > max ? max : (x < min ? min : x))

Expand Down Expand Up @@ -1150,15 +1153,26 @@ const Look& OpenGLContent::getLook(size_t id)
}

//Static methods
GLuint OpenGLContent::LoadTexture(std::string filename, bool hasAlphaChannel, GLfloat anisotropy)
GLuint OpenGLContent::LoadTexture(std::string filename, bool hasAlphaChannel, GLfloat anisotropy, bool internal)
{
int width, height, channels;
int reqChannels = hasAlphaChannel ? 4 : 3;
GLuint texture;

// Allocate image; fail out on error
stbi_set_flip_vertically_on_load(true);
#ifdef EMBEDDED_RESOURCES
unsigned char* dataBuffer;
if(internal)
{
ResourceHandle rh(filename);
dataBuffer = stbi_load_from_memory(rh.data(), rh.size(), &width, &height, &channels, reqChannels);
}
else
dataBuffer = stbi_load(filename.c_str(), &width, &height, &channels, reqChannels);
#else
unsigned char* dataBuffer = stbi_load(filename.c_str(), &width, &height, &channels, reqChannels);
#endif
if(dataBuffer == NULL)
{
cError("Failed to load texture from: %s", filename.c_str());
Expand Down Expand Up @@ -1191,7 +1205,7 @@ GLuint OpenGLContent::LoadTexture(std::string filename, bool hasAlphaChannel, GL

GLuint OpenGLContent::LoadInternalTexture(std::string filename, bool hasAlphaChannel, GLfloat anisotropy)
{
return LoadTexture(GetShaderPath() + filename, hasAlphaChannel, anisotropy);
return LoadTexture(GetShaderPath() + filename, hasAlphaChannel, anisotropy, true);
}

GLuint OpenGLContent::GenerateTexture(GLenum target, glm::uvec3 dimensions, GLenum internalFormat, GLenum format, GLenum type, const void* data,
Expand Down
24 changes: 18 additions & 6 deletions Library/src/graphics/OpenGLOcean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
#include "entities/forcefields/Uniform.h"
#include "entities/forcefields/Jet.h"
#include "entities/forcefields/Pipe.h"
#ifdef EMBEDDED_RESOURCES
#include <sstream>
#include "ResourceHandle.h"
#endif

namespace sf
{
Expand Down Expand Up @@ -308,13 +312,21 @@ OpenGLOcean::OpenGLOcean(GLfloat size)
glBindBuffer(GL_UNIFORM_BUFFER, 0);

//Load absorption coefficient table
#ifdef EMBEDDED_RESOURCES
ResourceHandle rh(GetShaderPath() + "jerlov.dat");
if(!rh.isValid())
cCritical("Ocean water data could not be loaded!");
std::istringstream dataStream(rh.string());
dataStream.read((char*)absorption, sizeof(absorption));
dataStream.read((char*)scattering, sizeof(scattering));
#else
std::ifstream dataFile(GetShaderPath() + "jerlov.dat", std::ios::in | std::ios::binary);
if(dataFile.is_open())
{
dataFile.read((char*)absorption, sizeof(absorption));
dataFile.read((char*)scattering, sizeof(scattering));
dataFile.close();
}
if(!dataFile.is_open())
cCritical("Ocean water data could not be loaded!");
dataFile.read((char*)absorption, sizeof(absorption));
dataFile.read((char*)scattering, sizeof(scattering));
dataFile.close();
#endif
}

OpenGLOcean::~OpenGLOcean()
Expand Down
Loading

0 comments on commit fd755de

Please sign in to comment.