[Scummvm-git-logs] scummvm master -> 99e6b6e09f5883dc7677da8316a6fe22f87166bd

aquadran noreply at scummvm.org
Tue May 20 22:22:01 UTC 2025


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

Summary:
99e6b6e09f WINTERMUTE: Implemented flat shadow for shader renderer


Commit: 99e6b6e09f5883dc7677da8316a6fe22f87166bd
    https://github.com/scummvm/scummvm/commit/99e6b6e09f5883dc7677da8316a6fe22f87166bd
Author: Paweł Kołodziejski (aquadran at gmail.com)
Date: 2025-05-21T00:21:56+02:00

Commit Message:
WINTERMUTE: Implemented flat shadow for shader renderer

Changed paths:
  R engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.fragment
  R engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.vertex
    dists/scummvm.rc
    engines/wintermute/ad/ad_actor_3dx.cpp
    engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp
    engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.h
    engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
    engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
    engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
    engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment
    engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex
    engines/wintermute/base/gfx/opengl/shaders/wme_simple_shadow.vertex
    engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment


diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index c6e2e25cd2a..d9e4f203642 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -102,8 +102,6 @@ shaders/stark_shadow.vertex          FILE    "engines/stark/shaders/stark_shadow
 #if PLUGIN_ENABLED_STATIC(WINTERMUTE)
 shaders/wme_fade.fragment               FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_fade.fragment"
 shaders/wme_fade.vertex                 FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_fade.vertex"
-shaders/wme_flat_shadow_mask.fragment   FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.fragment"
-shaders/wme_flat_shadow_mask.vertex     FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.vertex"
 shaders/wme_flat_shadow_modelx.fragment FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment"
 shaders/wme_flat_shadow_modelx.vertex   FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex"
 shaders/wme_geometry.fragment           FILE    "engines/wintermute/base/gfx/opengl/shaders/wme_geometry.fragment"
diff --git a/engines/wintermute/ad/ad_actor_3dx.cpp b/engines/wintermute/ad/ad_actor_3dx.cpp
index dc16a22a136..5c0780899b5 100644
--- a/engines/wintermute/ad/ad_actor_3dx.cpp
+++ b/engines/wintermute/ad/ad_actor_3dx.cpp
@@ -536,8 +536,8 @@ bool AdActor3DX::displayFlatShadow() {
 	}
 
 	DXVector3 lightPos = DXVector3(_shadowLightPos._x * _scale3D,
-								   _shadowLightPos._y * _scale3D,
-								   _shadowLightPos._z * _scale3D);
+	                               _shadowLightPos._y * _scale3D,
+	                               _shadowLightPos._z * _scale3D);
 
 	_gameRef->_renderer3D->getWorldTransform(&origWorld);
 
diff --git a/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp b/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp
index 49d80448b15..8bc746b8869 100644
--- a/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp
+++ b/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp
@@ -120,6 +120,9 @@ bool BaseRenderOpenGL3DShader::initRenderer(int width, int height, bool windowed
 	_simpleShadowShader->enableVertexAttribute("normal", _simpleShadowVBO, 3, GL_FLOAT, false, sizeof(SimpleShadowVertex), 12);
 	_simpleShadowShader->enableVertexAttribute("texcoord", _simpleShadowVBO, 2, GL_FLOAT, false, sizeof(SimpleShadowVertex), 24);
 
+	static const char *flatShadowAttributes[] = { "position", nullptr };
+	_flatShadowShader = OpenGL::Shader::fromFiles("wme_flat_shadow_modelx", flatShadowAttributes);
+
 	static const char *shadowVolumeAttributes[] = { "position", nullptr };
 	_shadowVolumeShader = OpenGL::Shader::fromFiles("wme_shadow_volume", shadowVolumeAttributes);
 
@@ -303,6 +306,10 @@ bool BaseRenderOpenGL3DShader::setup3D(Camera3D *camera, bool force) {
 	_simpleShadowShader->setUniform1f("alphaRef", _alphaRef);
 	_simpleShadowShader->setUniform("alphaTest", true);
 
+	_flatShadowShader->use();
+	_flatShadowShader->setUniform("viewMatrix", viewMatrix);
+	_flatShadowShader->setUniform("projMatrix", projectionMatrix);
+
 	_shadowVolumeShader->use();
 	_shadowVolumeShader->setUniform("viewMatrix", viewMatrix);
 	_shadowVolumeShader->setUniform("projMatrix", projectionMatrix);
@@ -695,7 +702,7 @@ BaseImage *BaseRenderOpenGL3DShader::takeScreenshot() {
 }
 
 bool BaseRenderOpenGL3DShader::enableShadows() {
-	_gameRef->_supportsRealTimeShadows = false;
+	_gameRef->_supportsRealTimeShadows = true;
 	return true;
 }
 
@@ -962,7 +969,9 @@ bool BaseRenderOpenGL3DShader::setWorldTransform(const DXMatrix &transform) {
 
 	_simpleShadowShader->use();
 	_simpleShadowShader->setUniform("modelMatrix", modelMatrix);
-	_simpleShadowShader->setUniform("normalMatrix", normalMatrix);
+
+	_flatShadowShader->use();
+	_flatShadowShader->setUniform("modelMatrix", modelMatrix);
 
 	_shadowVolumeShader->use();
 	_shadowVolumeShader->setUniform("modelMatrix", modelMatrix);
@@ -1003,7 +1012,7 @@ Mesh3DS *BaseRenderOpenGL3DShader::createMesh3DS() {
 }
 
 XMesh *BaseRenderOpenGL3DShader::createXMesh() {
-	return new XMeshOpenGLShader(_gameRef, _xmodelShader);
+	return new XMeshOpenGLShader(_gameRef, _xmodelShader, _flatShadowShader);
 }
 
 ShadowVolume *BaseRenderOpenGL3DShader::createShadowVolume() {
diff --git a/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.h b/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.h
index 34fc68a3042..d55f127d4fb 100644
--- a/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.h
+++ b/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.h
@@ -184,6 +184,7 @@ private:
 	OpenGL::Shader *_xmodelShader{};
 	OpenGL::Shader *_geometryShader{};
 	OpenGL::Shader *_simpleShadowShader{};
+	OpenGL::Shader *_flatShadowShader{};
 	OpenGL::Shader *_shadowVolumeShader{};
 	OpenGL::Shader *_lineShader{};
 };
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp b/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
index cd606b4cd74..91bcaa62a9e 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
@@ -159,8 +159,7 @@ bool XMeshOpenGL::renderFlatShadowModel(uint32 shadowColor) {
 	if (!_gameRef->_renderer3D->_camera)
 		return false;
 
-	auto fvf = _blendedMesh->getFVF();
-	uint32 vertexSize = DXGetFVFVertexSize(fvf) / sizeof(float);
+	uint32 vertexSize = DXGetFVFVertexSize(_blendedMesh->getFVF()) / sizeof(float);
 	float *vertexData = (float *)_blendedMesh->getVertexBuffer().ptr();
 	if (vertexData == nullptr) {
 		return false;
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
index 28618c3702e..825ec3670cc 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
@@ -43,8 +43,8 @@
 namespace Wintermute {
 
 //////////////////////////////////////////////////////////////////////////
-XMeshOpenGLShader::XMeshOpenGLShader(BaseGame *inGame, OpenGL::Shader *shader) :
-	XMesh(inGame), _shader(shader) {
+XMeshOpenGLShader::XMeshOpenGLShader(BaseGame *inGame, OpenGL::Shader *shader, OpenGL::Shader *flatShadowShader) :
+	XMesh(inGame), _shader(shader), _flatShadowShader(flatShadowShader) {
 	glGenBuffers(1, &_vertexBuffer);
 	glGenBuffers(1, &_indexBuffer);
 }
@@ -170,22 +170,87 @@ bool XMeshOpenGLShader::render(XModel *model) {
 }
 
 bool XMeshOpenGLShader::renderFlatShadowModel(uint32 shadowColor) {
-	float *vertexData = (float *)_blendedMesh->getVertexBuffer().ptr();
+	if (!_blendedMesh)
+		return false;
+
+	// For WME DX, mesh model is not visible, possible it's clipped.
+	// For OpenGL, mesh is visible, skip draw it here instead in core.
+	if (!_gameRef->_renderer3D->_camera)
+		return false;
+
 	uint32 vertexSize = DXGetFVFVertexSize(_blendedMesh->getFVF()) / sizeof(float);
+	float *vertexData = (float *)_blendedMesh->getVertexBuffer().ptr();
 	if (vertexData == nullptr) {
 		return false;
 	}
 
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
+	bool noAttrs = false;
+	auto attrsTable = _blendedMesh->getAttributeTable();
+	uint32 numAttrs = attrsTable->_size;
+	DXAttributeRange *attrs;
+	if (numAttrs == 0) {
+		noAttrs = true;
+		numAttrs = 1;
+		attrs = new DXAttributeRange[numAttrs];
+	} else {
+		attrs = attrsTable->_ptr;
+	}
 
-	_flatShadowShader->enableVertexAttribute("position", _vertexBuffer, 3, GL_FLOAT, false, 4 * vertexSize, 4);
+	if (noAttrs) {
+		attrs[0]._attribId = 0;
+		attrs[0]._vertexStart = attrs[0]._faceStart = 0;
+		attrs[0]._vertexCount = _blendedMesh->getNumVertices();
+		attrs[0]._faceCount = _blendedMesh->getNumFaces();
+	}
+
+	Math::Vector4d color;
+	color.x() = RGBCOLGetR(shadowColor) / 255.0f;
+	color.y() = RGBCOLGetG(shadowColor) / 255.0f;
+	color.z() = RGBCOLGetB(shadowColor) / 255.0f;
+	color.w() = RGBCOLGetA(shadowColor) / 255.0f;
+
+	_flatShadowShader->enableVertexAttribute("position", _vertexBuffer, 3, GL_FLOAT, false, 4 * vertexSize, 0);
 	_flatShadowShader->use(true);
 
-	glDrawElements(GL_TRIANGLES, _blendedMesh->getNumFaces() * 3, GL_UNSIGNED_SHORT, 0);
+	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+	glDepthMask(GL_FALSE);
+
+	glEnable(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 1, (GLuint)~0);
+	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
+
+	for (uint32 i = 0; i < numAttrs; i++) {
+		size_t offsetFace = 4 * attrsTable->_ptr[i]._faceStart * 3;
+		glDrawElements(GL_TRIANGLES, attrsTable->_ptr[i]._faceCount * 3, GL_UNSIGNED_INT, (void *)offsetFace);
+	}
+
+	glStencilFunc(GL_EQUAL, 1, (GLuint)~0);
+	glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
+
+	_flatShadowShader->setUniform("shadowColor", color);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+	glDepthMask(GL_TRUE);
+
+	for (uint32 i = 0; i < numAttrs; i++) {
+		size_t offsetFace = 4 * attrsTable->_ptr[i]._faceStart * 3;
+		glDrawElements(GL_TRIANGLES, attrsTable->_ptr[i]._faceCount * 3, GL_UNSIGNED_INT, (void *)offsetFace);
+	}
 
 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
+	if (noAttrs) {
+		delete[] attrs;
+	}
+
+	glDisable(GL_BLEND);
+	glDisable(GL_STENCIL_TEST);
+
 	return true;
 }
 
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
index 419e062f137..5aa5dfc3d30 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
@@ -41,7 +41,7 @@ namespace Wintermute {
 
 class XMeshOpenGLShader : public XMesh {
 public:
-	XMeshOpenGLShader(BaseGame *inGame, OpenGL::Shader *shader);
+	XMeshOpenGLShader(BaseGame *inGame, OpenGL::Shader *shader, OpenGL::Shader *flatShadowShader);
 	~XMeshOpenGLShader() override;
 
 	bool loadFromXData(const Common::String &filename, XFileData *xobj) override;
@@ -57,7 +57,7 @@ protected:
 	GLuint _indexBuffer;
 
 	OpenGL::Shader *_shader;
-	OpenGL::Shader *_flatShadowShader{};
+	OpenGL::Shader *_flatShadowShader;
 };
 
 } // namespace Wintermute
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.fragment b/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.fragment
deleted file mode 100644
index a55e79ecfec..00000000000
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.fragment
+++ /dev/null
@@ -1,13 +0,0 @@
-in vec3 Texcoord;
-
-uniform sampler2D tex;
-uniform vec4 shadowColor;
-
-OUTPUT
-
-void main() {
-	vec2 projectedTexcoord = Texcoord.xy / Texcoord.z;
-
-	vec4 texColor = texture(tex, projectedTexcoord);
-	outColor = shadowColor * texColor;
-}
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.vertex b/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.vertex
deleted file mode 100644
index e1cc2f8705c..00000000000
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.vertex
+++ /dev/null
@@ -1,22 +0,0 @@
-in vec3 position;
-
-uniform highp mat4 projMatrix;
-uniform highp mat4 viewMatrix;
-uniform highp mat4 worldMatrix;
-
-uniform highp mat4 lightProjMatrix;
-uniform highp mat4 lightViewMatrix;
-
-out vec3 Texcoord;
-
-void main() {
-	vec4 worldCoords = worldMatrix * vec4(position, 1.0);
-
-	vec4 textureCoords = lightProjMatrix * lightViewMatrix * worldCoords;
-
-	Texcoord.x = 0.5 * (textureCoords.x) + 0.5 * textureCoords.w;
-	Texcoord.y = 0.5 * (textureCoords.y) + 0.5 * textureCoords.w;
-	Texcoord.z = textureCoords.w;
-
-	gl_Position = projMatrix * viewMatrix * worldCoords;
-}
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment b/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment
index f480933ea8f..0296908835f 100644
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment
+++ b/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment
@@ -1,7 +1,8 @@
 uniform vec4 shadowColor;
+uniform float alphaRef;
 
 OUTPUT
 
 void main() {
-	outColor = vec4(shadowColor.rgb, 1.0);
+	outColor = shadowColor;
 }
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex b/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex
index 977847e9a94..96172c58f79 100644
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex
+++ b/engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex
@@ -5,6 +5,5 @@ uniform highp mat4 viewMatrix;
 uniform highp mat4 projMatrix;
 
 void main() {
-	vec4 viewCoords = viewMatrix * modelMatrix * vec4(position, 1.0);
-	gl_Position = projMatrix * viewCoords;
+	gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
 }
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_simple_shadow.vertex b/engines/wintermute/base/gfx/opengl/shaders/wme_simple_shadow.vertex
index 12582fd9a1e..15d0496cbe6 100644
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_simple_shadow.vertex
+++ b/engines/wintermute/base/gfx/opengl/shaders/wme_simple_shadow.vertex
@@ -5,7 +5,6 @@ in vec2 texcoord;
 out vec2 Texcoord;
 
 uniform highp mat4 modelMatrix;
-uniform highp mat4 normalMatrix;
 uniform highp mat4 viewMatrix;
 uniform highp mat4 projMatrix;
 
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment b/engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment
index 5f602beebab..cfa69415b02 100644
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment
+++ b/engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment
@@ -8,8 +8,7 @@ uniform UBOOL alphaTest;
 OUTPUT
 
 void main() {
-	vec4 texColor = texture(tex, Texcoord);
-	outColor = Color * texColor;
+	outColor = Color * texture(tex, Texcoord);
 
 	if (UBOOL_TEST(alphaTest) && outColor.a < alphaRef) {
 		discard;




More information about the Scummvm-git-logs mailing list