cinder / Cinder

Cinder is a community-developed, free and open source library for professional-quality creative coding in C++.
http://libcinder.org
Other
5.28k stars 939 forks source link

Uncompressed DDS files seem to fail to load with the built in DDS parser #1195

Open vade opened 8 years ago

vade commented 8 years ago

Hello

It appears the uncompressed DDS files don't parse correctly with the current DDS parser included with Cinder.

The following test app loads DXT1, 3, 5 compressed DDS files but not uncompressed. Test DDS files from ImageMagick, Graphic Converter and Gimp are included.

Attempting to load an uncompressed DDS file from this set of folders ( https://dl.dropboxusercontent.com/u/42612525/DDS%20Tests.zip ) with the simple Cinder code that follows throws:

libc++abi.dylib: terminating with uncaught exception of type cinder::gl::DdsParseExc: Unsupported image format

#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

 using namespace ci;
 using namespace ci::app;
 using namespace std;

 class DDSTestApp : public App {
   public:
    void setup() override;
    void mouseDown( MouseEvent event ) override;
    void update() override;
    void draw() override;

    gl::Texture2dRef ddsTexture;
};

 void DDSTestApp::setup()
{
     ci::app::Platform* pl = ci::app::Platform::get();
     fs::path ddsFile = pl->getOpenFilePath();

    ci::DataSourceRef ddsDataSource = ci::DataSourcePath::create(ddsFile);
    ddsTexture = gl::Texture2d::createFromDds(ddsDataSource);
}

 void DDSTestApp::draw()
{

    gl::clear( Color( 0, 0, 0 ) );

    Rectf textureBounds = ddsTexture->getBounds();
    Rectf drawBounds = textureBounds.getCenteredFit( getWindowBounds(), true );
    gl::draw( ddsTexture, drawBounds );
}

 CINDER_APP( DDSTestApp, RendererGl )
pizthewiz commented 8 years ago

Hmm, what does compressed and uncompressed mean in this context? DDS is a container and DXT# and encoding, so I'm not totally sure what's up.

In the console gaming space, I've read that pipeline architects will take DXT encoded content and post-process it with other data-compression stuffs, but that's kinda the exotic fringes and external to DDS files, but that's all I could come up with in regards to compressed and uncompressed (in which case uncompressed should work and compressed would not). https://www.youtube.com/watch?v=7bJ-D1xXEeg https://code.google.com/p/libsquish/ https://code.google.com/p/crunch/ https://code.google.com/p/snappy/

vade commented 8 years ago

Debugging this looks like the issue is the ddpfPixelFormat.dwFourCC is 0 in the files created by both GIMP "uncompressed" DDS export plugin, and ImageMagick via convert -define dds:compression=none.

adding a simple:

    case 0: // not noted, assume RGBA 8 bit?
    case 32 /*D3DFMT_A8B8G8R8*/:

on line 284 in TextureFormatParsers.cpp allowed the uncompressed files to load successfully on OS X. Am testing Windows shortly :)

The spec according to MS states the pixel format might not need to be respected in some cases:

"Note When you write .dds files, you should set the DDSD_CAPS and DDSD_PIXELFORMAT flags, and for mipmapped textures you should also set the DDSD_MIPMAPCOUNT flag. However, when you read a .dds file, you should not rely on the DDSD_CAPS, DDSD_PIXELFORMAT, and DDSD_MIPMAPCOUNT flags being set because some writers of such a file might not set these flags."

:X that seems wonky as hell but, hey, "standards".

pizthewiz commented 8 years ago

because some writers of such a file might not set these flags.

Bad actors!

vade commented 8 years ago

"The DirectDraw Surface file format (.dds) was introduced with DirectX 7 to store uncompressed and compressed (DXTn) textures. The file format supports mipmaps, cube maps, and volume maps. The DDS file format is supported by DirectXTex, DirectXTK, legacy D3DX, and other DirectX tools. Starting with Direct3D 10, DDS files support texture arrays."

https://msdn.microsoft.com/en-us/library/windows/desktop/bb943990(v=vs.85).aspx

I think its meant to support more than just compressed textures, but it seems like how thats handled might be a bit loose in many cases.

Thanks for making this super amazingly awesomely easy with Cinder. You all rock.

pizthewiz commented 8 years ago

Interesting, I've never seen the DDS container used without one of the DXT family encodings - is there any benefit over other uncompressed formats like TIFF?

vade commented 8 years ago

Well, for whatever reason, TIFF is slow as balls - I think due to system OS calls that evoke memcpy whereas the Cinder DDS path goes direct to PBO via TextureData?

Due to my profiling issues on Windows (it not working), I'm honestly not entirely sure, but I know its slow. On OS X, the slowness is mostly due to CGCopyDataProvider. I imagine something similar is happening in some Windows bitmap code somewhere :)

vade commented 8 years ago

Ah. Interestingly, this fix obviously doesn't sort out the nuance between uncompressed 24 bit vs 32 bit image (RGB vs RGBA). Ill poke around a bit tomorrow and see if I can deduce some differences in the header that can be better relied upon? But this is great progress.

pizthewiz commented 8 years ago

It seems like there must be some way to divine the content type if one cannot rely on DDSD_CAPS and DDSD_PIXELFORMAT, though if so, it would have been awesome for MS to have mentioned it right after that warning in the spec.

vade commented 8 years ago

Haha right?

majimboo commented 7 years ago

I too have DDS files that date back to 2000/2001. And they don't use any kind of compression. Failing on most of the new parsers. But works on the old ones.

Any more information about the uncompressed DDS?

y2keeth commented 1 year ago

would this work on old idtech4 games?