234 lines
6.5 KiB
C++
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
|