mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-07-14 05:12:25 +08:00
Added scaling and clamp support
This commit is contained in:
parent
4212095335
commit
11666abf32
@ -200,6 +200,8 @@ add_executable(
|
||||
|
||||
src/WallpaperEngine/Render/CWallpaper.h
|
||||
src/WallpaperEngine/Render/CWallpaper.cpp
|
||||
src/WallpaperEngine/Render/CWallpaperState.h
|
||||
src/WallpaperEngine/Render/CWallpaperState.cpp
|
||||
src/WallpaperEngine/Render/CScene.h
|
||||
src/WallpaperEngine/Render/CScene.cpp
|
||||
src/WallpaperEngine/Render/CVideo.h
|
||||
|
@ -28,10 +28,29 @@ struct option long_options[] = {
|
||||
{ "noautomute", no_argument, nullptr, 'm' },
|
||||
{ "no-fullscreen-pause", no_argument, nullptr, 'n' },
|
||||
{ "disable-mouse", no_argument, nullptr, 'e' },
|
||||
{ "clamp-strategy", required_argument, nullptr, 't' },
|
||||
{ "scaling", required_argument, nullptr, 't' },
|
||||
{ "clamping", required_argument, nullptr, 't' },
|
||||
{ nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
/* std::hash::operator() isn't constexpr, so it can't be used to get hash values as compile-time constants
|
||||
* So here is customHash. It skips all spaces, so hashes for " find " and "fi nd" are the same
|
||||
* Basicly got it from here: https://stackoverflow.com/questions/8317508/hash-function-for-a-string
|
||||
*/
|
||||
constexpr size_t customHash(const char* str) {
|
||||
constexpr size_t A = 54059; /* a prime */
|
||||
constexpr size_t B = 76963; /* another prime */
|
||||
constexpr size_t C = 86969; /* yet another prime */
|
||||
constexpr size_t FIRSTH = 37; /* also prime */
|
||||
size_t hash = FIRSTH;
|
||||
while (*str) {
|
||||
if(*str != ' ') // Skip spaces
|
||||
hash = (hash * A) ^ (*str * B);
|
||||
++str;
|
||||
}
|
||||
return hash % C;
|
||||
}
|
||||
|
||||
std::string stringPathFixes (const std::string& s)
|
||||
{
|
||||
if (s.empty ())
|
||||
@ -66,7 +85,8 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
|
||||
.mode = NORMAL_WINDOW,
|
||||
.maximumFPS = 30,
|
||||
.pauseOnFullscreen = true,
|
||||
.window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, .scaleToFit=false },
|
||||
.window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs,
|
||||
.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, },
|
||||
},
|
||||
.audio =
|
||||
{
|
||||
@ -105,6 +125,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
|
||||
// no need to check for previous screen being in the list, as it's the only way for this variable
|
||||
// to have any value
|
||||
this->settings.general.screenBackgrounds[lastScreen] = translateBackground (optarg);
|
||||
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
@ -133,6 +154,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
|
||||
this->settings.render.mode = DESKTOP_BACKGROUND;
|
||||
lastScreen = optarg;
|
||||
this->settings.general.screenBackgrounds[lastScreen] = "";
|
||||
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
@ -196,25 +218,38 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
|
||||
break;
|
||||
|
||||
case 't':
|
||||
{
|
||||
char opt = optarg[0];
|
||||
switch (opt)
|
||||
{
|
||||
case 's':/* stretch*/
|
||||
this->settings.render.window.scaleToFit=true;
|
||||
break;
|
||||
case 'b':/* clamp border (crop black)*/
|
||||
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;//clampStrategy(optarg);
|
||||
break;
|
||||
case 'c':/* clamp*/
|
||||
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs;
|
||||
break;
|
||||
case 'r':
|
||||
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags;
|
||||
break;
|
||||
default:
|
||||
sLog.error("Wrong argument provided for clamp-strategy");
|
||||
break;
|
||||
{
|
||||
size_t hash = customHash(optarg);
|
||||
// Use a switch statement with the hash
|
||||
switch (hash) {
|
||||
// --scale options
|
||||
case customHash("stretch"):
|
||||
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs;
|
||||
break;
|
||||
case customHash("fit"):
|
||||
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs;
|
||||
break;
|
||||
case customHash("fill"):
|
||||
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs;
|
||||
break;
|
||||
case customHash("default"):
|
||||
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs;
|
||||
break;
|
||||
// --clamp options
|
||||
case customHash("clamp"):
|
||||
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs;
|
||||
break;
|
||||
case customHash("border"):
|
||||
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;
|
||||
break;
|
||||
case customHash("repeat"):
|
||||
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags;
|
||||
break;
|
||||
default:
|
||||
sLog.error("Wrong argument:");
|
||||
sLog.error(optarg);
|
||||
sLog.exception("Wrong argument provided for --scale or --clamp option.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -314,5 +349,8 @@ void CApplicationContext::printHelp (const char* route)
|
||||
sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
|
||||
sLog.out ("\t--no-fullscreen-pause\tPrevents the background pausing when an app is fullscreen");
|
||||
sLog.out ("\t--disable-mouse\tDisables mouse interactions");
|
||||
sLog.out ("\t--clamp-strategy <strategy>\t Clamp strategy if wallpaper doesn't fit screen. Can be stretch, border, repeat, clamp. Can be shortend to s, b, r, c. Default is clamp");
|
||||
sLog.out ("\t--scaling <mode>\t Scaling mode for wallpaper. Can be stretch, fit, fill, default. Must be used before wallpaper provided.\n\
|
||||
\t\t For default wallpaper last specified value will be used.\n\
|
||||
\t\t Example: ./wallengine --scaling stretch --screen-root eDP-1 --bg 2667198601 --scaling fill --screen-root eDP-2 2667198602");
|
||||
sLog.out ("\t--clamping <mode>\t Clamping mode for all wallpapers. Can be clamp, border, repeat. Enables GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT accordingly. Default is clamp.");
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
#include "CApplicationState.h"
|
||||
|
||||
#include "WallpaperEngine/Assets/ITexture.h"
|
||||
#include "WallpaperEngine/Render/CWallpaperState.h"
|
||||
|
||||
namespace WallpaperEngine::Application
|
||||
{
|
||||
@ -52,6 +53,8 @@ namespace WallpaperEngine::Application
|
||||
std::map <std::string, std::filesystem::path> screenBackgrounds;
|
||||
/** Properties to change values for */
|
||||
std::map <std::string, std::string> properties;
|
||||
/** The scaling mode for different screens */
|
||||
std::map <std::string, WallpaperEngine::Render::CWallpaperState::TextureUVsScaling> screenScalings;
|
||||
} general;
|
||||
|
||||
/**
|
||||
@ -71,7 +74,7 @@ namespace WallpaperEngine::Application
|
||||
/** The window size used in explicit window */
|
||||
glm::ivec4 geometry;
|
||||
WallpaperEngine::Assets::ITexture::TextureFlags clamp;
|
||||
bool scaleToFit;
|
||||
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling scalingMode;
|
||||
} window;
|
||||
} render;
|
||||
|
||||
|
@ -322,13 +322,13 @@ namespace WallpaperEngine::Application
|
||||
for (const auto& it : this->m_backgrounds)
|
||||
context->setWallpaper (
|
||||
it.first,
|
||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext)
|
||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext, this->m_context.settings.general.screenScalings[it.first])
|
||||
);
|
||||
|
||||
// set the default rendering wallpaper if available
|
||||
if (this->m_defaultBackground != nullptr)
|
||||
context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
|
||||
this->m_defaultBackground->getWallpaper (), *context, *audioContext
|
||||
this->m_defaultBackground->getWallpaper (), *context, *audioContext, this->m_context.settings.render.window.scalingMode
|
||||
));
|
||||
|
||||
static time_t seconds;
|
||||
|
@ -36,9 +36,9 @@ namespace WallpaperEngine::Render
|
||||
|
||||
// render the background
|
||||
if (ref != this->m_wallpapers.end ())
|
||||
ref->second->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit);
|
||||
ref->second->render (viewport->viewport, this->getOutput ().renderVFlip ());
|
||||
else
|
||||
this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip (), this->getApp().getContext().settings.render.window.scaleToFit);
|
||||
this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip ());
|
||||
|
||||
#if !NDEBUG
|
||||
glPopDebugGroup ();
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "WallpaperEngine/Render/Objects/CImage.h"
|
||||
#include "WallpaperEngine/Render/Objects/CSound.h"
|
||||
|
||||
#include "WallpaperEngine/Render/CWallpaperState.h"
|
||||
|
||||
#include "CScene.h"
|
||||
|
||||
extern float g_Time;
|
||||
@ -14,8 +16,8 @@ extern float g_TimeLast;
|
||||
using namespace WallpaperEngine;
|
||||
using namespace WallpaperEngine::Render;
|
||||
|
||||
CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext) :
|
||||
CWallpaper (scene, Type, context, audioContext),
|
||||
CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
|
||||
CWallpaper (scene, Type, context, audioContext, scalingMode),
|
||||
m_mousePosition (),
|
||||
m_mousePositionLast (),
|
||||
m_parallaxDisplacement ()
|
||||
|
@ -15,7 +15,7 @@ namespace WallpaperEngine::Render
|
||||
class CScene : public CWallpaper
|
||||
{
|
||||
public:
|
||||
CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext);
|
||||
CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
|
||||
|
||||
CCamera* getCamera () const;
|
||||
|
||||
|
@ -11,8 +11,8 @@ void* get_proc_address (void* ctx, const char* name)
|
||||
return static_cast<CVideo*> (ctx)->getContext ().getDriver ().getProcAddress (name);
|
||||
}
|
||||
|
||||
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext) :
|
||||
CWallpaper (video, Type, context, audioContext),
|
||||
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
|
||||
CWallpaper (video, Type, context, audioContext, scalingMode),
|
||||
m_width (16),
|
||||
m_height (16),
|
||||
m_mpvGl (nullptr)
|
||||
|
@ -12,7 +12,7 @@ namespace WallpaperEngine::Render
|
||||
class CVideo : public CWallpaper
|
||||
{
|
||||
public:
|
||||
CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext);
|
||||
CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
|
||||
|
||||
Core::CVideo* getVideo ();
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
using namespace WallpaperEngine::Render;
|
||||
|
||||
CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext) :
|
||||
CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
|
||||
CContextAware (context),
|
||||
m_wallpaperData (wallpaperData),
|
||||
m_type (std::move(type)),
|
||||
@ -22,7 +22,8 @@ CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRend
|
||||
a_Position (GL_NONE),
|
||||
a_TexCoord (GL_NONE),
|
||||
m_vaoBuffer (GL_NONE),
|
||||
m_audioContext (audioContext)
|
||||
m_audioContext (audioContext),
|
||||
m_state(scalingMode)
|
||||
{
|
||||
// generate the VAO to stop opengl from complaining
|
||||
glGenVertexArrays (1, &this->m_vaoBuffer);
|
||||
@ -201,78 +202,26 @@ void CWallpaper::setupShaders ()
|
||||
this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
|
||||
}
|
||||
|
||||
void CWallpaper::updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const
|
||||
{
|
||||
glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
|
||||
glBufferData (GL_ARRAY_BUFFER, size, texCoords, GL_STATIC_DRAW);
|
||||
}
|
||||
void CWallpaper::setDestinationFramebuffer (GLuint framebuffer)
|
||||
{
|
||||
this->m_destFramebuffer = framebuffer;
|
||||
}
|
||||
|
||||
void CWallpaper::setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale,
|
||||
float& ustart, float& uend, float& vstart, float& vend){
|
||||
|
||||
ustart = 0.0f;
|
||||
uend = 1.0f;
|
||||
vstart = 1.0f;
|
||||
vend = 0.0f;
|
||||
if (vflip){
|
||||
vstart = 0.0f;
|
||||
vend = 1.0f;
|
||||
}
|
||||
if(!scale){
|
||||
uint32_t projectionWidth = this->getWidth ();
|
||||
uint32_t projectionHeight = this->getHeight ();
|
||||
const float m1 = float(viewport.z) / projectionWidth;
|
||||
const float m2 = float(viewport.w) / projectionHeight;
|
||||
const float m = std::max(m1,m2);
|
||||
projectionWidth*=m;
|
||||
projectionHeight*=m;
|
||||
if (projectionWidth!=viewport.z)
|
||||
{
|
||||
int newWidth = viewport.w / (float) projectionHeight * projectionWidth;
|
||||
float newCenter = newWidth / 2.0f;
|
||||
float viewportCenter = viewport.z / 2.0;
|
||||
|
||||
float left = newCenter - viewportCenter;
|
||||
float right = newCenter + viewportCenter;
|
||||
|
||||
ustart = left / newWidth;
|
||||
uend = right / newWidth;
|
||||
}
|
||||
|
||||
if (projectionHeight!=viewport.w)
|
||||
{
|
||||
int newHeight = viewport.z / (float) projectionWidth * projectionHeight;
|
||||
float newCenter = newHeight / 2.0f;
|
||||
float viewportCenter = viewport.w / 2.0;
|
||||
|
||||
float down = newCenter - viewportCenter;
|
||||
float up = newCenter + viewportCenter;
|
||||
|
||||
if (vflip)
|
||||
{
|
||||
vstart = down / newHeight;
|
||||
vend = up / newHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
vstart = up / newHeight;
|
||||
vend = down / newHeight;
|
||||
}
|
||||
}
|
||||
void CWallpaper::updateUVs(const glm::ivec4& viewport, const bool vflip){
|
||||
//update UVs if something has changed, otherwise use old values
|
||||
if(this->m_state.hasChanged(viewport, vflip, this->getWidth(), this->getHeight())){
|
||||
// Update wallpaper state
|
||||
this->m_state.updateState(viewport, vflip, this->getWidth(), this->getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool scale)
|
||||
void CWallpaper::render (glm::ivec4 viewport, bool vflip)
|
||||
{
|
||||
this->renderFrame (viewport);
|
||||
//Update UVs coordinates according to scaling mode of this wallpaper
|
||||
updateUVs(viewport,vflip);
|
||||
auto [ ustart, uend, vstart, vend ] = this->m_state.getTextureUVs();
|
||||
|
||||
float ustart,uend,vstart,vend;
|
||||
setTextureUVs(viewport, vflip, scale, ustart, uend, vstart, vend);
|
||||
|
||||
GLfloat texCoords [] = {
|
||||
ustart, vstart,
|
||||
uend, vstart,
|
||||
@ -363,12 +312,12 @@ CFBO* CWallpaper::getFBO () const
|
||||
return this->m_sceneFBO;
|
||||
}
|
||||
|
||||
CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext)
|
||||
CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode)
|
||||
{
|
||||
if (wallpaper->is <Core::CScene> ())
|
||||
return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext);
|
||||
return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext, scalingMode);
|
||||
else if (wallpaper->is <Core::CVideo> ())
|
||||
return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext);
|
||||
return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext, scalingMode);
|
||||
else
|
||||
sLog.exception ("Unsupported wallpaper type");
|
||||
}
|
@ -14,6 +14,8 @@
|
||||
#include "WallpaperEngine/Render/CFBO.h"
|
||||
#include "WallpaperEngine/Render/Helpers/CContextAware.h"
|
||||
|
||||
#include "CWallpaperState.h"
|
||||
|
||||
using namespace WallpaperEngine::Assets;
|
||||
using namespace WallpaperEngine::Audio;
|
||||
|
||||
@ -34,15 +36,10 @@ namespace WallpaperEngine::Render
|
||||
|
||||
~CWallpaper ();
|
||||
|
||||
/**
|
||||
* Get texture UV coordinates for render
|
||||
*/
|
||||
void setTextureUVs(const glm::ivec4& viewport, const bool vflip, const bool scale,
|
||||
float& ustart, float& uend, float& vstart, float& vend);
|
||||
/**
|
||||
* Performs a render pass of the wallpaper
|
||||
*/
|
||||
void render (glm::ivec4 viewport, bool vflip, bool scale);
|
||||
void render (glm::ivec4 viewport, bool vflip);
|
||||
|
||||
/**
|
||||
* @return The container to resolve files for this wallpaper
|
||||
@ -88,9 +85,9 @@ namespace WallpaperEngine::Render
|
||||
[[nodiscard]] CFBO* getFBO () const;
|
||||
|
||||
/**
|
||||
* Updates the texcoord used for drawing to the used framebuffer
|
||||
* Updates the UVs coordinates if window/screen/vflip/projection has changed
|
||||
*/
|
||||
void updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const;
|
||||
void updateUVs (const glm::ivec4& viewport, const bool vflip);
|
||||
|
||||
/**
|
||||
* Updates the destination framebuffer for this wallpaper
|
||||
@ -116,10 +113,10 @@ namespace WallpaperEngine::Render
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext);
|
||||
static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
|
||||
|
||||
protected:
|
||||
CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext);
|
||||
CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context, CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode);
|
||||
|
||||
/**
|
||||
* Renders a frame of the wallpaper
|
||||
@ -158,5 +155,7 @@ namespace WallpaperEngine::Render
|
||||
std::map<std::string, CFBO*> m_fbos;
|
||||
/** Audio context that is using this wallpaper */
|
||||
CAudioContext& m_audioContext;
|
||||
/** Current Wallpaper state */
|
||||
CWallpaperState m_state;
|
||||
};
|
||||
}
|
||||
|
170
src/WallpaperEngine/Render/CWallpaperState.cpp
Normal file
170
src/WallpaperEngine/Render/CWallpaperState.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
#include "CWallpaperState.h"
|
||||
#include <algorithm>
|
||||
#include "WallpaperEngine/Logging/CLog.h"
|
||||
|
||||
using namespace WallpaperEngine::Render;
|
||||
|
||||
// Reset UVs to 0/1 values
|
||||
void CWallpaperState::resetUVs(){
|
||||
this->UVs.ustart=0;
|
||||
this->UVs.uend=1;
|
||||
if (vflip){
|
||||
this->UVs.vstart = 0.0f;
|
||||
this->UVs.vend = 1.0f;
|
||||
}
|
||||
else{
|
||||
this->UVs.vstart=1.0f;
|
||||
this->UVs.vend=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Update Us coordinates for current viewport and projection
|
||||
void CWallpaperState::updateUs(const int& projectionWidth, const int& projectionHeight){
|
||||
const float viewportWidth = this->getViewportWidth();
|
||||
const float viewportHeight = this->getViewportHeight();
|
||||
int newWidth = viewportHeight / projectionHeight * projectionWidth;
|
||||
float newCenter = newWidth / 2.0f;
|
||||
float viewportCenter = viewportWidth / 2.0;
|
||||
|
||||
float left = newCenter - viewportCenter;
|
||||
float right = newCenter + viewportCenter;
|
||||
|
||||
this->UVs.ustart = left / newWidth;
|
||||
this->UVs.uend = right / newWidth;
|
||||
}
|
||||
|
||||
// Update Vs coordinates for current viewport and projection
|
||||
void CWallpaperState::updateVs(const int& projectionWidth, const int& projectionHeight){
|
||||
const float viewportWidth = this->getViewportWidth();
|
||||
const float viewportHeight = this->getViewportHeight();
|
||||
int newHeight = viewportWidth / projectionWidth * projectionHeight;
|
||||
float newCenter = newHeight / 2.0f;
|
||||
float viewportCenter = viewportHeight / 2.0;
|
||||
|
||||
float down = newCenter - viewportCenter;
|
||||
float up = newCenter + viewportCenter;
|
||||
|
||||
if (vflip)
|
||||
{
|
||||
this->UVs.vstart = down / newHeight;
|
||||
this->UVs.vend = up / newHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->UVs.vstart = up / newHeight;
|
||||
this->UVs.vend = down / newHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::StretchUVs>(){
|
||||
this->resetUVs();
|
||||
}
|
||||
|
||||
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFillUVs>(){
|
||||
this->resetUVs();
|
||||
|
||||
const int viewportWidth = this->getViewportWidth();
|
||||
const int viewportHeight = this->getViewportHeight();
|
||||
uint32_t projectionWidth = this->getProjectionWidth();
|
||||
uint32_t projectionHeight = this->getProjectionHeight();
|
||||
|
||||
const float m1 = static_cast<float>(viewportWidth) / projectionWidth;
|
||||
const float m2 = static_cast<float>(viewportHeight) / projectionHeight;
|
||||
const float m = std::max(m1,m2);
|
||||
projectionWidth*=m;
|
||||
projectionHeight*=m;
|
||||
|
||||
if (projectionWidth!=viewportWidth)
|
||||
{
|
||||
this->updateUs(projectionWidth,projectionHeight);
|
||||
}
|
||||
else if (projectionHeight!=viewportHeight)
|
||||
{
|
||||
this->updateVs(projectionWidth,projectionHeight);
|
||||
}
|
||||
}
|
||||
|
||||
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFitUVs>(){
|
||||
this->resetUVs();
|
||||
|
||||
const int viewportWidth = this->getViewportWidth();
|
||||
const int viewportHeight = this->getViewportHeight();
|
||||
uint32_t projectionWidth = this->getProjectionWidth();
|
||||
uint32_t projectionHeight = this->getProjectionHeight();
|
||||
|
||||
const float m1 = static_cast<float>(viewportWidth) / projectionWidth;
|
||||
const float m2 = static_cast<float>(viewportHeight) / projectionHeight;
|
||||
const float m = std::min(m1,m2);
|
||||
projectionWidth*=m;
|
||||
projectionHeight*=m;
|
||||
|
||||
if (projectionWidth!=viewportWidth)
|
||||
{
|
||||
this->updateUs(projectionWidth,projectionHeight);
|
||||
}
|
||||
else if (projectionHeight!=viewportHeight)
|
||||
{
|
||||
this->updateVs(projectionWidth,projectionHeight);
|
||||
}
|
||||
}
|
||||
|
||||
template<> void CWallpaperState::updateTextureUVs<CWallpaperState::TextureUVsScaling::DefaultUVs>(){
|
||||
this->resetUVs();
|
||||
|
||||
const int viewportWidth = this->getViewportWidth();
|
||||
const int viewportHeight = this->getViewportHeight();
|
||||
uint32_t projectionWidth = this->getProjectionWidth();
|
||||
uint32_t projectionHeight = this->getProjectionHeight();
|
||||
|
||||
if (
|
||||
(viewportHeight > viewportWidth && projectionWidth >= projectionHeight) ||
|
||||
(viewportWidth > viewportHeight && projectionHeight > projectionWidth)
|
||||
)
|
||||
{
|
||||
updateUs(projectionWidth,projectionHeight);
|
||||
}
|
||||
|
||||
if (
|
||||
(viewportWidth > viewportHeight && projectionWidth >= projectionHeight) ||
|
||||
(viewportHeight > viewportWidth && projectionHeight > projectionWidth)
|
||||
)
|
||||
{
|
||||
updateVs(projectionWidth,projectionHeight);
|
||||
}
|
||||
}
|
||||
|
||||
template<CWallpaperState::TextureUVsScaling T> void CWallpaperState::updateTextureUVs(){
|
||||
sLog.exception("Using generic template for scaling is not allowed. Write specialization template for your scaling mode.\
|
||||
This message is for developers, if you are just user it's a bug.");
|
||||
}
|
||||
|
||||
|
||||
void CWallpaperState::updateState(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight){
|
||||
this->viewport.width = viewport.z;
|
||||
this->viewport.height = viewport.w;
|
||||
this->vflip = vflip;
|
||||
this->projection.width = projectionWidth;
|
||||
this->projection.height = projectionHeight;
|
||||
|
||||
//Set texture UVs according to choosen scaling mode for this wallpaper
|
||||
switch (this->getTextureUVsScaling())
|
||||
{
|
||||
case CWallpaperState::TextureUVsScaling::StretchUVs :
|
||||
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::StretchUVs>();
|
||||
break;
|
||||
case CWallpaperState::TextureUVsScaling::ZoomFillUVs :
|
||||
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFillUVs>();
|
||||
break;
|
||||
case CWallpaperState::TextureUVsScaling::ZoomFitUVs :
|
||||
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::ZoomFitUVs>();
|
||||
break;
|
||||
case CWallpaperState::TextureUVsScaling::DefaultUVs :
|
||||
this->updateTextureUVs<CWallpaperState::TextureUVsScaling::DefaultUVs>();
|
||||
break;
|
||||
default:
|
||||
sLog.exception("Switch case for specified scaling mode doesn't exist. Add your realisation in switch statement.\
|
||||
This message is for developers, if you are just user it's a bug.");
|
||||
break;
|
||||
}
|
||||
}
|
99
src/WallpaperEngine/Render/CWallpaperState.h
Normal file
99
src/WallpaperEngine/Render/CWallpaperState.h
Normal file
@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
namespace WallpaperEngine::Render
|
||||
{
|
||||
/**
|
||||
* Represents current wallpaper state
|
||||
*/
|
||||
class CWallpaperState
|
||||
{
|
||||
public:
|
||||
// Scaling modes. Defines how UVs coordinates are calculated.
|
||||
enum class TextureUVsScaling : uint8_t
|
||||
{
|
||||
DefaultUVs,
|
||||
ZoomFitUVs,
|
||||
ZoomFillUVs,
|
||||
StretchUVs,
|
||||
};
|
||||
|
||||
CWallpaperState(const TextureUVsScaling& textureUVsMode) : m_textureUVsMode(textureUVsMode)
|
||||
{};
|
||||
|
||||
// Compares saved state values with passed arguments
|
||||
bool hasChanged(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight) const{
|
||||
return this->viewport.width != viewport.z || this->viewport.height != viewport.w ||
|
||||
this->projection.width != projectionWidth || this->projection.height != projectionHeight || this->vflip != vflip;
|
||||
}
|
||||
|
||||
// Reset UVs to 0/1 values
|
||||
void resetUVs();
|
||||
|
||||
// Update Us coordinates for current viewport and projection
|
||||
void updateUs(const int& projectionWidth, const int& projectionHeight);
|
||||
|
||||
// Update Vs coordinates for current viewport and projection
|
||||
void updateVs(const int& projectionWidth, const int& projectionHeight);
|
||||
|
||||
// Get texture UV coordinates
|
||||
auto getTextureUVs() const {return UVs;};
|
||||
|
||||
// Set texture UV coordinates according to texture scaling mode
|
||||
template<CWallpaperState::TextureUVsScaling> void updateTextureUVs();
|
||||
|
||||
// Updates state with provided values
|
||||
void updateState(const glm::ivec4& viewport, const bool& vflip, const int& projectionWidth, const int& projectionHeight);
|
||||
|
||||
// @return The texture scaling mode
|
||||
TextureUVsScaling getTextureUVsScaling () const { return m_textureUVsMode; };
|
||||
|
||||
// Set texture scaling mode
|
||||
void setTextureUVsStrategy(const TextureUVsScaling strategy) { m_textureUVsMode=strategy; } ;
|
||||
|
||||
// @return The width of viewport
|
||||
int getViewportWidth () const { return viewport.width;};
|
||||
|
||||
// @return The height of viewport
|
||||
int getViewportHeight () const { return viewport.height;};
|
||||
|
||||
// @return The width of viewport
|
||||
uint32_t getProjectionWidth () const { return projection.width;};
|
||||
|
||||
// @return The height of viewport
|
||||
uint32_t getProjectionHeight () const { return projection.height;};
|
||||
|
||||
private:
|
||||
// Cached UVs value for texture coordinates. No need to recalculate if viewport and projection haven't changed.
|
||||
struct
|
||||
{
|
||||
float ustart;
|
||||
float uend;
|
||||
float vstart;
|
||||
float vend;
|
||||
} UVs;
|
||||
|
||||
// Viewport for which UVs were calculated
|
||||
struct
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
} viewport{};
|
||||
|
||||
// Wallpaper dimensions
|
||||
struct
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} projection{};
|
||||
|
||||
// Are Vs coordinates fliped
|
||||
bool vflip = false;
|
||||
|
||||
// Texture scaling mode
|
||||
TextureUVsScaling m_textureUVsMode = TextureUVsScaling::DefaultUVs;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user