[Scummvm-git-logs] scummvm master -> c58d648da5ba044e654eb917944c91030d65c06d

aquadran noreply at scummvm.org
Sun Aug 2 20:26:37 UTC 2026


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:
c58d648da5 WINTERMUTE: Added effects shader support for 'Pizza Morgana'


Commit: c58d648da5ba044e654eb917944c91030d65c06d
    https://github.com/scummvm/scummvm/commit/c58d648da5ba044e654eb917944c91030d65c06d
Author: Paweł Kołodziejski (aquadran at gmail.com)
Date: 2026-08-02T22:26:25+02:00

Commit Message:
WINTERMUTE: Added effects shader support for 'Pizza Morgana'

Changed paths:
    engines/wintermute/base/gfx/3deffect_params.h
    engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.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_modelx.fragment
    engines/wintermute/base/gfx/opengl/shaders/wme_modelx.vertex


diff --git a/engines/wintermute/base/gfx/3deffect_params.h b/engines/wintermute/base/gfx/3deffect_params.h
index 33a2fc852de..3487fff6f1e 100644
--- a/engines/wintermute/base/gfx/3deffect_params.h
+++ b/engines/wintermute/base/gfx/3deffect_params.h
@@ -60,6 +60,12 @@ public:
 		void setValue(DXVector4 val);
 
 		const char *getParamName() const { return _paramName; }
+		const ParamType getParamType();
+		const char *getValue() const { return _valString; }
+		void getValue(int &val) { val = _valInt; }
+		void getValue(float &val) { val = _valFloat; }
+		void getValue(bool &val) { val = _valBool; }
+		void getValue(DXVector4 &val) { val = _valVector; }
 
 		bool persist(BasePersistenceManager *persistMgr);
 
@@ -85,9 +91,9 @@ public:
 	void clear();
 	void setParam(const char *paramName, ScValue *val);
 	void setParam(const char *paramName, DXVector4 Val);
+	Effect3DParam *getParamByName(const char *paramName);
 
 private:
-	Effect3DParam *getParamByName(const char *paramName);
 	BaseArray<Effect3DParam *> _params;
 };
 
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 efea67c9e19..bafa4708b7e 100644
--- a/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp
+++ b/engines/wintermute/base/gfx/opengl/base_render_opengl3d_shader.cpp
@@ -352,6 +352,9 @@ bool BaseRenderOpenGL3DShader::setup3D(Camera3D *camera, bool force) {
 	_xmodelShader->setUniform("projMatrix", projectionMatrix);
 	_xmodelShader->setUniform1f("alphaRef", _alphaRef);
 	_xmodelShader->setUniform("alphaTest", true);
+	_xmodelShader->setUniform("effectId", 0);
+	_xmodelShader->setUniform("effectSecondPass", false);
+	_xmodelShader->setUniform("borderWidth", 0);
 
 	_geometryShader->use();
 	_geometryShader->setUniform("viewMatrix", viewMatrix);
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
index 94979cd469d..9333f338850 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
@@ -148,16 +148,23 @@ bool XMeshOpenGLShader::render(XModel *model) {
 			glDisable(GL_TEXTURE_2D);
 		}
 
-		if (mat->getEffect()) {
-			renderEffect(mat);
-		} else {
-			Math::Vector4d diffuse(mat->_material._diffuse._data);
-			_shader->setUniform("diffuse", diffuse);
-			_shader->setUniform("ambient", diffuse);
-		}
+		Math::Vector4d diffuse(mat->_material._diffuse._data);
+		_shader->setUniform("diffuse", diffuse);
+		_shader->setUniform("ambient", diffuse);
+		_shader->setUniform("effectId", 0);
 
+		setupEffect(mat, false);
 		size_t offsetFace = 4 * attrsTable->_ptr[i]._faceStart * 3;
 		glDrawElements(GL_TRIANGLES, attrsTable->_ptr[i]._faceCount * 3, GL_UNSIGNED_INT, (void *)offsetFace);
+		if (setupEffect(mat, true)) {
+			GLboolean stateCullFace;
+			glGetBooleanv(GL_CULL_FACE, &stateCullFace);
+			glDrawElements(GL_TRIANGLES, attrsTable->_ptr[i]._faceCount * 3, GL_UNSIGNED_INT, (void *)offsetFace);
+			if (stateCullFace)
+				glEnable(GL_CULL_FACE);
+			else
+				glDisable(GL_CULL_FACE);
+		}
 	}
 
 	glBindTexture(GL_TEXTURE_2D, 0);
@@ -278,10 +285,49 @@ bool XMeshOpenGLShader::update(FrameNode *parentFrame) {
 	return true;
 }
 
-void XMeshOpenGLShader::renderEffect(Material *material) {
-	Math::Vector4d diffuse(material->_material._diffuse._data);
-	_shader->setUniform("diffuse", diffuse);
-	_shader->setUniform("ambient", diffuse);
+bool XMeshOpenGLShader::setupEffect(Material *material, bool secondPassNeeded) {
+	auto effect = material->getEffect();
+	if (!effect)
+		return false;
+	auto effectId = effect->getEffectHash();
+	switch (effectId) {
+	case 0x589E1D5C: // "actors\\abbey\\MyBorderGlow.fx"
+	case 0x699AF321: // "actors\\watcher\\MyBorderGlow.fx"
+	case 0x1255105D: // "actors\\Jackie\\MyBorderGlow.fx"
+	{
+		_shader->setUniform("effectId", 1);
+		auto params = material->getEffectParams();
+		auto param = params->getParamByName("SceneAmbientLight");
+		DXVector4 ambientColor;
+		param->getValue(ambientColor);
+		Math::Vector4d ambient(ambientColor);
+		float borderWidth;
+		if (effectId == 0x589E1D5C) {
+			borderWidth = 6.0f;
+			ambient = { 1.0, 1.0, 1.0, 1.0 };
+		}
+		if (effectId == 0x699AF321)
+			borderWidth = 10.0f;
+		if (effectId == 0x1255105D)
+			borderWidth = 8.0f;
+		_shader->setUniform("ambient", ambient);
+		_shader->setUniform1f("borderWidth", borderWidth);
+		_shader->setUniform("effectSecondPass", secondPassNeeded);
+		if (secondPassNeeded) {
+			glCullFace(GL_BACK);
+			glDisable(GL_CULL_FACE);
+			glDepthMask(GL_TRUE);
+		} else {
+			glCullFace(GL_FRONT);
+			glEnable(GL_CULL_FACE);
+			glDepthMask(GL_FALSE);
+		}
+		return true;
+	}
+	default:
+		warning("Unknown effect hash: %x", effectId);
+		return false;
+	}
 }
 
 } // namespace Wintermute
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
index e89be3cddaf..9a7d53c9441 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.h
@@ -50,7 +50,7 @@ public:
 	bool update(FrameNode *parentFrame) override;
 
 private:
-	void renderEffect(Material *material);
+	bool setupEffect(Material *material, bool secondPassNeeded);
 
 protected:
 	GLuint _vertexBuffer;
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.fragment b/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.fragment
index dcb69d0a7a4..3250a2ef177 100644
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.fragment
+++ b/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.fragment
@@ -7,23 +7,34 @@ uniform UBOOL alphaTest;
 uniform UBOOL useTexture;
 uniform UBOOL enableFog;
 uniform vec4 fogColor;
+uniform vec4 ambient;
+uniform int effectId;
+uniform UBOOL effectSecondPass;
 
 varying float fogFactor;
 
 OUTPUT
 
 void main() {
-	outColor = Color;
+	if (effectId == 0) {
+		outColor = Color;
 
-	if (useTexture) {
-		outColor = texture(tex, Texcoord) * outColor;
-	}
+		if (useTexture) {
+			outColor = texture(tex, Texcoord) * outColor;
+		}
 
-	if (enableFog) {
-		outColor.rgb = mix(fogColor.rgb, outColor.rgb, fogFactor);
-	}
+		if (enableFog) {
+			outColor.rgb = mix(fogColor.rgb, outColor.rgb, fogFactor);
+		}
 
-	if (UBOOL_TEST(alphaTest) && outColor.a < alphaRef) {
-		discard;
+		if (UBOOL_TEST(alphaTest) && outColor.a < alphaRef) {
+			discard;
+		}
+	} else if (effectId == 1) {
+		if (UBOOL_TEST(effectSecondPass)) {
+			outColor = texture(tex, Texcoord) * ambient;
+		} else {
+			outColor = Color;
+		}
 	}
 }
diff --git a/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.vertex b/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.vertex
index 67f5615b9ba..1d8e95aed93 100644
--- a/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.vertex
+++ b/engines/wintermute/base/gfx/opengl/shaders/wme_modelx.vertex
@@ -11,6 +11,10 @@ uniform vec4 ambientLight;
 uniform vec4 diffuse;
 uniform vec4 ambient;
 
+uniform int effectId;
+uniform UBOOL effectSecondPass;
+uniform float borderWidth;
+
 uniform float fogStart;
 uniform float fogEnd;
 varying float fogFactor;
@@ -30,49 +34,65 @@ out vec4 Color;
 out vec3 Normal;
 
 void main() {
-	vec4 viewCoords = viewMatrix * modelMatrix * vec4(position, 1.0);
-	gl_Position = projMatrix * viewCoords;
+	if (effectId == 0) {
+		Texcoord = texcoord;
+		Color = diffuse;
 
-	Texcoord = texcoord;
-	Color = diffuse;
+		vec4 viewCoords = viewMatrix * modelMatrix * vec4(position, 1.0);
+		gl_Position = projMatrix * viewCoords;
 
-	vec3 light = vec3(0.0, 0.0, 0.0);
-	vec3 normalEye = normalize((normalMatrix * vec4(normal, 0.0)).xyz);
+		vec3 light = vec3(0.0, 0.0, 0.0);
+		vec3 normalEye = normalize((normalMatrix * vec4(normal, 0.0)).xyz);
 
-	float fogCoord = abs(viewCoords.z);
-	fogFactor = clamp((fogEnd - fogCoord) / (fogEnd - fogStart), 0.0, 1.0);
+		float fogCoord = abs(viewCoords.z);
+		fogFactor = clamp((fogEnd - fogCoord) / (fogEnd - fogStart), 0.0, 1.0);
 
-	for (int i = 0; i < maxLights; ++i) {
-		if (lights[i].enabled < 0.0) {
-			continue;
-		}
+		for (int i = 0; i < maxLights; ++i) {
+			if (lights[i].enabled < 0.0) {
+				continue;
+			}
 
-		float intensity = 1.0;
-		vec4 lightPosition = viewMatrix * lights[i]._position;
-		vec3 vertexToLight = lightPosition.xyz - viewCoords.xyz;
-
-		if (lights[i]._direction.w < 0.0) { // Spotlight
-			vec4 lightDirection = viewMatrix * vec4(lights[i]._direction.xyz, 0.0);
-			// See DirectX spotlight documentation
-			float cosAngle = -dot(normalize(vertexToLight), normalize(lightDirection.xyz)); // rho
-			float cosPenumbra = 0.968912; // cos(1 / 4)
-			float cosUmbra = 0.877582; // cos(1 / 2)
-
-			if (cosAngle <= cosPenumbra) {
-				if (cosAngle < cosUmbra || cosPenumbra == cosUmbra) {
-					intensity = 0.0;
-				} else {
-					intensity *= (cosAngle - cosUmbra) / (cosPenumbra - cosUmbra);
+			float intensity = 1.0;
+			vec4 lightPosition = viewMatrix * lights[i]._position;
+			vec3 vertexToLight = lightPosition.xyz - viewCoords.xyz;
+
+			if (lights[i]._direction.w < 0.0) { // Spotlight
+				vec4 lightDirection = viewMatrix * vec4(lights[i]._direction.xyz, 0.0);
+				// See DirectX spotlight documentation
+				float cosAngle = -dot(normalize(vertexToLight), normalize(lightDirection.xyz)); // rho
+				float cosPenumbra = 0.968912; // cos(1 / 4)
+				float cosUmbra = 0.877582; // cos(1 / 2)
+
+				if (cosAngle <= cosPenumbra) {
+					if (cosAngle < cosUmbra || cosPenumbra == cosUmbra) {
+						intensity = 0.0;
+					} else {
+						intensity *= (cosAngle - cosUmbra) / (cosPenumbra - cosUmbra);
+					}
 				}
 			}
+
+			intensity *= max(0.0, dot(normalEye, normalize(vertexToLight)));
+			light += lights[i]._color.rgb * intensity;
 		}
 
-		intensity *= max(0.0, dot(normalEye, normalize(vertexToLight)));
-		light += lights[i]._color.rgb * intensity;
-	}
+		Color.rgb *= light;
+		Color.rgb += ambient.rgb * ambientLight.rgb;
 
-	Color.rgb *= light;
-	Color.rgb += ambient.rgb * ambientLight.rgb;
+		Color.rgb = clamp(Color.rgb, 0.0, 1.0);
+	} else if (effectId == 1) {
+		Texcoord = texcoord;
+		Color = vec4(0.0, 0.0, 0.0, 1.0);
 
-	Color.rgb = clamp(Color.rgb, 0.0, 1.0);
+		vec4 viewCoords = viewMatrix * modelMatrix * vec4(position, 1.0);
+		vec4 pos = projMatrix * viewCoords;
+
+		if (UBOOL_TEST(effectSecondPass)) {
+		} else {
+			vec3 nrm = (viewMatrix * modelMatrix * vec4(normal, 0.0)).xyz;
+			pos.xy += nrm.xy * pos.w * borderWidth * 0.001;
+		}
+
+		gl_Position = pos;
+	}
 }




More information about the Scummvm-git-logs mailing list