From 9ed35594d150b92f67bdff27fdcc9a6f61982fe1 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 20 Nov 2018 14:17:29 +0100 Subject: [PATCH 01/10] renderer: initial texture mapping --- renderer/level.h | 2 +- renderer/renderer.c | 64 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/renderer/level.h b/renderer/level.h index 997fa3c..63e79a4 100644 --- a/renderer/level.h +++ b/renderer/level.h @@ -6,7 +6,7 @@ typedef int TextureId; typedef struct TexCoord { - xy_t start, end; + real_t start, end; } TexCoord; typedef struct Location { diff --git a/renderer/renderer.c b/renderer/renderer.c index bf8dfa9..5b1d5a6 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -82,7 +82,7 @@ typedef struct } left, right; } WallSection; -bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg) +bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg, TexCoord* texCoord) { xz_t leftIntersection, rightIntersection; bool_t intersectsLeft = xz_lineIntersect(*wallSeg, me->leftFovSeg, &leftIntersection); @@ -108,9 +108,40 @@ bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg) : inWallSegLeft ? leftIntersection : (result = false, xz_zero); } + real_t texCoordAmpl = real_abs(real_sub(texCoord->start, texCoord->end)); + real_t texCoordStart = real_min(texCoord->start, texCoord->end); + if (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight) + texCoord->start = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); + if (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft) + texCoord->end = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); return result; } +typedef struct { + GColor* colors; + int width, height; +} Bild; + +static const Bild* genBild() +{ + static GColor pixels[64*64]; + static Bild bild; + bild.width = 64; + bild.height = 64; + bild.colors = pixels; + for (int i = 0; i <64*64; i++) + { + int x = i % 64; + int y = i / 64; + int c = x ^ y; + pixels[i].r = (c >> 0) & 2; + pixels[i].g = (c >> 2) & 2; + pixels[i].b = (c >> 4) & 2; + pixels[i].a = 3; + } + return &bild; +} + void renderer_project(const Renderer* me, const Sector* sector, const lineSeg_t* transformedSeg, WallSection* projected) { //const real_t halfHeight = real_div(real_from_int(sector->height), real_from_int(2)); @@ -139,12 +170,15 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r const Sector* const sector = request->sector; const Wall* const wall = §or->walls[wallIndex]; const real_t nearPlane = me->leftFovSeg.start.xz.z; + const Bild* bild = genBild(); + lineSeg_t wallSeg; renderer_transformWall(me, sector, wallIndex, &wallSeg); if (real_compare(wallSeg.start.xz.z, nearPlane) < 0 && real_compare(wallSeg.end.xz.z, nearPlane) < 0) return; - if (!renderer_clipByFov(me, &wallSeg)) + TexCoord texCoord = (TexCoord) { real_zero, real_one }; + if (!renderer_clipByFov(me, &wallSeg, &texCoord)) return; WallSection p; @@ -177,17 +211,39 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r me->yTop[x] = yPortalEnd = clampi(yBottom, lerpi(portalNomEnd, 0, sector->height, yCurStart, yCurEnd), yTop); } + int texCol = real_to_int(real_mul( + (x - max(0, p.left.x)) * (texCoord.end - texCoord.start) / (min(RENDERER_WIDTH - 1, p.right.x) - max(0, p.left.x) + 1) + texCoord.start, + real_from_int(bild->width))); + real_t texRow = yCurStart >= 0 ? real_zero + : real_mul(real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)), real_from_int(bild->height)); + real_t texRowIncr = real_div(real_from_int(bild->height), real_from_int(yCurEnd - yCurStart + 1)); + int y; for (y = yBottom; y < max(yBottom, yCurStart); y++) *(curPixel++) = sector->floorColor; for (; y <= min(yTop, yPortalStart - 1); y++) - *(curPixel++) = wall->color; + { + int texRowI = real_to_int(texRow); + *(curPixel++) = bild->colors[ + (texRowI % bild->height) * bild->width + + (texCol % bild->width) + ]; + texRow = real_add(texRow, texRowIncr); + } if (wall->portalTo >= 0) { //for (; y <= min(yTop, yPortalEnd); y++) //*(curPixel++) = ((y / 4) % 2) ? GColorFromRGB(255, 0, 255) : GColorFromRGB(0, 0, 0); + texRow = real_add(texRow, real_mul(texRowIncr, real_from_int(min(yTop, yPortalEnd) - y + 1))); curPixel += yPortalEnd - y; for (y = yPortalEnd; y <= min(yTop, yCurEnd); y++) - *(curPixel++) = wall->color; + { + int texRowI = real_to_int(texRow); + *(curPixel++) = bild->colors[ + (texRowI % bild->height) * bild->width + + (texCol % bild->width) + ]; + texRow = real_add(texRow, texRowIncr); + } } for (; y <= yTop; y++) *(curPixel++) = sector->ceilColor; From 0229b490ba950a460de2051977cf198cb96a24d5 Mon Sep 17 00:00:00 2001 From: Helco Date: Thu, 22 Nov 2018 10:34:57 +0100 Subject: [PATCH 02/10] renderer: use new lerp function --- renderer/renderer.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/renderer/renderer.c b/renderer/renderer.c index 5b1d5a6..5f4b86c 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -196,10 +196,13 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r } // render wall - for (int x = max(request->left, p.left.x); x <= min(request->right, p.right.x); x++) { + const int renderLeft = max(0, p.left.x); + const int renderRight = min(RENDERER_WIDTH - 1, p.right.x); + const real_t renderAmpl = real_from_int(renderRight - renderLeft + 1); + for (int x = renderLeft; x <= renderRight; x++) { const int yBottom = me->yBottom[x]; const int yTop = me->yTop[x]; - GColor* curPixel = framebuffer + x * RENDERER_HEIGHT + yBottom; + GColor* curPixel = framebuffer + x * RENDERER_HEIGHT; int yCurStart = lerpi(x, p.left.x, p.right.x, p.left.yStart, p.right.yStart); int yCurEnd = lerpi(x, p.left.x, p.right.x, p.left.yEnd, p.right.yEnd); if (yCurEnd < yBottom || yCurStart > yTop || yCurStart >= yCurEnd) @@ -211,9 +214,10 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r me->yTop[x] = yPortalEnd = clampi(yBottom, lerpi(portalNomEnd, 0, sector->height, yCurStart, yCurEnd), yTop); } - int texCol = real_to_int(real_mul( - (x - max(0, p.left.x)) * (texCoord.end - texCoord.start) / (min(RENDERER_WIDTH - 1, p.right.x) - max(0, p.left.x) + 1) + texCoord.start, - real_from_int(bild->width))); + real_t xNormalized = real_div(real_from_int(x - renderLeft), renderAmpl); + int texCol = real_to_int( + real_mul(real_lerp(xNormalized, texCoord.start, texCoord.end), real_from_int(bild->width)) + ); real_t texRow = yCurStart >= 0 ? real_zero : real_mul(real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)), real_from_int(bild->height)); real_t texRowIncr = real_div(real_from_int(bild->height), real_from_int(yCurEnd - yCurStart + 1)); From 3d82a159b4510b4c51cbda5c0fcaecc68bd6abb9 Mon Sep 17 00:00:00 2001 From: Helco Date: Thu, 22 Nov 2018 10:54:52 +0100 Subject: [PATCH 03/10] renderer: vertical texture-coordinates --- renderer/level.h | 2 +- renderer/renderer.c | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/renderer/level.h b/renderer/level.h index 63e79a4..997fa3c 100644 --- a/renderer/level.h +++ b/renderer/level.h @@ -6,7 +6,7 @@ typedef int TextureId; typedef struct TexCoord { - real_t start, end; + xy_t start, end; } TexCoord; typedef struct Location { diff --git a/renderer/renderer.c b/renderer/renderer.c index 5f4b86c..8620a34 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -108,12 +108,12 @@ bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg, TexCoord* texC : inWallSegLeft ? leftIntersection : (result = false, xz_zero); } - real_t texCoordAmpl = real_abs(real_sub(texCoord->start, texCoord->end)); - real_t texCoordStart = real_min(texCoord->start, texCoord->end); + real_t texCoordAmpl = real_abs(real_sub(texCoord->start.x, texCoord->end.x)); + real_t texCoordStart = real_min(texCoord->start.x, texCoord->end.x); if (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight) - texCoord->start = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); + texCoord->start.x = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); if (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft) - texCoord->end = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); + texCoord->end.x = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); return result; } @@ -177,7 +177,7 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r if (real_compare(wallSeg.start.xz.z, nearPlane) < 0 && real_compare(wallSeg.end.xz.z, nearPlane) < 0) return; - TexCoord texCoord = (TexCoord) { real_zero, real_one }; + TexCoord texCoord = (TexCoord) { xy_zero, xy_one }; if (!renderer_clipByFov(me, &wallSeg, &texCoord)) return; @@ -216,11 +216,14 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r real_t xNormalized = real_div(real_from_int(x - renderLeft), renderAmpl); int texCol = real_to_int( - real_mul(real_lerp(xNormalized, texCoord.start, texCoord.end), real_from_int(bild->width)) + real_mul(real_lerp(xNormalized, texCoord.start.x, texCoord.end.x), real_from_int(bild->width)) ); - real_t texRow = yCurStart >= 0 ? real_zero - : real_mul(real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)), real_from_int(bild->height)); - real_t texRowIncr = real_div(real_from_int(bild->height), real_from_int(yCurEnd - yCurStart + 1)); + real_t yNormalized = yCurStart >= 0 ? real_zero + : real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)); + real_t texRow = real_mul(real_lerp(yNormalized, texCoord.start.y, texCoord.end.y), real_from_int(bild->height)); + real_t texRowIncr = real_div( + real_mul(real_sub(texCoord.end.y, texCoord.start.y), real_from_int(bild->height)), + real_from_int(yCurEnd - yCurStart + 1)); int y; for (y = yBottom; y < max(yBottom, yCurStart); y++) From 91c89448c6af82957e6dae672df515a6be99b756 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 18:08:17 +0100 Subject: [PATCH 04/10] renderer: integrate texture-mapping with level and texture -loading --- renderer/level.c | 39 ++++++++++++++++++++----------- renderer/level.h | 3 ++- renderer/renderer.c | 49 +++++++++++---------------------------- renderer/renderer_debug.c | 2 +- 4 files changed, 42 insertions(+), 51 deletions(-) diff --git a/renderer/level.c b/renderer/level.c index 0e94551..f38ab1c 100644 --- a/renderer/level.c +++ b/renderer/level.c @@ -8,49 +8,62 @@ Level *level_load(int levelId) Wall walls_template[] = { // start triangle {.startCorner = xz(real_from_int(70), real_from_int(50)), - .color = GColorFromRGB(0, 255, 0), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = 1}, {.startCorner = xz(real_from_int(0), real_from_int(50)), - .color = GColorFromRGB(255, 0, 255), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, {.startCorner = xz(real_from_int(0), real_from_int(-30)), - .color = GColorFromRGB(0, 255, 255), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, // northern trapez {.startCorner = xz(real_from_int(70), real_from_int(50)), - .color = GColorFromRGB(0, 128, 0), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = 2}, {.startCorner = xz(real_from_int(50), real_from_int(80)), - .color = GColorFromRGB(128, 0, 128), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, {.startCorner = xz(real_from_int(20), real_from_int(80)), - .color = GColorFromRGB(0, 128, 128), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = 3}, {.startCorner = xz(real_from_int(00), real_from_int(50)), - .color = GColorFromRGB(128, 128, 0), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = 0}, // right wing {.startCorner = xz(real_from_int(70), real_from_int(50)), - .color = GColorFromRGB(128, 0, 0), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, {.startCorner = xz(real_from_int(90), real_from_int(65)), - .color = GColorFromRGB(0, 0, 128), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, {.startCorner = xz(real_from_int(50), real_from_int(80)), - .color = GColorFromRGB(255, 0, 128), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = 1}, // left wing {.startCorner = xz(real_from_int(00), real_from_int(50)), - .color = GColorFromRGB(255, 128, 0), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = 1}, {.startCorner = xz(real_from_int(20), real_from_int(80)), - .color = GColorFromRGB(255, 128, 128), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, {.startCorner = xz(real_from_int(-20), real_from_int(65)), - .color = GColorFromRGB(128, 255, 128), + .texture = 0, + .texCoord = { xy_zero, xy_one}, .portalTo = -1}, }; Sector sectors_template[] = { diff --git a/renderer/level.h b/renderer/level.h index 997fa3c..1d8e261 100644 --- a/renderer/level.h +++ b/renderer/level.h @@ -18,8 +18,9 @@ typedef struct Location { typedef struct Wall { xz_t startCorner; - GColor color; int portalTo; + TextureId texture; + TexCoord texCoord; } Wall; typedef struct Sector { diff --git a/renderer/renderer.c b/renderer/renderer.c index 8620a34..35008e8 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -117,31 +117,6 @@ bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg, TexCoord* texC return result; } -typedef struct { - GColor* colors; - int width, height; -} Bild; - -static const Bild* genBild() -{ - static GColor pixels[64*64]; - static Bild bild; - bild.width = 64; - bild.height = 64; - bild.colors = pixels; - for (int i = 0; i <64*64; i++) - { - int x = i % 64; - int y = i / 64; - int c = x ^ y; - pixels[i].r = (c >> 0) & 2; - pixels[i].g = (c >> 2) & 2; - pixels[i].b = (c >> 4) & 2; - pixels[i].a = 3; - } - return &bild; -} - void renderer_project(const Renderer* me, const Sector* sector, const lineSeg_t* transformedSeg, WallSection* projected) { //const real_t halfHeight = real_div(real_from_int(sector->height), real_from_int(2)); @@ -170,14 +145,14 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r const Sector* const sector = request->sector; const Wall* const wall = §or->walls[wallIndex]; const real_t nearPlane = me->leftFovSeg.start.xz.z; - const Bild* bild = genBild(); + const Texture* texture = texture_load(me->textureManager, wall->texture); lineSeg_t wallSeg; renderer_transformWall(me, sector, wallIndex, &wallSeg); if (real_compare(wallSeg.start.xz.z, nearPlane) < 0 && real_compare(wallSeg.end.xz.z, nearPlane) < 0) return; - TexCoord texCoord = (TexCoord) { xy_zero, xy_one }; + TexCoord texCoord = wall->texCoord; if (!renderer_clipByFov(me, &wallSeg, &texCoord)) return; @@ -216,13 +191,13 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r real_t xNormalized = real_div(real_from_int(x - renderLeft), renderAmpl); int texCol = real_to_int( - real_mul(real_lerp(xNormalized, texCoord.start.x, texCoord.end.x), real_from_int(bild->width)) + real_mul(real_lerp(xNormalized, texCoord.start.x, texCoord.end.x), real_from_int(texture->size.w)) ); real_t yNormalized = yCurStart >= 0 ? real_zero : real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)); - real_t texRow = real_mul(real_lerp(yNormalized, texCoord.start.y, texCoord.end.y), real_from_int(bild->height)); + real_t texRow = real_mul(real_lerp(yNormalized, texCoord.start.y, texCoord.end.y), real_from_int(texture->size.h)); real_t texRowIncr = real_div( - real_mul(real_sub(texCoord.end.y, texCoord.start.y), real_from_int(bild->height)), + real_mul(real_sub(texCoord.end.y, texCoord.start.y), real_from_int(texture->size.h)), real_from_int(yCurEnd - yCurStart + 1)); int y; @@ -231,9 +206,9 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r for (; y <= min(yTop, yPortalStart - 1); y++) { int texRowI = real_to_int(texRow); - *(curPixel++) = bild->colors[ - (texRowI % bild->height) * bild->width + - (texCol % bild->width) + *(curPixel++) = texture->pixels[ + (texRowI % texture->size.h) * texture->size.w + + (texCol % texture->size.w) ]; texRow = real_add(texRow, texRowIncr); } @@ -245,9 +220,9 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r for (y = yPortalEnd; y <= min(yTop, yCurEnd); y++) { int texRowI = real_to_int(texRow); - *(curPixel++) = bild->colors[ - (texRowI % bild->height) * bild->width + - (texCol % bild->width) + *(curPixel++) = texture->pixels[ + (texRowI % texture->size.h) * texture->size.w + + (texCol % texture->size.w) ]; texRow = real_add(texRow, texRowIncr); } @@ -255,6 +230,8 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r for (; y <= yTop; y++) *(curPixel++) = sector->ceilColor; } + + texture_free(me->textureManager, texture); } void renderer_renderSector(Renderer* renderer, GColor* framebuffer, const DrawRequest* request) diff --git a/renderer/renderer_debug.c b/renderer/renderer_debug.c index c6b0fa5..c4fc675 100644 --- a/renderer/renderer_debug.c +++ b/renderer/renderer_debug.c @@ -66,7 +66,7 @@ void renderer_renderDebugSector(Renderer* me, SDL_Renderer* sdlRenderer, xz_t of lineSeg_t wallLine; wallLine.start.xz = curWall->startCorner; wallLine.end.xz = sector->walls[(i + 1) % sector->wallCount].startCorner; - renderer_setDebugColor(sdlRenderer, curWall->color); + renderer_setDebugColor(sdlRenderer, GColorFromRGB((i % 3 == 0) * 255, (i % 3 == 1) * 255, (i % 3 == 2) * 255)); renderer_renderSDLDebugLine(me, sdlRenderer, offset, wallLine, opts); } } From 0ace346ff40235bc4a862f7dbdb0d78dd56ae876 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 18:17:42 +0100 Subject: [PATCH 05/10] algebra: add real_norm_lerp --- renderer/algebra.h | 1 + renderer/algebra_float.c | 6 ++++++ test/fixtures.h | 1 + test/test_real.cpp | 13 +++++++++++++ 4 files changed, 21 insertions(+) diff --git a/renderer/algebra.h b/renderer/algebra.h index 38fa060..2ee4d98 100644 --- a/renderer/algebra.h +++ b/renderer/algebra.h @@ -63,6 +63,7 @@ real_t real_max(real_t a, real_t b); real_t real_abs(real_t a); int real_signInt(real_t a); real_t real_lerp(real_t value, real_t start, real_t end); // input amplitude is normal 1 +real_t real_norm_lerp(real_t value, real_t inputStart, real_t inputEnd, real_t outputStart, real_t outputEnd); real_t real_clamp(real_t minimum, real_t value, real_t maximum); real_t real_floor(real_t a); diff --git a/renderer/algebra_float.c b/renderer/algebra_float.c index e12233c..6258dd1 100644 --- a/renderer/algebra_float.c +++ b/renderer/algebra_float.c @@ -132,6 +132,12 @@ real_t real_lerp(real_t value, real_t start, real_t end) return real_add(real_mul(value, ampl), start); } +real_t real_norm_lerp(real_t value, real_t inputStart, real_t inputEnd, real_t outputStart, real_t outputEnd) +{ + real_t normalized = real_div(real_sub(value, inputStart), real_sub(inputEnd, inputStart)); + return real_lerp(normalized, outputStart, outputEnd); +} + real_t real_clamp(real_t minimum, real_t value, real_t maximum) { return real_max(minimum, real_min(value, maximum)); diff --git a/test/fixtures.h b/test/fixtures.h index 105e06b..feb514f 100644 --- a/test/fixtures.h +++ b/test/fixtures.h @@ -17,6 +17,7 @@ class MathFixture : public testing::Test { const real_t three = real_from_int(3); const real_t four = real_from_int(4); const real_t five = real_from_int(5); + const real_t eight = real_from_int(8); const real_t ten = real_from_int(10); const real_t halfpi = real_div(real_pi, real_from_int(2)); diff --git a/test/test_real.cpp b/test/test_real.cpp index 57471f6..14ea172 100644 --- a/test/test_real.cpp +++ b/test/test_real.cpp @@ -118,6 +118,19 @@ TEST_F(TestAlgebraReal, real_lerp) { expectApproxEq(real_from_int(-20), real_lerp(real_neg(two), real_zero, ten)); } +TEST_F(TestAlgebraReal, real_norm_lerp) { + EXPECT_EQ(real_zero, real_norm_lerp(real_zero, real_zero, four, real_zero, ten)); + EXPECT_EQ(ten, real_norm_lerp(four, real_zero, four, real_zero, ten)); + EXPECT_EQ(five, real_norm_lerp(two, real_zero, four, real_zero, ten)); + EXPECT_EQ(real_zero, real_norm_lerp(two, two, four, real_zero, ten)); + EXPECT_EQ(five, real_norm_lerp(two, two, four, five, ten)); + EXPECT_EQ(five, real_norm_lerp(real_zero, real_neg(four), four, real_zero, ten)); + EXPECT_EQ(real_neg(ten), real_norm_lerp(two, two, four, real_neg(ten), ten)); + EXPECT_EQ(five, real_norm_lerp(two, real_neg(four), four, real_neg(ten), ten)); + EXPECT_EQ(real_from_int(20), real_norm_lerp(eight, real_zero, four, real_zero, ten)); + EXPECT_EQ(real_from_int(-20), real_norm_lerp(real_neg(eight), real_zero, four, real_zero, ten)); +} + TEST_F(TestAlgebraReal, real_clamp) { const real_t eleven = real_from_int(11); expectApproxEq(five, real_clamp(real_zero, five, ten)); From f90b69122a9fb56441a546f435092a1212bd24aa Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 18:28:56 +0100 Subject: [PATCH 06/10] renderer: use real_norm_lerp --- renderer/renderer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/renderer/renderer.c b/renderer/renderer.c index 35008e8..bfbc8cf 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -173,7 +173,6 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r // render wall const int renderLeft = max(0, p.left.x); const int renderRight = min(RENDERER_WIDTH - 1, p.right.x); - const real_t renderAmpl = real_from_int(renderRight - renderLeft + 1); for (int x = renderLeft; x <= renderRight; x++) { const int yBottom = me->yBottom[x]; const int yTop = me->yTop[x]; @@ -189,10 +188,11 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r me->yTop[x] = yPortalEnd = clampi(yBottom, lerpi(portalNomEnd, 0, sector->height, yCurStart, yCurEnd), yTop); } - real_t xNormalized = real_div(real_from_int(x - renderLeft), renderAmpl); - int texCol = real_to_int( - real_mul(real_lerp(xNormalized, texCoord.start.x, texCoord.end.x), real_from_int(texture->size.w)) - ); + real_t xLerped = real_norm_lerp(real_from_int(x), + real_from_int(renderLeft), real_from_int(renderRight), + texCoord.start.x, texCoord.end.x); + int texCol = real_to_int(real_mul(xLerped, real_from_int(texture->size.w))); + real_t yNormalized = yCurStart >= 0 ? real_zero : real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)); real_t texRow = real_mul(real_lerp(yNormalized, texCoord.start.y, texCoord.end.y), real_from_int(texture->size.h)); From 8f42b5ef40335c8a712a5e530f8965c0fdc6ae27 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 21:03:06 +0100 Subject: [PATCH 07/10] renderer: fix texture not being freed properly --- renderer/renderer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/renderer/renderer.c b/renderer/renderer.c index bfbc8cf..0867945 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -171,6 +171,7 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r } // render wall + const Texture* texture = texture_load(me->textureManager, wall->texture); const int renderLeft = max(0, p.left.x); const int renderRight = min(RENDERER_WIDTH - 1, p.right.x); for (int x = renderLeft; x <= renderRight; x++) { From 9d2bcd78a0462dbbf3b2378f5679598f834bdefb Mon Sep 17 00:00:00 2001 From: Helco Date: Wed, 19 Dec 2018 15:29:28 +0100 Subject: [PATCH 08/10] renderer: perspective correction --- renderer/renderer.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/renderer/renderer.c b/renderer/renderer.c index 0867945..6256431 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -91,29 +91,29 @@ bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg, TexCoord* texC real_t wallPhaseRight = intersectsRight ? xz_linePhase(*wallSeg, rightIntersection) : real_zero; bool_t inWallSegLeft = real_inBetween(wallPhaseLeft, real_zero, real_one); bool_t inWallSegRight = real_inBetween(wallPhaseRight, real_zero, real_one); + real_t texCoordAmpl = real_abs(real_sub(texCoord->start.x, texCoord->end.x)); + real_t texCoordStart = real_min(texCoord->start.x, texCoord->end.x); bool_t result = true; if (real_compare(wallSeg->start.xz.z, me->leftFovSeg.start.xz.z) <= 0) { - - wallSeg->start.xz = (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft) - ? leftIntersection + bool_t useRightIntersection = (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight); + wallSeg->start.xz = useRightIntersection + ? leftIntersection : inWallSegRight ? rightIntersection : (result = false, xz_zero); + if (useRightIntersection) + texCoord->start.x = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); } if (real_compare(wallSeg->end.xz.z, me->leftFovSeg.start.xz.z) <= 0) { - wallSeg->end.xz = (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight) + bool_t useLeftIntersection = (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft); + wallSeg->end.xz = useLeftIntersection ? rightIntersection : inWallSegLeft ? leftIntersection : (result = false, xz_zero); + if (useLeftIntersection) + texCoord->end.x = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); } - - real_t texCoordAmpl = real_abs(real_sub(texCoord->start.x, texCoord->end.x)); - real_t texCoordStart = real_min(texCoord->start.x, texCoord->end.x); - if (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight) - texCoord->start.x = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); - if (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft) - texCoord->end.x = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); return result; } @@ -145,7 +145,6 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r const Sector* const sector = request->sector; const Wall* const wall = §or->walls[wallIndex]; const real_t nearPlane = me->leftFovSeg.start.xz.z; - const Texture* texture = texture_load(me->textureManager, wall->texture); lineSeg_t wallSeg; renderer_transformWall(me, sector, wallIndex, &wallSeg); @@ -171,7 +170,7 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r } // render wall - const Texture* texture = texture_load(me->textureManager, wall->texture); + const Texture* const texture = texture_load(me->textureManager, wall->texture); const int renderLeft = max(0, p.left.x); const int renderRight = min(RENDERER_WIDTH - 1, p.right.x); for (int x = renderLeft; x <= renderRight; x++) { @@ -189,10 +188,14 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r me->yTop[x] = yPortalEnd = clampi(yBottom, lerpi(portalNomEnd, 0, sector->height, yCurStart, yCurEnd), yTop); } - real_t xLerped = real_norm_lerp(real_from_int(x), - real_from_int(renderLeft), real_from_int(renderRight), - texCoord.start.x, texCoord.end.x); - int texCol = real_to_int(real_mul(xLerped, real_from_int(texture->size.w))); + real_t xNorm = real_div(real_from_int(x - p.left.x), real_from_int(p.right.x - p.left.x)); + real_t invZLerped = real_lerp(xNorm, real_reciprocal(wallSeg.start.xz.z), real_reciprocal(wallSeg.end.xz.z)); + real_t invTexLerped = real_lerp(xNorm, + real_div(texCoord.start.x, wallSeg.start.xz.z), + real_div(texCoord.end.x, wallSeg.end.xz.z) + ); + real_t texLerped = real_div(invTexLerped, invZLerped); + int texCol = real_to_int(real_mul(texLerped, real_from_int(texture->size.w))); real_t yNormalized = yCurStart >= 0 ? real_zero : real_div(real_from_int(-yCurStart), real_from_int(yCurEnd - yCurStart)); From fa2a4fb5f35ec77c214bd91392fd096dafb5c93e Mon Sep 17 00:00:00 2001 From: Helco Date: Wed, 19 Dec 2018 16:15:34 +0100 Subject: [PATCH 09/10] renderer: fix logical merge errors --- renderer/renderer.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/renderer/renderer.c b/renderer/renderer.c index 6256431..0d5d75a 100644 --- a/renderer/renderer.c +++ b/renderer/renderer.c @@ -97,22 +97,22 @@ bool_t renderer_clipByFov(const Renderer* me, lineSeg_t* wallSeg, TexCoord* texC if (real_compare(wallSeg->start.xz.z, me->leftFovSeg.start.xz.z) <= 0) { - bool_t useRightIntersection = (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight); - wallSeg->start.xz = useRightIntersection + bool_t useLeftIntersection = (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft); + wallSeg->start.xz = useLeftIntersection ? leftIntersection : inWallSegRight ? rightIntersection : (result = false, xz_zero); - if (useRightIntersection) - texCoord->start.x = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); + if (useLeftIntersection) + texCoord->start.x = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); } if (real_compare(wallSeg->end.xz.z, me->leftFovSeg.start.xz.z) <= 0) { - bool_t useLeftIntersection = (real_compare(leftIntersection.z, real_zero) > 0 && inWallSegLeft); - wallSeg->end.xz = useLeftIntersection + bool_t useRightIntersection = (real_compare(rightIntersection.z, real_zero) > 0 && inWallSegRight); + wallSeg->end.xz = useRightIntersection ? rightIntersection : inWallSegLeft ? leftIntersection : (result = false, xz_zero); - if (useLeftIntersection) - texCoord->end.x = real_add(real_mul(wallPhaseLeft, texCoordAmpl), texCoordStart); + if (useRightIntersection) + texCoord->end.x = real_add(real_mul(wallPhaseRight, texCoordAmpl), texCoordStart); } return result; } @@ -171,12 +171,12 @@ void renderer_renderWall(Renderer* me, GColor* framebuffer, const DrawRequest* r // render wall const Texture* const texture = texture_load(me->textureManager, wall->texture); - const int renderLeft = max(0, p.left.x); - const int renderRight = min(RENDERER_WIDTH - 1, p.right.x); + const int renderLeft = max(request->left, p.left.x); + const int renderRight = min(request->right, p.right.x); for (int x = renderLeft; x <= renderRight; x++) { const int yBottom = me->yBottom[x]; const int yTop = me->yTop[x]; - GColor* curPixel = framebuffer + x * RENDERER_HEIGHT; + GColor* curPixel = framebuffer + x * RENDERER_HEIGHT + yBottom; int yCurStart = lerpi(x, p.left.x, p.right.x, p.left.yStart, p.right.yStart); int yCurEnd = lerpi(x, p.left.x, p.right.x, p.left.yEnd, p.right.yEnd); if (yCurEnd < yBottom || yCurStart > yTop || yCurStart >= yCurEnd) From 160e6fcc5bb1f8e36868624ae71d5e1f712dac06 Mon Sep 17 00:00:00 2001 From: Helco Date: Wed, 19 Dec 2018 16:50:00 +0100 Subject: [PATCH 10/10] pebble: Fix texture loading --- pebbleapp/PDoom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pebbleapp/PDoom.c b/pebbleapp/PDoom.c index 06b3264..f5bb6db 100644 --- a/pebbleapp/PDoom.c +++ b/pebbleapp/PDoom.c @@ -32,8 +32,10 @@ bool loadTextures() static const int countIds = sizeof(resourceIds) / sizeof(uint32_t); for (int i = 0; i < countIds; i++) { - if (loadTextureFromResource(resourceIds[i]) == INVALID_TEXTURE_ID) + TextureId texId = loadTextureFromResource(resourceIds[i]); + if (texId == INVALID_TEXTURE_ID) return false; + texture_load(NULL, texId); } return true; }