aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/player.zig52
-rw-r--r--src/sfml/graphics/color.zig2
2 files changed, 41 insertions, 13 deletions
diff --git a/src/player.zig b/src/player.zig
index 8ad3a1e..e69b3ce 100644
--- a/src/player.zig
+++ b/src/player.zig
@@ -35,6 +35,42 @@ fn playerDistComp(pos: [2]f32, lhs: level.Object, rhs: level.Object) bool {
return (lx * lx + ly * ly > rx * rx + ry * ry);
}
+fn fasterColourBlend(onto: Colour, from: Colour) Colour {
+ const af: u16 = from.a;
+ const of: u16 = onto.a;
+
+ const na: u16 = af + @divTrunc(of * (255 - af), 255);
+ if (na == 0) return Colour.Black;
+
+ const rf: u16 = from.r;
+ const ro: u16 = onto.r;
+ const gf: u16 = from.g;
+ const go: u16 = onto.g;
+ const bf: u16 = from.b;
+ const bo: u16 = onto.b;
+
+ // These computations are expensive, but more accurate
+ // const nr = @divTrunc(af * rf, na) + ro - @divTrunc(af * ro, na);
+ // const ng = @divTrunc(af * gf, na) + go - @divTrunc(af * go, na);
+ // const nb = @divTrunc(af * bf, na) + bo - @divTrunc(af * bo, na);
+
+ // These computations are incorrect, but fast
+ const nr = (af * rf + (255 - af) * ro) / 255;
+ const ng = (af * gf + (255 - af) * go) / 255;
+ const nb = (af * bf + (255 - af) * bo) / 255;
+
+ // The most accurate i've found is @divTrunc(ro * na + (rf - ro) * af, na);
+ // but this requires using signed integers, for which presumably division is
+ // slower still
+
+ return Colour{
+ .a = @intCast(u8, na),
+ .r = @intCast(u8, nr),
+ .g = @intCast(u8, ng),
+ .b = @intCast(u8, nb),
+ };
+}
+
pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type {
const FOV: f32 = std.math.pi / 3.0;
const PlanePixels = PlaneWidth * PlaneHeight;
@@ -144,17 +180,11 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type {
// then render the ceilings to our pixel array
self.renderCeilingsToTexture(surfaces_image, map, &pixels);
- // we're now ready to draw the surfaces
- try rendered_surfaces_texture.updateFromPixels(&pixels, null);
- window.draw(rendered_surfaces_sprite, null);
-
- // TODO: use the z_buffer to render sprites, reset the
- // pixel array as a cheap hack to avoid colour mixing ...
- pixels = [_]Colour{Colour.Transparent} ** (PlaneWidth * PlaneHeight);
+ // use the z_buffer to render sprites
self.renderObjects(objects_image, map, &pixels);
+
try rendered_surfaces_texture.updateFromPixels(&pixels, null);
window.draw(rendered_surfaces_sprite, null);
-
}
fn renderObjects(
@@ -236,10 +266,8 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type {
const ty = @floatToInt(c_uint, texel_y * constants.TextureDim);
const texel = objects_image.getPixel(.{ .x = toff + tx, .y = ty });
const pix_index = @floatToInt(usize, PlaneWidth) * pix_y + col;
- // TODO: currently i have a cheap hack to
- // avoid colour mixing. Is there a better
- // way to do this?
- pixels[pix_index] = texel;
+ // TODO: Decide whether being accurate is as important as being fast
+ pixels[pix_index] = fasterColourBlend(pixels[pix_index], texel);
}
}
}
diff --git a/src/sfml/graphics/color.zig b/src/sfml/graphics/color.zig
index d6aa850..5555c22 100644
--- a/src/sfml/graphics/color.zig
+++ b/src/sfml/graphics/color.zig
@@ -55,7 +55,7 @@ pub const Color = packed struct {
}
/// Creates a color with rgba floats from 0 to 1
- fn fromFloats(red: f32, green: f32, blue: f32, alpha: f32) Color {
+ pub fn fromFloats(red: f32, green: f32, blue: f32, alpha: f32) Color {
return Color{
.r = @floatToInt(u8, math.clamp(red, 0.0, 1.0) * 255.0),
.g = @floatToInt(u8, math.clamp(green, 0.0, 1.0) * 255.0),