Files
demo/src/texture_generator.cpp
T
2022-04-23 17:14:02 +03:00

234 lines
6.5 KiB
C++

#include "texture_generator.h"
#include <cmath>
#include <memory>
#include <cstring>
BEGIN_NAMESPACE
texture_generator::texture_generator(uint16_t w, uint16_t h)
: width(w), height(h) {
for (auto &layer: layers)
layer = new uint8_t[width * height * 4];
}
texture_generator::~texture_generator() {
for (auto &layer: layers)
delete[] layer;
}
texture_generator &texture_generator::checker_board(uint8_t layer,
uint8_t block_size,
colour on,
colour off) {
auto *input = reinterpret_cast<uint32_t *>(layers[layer]);
uint32_t on_color = as_int(on);
uint32_t off_color = as_int(off);
for (auto y = 0; y < height; y++) {
for (auto x = 0; x < width; x++) {
bool in_block = (
((x % (2 * block_size)) < block_size) &&
((y % (2 * block_size)) < block_size)
);
*input++ = in_block ? on_color : off_color;
// *input++ = 0xffffffff;
}
}
return *this;
}
texture_generator &texture_generator::env_map(uint8_t layer, uint8_t size) {
auto *input = reinterpret_cast<uint32_t *>(layers[layer]);
colour col{1};
float size_squared = size * size;
for (uint16_t y = 0; y < height; y++) {
for (uint16_t x = 0; x < width; x++) {
int32_t rx = x - width / 2;
int32_t ry = y - height / 2;
float r_square = static_cast<float>(rx * rx + ry * ry);
if (r_square <= size_squared) {
float a = 1.0f - (r_square / size_squared);
col.r = col.g = col.b = a;
// col.a = 1;
} else {
col.r = col.g = col.b = 0;
// col.a = 1;
}
*input++ = as_int(col);
}
}
return *this;
}
texture_generator &texture_generator::lens(uint8_t layer, uint8_t size) {
auto *input = reinterpret_cast<uint32_t *>(layers[layer]);
colour col{0};
float size_squared = size * size;
float c;
for (uint16_t y = 0; y < height; y++) {
for (uint16_t x = 0; x < width; x++) {
int32_t rx = x - width / 2;
int32_t ry = y - height / 2;
auto r_squared = static_cast<float>(rx * rx + ry * ry);
if (r_squared <= size_squared) {
// double r = sqrt(static_cast<double>rsquare) / static_cast<double>(size);
float r = 0;
c = 1.0f - r;
c = c * c;
if (r > 1.0f)
c = 0.0f;
col = glm::vec4(c);
} else {
col = glm::vec4(0);
}
*input++ = as_int(col);
}
}
return *this;
}
texture_generator &texture_generator::roll(uint8_t layer, uint8_t x, uint8_t y) {
uint8_t *input = layers[layer];
auto *output = new uint8_t[width * height * 4];
uint8_t *out_ptr = output;
for (uint16_t j = 0; j < height; j++) {
for (uint16_t i = 0; i < width; i++) {
uint32_t index = ((j + y) % height) * width + ((i + x) % width);
*out_ptr++ = input[index * 4 + 0];
*out_ptr++ = input[index * 4 + 1];
*out_ptr++ = input[index * 4 + 2];
*out_ptr++ = input[index * 4 + 3];
}
}
memcpy(input, output, width * height * 4);
delete[] output;
return *this;
}
uint8_t *texture_generator::get(uint8_t layer) {
return layers[layer];
}
std::shared_ptr<texture> texture_generator::get_texture(uint8_t layer) {
return std::make_shared<texture>(width, height, get(layer));
}
texture_generator &texture_generator::white_noise(uint8_t layer) {
auto *input = reinterpret_cast<uint32_t *>(layers[layer]);
for (uint16_t y = 0; y < height; y++) {
for (uint16_t x = 0; x < width; x++) {
*input++ = rand();
}
}
return *this;
}
texture_generator &texture_generator::polar_grid(uint8_t layer) {
uint8_t *input = layers[layer];
auto *output = new uint8_t[width * height * 4];
uint8_t *out_ptr = output;
for (int j = 0; j < height; j++) {
double theta = M_PI * (j - (height - 1) / 2.0) / static_cast<double>(height - 1);
for (int i = 0; i < width; i++) {
double phi = 2 * M_PI * (i - width / 2.0) / static_cast<double>(width);
double phi2 = phi * cos(theta);
int i2 = phi2 * width / (2 * M_PI) + width / 2;
if (i2 < 0 || i2 > width - 1) {
*out_ptr++ = 255;
*out_ptr++ = 0;
*out_ptr++ = 0;
*out_ptr++ = 1;
} else {
*out_ptr++ = input[(j * width + i2) * 4 + 0];
*out_ptr++ = input[(j * width + i2) * 4 + 1];
*out_ptr++ = input[(j * width + i2) * 4 + 2];
*out_ptr++ = input[(j * width + i2) * 4 + 3];
}
}
}
memcpy(input, output, width * height * 4);
delete[] output;
return *this;
}
texture_generator &texture_generator::brick(uint8_t layer,
uint8_t brick_width,
uint8_t brick_height,
uint8_t gap_size,
colour mortar_col,
colour brick_col) {
auto *input = reinterpret_cast<uint32_t *>(layers[layer]);
uint32_t mortar = as_int(mortar_col);
uint32_t brick = as_int(brick_col);
for (int i = 0; i < width * height; i++) {
input[i] = brick;
}
int y = 0;
while (y < height) {
for (int i = 0; i < gap_size; i++) {
if ((y + i) < height) {
for (int x = 0; x < width; x++) {
input[x + (y + i) * width] = mortar;
}
}
}
y += brick_height + gap_size;
}
int offset = 0;
bool is_odd_row = false;
y = gap_size;
while (y < height) {
int x = is_odd_row ? 0 : brick_width / 2;
while (x < width) {
for (int i = 0; i < gap_size; i++) {
for (int current_brick_y = 0; current_brick_y < brick_height; current_brick_y++) {
input[x + i + (current_brick_y + y) * width] = mortar;
}
}
x += gap_size + brick_width;
}
y += brick_height + gap_size;
is_odd_row = !is_odd_row;
}
return *this;
}
END_NAMESPACE