Enhance video texture handling and add release build configurations
This commit is contained in:
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
@@ -19,6 +19,25 @@
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Release live-wallpaper",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/release/live-wallpaper",
|
||||
"args": [
|
||||
"${workspaceFolder}/samples/test.lua"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
22
.vscode/tasks.json
vendored
22
.vscode/tasks.json
vendored
@@ -25,6 +25,28 @@
|
||||
},
|
||||
"problemMatcher": "$gcc",
|
||||
"dependsOn": "CMake: configure debug"
|
||||
},
|
||||
{
|
||||
"label": "CMake: configure release",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"args": ["--preset", "release"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "CMake: build release",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"args": ["--build", "--preset", "release"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"group": "build",
|
||||
"problemMatcher": "$gcc",
|
||||
"dependsOn": "CMake: configure release"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ effect = nil
|
||||
|
||||
function _create()
|
||||
local fxSrc = [[
|
||||
in vec2 vPosition;
|
||||
|
||||
#define time uTime
|
||||
|
||||
mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);}
|
||||
|
||||
@@ -13,8 +13,6 @@ function _create()
|
||||
rockTexture:GenerateMipmaps()
|
||||
|
||||
local fxSrc = [[
|
||||
in vec2 vPosition;
|
||||
|
||||
uniform sampler2D iChannel0;
|
||||
|
||||
#define FAR 80.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
effect = nil
|
||||
|
||||
function _create()
|
||||
local fxSrc = [[in vec2 vPosition;
|
||||
|
||||
local fxSrc = [[
|
||||
void main() {
|
||||
vec2 uv = vPosition * 0.5 + 0.5;
|
||||
FragColor = vec4(uv, 0.5 + 0.5 * sin(uTime), 1.0);
|
||||
|
||||
@@ -5,8 +5,6 @@ effect = nil
|
||||
|
||||
function _create()
|
||||
local fxSrc = [[
|
||||
in vec2 vPosition;
|
||||
|
||||
const bool USE_MOUSE = false;
|
||||
|
||||
const float PI = 3.14159265;
|
||||
|
||||
@@ -2,16 +2,22 @@ effect = nil
|
||||
video = nil
|
||||
|
||||
function _create()
|
||||
video = Texture.FromGStreamer("filesrc location=/media/diego/Data/Projects/live-wallpaper/samples/video.mp4")
|
||||
video = Texture.FromGStreamer("filesrc location=" .. Resolve("sunset.mkv"))
|
||||
|
||||
local fxSrc = [[in vec2 vPosition;
|
||||
|
||||
uniform sampler2D uTexture;
|
||||
local fxSrc = [[uniform sampler2D uTexture;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vPosition * 0.5 + 0.5;
|
||||
uv.y = 1.0 - uv.y;
|
||||
FragColor = texture(uTexture, uv);
|
||||
vec2 uv = vUV;
|
||||
|
||||
for (int i = 0; i < uNumDisplays; i++) {
|
||||
vec4 displayNorm = uDisplayNorm[i];
|
||||
|
||||
if (vUV.x >= displayNorm.x && vUV.x <= displayNorm.x + displayNorm.z &&
|
||||
vUV.y >= displayNorm.y && vUV.y <= displayNorm.y + displayNorm.w) {
|
||||
FragColor = texture(uTexture, GetDisplayUV(uTexture, i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]
|
||||
effect = Effect.new(fxSrc)
|
||||
|
||||
Binary file not shown.
125
src/effect.cpp
125
src/effect.cpp
@@ -13,6 +13,106 @@
|
||||
|
||||
GLuint Effect::g_dummyVAO = 0;
|
||||
|
||||
static std::string shaderHeader = R"(#version 460 core
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec2 vUV;
|
||||
in vec2 vPosition;
|
||||
|
||||
uniform float uTime;
|
||||
uniform vec4 uMouse;
|
||||
uniform vec2 uDesktopSize;
|
||||
uniform vec4 uDisplay[16]; // support up to 16 displays, more can be added if needed
|
||||
uniform vec4 uDisplayNorm[16]; // pre-normalized display rects for convenience
|
||||
uniform int uNumDisplays;
|
||||
|
||||
#define MAX_DISPLAYS 16
|
||||
|
||||
// Background modes
|
||||
#define BG_FIT_WIDTH 0
|
||||
#define BG_FIT_HEIGHT 1
|
||||
#define BG_COVER 2
|
||||
#define BG_STRETCH 3
|
||||
#define BG_CONTAIN 4
|
||||
#define BG_TILE 5
|
||||
|
||||
vec2 GetDisplayUV(sampler2D tex, int displayIndex, int mode) {
|
||||
vec2 inUV = vec2(0.0);
|
||||
|
||||
if (displayIndex < 0 || displayIndex >= uNumDisplays) {
|
||||
// Entire desktop as fallback
|
||||
inUV = vUV;
|
||||
} else {
|
||||
// Map global UV to display-local [0,1]
|
||||
inUV = (vUV - uDisplayNorm[displayIndex].xy) / uDisplayNorm[displayIndex].zw;
|
||||
}
|
||||
|
||||
vec2 uv = inUV;
|
||||
|
||||
if (mode == BG_STRETCH) {
|
||||
// No adjustment needed
|
||||
return uv;
|
||||
}
|
||||
|
||||
vec4 display = uDisplay[displayIndex];
|
||||
float displayRatio = display.z / display.w;
|
||||
|
||||
vec2 texSize = vec2(textureSize(tex, 0));
|
||||
float textureRatio = texSize.x / texSize.y;
|
||||
|
||||
if (mode == BG_COVER) {
|
||||
if (displayRatio > textureRatio) {
|
||||
// Display wider: crop top/bottom
|
||||
float scale = textureRatio / displayRatio;
|
||||
uv.y = uv.y * scale + (1.0 - scale) * 0.5;
|
||||
} else {
|
||||
// Display taller: crop left/right
|
||||
float scale = displayRatio / textureRatio;
|
||||
uv.x = uv.x * scale + (1.0 - scale) * 0.5;
|
||||
}
|
||||
} else if (mode == BG_CONTAIN) {
|
||||
if (displayRatio > textureRatio) {
|
||||
// Display wider: pillarbox left/right
|
||||
float scale = displayRatio / textureRatio;
|
||||
uv.x = uv.x * scale + (1.0 - scale) * 0.5;
|
||||
} else {
|
||||
// Display taller: letterbox top/bottom
|
||||
float scale = textureRatio / displayRatio;
|
||||
uv.y = uv.y * scale + (1.0 - scale) * 0.5;
|
||||
}
|
||||
} else if (mode == BG_FIT_WIDTH) {
|
||||
// Scale to match display width, adjust Y
|
||||
float scale = textureRatio / displayRatio;
|
||||
uv.y = uv.y * scale + (1.0 - scale) * 0.5;
|
||||
} else if (mode == BG_FIT_HEIGHT) {
|
||||
// Scale to match display height, adjust X
|
||||
float scale = displayRatio / textureRatio;
|
||||
uv.x = uv.x * scale + (1.0 - scale) * 0.5;
|
||||
} else if (mode == BG_TILE) {
|
||||
// Tile at native texture resolution
|
||||
uv = uv * display.zw / texSize;
|
||||
}
|
||||
|
||||
return uv;
|
||||
}
|
||||
|
||||
// Default mode = BG_COVER
|
||||
vec2 GetDisplayUV(sampler2D tex, int displayIndex) {
|
||||
return GetDisplayUV(tex, displayIndex, BG_COVER);
|
||||
}
|
||||
|
||||
vec2 GetFullUV(sampler2D tex) {
|
||||
return GetDisplayUV(tex, -1, BG_COVER);
|
||||
}
|
||||
|
||||
vec2 GetFullUV(sampler2D tex, int mode) {
|
||||
return GetDisplayUV(tex, -1, mode);
|
||||
}
|
||||
|
||||
#line 1
|
||||
)";
|
||||
|
||||
static std::vector<std::string> SplitLines(const std::string& str) {
|
||||
std::vector<std::string> lines;
|
||||
size_t start = 0, end = 0;
|
||||
@@ -32,27 +132,13 @@ Effect::Effect(const std::string& fragmentShaderSource)
|
||||
#include "fx_vertex.glsl.h"
|
||||
;
|
||||
|
||||
std::string code =
|
||||
"#version 460 core\n\n"
|
||||
"out vec4 FragColor;\n\n"
|
||||
"uniform float uTime;\n"
|
||||
"uniform vec4 uMouse;\n"
|
||||
"uniform vec2 uDesktopSize;\n";
|
||||
|
||||
for (size_t i = 0; i < g_Displays.size(); i++) {
|
||||
code += "uniform vec4 uDisplay" + std::to_string(i) + ";\n";
|
||||
}
|
||||
|
||||
// reset line number
|
||||
code += "#line 1\n";
|
||||
|
||||
GLuint vertexShader = CreateShader(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
if (!vertexShader) {
|
||||
throw std::runtime_error("Failed to compile vertex shader");
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint fragmentShader = CreateShader(code + fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
GLuint fragmentShader = CreateShader(shaderHeader + fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
if (!fragmentShader) {
|
||||
glDeleteShader(vertexShader);
|
||||
throw std::runtime_error("Failed to compile fragment shader");
|
||||
@@ -122,6 +208,11 @@ void Effect::SetTexture(const std::string &name, const Texture& texture, size_t
|
||||
glUniform1i(GetUniformLocation(name), static_cast<GLint>(textureUnit));
|
||||
}
|
||||
|
||||
void Effect::SetInt(const std::string &name, int value)
|
||||
{
|
||||
glUniform1i(GetUniformLocation(name), value);
|
||||
}
|
||||
|
||||
void Effect::SetFloat(const std::string &name, float value)
|
||||
{
|
||||
glUniform1f(GetUniformLocation(name), value);
|
||||
@@ -156,8 +247,10 @@ void Effect::Render()
|
||||
SetVector4("uMouse", g_Mouse);
|
||||
SetVector2("uDesktopSize", g_DesktopSize);
|
||||
for (size_t i = 0; i < g_Displays.size(); i++) {
|
||||
SetVector4("uDisplay" + std::to_string(i), g_Displays[i]);
|
||||
SetVector4("uDisplay[" + std::to_string(i) + "]", g_Displays[i]);
|
||||
SetVector4("uDisplayNorm[" + std::to_string(i) + "]", g_Displays[i] / Vector4(g_DesktopSize, g_DesktopSize));
|
||||
}
|
||||
SetInt("uNumDisplays", static_cast<int>(g_Displays.size()));
|
||||
|
||||
glBindVertexArray(g_dummyVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
GLuint GetUniformLocation(const std::string& name);
|
||||
|
||||
void SetTexture(const std::string& name, const Texture& texture, size_t textureUnit);
|
||||
void SetInt(const std::string& name, int value);
|
||||
void SetFloat(const std::string& name, float value);
|
||||
void SetVector2(const std::string& name, const Vector2& value);
|
||||
void SetVector3(const std::string& name, const Vector3& value);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
R"(#version 460 core
|
||||
out vec2 vPosition;
|
||||
out vec2 vUV;
|
||||
|
||||
vec2 coords[] = vec2[](
|
||||
vec2(-1.0, -1.0),
|
||||
@@ -10,5 +11,8 @@ vec2 coords[] = vec2[](
|
||||
|
||||
void main() {
|
||||
vPosition = coords[gl_VertexID];
|
||||
vUV = vPosition * 0.5 + 0.5;
|
||||
vUV.y = 1.0 - vUV.y; // flip Y for texture coordinates
|
||||
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
})"
|
||||
13
src/lua.cpp
13
src/lua.cpp
@@ -328,13 +328,12 @@ static void RegisterTexture(sol::state& lua) {
|
||||
tex["CreateTexture3D"] = static_cast<std::unique_ptr<Texture3D>(*)(uint32_t, uint32_t, uint32_t, TextureFormatType)>(&Texture::CreateTexture);
|
||||
tex["CreateCubeMap"] = &Texture::CreateCubeMap;
|
||||
tex["FromGStreamer"] = &Texture::FromGStreamer;
|
||||
tex["FromFile"] = [](const std::string& filepath) -> std::unique_ptr<Texture2D> {
|
||||
std::filesystem::path p(filepath);
|
||||
if (p.is_relative() && !g_ScriptDir.empty()) {
|
||||
p = std::filesystem::path(g_ScriptDir) / p;
|
||||
}
|
||||
return Texture::FromFile(p.string());
|
||||
};
|
||||
tex["FromFile"] = &Texture::FromFile;
|
||||
|
||||
// ── Useful functions ───────────────────────────────────────────────
|
||||
lua.set_function("Resolve", [](const std::string& path) {
|
||||
return std::filesystem::absolute(std::filesystem::path(g_ScriptDir) / path).string();
|
||||
});
|
||||
}
|
||||
|
||||
static void RegisterFrameBuffer(sol::state& lua) {
|
||||
|
||||
27
src/main.cpp
27
src/main.cpp
@@ -171,24 +171,17 @@ int main(int argc, char* argv[])
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse position and button state
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
g_Mouse.x = static_cast<float>(event.motion.x);
|
||||
g_Mouse.y = static_cast<float>(event.motion.y);
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
g_Mouse.z = (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? 1.0f : 0.0f;
|
||||
} else if (event.button.button == SDL_BUTTON_RIGHT) {
|
||||
g_Mouse.w = (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? 1.0f : 0.0f;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Poll global mouse position (the window is click-through so it
|
||||
// receives no input events — query the pointer directly instead).
|
||||
{
|
||||
float gx, gy;
|
||||
SDL_MouseButtonFlags buttons = SDL_GetGlobalMouseState(&gx, &gy);
|
||||
g_Mouse.x = gx;
|
||||
g_Mouse.y = g_DesktopSize.y - gy;
|
||||
g_Mouse.z = (buttons & SDL_BUTTON_LMASK) ? 1.0f : 0.0f;
|
||||
g_Mouse.w = (buttons & SDL_BUTTON_RMASK) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
bool canRender = false;
|
||||
|
||||
@@ -271,6 +271,7 @@ public:
|
||||
constexpr Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
constexpr Vector4(const Vector2& v, float z = 0.0f, float w = 0.0f) : x(v.x), y(v.y), z(z), w(w) {}
|
||||
constexpr Vector4(const Vector3& v, float w = 0.0f) : x(v.x), y(v.y), z(v.z), w(w) {}
|
||||
constexpr Vector4(const Vector2& v1, const Vector2& v2) : x(v1.x), y(v1.y), z(v2.x), w(v2.y) {}
|
||||
|
||||
[[nodiscard]] constexpr Vector2 toVector2() const { return Vector2(x, y); }
|
||||
[[nodiscard]] constexpr Vector3 toVector3() const { return Vector3(x, y, z); }
|
||||
|
||||
Reference in New Issue
Block a user