// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #include "noise_texture.h" #include "texture_loader.h" #include #include namespace dragonx { namespace util { static constexpr int kNoiseSize = 256; ImTextureID GetNoiseTexture(int* texSize) { static ImTextureID s_tex = 0; static bool s_init = false; if (texSize) *texSize = kNoiseSize; if (s_init) return s_tex; s_init = true; // Generate subtle white-noise RGBA pixels. // Each pixel is white (RGB=255) with alpha in a narrow band // around 128 so the grain is uniform and gentle. const int numPixels = kNoiseSize * kNoiseSize; unsigned char* pixels = (unsigned char*)malloc(numPixels * 4); if (!pixels) return 0; // Simple LCG PRNG (deterministic, fast, no need for crypto quality) unsigned int seed = 0xDEADBEEF; for (int i = 0; i < numPixels; ++i) { seed = seed * 1664525u + 1013904223u; // Range: 16–240 (centered on 128, ±112) for visible, high-contrast grain unsigned char v = 16 + (unsigned char)((seed >> 24) % 225); pixels[i * 4 + 0] = 255; // R pixels[i * 4 + 1] = 255; // G pixels[i * 4 + 2] = 255; // B pixels[i * 4 + 3] = v; // A — high contrast variation } bool ok = CreateRawTexture(pixels, kNoiseSize, kNoiseSize, true /* repeat/tile */, &s_tex); free(pixels); if (!ok) { s_tex = 0; } return s_tex; } // ============================================================================ // Pre-tiled viewport-sized noise texture // ============================================================================ // Generate the base 256x256 noise pattern into a caller-allocated buffer. // Same deterministic LCG as GetNoiseTexture(). static void GenerateBaseNoise(unsigned char* out, int sz) { unsigned int seed = 0xDEADBEEF; const int numPixels = sz * sz; for (int i = 0; i < numPixels; ++i) { seed = seed * 1664525u + 1013904223u; unsigned char v = 16 + (unsigned char)((seed >> 24) % 225); out[i * 4 + 0] = 255; out[i * 4 + 1] = 255; out[i * 4 + 2] = 255; out[i * 4 + 3] = v; } } ImTextureID GetTiledNoiseTexture(int viewportW, int viewportH, int* outW, int* outH) { static ImTextureID s_tex = 0; static int s_texW = 0; static int s_texH = 0; if (outW) *outW = s_texW; if (outH) *outH = s_texH; // Re-use if viewport hasn't changed if (s_tex && s_texW == viewportW && s_texH == viewportH) { return s_tex; } // Destroy old texture if (s_tex) { DestroyTexture(s_tex); s_tex = 0; s_texW = s_texH = 0; } if (viewportW <= 0 || viewportH <= 0) return 0; // Generate base tile unsigned char* base = (unsigned char*)malloc(kNoiseSize * kNoiseSize * 4); if (!base) return 0; GenerateBaseNoise(base, kNoiseSize); // Allocate viewport-sized buffer and tile the base pattern const size_t rowBytes = (size_t)viewportW * 4; unsigned char* tiled = (unsigned char*)malloc(rowBytes * viewportH); if (!tiled) { free(base); return 0; } const int basePitch = kNoiseSize * 4; for (int y = 0; y < viewportH; ++y) { int sy = y % kNoiseSize; unsigned char* dst = tiled + y * rowBytes; const unsigned char* srcRow = base + sy * basePitch; int x = 0; // Copy full tile-width strips while (x + kNoiseSize <= viewportW) { memcpy(dst + x * 4, srcRow, basePitch); x += kNoiseSize; } // Partial remaining strip if (x < viewportW) { memcpy(dst + x * 4, srcRow, (viewportW - x) * 4); } } free(base); bool ok = CreateRawTexture(tiled, viewportW, viewportH, false /* no repeat needed */, &s_tex); free(tiled); if (ok) { s_texW = viewportW; s_texH = viewportH; } else { s_tex = 0; } if (outW) *outW = s_texW; if (outH) *outH = s_texH; return s_tex; } void DrawTiledNoiseRect(ImDrawList* dl, const ImVec2& pMin, const ImVec2& pMax, ImU32 tintColor) { if (!dl || (tintColor & IM_COL32_A_MASK) == 0) return; ImGuiViewport* vp = ImGui::GetMainViewport(); int vpW = (int)vp->Size.x; int vpH = (int)vp->Size.y; if (vpW <= 0 || vpH <= 0) return; int texW = 0, texH = 0; ImTextureID tex = GetTiledNoiseTexture(vpW, vpH, &texW, &texH); if (!tex || texW <= 0 || texH <= 0) return; // Compute UVs: map screen-space rect to texture coordinates. // The tiled texture covers the entire viewport, so UV = screenPos / vpSize. // Subtract viewport origin for multi-viewport support. float u0 = (pMin.x - vp->Pos.x) / (float)texW; float v0 = (pMin.y - vp->Pos.y) / (float)texH; float u1 = (pMax.x - vp->Pos.x) / (float)texW; float v1 = (pMax.y - vp->Pos.y) / (float)texH; dl->AddImage(tex, pMin, pMax, ImVec2(u0, v0), ImVec2(u1, v1), tintColor); } } // namespace util } // namespace dragonx