+ added FreeImage for loading all the non-compiled textures (jpg, pngs, etc)

+ set proper glViewport instead of hardcoded 1920 by 1080 (this might require some changing and instead do a glViewport of the screen/window size and then scaling the backbuffers)
~ set proper texture size for pingpong buffers (to work with the viewport fixes)
- removed FREE_IMAGE_FORMAT as it's already included in the FreeImage library

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2021-09-02 23:59:00 +02:00
parent 9d7d344b80
commit 16ed2f30de
8 changed files with 224 additions and 119 deletions

View File

@ -19,8 +19,9 @@ find_package(SDL REQUIRED)
find_package(SDL_mixer REQUIRED)
find_package(LZ4 REQUIRED)
find_package(FFmpeg REQUIRED)
find_package(FreeImage REQUIRED)
include_directories(${X11_INCLUDE_DIR} ${XRANDR_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${glfw3_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} ${SDL_INCLUDE_DIRS} ${SDL_MIXER_INCLUDE_DIRS} ${FFMPEG_INCLUDE_DIR} src include)
include_directories(${X11_INCLUDE_DIR} ${XRANDR_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${glfw3_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} ${SDL_INCLUDE_DIRS} ${SDL_MIXER_INCLUDE_DIRS} ${FFMPEG_INCLUDE_DIR} ${FREEIMAGE_INCLUDE_DIR} src include)
add_executable(
wallengine
@ -169,4 +170,4 @@ add_executable(
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.h
)
target_link_libraries(wallengine ${X11_LIBRARIES} ${XRANDR_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES} ${GLFW3_LIBRARY} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${LZ4_LIBRARY} ${SDL_LIBRARY} ${SDL_MIXER_LIBRARIES} ${FFMPEG_LIBRARIES})
target_link_libraries(wallengine ${X11_LIBRARIES} ${XRANDR_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES} ${GLFW3_LIBRARY} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${LZ4_LIBRARY} ${SDL_LIBRARY} ${SDL_MIXER_LIBRARIES} ${FFMPEG_LIBRARIES} ${FREEIMAGE_LIBRARIES})

View File

@ -0,0 +1,83 @@
# Find the FreeImage library.
#
# This module defines
# FREEIMAGE_FOUND - True if FREEIMAGE was found.
# FREEIMAGE_INCLUDE_DIRS - Include directories for FREEIMAGE headers.
# FREEIMAGE_LIBRARIES - Libraries for FREEIMAGE.
#
# To specify an additional directory to search, set FREEIMAGE_ROOT.
#
# Copyright (c) 2010, Ewen Cheslack-Postava
# Based on FindSQLite3.cmake by:
# Copyright (c) 2006, Jaroslaw Staniek, <js@iidea.pl>
# Extended by Siddhartha Chaudhuri, 2008.
#
# Redistribution and use is allowed according to the terms of the BSD license.
#
SET(FREEIMAGE_FOUND FALSE)
SET(FREEIMAGE_INCLUDE_DIRS)
SET(FREEIMAGE_LIBRARIES)
SET(SEARCH_PATHS
$ENV{ProgramFiles}/freeimage/include
$ENV{SystemDrive}/freeimage/include
$ENV{ProgramFiles}/freeimage
$ENV{SystemDrive}/freeimage
)
IF(FREEIMAGE_ROOT)
SET(SEARCH_PATHS
${FREEIMAGE_ROOT}
${FREEIMAGE_ROOT}/include
${SEARCH_PATHS}
)
ENDIF()
FIND_PATH(FREEIMAGE_INCLUDE_DIRS
NAMES FreeImage.h
PATHS ${SEARCH_PATHS}
NO_DEFAULT_PATH)
IF(NOT FREEIMAGE_INCLUDE_DIRS) # now look in system locations
FIND_PATH(FREEIMAGE_INCLUDE_DIRS NAMES FreeImage.h)
ENDIF(NOT FREEIMAGE_INCLUDE_DIRS)
SET(FREEIMAGE_LIBRARY_DIRS)
IF(FREEIMAGE_ROOT)
SET(FREEIMAGE_LIBRARY_DIRS ${FREEIMAGE_ROOT})
IF(EXISTS "${FREEIMAGE_ROOT}/lib")
SET(FREEIMAGE_LIBRARY_DIRS ${FREEIMAGE_LIBRARY_DIRS} ${FREEIMAGE_ROOT}/lib)
ENDIF()
IF(EXISTS "${FREEIMAGE_ROOT}/lib/static")
SET(FREEIMAGE_LIBRARY_DIRS ${FREEIMAGE_LIBRARY_DIRS} ${FREEIMAGE_ROOT}/lib/static)
ENDIF()
ENDIF()
# FREEIMAGE
# Without system dirs
FIND_LIBRARY(FREEIMAGE_LIBRARY
NAMES freeimage
PATHS ${FREEIMAGE_LIBRARY_DIRS}
NO_DEFAULT_PATH
)
IF(NOT FREEIMAGE_LIBRARY) # now look in system locations
FIND_LIBRARY(FREEIMAGE_LIBRARY NAMES freeimage)
ENDIF(NOT FREEIMAGE_LIBRARY)
SET(FREEIMAGE_LIBRARIES)
IF(FREEIMAGE_LIBRARY)
SET(FREEIMAGE_LIBRARIES ${FREEIMAGE_LIBRARY})
ENDIF()
IF(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES)
SET(FREEIMAGE_FOUND TRUE)
IF(NOT FREEIMAGE_FIND_QUIETLY)
MESSAGE(STATUS "Found FreeImage: headers at ${FREEIMAGE_INCLUDE_DIRS}, libraries at ${FREEIMAGE_LIBRARY_DIRS} :: ${FREEIMAGE_LIBRARIES}")
ENDIF(NOT FREEIMAGE_FIND_QUIETLY)
ELSE(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES)
SET(FREEIMAGE_FOUND FALSE)
IF(FREEIMAGE_FIND_REQUIRED)
MESSAGE(STATUS "FreeImage not found")
ENDIF(FREEIMAGE_FIND_REQUIRED)
ENDIF(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES)
MARK_AS_ADVANCED(FREEIMAGE_INCLUDE_DIRS FREEIMAGE_LIBRARIES)

View File

@ -19,6 +19,7 @@ Wallpaper Engine is a software designed by [Kristjan Skutta](https://store.steam
- Xrandr
- GLW3
- GLM
- FreeImage
# 5. How to use
## 5.1. Pre-requirements

View File

@ -3,6 +3,7 @@
#include <unistd.h>
#include <SDL_mixer.h>
#include <SDL.h>
#include <FreeImage.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
@ -136,38 +137,14 @@ int main (int argc, char* argv[])
return 1;
}
// initialize freeimage
FreeImage_Initialise (TRUE);
// set some window hints (opengl version to be used)
glfwWindowHint (GLFW_SAMPLES, 4);
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 1);
// create the window!
// TODO: DO WE NEED TO PASS MONITOR HERE OR ANYTHING?
// TODO: FIGURE OUT HOW TO PUT THIS WINDOW IN THE BACKGROUND
GLFWwindow* window = glfwCreateWindow (1920, 1080, "WallpaperEngine", NULL, NULL);
if (window == nullptr)
{
fprintf (stderr, "Failed to open a GLFW window");
glfwTerminate ();
return 2;
}
glfwMakeContextCurrent (window);
int windowWidth = 1920;
int windowHeight = 1080;
// get the real framebuffer size
glfwGetFramebufferSize (window, &windowWidth, &windowHeight);
if (glewInit () != GLEW_OK)
{
fprintf (stderr, "Failed to initialize GLEW");
glfwTerminate ();
return 3;
}
std::string project_path = path + "project.json";
auto containers = new WallpaperEngine::Assets::CCombinedContainer ();
@ -192,6 +169,34 @@ int main (int argc, char* argv[])
auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", containers);
WallpaperEngine::Render::CWallpaper* wallpaper;
auto projection = project->getWallpaper ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
// create the window!
// TODO: DO WE NEED TO PASS MONITOR HERE OR ANYTHING?
// TODO: FIGURE OUT HOW TO PUT THIS WINDOW IN THE BACKGROUND
GLFWwindow* window = glfwCreateWindow (projection->getWidth (), projection->getHeight (), "WallpaperEngine", NULL, NULL);
if (window == nullptr)
{
fprintf (stderr, "Failed to open a GLFW window");
glfwTerminate ();
return 2;
}
glfwMakeContextCurrent (window);
int windowWidth = projection->getWidth ();
int windowHeight = projection->getHeight ();
// get the real framebuffer size
glfwGetFramebufferSize (window, &windowWidth, &windowHeight);
if (glewInit () != GLEW_OK)
{
fprintf (stderr, "Failed to initialize GLEW");
glfwTerminate ();
return 3;
}
if (project->getType () == "scene")
{
WallpaperEngine::Core::CScene* scene = project->getWallpaper ()->as <WallpaperEngine::Core::CScene> ();
@ -248,15 +253,6 @@ int main (int argc, char* argv[])
// get the start time of the frame
startTime = clock ();
// do not use any framebuffer for now
glBindFramebuffer (GL_FRAMEBUFFER, 0);
// ensure we render over the whole screen
glViewport (0, 0, 1920, 1080);
glClearColor (clearColor.r, clearColor.g, clearColor.b, clearColor.a);
// clear window
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// render the scene
wallpaper->render ();
@ -276,6 +272,8 @@ int main (int argc, char* argv[])
glfwTerminate ();
// terminate SDL
SDL_Quit ();
// terminate free image
FreeImage_DeInitialise ();
return 0;
}

View File

@ -11,8 +11,40 @@ CTexture::CTexture (void* fileData)
// ensure the header is parsed
this->parseHeader (static_cast <char*> (fileData));
GLint internalFormat;
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
throw std::runtime_error ("Normal images are not supported yet");
{
internalFormat = GL_RGBA8;
// set some extra information too as it's used for image sizing
// this ensures that a_TexCoord uses the full image instead of just part of it
this->m_header->width = this->m_header->mipmaps [0]->width;
this->m_header->height = this->m_header->mipmaps [0]->height;
this->m_header->textureWidth = this->m_header->mipmaps [0]->width;
this->m_header->textureHeight = this->m_header->mipmaps [0]->height;
}
else
{
// detect the image format and hand it to openGL to be used
switch (this->m_header->format)
{
case TextureFormat::DXT5:
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
case TextureFormat::DXT3:
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case TextureFormat::DXT1:
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case TextureFormat::ARGB8888:
internalFormat = GL_RGBA8;
break;
default:
delete this->m_header;
throw std::runtime_error ("Cannot determine the texture format");
}
}
// set the texture resolution
// TODO: SUPPORT SPRITES
@ -21,28 +53,6 @@ CTexture::CTexture (void* fileData)
this->m_header->textureWidth, this->m_header->textureHeight
};
GLint formatGL;
// detect the image format and hand it to openGL to be used
switch (this->m_header->format)
{
case TextureFormat::DXT5:
formatGL = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
case TextureFormat::DXT3:
formatGL = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case TextureFormat::DXT1:
formatGL = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case TextureFormat::ARGB8888:
formatGL = GL_RGBA8;
break;
default:
delete this->m_header;
throw std::runtime_error ("Cannot determine the texture format");
}
// reserve a texture
glGenTextures (1, &this->m_textureID);
@ -76,32 +86,64 @@ CTexture::CTexture (void* fileData)
}
// TODO: USE THIS ONE
uint32_t blockSize = (formatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
uint32_t blockSize = (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
auto cur = this->m_header->mipmaps.begin ();
auto end = this->m_header->mipmaps.end ();
for (int32_t level = 0; cur != end; cur ++, level ++)
{
switch (formatGL)
FIBITMAP* bitmap = nullptr;
FIBITMAP* converted = nullptr;
FIMEMORY* memory = nullptr;
void* dataptr = (*cur)->uncompressedData;
uint32_t width = (*cur)->width;
uint32_t height = (*cur)->height;
GLenum textureFormat = GL_RGBA;
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
{
memory = FreeImage_OpenMemory (reinterpret_cast <BYTE *> ((*cur)->uncompressedData), (*cur)->uncompressedSize);
// load the image and setup pointers so they can be used
bitmap = FreeImage_LoadFromMemory (this->m_header->freeImageFormat, memory);
// flip the image vertically
FreeImage_FlipVertical (bitmap);
// convert to a 32bits bytearray
converted = FreeImage_ConvertTo32Bits (bitmap);
dataptr = FreeImage_GetBits (converted);
width = FreeImage_GetWidth (converted);
height = FreeImage_GetHeight (converted);
textureFormat = GL_BGRA;
}
switch (internalFormat)
{
case GL_RGBA8:
glTexImage2D (GL_TEXTURE_2D, level, formatGL,
(*cur)->width, (*cur)->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE,
(*cur)->uncompressedData
glTexImage2D (GL_TEXTURE_2D, level, internalFormat,
width, height, 0,
textureFormat, GL_UNSIGNED_BYTE,
dataptr
);
break;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
glCompressedTexImage2D (
GL_TEXTURE_2D, level, formatGL,
(*cur)->width, (*cur)->height, 0,
(*cur)->uncompressedSize, (*cur)->uncompressedData
GL_TEXTURE_2D, level, internalFormat,
(*cur)->width, (*cur)->height, 0,
(*cur)->uncompressedSize, dataptr
);
break;
}
// freeimage buffer won't be used anymore, so free memory
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
{
FreeImage_Unload (bitmap);
FreeImage_Unload (converted);
FreeImage_CloseMemory (memory);
}
}

View File

@ -7,6 +7,8 @@
#include <GL/glew.h>
#include <glm/vec4.hpp>
#include <FreeImage.h>
namespace WallpaperEngine::Assets
{
class CTexture
@ -30,50 +32,6 @@ namespace WallpaperEngine::Assets
R8 = 9,
};
// extracted from the free image library
enum FREE_IMAGE_FORMAT : int
{
FIF_UNKNOWN = -1,
FIF_BMP = 0,
FIF_ICO = 1,
FIF_JPEG = 2,
FIF_JNG = 3,
FIF_KOALA = 4,
FIF_LBM = 5,
FIF_IFF = FIF_LBM,
FIF_MNG = 6,
FIF_PBM = 7,
FIF_PBMRAW = 8,
FIF_PCD = 9,
FIF_PCX = 10,
FIF_PGM = 11,
FIF_PGMRAW = 12,
FIF_PNG = 13,
FIF_PPM = 14,
FIF_PPMRAW = 15,
FIF_RAS = 16,
FIF_TARGA = 17,
FIF_TIFF = 18,
FIF_WBMP = 19,
FIF_PSD = 20,
FIF_CUT = 21,
FIF_XBM = 22,
FIF_XPM = 23,
FIF_DDS = 24,
FIF_GIF = 25,
FIF_HDR = 26,
FIF_FAXG3 = 27,
FIF_SGI = 28,
FIF_EXR = 29,
FIF_J2K = 30,
FIF_JP2 = 31,
FIF_PFM = 32,
FIF_PICT = 33,
FIF_RAW = 34,
FIF_WEBP = 35,
FIF_JXR = 36
};
class TextureMipmap
{
public:

View File

@ -47,9 +47,21 @@ CCamera* CScene::getCamera () const
void CScene::render ()
{
auto projection = this->getScene ()->getOrthogonalProjection ();
auto cur = this->m_objects.begin ();
auto end = this->m_objects.end ();
// do not use any framebuffer for now
glBindFramebuffer (GL_FRAMEBUFFER, 0);
// ensure we render over the whole screen
glViewport (0, 0, projection->getWidth (), projection->getHeight ());
// clear screen
FloatColor clearColor = this->getScene ()->getClearColor ();
glClearColor (clearColor.r, clearColor.g, clearColor.b, clearColor.a);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (; cur != end; cur ++)
(*cur)->render ();
}

View File

@ -49,7 +49,17 @@ void CWallpaper::pinpongFramebuffer (GLuint* drawTo, GLuint* inputTexture)
void CWallpaper::setupFramebuffers ()
{
// TODO: ENSURE THE WINDOW WIDTH AND HEIGHT IS CORRECT AND UPDATE THEM WHEN THE SCREEN CHANGES
int windowWidth = 1920;
int windowHeight = 1080;
if (this->getWallpaperData ()->is <WallpaperEngine::Core::CScene> ())
{
auto projection = this->getWallpaperData ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
windowWidth = projection->getWidth ();
windowHeight = projection->getHeight ();
}
GLenum drawBuffers [1] = {GL_COLOR_ATTACHMENT0};
// create the main framebuffer
glGenFramebuffers (1, &this->m_mainFramebuffer);
@ -59,7 +69,7 @@ void CWallpaper::setupFramebuffers ()
// bind the new texture to set settings on it
glBindTexture (GL_TEXTURE_2D, this->m_mainTexture);
// give OpenGL an empty image
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, windowWidth, windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// set filtering parameters, otherwise the texture is not rendered
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -70,7 +80,7 @@ void CWallpaper::setupFramebuffers ()
// create the depth render buffer for the main framebuffer
glGenRenderbuffers (1, &this->m_mainDepthBuffer);
glBindRenderbuffer (GL_RENDERBUFFER, this->m_mainDepthBuffer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1920, 1080);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->m_mainDepthBuffer);
// set the texture as the colour attachmend #0
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->m_mainTexture, 0);
@ -89,7 +99,7 @@ void CWallpaper::setupFramebuffers ()
// bind the new texture to set settings on it
glBindTexture (GL_TEXTURE_2D, this->m_subTexture);
// give OpenGL an empty image
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, windowWidth, windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// set filtering parameters, otherwise the texture is not rendered
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -100,7 +110,7 @@ void CWallpaper::setupFramebuffers ()
// create the depth render buffer for the main framebuffer
glGenRenderbuffers (1, &this->m_subDepthBuffer);
glBindRenderbuffer (GL_RENDERBUFFER, this->m_subDepthBuffer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1920, 1080);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->m_subDepthBuffer);
// set the texture as the colour attachmend #0
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->m_subTexture, 0);