• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lonesock

SOIL: new lightweight image loading lib

130 posts in this topic

Hi, All. This is an announcement, but I think it fits better in this forum. If I'm wrong, feel free to move it [8^) I've been looking for a tiny image loading library for some hobby OpenGL game projects I'm working on, but never really found exactly what I wanted. Then I found Sean Barrett's awesome C code for loading BMP/PNG/JPG files (here). I took that, added TGA loading support (except for indexed TGA images), wrapped some common functions like upsizing to power-of-two sizes, MIPmap generation, pre-multiplying alpha, etc. all into a single function call for easy loading of textures into OpenGL. Presenting the Simple OpenGL Image Library (yes, I'm sorry SOIL is such a lame acronym [8^) Features: Loads PNG, JPG, TGA, BMP, DDS (a subset of each type) Saves TGA, BMP, DDS Loads an image file directly into an OpenGL texture Can automatically rescale the image to the next largest power-of-two size Can automatically create MIPmaps Can multiply alpha on load (for more correct blending / compositing) Can flip the image vertically Can compress to DXT1 or DXT5 (if EXT_texture_compression_s3tc is available) Will downsize the image if necessary to fit GL_MAX_TEXTURE_SIZE No external dependencies Tiny Public Domain If anybody is willing to give some feedback, I'd really appreciate it (I'm keeping this a C project, and my C skills are extremely rusty). Feature requests are also welcome. [edited to add new features] [Edited by - lonesock on August 16, 2007 11:59:53 AM]
0

Share this post


Link to post
Share on other sites
Quote:
Original post by ForestMaster
I've found it such a neat, tidy and useful drop i can't help saying thanks, good job!

Thanks!

I updated SOIL a bit: you can now pass in a flag to specify that you want the image flipped vertically, and you can flag that you want the image compressed to use DXT(1 for RGB, 5 for RGBA), if EXT_texture_compression_s3tc is available. Note that this could be slow, depending on your OpenGL drivers. I'm looking into writing my own (hopefully faster) DXT1/3/5 compressor, but that's down the road. Next step is just loading already compressed DDS files.
0

Share this post


Link to post
Share on other sites
Looks very cool - bookmarked for future reference :)
0

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Looks very cool - bookmarked for future reference :)

[8^)

OK, I have written my own DXT1 compressor, decent quality, very fast (about 31ms for a 512x512 RGB image). I'm planning to add this to SOIL this weekend, so if a user specifies that they want the image loaded as DXT, SOIL will do the conversion without relying on the (very slow, for me at least) OpenGL driver to do the conversion.

A sample:
Here is the original image, and
here is the one done in 31ms, and
here is the DXT1 file from ATI's Compressonator (~1.5 seconds)
0

Share this post


Link to post
Share on other sites
SOIL can now load compressed DDS files directly as an OpenGL texture! It also has its own DXT compressor now, so no reliance on the OpenGL driver for uploading uncompressed images in S3TC format. Any image file SOIL can load can be quickly compressed (~26ms for a 512x512 image on my Athlon64 3000+). You can also save any file as a DDS file (SOIL will use the internal compressor). This works for screenshots too.

The testSOIL.exe file takes an image specified on the command line, then resizes it to the nearest larger power-of-two (if needed), pre-multiplies alpha, generates the MIPmaps, compresses to DXT1 (for RGB images) or DXT5 (for RGBA images), uploads the image to OpenGL then displays 2 quads, 1 stationary and 1 spinning with that texture on it. When you hit [Esc] the program will exit after saving a screenshot in TGA format.

The exe was compiled with MinGW 3.4.5, as was the libSOIL.a file. The SOIL_vc8.lib file was compiled with Microsoft's very nifty free VS2005 Express edition.

Please let me know if anybody gets it to work under a new compiler or has any feedback / feature requests.
0

Share this post


Link to post
Share on other sites
I just uploaded a new SOIL version, here are the changes:

Updated to stb_image version 0.97

SOIL can now decompress DDS files (allows regular file loading, e.g. for heightmaps, etc, allows image flipping, resizing, pre-multiplying alpha, etc. It also means that there is no need to have an alternate art asset path in case the user's machine doesn't support DXT compression)

You can still force the DDS files to be loaded directly if supported (and everything GeForce2 and above will support it), but you lose all the other nifty options.

There is some simple error reporting, in case an image fails to load.
0

Share this post


Link to post
Share on other sites
SOIL can now load Indexed TGA images.

So, basically, except for bug fixes and porting, I'm pretty much ready to call it a day.

Feedback is always appreciated.
0

Share this post


Link to post
Share on other sites
This is a very nice, clean library you have here, lonesock.
I'm going to be using it to replace SDL_Image as my image loading library in my game engine.
thanks for the awesome work!
0

Share this post


Link to post
Share on other sites
Quote:
Original post by lonesock
SOIL can now load Indexed TGA images.

So, basically, except for bug fixes and porting, I'm pretty much ready to call it a day.


Inevitably some fool will later spurn your library, claiming it's "unmaintained... no updates since 2007". :)

Sounds good. I'll get it up on my library list when I get around to the next update.

Just a thought though; how good is the mip-map generation algorithm? Someone might want something better than the typical bilinear filtering. (eg. bicubic)
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Inevitably some fool will later spurn your library, claiming it's "unmaintained... no updates since 2007". :)

[8^)
Not to mention I spoke too soon! On my laptop's S3 chipset I ran into a 1024x1024 texture size limit. So SOIL now queries GL_MAX_TEXTURE_SIZE, and will automatically downsize the image to fit the implementation limits (only the offending dimension(s), and only when uploading a texture to OpenGL, nothing is touched when you load an image by itself). I'll try to get the fix up on my website today or tomorrow.

Quote:
Original post by Kylotan
Just a thought though; how good is the mip-map generation algorithm? Someone might want something better than the typical bilinear filtering. (eg. bicubic)

Hmm, I cheat. If the user wants MIPmaps, I force the image to be a power-of-two size (upsizing it if necessary using simple bilinear sampling). Then for each MIPmap I do a simple average over the appropriate block. So for MIPmap 1, each pixel is an average over the associated 2x2 block. For MIPmap 2, each pixel is an average over 4x4 blocks, etc. I do this to try to keep from propagating errors at each level (i.e. I build MIP 2 from MIP 0, not just from MIP 1).

If you have any links pointing to literature on the proper / better / best way to do MIPmaps, I'd be more than happy to implement a different method.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by zerotri
This is a very nice, clean library you have here, lonesock.
I'm going to be using it to replace SDL_Image as my image loading library in my game engine.
thanks for the awesome work!

Thanks! And you're welcome [8^)
0

Share this post


Link to post
Share on other sites
Soil is updated once again:

* Will now downsize the image if necessary to fit GL_MAX_TEXTURE_SIZE

* Added SOIL_create_OGL_texture() to upload raw image data that isn't from an image file. Basically I just split the standard SOIL_load_OGL_texture() out so I could upload my own generated/modified image data straight from RAM, with all of the other nifty features still available to me, like DXT compression, MIPmap generation, etc.
0

Share this post


Link to post
Share on other sites
Great library, thanks =D
For *nix (X11) systems, you need to #include <GL/glx.h> for glXGetProcAddressARB() in SOIL.c, otherwise it works perfectly under linux.
Also, it won't compile ansi-strict as there isn't enough implicit casting (generally mallocs), also you're using C++ style comments in C code, and possibly one or two other bits and bobs, but that isn't really much of an issue (I just prefer to compile all my code ansi-strict, just a habit).
If you're looking of ways to extend this, you could add loaders for cube (and possibly sphere and dual-paraboloid) environment maps =)

Great work! I'll definitely be using this for my projects.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by DeathCarrot
Great library, thanks =D
For *nix (X11) systems, you need to #include <GL/glx.h> for glXGetProcAddressARB() in SOIL.c, otherwise it works perfectly under linux.
Also, it won't compile ansi-strict as there isn't enough implicit casting (generally mallocs), also you're using C++ style comments in C code, and possibly one or two other bits and bobs, but that isn't really much of an issue (I just prefer to compile all my code ansi-strict, just a habit).
If you're looking of ways to extend this, you could add loaders for cube (and possibly sphere and dual-paraboloid) environment maps =)

Great work! I'll definitely be using this for my projects.

Thanks! OK, I cleaned up the C++ style comments and the malloc/free casts (in SOIL proper, I'm pretty much leaving the stb_image code alone, sorry). I also put in the include for glx.h for *nix extension loading (now I just need to verify on Apple!)

I'm also adding in a function for loading 6 images into a cube map texture. After that is working, I'll extend the DDS loader to handle cube map loading so you can do a direct load of DDS cube map files. Adding these features will probably take a while, between my limited time right now and possible code complexity (I haven't actually used cube maps before, so it may be easy, I just don't know).

As to sphere maps, doesn't OpenGL just load them as regular textures, then you use the appropriate texture generation mode? I haven't used sphere maps either, but that seems to be something you would actually enable/set-up outside of SOIL. Please let me know if I'm wrong, and thanks for the feedback and suggestions!

0

Share this post


Link to post
Share on other sites
Quote:
Original post by lonesock

Quote:
Original post by Kylotan
Just a thought though; how good is the mip-map generation algorithm? Someone might want something better than the typical bilinear filtering. (eg. bicubic)

Hmm, I cheat. If the user wants MIPmaps, I force the image to be a power-of-two size (upsizing it if necessary using simple bilinear sampling). Then for each MIPmap I do a simple average over the appropriate block. So for MIPmap 1, each pixel is an average over the associated 2x2 block. For MIPmap 2, each pixel is an average over 4x4 blocks, etc. I do this to try to keep from propagating errors at each level (i.e. I build MIP 2 from MIP 0, not just from MIP 1).

If you have any links pointing to literature on the proper / better / best way to do MIPmaps, I'd be more than happy to implement a different method.


Yeah, that average is just a typical box filter, and is fine in most cases. It's what gluBuild2DMipmaps() uses, apparently. There's a little more info here but thinking about it, it's probably not a big deal, as long as people can still generate their own mipmaps if they need to.
0

Share this post


Link to post
Share on other sites
Some SOIL updates:
* can now load 6 faces into a cube map (needs testing)
* can now compress 1 or 2 channel images to DXT1/5 (before it would just leave them uncompressed)
* can hopefully compile/work under *nix and Mac (please let me know if there is anything more I need to fix...I don't have access to these platforms right now)

Upcoming:
* ability to load uncompressed and cube map DDS files

Quote:
Original post by Kylotan
Yeah, that average is just a typical box filter, and is fine in most cases. It's what gluBuild2DMipmaps() uses, apparently. There's a little more info here but thinking about it, it's probably not a big deal, as long as people can still generate their own mipmaps if they need to.

SOIL is mostly about raw image loading/saving, and having a dirt-simple path for uploading image files to OpenGL textures...if what I'm doing is the common standard I'll probably just keep it as is. Thanks for the info and feedback.
0

Share this post


Link to post
Share on other sites
Great stuff =D

Got around to trying the cube map importing, and it works wonderfully (I'm at work now and I only have windows to play around with here, but I guess there's nothing new enough for it to not work on *nix).

If anyone hasn't used cube maps before and wants to try it out but doesn't want to go hunting for tutorials for how to bind them, get 6 cube maps, load them using SOIL:

tex = SOIL_load_OGL_cubemap(
"tex/xp.bmp",
"tex/xn.bmp",
"tex/yp.bmp",
"tex/yn.bmp",
"tex/zp.bmp",
"tex/zn.bmp",
0,0,SOIL_FLAG_MIPMAPS
);

And bind:

glEnable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);

Easy as pie =)

0

Share this post


Link to post
Share on other sites
Quote:
Original post by DeathCarrot
If anyone hasn't used cube maps before and wants to try it out but doesn't want to go hunting for tutorials for how to bind them, get 6 cube maps, load them using SOIL:
...
Easy as pie =)

You rock!

I've updated the website a bit, especially the usage examples...so now it's easier to see what SOIL can do. (note that the 'SOIL_CREATE_NEW_ID' enum is new, and not in the uploaded source yet, but it is just = 0. I will be uploading a new version in a bit, once I finish a few things on the TODO list)
0

Share this post


Link to post
Share on other sites
Well, Ive just read the header file and was astonished to find that it supports loading and saving files, and can automaticaly generate a screenshot. I'll definitely be using this for the next few days. Good Job!
0

Share this post


Link to post
Share on other sites
@ speciesUnknown & ForestMaster: thanks!

Updated SOIL a bit:
* now has the SOIL_CREATE_NEW_ID enum in SOIL.h (as shown in the usage examples)
* can now load uncompressed DDS files (directly which will preserve MIPmaps, or via stb_image which will ignore the MIPmaps, then regenerate them if requested)

The next thing I'm going to implement is loading cubemaps from single image files. This would include DDS cubemap files, and also any other format where the width is 6x the height (or vice versa). This way you could stitch together your 6 265x265 cubemap faces side to side into a single 1536x256 texture, or vertically to form a 256x1536 texture, then save it as png/jpg(make sure that your image size is a multiple of 8 so the jpeg blocks don't cross image boundaries)/dds(ditto, but multiples of 4)/whatever.

I'd like to just add a flag to SOIL_load_OGL_texture(), SOIL_FLAG_SPLIT_CUBEMAPS. This way SOIL would automatically split any image texture where the width is 6x the height and load it as a cubemap. Here's my question...does that make sense to everybody, or should I introduce a new function (SOIL_load_OGL_single_cubemap() or similar)? I'm not sure which way would be more intuitive.

Please cast your votes!

P.S. this version of the zip only has the library built with MinGW and VC2k5 Express...the VC6 and VC2k3 versions will have to wait till I get back to work. But the project files are still there, so you can easily perform the build if necessary.
0

Share this post


Link to post
Share on other sites
Quote:
Original post by lonesock
I'd like to just add a flag to SOIL_load_OGL_texture(), SOIL_FLAG_SPLIT_CUBEMAPS. This way SOIL would automatically split any image texture where the width is 6x the height and load it as a cubemap. Here's my question...does that make sense to everybody, or should I introduce a new function (SOIL_load_OGL_single_cubemap() or similar)? I'm not sure which way would be more intuitive.

Please cast your votes!


you can make two functions with the same name:

unsigned int
SOIL_load_OGL_texture
(
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
unsigned int
SOIL_load_OGL_texture
(
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags,
unsigned int cubemapflag
);


that can work either this way

SOIL_load_OGL_texture
(
"img.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT
);


or this way

SOIL_load_OGL_texture
(
"img.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT, SOIL_FLAG_SPLIT_CUBEMAPS
);



so you have one function 'name' only that can work ordinarily without specifying the flag or using the cubemap if the last parameter is added
similarly you can make 2 versions of the soil load ogl cube map function

unsigned int
SOIL_load_OGL_cubemap
(
const char *x_pos_file,
const char *x_neg_file,
const char *y_pos_file,
const char *y_neg_file,
const char *z_pos_file,
const char *z_neg_file,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
unsigned int
SOIL_load_OGL_cubemap
(
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);


and you have two different definitions of the function, the one with one char* prameter only will have to be split.
hope its clear

forest
0

Share this post


Link to post
Share on other sites
ForestMaster: I think author is making SOIL as C not C++ library. So function overloading is not available.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0