// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #include "blur_shader.h" #ifdef DRAGONX_HAS_GLAD #include #include #include #include "../../util/logger.h" namespace dragonx { namespace ui { namespace effects { // ============================================================================ // BlurShader Implementation (GLEW Available) // ============================================================================ BlurShader::BlurShader() = default; BlurShader::~BlurShader() { destroy(); } bool BlurShader::init() { // Create shaders vertexShader_ = glCreateShader(GL_VERTEX_SHADER); fragmentShader_ = glCreateShader(GL_FRAGMENT_SHADER); if (!compileShader(vertexShader_, ShaderSource::BLUR_VERTEX)) { DEBUG_LOGF("BlurShader: Failed to compile vertex shader\n"); destroy(); return false; } if (!compileShader(fragmentShader_, ShaderSource::BLUR_FRAGMENT)) { DEBUG_LOGF("BlurShader: Failed to compile fragment shader\n"); destroy(); return false; } // Create program program_ = glCreateProgram(); glAttachShader(program_, vertexShader_); glAttachShader(program_, fragmentShader_); if (!linkProgram()) { DEBUG_LOGF("BlurShader: Failed to link program\n"); destroy(); return false; } // Get uniform locations uTexture_ = glGetUniformLocation(program_, "uTexture"); uDirection_ = glGetUniformLocation(program_, "uDirection"); uResolution_ = glGetUniformLocation(program_, "uResolution"); uRadius_ = glGetUniformLocation(program_, "uRadius"); DEBUG_LOGF("BlurShader: Initialized successfully\n"); DEBUG_LOGF(" Uniforms: uTexture=%d, uDirection=%d, uResolution=%d, uRadius=%d\n", uTexture_, uDirection_, uResolution_, uRadius_); return true; } void BlurShader::destroy() { if (program_) { glDeleteProgram(program_); program_ = 0; } if (vertexShader_) { glDeleteShader(vertexShader_); vertexShader_ = 0; } if (fragmentShader_) { glDeleteShader(fragmentShader_); fragmentShader_ = 0; } uTexture_ = -1; uDirection_ = -1; uResolution_ = -1; uRadius_ = -1; } bool BlurShader::compileShader(unsigned int shader, const char* source) { glShaderSource(shader, 1, &source, nullptr); glCompileShader(shader); GLint success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { GLint logLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); std::vector log(logLength + 1); glGetShaderInfoLog(shader, logLength, nullptr, log.data()); DEBUG_LOGF("Shader compile error:\n%s\n", log.data()); return false; } return true; } bool BlurShader::linkProgram() { glLinkProgram(program_); GLint success; glGetProgramiv(program_, GL_LINK_STATUS, &success); if (!success) { GLint logLength; glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &logLength); std::vector log(logLength + 1); glGetProgramInfoLog(program_, logLength, nullptr, log.data()); DEBUG_LOGF("Program link error:\n%s\n", log.data()); return false; } return true; } void BlurShader::bind() { glUseProgram(program_); } void BlurShader::unbind() { glUseProgram(0); } void BlurShader::setDirection(bool horizontal) { if (uDirection_ >= 0) { if (horizontal) { glUniform2f(uDirection_, 1.0f, 0.0f); } else { glUniform2f(uDirection_, 0.0f, 1.0f); } } } void BlurShader::setRadius(float radius) { if (uRadius_ >= 0) { glUniform1f(uRadius_, radius); } } void BlurShader::setResolution(int width, int height) { if (uResolution_ >= 0) { glUniform2f(uResolution_, static_cast(width), static_cast(height)); } } void BlurShader::setTexture(int unit) { if (uTexture_ >= 0) { glUniform1i(uTexture_, unit); } } // ============================================================================ // FullscreenQuad Implementation // ============================================================================ FullscreenQuad::FullscreenQuad() = default; FullscreenQuad::~FullscreenQuad() { destroy(); } bool FullscreenQuad::init() { // Fullscreen quad vertices: position (x,y) and texcoord (u,v) // NDC coordinates: -1 to 1 static const float vertices[] = { // Position // TexCoord -1.0f, 1.0f, 0.0f, 1.0f, // Top-left -1.0f, -1.0f, 0.0f, 0.0f, // Bottom-left 1.0f, -1.0f, 1.0f, 0.0f, // Bottom-right -1.0f, 1.0f, 0.0f, 1.0f, // Top-left 1.0f, -1.0f, 1.0f, 0.0f, // Bottom-right 1.0f, 1.0f, 1.0f, 1.0f // Top-right }; glGenVertexArrays(1, &vao_); glGenBuffers(1, &vbo_); glBindVertexArray(vao_); glBindBuffer(GL_ARRAY_BUFFER, vbo_); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Position attribute (location = 0) glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // TexCoord attribute (location = 1) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glEnableVertexAttribArray(1); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); return vao_ != 0; } void FullscreenQuad::destroy() { if (vbo_) { glDeleteBuffers(1, &vbo_); vbo_ = 0; } if (vao_) { glDeleteVertexArrays(1, &vao_); vao_ = 0; } } void FullscreenQuad::draw() { glBindVertexArray(vao_); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); } } // namespace effects } // namespace ui } // namespace dragonx #else // !DRAGONX_HAS_GLAD // ============================================================================ // Stub Implementation (No GLAD - Acrylic effects disabled) // ============================================================================ namespace dragonx { namespace ui { namespace effects { BlurShader::BlurShader() = default; BlurShader::~BlurShader() = default; bool BlurShader::init() { return false; } void BlurShader::destroy() {} bool BlurShader::compileShader(unsigned int, const char*) { return false; } bool BlurShader::linkProgram() { return false; } void BlurShader::bind() {} void BlurShader::unbind() {} void BlurShader::setDirection(bool) {} void BlurShader::setRadius(float) {} void BlurShader::setResolution(int, int) {} void BlurShader::setTexture(int) {} FullscreenQuad::FullscreenQuad() = default; FullscreenQuad::~FullscreenQuad() = default; bool FullscreenQuad::init() { return false; } void FullscreenQuad::destroy() {} void FullscreenQuad::draw() {} } // namespace effects } // namespace ui } // namespace dragonx #endif // DRAGONX_HAS_GLAD