Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DXT textures have black mipmap levels (Windows, DirectX) #1783

Closed
DigitalRune opened this issue Jun 10, 2013 · 7 comments
Closed

DXT textures have black mipmap levels (Windows, DirectX) #1783

DigitalRune opened this issue Jun 10, 2013 · 7 comments

Comments

@DigitalRune
Copy link
Contributor

In our Windows/DirectX application the lowest resolution mipmap levels of DXT textures are black.

There is following code in Texture2D:

// For DXT textures the width and height of each level is a multiple of 4.
                        // The last two mip levels require the width and height to be passed as 2x2 and 1x1, but
                        // there needs to be enough data passed to occupy a 4x4 block.
                        // Ref: http://www.mentby.com/Group/mac-opengl/issue-with-dxt-mipmapped-textures.html 
                        if (_format == SurfaceFormat.Dxt1 ||
                            _format == SurfaceFormat.Dxt1a ||
                            _format == SurfaceFormat.Dxt3 ||
                            _format == SurfaceFormat.Dxt5)
                        {
                            if (w > 4)
                                w = (w + 3) & ~3;
                            if (h > 4)
                                h = (h + 3) & ~3;
                        }

(https://github.com/mono/MonoGame/blob/450733b035add1a359033a0aefdc5dc2ea6fa2af/MonoGame.Framework/Graphics/Texture2D.cs#L327-L340)

Without if (w > 4) and if (h > 4) the textures are displayed correctly (in DirectX).
I believe those if statements were added in following commit by @KonajuGames: 620642b.
It seems the ifs are needed for OpenGL, but not for DirectX.

Was this change tested with DirectX or only with OpenGL?

P.S. I guess TextureCube has the same problem.

@tomspilman
Copy link
Member

Hum.... @KonajuGames will have to respond to this one. My understanding at the time was that this was required for both DX and GL, but I could be wrong.

@KonajuGames
Copy link
Contributor

It may well be an OpenGL only requirement. If you wish to submit a pull
request to make it work properly on DirectX then we can merge it.

@flibitijibibo
Copy link
Contributor

We have similar problems on OpenGL as well... we were dealing with this in Gateways on MG-SDL2 after adding S3TC support, made a quick (read: bad and awfully slow) fix in MG-SDL2:

https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/Content/ContentReaders/Texture2DReader.cs#L245
https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/Graphics/Texture2D.cs#L288

The w/h checks don't seem to affect things either way for us.

@DigitalRune
Copy link
Contributor Author

Thanks for the quick replies. We will make some more tests and create a pull request which updates the DirectX paths in Texture2D and TextureCube.

@DigitalRune
Copy link
Contributor Author

Something else I have found (which is not addressed in the pull request):
The MonoGame code contains following assert in Texture.GetPitch():

case SurfaceFormat.Dxt1:
case SurfaceFormat.Dxt1a:
case SurfaceFormat.RgbPvrtc2Bpp:
case SurfaceFormat.RgbaPvrtc2Bpp:
case SurfaceFormat.RgbEtc1:
case SurfaceFormat.Dxt3:
case SurfaceFormat.Dxt5:
case SurfaceFormat.RgbPvrtc4Bpp:
case SurfaceFormat.RgbaPvrtc4Bpp:
    Debug.Assert(MathHelper.IsPowerOfTwo(width), "This format must be power of two!");
    pitch = ((width + 3) / 4) * _format.Size();
    break;

AFAIK, DXT textures only have to be a multiply of 4. It is not required that they are POT. And NPOT DXT textures seem to work fine (when you ignore the assert messages). (Tested on Windows desktop (DX and OpenGL) and Windows Store.)
Is there anything else in MonoGame that requires DXT textures to be POT?

@KonajuGames
Copy link
Contributor

In XNA, DXT was required to be POT when using the Reach graphics profile
(low-end PC, Windows Phone 7). HiDef graphics profile allowed non-POT DXT,
but still has the multiple-of-4 width/height requirement.

I believe PVRTC requires POT. ETC1 likely same as DXT as it is 4x4
block-based as well.

@DigitalRune
Copy link
Contributor Author

Thanks for the info.

KonajuGames added a commit that referenced this issue Jun 17, 2013
Fixed black mipmap levels in DXT textures (DirectX) - Issue #1783.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants