[Scummvm-git-logs] scummvm master -> 9b0c32ef97b5f7b5bfa9459aee734bfc461f3ecb
neuromancer
noreply at scummvm.org
Sun Mar 1 13:29:01 UTC 2026
This automated email contains information about 13 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
8126c6a0f8 FREESCAPE: fix rebase conflicts in area.cpp
140485479c FREESCAPE: extended new rendering to tingyl
0fea7584de FREESCAPE: extended new rendering to shaders
de1efbe042 FREESCAPE: fix rebase conflicts in area.cpp
19acb87f0a FREESCAPE: removed depth testing code
878ae8a478 FREESCAPE: reduced artifacts in rendering thanks to @dhruv0154 fixes
32bbd7071d FREESCAPE: fix culling issues in castle master.
6413ffa6a0 FREESCAPE: fix overlap for planar objects.
5e8deecc78 FREESCAPE: fixes for renderRectangle
1fc666556b FREESCAPE: fixed invisible bottom of a chest in eclipse demo (cpc)
e7da5f1b9a FREESACPE: improved debugger.
814f7e2243 FREESCAPE: fix artifacts in castle master.
9b0c32ef97 FREESCAPE: updated credits
Commit: 8126c6a0f860aeb4f3d59037e013defe272b61dd
https://github.com/scummvm/scummvm/commit/8126c6a0f860aeb4f3d59037e013defe272b61dd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fix rebase conflicts in area.cpp
Changed paths:
engines/freescape/area.cpp
engines/freescape/gfx.cpp
engines/freescape/gfx.h
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl.h
engines/freescape/objects/geometricobject.cpp
engines/freescape/objects/object.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 90bb56e99b0..cba071534ad 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -84,18 +84,6 @@ Area::Area(uint16 areaID_, uint16 areaFlags_, ObjectMap *objectsByID_, ObjectMap
}
}
- // sort so that those that are planar are drawn last
- struct {
- bool operator()(Object *object1, Object *object2) {
- if (!object1->isPlanar() && object2->isPlanar())
- return true;
- if (object1->isPlanar() && !object2->isPlanar())
- return false;
- return object1->getObjectID() > object2->getObjectID();
- };
- } compareObjects;
-
- Common::sort(_drawableObjects.begin(), _drawableObjects.end(), compareObjects);
_lastTick = 0;
}
@@ -238,11 +226,8 @@ void Area::resetArea() {
void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d camera, Math::Vector3d direction, bool insideWait) {
bool runAnimation = animationTicks != _lastTick;
assert(_drawableObjects.size() > 0);
- ObjectArray planarObjects;
- ObjectArray nonPlanarObjects;
+ ObjectArray sortedObjects;
Object *floor = nullptr;
- Common::HashMap<Object *, float> sizes;
- float offset = MAX(0.15, 1.0 / _scale);
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
@@ -256,10 +241,7 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
continue;
}
- if (obj->isPlanar())
- planarObjects.push_back(obj);
- else
- nonPlanarObjects.push_back(obj);
+ sortedObjects.push_back(obj);
}
}
@@ -269,118 +251,120 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
gfx->depthTesting(true);
}
- Common::HashMap<Object *, float> offsetMap;
- for (auto &planar : planarObjects)
- offsetMap[planar] = 0;
-
- for (auto &planar : planarObjects) {
- Math::Vector3d centerPlanar = planar->_boundingBox.getMin() + planar->_boundingBox.getMax();
- centerPlanar /= 2;
- Math::Vector3d distance;
- for (auto &object : nonPlanarObjects) {
- if (object->_partOfGroup)
- continue;
-
- distance = object->_boundingBox.distance(centerPlanar);
- if (distance.length() > 0.0001)
- continue;
-
- float sizeNonPlanar = object->_boundingBox.getSize().length();
- if (sizes[planar] >= sizeNonPlanar)
- continue;
-
- sizes[planar] = sizeNonPlanar;
-
- if (planar->getSize().x() == 0) {
- if (object->getOrigin().x() >= centerPlanar.x())
- offsetMap[planar] = -offset;
- else
- offsetMap[planar] = offset;
- } else if (planar->getSize().y() == 0) {
- if (object->getOrigin().y() >= centerPlanar.y())
- offsetMap[planar] = -offset;
- else
- offsetMap[planar] = offset;
- } else if (planar->getSize().z() == 0) {
- if (object->getOrigin().z() >= centerPlanar.z())
- offsetMap[planar] = -offset;
- else
- offsetMap[planar] = offset;
- } else
- ; //It was not really planar?!
- }
- }
-
- for (auto &planar : planarObjects) {
- Math::Vector3d centerPlanar = planar->_boundingBox.getMin() + planar->_boundingBox.getMax();
- centerPlanar /= 2;
- Math::Vector3d distance;
- for (auto &object : planarObjects) {
- if (object == planar)
- continue;
-
- distance = object->_boundingBox.distance(centerPlanar);
- if (distance.length() > 0)
- continue;
-
- if (planar->getSize().x() == 0) {
- if (object->getSize().x() > 0)
- continue;
- } else if (planar->getSize().y() == 0) {
- if (object->getSize().y() > 0)
- continue;
- } else if (planar->getSize().z() == 0) {
- if (object->getSize().z() > 0)
- continue;
- } else
- continue;
-
- //debug("planar object %d collides with planar object %d", planar->getObjectID(), object->getObjectID());
- if (offsetMap[planar] == offsetMap[object] && offsetMap[object] != 0) {
- // Nothing to do?
- } else if (offsetMap[planar] == offsetMap[object] && offsetMap[object] == 0) {
- if (planar->getSize().x() == 0) {
- if (object->getOrigin().x() < centerPlanar.x())
- offsetMap[planar] = -offset;
- else
- offsetMap[planar] = offset;
- } else if (planar->getSize().y() == 0) {
- if (object->getOrigin().y() < centerPlanar.y())
- offsetMap[planar] = -offset;
- else
- offsetMap[planar] = offset;
- } else if (planar->getSize().z() == 0) {
- if (object->getOrigin().z() < centerPlanar.z())
- offsetMap[planar] = -offset;
- else
- offsetMap[planar] = offset;
- } else
- ; //It was not really planar?!
+ // Corresponds to L9c66 in assembly (bounding_box_axis_loop)
+ auto checkAxis = [](float minA, float maxA, float minB, float maxB) -> int {
+ if (minA >= maxB) { // A is clearly "greater" than B (L9c9b_one_object_clearly_further_than_the_other)
+ bool signMinA = minA >= 0;
+ bool signMaxA = maxA >= 0;
+ bool signMinB = minB >= 0;
+ bool signMaxB = maxB >= 0;
+
+ if (signMinA != signMaxA) // A covers 0 (L9ce6_first_object_is_closer)
+ return 1; // A is closer
+ if (signMinB != signMaxB) // B covers 0 (L9cec_second_object_is_closer)
+ return 2; // B is closer
+
+ if (signMinA != signMinB) // Different sides (L9cf3_objects_incomparable_in_this_axis)
+ return 0;
+
+ // Same side
+ if (!signMinA) { // Negative side (sign bit set in asm)
+ if (minA > minB) return 1; // A closer
+ if (minA < minB) return 2; // B closer
+ if (maxA > maxB) return 1; // A closer
+ return 2; // B closer
+ } else { // Positive side (sign bit clear in asm)
+ if (minA < minB) return 1; // A closer
+ if (minA > minB) return 2; // B closer
+ if (maxA > maxB) return 2; // B closer
+ return 1; // A closer
+ }
+ } else if (minB >= maxA) { // B is clearly "greater" than A
+ bool signMinB = minB >= 0;
+ bool signMaxB = maxB >= 0;
+ bool signMinA = minA >= 0;
+ bool signMaxA = maxA >= 0;
+
+ if (signMinB != signMaxB) // B covers 0 (L9cec_second_object_is_closer)
+ return 2; // B is closer
+ if (signMinA != signMaxA) // A covers 0 (L9ce6_first_object_is_closer)
+ return 1; // A is closer
+
+ if (signMinA != signMinB) // Different sides (L9cf3_objects_incomparable_in_this_axis)
+ return 0;
+
+ // Same side
+ if (!signMinB) { // Negative side
+ if (minB > minA) return 2; // B closer
+ if (minB < minA) return 1; // A closer
+ if (maxB > maxA) return 2; // B closer
+ return 1; // A closer
+ } else { // Positive side
+ if (minB < minA) return 2; // B closer
+ if (minB > minA) return 1; // A closer
+ if (maxB > maxA) return 1; // A closer
+ return 2; // B closer
}
}
- }
-
- for (auto &obj : nonPlanarObjects) {
- if (gfx->_debugHighlightObjectID != -1 && obj->getObjectID() != gfx->_debugHighlightObjectID)
- continue;
-
- obj->draw(gfx);
-
- // draw bounding boxes
- if (gfx->_debugRenderBoundingBoxes) {
- if (gfx->_debugBoundingBoxFilterID == -1 || gfx->_debugBoundingBoxFilterID == obj->getObjectID()) {
- gfx->drawAABB(obj->_boundingBox, 0, 255, 0);
+ return 0; // Overlap (L9cf3_objects_incomparable_in_this_axis)
+ };
+
+ // Bubble sort as implemented in castlemaster2-annotated.asm (L9c2d_sort_objects_for_rendering)
+ // NOTE: The sorting is performed on unprojected world-space coordinates relative to the player (L847f).
+ // The rotation/view matrix (computed in L95de) is NOT applied to the bounding boxes used for sorting.
+ // It is only applied to the vertices during the projection phase (L850f/L9177).
+ int n = sortedObjects.size();
+ if (n > 1) {
+ for (int i = 0; i < n; i++) { // L9c31_whole_object_pass_loop
+ bool changed = false;
+ for (int j = 0; j < n - 1; j++) { // L9c45_objects_loop
+ Object *a = sortedObjects[j];
+ Object *b = sortedObjects[j + 1];
+
+ Math::AABB bboxA = a->_occlusionBox;
+ Math::AABB bboxB = b->_occlusionBox;
+ Math::Vector3d minA = bboxA.getMin() - camera;
+ Math::Vector3d maxA = bboxA.getMax() - camera;
+ Math::Vector3d minB = bboxB.getMin() - camera;
+ Math::Vector3d maxB = bboxB.getMax() - camera;
+
+ int result = 0;
+
+ // X axis
+ result = (result << 2) | checkAxis(minA.x(), maxA.x(), minB.x(), maxB.x());
+ // Y axis
+ result = (result << 2) | checkAxis(minA.y(), maxA.y(), minB.y(), maxB.y());
+ // Z axis
+ result = (result << 2) | checkAxis(minA.z(), maxA.z(), minB.z(), maxB.z());
+
+ bool keepOrder = false;
+ // If result indicates B is closer in at least one axis, AND A is NEVER closer in any axis, keep order (A before B)
+ // Codes where B is closer (2) and A is not (1):
+ // 2 (Z), 8 (Y), 32 (X) -> hex: 02, 08, 20
+ // 2+8=10 (0A), 2+32=34 (22), 8+32=40 (28)
+ // 2+8+32=42 (2A)
+ // L9d37_next_object (Keep order)
+ if (result == 0x02 || result == 0x08 || result == 0x20 ||
+ result == 0x0A || result == 0x22 || result == 0x28 || result == 0x2A)
+ keepOrder = true; // A before B
+
+ if (!keepOrder) {
+ // Swap objects (L9d2c_flip_objects_loop)
+ sortedObjects[j] = b;
+ sortedObjects[j + 1] = a;
+ changed = true;
+ }
}
+ if (!changed)
+ break;
}
}
- for (auto &pair : offsetMap) {
- Object *obj = pair._key;
-
+ for (auto &obj : sortedObjects) {
if (gfx->_debugHighlightObjectID != -1 && obj->getObjectID() != gfx->_debugHighlightObjectID)
continue;
- obj->draw(gfx, pair._value);
+ obj->draw(gfx);
// draw bounding boxes
if (gfx->_debugRenderBoundingBoxes) {
@@ -389,7 +373,6 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
}
}
}
-
_lastTick = animationTicks;
}
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 83410420e9a..d4ad2d759ed 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -850,13 +850,13 @@ void Renderer::renderCube(const Math::Vector3d &originalOrigin, const Math::Vect
uint color = (*colours)[0];
uint ecolor = ecolours ? (*ecolours)[0] : 0;
- if (size.x() <= 1) {
+ /*if (size.x() <= 1) {
origin.x() += offset;
} else if (size.y() <= 1) {
origin.y() += offset;
} else if (size.z() <= 1) {
origin.z() += offset;
- }
+ }*/
if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
setStippleData(stipple);
@@ -980,8 +980,7 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
Math::Vector3d size = originalSize;
Math::Vector3d origin = originalOrigin;
- if (!_isAccelerated)
- polygonOffset(true);
+ enableCulling(false);
if (size.x() > 0 && size.y() > 0 && size.z() > 0) {
/* According to https://www.shdon.com/freescape/
@@ -998,17 +997,16 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
it were a rectangle perpendicular to the Z axis.
TODO: fix this case.
*/
- if (size.x() <= size.y() && size.x() <= size.z())
+ /*if (size.x() <= size.y() && size.x() <= size.z())
size.x() = 0;
else if (size.y() <= size.x() && size.y() <= size.z())
size.y() = 0;
else if (size.z() <= size.x() && size.z() <= size.y())
size.z() = 0;
else
- error("Invalid size!");
+ error("Invalid size!");*/
}
- float dx, dy, dz;
uint8 r1, g1, b1, r2, g2, b2;
byte *stipple = nullptr;
Common::Array<Math::Vector3d> vertices;
@@ -1031,33 +1029,36 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
setStippleData(stipple);
useColor(r1, g1, b1);
- vertices.clear();
- vertices.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z()));
-
- dx = dy = dz = 0.0;
+ float d1x = 0, d1y = 0, d1z = 0;
if (size.x() == 0) {
- dy = size.y();
+ d1y = size.y();
} else if (size.y() == 0) {
- dx = size.x();
+ d1x = size.x();
} else if (size.z() == 0) {
- dx = size.x();
+ d1x = size.x();
}
- vertices.push_back(Math::Vector3d(origin.x() + dx, origin.y() + dy, origin.z() + dz));
- vertices.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z() + size.z()));
- vertices.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z()));
-
- dx = dy = dz = 0.0;
+ float d2x = 0, d2y = 0, d2z = 0;
if (size.x() == 0) {
- dz = size.z();
+ d2z = size.z();
} else if (size.y() == 0) {
- dz = size.z();
+ d2z = size.z();
} else if (size.z() == 0) {
- dy = size.y();
+ d2y = size.y();
}
- vertices.push_back(Math::Vector3d(origin.x() + dx, origin.y() + dy, origin.z() + dz));
- vertices.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z() + size.z()));
+ vertices.clear();
+ if (i == 0) {
+ vertices.push_back(origin);
+ vertices.push_back(Math::Vector3d(origin.x() + d2x, origin.y() + d2y, origin.z() + d2z));
+ vertices.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z() + size.z()));
+ vertices.push_back(Math::Vector3d(origin.x() + d1x, origin.y() + d1y, origin.z() + d1z));
+ } else {
+ vertices.push_back(origin);
+ vertices.push_back(Math::Vector3d(origin.x() + d1x, origin.y() + d1y, origin.z() + d1z));
+ vertices.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z() + size.z()));
+ vertices.push_back(Math::Vector3d(origin.x() + d2x, origin.y() + d2y, origin.z() + d2z));
+ }
renderFace(vertices);
if (r1 != r2 || g1 != g2 || b1 != b2) {
useStipple(true);
@@ -1067,7 +1068,8 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
}
}
}
- polygonOffset(false);
+
+ enableCulling(true);
}
void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<float> *originalOrdinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset) {
@@ -1082,9 +1084,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
uint color = 0;
uint ecolor = 0;
-
+ enableCulling(false);
if (ordinates->size() == 6) { // Line
- polygonOffset(true);
color = (*colours)[0];
ecolor = ecolours ? (*ecolours)[0] : 0;
@@ -1117,12 +1118,7 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
renderFace(vertices);
useStipple(false);
}
- polygonOffset(false);
} else {
-
- if (!_isAccelerated)
- polygonOffset(true);
-
if (size.x() == 0) {
for (int i = 0; i < int(ordinates->size()); i++) {
if (i % 3 == 0)
@@ -1177,7 +1173,7 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
}
- polygonOffset(false);
+ enableCulling(true);
delete(ordinates);
}
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 8f9ae18fb78..1844772ad6b 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -78,6 +78,7 @@ public:
virtual void flipBuffer() {}
virtual void useColor(uint8 r, uint8 g, uint8 b) = 0;
virtual void depthTesting(bool enabled) {};
+ virtual void enableCulling(bool enabled) {};
virtual void polygonOffset(bool enabled) = 0;
virtual Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) = 0;
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index e7c199a6172..466bb3000e7 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -77,7 +77,9 @@ void OpenGLRenderer::init() {
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glFrontFace(GL_CW);
glEnable(GL_SCISSOR_TEST);
setViewport(_viewport);
glEnable(GL_DEPTH_CLAMP);
@@ -127,6 +129,7 @@ void OpenGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glColor4f(1.0, 1.0, 1.0, 1.0);
glDepthMask(GL_FALSE);
@@ -154,7 +157,8 @@ void OpenGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
glBindTexture(GL_TEXTURE_2D, 0); // Bind the default (empty) texture to avoid darker colors!
glFlush();
}
@@ -163,6 +167,7 @@ void OpenGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
OpenGLTexture *glTexture = static_cast<OpenGLTexture *>(texture);
glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
@@ -197,7 +202,8 @@ void OpenGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
glFlush();
}
@@ -331,7 +337,7 @@ void OpenGLRenderer::renderCrossair(const Common::Point &crossairPosition) {
glLineWidth(1);
glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -385,7 +391,7 @@ void OpenGLRenderer::renderPlayerShootRay(byte color, const Common::Point &posit
glLineWidth(1);
glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -456,7 +462,7 @@ void OpenGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, by
useStipple(false);
}
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glPopMatrix();
}
@@ -513,7 +519,7 @@ void OpenGLRenderer::renderPlayerShootBall(byte color, const Common::Point &posi
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -554,12 +560,14 @@ void OpenGLRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
}
void OpenGLRenderer::depthTesting(bool enabled) {
+ glDisable(GL_DEPTH_TEST);
+}
+
+void OpenGLRenderer::enableCulling(bool enabled) {
if (enabled) {
- // If we re-enable depth testing, we need to clear the depth buffer
- glClear(GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
} else {
- glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
}
}
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index 30b1c325827..ac19acac47f 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -76,6 +76,7 @@ public:
virtual void polygonOffset(bool enabled) override;
virtual void setStippleData(byte *data) override;
virtual void useStipple(bool enabled) override;
+ virtual void enableCulling(bool enabled) override;
virtual void depthTesting(bool enabled) override;
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index c3647016676..48ab8db3ce2 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -273,6 +273,12 @@ Object *GeometricObject::duplicate() {
void GeometricObject::computeBoundingBox() {
_boundingBox = Math::AABB();
+ _occlusionBox = Math::AABB();
+
+ // These are used for the rendered, they should NOT be refined or it will break the sorting algorithm
+ _occlusionBox.expand(_origin);
+ _occlusionBox.expand(_origin + _size);
+
Math::Vector3d v;
switch (_type) {
default:
diff --git a/engines/freescape/objects/object.h b/engines/freescape/objects/object.h
index 6bcc6abced1..b1b852c27b4 100644
--- a/engines/freescape/objects/object.h
+++ b/engines/freescape/objects/object.h
@@ -91,6 +91,7 @@ public:
uint16 _objectID;
Math::Vector3d _origin, _size, _rotation;
Math::AABB _boundingBox;
+ Math::AABB _occlusionBox;
Object *_partOfGroup = nullptr;
};
Commit: 140485479c53666f45b5360a95aacdfdb41ae240
https://github.com/scummvm/scummvm/commit/140485479c53666f45b5360a95aacdfdb41ae240
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: extended new rendering to tingyl
Changed paths:
engines/freescape/gfx_tinygl.cpp
engines/freescape/gfx_tinygl.h
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index b646b73c84a..7a42e0cac50 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -78,7 +78,8 @@ void TinyGLRenderer::init() {
tglDisable(TGL_LIGHTING);
tglDisable(TGL_TEXTURE_2D);
- tglEnable(TGL_DEPTH_TEST);
+ tglEnable(TGL_CULL_FACE);
+ tglFrontFace(TGL_CW);
_stippleEnabled = false;
}
@@ -106,6 +107,7 @@ void TinyGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
void TinyGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
TinyGL3DTexture *glTexture = static_cast<TinyGL3DTexture *>(texture);
tglDisable(TGL_DEPTH_TEST);
+ tglDisable(TGL_CULL_FACE);
tglEnable(TGL_TEXTURE_2D);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_REPEAT);
@@ -141,7 +143,7 @@ void TinyGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
tglBindTexture(TGL_TEXTURE_2D, 0);
tglDisable(TGL_TEXTURE_2D);
- tglEnable(TGL_DEPTH_TEST);
+ tglEnable(TGL_CULL_FACE);
tglFlush();
}
@@ -280,7 +282,6 @@ void TinyGLRenderer::renderPlayerShootBall(byte color, const Common::Point &posi
tglDisableClientState(TGL_VERTEX_ARRAY);
tglDisable(TGL_BLEND);
- tglEnable(TGL_DEPTH_TEST);
tglDepthMask(TGL_TRUE);
}
@@ -313,7 +314,6 @@ void TinyGLRenderer::renderPlayerShootRay(byte color, const Common::Point &posit
tglBlendFunc(TGL_ONE_MINUS_DST_COLOR, TGL_ZERO);
}
- tglDisable(TGL_DEPTH_TEST);
tglDepthMask(TGL_FALSE);
tglColor4ub(r, g, b, 255);
@@ -337,7 +337,6 @@ void TinyGLRenderer::renderPlayerShootRay(byte color, const Common::Point &posit
tglDisableClientState(TGL_VERTEX_ARRAY);
tglDisable(TGL_BLEND);
- tglEnable(TGL_DEPTH_TEST);
tglDepthMask(TGL_TRUE);
}
@@ -350,7 +349,6 @@ void TinyGLRenderer::renderCrossair(const Common::Point &crossairPosition) {
tglEnable(TGL_BLEND);
tglBlendFunc(TGL_ONE_MINUS_DST_COLOR, TGL_ZERO);
- tglDisable(TGL_DEPTH_TEST);
tglDepthMask(TGL_FALSE);
useColor(255, 255, 255);
@@ -373,7 +371,6 @@ void TinyGLRenderer::renderCrossair(const Common::Point &crossairPosition) {
tglDisableClientState(TGL_VERTEX_ARRAY);
tglDisable(TGL_BLEND);
- tglEnable(TGL_DEPTH_TEST);
tglDepthMask(TGL_TRUE);
}
@@ -463,7 +460,6 @@ void TinyGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, by
}
tglLoadMatrixf(m);
- tglDisable(TGL_DEPTH_TEST);
tglDepthMask(TGL_FALSE);
setStippleData(stipple);
@@ -490,17 +486,24 @@ void TinyGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, by
useStipple(false);
- tglEnable(TGL_DEPTH_TEST);
tglDepthMask(TGL_TRUE);
tglPopMatrix();
}
void TinyGLRenderer::depthTesting(bool enabled) {
- if (enabled) {
+ /*if (enabled) {
tglClear(TGL_DEPTH_BUFFER_BIT);
tglEnable(TGL_DEPTH_TEST);
} else {
tglDisable(TGL_DEPTH_TEST);
+ }*/
+}
+
+void TinyGLRenderer::enableCulling(bool enabled) {
+ if (enabled) {
+ tglEnable(TGL_CULL_FACE);
+ } else {
+ tglDisable(TGL_CULL_FACE);
}
}
diff --git a/engines/freescape/gfx_tinygl.h b/engines/freescape/gfx_tinygl.h
index a1a515ae88d..beed3e6f2e6 100644
--- a/engines/freescape/gfx_tinygl.h
+++ b/engines/freescape/gfx_tinygl.h
@@ -77,6 +77,7 @@ public:
virtual void useColor(uint8 r, uint8 g, uint8 b) override;
virtual void polygonOffset(bool enabled) override;
virtual void depthTesting(bool enabled) override;
+ virtual void enableCulling(bool enabled) override;
virtual void setStippleData(byte *data) override;
virtual void useStipple(bool enabled) override;
Commit: 0fea7584de738bfd41784ad50ac4acd108ea2fae
https://github.com/scummvm/scummvm/commit/0fea7584de738bfd41784ad50ac4acd108ea2fae
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: extended new rendering to shaders
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
engines/freescape/gfx_opengl_shaders.h
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 404f500a6fb..2b2eae33a36 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -118,7 +118,9 @@ void OpenGLShaderRenderer::init() {
_defaultShaderStippleArray[i] = _defaultStippleArray[i];
glDisable(GL_TEXTURE_2D);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glFrontFace(GL_CW);
glEnable(GL_SCISSOR_TEST);
setViewport(_viewport);
}
@@ -147,6 +149,8 @@ void OpenGLShaderRenderer::drawTexturedRect2D(const Common::Rect &screenRect, co
_bitmapShader->use();
_bitmapShader->setUniform("flipY", glTexture->_upsideDown);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, glTexture->_id);
@@ -155,6 +159,8 @@ void OpenGLShaderRenderer::drawTexturedRect2D(const Common::Rect &screenRect, co
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
_bitmapShader->unbind();
}
@@ -178,6 +184,7 @@ void OpenGLShaderRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
_cubemapShader->setUniform("mvpMatrix", skyboxMVP);
glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, _cubemapTexCoordVBO);
if (texture->_width == 1008)
@@ -194,7 +201,8 @@ void OpenGLShaderRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
_cubemapShader->unbind();
}
@@ -278,6 +286,7 @@ void OpenGLShaderRenderer::renderPlayerShootBall(byte color, const Common::Point
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
}
+ glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
@@ -307,7 +316,8 @@ void OpenGLShaderRenderer::renderPlayerShootBall(byte color, const Common::Point
glDrawArrays(GL_TRIANGLE_FAN, 0, (triangleAmount + 2));
glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -342,6 +352,7 @@ void OpenGLShaderRenderer::renderPlayerShootRay(byte color, const Common::Point
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
}
+ glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
@@ -369,7 +380,8 @@ void OpenGLShaderRenderer::renderPlayerShootRay(byte color, const Common::Point
glLineWidth(1);
glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -451,7 +463,7 @@ void OpenGLShaderRenderer::drawCelestialBody(const Math::Vector3d position, floa
}
// === Restore state ===
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
// === Cleanup binding ===
@@ -564,7 +576,7 @@ void OpenGLShaderRenderer::renderCrossair(const Common::Point &crossairPosition)
glLineWidth(1);
glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
+ glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -650,12 +662,14 @@ void OpenGLShaderRenderer::renderFace(const Common::Array<Math::Vector3d> &verti
}
void OpenGLShaderRenderer::depthTesting(bool enabled) {
+ glDisable(GL_DEPTH_TEST);
+}
+
+void OpenGLShaderRenderer::enableCulling(bool enabled) {
if (enabled) {
- // If we re-enable depth testing, we need to clear the depth buffer
- glClear(GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
} else {
- glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
}
}
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
index c259fc5d4dc..b08c620f64b 100644
--- a/engines/freescape/gfx_opengl_shaders.h
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -83,6 +83,7 @@ public:
virtual void useColor(uint8 r, uint8 g, uint8 b) override;
virtual void polygonOffset(bool enabled) override;
virtual void depthTesting(bool enabled) override;
+ virtual void enableCulling(bool enabled) override;
virtual void setStippleData(byte *data) override;
virtual void useStipple(bool enabled) override;
Commit: de1efbe042f2533e90bd26da4aaf65373a4ef79f
https://github.com/scummvm/scummvm/commit/de1efbe042f2533e90bd26da4aaf65373a4ef79f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fix rebase conflicts in area.cpp
Changed paths:
engines/freescape/area.cpp
engines/freescape/area.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index cba071534ad..55219d84b92 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -225,8 +225,13 @@ void Area::resetArea() {
void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d camera, Math::Vector3d direction, bool insideWait) {
bool runAnimation = animationTicks != _lastTick;
+ bool cameraChanged = camera != _lastCameraPosition;
+ bool sort = runAnimation || cameraChanged || _sortedObjects.empty();
+
assert(_drawableObjects.size() > 0);
- ObjectArray sortedObjects;
+ if (sort)
+ _sortedObjects.clear();
+
Object *floor = nullptr;
for (auto &obj : _drawableObjects) {
@@ -241,7 +246,8 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
continue;
}
- sortedObjects.push_back(obj);
+ if (sort)
+ _sortedObjects.push_back(obj);
}
}
@@ -313,13 +319,13 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
// NOTE: The sorting is performed on unprojected world-space coordinates relative to the player (L847f).
// The rotation/view matrix (computed in L95de) is NOT applied to the bounding boxes used for sorting.
// It is only applied to the vertices during the projection phase (L850f/L9177).
- int n = sortedObjects.size();
- if (n > 1) {
+ int n = _sortedObjects.size();
+ if (n > 1 && sort) {
for (int i = 0; i < n; i++) { // L9c31_whole_object_pass_loop
bool changed = false;
for (int j = 0; j < n - 1; j++) { // L9c45_objects_loop
- Object *a = sortedObjects[j];
- Object *b = sortedObjects[j + 1];
+ Object *a = _sortedObjects[j];
+ Object *b = _sortedObjects[j + 1];
Math::AABB bboxA = a->_occlusionBox;
Math::AABB bboxB = b->_occlusionBox;
@@ -350,8 +356,8 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
if (!keepOrder) {
// Swap objects (L9d2c_flip_objects_loop)
- sortedObjects[j] = b;
- sortedObjects[j + 1] = a;
+ _sortedObjects[j] = b;
+ _sortedObjects[j + 1] = a;
changed = true;
}
}
@@ -360,7 +366,7 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
}
}
- for (auto &obj : sortedObjects) {
+ for (auto &obj : _sortedObjects) {
if (gfx->_debugHighlightObjectID != -1 && obj->getObjectID() != gfx->_debugHighlightObjectID)
continue;
@@ -374,6 +380,8 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
}
}
_lastTick = animationTicks;
+ if (sort)
+ _lastCameraPosition = camera;
}
void Area::drawGroup(Freescape::Renderer *gfx, Group* group, bool runAnimation) {
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 87bfbddb918..f65feb5ff33 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -102,6 +102,9 @@ public:
uint32 _lastTick;
private:
+ Math::Vector3d _lastCameraPosition;
+ ObjectArray _sortedObjects;
+
uint16 _areaID;
uint16 _areaFlags;
ObjectMap *_objectsByID;
Commit: 19acb87f0a78a01135184c3e152839e6154eaa53
https://github.com/scummvm/scummvm/commit/19acb87f0a78a01135184c3e152839e6154eaa53
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: removed depth testing code
Changed paths:
engines/freescape/area.cpp
engines/freescape/gfx.h
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl.h
engines/freescape/gfx_opengl_shaders.cpp
engines/freescape/gfx_opengl_shaders.h
engines/freescape/gfx_tinygl.cpp
engines/freescape/gfx_tinygl.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 55219d84b92..0b5b87787a2 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -252,9 +252,7 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
}
if (floor) {
- gfx->depthTesting(false);
floor->draw(gfx);
- gfx->depthTesting(true);
}
// Corresponds to L9c66 in assembly (bounding_box_axis_loop)
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 1844772ad6b..9e946a7773a 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -77,7 +77,6 @@ public:
*/
virtual void flipBuffer() {}
virtual void useColor(uint8 r, uint8 g, uint8 b) = 0;
- virtual void depthTesting(bool enabled) {};
virtual void enableCulling(bool enabled) {};
virtual void polygonOffset(bool enabled) = 0;
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 466bb3000e7..920e70925f7 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -77,7 +77,6 @@ void OpenGLRenderer::init() {
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
- glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glEnable(GL_SCISSOR_TEST);
@@ -128,7 +127,7 @@ void OpenGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- glDisable(GL_DEPTH_TEST);
+
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glColor4f(1.0, 1.0, 1.0, 1.0);
@@ -157,7 +156,6 @@ void OpenGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
- glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glBindTexture(GL_TEXTURE_2D, 0); // Bind the default (empty) texture to avoid darker colors!
glFlush();
@@ -166,7 +164,6 @@ void OpenGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
void OpenGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
OpenGLTexture *glTexture = static_cast<OpenGLTexture *>(texture);
- glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
@@ -202,7 +199,6 @@ void OpenGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
- glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glFlush();
}
@@ -311,7 +307,7 @@ void OpenGLRenderer::renderCrossair(const Common::Point &crossairPosition) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
- glDisable(GL_DEPTH_TEST);
+
glDepthMask(GL_FALSE);
useColor(255, 255, 255);
@@ -337,7 +333,6 @@ void OpenGLRenderer::renderCrossair(const Common::Point &crossairPosition) {
glLineWidth(1);
glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -367,7 +362,6 @@ void OpenGLRenderer::renderPlayerShootRay(byte color, const Common::Point &posit
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
}
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glColor4ub(r, g, b, 255);
@@ -391,7 +385,6 @@ void OpenGLRenderer::renderPlayerShootRay(byte color, const Common::Point &posit
glLineWidth(1);
glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -420,7 +413,6 @@ void OpenGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, by
}
glLoadMatrixf(m);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
setStippleData(stipple);
@@ -462,7 +454,6 @@ void OpenGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, by
useStipple(false);
}
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glPopMatrix();
}
@@ -493,7 +484,6 @@ void OpenGLRenderer::renderPlayerShootBall(byte color, const Common::Point &posi
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
}
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glColor4ub(r, g, b, 255);
@@ -519,7 +509,6 @@ void OpenGLRenderer::renderPlayerShootBall(byte color, const Common::Point &posi
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -559,10 +548,6 @@ void OpenGLRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
glDisableClientState(GL_VERTEX_ARRAY);
}
-void OpenGLRenderer::depthTesting(bool enabled) {
- glDisable(GL_DEPTH_TEST);
-}
-
void OpenGLRenderer::enableCulling(bool enabled) {
if (enabled) {
glEnable(GL_CULL_FACE);
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index ac19acac47f..691faa42222 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -77,7 +77,6 @@ public:
virtual void setStippleData(byte *data) override;
virtual void useStipple(bool enabled) override;
virtual void enableCulling(bool enabled) override;
- virtual void depthTesting(bool enabled) override;
Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) override;
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 2b2eae33a36..adc8bda0304 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -118,7 +118,6 @@ void OpenGLShaderRenderer::init() {
_defaultShaderStippleArray[i] = _defaultStippleArray[i];
glDisable(GL_TEXTURE_2D);
- glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glEnable(GL_SCISSOR_TEST);
@@ -150,7 +149,6 @@ void OpenGLShaderRenderer::drawTexturedRect2D(const Common::Rect &screenRect, co
_bitmapShader->setUniform("flipY", glTexture->_upsideDown);
glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, glTexture->_id);
@@ -159,7 +157,6 @@ void OpenGLShaderRenderer::drawTexturedRect2D(const Common::Rect &screenRect, co
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
- glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
_bitmapShader->unbind();
}
@@ -183,7 +180,6 @@ void OpenGLShaderRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
_cubemapShader->use();
_cubemapShader->setUniform("mvpMatrix", skyboxMVP);
- glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, _cubemapTexCoordVBO);
@@ -201,7 +197,6 @@ void OpenGLShaderRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
- glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
_cubemapShader->unbind();
@@ -287,7 +282,6 @@ void OpenGLShaderRenderer::renderPlayerShootBall(byte color, const Common::Point
}
glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
useColor(r, g, b);
@@ -317,7 +311,6 @@ void OpenGLShaderRenderer::renderPlayerShootBall(byte color, const Common::Point
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -353,7 +346,6 @@ void OpenGLShaderRenderer::renderPlayerShootRay(byte color, const Common::Point
}
glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
useColor(r, g, b);
@@ -381,7 +373,6 @@ void OpenGLShaderRenderer::renderPlayerShootRay(byte color, const Common::Point
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -449,7 +440,6 @@ void OpenGLShaderRenderer::drawCelestialBody(const Math::Vector3d position, floa
_triangleShader->setUniform("useStipple", false);
// === Render settings ===
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
// === Draw vertex fan ===
@@ -463,7 +453,6 @@ void OpenGLShaderRenderer::drawCelestialBody(const Math::Vector3d position, floa
}
// === Restore state ===
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
// === Cleanup binding ===
@@ -549,7 +538,6 @@ void OpenGLShaderRenderer::renderCrossair(const Common::Point &crossairPosition)
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
useColor(255, 255, 255);
@@ -576,7 +564,6 @@ void OpenGLShaderRenderer::renderCrossair(const Common::Point &crossairPosition)
glLineWidth(1);
glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
@@ -661,10 +648,6 @@ void OpenGLShaderRenderer::renderFace(const Common::Array<Math::Vector3d> &verti
#endif
}
-void OpenGLShaderRenderer::depthTesting(bool enabled) {
- glDisable(GL_DEPTH_TEST);
-}
-
void OpenGLShaderRenderer::enableCulling(bool enabled) {
if (enabled) {
glEnable(GL_CULL_FACE);
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
index b08c620f64b..898bcb362ee 100644
--- a/engines/freescape/gfx_opengl_shaders.h
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -82,7 +82,6 @@ public:
virtual void useColor(uint8 r, uint8 g, uint8 b) override;
virtual void polygonOffset(bool enabled) override;
- virtual void depthTesting(bool enabled) override;
virtual void enableCulling(bool enabled) override;
virtual void setStippleData(byte *data) override;
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index 7a42e0cac50..f4b094c617f 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -106,7 +106,6 @@ void TinyGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
void TinyGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
TinyGL3DTexture *glTexture = static_cast<TinyGL3DTexture *>(texture);
- tglDisable(TGL_DEPTH_TEST);
tglDisable(TGL_CULL_FACE);
tglEnable(TGL_TEXTURE_2D);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_REPEAT);
@@ -256,7 +255,7 @@ void TinyGLRenderer::renderPlayerShootBall(byte color, const Common::Point &posi
tglBlendFunc(TGL_ONE_MINUS_DST_COLOR, TGL_ZERO);
}
- tglDisable(TGL_DEPTH_TEST);
+
tglDepthMask(TGL_FALSE);
tglColor4ub(r, g, b, 255);
@@ -490,15 +489,6 @@ void TinyGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, by
tglPopMatrix();
}
-void TinyGLRenderer::depthTesting(bool enabled) {
- /*if (enabled) {
- tglClear(TGL_DEPTH_BUFFER_BIT);
- tglEnable(TGL_DEPTH_TEST);
- } else {
- tglDisable(TGL_DEPTH_TEST);
- }*/
-}
-
void TinyGLRenderer::enableCulling(bool enabled) {
if (enabled) {
tglEnable(TGL_CULL_FACE);
diff --git a/engines/freescape/gfx_tinygl.h b/engines/freescape/gfx_tinygl.h
index beed3e6f2e6..cc4228018c5 100644
--- a/engines/freescape/gfx_tinygl.h
+++ b/engines/freescape/gfx_tinygl.h
@@ -76,7 +76,6 @@ public:
virtual void useColor(uint8 r, uint8 g, uint8 b) override;
virtual void polygonOffset(bool enabled) override;
- virtual void depthTesting(bool enabled) override;
virtual void enableCulling(bool enabled) override;
virtual void setStippleData(byte *data) override;
virtual void useStipple(bool enabled) override;
Commit: 878ae8a478389b237cc22552cd71d90747e6a3a9
https://github.com/scummvm/scummvm/commit/878ae8a478389b237cc22552cd71d90747e6a3a9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: reduced artifacts in rendering thanks to @dhruv0154 fixes
Changed paths:
engines/freescape/area.cpp
engines/freescape/gfx.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 0b5b87787a2..a515cda0399 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -257,13 +257,12 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
// Corresponds to L9c66 in assembly (bounding_box_axis_loop)
auto checkAxis = [](float minA, float maxA, float minB, float maxB) -> int {
+ bool signMinA = minA >= 0;
+ bool signMaxA = maxA >= 0;
+ bool signMinB = minB >= 0;
+ bool signMaxB = maxB >= 0;
if (minA >= maxB) { // A is clearly "greater" than B (L9c9b_one_object_clearly_further_than_the_other)
- bool signMinA = minA >= 0;
- bool signMaxA = maxA >= 0;
- bool signMinB = minB >= 0;
- bool signMaxB = maxB >= 0;
-
- if (signMinA != signMaxA) // A covers 0 (L9ce6_first_object_is_closer)
+ if (signMinA != signMaxB) // A covers 0 (L9ce6_first_object_is_closer)
return 1; // A is closer
if (signMinB != signMaxB) // B covers 0 (L9cec_second_object_is_closer)
return 2; // B is closer
@@ -284,11 +283,6 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
return 1; // A closer
}
} else if (minB >= maxA) { // B is clearly "greater" than A
- bool signMinB = minB >= 0;
- bool signMaxB = maxB >= 0;
- bool signMinA = minA >= 0;
- bool signMaxA = maxA >= 0;
-
if (signMinB != signMaxB) // B covers 0 (L9cec_second_object_is_closer)
return 2; // B is closer
if (signMinA != signMaxA) // A covers 0 (L9ce6_first_object_is_closer)
@@ -352,6 +346,21 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
result == 0x0A || result == 0x22 || result == 0x28 || result == 0x2A)
keepOrder = true; // A before B
+ if (result == 0) {
+ bool aInFront = minA.z() < 0;
+ bool bInFront = minB.z() < 0;
+ // if signs differ that means one object is positive in the z axis i.e. not visible in the camera
+ if (aInFront != bInFront) {
+ // one is visible, one is behind us.
+ // we want the one behind the camera (positive Z) to be drawn first
+ // so the visible object draws on top of it
+ // the one with the larger Z (positive) should come first
+ if (minA.z() > minB.z()) {
+ keepOrder = true;
+ }
+ }
+ }
+
if (!keepOrder) {
// Swap objects (L9d2c_flip_objects_loop)
_sortedObjects[j] = b;
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index d4ad2d759ed..c56f1d90e7c 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -980,7 +980,7 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
Math::Vector3d size = originalSize;
Math::Vector3d origin = originalOrigin;
- enableCulling(false);
+ //enableCulling(false);
if (size.x() > 0 && size.y() > 0 && size.z() > 0) {
/* According to https://www.shdon.com/freescape/
@@ -1069,7 +1069,7 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
}
}
- enableCulling(true);
+ //enableCulling(true);
}
void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<float> *originalOrdinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset) {
@@ -1084,7 +1084,7 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
uint color = 0;
uint ecolor = 0;
- enableCulling(false);
+ //enableCulling(false);
if (ordinates->size() == 6) { // Line
color = (*colours)[0];
ecolor = ecolours ? (*ecolours)[0] : 0;
@@ -1173,7 +1173,7 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
}
- enableCulling(true);
+ //enableCulling(true);
delete(ordinates);
}
Commit: 32bbd7071d800725e92f9a8d59a989a13da62f0a
https://github.com/scummvm/scummvm/commit/32bbd7071d800725e92f9a8d59a989a13da62f0a
Author: dhruv (dhruvranger97 at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fix culling issues in castle master.
Changed paths:
engines/freescape/gfx.cpp
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index c56f1d90e7c..0f702d0784d 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -980,8 +980,6 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
Math::Vector3d size = originalSize;
Math::Vector3d origin = originalOrigin;
- //enableCulling(false);
-
if (size.x() > 0 && size.y() > 0 && size.z() > 0) {
/* According to https://www.shdon.com/freescape/
If the bounding box is has all non-zero dimensions
@@ -1021,6 +1019,8 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
origin.z() += offset;
}
+ bool isHorizontal = (size.y() == 0);
+
for (int i = 0; i < 2; i++) {
color = (*colours)[i];
@@ -1048,7 +1048,8 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
}
vertices.clear();
- if (i == 0) {
+ bool useFlippedWinding = (i == 0) || (isHorizontal && i == 1);
+ if (useFlippedWinding) {
vertices.push_back(origin);
vertices.push_back(Math::Vector3d(origin.x() + d2x, origin.y() + d2y, origin.z() + d2z));
vertices.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z() + size.z()));
@@ -1068,11 +1069,12 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
}
}
}
-
- //enableCulling(true);
}
-void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<float> *originalOrdinates, Common::Array<uint8> *colours, Common::Array<uint8> *ecolours, float offset) {
+void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size,
+ const Common::Array<float> *originalOrdinates, Common::Array<uint8> *colours,
+ Common::Array<uint8> *ecolours, float offset) {
+
Common::Array<float> *ordinates = new Common::Array<float>(*originalOrdinates);
uint8 r1, g1, b1, r2, g2, b2;
@@ -1084,7 +1086,7 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
uint color = 0;
uint ecolor = 0;
- //enableCulling(false);
+ bool isPlanar = (size.x() == 0 || size.y() == 0 || size.z() == 0);
if (ordinates->size() == 6) { // Line
color = (*colours)[0];
ecolor = ecolours ? (*ecolours)[0] : 0;
@@ -1142,9 +1144,10 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
setStippleData(stipple);
useColor(r1, g1, b1);
- for (uint i = 0; i < ordinates->size(); i = i + 3) {
- vertices.push_back(Math::Vector3d((*ordinates)[i], (*ordinates)[i + 1], (*ordinates)[i + 2]));
- }
+ // reverse winding
+ for (int k = ordinates->size(); k > 0; k = k - 3)
+ vertices.push_back(Math::Vector3d((*ordinates)[k - 3], (*ordinates)[k - 2], (*ordinates)[k - 1]));
+
renderFace(vertices);
if (r1 != r2 || g1 != g2 || b1 != b2) {
useStipple(true);
@@ -1160,9 +1163,10 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
if (getRGBAt(color, ecolor, r1, g1, b1, r2, g2, b2, stipple)) {
setStippleData(stipple);
useColor(r1, g1, b1);
- for (int i = ordinates->size(); i > 0; i = i - 3) {
- vertices.push_back(Math::Vector3d((*ordinates)[i - 3], (*ordinates)[i - 2], (*ordinates)[i - 1]));
- }
+ // forward winding
+ for (uint k = 0; k < ordinates->size(); k = k + 3)
+ vertices.push_back(Math::Vector3d((*ordinates)[k], (*ordinates)[k + 1], (*ordinates)[k + 2]));
+
renderFace(vertices);
if (r1 != r2 || g1 != g2 || b1 != b2) {
useStipple(true);
@@ -1173,7 +1177,6 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
}
- //enableCulling(true);
delete(ordinates);
}
Commit: 6413ffa6a04f2ec6523358cfb76cfff44524245e
https://github.com/scummvm/scummvm/commit/6413ffa6a04f2ec6523358cfb76cfff44524245e
Author: dhruv (dhruvranger97 at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fix overlap for planar objects.
objects like door handles were flickering from some camera position, this is solved in this commit.
Changed paths:
engines/freescape/area.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index a515cda0399..82ea08c6692 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -261,7 +261,7 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
bool signMaxA = maxA >= 0;
bool signMinB = minB >= 0;
bool signMaxB = maxB >= 0;
- if (minA >= maxB) { // A is clearly "greater" than B (L9c9b_one_object_clearly_further_than_the_other)
+ if (minA >= maxB - 0.5f) { // A is clearly "greater" than B (L9c9b_one_object_clearly_further_than_the_other)
if (signMinA != signMaxB) // A covers 0 (L9ce6_first_object_is_closer)
return 1; // A is closer
if (signMinB != signMaxB) // B covers 0 (L9cec_second_object_is_closer)
@@ -282,7 +282,7 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
if (maxA > maxB) return 2; // B closer
return 1; // A closer
}
- } else if (minB >= maxA) { // B is clearly "greater" than A
+ } else if (minB >= maxA - 0.5f) { // B is clearly "greater" than A
if (signMinB != signMaxB) // B covers 0 (L9cec_second_object_is_closer)
return 2; // B is closer
if (signMinA != signMaxA) // A covers 0 (L9ce6_first_object_is_closer)
Commit: 5e8deecc7834e6a658d103504bc8787ff0111906
https://github.com/scummvm/scummvm/commit/5e8deecc7834e6a658d103504bc8787ff0111906
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fixes for renderRectangle
Changed paths:
engines/freescape/gfx.cpp
engines/freescape/gfx_opengl.cpp
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 0f702d0784d..2cf10feac71 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -1019,8 +1019,6 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
origin.z() += offset;
}
- bool isHorizontal = (size.y() == 0);
-
for (int i = 0; i < 2; i++) {
color = (*colours)[i];
@@ -1048,7 +1046,11 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
}
vertices.clear();
- bool useFlippedWinding = (i == 0) || (isHorizontal && i == 1);
+ bool useFlippedWinding = (size.x() == 0) || (size.z() == 0);
+
+ if (i == 1)
+ useFlippedWinding = !useFlippedWinding;
+
if (useFlippedWinding) {
vertices.push_back(origin);
vertices.push_back(Math::Vector3d(origin.x() + d2x, origin.y() + d2y, origin.z() + d2z));
@@ -1086,7 +1088,6 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
uint color = 0;
uint ecolor = 0;
- bool isPlanar = (size.x() == 0 || size.y() == 0 || size.z() == 0);
if (ordinates->size() == 6) { // Line
color = (*colours)[0];
ecolor = ecolours ? (*ecolours)[0] : 0;
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 920e70925f7..3bf43dcd3e0 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -79,6 +79,7 @@ void OpenGLRenderer::init() {
glDisable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
+ glCullFace(GL_BACK);
glEnable(GL_SCISSOR_TEST);
setViewport(_viewport);
glEnable(GL_DEPTH_CLAMP);
Commit: 1fc666556b6324a5953952f43a655e94bd80c5f2
https://github.com/scummvm/scummvm/commit/1fc666556b6324a5953952f43a655e94bd80c5f2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fixed invisible bottom of a chest in eclipse demo (cpc)
Changed paths:
engines/freescape/games/eclipse/cpc.cpp
engines/freescape/objects/geometricobject.cpp
engines/freescape/objects/geometricobject.h
diff --git a/engines/freescape/games/eclipse/cpc.cpp b/engines/freescape/games/eclipse/cpc.cpp
index 0f4dd244126..96460fe0a55 100644
--- a/engines/freescape/games/eclipse/cpc.cpp
+++ b/engines/freescape/games/eclipse/cpc.cpp
@@ -143,6 +143,12 @@ void EclipseEngine::loadAssetsCPCDemo() {
loadColorPalette();
swapPalette(1);
+ // This patch forces a solid color to the bottom of the chest in the area 5
+ // It was transparent in the original game
+ GeometricObject *obj = (GeometricObject *)_areaMap[5]->objectWithID(12);
+ assert(obj);
+ obj->setColor(2, 4);
+
_indicators.push_back(loadBundledImage("eclipse_ankh_indicator"));
for (auto &it : _indicators)
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index 48ab8db3ce2..bc5b1c6b80c 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -484,4 +484,10 @@ void GeometricObject::draw(Renderer *gfx, float offset) {
}
}
+void GeometricObject::setColor(int idx, int color) {
+ assert(_colours);
+ assert(idx < _colours->size());
+ (*_colours)[idx] = color;
+}
+
} // End of namespace Freescape
diff --git a/engines/freescape/objects/geometricobject.h b/engines/freescape/objects/geometricobject.h
index 2b8bd956a24..6d7d4f12117 100644
--- a/engines/freescape/objects/geometricobject.h
+++ b/engines/freescape/objects/geometricobject.h
@@ -59,6 +59,7 @@ public:
void computeBoundingBox();
bool collides(const Math::AABB &boundingBox);
void draw(Freescape::Renderer *gfx, float offset = 0.0) override;
+ void setColor(int idx, int color);
bool isDrawable() override;
bool isPlanar() override;
bool _cyclingColors;
Commit: e7da5f1b9a3f3f68d4265e3a0696b89f3e5a086b
https://github.com/scummvm/scummvm/commit/e7da5f1b9a3f3f68d4265e3a0696b89f3e5a086b
Author: dhruv (dhruvranger97 at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESACPE: improved debugger.
added command to print sort order, show occlusion boxes and improved iso command to isolate multiple objects and only sort and render isolated objects.
Changed paths:
engines/freescape/area.cpp
engines/freescape/area.h
engines/freescape/debugger.cpp
engines/freescape/debugger.h
engines/freescape/gfx.cpp
engines/freescape/gfx.h
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 82ea08c6692..8c3d554ab0e 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -236,6 +236,19 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
+ if (!gfx->_debugHighlightObjectIDs.empty()) {
+ bool found = false;
+ for (auto id : gfx->_debugHighlightObjectIDs) {
+ if (obj->getObjectID() == id) {
+ found = true;
+ break;
+ }
+ }
+ // if this object is not in our list, skip it completely.
+ // it will not be sorted, and it will not be drawn.
+ if (!found)
+ continue;
+ }
if (obj->getObjectID() == 0 && _groundColor < 255 && _skyColor < 255) {
floor = obj;
continue;
@@ -374,17 +387,13 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
}
for (auto &obj : _sortedObjects) {
- if (gfx->_debugHighlightObjectID != -1 && obj->getObjectID() != gfx->_debugHighlightObjectID)
- continue;
-
obj->draw(gfx);
// draw bounding boxes
- if (gfx->_debugRenderBoundingBoxes) {
- if (gfx->_debugBoundingBoxFilterID == -1 || gfx->_debugBoundingBoxFilterID == obj->getObjectID()) {
- gfx->drawAABB(obj->_boundingBox, 0, 255, 0);
- }
- }
+ if (gfx->_debugRenderBoundingBoxes)
+ gfx->drawAABB(obj->_boundingBox, 0, 255, 0);
+ if (gfx->_debugRenderOcclusionBoxes)
+ gfx->drawAABB(obj->_occlusionBox, 255, 0, 0);
}
_lastTick = animationTicks;
if (sort)
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index f65feb5ff33..62a0106acfd 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -50,6 +50,7 @@ public:
void changeObjectID(uint16 objectID, uint16 newObjectID);
ObjectArray getSensors();
uint16 getAreaID();
+ Common::Array<Object *> &getSortedObjects() { return _sortedObjects; }
uint16 getAreaFlags();
uint8 getScale();
void remapColor(int index, int color);
diff --git a/engines/freescape/debugger.cpp b/engines/freescape/debugger.cpp
index f9d1e4e80d2..7f05fa6433e 100644
--- a/engines/freescape/debugger.cpp
+++ b/engines/freescape/debugger.cpp
@@ -40,20 +40,18 @@ Debugger::Debugger(FreescapeEngine *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("obj_pos", WRAP_METHOD(Debugger, cmdObjPos)); // get object pos
registerCmd("obj_mov", WRAP_METHOD(Debugger, cmdSetObjPos)); // move object
registerCmd("goto", WRAP_METHOD(Debugger, cmdGoto)); // teleport to a position
+ registerCmd("sort_order", WRAP_METHOD(Debugger, cmdSortOrder)); // print current draw order of objects
+ registerCmd("occ", WRAP_METHOD(Debugger, cmdShowOcclusion)); // toggle occlussion boxes
}
Debugger::~Debugger() {}
bool Debugger::cmdShowBBox(int argc, const char **argv) {
if (argc < 2) {
- debugPrintf("Usage: bbox <0/1> [id]\n");
+ debugPrintf("Usage: bbox <0/1>\n");
return true;
}
_vm->_gfx->_debugRenderBoundingBoxes = atoi(argv[1]);
- if (argc > 2)
- _vm->_gfx->_debugBoundingBoxFilterID = atoi(argv[2]);
- else
- _vm->_gfx->_debugBoundingBoxFilterID = -1;
return true;
}
@@ -76,11 +74,25 @@ bool Debugger::cmdShowNormals(int argc, const char **argv) {
}
bool Debugger::cmdHighlightID(int argc, const char **argv) {
+ _vm->_gfx->_debugHighlightObjectIDs.clear();
if (argc < 2) {
- debugPrintf("Usage: iso <id> (-1 for all)\n");
+ debugPrintf("Isolation cleared, drawing all objects.\n");
+ debugPrintf("Usage: iso [id1] [id2] [id3] ...\n");
return true;
}
- _vm->_gfx->_debugHighlightObjectID = atoi(argv[1]);
+ debugPrintf("Isolating Objects: ");
+ for (int i = 1; i < argc; i++) {
+ int id = atoi(argv[i]);
+ if (id == -1) {
+ _vm->_gfx->_debugHighlightObjectIDs.clear();
+ debugPrintf("All (Cleared)");
+ break;
+ }
+
+ _vm->_gfx->_debugHighlightObjectIDs.push_back(id);
+ debugPrintf("%d ", id);
+ }
+ debugPrintf("\n");
return true;
}
@@ -164,4 +176,31 @@ bool Debugger::cmdGoto(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdSortOrder(int argc, const char** argv) {
+ if (!_vm->_currentArea) {
+ debugPrintf("No area loaded.\n");
+ return true;
+ }
+
+ Common::Array<Object *> &objs = _vm->_currentArea->getSortedObjects();
+
+ debugPrintf("Current Draw Order:\n");
+ debugPrintf("Total Objects: %d\n", objs.size());
+ for (uint i = 0; i < objs.size(); i++) {
+ Object *obj = objs[i];
+ debugPrintf("%d ", obj->getObjectID());
+ }
+ debugPrintf("\n");
+ return true;
+}
+
+bool Debugger::cmdShowOcclusion(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("Usage: occ <0/1>\n");
+ return true;
+ }
+ _vm->_gfx->_debugRenderOcclusionBoxes = atoi(argv[1]);
+ return true;
+}
+
}
diff --git a/engines/freescape/debugger.h b/engines/freescape/debugger.h
index fa719919440..1c7c549e166 100644
--- a/engines/freescape/debugger.h
+++ b/engines/freescape/debugger.h
@@ -44,6 +44,8 @@ private:
bool cmdGoto(int argc, const char **argv);
bool cmdObjPos(int argc, const char **argv);
bool cmdSetObjPos(int argc, const char **argv);
+ bool cmdSortOrder(int argc, const char **argv);
+ bool cmdShowOcclusion(int argc, const char **argv);
};
}
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 2cf10feac71..49a4a6fe1c7 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -51,10 +51,9 @@ Renderer::Renderer(int screenW, int screenH, Common::RenderMode renderMode, bool
_renderMode = renderMode;
_isAccelerated = false;
_debugRenderBoundingBoxes = false;
- _debugBoundingBoxFilterID = -1;
+ _debugRenderOcclusionBoxes = false;
_debugRenderWireframe = false;
_debugRenderNormals = false;
- _debugHighlightObjectID = -1;
_authenticGraphics = authenticGraphics;
for (int i = 0; i < 16; i++) {
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 9e946a7773a..ba9187c2a3a 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -294,10 +294,10 @@ public:
// debug flags
bool _debugRenderBoundingBoxes;
- int _debugBoundingBoxFilterID;
+ bool _debugRenderOcclusionBoxes;
bool _debugRenderWireframe;
bool _debugRenderNormals;
- int _debugHighlightObjectID;
+ Common::Array<uint8> _debugHighlightObjectIDs;
// for drawing bounding boxes
virtual void drawAABB(const Math::AABB &aabb, uint8 r, uint8 g, uint8 b) {}
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index adc8bda0304..413b9da1f28 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -521,7 +521,6 @@ void OpenGLShaderRenderer::drawAABB(const Math::AABB &aabb, uint8 r, uint8 g, ui
// restore state
glLineWidth(1.0f);
- glEnable(GL_DEPTH_TEST);
}
void OpenGLShaderRenderer::renderCrossair(const Common::Point &crossairPosition) {
Commit: 814f7e22431562ddd2c57828d82513ee70313a09
https://github.com/scummvm/scummvm/commit/814f7e22431562ddd2c57828d82513ee70313a09
Author: dhruv (dhruvranger97 at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: fix artifacts in castle master.
Changed paths:
engines/freescape/area.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 8c3d554ab0e..ac288f6c159 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -359,21 +359,6 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
result == 0x0A || result == 0x22 || result == 0x28 || result == 0x2A)
keepOrder = true; // A before B
- if (result == 0) {
- bool aInFront = minA.z() < 0;
- bool bInFront = minB.z() < 0;
- // if signs differ that means one object is positive in the z axis i.e. not visible in the camera
- if (aInFront != bInFront) {
- // one is visible, one is behind us.
- // we want the one behind the camera (positive Z) to be drawn first
- // so the visible object draws on top of it
- // the one with the larger Z (positive) should come first
- if (minA.z() > minB.z()) {
- keepOrder = true;
- }
- }
- }
-
if (!keepOrder) {
// Swap objects (L9d2c_flip_objects_loop)
_sortedObjects[j] = b;
Commit: 9b0c32ef97b5f7b5bfa9459aee734bfc461f3ecb
https://github.com/scummvm/scummvm/commit/9b0c32ef97b5f7b5bfa9459aee734bfc461f3ecb
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-03-01T14:28:50+01:00
Commit Message:
FREESCAPE: updated credits
Changed paths:
engines/freescape/credits.pl
diff --git a/engines/freescape/credits.pl b/engines/freescape/credits.pl
index 12652d09a78..1d9c21c4bba 100644
--- a/engines/freescape/credits.pl
+++ b/engines/freescape/credits.pl
@@ -1,4 +1,5 @@
begin_section("Freescape");
add_person("Chris Allen", "", "Sound engine programming");
+ add_person("Dhruv", "", "Render engine fixes");
add_person("Gustavo Grieco", "neuromancer", "");
end_section();
More information about the Scummvm-git-logs
mailing list