mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 13:56:48 +08:00

* feat: added glslang and spirv-core for handling shaders, should provide better results than current systems
* fix: brought back proper include placement, should fix some shaders not working
* chore: dial down required version to 330
* fix: crash when taking screenshot
* fix: use glReadnPixels for X11 copying to be more memory safe
* chore: reverted part of last commit
* chore: delay initialization of browser until it's used once
* chore: do not initialize web browser unless explicitly needed
* chore: cleanup filesystem functions to use containers directly
* chore: memory cleanup fixes
* chore: fix glReadPixels for older opengl versions
* chore: remove shader patches as they shouldn't be needed anymore
* chore: initialise variables
* chore: update deps, actions and readme
* chore: make use of custon glslang and SPIRV-Cross
* Revert "chore: update deps, actions and readme"
This reverts commit c3fbc9340b
.
* chore: update actions to include submodules
* chore: do not depend on SPIRV-Tools
* fix: added log10 macro
* feat: update to latest glslang (swizzle and vec2/vec3/vec4 implicit casting to float)
* revert: delayed initialization of cef was causing issues, reverted
* chore: re-organized web wallpaper support to use custom scheme and better handle multiprocessing
* chore: make use of external repos for all deps instead of copying things manually and more cleanup work
* chore: wrong include file used in CGLSLContext.cpp
* chore: fix wayland generation folder not being present
* feat: somewhat support TEXB0004
* chore: improve function call matching and fallback to more lax method if no function is found
* chore: changed shader compilation slightly so they're passed onto glsl just once
* feat: swap android's fft implementation (which wasn't right) with kissfft's and fix update frequency issues
* chore: added missing dependency
* chore: added missing dep to PKGBUILD
* feat: add testing tools to run over all backgrounds and getting output data
* chore: jail CDirectory to the basepath and prevent accessing data outside of the main directory
* chore: process script now scales the previews so the html file is not too big
* chore: add showcase gallery to the README.md
* chore: update README
* chore: some readability improvements on code
* chore: fix segfault after code cleanup
* chore: make use of std::filesystem::canonical instead of basepath and slight typing changes on texture objects
* chore: fix path detection being wrong, make use of std::filesystem::path on CContainers
* chore: cleanup of the core part of the project
* chore: bring back std::move and make some methods const where it makes sense
* feat: added a pretty printer for easier debug and comparison between different versions of linux-wallpaperengine
* chore: refactored shader compilation code once more to be easier to follow and fixed the longstanding bug of #include not being added in the right place
* chore: more debug info for the pretty printer
* fix: some textures applied were not the right ones
* chore: properly set combos based on textures
* feat: take into account project properties for shader values
feat: proper parsing of combo values in shaders
fix: shader units weren't linked as they should
chore: more support for detecting shader things automatically
* fix: blending mode for passes using the wrong value
fix: shader uniforms from project properties should now be taken into account
* chore: use ubuntu 22 and ubuntu 24 as builders, ubuntu 20 is retired
* chore: use ubuntu 22 and ubuntu 24 as builders, ubuntu 20 is retired
* chore: hopefully fix github actions build
* refactor: simplified working with properties, constants and shader variables
* chore: remove a couple of todos that aren't needed anymore
* chore: simplify the texture detection a little bit, still work left to do
* fix: regression on texture setup not working properly
* fix: filenames with dots were not being handled properly
* chore: remove some uselesss messages
* chore: fixed std::string json values not casting anything to it as it was assumed
* fix: null user value for constants means it cannot be modified by the user
* chore: remove exception when a shader constant uses a non-existant property
* fix: angles can be an user setting too, also added detection for animation frames to show a warning
* fix: ensure variable information is not commented out by a line comment
* fix: shader includes weren't being processed properly
* chore: update to latest glslang and SPIRV-Cross to support non-integer array indices
* chore: make use of auto where it made sense
* feat: make use of in/out promotion on glslang-WallpaperEngine
feat: use glslang-WallpaperEngine linkin process as an extra validation
* chore: improve scripts for running the app
* chore: hide background structure dump behind a command-line switch
* chore: rewritten bloom effect as a json object inside C++ so it's easier to follow
* chore: removed deprecated parameters and switched to argparse instead of getopt
fix: clamping mode wasn't applied by background properly, only globally
* chore: removed help prompt from the output unless actually required
* fix: web subprocesses weren't launching due to parameter's parsing, temporal fix
* feat: added material command copy support
* feat: do not initialize some subsystems if they're disabled or not used by backgrounds
* chore: ignore type in combos as only seems to be used in the editor
* chore: update to latest glslang-WallpaperEngine changes
* chore: delete uniforms if they already exist before setting
* chore: more cleanup and fixes
* chore: more cleanup and fixes
* chore: more cleanup and fixes
* chore: update file functions to make use of shared_ptr/unique_ptr instead of copying things around
* chore: more changes to unique_ptr and shared_ptr
* chore: more changes to unique_ptr and shared_ptr
* chore: more changes to unique_ptr and shared_ptr
feat: improved render initialization process to make it easier and simpler to add new drivers (no more #ifdef in CWallpaperApplication.cpp)
* chore: change all is/as castings to use typeid so no string comparison takes place
* chore: more cleanup, default initialization of values wherever possible
* chore: moved more things to std::unique_ptr and std::shared_ptr
* chore: moved more things to std::unique_ptr and std::shared_ptr
* fix: browser context usage crashed the app
* chore: the setting controls fullscreen detection creation the same way audio works
* fix: ensure that at least one frame is rendered before detecting fullscreen windows
* chore: slight changes to output and documentation to properly reflect current build configuration
* chore: fix mipmap texture creation
* chore: fix pass uniforms not taking into account fragment shader's uniforms
chore: keep processed code in the shader sent to opengl so it appears on RenderDoc
* chore: formating issues by codefactor
* chore: do not use new to allocate the pretty printer
* fix: strchr wasn't properly done for window geometry
* chore: add recording mode for status page generation
* chore: update .gitignore
* chore: update script to make use of video generation instead of the old python scripts
* chore: also copy project.json so it can be used on the site too
* fix: regression on invisible images not being rendered
* feat: add option to disable camera parallax
* chore: add the reversing tools I have locally
* chore: mention some of the common issues in the README.md
* chore: take submodules into account for archlinux
* chore: missed cd "$pkgname" in arch's prepare step
273 lines
12 KiB
C++
273 lines
12 KiB
C++
#include "WallpaperEngine/Core/Objects/CImage.h"
|
|
#include "WallpaperEngine/Core/Objects/CSound.h"
|
|
|
|
#include "WallpaperEngine/Render/Objects/CImage.h"
|
|
#include "WallpaperEngine/Render/Objects/CSound.h"
|
|
|
|
#include "WallpaperEngine/Render/CWallpaperState.h"
|
|
|
|
#include "CScene.h"
|
|
#include "WallpaperEngine/Logging/CLog.h"
|
|
|
|
extern float g_Time;
|
|
extern float g_TimeLast;
|
|
|
|
using namespace WallpaperEngine;
|
|
using namespace WallpaperEngine::Render;
|
|
using namespace WallpaperEngine::Render::Wallpapers;
|
|
|
|
CScene::CScene (
|
|
std::shared_ptr<const Core::CWallpaper> wallpaper, CRenderContext& context, CAudioContext& audioContext,
|
|
const CWallpaperState::TextureUVsScaling& scalingMode,
|
|
const WallpaperEngine::Assets::ITexture::TextureFlags& clampMode
|
|
) :
|
|
CWallpaper (wallpaper, context, audioContext, scalingMode, clampMode) {
|
|
// caller should check this, if not a std::bad_cast is good to throw
|
|
const auto& scene = wallpaper->as <Core::Wallpapers::CScene> ();
|
|
// setup the scene camera
|
|
this->m_camera = new CCamera (this, scene->getCamera ());
|
|
|
|
// detect size if the orthogonal project is auto
|
|
if (scene->getOrthogonalProjection ()->isAuto ()) {
|
|
// calculate the size of the projection based on the size of everything
|
|
for (const auto& [id, sceneObject] : scene->getObjects ()) {
|
|
if (!sceneObject->is<Core::Objects::CImage> ())
|
|
continue;
|
|
|
|
const glm::vec2 size = sceneObject->as<Core::Objects::CImage> ()->getSize ();
|
|
|
|
scene->getOrthogonalProjection ()->setWidth (size.x);
|
|
scene->getOrthogonalProjection ()->setHeight (size.y);
|
|
}
|
|
}
|
|
|
|
this->m_parallaxDisplacement = {0, 0};
|
|
|
|
this->m_camera->setOrthogonalProjection (scene->getOrthogonalProjection ()->getWidth (),
|
|
scene->getOrthogonalProjection ()->getHeight ());
|
|
|
|
// setup framebuffers here as they're required for the scene setup
|
|
this->setupFramebuffers ();
|
|
|
|
// set clear color
|
|
const glm::vec3 clearColor = this->getScene ()->getClearColor ();
|
|
|
|
glClearColor (clearColor.r, clearColor.g, clearColor.b, 1.0f);
|
|
|
|
// create all objects based off their dependencies
|
|
for (const auto& [id, sceneObject] : scene->getObjects ())
|
|
this->createObject (sceneObject);
|
|
|
|
// copy over objects by render order
|
|
for (const auto& cur : scene->getObjectsByRenderOrder ()) {
|
|
auto obj = this->m_objects.find (cur->getId ());
|
|
|
|
// ignores not created objects like particle systems
|
|
if (obj == this->m_objects.end ())
|
|
continue;
|
|
|
|
this->m_objectsByRenderOrder.emplace_back (obj->second);
|
|
}
|
|
|
|
const uint32_t sceneWidth = scene->getOrthogonalProjection ()->getWidth ();
|
|
const uint32_t sceneHeight = scene->getOrthogonalProjection ()->getHeight ();
|
|
|
|
// create extra framebuffers for the bloom effect
|
|
this->_rt_4FrameBuffer =
|
|
this->createFBO ("_rt_4FrameBuffer", ITexture::TextureFormat::ARGB8888, ITexture::TextureFlags::ClampUVs, 1.0,
|
|
sceneWidth / 4, sceneHeight / 4, sceneWidth / 4, sceneHeight / 4);
|
|
this->_rt_8FrameBuffer =
|
|
this->createFBO ("_rt_8FrameBuffer", ITexture::TextureFormat::ARGB8888, ITexture::TextureFlags::ClampUVs, 1.0,
|
|
sceneWidth / 8, sceneHeight / 8, sceneWidth / 8, sceneHeight / 8);
|
|
this->_rt_Bloom = this->createFBO ("_rt_Bloom", ITexture::TextureFormat::ARGB8888, ITexture::TextureFlags::ClampUVs,
|
|
1.0, sceneWidth / 8, sceneHeight / 8, sceneWidth / 8, sceneHeight / 8);
|
|
|
|
//
|
|
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
|
|
// this custom image loads some effect files from the virtual container to achieve the same bloom effect
|
|
// this approach requires of two extra draw calls due to the way the effect works in official WPE
|
|
// (it renders directly to the screen, whereas here we never do that from a scene)
|
|
//
|
|
|
|
const std::string imagejson = "{"
|
|
"\t\"image\": \"models/wpenginelinux.json\","
|
|
"\t\"name\": \"bloomimagewpenginelinux\","
|
|
"\t\"visible\": true,"
|
|
"\t\"scale\": \"1.0 1.0 1.0\","
|
|
"\t\"angles\": \"0.0 0.0 0.0\","
|
|
"\t\"origin\": \"" +
|
|
std::to_string (sceneWidth / 2) + " " + std::to_string (sceneHeight / 2) +
|
|
" 0.0\","
|
|
"\t\"id\": -1" +
|
|
","
|
|
"\t\"effects\":"
|
|
"\t["
|
|
"\t\t{"
|
|
"\t\t\t\"file\": \"effects/wpenginelinux/bloomeffect.json\","
|
|
"\t\t\t\"id\": 15242000,"
|
|
"\t\t\t\"name\": \"\","
|
|
"\t\t\t\"passes\":"
|
|
"\t\t\t["
|
|
"\t\t\t\t{"
|
|
"\t\t\t\t\t\"constantshadervalues\":"
|
|
"\t\t\t\t\t{"
|
|
"\t\t\t\t\t\t\"bloomstrength\": " +
|
|
std::to_string (this->getScene ()->getBloomStrength ()) +
|
|
","
|
|
"\t\t\t\t\t\t\"bloomthreshold\": " +
|
|
std::to_string (this->getScene ()->getBloomThreshold ()) +
|
|
"\t\t\t\t\t}"
|
|
"\t\t\t\t},"
|
|
"\t\t\t\t{"
|
|
"\t\t\t\t\t\"constantshadervalues\":"
|
|
"\t\t\t\t\t{"
|
|
"\t\t\t\t\t\t\"bloomstrength\": " +
|
|
std::to_string (this->getScene ()->getBloomStrength ()) +
|
|
","
|
|
"\t\t\t\t\t\t\"bloomthreshold\": " +
|
|
std::to_string (this->getScene ()->getBloomThreshold ()) +
|
|
"\t\t\t\t\t}"
|
|
"\t\t\t\t},"
|
|
"\t\t\t\t{"
|
|
"\t\t\t\t\t\"constantshadervalues\":"
|
|
"\t\t\t\t\t{"
|
|
"\t\t\t\t\t\t\"bloomstrength\": " +
|
|
std::to_string (this->getScene ()->getBloomStrength ()) +
|
|
","
|
|
"\t\t\t\t\t\t\"bloomthreshold\": " +
|
|
std::to_string (this->getScene ()->getBloomThreshold ()) +
|
|
"\t\t\t\t\t}"
|
|
"\t\t\t\t}"
|
|
"\t\t\t]"
|
|
"\t\t}"
|
|
"\t],"
|
|
"\t\"size\": \"" +
|
|
std::to_string (sceneWidth) + " " + std::to_string (sceneHeight) +
|
|
"\""
|
|
"}";
|
|
const auto json = nlohmann::json::parse (imagejson);
|
|
|
|
// create image for bloom passes
|
|
if (this->getScene ()->isBloom ()) {
|
|
this->m_bloomObject = this->createObject (
|
|
WallpaperEngine::Core::CObject::fromJSON (json, scene->getProject (), this->getContainer ()));
|
|
|
|
this->m_objectsByRenderOrder.push_back (this->m_bloomObject);
|
|
}
|
|
}
|
|
|
|
Render::CObject* CScene::createObject (const Core::CObject* object) {
|
|
Render::CObject* renderObject = nullptr;
|
|
|
|
// ensure the item is not loaded already
|
|
const auto current = this->m_objects.find (object->getId ());
|
|
|
|
if (current != this->m_objects.end ())
|
|
return current->second;
|
|
|
|
// check dependencies too!
|
|
for (const auto& cur : object->getDependencies ()) {
|
|
// self-dependency is a possibility...
|
|
if (cur == object->getId ())
|
|
continue;
|
|
|
|
auto dep = this->getScene ()->getObjects ().find (cur);
|
|
|
|
if (dep != this->getScene ()->getObjects ().end ())
|
|
this->createObject (dep->second);
|
|
}
|
|
|
|
if (object->is<Core::Objects::CImage> ()) {
|
|
auto* image = new Objects::CImage (this, object->as<Core::Objects::CImage> ());
|
|
|
|
try {
|
|
image->setup ();
|
|
} catch (std::runtime_error&) {
|
|
// this error message is already printed, so just show extra info about it
|
|
sLog.error ("Cannot setup image ", image->getImage ()->getName ());
|
|
}
|
|
|
|
renderObject = image;
|
|
} else if (object->is<Core::Objects::CSound> ()) {
|
|
renderObject = new Objects::CSound (this, object->as<Core::Objects::CSound> ());
|
|
}
|
|
|
|
if (renderObject != nullptr)
|
|
this->m_objects.emplace (renderObject->getId (), renderObject);
|
|
|
|
return renderObject;
|
|
}
|
|
|
|
CCamera* CScene::getCamera () const {
|
|
return this->m_camera;
|
|
}
|
|
|
|
void CScene::renderFrame (glm::ivec4 viewport) {
|
|
// ensure the virtual mouse position is up to date
|
|
this->updateMouse (viewport);
|
|
|
|
// update the parallax position if required
|
|
if (this->getScene ()->isCameraParallax () && !this->getContext ().getApp ().getContext ().settings.mouse.disableparallax) {
|
|
const float influence = this->getScene ()->getCameraParallaxMouseInfluence ();
|
|
const float amount = this->getScene ()->getCameraParallaxAmount ();
|
|
const float delay =
|
|
glm::min (static_cast<float> (this->getScene ()->getCameraParallaxDelay ()), g_Time - g_TimeLast);
|
|
|
|
this->m_parallaxDisplacement =
|
|
glm::mix (this->m_parallaxDisplacement, (this->m_mousePosition * amount) * influence, delay);
|
|
}
|
|
|
|
// use the scene's framebuffer by default
|
|
glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer ());
|
|
// ensure we render over the whole framebuffer
|
|
glViewport (0, 0, this->m_sceneFBO->getRealWidth (), this->m_sceneFBO->getRealHeight ());
|
|
|
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
for (const auto& cur : this->m_objectsByRenderOrder)
|
|
cur->render ();
|
|
}
|
|
|
|
void CScene::updateMouse (glm::ivec4 viewport) {
|
|
// update virtual mouse position first
|
|
const glm::dvec2 position = this->getContext ().getInputContext ().getMouseInput ().position ();
|
|
// TODO: PROPERLY TRANSLATE THESE TO WHAT'S VISIBLE ON SCREEN (FOR BACKGROUNDS THAT DO NOT EXACTLY FIT ON SCREEN)
|
|
|
|
// rollover the position to the last
|
|
this->m_mousePositionLast = this->m_mousePosition;
|
|
|
|
// calculate the current position of the mouse
|
|
this->m_mousePosition.x = glm::clamp ((position.x - viewport.x) / viewport.z, 0.0, 1.0);
|
|
this->m_mousePosition.y = glm::clamp ((position.y - viewport.y) / viewport.w, 0.0, 1.0);
|
|
|
|
// screen-space positions have to be transposed to what the screen will actually show
|
|
}
|
|
|
|
const Core::Wallpapers::CScene* CScene::getScene () const {
|
|
return this->getWallpaperData ()->as<Core::Wallpapers::CScene> ();
|
|
}
|
|
|
|
int CScene::getWidth () const {
|
|
return this->getScene ()->getOrthogonalProjection ()->getWidth ();
|
|
}
|
|
|
|
int CScene::getHeight () const {
|
|
return this->getScene ()->getOrthogonalProjection ()->getHeight ();
|
|
}
|
|
|
|
glm::vec2* CScene::getMousePosition () {
|
|
return &this->m_mousePosition;
|
|
}
|
|
|
|
glm::vec2* CScene::getMousePositionLast () {
|
|
return &this->m_mousePositionLast;
|
|
}
|
|
|
|
glm::vec2* CScene::getParallaxDisplacement () {
|
|
return &this->m_parallaxDisplacement;
|
|
}
|
|
|
|
const std::vector<CObject*>& CScene::getObjectsByRenderOrder () const {
|
|
return this->m_objectsByRenderOrder;
|
|
}
|