Skip to content

Commit f9e800e

Browse files
committed
Merge branch 'ivecometomakeanannouncement' into 'master'
Fix moon blending (#6439) Closes #6439 See merge request OpenMW/openmw!5211
2 parents 663ae0f + dc5f9b4 commit f9e800e

File tree

2 files changed

+32
-23
lines changed

2 files changed

+32
-23
lines changed

apps/openmw/mwrender/skyutil.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -318,45 +318,32 @@ namespace MWRender
318318

319319
struct MoonUpdater : SceneUtil::StateSetUpdater
320320
{
321-
Resource::ImageManager& mImageManager;
322-
osg::ref_ptr<osg::Texture2D> mPhaseTex;
323-
osg::ref_ptr<osg::Texture2D> mCircleTex;
324-
float mTransparency;
325-
float mShadowBlend;
326-
osg::Vec4f mAtmosphereColor;
327-
osg::Vec4f mMoonColor;
321+
float mTransparency{ 1.f };
322+
float mShadowBlend{ 1.f };
323+
osg::Vec4f mAtmosphereColor{ 1.f, 1.f, 1.f, 1.f };
324+
osg::Vec4f mMoonColor{ 1.f, 1.f, 1.f, 1.f };
328325

329326
MoonUpdater(Resource::ImageManager& imageManager)
330327
: mImageManager(imageManager)
331-
, mPhaseTex()
332-
, mCircleTex()
333-
, mTransparency(1.0f)
334-
, mShadowBlend(1.0f)
335-
, mAtmosphereColor(1.0f, 1.0f, 1.0f, 1.0f)
336-
, mMoonColor(1.0f, 1.0f, 1.0f, 1.0f)
337328
{
338329
}
339330

340331
void setDefaults(osg::StateSet* stateset) override
341332
{
342333
stateset->addUniform(new osg::Uniform("pass", static_cast<int>(Pass::Moon)));
343-
stateset->setTextureAttributeAndModes(0, mPhaseTex);
344-
stateset->setTextureAttributeAndModes(1, mCircleTex);
345-
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
346-
stateset->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
334+
stateset->setTextureAttribute(0, mPhaseTex);
335+
stateset->setTextureAttribute(1, mCircleTex);
347336
stateset->addUniform(new osg::Uniform("moonBlend", osg::Vec4f{}));
348337
stateset->addUniform(new osg::Uniform("atmosphereFade", osg::Vec4f{}));
349338
stateset->addUniform(new osg::Uniform("diffuseMap", 0));
350339
stateset->addUniform(new osg::Uniform("maskMap", 1));
351340
stateset->setAttributeAndModes(
352-
createUnlitMaterial(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
341+
new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON);
342+
stateset->setAttributeAndModes(createUnlitMaterial(), osg::StateAttribute::ON);
353343
}
354344

355345
void apply(osg::StateSet* stateset, osg::NodeVisitor*) override
356346
{
357-
stateset->setTextureAttribute(0, mPhaseTex, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
358-
stateset->setTextureAttribute(1, mCircleTex, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
359-
360347
if (auto* uMoonBlend = stateset->getUniform("moonBlend"))
361348
uMoonBlend->set(mMoonColor * mShadowBlend);
362349
if (auto* uAtmosphereFade = stateset->getUniform("atmosphereFade"))
@@ -375,6 +362,11 @@ namespace MWRender
375362

376363
reset();
377364
}
365+
366+
private:
367+
Resource::ImageManager& mImageManager;
368+
osg::ref_ptr<osg::Texture2D> mPhaseTex;
369+
osg::ref_ptr<osg::Texture2D> mCircleTex;
378370
};
379371

380372
class CameraRelativeTransformCullCallback

files/shaders/compatibility/sky.frag

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,25 @@ void paintMoon(inout vec4 color)
3939
vec4 phase = texture2D(diffuseMap, diffuseMapUV);
4040
vec4 mask = texture2D(maskMap, diffuseMapUV);
4141

42-
vec4 blendedLayer = phase * moonBlend;
43-
color = vec4(blendedLayer.xyz + atmosphereFade.xyz, atmosphereFade.a * mask.a);
42+
// Morrowind does this in two passes
43+
44+
// First pass: moon shadow, normal blending (src alpha, 1 - src alpha)
45+
// dst.rgb = mask.rgb * mask.a + dst.rgb * (1 - mask.a)
46+
// Second pass: moon phase, additive blending (src alpha, 1)
47+
// dst.rgb += phase.rgb * phase.a
48+
49+
// The same is doable in a single pass through premultiplied alpha blending
50+
// color.rgb = mask.rgb * mask.a + phase.rgb * phase.a
51+
// color.a = mask.a
52+
// dst.rgb = color.rgb + dst.rgb * (1 - color.a)
53+
54+
vec3 maskTinted = mask.rgb * atmosphereFade.rgb;
55+
float maskAlpha = mask.a * atmosphereFade.a;
56+
vec3 phaseTinted = phase.rgb * moonBlend.rgb;
57+
float phaseAlpha = phase.a * atmosphereFade.a;
58+
59+
color.rgb = maskTinted * maskAlpha + phaseTinted * phaseAlpha;
60+
color.a = maskAlpha;
4461
}
4562

4663
void paintSun(inout vec4 color)

0 commit comments

Comments
 (0)