blocky/playground/input_noise.cc
2022-06-22 11:48:52 +09:00

104 lines
2.6 KiB
C++

#include "app.hh"
#include "input.hh"
#include <vector>
#include <imgui.h>
namespace pg {
namespace {
class Noise final : public App, public Input::Data {
public:
static inline TypeInfo kType = TypeInfo::Create<Noise>("Input_Noise");
static uint32_t xorshift(uint32_t x) noexcept {
x ^= x<<13;
x ^= x>>17;
x ^= x<<5;
return x;
}
Noise() noexcept : Data("random noise") {
}
void Update() noexcept override {
const auto id = std::to_string(index())+" Input_Noise | "+
std::to_string(reinterpret_cast<uintptr_t>(this));
if (ImGui::Begin(id.c_str())) {
ImGui::DragInt("src", &src_, 1, 0, 1024);
ImGui::DragInt("w", &w_, 1, 1, 1024);
ImGui::DragInt("h", &h_, 1, 1, 1024);
ImGui::DragFloat("level", &level_, 1e-4f, 0, 1);
ImGui::DragInt("seed", &seed_);
}
ImGui::End();
}
Frame Fetch(size_t n) noexcept override {
auto src = Input::instance().slots(static_cast<size_t>(src_));
if (!src) return {};
const auto w = static_cast<size_t>(w_);
const auto h = static_cast<size_t>(h_);
buf_.resize(w*h*4);
uint8_t* buf = buf_.data();
auto srcf = src->Fetch(n);
for (size_t y = 0; y < h; ++y) {
const auto yf = static_cast<float>(y)/static_cast<float>(h);
for (size_t x = 0; x < w; ++x) {
const auto xf = static_cast<float>(x)/static_cast<float>(w);
const auto srcx = static_cast<float>(srcf.w) * xf;
const auto srcy = static_cast<float>(srcf.h) * yf;
const auto srcxi = static_cast<size_t>(srcx);
const auto srcyi = static_cast<size_t>(srcy);
auto v = srcf.rgba + 4*(srcxi+srcyi*srcf.w);
for (size_t i = 0; i < 4; ++i) {
*(buf++) = TryAttack(n, x, y, i, *(v++));
}
}
}
return Frame { .w = w, .h = h, .rgba = buf_.data(), };
}
size_t frames() noexcept override {
auto src = Input::instance().slots(static_cast<size_t>(src_));
if(!src) return 0;
return src->frames();
}
uint8_t TryAttack(
size_t n, size_t x, size_t y, size_t i, uint8_t v) const noexcept {
if (i == 3) return v;
const auto s = static_cast<uint32_t>(seed_);
const auto seed = static_cast<uint32_t>(s*s*s*n + s*s*x + s*y + i);
const auto rand = xorshift(seed);
if (rand%100 < 50) {
const auto t = static_cast<float>(rand%100)/100.f*level_;
const auto a = static_cast<uint8_t>(t*UINT8_MAX);
return v+a;
} else {
return v;
}
}
private:
int src_ = 0;
int w_ = 100, h_ = 100;
float level_ = 0.01f;
int seed_ = 1234;
std::vector<uint8_t> buf_;
};
}
} // namespace pg