[Scummvm-git-logs] scummvm master -> 6a88a4c06827659d49364b645a1929e785370619

neuromancer noreply at scummvm.org
Sat Nov 23 08:01:25 UTC 2024


This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
0edaf859d3 FREESCAPE: more tinygl fixes to avoid rounding issues
66df0b3f54 FREESCAPE: tweak glPolygonOffset values
867960e60d FREESCAPE: added 3D textures to TinyGL and implemented background for castle
4ceba8c1f8 FREESCAPE: refactored and unified getRGBAPixelFormat across all the codebase
6a88a4c068 FREESCAPE: first attempt to implement stipple patterns in TinyGL using textures


Commit: 0edaf859d34e656a78629df15dc8bc5e2d2f518e
    https://github.com/scummvm/scummvm/commit/0edaf859d34e656a78629df15dc8bc5e2d2f518e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-11-23T09:01:43+01:00

Commit Message:
FREESCAPE: more tinygl fixes to avoid rounding issues

Changed paths:
    engines/freescape/area.cpp
    engines/freescape/gfx.cpp
    engines/freescape/gfx_tinygl.cpp


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 30e204af6b0..039bac55de9 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -241,7 +241,7 @@ void Area::draw(Freescape::Renderer *gfx, uint32 animationTicks, Math::Vector3d
 	ObjectArray nonPlanarObjects;
 	Object *floor = nullptr;
 	Common::HashMap<Object *, float> sizes;
-	float offset = (gfx->_isAccelerated ? 1.0 : 2.0) / _scale;
+	float offset = 1.0 / _scale;
 
 	for (auto &obj : _drawableObjects) {
 		if (!obj->isDestroyed() && !obj->isInvisible()) {
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 4f4cfe17d02..e4a0c6614a9 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -955,6 +955,9 @@ void Renderer::renderRectangle(const Math::Vector3d &originalOrigin, const Math:
 	Math::Vector3d size = originalSize;
 	Math::Vector3d origin = originalOrigin;
 
+	if (!_isAccelerated)
+		polygonOffset(true);
+
 	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
@@ -1091,6 +1094,10 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 		}
 		polygonOffset(false);
 	} else {
+
+		if (!_isAccelerated)
+			polygonOffset(true);
+
 		if (size.x() == 0) {
 			for (int i = 0; i < int(ordinates->size()); i++) {
 				if (i % 3 == 0)
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index 434da92facf..e1230a8395f 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -273,7 +273,7 @@ void TinyGLRenderer::useStipple(bool enabled) {
 		TGLfloat factor = 0;
 		tglGetFloatv(TGL_POLYGON_OFFSET_FACTOR, &factor);
 		tglEnable(TGL_POLYGON_OFFSET_FILL);
-		tglPolygonOffset(factor - 5.0f, -1.0f);
+		tglPolygonOffset(factor - 1.0f, -1.0f);
 		tglEnable(TGL_POLYGON_STIPPLE);
 		if (_renderMode == Common::kRenderZX  ||
 			_renderMode == Common::kRenderCPC ||
@@ -405,7 +405,7 @@ void TinyGLRenderer::depthTesting(bool enabled) {
 void TinyGLRenderer::polygonOffset(bool enabled) {
 	if (enabled) {
 		tglEnable(TGL_POLYGON_OFFSET_FILL);
-		tglPolygonOffset(-10.0f, 1.0f);
+		tglPolygonOffset(-1.0f, 1.0f);
 	} else {
 		tglPolygonOffset(0, 0);
 		tglDisable(TGL_POLYGON_OFFSET_FILL);


Commit: 66df0b3f5417f70e4762a827193c92e523fff103
    https://github.com/scummvm/scummvm/commit/66df0b3f5417f70e4762a827193c92e523fff103
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-11-23T09:01:43+01:00

Commit Message:
FREESCAPE: tweak glPolygonOffset values

Changed paths:
    engines/freescape/gfx_opengl.cpp
    engines/freescape/gfx_tinygl.cpp


diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 15ed174e24c..148728925ec 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -492,7 +492,7 @@ void OpenGLRenderer::depthTesting(bool enabled) {
 void OpenGLRenderer::polygonOffset(bool enabled) {
 	if (enabled) {
 		glEnable(GL_POLYGON_OFFSET_FILL);
-		glPolygonOffset(-10.0f, 1.0f);
+		glPolygonOffset(-1.0f, 1.0f);
 	} else {
 		glPolygonOffset(0, 0);
 		glDisable(GL_POLYGON_OFFSET_FILL);
@@ -513,7 +513,7 @@ void OpenGLRenderer::useStipple(bool enabled) {
 		GLfloat factor = 0;
 		glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &factor);
 		glEnable(GL_POLYGON_OFFSET_FILL);
-		glPolygonOffset(factor - 1.0f, -1.0f);
+		glPolygonOffset(factor - 0.5f, -1.0f);
 		glEnable(GL_POLYGON_STIPPLE);
 		if (_renderMode == Common::kRenderZX    ||
 			_renderMode == Common::kRenderCPC   ||
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index e1230a8395f..c1317a905fb 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -273,7 +273,7 @@ void TinyGLRenderer::useStipple(bool enabled) {
 		TGLfloat factor = 0;
 		tglGetFloatv(TGL_POLYGON_OFFSET_FACTOR, &factor);
 		tglEnable(TGL_POLYGON_OFFSET_FILL);
-		tglPolygonOffset(factor - 1.0f, -1.0f);
+		tglPolygonOffset(factor - 0.5f, -1.0f);
 		tglEnable(TGL_POLYGON_STIPPLE);
 		if (_renderMode == Common::kRenderZX  ||
 			_renderMode == Common::kRenderCPC ||


Commit: 867960e60d5b843a8a7b895e6eaa952d40eec5ee
    https://github.com/scummvm/scummvm/commit/867960e60d5b843a8a7b895e6eaa952d40eec5ee
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-11-23T09:01:43+01:00

Commit Message:
FREESCAPE: added 3D textures to TinyGL and implemented background for castle

Changed paths:
    engines/freescape/freescape.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_opengl_texture.cpp
    engines/freescape/gfx_tinygl.cpp
    engines/freescape/gfx_tinygl.h
    engines/freescape/gfx_tinygl_texture.cpp
    engines/freescape/gfx_tinygl_texture.h


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 35cb66a4009..c702ff6f82c 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -406,7 +406,7 @@ void FreescapeEngine::drawBackground() {
 
 	if (isCastle() && _background) {
 		if (!_skyTexture)
-			_skyTexture = _gfx->createTexture(_background->surfacePtr());
+			_skyTexture = _gfx->createTexture(_background->surfacePtr(), true);
 		_gfx->drawSkybox(_skyTexture, _position);
 	}
 }
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 25a14a3527e..19586fd3269 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -79,7 +79,7 @@ public:
 	virtual void depthTesting(bool enabled) {};
 	virtual void polygonOffset(bool enabled) = 0;
 
-	virtual Texture *createTexture(const Graphics::Surface *surface) = 0;
+	virtual Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) = 0;
 	Graphics::Surface *convertImageFormatIfNecessary(Graphics::ManagedSurface *surface);
 
 	virtual void freeTexture(Texture *texture) = 0;
@@ -172,6 +172,91 @@ public:
 
 	byte *_variableStippleArray;
 
+	float _skyNormals[16][3] = {
+		{ 0.0, 0.0, 1.0 }, //front //0
+		{ 0.0, 0.0, 1.0 },		//1
+		{ 0.0, 0.0, 1.0 },		//2
+		{ 0.0, 0.0, 1.0 },		//3
+		{ 0.0, 0.0, -1.0 }, //back //0
+		{ 0.0, 0.0, -1.0 },		//1
+		{ 0.0, 0.0, -1.0 },		//2
+		{ 0.0, 0.0, -1.0 },		//3
+		{ -1.0, 0.0, 0.0 }, //left
+		{ -1.0, 0.0, 0.0 },
+		{ -1.0, 0.0, 0.0 },
+		{ -1.0, 0.0, 0.0 },
+		{ 1.0, 0.0, 0.0 }, //right
+		{ 1.0, 0.0, 0.0 },
+		{ 1.0, 0.0, 0.0 },
+		{ 1.0, 0.0, 0.0 }
+	};
+
+	float _skyUvs1008[16][2] = {
+		{ 0.0f, 0.0f }, //1
+		{ 0.0f, 2.0f }, //2
+		{ 0.4f, 2.0f }, //3
+		{ 0.4f, 0.0f }, //front //4
+
+		{ 0.0f, 2.0f }, //back //1
+		{ 0.4f, 2.0f }, //2
+		{ 0.4f, 0.0f }, //3
+		{ 0.0f, 0.0f }, //4
+
+		{ 0.0f, 0.0f }, //left //1
+		{ 0.4f, 0.0f }, //2
+		{ 0.4f, 2.0f }, //3
+		{ 0.0f, 2.0f }, //4
+
+		{ 0.4f, 0.0f }, //right //1
+		{ 0.0f, 0.0f }, //2
+		{ 0.0f, 2.0f }, //3
+		{ 0.4f, 2.0f }, //4
+	};
+
+	float _skyUvs128[16][2] = {
+		{ 0.0f, 0.0f }, //1
+		{ 0.0f, 2.0f }, //2
+		{ 2.5f, 2.0f }, //3
+		{ 2.5f, 0.0f }, //front //4
+
+		{ 0.0f, 2.0f }, //back //1
+		{ 2.5f, 2.0f }, //2
+		{ 2.5f, 0.0f }, //3
+		{ 0.0f, 0.0f }, //4
+
+		{ 0.0f, 0.0f }, //left //1
+		{ 2.5f, 0.0f }, //2
+		{ 2.5f, 2.0f }, //3
+		{ 0.0f, 2.0f }, //4
+
+		{ 2.5f, 0.0f }, //right //1
+		{ 0.0f, 0.0f }, //2
+		{ 0.0f, 2.0f }, //3
+		{ 2.5f, 2.0f }, //4
+	};
+
+	float _skyVertices[16][3] = {
+		{ -81280.0, 8128.0, 81280.0 },          //1     // Vertex #0 front
+		{ -81280.0, -8128.0, 81280.0 }, //2     // Vertex #1
+		{ 81280.0,  -8128.0, 81280.0 }, //3     // Vertex #2
+		{ 81280.0,  8128.0, 81280.0 },          //4     // Vertex #3
+
+		{ 81280.0f, -8128.0f, -81280.0f }, // 1
+		{ -81280.0f, -8128.0f, -81280.0f }, // 2
+		{ -81280.0f, 8128.0f, -81280.0f }, // 3
+		{ 81280.0f, 8128.0f, -81280.0f }, // 4
+
+		{ -81280.0f,  8128.0f,  81280.0f }, //left //1
+		{ -81280.0f,  8128.0f, -81280.0f }, //2
+		{ -81280.0f, -8128.0f, -81280.0f }, //3
+		{ -81280.0f, -8128.0f,  81280.0f }, //4
+
+		{ 81280.0f,  8128.0f, -81280.0f }, //right //1
+		{ 81280.0f,  8128.0f,  81280.0f }, //2
+		{ 81280.0f, -8128.0f,  81280.0f },//3
+		{ 81280.0f, -8128.0f, -81280.0f },//4
+	};
+
 	byte *_palette;
 	void setColorMap(ColorMap *colorMap_);
 	ColorMap *_colorMap;
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 148728925ec..c518c89c3bd 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -51,7 +51,7 @@ OpenGLRenderer::~OpenGLRenderer() {
 	free(_coords);
 }
 
-Texture *OpenGLRenderer::createTexture(const Graphics::Surface *surface) {
+Texture *OpenGLRenderer::createTexture(const Graphics::Surface *surface, bool is3D) {
 	return new OpenGLTexture(surface);
 }
 
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index 43d8c1c30b8..5ed5a02326f 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -76,7 +76,7 @@ public:
 	virtual void depthTesting(bool enabled) override;
 
 
-	Texture *createTexture(const Graphics::Surface *surface) override;
+	Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) override;
 	void freeTexture(Texture *texture) override;
 	virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) override;
 
@@ -93,90 +93,6 @@ public:
 	void drawSkybox(Texture *texture, Math::Vector3d camera) override;
 
 	virtual Graphics::Surface *getScreenshot() override;
-	GLfloat _skyNormals[16][3] = {
-		{ 0.0, 0.0, 1.0 }, //front //0
-		{ 0.0, 0.0, 1.0 },		//1
-		{ 0.0, 0.0, 1.0 },		//2
-		{ 0.0, 0.0, 1.0 },		//3
-		{ 0.0, 0.0, -1.0 }, //back //0
-		{ 0.0, 0.0, -1.0 },		//1
-		{ 0.0, 0.0, -1.0 },		//2
-		{ 0.0, 0.0, -1.0 },		//3
-		{ -1.0, 0.0, 0.0 }, //left
-		{ -1.0, 0.0, 0.0 },
-		{ -1.0, 0.0, 0.0 },
-		{ -1.0, 0.0, 0.0 },
-		{ 1.0, 0.0, 0.0 }, //right
-		{ 1.0, 0.0, 0.0 },
-		{ 1.0, 0.0, 0.0 },
-		{ 1.0, 0.0, 0.0 }
-	};
-
-	GLfloat _skyUvs1008[16][2] = {
-		{ 0.0f, 0.0f }, //1
-		{ 0.0f, 2.0f }, //2
-		{ 0.4f, 2.0f }, //3
-		{ 0.4f, 0.0f }, //front //4
-
-		{ 0.0f, 2.0f }, //back //1
-		{ 0.4f, 2.0f }, //2
-		{ 0.4f, 0.0f }, //3
-		{ 0.0f, 0.0f }, //4
-
-		{ 0.0f, 0.0f }, //left //1
-		{ 0.4f, 0.0f }, //2
-		{ 0.4f, 2.0f }, //3
-		{ 0.0f, 2.0f }, //4
-
-		{ 0.4f, 0.0f }, //right //1
-		{ 0.0f, 0.0f }, //2
-		{ 0.0f, 2.0f }, //3
-		{ 0.4f, 2.0f }, //4
-	};
-
-	GLfloat _skyUvs128[16][2] = {
-		{ 0.0f, 0.0f }, //1
-		{ 0.0f, 2.0f }, //2
-		{ 2.5f, 2.0f }, //3
-		{ 2.5f, 0.0f }, //front //4
-
-		{ 0.0f, 2.0f }, //back //1
-		{ 2.5f, 2.0f }, //2
-		{ 2.5f, 0.0f }, //3
-		{ 0.0f, 0.0f }, //4
-
-		{ 0.0f, 0.0f }, //left //1
-		{ 2.5f, 0.0f }, //2
-		{ 2.5f, 2.0f }, //3
-		{ 0.0f, 2.0f }, //4
-
-		{ 2.5f, 0.0f }, //right //1
-		{ 0.0f, 0.0f }, //2
-		{ 0.0f, 2.0f }, //3
-		{ 2.5f, 2.0f }, //4
-	};
-
-	GLfloat _skyVertices[16][3] = {
-		{ -81280.0, 8128.0, 81280.0 },		//1	// Vertex #0 front
-		{ -81280.0, -8128.0, 81280.0 },	//2	// Vertex #1
-		{ 81280.0,  -8128.0, 81280.0 },	//3	// Vertex #2
-		{ 81280.0,  8128.0, 81280.0 },		//4	// Vertex #3
-
-		{ 81280.0f, -8128.0f, -81280.0f }, // 1
-		{ -81280.0f, -8128.0f, -81280.0f }, // 2
-		{ -81280.0f, 8128.0f, -81280.0f }, // 3
-		{ 81280.0f, 8128.0f, -81280.0f }, // 4
-
-		{ -81280.0f,  8128.0f,  81280.0f }, //left //1
-		{ -81280.0f,  8128.0f, -81280.0f }, //2
-		{ -81280.0f, -8128.0f, -81280.0f }, //3
-		{ -81280.0f, -8128.0f,  81280.0f }, //4
-
-		{ 81280.0f,  8128.0f, -81280.0f }, //right //1
-		{ 81280.0f,  8128.0f,  81280.0f }, //2
-		{ 81280.0f, -8128.0f,  81280.0f },//3
-		{ 81280.0f, -8128.0f, -81280.0f },//4
-	};
 };
 
 } // End of namespace Freescape
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 7ff7e38df9d..f1898754188 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -64,7 +64,7 @@ OpenGLShaderRenderer::~OpenGLShaderRenderer() {
 	free(_verts);
 }
 
-Texture *OpenGLShaderRenderer::createTexture(const Graphics::Surface *surface) {
+Texture *OpenGLShaderRenderer::createTexture(const Graphics::Surface *surface, bool is3D) {
 	return new OpenGLTexture(surface);
 }
 
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
index 33211f60392..d5d258cae7b 100644
--- a/engines/freescape/gfx_opengl_shaders.h
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -78,7 +78,7 @@ public:
 	virtual void setStippleData(byte *data) override;
 	virtual void useStipple(bool enabled) override;
 
-	Texture *createTexture(const Graphics::Surface *surface) override;
+	Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) override;
 	void freeTexture(Texture *texture) override;
 	virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) override;
 
diff --git a/engines/freescape/gfx_opengl_texture.cpp b/engines/freescape/gfx_opengl_texture.cpp
index e9db5c3cd4a..bc68440908e 100644
--- a/engines/freescape/gfx_opengl_texture.cpp
+++ b/engines/freescape/gfx_opengl_texture.cpp
@@ -110,18 +110,7 @@ void OpenGLTexture::updateTexture(const Graphics::Surface *surface, const Common
 	assert(surface->format == _format);
 
 	glBindTexture(GL_TEXTURE_2D, _id);
-
-	if (OpenGLContext.unpackSubImageSupported) {
-		const Graphics::Surface subArea = surface->getSubArea(rect);
-
-		glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format.bytesPerPixel);
-
-		glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, subArea.w, subArea.h, _internalFormat, _sourceFormat, const_cast<void *>(subArea.getPixels()));
-		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-	} else {
-		// GL_UNPACK_ROW_LENGTH is not supported, don't bother and do a full texture update
-		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface->w, surface->h, _internalFormat, _sourceFormat, const_cast<void *>(surface->getPixels()));
-	}
+	glTexImage2D(GL_TEXTURE_2D, 0, _internalFormat, surface->w, surface->h, 0, _internalFormat, _sourceFormat, const_cast<void *>(surface->getPixels()));
 }
 
 void OpenGLTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) {
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index c1317a905fb..c7a71f642be 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -39,7 +39,7 @@ Renderer *CreateGfxTinyGL(int screenW, int screenH, Common::RenderMode renderMod
 
 TinyGLRenderer::TinyGLRenderer(int screenW, int screenH, Common::RenderMode renderMode) : Renderer(screenW, screenH, renderMode, true) {
 	_verts = (Vertex *)malloc(sizeof(Vertex) * kVertexArraySize);
-	_texturePixelFormat = TinyGLTexture::getRGBAPixelFormat();
+	_texturePixelFormat = TinyGL2DTexture::getRGBAPixelFormat();
 	_variableStippleArray = nullptr;
 }
 
@@ -48,13 +48,16 @@ TinyGLRenderer::~TinyGLRenderer() {
 	free(_verts);
 }
 
-Texture *TinyGLRenderer::createTexture(const Graphics::Surface *surface) {
-	return new TinyGLTexture(surface);
+Texture *TinyGLRenderer::createTexture(const Graphics::Surface *surface, bool is3D) {
+	if (is3D)
+		return new TinyGL3DTexture(surface);
+	else
+		return new TinyGL2DTexture(surface);
 }
 
 void TinyGLRenderer::freeTexture(Texture *texture) {
-	TinyGLTexture *glTexture = static_cast<TinyGLTexture *>(texture);
-	delete glTexture;
+	//TinyGLTexture *glTexture = static_cast<TinyGLTexture *>(texture);
+	delete texture;
 }
 
 void TinyGLRenderer::init() {
@@ -92,7 +95,47 @@ void TinyGLRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Co
 
 	TinyGL::BlitTransform transform(sLeft + viewPort[0], sTop + viewPort[1]);
 	transform.sourceRectangle(textureRect.left, textureRect.top, sWidth, sHeight);
-	tglBlit(((TinyGLTexture *)texture)->getBlitTexture(), transform);
+	tglBlit(((TinyGL2DTexture *)texture)->getBlitTexture(), transform);
+}
+
+void TinyGLRenderer::drawSkybox(Texture *texture, Math::Vector3d camera) {
+	TinyGL3DTexture *glTexture = static_cast<TinyGL3DTexture *>(texture);
+	tglDisable(TGL_DEPTH_TEST);
+	tglEnable(TGL_TEXTURE_2D);
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_REPEAT);
+
+	tglBindTexture(TGL_TEXTURE_2D, glTexture->_id);
+	tglColor4f(1.f, 1.f, 1.f, 1.f);
+	tglVertexPointer(3, TGL_FLOAT, 0, _skyVertices);
+	tglNormalPointer(TGL_FLOAT, 0, _skyNormals);
+	if (texture->_width == 1008)
+		tglTexCoordPointer(2, TGL_FLOAT, 0, _skyUvs1008);
+	else if (texture->_width == 128)
+		tglTexCoordPointer(2, TGL_FLOAT, 0, _skyUvs128);
+	else
+		error("Unsupported skybox texture width %d", glTexture->_width);
+
+	tglEnableClientState(TGL_VERTEX_ARRAY);
+	tglEnableClientState(TGL_TEXTURE_COORD_ARRAY);
+	tglEnableClientState(TGL_NORMAL_ARRAY);
+
+	tglPolygonMode(TGL_BACK, TGL_FILL);
+
+	tglPushMatrix();
+	{
+		tglTranslatef(camera.x(), camera.y(), camera.z());
+		tglDrawArrays(TGL_QUADS, 0, 16);
+	}
+	tglPopMatrix();
+
+	tglDisableClientState(TGL_NORMAL_ARRAY);
+	tglDisableClientState(TGL_TEXTURE_COORD_ARRAY);
+	tglDisableClientState(TGL_VERTEX_ARRAY);
+
+	tglBindTexture(TGL_TEXTURE_2D, 0);
+	tglDisable(TGL_TEXTURE_2D);
+	tglEnable(TGL_DEPTH_TEST);
+	tglFlush();
 }
 
 void TinyGLRenderer::updateProjectionMatrix(float fov, float aspectRatio, float nearClipPlane, float farClipPlane) {
@@ -499,7 +542,7 @@ Graphics::Surface *TinyGLRenderer::getScreenshot() {
 	TinyGL::getSurfaceRef(glBuffer);
 
 	Graphics::Surface *s = new Graphics::Surface();
-	s->create(_screenW, _screenH, TinyGLTexture::getRGBAPixelFormat());
+	s->create(_screenW, _screenH, TinyGL2DTexture::getRGBAPixelFormat());
 	s->copyFrom(glBuffer);
 
 	return s;
diff --git a/engines/freescape/gfx_tinygl.h b/engines/freescape/gfx_tinygl.h
index 7a97f6776c2..5174c1e9749 100644
--- a/engines/freescape/gfx_tinygl.h
+++ b/engines/freescape/gfx_tinygl.h
@@ -60,9 +60,10 @@ public:
 
 	TGLubyte *_variableStippleArray;
 
-	Texture *createTexture(const Graphics::Surface *surface) override;
+	Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) override;
 	void freeTexture(Texture *texture) override;
 	virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) override;
+	void drawSkybox(Texture *texture, Math::Vector3d camera) override;
 
 	virtual void renderSensorShoot(byte color, const Math::Vector3d sensor, const Math::Vector3d player, const Common::Rect viewPort) override;
 	virtual void renderPlayerShootBall(byte color, const Common::Point position, int frame, const Common::Rect viewPort) override;
diff --git a/engines/freescape/gfx_tinygl_texture.cpp b/engines/freescape/gfx_tinygl_texture.cpp
index 887a386afb7..01c150728cb 100644
--- a/engines/freescape/gfx_tinygl_texture.cpp
+++ b/engines/freescape/gfx_tinygl_texture.cpp
@@ -25,11 +25,11 @@
 
 namespace Freescape {
 
-const Graphics::PixelFormat TinyGLTexture::getRGBAPixelFormat() {
+const Graphics::PixelFormat TinyGL2DTexture::getRGBAPixelFormat() {
 	return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
 }
 
-TinyGLTexture::TinyGLTexture(const Graphics::Surface *surface) {
+TinyGL2DTexture::TinyGL2DTexture(const Graphics::Surface *surface) {
 	_width = surface->w;
 	_height = surface->h;
 	_format = surface->format;
@@ -41,22 +41,72 @@ TinyGLTexture::TinyGLTexture(const Graphics::Surface *surface) {
 	update(surface);
 }
 
-TinyGLTexture::~TinyGLTexture() {
+TinyGL2DTexture::~TinyGL2DTexture() {
 	tglDeleteBlitImage(_blitImage);
 }
 
-void TinyGLTexture::update(const Graphics::Surface *surface) {
+void TinyGL2DTexture::update(const Graphics::Surface *surface) {
 	uint32 keyColor = getRGBAPixelFormat().RGBToColor(0xA0, 0xA0, 0xA0);
 	tglUploadBlitImage(_blitImage, *surface, keyColor, true);
 }
 
-void TinyGLTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) {
+void TinyGL2DTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) {
 	// FIXME: TinyGL does not support partial texture update
 	update(surface);
 }
 
-TinyGL::BlitImage *TinyGLTexture::getBlitTexture() const {
+TinyGL::BlitImage *TinyGL2DTexture::getBlitTexture() const {
 	return _blitImage;
 }
 
+const Graphics::PixelFormat TinyGL3DTexture::getRGBAPixelFormat() {
+	return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+}
+
+TinyGL3DTexture::TinyGL3DTexture(const Graphics::Surface *surface) {
+	_width = surface->w;
+	_height = surface->h;
+	_format = surface->format;
+	_upsideDown = false;
+
+	if (_format.bytesPerPixel == 4) {
+		assert(surface->format == getRGBAPixelFormat());
+		_format = surface->format;
+		_internalFormat = TGL_RGBA;
+		_sourceFormat = TGL_UNSIGNED_BYTE;
+	} else if (_format.bytesPerPixel == 2) {
+		_internalFormat = TGL_RGB;
+		_sourceFormat = TGL_UNSIGNED_SHORT_5_6_5;
+	} else
+		error("Unknown pixel format");
+
+
+	tglGenTextures(1, &_id);
+	tglBindTexture(TGL_TEXTURE_2D, _id);
+	tglTexImage2D(TGL_TEXTURE_2D, 0, _internalFormat, _width, _height, 0, _internalFormat, _sourceFormat, nullptr);
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
+
+	// NOTE: TinyGL doesn't have issues with white lines so doesn't need use TGL_CLAMP_TO_EDGE
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_CLAMP_TO_EDGE);
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_CLAMP_TO_EDGE);
+	update(surface);
+}
+
+TinyGL3DTexture::~TinyGL3DTexture() {
+	tglDeleteTextures(1, &_id);
+}
+
+void TinyGL3DTexture::update(const Graphics::Surface *surface) {
+	assert(surface->format == _format);
+
+	tglBindTexture(TGL_TEXTURE_2D, _id);
+	tglTexImage2D(TGL_TEXTURE_2D, 0, _internalFormat, surface->w, surface->h, 0, _internalFormat, _sourceFormat, const_cast<void *>(surface->getPixels()));
+}
+
+void TinyGL3DTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) {
+	// FIXME: TinyGL does not support partial texture update
+	update(surface);
+}
+
 } // End of namespace Freescape
diff --git a/engines/freescape/gfx_tinygl_texture.h b/engines/freescape/gfx_tinygl_texture.h
index 5dbedf40f8d..c2ce33845ec 100644
--- a/engines/freescape/gfx_tinygl_texture.h
+++ b/engines/freescape/gfx_tinygl_texture.h
@@ -28,10 +28,10 @@
 
 namespace Freescape {
 
-class TinyGLTexture : public Texture {
+class TinyGL2DTexture : public Texture {
 public:
-	TinyGLTexture(const Graphics::Surface *surface);
-	virtual ~TinyGLTexture();
+	TinyGL2DTexture(const Graphics::Surface *surface);
+	virtual ~TinyGL2DTexture();
 
 	const static Graphics::PixelFormat getRGBAPixelFormat();
 
@@ -47,6 +47,25 @@ private:
 	TinyGL::BlitImage *_blitImage;
 };
 
+
+class TinyGL3DTexture : public Texture {
+public:
+	TinyGL3DTexture(const Graphics::Surface *surface);
+	virtual ~TinyGL3DTexture();
+
+	const static Graphics::PixelFormat getRGBAPixelFormat();
+
+	void update(const Graphics::Surface *surface) override;
+	void updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) override;
+
+	TGLuint _id;
+	TGLuint _internalFormat;
+	TGLuint _sourceFormat;
+	uint32 _internalWidth;
+	uint32 _internalHeight;
+	bool _upsideDown;
+};
+
 } // End of namespace Freescape
 
 #endif // FREESCAPE_GFX_TINYGL_TEXTURE_H


Commit: 4ceba8c1f8c808ac1efcb5c3efb9d2488ec648d3
    https://github.com/scummvm/scummvm/commit/4ceba8c1f8c808ac1efcb5c3efb9d2488ec648d3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-11-23T09:01:43+01:00

Commit Message:
FREESCAPE: refactored and unified getRGBAPixelFormat across all the codebase

Changed paths:
    engines/freescape/gfx.cpp
    engines/freescape/gfx.h
    engines/freescape/gfx_opengl.cpp
    engines/freescape/gfx_opengl_shaders.cpp
    engines/freescape/gfx_opengl_texture.cpp
    engines/freescape/gfx_opengl_texture.h
    engines/freescape/gfx_tinygl.cpp
    engines/freescape/gfx_tinygl_texture.cpp
    engines/freescape/gfx_tinygl_texture.h


diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index e4a0c6614a9..3ddf77aeaa6 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -34,6 +34,14 @@
 
 namespace Freescape {
 
+const Graphics::PixelFormat getRGBAPixelFormat() {
+#ifdef SCUMM_BIG_ENDIAN
+		return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+#else
+		return Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
+#endif
+}
+
 Renderer::Renderer(int screenW, int screenH, Common::RenderMode renderMode, bool authenticGraphics) {
 	_screenW = screenW;
 	_screenH = screenH;
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 19586fd3269..24506afd9d9 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -42,6 +42,8 @@ typedef Common::HashMap<int, int> ColorReMap;
 
 class Renderer;
 
+const Graphics::PixelFormat getRGBAPixelFormat();
+
 class Texture {
 public:
 	Texture(){ _width = 0; _height = 0; };
@@ -53,8 +55,6 @@ public:
 
 	virtual void update(const Graphics::Surface *surface) = 0;
 	virtual void updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) = 0;
-
-	static const Graphics::PixelFormat getRGBAPixelFormat();
 };
 
 class Renderer {
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index c518c89c3bd..eb51a158d07 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -41,7 +41,7 @@ Renderer *CreateGfxOpenGL(int screenW, int screenH, Common::RenderMode renderMod
 OpenGLRenderer::OpenGLRenderer(int screenW, int screenH, Common::RenderMode renderMode, bool authenticGraphics) : Renderer(screenW, screenH, renderMode, authenticGraphics) {
 	_verts = (Vertex *)malloc(sizeof(Vertex) * kVertexArraySize);
 	_coords = (Coord *)malloc(sizeof(Coord) * kCoordsArraySize);
-	_texturePixelFormat = OpenGLTexture::getRGBAPixelFormat();
+	_texturePixelFormat = getRGBAPixelFormat();
 	_isAccelerated = true;
 	_variableStippleArray = nullptr;
 }
@@ -563,7 +563,7 @@ void OpenGLRenderer::flipBuffer() {}
 Graphics::Surface *OpenGLRenderer::getScreenshot() {
 	Common::Rect screen = viewport();
 	Graphics::Surface *s = new Graphics::Surface();
-	s->create(screen.width(), screen.height(), OpenGLTexture::getRGBAPixelFormat());
+	s->create(screen.width(), screen.height(), getRGBAPixelFormat());
 	glReadPixels(screen.left, screen.top, screen.width(), screen.height(), GL_RGBA, GL_UNSIGNED_BYTE, s->getPixels());
 	flipVertical(s);
 	return s;
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index f1898754188..9569c6ff1d3 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -52,7 +52,7 @@ OpenGLShaderRenderer::OpenGLShaderRenderer(int screenW, int screenH, Common::Ren
 	_bitmapShader = nullptr;
 	_bitmapVBO = 0;
 
-	_texturePixelFormat = OpenGLTexture::getRGBAPixelFormat();
+	_texturePixelFormat = getRGBAPixelFormat();
 	_isAccelerated = true;
 }
 
@@ -519,7 +519,7 @@ void OpenGLShaderRenderer::flipBuffer() {}
 Graphics::Surface *OpenGLShaderRenderer::getScreenshot() {
 	Common::Rect screen = viewport();
 	Graphics::Surface *s = new Graphics::Surface();
-	s->create(screen.width(), screen.height(), OpenGLTexture::getRGBAPixelFormat());
+	s->create(screen.width(), screen.height(), getRGBAPixelFormat());
 	glReadPixels(screen.left, screen.top, screen.width(), screen.height(), GL_RGBA, GL_UNSIGNED_BYTE, s->getPixels());
 	flipVertical(s);
 	return s;
diff --git a/engines/freescape/gfx_opengl_texture.cpp b/engines/freescape/gfx_opengl_texture.cpp
index bc68440908e..bcbd1a6c054 100644
--- a/engines/freescape/gfx_opengl_texture.cpp
+++ b/engines/freescape/gfx_opengl_texture.cpp
@@ -41,14 +41,6 @@ static uint32 upperPowerOfTwo(uint32 v) {
 	return v;
 }
 
-const Graphics::PixelFormat OpenGLTexture::getRGBAPixelFormat() {
-#ifdef SCUMM_BIG_ENDIAN
-		return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-#else
-		return Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
-#endif
-}
-
 OpenGLTexture::OpenGLTexture() :
 		_internalFormat(0),
 		_sourceFormat(0),
diff --git a/engines/freescape/gfx_opengl_texture.h b/engines/freescape/gfx_opengl_texture.h
index cd3f3b073ee..31d8c3592f2 100644
--- a/engines/freescape/gfx_opengl_texture.h
+++ b/engines/freescape/gfx_opengl_texture.h
@@ -35,8 +35,6 @@ public:
 	OpenGLTexture();
 	virtual ~OpenGLTexture();
 
-	const static Graphics::PixelFormat getRGBAPixelFormat();
-
 	void update(const Graphics::Surface *surface) override;
 	void updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) override;
 
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index c7a71f642be..cd5a72db205 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -39,7 +39,7 @@ Renderer *CreateGfxTinyGL(int screenW, int screenH, Common::RenderMode renderMod
 
 TinyGLRenderer::TinyGLRenderer(int screenW, int screenH, Common::RenderMode renderMode) : Renderer(screenW, screenH, renderMode, true) {
 	_verts = (Vertex *)malloc(sizeof(Vertex) * kVertexArraySize);
-	_texturePixelFormat = TinyGL2DTexture::getRGBAPixelFormat();
+	_texturePixelFormat = getRGBAPixelFormat();
 	_variableStippleArray = nullptr;
 }
 
@@ -542,7 +542,7 @@ Graphics::Surface *TinyGLRenderer::getScreenshot() {
 	TinyGL::getSurfaceRef(glBuffer);
 
 	Graphics::Surface *s = new Graphics::Surface();
-	s->create(_screenW, _screenH, TinyGL2DTexture::getRGBAPixelFormat());
+	s->create(_screenW, _screenH, getRGBAPixelFormat());
 	s->copyFrom(glBuffer);
 
 	return s;
diff --git a/engines/freescape/gfx_tinygl_texture.cpp b/engines/freescape/gfx_tinygl_texture.cpp
index 01c150728cb..ca71310113c 100644
--- a/engines/freescape/gfx_tinygl_texture.cpp
+++ b/engines/freescape/gfx_tinygl_texture.cpp
@@ -25,10 +25,6 @@
 
 namespace Freescape {
 
-const Graphics::PixelFormat TinyGL2DTexture::getRGBAPixelFormat() {
-	return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-}
-
 TinyGL2DTexture::TinyGL2DTexture(const Graphics::Surface *surface) {
 	_width = surface->w;
 	_height = surface->h;
@@ -59,10 +55,6 @@ TinyGL::BlitImage *TinyGL2DTexture::getBlitTexture() const {
 	return _blitImage;
 }
 
-const Graphics::PixelFormat TinyGL3DTexture::getRGBAPixelFormat() {
-	return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-}
-
 TinyGL3DTexture::TinyGL3DTexture(const Graphics::Surface *surface) {
 	_width = surface->w;
 	_height = surface->h;
diff --git a/engines/freescape/gfx_tinygl_texture.h b/engines/freescape/gfx_tinygl_texture.h
index c2ce33845ec..5832e8d7199 100644
--- a/engines/freescape/gfx_tinygl_texture.h
+++ b/engines/freescape/gfx_tinygl_texture.h
@@ -33,8 +33,6 @@ public:
 	TinyGL2DTexture(const Graphics::Surface *surface);
 	virtual ~TinyGL2DTexture();
 
-	const static Graphics::PixelFormat getRGBAPixelFormat();
-
 	TinyGL::BlitImage *getBlitTexture() const;
 
 	void update(const Graphics::Surface *surface) override;
@@ -53,8 +51,6 @@ public:
 	TinyGL3DTexture(const Graphics::Surface *surface);
 	virtual ~TinyGL3DTexture();
 
-	const static Graphics::PixelFormat getRGBAPixelFormat();
-
 	void update(const Graphics::Surface *surface) override;
 	void updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) override;
 


Commit: 6a88a4c06827659d49364b645a1929e785370619
    https://github.com/scummvm/scummvm/commit/6a88a4c06827659d49364b645a1929e785370619
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-11-23T09:01:43+01:00

Commit Message:
FREESCAPE: first attempt to implement stipple patterns in TinyGL using textures

Changed paths:
    engines/freescape/gfx.cpp
    engines/freescape/gfx_tinygl.cpp
    engines/freescape/gfx_tinygl.h
    engines/freescape/gfx_tinygl_texture.cpp
    engines/freescape/gfx_tinygl_texture.h


diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 3ddf77aeaa6..3001eb80550 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -282,6 +282,7 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 
 	assert (_renderMode == Common::kRenderCGA);
 	if (index <= 4) { // Solid colors
+		stipple = nullptr;
 		readFromPalette(index - 1, r1, g1, b1);
 		r2 = r1;
 		g2 = g1;
@@ -295,6 +296,9 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	byte c2 = (pair >> 4) & 0xf;
 	readFromPalette(c1, r1, g1, b1);
 	readFromPalette(c2, r2, g2, b2);
+	if (r1 == r2 && g1 == g2 && b1 == b2) {
+		stipple = nullptr;
+	}
 	return true;
 }
 
@@ -372,12 +376,14 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
 	if (entry[0] == 0 && entry[1] == 0 && entry[2] == 0 && entry[3] == 0) {
 		readFromPalette(_paperColor, r1, g1, b1);
 		readFromPalette(_paperColor, r2, g2, b2);
+		stipple = nullptr;
 		return true;
 	}
 
 	if (entry[0] == 0xff && entry[1] == 0xff && entry[2] == 0xff && entry[3] == 0xff) {
 		readFromPalette(_inkColor, r1, g1, b1);
 		readFromPalette(_inkColor, r2, g2, b2);
+		stipple = nullptr;
 		return true;
 	}
 
@@ -385,6 +391,9 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
 
 	readFromPalette(_paperColor, r1, g1, b1);
 	readFromPalette(_inkColor, r2, g2, b2);
+	if (r1 == r2 && g1 == g2 && b1 == g2) {
+		stipple = nullptr;
+	}
 	return true;
 }
 
@@ -438,12 +447,14 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 			r2 = r1;
 			g2 = g1;
 			b2 = b1;
+			stipple = nullptr;
 			return true;
 		}
 		readFromPalette(index, r1, g1, b1);
 		r2 = r1;
 		g2 = g1;
 		b2 = b1;
+		stipple = nullptr;
 		return true;
 	}
 
@@ -453,6 +464,7 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 		r2 = r1;
 		g2 = g1;
 		b2 = b1;
+		stipple = nullptr;
 		return true;
 	}
 
@@ -462,6 +474,9 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
 	uint8 i2 = getCPCPixel(entry[0], 1, true);
 	selectColorFromFourColorPalette(i1, r1, g1, b1);
 	selectColorFromFourColorPalette(i2, r2, g2, b2);
+	if (r1 == r2 && g1 == g2 && b1 == b2) {
+		stipple = nullptr;
+	}
 	return true;
 }
 
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index cd5a72db205..8f1c7ada75e 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -39,13 +39,18 @@ Renderer *CreateGfxTinyGL(int screenW, int screenH, Common::RenderMode renderMod
 
 TinyGLRenderer::TinyGLRenderer(int screenW, int screenH, Common::RenderMode renderMode) : Renderer(screenW, screenH, renderMode, true) {
 	_verts = (Vertex *)malloc(sizeof(Vertex) * kVertexArraySize);
+	_texCoord = (Coord *)malloc(sizeof(Coord) * kVertexArraySize);
 	_texturePixelFormat = getRGBAPixelFormat();
 	_variableStippleArray = nullptr;
 }
 
 TinyGLRenderer::~TinyGLRenderer() {
+	for (auto &it : _stippleTextureCache) {
+		delete (TinyGL3DTexture *)it._value;
+	}
 	TinyGL::destroyContext();
 	free(_verts);
+	free(_texCoord);
 }
 
 Texture *TinyGLRenderer::createTexture(const Graphics::Surface *surface, bool is3D) {
@@ -76,6 +81,10 @@ void TinyGLRenderer::init() {
 	tglDisable(TGL_LIGHTING);
 	tglDisable(TGL_TEXTURE_2D);
 	tglEnable(TGL_DEPTH_TEST);
+	_stippleEnabled = false;
+	_lastColorSet0 = 0;
+	_lastColorSet1 = 0;
+	_stippleTexture = nullptr;
 }
 
 void TinyGLRenderer::setViewport(const Common::Rect &rect) {
@@ -303,31 +312,27 @@ void TinyGLRenderer::renderCrossair(const Common::Point crossairPosition) {
 }
 
 void TinyGLRenderer::setStippleData(byte *data) {
-	if (!data)
+	if (!data) {
+		_stippleTexture = nullptr;
+		assert(_stippleEnabled == false);
+		_variableStippleArray = nullptr;
 		return;
+	}
+	if (_stippleTextureCache.contains(uint64(data))) {
+
+	}
+	assert(_stippleTextureCache.size() <= 16);
 
 	_variableStippleArray = data;
-	//for (int i = 0; i < 128; i++)
-	//	_variableStippleArray[i] = data[(i / 16) % 4];
 }
 
 void TinyGLRenderer::useStipple(bool enabled) {
+	_stippleEnabled = enabled;
+
 	if (enabled) {
-		TGLfloat factor = 0;
-		tglGetFloatv(TGL_POLYGON_OFFSET_FACTOR, &factor);
-		tglEnable(TGL_POLYGON_OFFSET_FILL);
-		tglPolygonOffset(factor - 0.5f, -1.0f);
-		tglEnable(TGL_POLYGON_STIPPLE);
-		if (_renderMode == Common::kRenderZX  ||
-			_renderMode == Common::kRenderCPC ||
-			_renderMode == Common::kRenderCGA)
-			tglPolygonStipple(_variableStippleArray);
-		else
-			tglPolygonStipple(_defaultStippleArraySmall);
+		assert(_variableStippleArray);
 	} else {
-		tglPolygonOffset(0, 0);
-		tglDisable(TGL_POLYGON_OFFSET_FILL);
-		tglDisable(TGL_POLYGON_STIPPLE);
+		_stippleTexture = nullptr;
 	}
 }
 
@@ -349,6 +354,16 @@ void TinyGLRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
 		return;
 	}
 
+	if (_stippleEnabled) {
+		if (_stippleTextureCache.contains(uint64(_variableStippleArray))) {
+			_stippleTexture = _stippleTextureCache[uint64(_variableStippleArray)];
+		} else {
+			_stippleTexture = new TinyGL3DTexture(_variableStippleArray, _lastColorSet0, _lastColorSet1);
+			_stippleTextureCache[uint64(_variableStippleArray)] = _stippleTexture;
+		}
+	} else if (_variableStippleArray)
+		return; // We are in the middle of a stipple rendering operation, so we should skip this face
+
 	tglEnableClientState(TGL_VERTEX_ARRAY);
 	uint vi = 0;
 	for (uint i = 1; i < vertices.size() - 1; i++) { // no underflow since vertices.size() > 2
@@ -360,8 +375,61 @@ void TinyGLRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
 		copyToVertexArray(vi + 2, v2);
 	}
 	tglVertexPointer(3, TGL_FLOAT, 0, _verts);
+
+	if (_stippleEnabled) {
+		tglClear(TGL_STENCIL_BUFFER_BIT);
+		tglEnable(TGL_STENCIL_TEST);
+		tglStencilFunc(TGL_ALWAYS, 1, 0xFF);        // Always pass stencil test
+		tglStencilOp(TGL_KEEP, TGL_KEEP, TGL_REPLACE); // Replace stencil buffer where drawn
+		tglEnable(TGL_DEPTH_TEST);
+		tglDepthMask(TGL_TRUE);
+		tglColorMask(TGL_FALSE, TGL_FALSE, TGL_FALSE, TGL_FALSE);
+	}
+
 	tglDrawArrays(TGL_TRIANGLES, 0, vi + 3);
 	tglDisableClientState(TGL_VERTEX_ARRAY);
+
+	if (_stippleEnabled) {
+		tglColorMask(TGL_TRUE, TGL_TRUE, TGL_TRUE, TGL_TRUE);
+		tglStencilFunc(TGL_EQUAL, 1, 0xFF); // Only render where stencil value is 1
+		tglStencilOp(TGL_KEEP, TGL_KEEP, TGL_KEEP); // Don't change stencil buffer
+
+		tglMatrixMode(TGL_PROJECTION);
+		tglPushMatrix();
+
+		tglLoadIdentity();
+		tglOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); // Orthographic projection
+
+		tglScalef(1, 1, 1);
+		tglMatrixMode(TGL_MODELVIEW);
+		tglPushMatrix();
+		tglLoadIdentity();
+
+		tglEnable(TGL_TEXTURE_2D);
+		tglBindTexture(TGL_TEXTURE_2D, _stippleTexture->_id);
+		tglColor4f(1.f, 1.f, 1.f, 1.f);
+		tglDepthMask(TGL_FALSE);
+
+		tglBegin(TGL_QUADS);
+		tglTexCoord2f(0.0f, 0.0f); tglVertex2f(0.0f, 0.0f);
+		tglTexCoord2f(1.0, 0.0f); tglVertex2f(1.0, 0.0f);
+		tglTexCoord2f(1.0, 1.0); tglVertex2f(1.0, 1.0);
+		tglTexCoord2f(0.0f, 1.0); tglVertex2f(0.0f, 1.0);
+		tglEnd();
+
+		tglDepthMask(TGL_TRUE);
+		tglDisable(TGL_STENCIL_TEST);
+		tglDisable(TGL_TEXTURE_2D);
+		tglDisable(TGL_TEXTURE);
+		tglFlush();
+		tglBindTexture(TGL_TEXTURE_2D, 0);
+
+		tglMatrixMode(TGL_PROJECTION);
+		tglPopMatrix();
+
+		tglMatrixMode(TGL_MODELVIEW);
+		tglPopMatrix();
+	}
 }
 
 void TinyGLRenderer::drawCelestialBody(Math::Vector3d position, float radius, byte color) {
@@ -456,11 +524,13 @@ void TinyGLRenderer::polygonOffset(bool enabled) {
 }
 
 void TinyGLRenderer::useColor(uint8 r, uint8 g, uint8 b) {
+	_lastColorSet1 = _lastColorSet0;
+	_lastColorSet0 = _texturePixelFormat.RGBToColor(r, g, b);
 	tglColor3ub(r, g, b);
 }
 
 void TinyGLRenderer::clear(uint8 r, uint8 g, uint8 b, bool ignoreViewport) {
-	tglClear(TGL_DEPTH_BUFFER_BIT);
+	tglClear(TGL_DEPTH_BUFFER_BIT | TGL_STENCIL_BITS);
 	if (ignoreViewport) {
 		tglClearColor(r / 255., g / 255., b / 255., 1.0);
 		tglClear(TGL_COLOR_BUFFER_BIT);
diff --git a/engines/freescape/gfx_tinygl.h b/engines/freescape/gfx_tinygl.h
index 5174c1e9749..973b1b63282 100644
--- a/engines/freescape/gfx_tinygl.h
+++ b/engines/freescape/gfx_tinygl.h
@@ -23,8 +23,10 @@
 #define FREESCAPE_GFX_TINYGL_H
 
 #include "math/vector3d.h"
+#include "common/hashmap.h"
 
 #include "freescape/gfx.h"
+#include "freescape/gfx_tinygl_texture.h"
 
 namespace Freescape {
 
@@ -39,12 +41,29 @@ public:
 		TGLfloat z;
 	};
 
+	Vertex *_verts;
 	void copyToVertexArray(uint idx, const Math::Vector3d &src) {
 		assert(idx < kVertexArraySize);
 		_verts[idx].x = src.x(); _verts[idx].y = src.y(); _verts[idx].z = src.z();
 	}
 
-	Vertex *_verts;
+	struct Coord {
+		TGLfloat x;
+		TGLfloat y;
+	};
+
+	Coord *_texCoord;
+
+	void copyToTexCoordArray(uint idx, float x, float y) {
+		assert(idx < kVertexArraySize);
+		_texCoord[idx].x = x; _texCoord[idx].y = y;
+	}
+
+	bool _stippleEnabled;
+	TinyGL3DTexture *_stippleTexture;
+	Common::HashMap<uint64, TinyGL3DTexture *> _stippleTextureCache;
+	uint32 _lastColorSet0;
+	uint32 _lastColorSet1;
 
 	virtual void init() override;
 	virtual void clear(uint8 r, uint8 g, uint8 b, bool ignoreViewport = false) override;
@@ -58,8 +77,6 @@ public:
 	virtual void setStippleData(byte *data) override;
 	virtual void useStipple(bool enabled) override;
 
-	TGLubyte *_variableStippleArray;
-
 	Texture *createTexture(const Graphics::Surface *surface, bool is3D = false) override;
 	void freeTexture(Texture *texture) override;
 	virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) override;
diff --git a/engines/freescape/gfx_tinygl_texture.cpp b/engines/freescape/gfx_tinygl_texture.cpp
index ca71310113c..c3ad12c027b 100644
--- a/engines/freescape/gfx_tinygl_texture.cpp
+++ b/engines/freescape/gfx_tinygl_texture.cpp
@@ -55,6 +55,82 @@ TinyGL::BlitImage *TinyGL2DTexture::getBlitTexture() const {
 	return _blitImage;
 }
 
+TinyGL3DTexture::TinyGL3DTexture(byte *stipple, uint32 c1, uint32 c2) {
+	Graphics::Surface *surface = new Graphics::Surface();
+	int width = 32;
+	int height = 32;
+
+	surface->create(width, height, getRGBAPixelFormat());
+	surface->fillRect(Common::Rect(0, 0, width, height), surface->format.RGBToColor(0, 0, 0xFF));
+
+	const int stippleWidth = 32;
+	const int stippleHeight = 32;
+
+
+	for (int y = 0; y < height; ++y) {
+		for (int x = 0; x < width; ++x) {
+
+			// Match OpenGL's stipple bit layout
+			int stippleX = x % stippleWidth; // Bit position in the row
+			int stippleY = y % stippleHeight; // Row index
+
+			int byteIndex = stippleY * 4 + (stippleX / 8); // 4 bytes per row
+			int bitIndex = stippleX % 8;
+
+			byte bitmask = 1 << (7 - bitIndex);
+			bool isForeground = stipple[byteIndex] & bitmask;
+			//debug("stippleX=%d stippleY=%d byteIndex=%d bitIndex=%d stipple[byteIndex]: %x color: %s", stippleX, stippleY, byteIndex, bitIndex, stipple[byteIndex], isForeground ? "X" : " ");
+			surface->setPixel(stippleX, stippleY, isForeground ? c1 : c2);
+		}
+	}
+	//assert(0);
+	Graphics::Surface *texture = new Graphics::Surface();
+	texture->create(320, 200, getRGBAPixelFormat());
+	texture->fillRect(Common::Rect(0, 0, 320, 200), texture->format.RGBToColor(0, 0, 0xFF));
+	//texture->copyRectToSurface(*surface, 0, 0, Common::Rect(0, 0, 32, 32));
+
+	// Replicate the stipple pattern to fill the entire texture
+	for (int x = 0; x < 320; x += width) {
+		for (int y = 0; y < 200; y += height) {
+			if (x + width >= 320 || y + height >= 200) {
+				texture->copyRectToSurface(*surface, x, y, Common::Rect(0, 0, MIN(width, 320 - x), MIN(height, 200 - y)));
+			} else
+				texture->copyRectToSurface(*surface, x, y, Common::Rect(0, 0, width, height));
+		}
+	}
+
+	// This surface is no longer needed
+	surface->free();
+	delete surface;
+
+	_width = texture->w;
+	_height = texture->h;
+	_format = texture->format;
+	_upsideDown = false;
+
+	if (_format.bytesPerPixel == 4) {
+		assert(texture->format == getRGBAPixelFormat());
+		_format = texture->format;
+		_internalFormat = TGL_RGBA;
+		_sourceFormat = TGL_UNSIGNED_BYTE;
+	} else if (_format.bytesPerPixel == 2) {
+		_internalFormat = TGL_RGB;
+		_sourceFormat = TGL_UNSIGNED_SHORT_5_6_5;
+	} else
+		error("Unknown pixel format");
+
+	tglGenTextures(1, &_id);
+	tglBindTexture(TGL_TEXTURE_2D, _id);
+	tglTexImage2D(TGL_TEXTURE_2D, 0, _internalFormat, _width, _height, 0, _internalFormat, _sourceFormat, nullptr);
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
+	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
+
+	update(texture);
+
+	texture->free();
+	delete texture;
+}
+
 TinyGL3DTexture::TinyGL3DTexture(const Graphics::Surface *surface) {
 	_width = surface->w;
 	_height = surface->h;
@@ -80,8 +156,8 @@ TinyGL3DTexture::TinyGL3DTexture(const Graphics::Surface *surface) {
 	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
 
 	// NOTE: TinyGL doesn't have issues with white lines so doesn't need use TGL_CLAMP_TO_EDGE
-	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_CLAMP_TO_EDGE);
-	tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_CLAMP_TO_EDGE);
+	//tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_CLAMP_TO_EDGE);
+	//tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_CLAMP_TO_EDGE);
 	update(surface);
 }
 
diff --git a/engines/freescape/gfx_tinygl_texture.h b/engines/freescape/gfx_tinygl_texture.h
index 5832e8d7199..7b0d09c6a45 100644
--- a/engines/freescape/gfx_tinygl_texture.h
+++ b/engines/freescape/gfx_tinygl_texture.h
@@ -49,6 +49,7 @@ private:
 class TinyGL3DTexture : public Texture {
 public:
 	TinyGL3DTexture(const Graphics::Surface *surface);
+	TinyGL3DTexture(byte *stipple, uint32 color1, uint32 color2);
 	virtual ~TinyGL3DTexture();
 
 	void update(const Graphics::Surface *surface) override;




More information about the Scummvm-git-logs mailing list