Compare commits

...

14 Commits

Author SHA1 Message Date
Annika 3acd7de9a7 minor cleanup 2026-07-25 23:50:05 -07:00
Annika 1c2579148e moved textures into their own classes, better tilemapping 2026-07-25 23:47:54 -07:00
Annika e6ce80ce13 basic tilemapping 2026-07-25 21:53:33 -07:00
Annika 5298e75fdb added origin to mapper parameters 2026-07-24 19:06:14 -07:00
Annika eddbb85256 added mappers to rest of primatives 2026-07-24 18:31:49 -07:00
Annika 78ec985f7a header files, cleanup 2026-07-24 18:10:35 -07:00
Annika a89ef52247 added basic mappers 2026-07-24 18:01:59 -07:00
Annika c7cdfd402e started arc/circle plotting algorithm 2026-07-20 15:03:13 -07:00
Annika ee2c66f97b implemented H and V GradientShaders 2026-07-20 14:31:28 -07:00
Annika 8a00e42f75 completed CRTP shader migration 2026-07-20 02:08:40 -07:00
Annika 90df991e7e CRTP shaders on Lines 2026-07-20 02:08:06 -07:00
Annika 3588a41657 CRTP shaders on Lines 2026-07-20 02:04:17 -07:00
Annika 0f0e352fca shaders headerfile, and added CRTP shader to Point 2026-07-20 01:52:30 -07:00
Annika 444143ced9 implemented CRTP shader on ColorShader and Rectangle 2026-07-20 01:41:10 -07:00
34 changed files with 580 additions and 477 deletions
+19
View File
@@ -0,0 +1,19 @@
shapes:
triangles:
point
line
solid
gradient
rectangle
solid
gradient
blitter (tilemaps)
triangle
solid
gradient
perspective mapping (3D!!!)
quad
solid
gradient (charts)
blitter (isometric)
affine mapping (sprite rotation and scaling)
+127
View File
@@ -0,0 +1,127 @@
# UwUGL Styleguide
This document describes the coding conventions used in UwUGL, inferred from the existing codebase. It prioritizes readability and simplicity for a small graphics library.
---
## 1. File Organization
- **Single monolithic header**: `uwugl.h` is the public entry point and includes all implementation files.
- **Header-like `.cpp` files**: Every implementation file begins with `#pragma once` and is designed to be `#include`d directly by `uwugl.h` (or by other `.cpp` files). There are no traditional separate `.h`/`.cpp` pairs.
- **No separate headers for internal modules**: Classes and structs are declared and defined directly in `.cpp` files.
- **Exception**: `shaders/shaders.h` is a small aggregator file that includes the shader `.cpp` files.
- **Directory layout**:
- `primatives/` — shape classes (`Line`, `Point`, `Rectangle`, `Trapezoid`, `Triangle`)
- `shaders/` — shader classes and base
- `waymini/` — external Wayland helper library (C)
## 2. Naming Conventions
- **Namespace**: All library code lives in `namespace UwU`.
- **Classes / structs**: PascalCase (`Buffer`, `ColorShader`, `Rectangle`, `Helpers`).
- **Functions / methods**: camelCase (`drawPixel`, `lerpColor`, `bresenham`, `shouldClose`).
- **Member variables**: lowercase with no prefix (`pixels`, `width`, `x0`, `c`).
- **Template parameters**: PascalCase ending in `T` (`ShaderT`).
- **Enums**: PascalCase type name; UPPER_SNAKE_CASE values (`ShaderType`, `COLOR`, `HGRADIENT`, `VGRADIENT`).
- **Constants in code**: prefer lowercase; UPPER_SNAKE_CASE may be used for local compile-time-ish constants in comments or test code.
- **Filenames**: lowercase and descriptive (`buffer.cpp`, `colorshader.cpp`, `line.cpp`).
## 3. Formatting
- **Indentation**: 2 spaces.
- **Brace style**: K&R — opening brace on the same line as the class/function/control statement.
- **Pointer/reference syntax**: attach `*` and `&` to the variable name:
- `uint8_t* pixels`
- `ShaderBase<ShaderT>& shader`
- **Empty parameter lists**: use `()` for default constructors, e.g., `Color() {}`.
- **Spacing around operators**: use spaces around binary operators for readability (`x + y` instead of `x+y`).
- **Explicit `return;` at end of void functions**: Acceptable, but not required.
- **Comments**: use `//` for both inline and block-style comments. Keep them informal and focused on intent or known issues.
## 4. Includes
Include order within a file:
1. `#pragma once`
2. C/C++ standard headers (`<stdint.h>`, `<stdio.h>`, `<algorithm>`)
3. Project implementation files via relative paths (`"../datatypes.cpp"`, `"../buffer.cpp"`)
External C library headers (e.g., `"waymini/waymini.h"`) are included where needed.
## 5. Code Patterns
- **Composition over inheritance**: primitives hold data; shaders are passed into `draw()`.
- **CRTP for shaders**: `ShaderBase<ShaderT>` uses the Curiously Recurring Template Pattern for static polymorphism.
- **Template `draw` methods**: every primitive's `draw()` is templated on `ShaderT` and takes `(Buffer buffer, ShaderBase<ShaderT>& shader)`.
- **Manual memory management**: `new uint8_t[...]` in `Buffer`; no smart pointers.
- **C-style casts**: `(uint16_t)x`, `(uint8_t*)ptr`.
- **Bounds checks**: primitives guard `draw()` with `if (x > buffer.width || y > buffer.height) {return;};`.
- **Unused parameter suppression**: use `(void)param;` to silence warnings.
## 6. C++ Feature Usage
### Used
- Classes and structs
- Namespaces
- Templates (`template <class ShaderT>`)
- CRTP (Curiously Recurring Template Pattern)
- Function overloading (constructors)
- References
- C-style casts
- `new` / `new[]` for dynamic allocation
- Raw pointers
- Stack-allocated arrays
- C standard headers (`<stdint.h>`, `<stdio.h>`, `<stdlib.h>`, `<string.h>`, `<time.h>`, `<algorithm>`)
### Not Used but Allowed
- Smart pointers (`std::unique_ptr`, `std::shared_ptr`)
- Standard containers (`std::vector`, `std::array`, etc.)
- `enum class`
- Exceptions
- `std::string`
- `std::chrono`
- `std::function`
### Not Used
The following features are intentionally not used. This keeps the codebase small, predictable, and easy to reason about.
- `auto`
- Range-based `for` loops
- `nullptr`
- Lambda expressions
- `constexpr` / `consteval`
- `using` type aliases
- Move semantics / rvalue references
- Default member initializers
- Delegating constructors
- `override` / `final`
- Named casts (`static_cast`, `reinterpret_cast`, etc.)
- Structured bindings
- Concepts / `requires` (C++20)
- Virtual functions / runtime polymorphism / abstract base classes
- Operator overloading
- RTTI / `dynamic_cast` / `typeid`
- `<iostream>` (use C-style `printf`/`fflush`)
## 7. Build System
- **Makefile-based**.
- C library (`waymini`) compiled with `gcc`.
- Main example compiled with `g++`.
- Flags: `-Wall -Wextra -O3`, plus Wayland client flags from `pkg-config`.
## 8. Known Inconsistencies and Recommendations
The codebase currently has a few inconsistencies. The following recommendations aim to improve readability without adding complexity:
- **Indentation consistency**: some blocks are not aligned (e.g., `line.cpp` inner loop). Keep all indentation strictly at 2 spaces per level.
- **Spacing consistency**: standardize on spaces around binary operators and after commas.
- **Include consistency**: some primitives include `../shaders/shaders.h` while `rectangle.cpp` also includes `../shaders/shaderbase.cpp` directly. Prefer the aggregator `shaders.h` everywhere.
- **`return;` at end of void functions**: acceptable, but can be omitted when it adds no clarity.
- **Bounds check style**: the pattern `if (...) {return;};` has a redundant semicolon. Prefer `if (...) { return; }`.
---
This guide should evolve with the project. When in doubt, favor simplicity and consistency with the existing code.
+1 -1
View File
@@ -1,4 +1,4 @@
[ ] write a monolithic header file [x] write a monolithic header file
[x] refactor example code using composition [x] refactor example code using composition
[x] remove draw class entirely [x] remove draw class entirely
[x] create shader classes with polymorphism [x] create shader classes with polymorphism
+9 -9
View File
@@ -26,15 +26,15 @@ namespace UwU {
}; };
// Coord2 datatype for xy coordinates, from top-left of surface // Coord2 datatype for xy coordinates, from top-left of surface
// struct Coord2 { struct Coord2 {
// Coord2(uint16_t x, uint16_t y) { Coord2(uint16_t x, uint16_t y) {
// this->x = x; this->x = x;
// this->y = y; this->y = y;
// } }
// Coord2() {} Coord2() {}
// uint16_t x; uint16_t x;
// uint16_t y; uint16_t y;
// }; };
// Vec2 datatype for signed x, y coordinates // Vec2 datatype for signed x, y coordinates
// struct Vec2 { // struct Vec2 {
BIN
View File
Binary file not shown.
+55 -96
View File
@@ -7,21 +7,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "datatypes.cpp" #include "uwugl.h"
#include "helpers.cpp"
#include "buffer.cpp"
#include "surface.cpp"
#include "primatives/line.cpp"
#include "primatives/point.cpp"
#include "primatives/rectangle.cpp"
#include "primatives/trapezoid.cpp"
#include "primatives/triangle.cpp"
#include "shader.cpp"
#include <time.h> #include <time.h>
#include "font.cpp" #include "font.cpp"
static void onKey(void *user, uint32_t keycode, uint32_t state) { static void onKey(void *user, uint32_t keycode, uint32_t state) {
if (keycode == 1) { if (keycode == 1) {
exit(1); exit(1);
@@ -34,99 +24,68 @@ static void onKey(void *user, uint32_t keycode, uint32_t state) {
int main(void) { int main(void) {
uint16_t w = 800, h = 480; uint16_t w = 800, h = 480;
UwU::Shader fuchsia = UwU::Shader(UwU::Direction::V, 100, 300, UwU::Color(0xb00b69ff), UwU::Color(0x00000000));
UwU::Shader red = UwU::Shader(UwU::Direction::V, 69, 420, UwU::Color(0xff0000ff), UwU::Color(0x00000000));
UwU::Shader bisexual = UwU::Shader(UwU::Direction::H, 0, 799, UwU::Color(0xff0000ff), UwU::Color(0x0000ffff));
UwU::Shader aqua = UwU::Shader(UwU::Direction::V, 2, 349, UwU::Color(0x00ff00ff), UwU::Color(0x0000ffff));
UwU::Shader warmup = UwU::Shader(UwU::Color(0xb00b69ff));
UwU::Shader green = UwU::Shader(UwU::Color(0x00ff00ff));
UwU::Color blue = UwU::Color(0x0000ff80);
// UwU::Color alpha = UwU::Color(0x00000000);
UwU::Surface surface = UwU::Surface(w, h, onKey); UwU::Surface surface = UwU::Surface(w, h, onKey);
UwU::Buffer buffer = UwU::Buffer(800, 480);
UwU::Shader gradientBuffer = UwU::Shader(69, 69, buffer); // UwU::Color fuchsia = UwU::Color(0xb00b69ff);
UwU::Color red = UwU::Color(0xff0000ff);
UwU::Color green = UwU::Color(0x00ff00ff);
UwU::Color blue = UwU::Color(0x0000ffff);
// UwU::ColorTexture fuchsia = UwU::ColorTexture(UwU::Color(0xb00b69ff));
UwU::HGradientTexture bisexual = UwU::HGradientTexture(180, red, blue);
UwU::OffsetMapper offsetMapper = UwU::OffsetMapper();
UwU::Tilemap myTilemap = UwU::Tilemap();
myTilemap.tilemap[0] = 0x0000;
myTilemap.tilemap[1] = 0x0001;
myTilemap.tilemap[2] = 0x0000;
myTilemap.tilemap[3] = 0x0002;
myTilemap.tilemap[4] = 0x0003;
UwU::Buffer fontBuffer = font();
UwU::TilemapTexture textMap = UwU::TilemapTexture(myTilemap, fontBuffer);
UwU::Rectangle rectangle = UwU::Rectangle(69, 69, 420, 420); UwU::Rectangle rectangle = UwU::Rectangle(69, 69, 420, 420);
UwU::Rectangle bgRectangle = UwU::Rectangle(2, 2, 797, 477); rectangle.draw(surface.buffer, offsetMapper, textMap);
UwU::Trapezoid trapezoid = UwU::Trapezoid(300, 400, 360, 380, 600, 480);
UwU::Triangle triangle = UwU::Triangle(280, 100, 240, 290, 320, 300);
UwU::Point point = UwU::Point(387, 43);
// Window Header UwU::ColorTexture greenTexture = UwU::ColorTexture(green);
UwU::Trapezoid trap0 = UwU::Trapezoid(0, 7, 7, 0, 792, 799); UwU::NullMapper nullMapper = UwU::NullMapper();
UwU::Rectangle rect1 = UwU::Rectangle(0, 8, 799, 23); UwU::Point point = UwU::Point(187, 37);
UwU::Trapezoid trap2 = UwU::Trapezoid(24, 31, 0, 0, 71, 63); point.draw(surface.buffer, nullMapper, greenTexture);
UwU::Trapezoid trap3 = UwU::Trapezoid(24, 31, 727, 736, 799, 799);
// trap0.draw(surface.buffer, bisexual);
// rect1.draw(surface.buffer, bisexual);
// trap2.draw(surface.buffer, bisexual);
// trap3.draw(surface.buffer, bisexual);
// Window Body UwU::ColorTexture blueTexture = UwU::ColorTexture(blue);
UwU::Shader sU1 = UwU::Shader(8, 8, font()); UwU::Trapezoid trapezoid = UwU::Trapezoid(100, 300, 690, 320, 720, 780);
UwU::Shader sw1 = UwU::Shader(10, 8, font()); trapezoid.draw(surface.buffer, nullMapper, blueTexture);
UwU::Shader sU2 = UwU::Shader(28, 8, font());
UwU::Shader sG1 = UwU::Shader(20, 8, font());
UwU::Shader sL1 = UwU::Shader(22, 8, font());
UwU::Rectangle rU1 = UwU::Rectangle(8, 8, 13, 16);
UwU::Rectangle rw1 = UwU::Rectangle(16, 8, 25, 16);
UwU::Rectangle rU2 = UwU::Rectangle(28, 8, 33, 16);
UwU::Rectangle rG1 = UwU::Rectangle(36, 8, 41, 16);
UwU::Rectangle rL1 = UwU::Rectangle(44, 8, 48, 16);
rU1.draw(surface.buffer, sU1);
rw1.draw(surface.buffer, sw1);
rU2.draw(surface.buffer, sU2);
rG1.draw(surface.buffer, sG1);
rL1.draw(surface.buffer, sL1);
// Window Footer UwU::ColorTexture redTexture = UwU::ColorTexture(red);
UwU::Trapezoid trap5 = UwU::Trapezoid(440, 471, 712, 689, 799, 799); UwU::Triangle triangle = UwU::Triangle(140, 140, 60, 400, 240, 240);
UwU::Trapezoid trap6 = UwU::Trapezoid(472, 479, 0, 7, 799, 792); triangle.draw(surface.buffer, offsetMapper, bisexual);
trap5.draw(surface.buffer, bisexual);
trap6.draw(surface.buffer, bisexual);
// Window Buttons
UwU::Trapezoid trap7 = UwU::Trapezoid(448, 455, 728, 720, 791, 791);
UwU::Rectangle rect8 = UwU::Rectangle(720, 456, 791, 463);
UwU::Trapezoid trap9 = UwU::Trapezoid(464, 471, 720, 720, 791, 783);
trap7.draw(surface.buffer, fuchsia);
rect8.draw(surface.buffer, fuchsia);
trap9.draw(surface.buffer, fuchsia);
bgRectangle.draw(buffer, aqua);
// Benchmarking // // Benchmarking
struct timespec start, end; // struct timespec start, end;
const int WARMUP = 100; // const int WARMUP = 100;
const int BATCH = 1000; // const int BATCH = 1000;
const int SAMPLES = 10; // const int SAMPLES = 10;
for (int i = 0; i < WARMUP; i++) { // for (int i = 0; i < WARMUP; i++) {
rectangle.draw(surface.buffer, gradientBuffer); // rectangle.draw(surface.buffer, gradientBuffer);
} // }
long times[SAMPLES]; // long times[SAMPLES];
for (int s = 0; s < SAMPLES; s++) { // for (int s = 0; s < SAMPLES; s++) {
clock_gettime(CLOCK_MONOTONIC, &start); // clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < BATCH; i++) { // for (int i = 0; i < BATCH; i++) {
rectangle.draw(surface.buffer, gradientBuffer); // rectangle.draw(surface.buffer, gradientBuffer);
} // }
clock_gettime(CLOCK_MONOTONIC, &end); // clock_gettime(CLOCK_MONOTONIC, &end);
times[s] = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec); // times[s] = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec);
} // }
long timeAvg = 0; // long timeAvg = 0;
for (int i = 0; i < SAMPLES; i++) { // for (int i = 0; i < SAMPLES; i++) {
timeAvg += times[i]; // timeAvg += times[i];
} // }
timeAvg /= SAMPLES; // timeAvg /= SAMPLES;
timeAvg /= BATCH; // timeAvg /= BATCH;
printf("Elapsed: %ld ns\n", timeAvg); // printf("Elapsed: %ld ns\n", timeAvg);
triangle.draw(surface.buffer, fuchsia);
trapezoid.draw(surface.buffer, red);
point.draw(surface.buffer, green);
UwU::Line lines[8] { UwU::Line lines[8] {
UwU::Line(300, 100, 250, 469), UwU::Line(300, 100, 250, 469),
UwU::Line(250, 100, 300, 469), UwU::Line(250, 100, 300, 469),
@@ -139,7 +98,7 @@ int main(void) {
}; };
for (uint16_t i = 0; i < 8; i++) { for (uint16_t i = 0; i < 8; i++) {
lines[i].draw(surface.buffer, bisexual); lines[i].draw(surface.buffer, nullMapper, blueTexture);
} }
+4
View File
@@ -90,5 +90,9 @@ namespace UwU {
} }
return; return;
} }
// plot a 90 degree arc
static void fastArc(uint16_t radius, uint16_t* LUT) {
}
}; };
} }
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
namespace UwU {
template <class MapperT>
class MapperBase {
public:
Coord2 map(uint16_t x0, uint16_t y0, uint16_t x, uint16_t y) {
return static_cast<MapperT*>(this)->map(x0, y0, x, y);
}
};
}
+4
View File
@@ -0,0 +1,4 @@
#include "mapperbase.cpp"
#include "nullmapper.cpp"
#include "offsetmapper.cpp"
// #include "tilemapper.cpp"
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "mapperbase.cpp"
namespace UwU {
class NullMapper : public MapperBase<NullMapper> {
public:
NullMapper() {}
Coord2 map(uint16_t x0, uint16_t y0, uint16_t x, uint16_t y) {
(void)x0;
(void)y0;
return Coord2(x, y);
}
};
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "mapperbase.cpp"
namespace UwU {
class OffsetMapper : public MapperBase<OffsetMapper> {
public:
OffsetMapper() {}
Coord2 map(uint16_t x0, uint16_t y0, uint16_t x, uint16_t y) {
uint16_t u = x -x0;
uint16_t v = y -y0;
return Coord2(u, v);
}
};
}
+27 -95
View File
@@ -5,14 +5,16 @@
#include "../datatypes.cpp" #include "../datatypes.cpp"
#include "../helpers.cpp" #include "../helpers.cpp"
#include "../buffer.cpp" #include "../buffer.cpp"
#include "../shader.cpp" #include "../mappers/mappers.h"
#include "../textures/textures.h"
namespace UwU { namespace UwU {
// line // line
class Line { class Line {
private: private:
// plot lines if m <= 1 // plot lines if m <= 1
void lineLow(int16_t ix0, int16_t iy0, int16_t ix1, int16_t iy1, Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void lineLow(int16_t ix0, int16_t iy0, int16_t ix1, int16_t iy1, Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
int16_t dx = ix1 - ix0; int16_t dx = ix1 - ix0;
int16_t dy = iy1 - iy0; int16_t dy = iy1 - iy0;
int16_t yi = 1; int16_t yi = 1;
@@ -23,59 +25,24 @@ namespace UwU {
int16_t d = (2 * dy) - dx; int16_t d = (2 * dy) - dx;
int16_t y = iy0; int16_t y = iy0;
if (shader.shaderType == COLOR) { Coord2 uv;
for (int16_t x = ix0; x < ix1; x++) {
buffer.drawPixel((uint16_t)x, (uint16_t)y, shader.c0);
if (d > 0) {
y += yi;
d += (2 * (dy - dx));
} else {
d += (2 * dy);
}
}
return;
} else if (shader.shaderType == HGRADIENT) { for (int16_t x = ix0; x < ix1; x++) {
for (int16_t x = ix0; x < ix1; x++) { uv = mapper.map(ix0, iy0, x, y);
buffer.drawPixel((uint16_t)x, (uint16_t)y, ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x)); buffer.drawPixel((uint16_t)x, (uint16_t)y, texture.texel(uv.x, uv.y));
if (d > 0) { if (d > 0) {
y += yi; y += yi;
d += (2 * (dy - dx)); d += (2 * (dy - dx));
} else { } else {
d += (2 * dy); d += (2 * dy);
}
} }
return;
} else if (shader.shaderType == VGRADIENT) {
for (int16_t x = ix0; x < ix1; x++) {
buffer.drawPixel((uint16_t)x, (uint16_t)y, ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, y));
if (d > 0) {
y += yi;
d += (2 * (dy - dx));
} else {
d += (2 * dy);
}
}
return;
} else if (shader.shaderType == BUFFER) {
for (int16_t x = ix0; x < ix1; x++) {
buffer.drawPixel((uint16_t)x, (uint16_t)y, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, y));
if (d > 0) {
y += yi;
d += (2 * (dy - dx));
} else {
d += (2 * dy);
}
}
return;
} }
return; return;
} }
// plot lines if m >1 // plot lines if m >1
void lineHigh(int16_t ix0, int16_t iy0, int16_t ix1, int16_t iy1, Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void lineHigh(int16_t ix0, int16_t iy0, int16_t ix1, int16_t iy1, Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
int16_t dx = ix1 - ix0; int16_t dx = ix1 - ix0;
int16_t dy = iy1 - iy0; int16_t dy = iy1 - iy0;
int16_t xi = 1; int16_t xi = 1;
@@ -86,55 +53,19 @@ namespace UwU {
int16_t d = (2 * dx) - dy; int16_t d = (2 * dx) - dy;
int16_t x = ix0; int16_t x = ix0;
if (shader.shaderType == COLOR) { Coord2 uv;
for (int16_t y = iy0; y < iy1; y++) {
buffer.drawPixel((uint16_t)x, (uint16_t)y, shader.c0);
if (d > 0) {
x += xi;
d += (2 * (dx - dy));
} else {
d += (2 * dx);
}
}
return;
} else if (shader.shaderType == HGRADIENT) { for (int16_t y = iy0; y < iy1; y++) {
for (int16_t y = iy0; y < iy1; y++) { uv = mapper.map(ix0, iy0, x, y);
buffer.drawPixel((uint16_t)x, (uint16_t)y, ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x)); buffer.drawPixel((uint16_t)x, (uint16_t)y, texture.texel(uv.x, uv.y));
if (d > 0) { if (d > 0) {
x += xi; x += xi;
d += (2 * (dx - dy)); d += (2 * (dx - dy));
} else { } else {
d += (2 * dx); d += (2 * dx);
} }
} }
return; return;
} else if (shader.shaderType == VGRADIENT) {
for (int16_t y = iy0; y < iy1; y++) {
buffer.drawPixel((uint16_t)x, (uint16_t)y, ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, y));
if (d > 0) {
x += xi;
d += (2 * (dx - dy));
} else {
d += (2 * dx);
}
}
return;
} else if (shader.shaderType == BUFFER) {
for (int16_t y = iy0; y < iy1; y++) {
buffer.drawPixel((uint16_t)x, (uint16_t)y, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, y));
if (d > 0) {
x += xi;
d += (2 * (dx - dy));
} else {
d += (2 * dx);
}
}
return;
}
return;
} }
public: public:
@@ -151,7 +82,8 @@ namespace UwU {
uint16_t y1; uint16_t y1;
// Uses Bresenham's line algorithm to draw line of any slope // Uses Bresenham's line algorithm to draw line of any slope
void draw (Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void draw (Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
if (x0 > buffer.width || y0 > buffer.height || x1 > buffer.width || y1 > buffer.height) {return;}; if (x0 > buffer.width || y0 > buffer.height || x1 > buffer.width || y1 > buffer.height) {return;};
int16_t ix0 = x0; int16_t ix0 = x0;
int16_t iy0 = y0; int16_t iy0 = y0;
@@ -159,15 +91,15 @@ namespace UwU {
int16_t iy1 = y1; int16_t iy1 = y1;
if (abs(iy1 - iy0) < abs(ix1 - ix0)) { if (abs(iy1 - iy0) < abs(ix1 - ix0)) {
if (ix0 > ix1) { if (ix0 > ix1) {
lineLow(ix1, iy1, ix0, iy0, buffer, shader); lineLow(ix1, iy1, ix0, iy0, buffer, mapper, texture);
} else { } else {
lineLow(ix0, iy0, ix1, iy1, buffer, shader); lineLow(ix0, iy0, ix1, iy1, buffer, mapper, texture);
} }
} else { } else {
if (iy0 > iy1) { if (iy0 > iy1) {
lineHigh(ix1, iy1, ix0, iy0, buffer, shader); lineHigh(ix1, iy1, ix0, iy0, buffer, mapper, texture);
} else { } else {
lineHigh(ix0, iy0, ix1, iy1, buffer, shader); lineHigh(ix0, iy0, ix1, iy1, buffer, mapper, texture);
} }
} }
return; return;
+7 -16
View File
@@ -5,7 +5,8 @@
#include "../datatypes.cpp" #include "../datatypes.cpp"
#include "../helpers.cpp" #include "../helpers.cpp"
#include "../buffer.cpp" #include "../buffer.cpp"
#include "../shader.cpp" #include "../mappers/mappers.h"
#include "../textures/textures.h"
namespace UwU { namespace UwU {
// point // point
@@ -19,22 +20,12 @@ namespace UwU {
uint16_t x; uint16_t x;
uint16_t y; uint16_t y;
// Draw a rectangle // Draw a point
void draw (Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void draw (Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
if (x > buffer.width || y > buffer.height) {return;}; if (x > buffer.width || y > buffer.height) {return;};
Coord2 uv = mapper.map(x, y, x, y);
if (shader.shaderType == COLOR) { buffer.drawPixel(x, y, texture.texel(uv.x, uv.y));
buffer.drawPixel(x, y, shader.c0);
return;
} else if (shader.shaderType == HGRADIENT) {
buffer.drawPixel(x, y, ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x));
return;
} else if (shader.shaderType == VGRADIENT) {
buffer.drawPixel(x, y, ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, y));
return;
} else if (shader.shaderType == BUFFER) {
buffer.drawPixel(x, y, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, y));
}
return; return;
} }
}; };
+5
View File
@@ -0,0 +1,5 @@
#include "point.cpp"
#include "line.cpp"
#include "rectangle.cpp"
#include "trapezoid.cpp"
#include "triangle.cpp"
+7 -39
View File
@@ -5,7 +5,8 @@
#include "../datatypes.cpp" #include "../datatypes.cpp"
#include "../helpers.cpp" #include "../helpers.cpp"
#include "../buffer.cpp" #include "../buffer.cpp"
#include "../shader.cpp" #include "../mappers/mappers.h"
#include "../textures/textures.h"
namespace UwU { namespace UwU {
// rectangle // rectangle
@@ -24,47 +25,14 @@ namespace UwU {
uint16_t y1; uint16_t y1;
// Draw a rectangle // Draw a rectangle
void draw (Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void draw (Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
if (x0 > buffer.width || y0 > buffer.height || x1 > buffer.width || y1 > buffer.height) {return;}; if (x0 > buffer.width || y0 > buffer.height || x1 > buffer.width || y1 > buffer.height) {return;};
if (shader.shaderType == COLOR) { for (uint16_t y = y0; y <= y1; y++) {
for (uint16_t y = y0; y <= y1; y++) {
for (uint16_t x = x0; x <= x1; x++) {
buffer.drawPixel(x, y, shader.c0);
}
}
return;
} else if (shader.shaderType == HGRADIENT) {
// Precompute gradient LUT
Color cols[x1 - x0];
for (uint16_t x = x0; x <= x1; x++) { for (uint16_t x = x0; x <= x1; x++) {
cols[x - x0] = ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x); Coord2 uv = mapper.map(x0, y0, x, y);
buffer.drawPixel(x, y, texture.texel(uv.x, uv.y));
} }
for (uint16_t y = y0; y <= y1; y++) {
for (uint16_t x = x0; x <= x1; x++) {
buffer.drawPixel(x, y, cols[x - x0]);
}
}
return;
} else if (shader.shaderType == VGRADIENT) {
for (uint16_t y = y0; y <= y1; y++) {
Color c = ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, y);
for (uint16_t x = x0; x <= x1; x++) {
buffer.drawPixel(x, y, c);
}
}
return;
} else if (shader.shaderType == BUFFER) {
for (uint16_t y = y0; y <= y1; y++) {
for (uint16_t x = x0; x <= x1; x++) {
buffer.drawPixel(x, y, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, y));
}
}
return;
} }
return; return;
} }
+10 -44
View File
@@ -6,7 +6,8 @@
#include "../datatypes.cpp" #include "../datatypes.cpp"
#include "../helpers.cpp" #include "../helpers.cpp"
#include "../buffer.cpp" #include "../buffer.cpp"
#include "../shader.cpp" #include "../mappers/mappers.h"
#include "../textures/textures.h"
namespace UwU { namespace UwU {
// trapezoid (horizontally constrained) // trapezoid (horizontally constrained)
@@ -30,57 +31,22 @@ namespace UwU {
// Draw a horizontally bounded trapezoid // Draw a horizontally bounded trapezoid
// y1 >= y0 // y1 >= y0
void draw (Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void draw (Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
uint16_t height = 1 + y1 - y0; uint16_t height = 1 + y1 - y0;
int16_t LeftBound[height]; int16_t LeftBound[height];
int16_t RightBound[height]; int16_t RightBound[height];
Helpers::bresenham(0, xl0, y1 - y0, xl1, LeftBound); Helpers::bresenham(0, xl0, y1 - y0, xl1, LeftBound);
Helpers::bresenham(0, xr0, y1 - y0, xr1, RightBound); Helpers::bresenham(0, xr0, y1 - y0, xr1, RightBound);
uint16_t x0 = std::min(xl0, xl1);
if (shader.shaderType == COLOR) { for (uint16_t i = 0; i < height; i++) {
for (uint16_t i = 0; i < height; i++) { for (uint16_t x = LeftBound[i]; x <= RightBound[i]; x++) {
for (uint16_t x = LeftBound[i]; x <= RightBound[i]; x++) { Coord2 uv = mapper.map(x0, y0, x, i + y0);
buffer.drawPixel(x, i + y0, shader.c0); buffer.drawPixel(x, i + y0, texture.texel(uv.x, uv.y));
}
} }
return;
} else if (shader.shaderType == HGRADIENT) {
// find left-right boundaries
uint16_t leftmost = std::min(xl0, xl1);
uint16_t rightmost = std::max(xr0, xr1);
// precompute gradient LUT
Color cols[rightmost - leftmost];
for (uint16_t x = leftmost; x < rightmost; x++) {
cols[x - leftmost] = ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x);
}
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = LeftBound[i]; x <= RightBound[i]; x++) {
buffer.drawPixel(x, i + y0, cols[x - leftmost]);
}
}
return;
} else if (shader.shaderType == VGRADIENT) {
Color c;
for (uint16_t i = 0; i < height; i++) {
c = ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, i + y0);
for (uint16_t x = LeftBound[i]; x <= RightBound[i]; x++) {
buffer.drawPixel(x, i + y0, c);
}
}
return;
} else if (shader.shaderType == BUFFER) {
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = LeftBound[i]; x <= RightBound[i]; x++) {
buffer.drawPixel(x, i + y0, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, i + y0));
}
}
return;
} }
return; return;
} }
+19 -83
View File
@@ -6,7 +6,8 @@
#include "../datatypes.cpp" #include "../datatypes.cpp"
#include "../helpers.cpp" #include "../helpers.cpp"
#include "../buffer.cpp" #include "../buffer.cpp"
#include "../shader.cpp" #include "../mappers/mappers.h"
#include "../textures/textures.h"
namespace UwU { namespace UwU {
class Triangle { class Triangle {
@@ -30,7 +31,8 @@ namespace UwU {
uint16_t y2; uint16_t y2;
// Draw a triangle // Draw a triangle
void draw (Buffer buffer, Shader shader) { template <class MapperT, class TextureT>
void draw (Buffer buffer, MapperBase<MapperT>& mapper, TextureBase<TextureT>& texture) {
uint16_t topX, topY, midX, midY, btmX, btmY; uint16_t topX, topY, midX, midY, btmX, btmY;
// Find top, middle and bottom points of triangle // Find top, middle and bottom points of triangle
if (y0 <= y1 && y0 <= y2) { if (y0 <= y1 && y0 <= y2) {
@@ -90,91 +92,25 @@ namespace UwU {
Helpers::bresenham(0, topX, midY - topY, midX, splitBound); Helpers::bresenham(0, topX, midY - topY, midX, splitBound);
Helpers::bresenham(midY - topY, midX, height - 1, btmX, splitBound); Helpers::bresenham(midY - topY, midX, height - 1, btmX, splitBound);
if (shader.shaderType == COLOR) { Coord2 uv;
// Left-handed triangle case (midpoint is left of triangle) uint16_t leftX = std::min(topX, std::min(midX, btmX));
if ((int16_t)midX < longBound[midY - topY]) {
for (uint16_t i = 0; i < height; i++) { // Left-handed triangle case (midpoint is left of triangle)
for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) { if ((int16_t)midX < longBound[midY - topY]) {
buffer.drawPixel(x, i + (uint16_t)topY, shader.c0); for (uint16_t i = 0; i < height; i++) {
} for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) {
} uv = mapper.map(leftX, topY, x, i + (uint16_t)topY);
// Right-handed triangle case (midpoint is right of triangle) buffer.drawPixel(x, i + (uint16_t)topY, texture.texel(uv.x, uv.y));
} else {
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, shader.c0);
}
} }
} }
return; // Right-handed triangle case (midpoint is right of triangle)
} else {
} else if (shader.shaderType == HGRADIENT) { for (uint16_t i = 0; i < height; i++) {
// find left and right bounds for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) {
uint16_t leftmost = std::min(x0, std::min(x1, x2)); uv = mapper.map(leftX, topY, x, i + (uint16_t)topY);
uint16_t rightmost = std::max(x0, std::max(x1, x2)); buffer.drawPixel(x, i + (uint16_t)topY, texture.texel(uv.x, uv.y));
// precompute gradient LUT
Color cols[rightmost - leftmost];
for (uint16_t x = leftmost; x < rightmost; x++) {
cols[x - leftmost] = ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x);
}
// Left-handed triangle case (midpoint is left of triangle)
if ((int16_t)midX < longBound[midY - topY]) {
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, cols[x - leftmost]);
}
}
// Right-handed triangle case (midpoint is right of triangle)
} else {
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, cols[x - leftmost]);
}
} }
} }
return;
} else if (shader.shaderType == VGRADIENT) {
Color c;
// Left-handed triangle case (midpoint is left of triangle)
if ((int16_t)midX < longBound[midY - topY]) {
for (uint16_t i = 0; i < height; i++) {
c = ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, i + topY);
for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, c);
}
}
// Right-handed triangle case (midpoint is right of triangle)
} else {
for (uint16_t i = 0; i < height; i++) {
c = ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, i + topY);
for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, c);
}
}
}
return;
} else if (shader.shaderType == BUFFER) {
// Left-handed triangle case (midpoint is left of triangle)
if ((int16_t)midX < longBound[midY - topY]) {
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, i + topY));
}
}
// Right-handed triangle case (midpoint is right of triangle)
} else {
for (uint16_t i = 0; i < height; i++) {
for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) {
buffer.drawPixel(x, i + (uint16_t)topY, ShaderMethods::buffer(shader.u0, shader.v0, shader.buffer, x, i + topY));
}
}
}
return;
} }
return; return;
} }
-70
View File
@@ -1,70 +0,0 @@
#pragma once
#include <stdint.h>
#include "datatypes.cpp"
#include "helpers.cpp"
#include "buffer.cpp"
namespace UwU {
// shader prototype
class Shader {
public:
//COLOR Shader
Shader(Color color) {
this->shaderType = COLOR;
this->c0 = color;
}
//HGRADIENT or VGRADIENT shader
Shader(Direction direction, uint16_t uv0, uint16_t uv1, Color c0, Color c1) {
this->c0 = c0;
this->c1 = c1;
switch (direction) {
case H:
shaderType = HGRADIENT;
this->u0 = uv0;
this->scale = 0xffffffff / (1 + (uint32_t)uv1 - (uint32_t)uv0);
break;
case V:
shaderType = VGRADIENT;
this->v0 = uv0;
this->scale = 0xffffffff / (1 + (uint32_t)uv1 - (uint32_t)uv0);
break;
}
}
// BUFFER shader
Shader(uint16_t u, uint16_t v, Buffer buffer) {
this->shaderType = BUFFER;
this->u0 = u;
this->v0 = v;
this->buffer = buffer;
}
ShaderType shaderType;
uint16_t u0;
uint16_t v0;
Color c0;
Color c1;
uint32_t scale;
Buffer buffer;
};
class ShaderMethods {
public:
static Color gradient(uint16_t uv0, uint32_t scale, Color c0, Color c1, uint16_t xy) {
uint32_t t = (((uint32_t)xy - (uint32_t)uv0) * scale) / 0x01000000;
return Helpers::lerpColor(c0, c1, (uint8_t)t);
}
static Color buffer(uint16_t u0, uint16_t v0, Buffer buffer, uint16_t x, uint16_t y) {
size_t i = ((size_t)y - (size_t)v0) * buffer.stride + ((size_t)x - (size_t)u0) * 4;
uint8_t b = buffer.pixels[i + 0];
uint8_t g = buffer.pixels[i + 1];
uint8_t r = buffer.pixels[i + 2];
uint8_t a = buffer.pixels[i + 3];
return Color(r, g, b, a);
}
};
}
-22
View File
@@ -1,22 +0,0 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "shaderbase.cpp"
namespace UwU {
class ColorShader : public ShaderBase<ColorShader> {
public:
ColorShader(Color c) {
this->c = c;
}
Color c;
Color shade(uint16_t x, uint16_t y) {
return c;
}
};
}
+2 -2
View File
@@ -7,11 +7,11 @@
#include "../buffer.cpp" #include "../buffer.cpp"
namespace UwU { namespace UwU {
template <typename Derived> template <class ShaderT>
class ShaderBase { class ShaderBase {
public: public:
Color shade(uint16_t x, uint16_t y) { Color shade(uint16_t x, uint16_t y) {
return static_cast<Derived*>(this)->shade(x, y); return static_cast<ShaderT*>(this)->shade(x, y);
} }
}; };
} }
+1
View File
@@ -0,0 +1 @@
#include "shaderbase.cpp"
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "texturebase.cpp"
namespace UwU {
class BitmapTexture : public TextureBase<BitmapTexture> {
private:
Buffer buffer;
public:
BitmapTexture(Buffer buffer) {
this->buffer = buffer;
}
Color texel(uint16_t u, uint16_t v) {
uint32_t index = (v * buffer.stride) + (u * 4);
Color c = Color(buffer.pixels[index + 2], buffer.pixels[index + 1], buffer.pixels[index], buffer.pixels[index + 3]);
return c;
}
};
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "texturebase.cpp"
namespace UwU {
class ColorTexture : public TextureBase<ColorTexture> {
private:
Color color;
public:
ColorTexture(Color color) {
this->color = color;
}
Color texel(uint16_t u, uint16_t v) {
(void)u;
(void)v;
return color;
}
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "texturebase.cpp"
namespace UwU {
class GradientTexture : public TextureBase<GradientTexture> {
public:
GradientTexture(uint16_t width, Color c0, Color c1) {
this->uScale = 0xffffffff / (1 + (uint32_t)width);
this->c0 = c0;
this->c1 = c1;
}
uint32_t uScale;
Color c0;
Color c1;
Color texel(uint16_t u, uint16_t v) {
(void)v;
uint32_t t = (((uint32_t)u) * uScale) / 0x01000000;
return Helpers::lerpColor(c0, c1, (uint8_t)t);
}
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "texturebase.cpp"
namespace UwU {
class HGradientTexture : public TextureBase<HGradientTexture> {
public:
HGradientTexture(uint16_t width, Color c0, Color c1) {
this->uScale = 0xffffffff / (1 + (uint32_t)width);
this->c0 = c0;
this->c1 = c1;
}
uint32_t uScale;
Color c0;
Color c1;
Color texel(uint16_t u, uint16_t v) {
(void)v;
uint32_t t = (((uint32_t)u) * uScale) / 0x01000000;
return Helpers::lerpColor(c0, c1, (uint8_t)t);
}
};
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
namespace UwU {
template <class TextureT>
class TextureBase {
public:
Color texel(uint16_t u, uint16_t v) {
return static_cast<TextureT*>(this)->texel(u, v);
}
};
}
+7
View File
@@ -0,0 +1,7 @@
#include "texturebase.cpp"
#include "colortexture.cpp"
#include "bitmaptexture.cpp"
#include "tilemaptexture.cpp"
#include "hgradienttexture.cpp"
#include "vgradienttexture.cpp"
// #include "gradienttexture.cpp"
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "texturebase.cpp"
#include "../tilemap.cpp"
namespace UwU {
class TilemapTexture : public TextureBase<TilemapTexture> {
private:
Buffer buffer;
Tilemap tilemap;
public:
TilemapTexture(Tilemap tilemap, Buffer buffer) {
this->buffer = buffer;
this->tilemap = tilemap;
}
Color texel(uint16_t u, uint16_t v) {
Coord2 bitmapUV = tilemap.map(u, v);
uint32_t index = (bitmapUV.y * buffer.stride) + (bitmapUV.x * 4);
Color c = Color(buffer.pixels[index + 2], buffer.pixels[index + 1], buffer.pixels[index], buffer.pixels[index + 3]);
return c;
}
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include "../datatypes.cpp"
#include "../helpers.cpp"
#include "../buffer.cpp"
#include "texturebase.cpp"
namespace UwU {
class VGradientTexture : public TextureBase<VGradientTexture> {
public:
VGradientTexture(uint16_t height, Color c0, Color c1) {
this->vScale = 0xffffffff / (1 + (uint32_t)height);
this->c0 = c0;
this->c1 = c1;
}
uint32_t vScale;
Color c0;
Color c1;
Color texel(uint16_t u, uint16_t v) {
(void)u;
uint32_t t = (((uint32_t)v) * vScale) / 0x01000000;
return Helpers::lerpColor(c0, c1, (uint8_t)t);
}
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include "datatypes.cpp"
#include "helpers.cpp"
namespace UwU {
class Tilemap {
public:
Tilemap() {
this->tilemap = new uint16_t[16384]; // the map of tile positions 128x128 8x8 tiles from a 512x512 bitmap space
}
uint16_t* tilemap;
Coord2 map(uint16_t u, uint16_t v) {
// returns uv coordinates that point to a specific pixel of a specific tile on a tilesheet buffer
uint16_t mapX = (u & 0x03f8) >> 3;
uint16_t mapY = (v & 0x03f8) << 4;
uint16_t tileIndex = tilemap[mapY + mapX];
uint16_t u1 = (tileIndex & 0x003f) << 3;
u1 += (u & 0x0007);
uint16_t v1 = (tileIndex & 0x0fc0) >> 3;
v1 += (v & 0x0007);
return Coord2(u1, v1);
}
};
}
+9
View File
@@ -0,0 +1,9 @@
#include "datatypes.cpp"
#include "helpers.cpp"
#include "buffer.cpp"
#include "surface.cpp"
#include "primatives/primatives.h"
#include "mappers/mappers.h"
#include "textures/textures.h"
#include "tilemap.cpp"
// #include "shaders/shaders.h"
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.