12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042 |
- /*
- Jonathan Dummer
- 2007-07-26-10.36
- Simple OpenGL Image Library
- Public Domain
- using Sean Barret's stb_image as a base
- Thanks to:
- * Sean Barret - for the awesome stb_image
- * Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts
- * everybody at gamedev.net
- */
- #define SOIL_CHECK_FOR_GL_ERRORS 0
- #ifdef WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <wingdi.h>
- #if 0
- #include <GL/gl.h>
- #endif
- #elif defined(__APPLE__) || defined(__APPLE_CC__)
- /* I can't test this Apple stuff! */
- #if 0
- #include <OpenGL/gl.h>
- #endif
- #include <Carbon/Carbon.h>
- #define APIENTRY
- #else
- #if 0
- #include <GL/gl.h>
- #include <GL/glx.h>
- #endif
- #endif
- #include "SOIL.h"
- #include "stb_image_aug.h"
- #include "image_helper.h"
- #include "image_DXT.h"
- #include <stdlib.h>
- #include <string.h>
- /* error reporting */
- const char *result_string_pointer = "SOIL initialized";
- /* for loading cube maps */
- enum{
- SOIL_CAPABILITY_UNKNOWN = -1,
- SOIL_CAPABILITY_NONE = 0,
- SOIL_CAPABILITY_PRESENT = 1
- };
- /* static int has_cubemap_capability = SOIL_CAPABILITY_UNKNOWN; */
- int query_cubemap_capability( void );
- #define SOIL_TEXTURE_WRAP_R 0x8072
- #define SOIL_CLAMP_TO_EDGE 0x812F
- #define SOIL_NORMAL_MAP 0x8511
- #define SOIL_REFLECTION_MAP 0x8512
- #define SOIL_TEXTURE_CUBE_MAP 0x8513
- #define SOIL_TEXTURE_BINDING_CUBE_MAP 0x8514
- #define SOIL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
- #define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
- #define SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
- #define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
- #define SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
- #define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
- #define SOIL_PROXY_TEXTURE_CUBE_MAP 0x851B
- #define SOIL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
- /* for non-power-of-two texture */
- /* static int has_NPOT_capability = SOIL_CAPABILITY_UNKNOWN; */
- int query_NPOT_capability( void );
- /* for texture rectangles */
- /* static int has_tex_rectangle_capability = SOIL_CAPABILITY_UNKNOWN; */
- int query_tex_rectangle_capability( void );
- #define SOIL_TEXTURE_RECTANGLE_ARB 0x84F5
- #define SOIL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
- /* for using DXT compression */
- /* static int has_DXT_capability = SOIL_CAPABILITY_UNKNOWN; */
- int query_DXT_capability( void );
- #define SOIL_RGB_S3TC_DXT1 0x83F0
- #define SOIL_RGBA_S3TC_DXT1 0x83F1
- #define SOIL_RGBA_S3TC_DXT3 0x83F2
- #define SOIL_RGBA_S3TC_DXT5 0x83F3
- #if 0
- typedef void (APIENTRY * P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data);
- P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC soilGlCompressedTexImage2D = NULL;
- unsigned int SOIL_direct_load_DDS(
- const char *filename,
- unsigned int reuse_texture_ID,
- int flags,
- int loading_as_cubemap );
- unsigned int SOIL_direct_load_DDS_from_memory(
- const unsigned char *const buffer,
- int buffer_length,
- unsigned int reuse_texture_ID,
- int flags,
- int loading_as_cubemap );
- /* other functions */
- unsigned int
- SOIL_internal_create_OGL_texture
- (
- const unsigned char *const data,
- int width, int height, int channels,
- unsigned int reuse_texture_ID,
- unsigned int flags,
- unsigned int opengl_texture_type,
- unsigned int opengl_texture_target,
- unsigned int texture_check_size_enum
- );
- /* and the code magic begins here [8^) */
- unsigned int
- SOIL_load_OGL_texture
- (
- const char *filename,
- int force_channels,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels;
- unsigned int tex_id;
- /* does the user want direct uploading of the image as a DDS file? */
- if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
- {
- /* 1st try direct loading of the image as a DDS file
- note: direct uploading will only load what is in the
- DDS file, no MIPmaps will be generated, the image will
- not be flipped, etc. */
- tex_id = SOIL_direct_load_DDS( filename, reuse_texture_ID, flags, 0 );
- if( tex_id )
- {
- /* hey, it worked!! */
- return tex_id;
- }
- }
- /* try to load the image */
- img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* OK, make it a texture! */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- reuse_texture_ID, flags,
- GL_TEXTURE_2D, GL_TEXTURE_2D,
- GL_MAX_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- /* and return the handle, such as it is */
- return tex_id;
- }
- unsigned int
- SOIL_load_OGL_HDR_texture
- (
- const char *filename,
- int fake_HDR_format,
- int rescale_to_max,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels;
- unsigned int tex_id;
- /* no direct uploading of the image as a DDS file */
- /* error check */
- if( (fake_HDR_format != SOIL_HDR_RGBE) &&
- (fake_HDR_format != SOIL_HDR_RGBdivA) &&
- (fake_HDR_format != SOIL_HDR_RGBdivA2) )
- {
- result_string_pointer = "Invalid fake HDR format specified";
- return 0;
- }
- /* try to load the image (only the HDR type) */
- img = stbi_hdr_load_rgbe( filename, &width, &height, &channels, 4 );
- /* channels holds the original number of channels, which may have been forced */
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* the load worked, do I need to convert it? */
- if( fake_HDR_format == SOIL_HDR_RGBdivA )
- {
- RGBE_to_RGBdivA( img, width, height, rescale_to_max );
- } else if( fake_HDR_format == SOIL_HDR_RGBdivA2 )
- {
- RGBE_to_RGBdivA2( img, width, height, rescale_to_max );
- }
- /* OK, make it a texture! */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- reuse_texture_ID, flags,
- GL_TEXTURE_2D, GL_TEXTURE_2D,
- GL_MAX_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- /* and return the handle, such as it is */
- return tex_id;
- }
- unsigned int
- SOIL_load_OGL_texture_from_memory
- (
- const unsigned char *const buffer,
- int buffer_length,
- int force_channels,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels;
- unsigned int tex_id;
- /* does the user want direct uploading of the image as a DDS file? */
- if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
- {
- /* 1st try direct loading of the image as a DDS file
- note: direct uploading will only load what is in the
- DDS file, no MIPmaps will be generated, the image will
- not be flipped, etc. */
- tex_id = SOIL_direct_load_DDS_from_memory(
- buffer, buffer_length,
- reuse_texture_ID, flags, 0 );
- if( tex_id )
- {
- /* hey, it worked!! */
- return tex_id;
- }
- }
- /* try to load the image */
- img = SOIL_load_image_from_memory(
- buffer, buffer_length,
- &width, &height, &channels,
- force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* OK, make it a texture! */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- reuse_texture_ID, flags,
- GL_TEXTURE_2D, GL_TEXTURE_2D,
- GL_MAX_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- /* and return the handle, such as it is */
- return tex_id;
- }
- 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
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels;
- unsigned int tex_id;
- /* error checking */
- if( (x_pos_file == NULL) ||
- (x_neg_file == NULL) ||
- (y_pos_file == NULL) ||
- (y_neg_file == NULL) ||
- (z_pos_file == NULL) ||
- (z_neg_file == NULL) )
- {
- result_string_pointer = "Invalid cube map files list";
- return 0;
- }
- /* capability checking */
- if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
- {
- result_string_pointer = "No cube map capability present";
- return 0;
- }
- /* 1st face: try to load the image */
- img = SOIL_load_image( x_pos_file, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, and create a texture ID if necessary */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- reuse_texture_ID, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_X,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image( x_neg_file, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image( y_pos_file, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image( y_neg_file, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image( z_pos_file, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image( z_neg_file, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* and return the handle, such as it is */
- return tex_id;
- }
- unsigned int
- SOIL_load_OGL_cubemap_from_memory
- (
- const unsigned char *const x_pos_buffer,
- int x_pos_buffer_length,
- const unsigned char *const x_neg_buffer,
- int x_neg_buffer_length,
- const unsigned char *const y_pos_buffer,
- int y_pos_buffer_length,
- const unsigned char *const y_neg_buffer,
- int y_neg_buffer_length,
- const unsigned char *const z_pos_buffer,
- int z_pos_buffer_length,
- const unsigned char *const z_neg_buffer,
- int z_neg_buffer_length,
- int force_channels,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels;
- unsigned int tex_id;
- /* error checking */
- if( (x_pos_buffer == NULL) ||
- (x_neg_buffer == NULL) ||
- (y_pos_buffer == NULL) ||
- (y_neg_buffer == NULL) ||
- (z_pos_buffer == NULL) ||
- (z_neg_buffer == NULL) )
- {
- result_string_pointer = "Invalid cube map buffers list";
- return 0;
- }
- /* capability checking */
- if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
- {
- result_string_pointer = "No cube map capability present";
- return 0;
- }
- /* 1st face: try to load the image */
- img = SOIL_load_image_from_memory(
- x_pos_buffer, x_pos_buffer_length,
- &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, and create a texture ID if necessary */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- reuse_texture_ID, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_X,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image_from_memory(
- x_neg_buffer, x_neg_buffer_length,
- &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image_from_memory(
- y_pos_buffer, y_pos_buffer_length,
- &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image_from_memory(
- y_neg_buffer, y_neg_buffer_length,
- &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image_from_memory(
- z_pos_buffer, z_pos_buffer_length,
- &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* continue? */
- if( tex_id != 0 )
- {
- /* 1st face: try to load the image */
- img = SOIL_load_image_from_memory(
- z_neg_buffer, z_neg_buffer_length,
- &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* upload the texture, but reuse the assigned texture ID */
- tex_id = SOIL_internal_create_OGL_texture(
- img, width, height, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- /* and nuke the image data */
- SOIL_free_image_data( img );
- }
- /* and return the handle, such as it is */
- return tex_id;
- }
- unsigned int
- SOIL_load_OGL_single_cubemap
- (
- const char *filename,
- const char face_order[6],
- int force_channels,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels, i;
- unsigned int tex_id = 0;
- /* error checking */
- if( filename == NULL )
- {
- result_string_pointer = "Invalid single cube map file name";
- return 0;
- }
- /* does the user want direct uploading of the image as a DDS file? */
- if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
- {
- /* 1st try direct loading of the image as a DDS file
- note: direct uploading will only load what is in the
- DDS file, no MIPmaps will be generated, the image will
- not be flipped, etc. */
- tex_id = SOIL_direct_load_DDS( filename, reuse_texture_ID, flags, 1 );
- if( tex_id )
- {
- /* hey, it worked!! */
- return tex_id;
- }
- }
- /* face order checking */
- for( i = 0; i < 6; ++i )
- {
- if( (face_order[i] != 'N') &&
- (face_order[i] != 'S') &&
- (face_order[i] != 'W') &&
- (face_order[i] != 'E') &&
- (face_order[i] != 'U') &&
- (face_order[i] != 'D') )
- {
- result_string_pointer = "Invalid single cube map face order";
- return 0;
- };
- }
- /* capability checking */
- if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
- {
- result_string_pointer = "No cube map capability present";
- return 0;
- }
- /* 1st off, try to load the full image */
- img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* now, does this image have the right dimensions? */
- if( (width != 6*height) &&
- (6*width != height) )
- {
- SOIL_free_image_data( img );
- result_string_pointer = "Single cubemap image must have a 6:1 ratio";
- return 0;
- }
- /* try the image split and create */
- tex_id = SOIL_create_OGL_single_cubemap(
- img, width, height, channels,
- face_order, reuse_texture_ID, flags
- );
- /* nuke the temporary image data and return the texture handle */
- SOIL_free_image_data( img );
- return tex_id;
- }
- unsigned int
- SOIL_load_OGL_single_cubemap_from_memory
- (
- const unsigned char *const buffer,
- int buffer_length,
- const char face_order[6],
- int force_channels,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* img;
- int width, height, channels, i;
- unsigned int tex_id = 0;
- /* error checking */
- if( buffer == NULL )
- {
- result_string_pointer = "Invalid single cube map buffer";
- return 0;
- }
- /* does the user want direct uploading of the image as a DDS file? */
- if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
- {
- /* 1st try direct loading of the image as a DDS file
- note: direct uploading will only load what is in the
- DDS file, no MIPmaps will be generated, the image will
- not be flipped, etc. */
- tex_id = SOIL_direct_load_DDS_from_memory(
- buffer, buffer_length,
- reuse_texture_ID, flags, 1 );
- if( tex_id )
- {
- /* hey, it worked!! */
- return tex_id;
- }
- }
- /* face order checking */
- for( i = 0; i < 6; ++i )
- {
- if( (face_order[i] != 'N') &&
- (face_order[i] != 'S') &&
- (face_order[i] != 'W') &&
- (face_order[i] != 'E') &&
- (face_order[i] != 'U') &&
- (face_order[i] != 'D') )
- {
- result_string_pointer = "Invalid single cube map face order";
- return 0;
- };
- }
- /* capability checking */
- if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
- {
- result_string_pointer = "No cube map capability present";
- return 0;
- }
- /* 1st off, try to load the full image */
- img = SOIL_load_image_from_memory(
- buffer, buffer_length,
- &width, &height, &channels,
- force_channels );
- /* channels holds the original number of channels, which may have been forced */
- if( (force_channels >= 1) && (force_channels <= 4) )
- {
- channels = force_channels;
- }
- if( NULL == img )
- {
- /* image loading failed */
- result_string_pointer = stbi_failure_reason();
- return 0;
- }
- /* now, does this image have the right dimensions? */
- if( (width != 6*height) &&
- (6*width != height) )
- {
- SOIL_free_image_data( img );
- result_string_pointer = "Single cubemap image must have a 6:1 ratio";
- return 0;
- }
- /* try the image split and create */
- tex_id = SOIL_create_OGL_single_cubemap(
- img, width, height, channels,
- face_order, reuse_texture_ID, flags
- );
- /* nuke the temporary image data and return the texture handle */
- SOIL_free_image_data( img );
- return tex_id;
- }
- unsigned int
- SOIL_create_OGL_single_cubemap
- (
- const unsigned char *const data,
- int width, int height, int channels,
- const char face_order[6],
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* variables */
- unsigned char* sub_img;
- int dw, dh, sz, i;
- unsigned int tex_id;
- /* error checking */
- if( data == NULL )
- {
- result_string_pointer = "Invalid single cube map image data";
- return 0;
- }
- /* face order checking */
- for( i = 0; i < 6; ++i )
- {
- if( (face_order[i] != 'N') &&
- (face_order[i] != 'S') &&
- (face_order[i] != 'W') &&
- (face_order[i] != 'E') &&
- (face_order[i] != 'U') &&
- (face_order[i] != 'D') )
- {
- result_string_pointer = "Invalid single cube map face order";
- return 0;
- };
- }
- /* capability checking */
- if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
- {
- result_string_pointer = "No cube map capability present";
- return 0;
- }
- /* now, does this image have the right dimensions? */
- if( (width != 6*height) &&
- (6*width != height) )
- {
- result_string_pointer = "Single cubemap image must have a 6:1 ratio";
- return 0;
- }
- /* which way am I stepping? */
- if( width > height )
- {
- dw = height;
- dh = 0;
- } else
- {
- dw = 0;
- dh = width;
- }
- sz = dw+dh;
- sub_img = (unsigned char *)malloc( sz*sz*channels );
- /* do the splitting and uploading */
- tex_id = reuse_texture_ID;
- for( i = 0; i < 6; ++i )
- {
- int x, y, idx = 0;
- unsigned int cubemap_target = 0;
- /* copy in the sub-image */
- for( y = i*dh; y < i*dh+sz; ++y )
- {
- for( x = i*dw*channels; x < (i*dw+sz)*channels; ++x )
- {
- sub_img[idx++] = data[y*width*channels+x];
- }
- }
- /* what is my texture target?
- remember, this coordinate system is
- LHS if viewed from inside the cube! */
- switch( face_order[i] )
- {
- case 'N':
- cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z;
- break;
- case 'S':
- cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
- break;
- case 'W':
- cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X;
- break;
- case 'E':
- cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_X;
- break;
- case 'U':
- cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y;
- break;
- case 'D':
- cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
- break;
- }
- /* upload it as a texture */
- tex_id = SOIL_internal_create_OGL_texture(
- sub_img, sz, sz, channels,
- tex_id, flags,
- SOIL_TEXTURE_CUBE_MAP,
- cubemap_target,
- SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
- }
- /* and nuke the image and sub-image data */
- SOIL_free_image_data( sub_img );
- /* and return the handle, such as it is */
- return tex_id;
- }
- unsigned int
- SOIL_create_OGL_texture
- (
- const unsigned char *const data,
- int width, int height, int channels,
- unsigned int reuse_texture_ID,
- unsigned int flags
- )
- {
- /* wrapper function for 2D textures */
- return SOIL_internal_create_OGL_texture(
- data, width, height, channels,
- reuse_texture_ID, flags,
- GL_TEXTURE_2D, GL_TEXTURE_2D,
- GL_MAX_TEXTURE_SIZE );
- }
- #if SOIL_CHECK_FOR_GL_ERRORS
- void check_for_GL_errors( const char *calling_location )
- {
- /* check for errors */
- GLenum err_code = GL_REPORT_ERROR();
- while( GL_NO_ERROR != err_code )
- {
- printf( "OpenGL Error @ %s: %i", calling_location, err_code );
- err_code = GL_REPORT_ERROR();
- }
- }
- #else
- void check_for_GL_errors( const char *calling_location )
- {
- /* no check for errors */
- }
- #endif
- unsigned int
- SOIL_internal_create_OGL_texture
- (
- const unsigned char *const data,
- int width, int height, int channels,
- unsigned int reuse_texture_ID,
- unsigned int flags,
- unsigned int opengl_texture_type,
- unsigned int opengl_texture_target,
- unsigned int texture_check_size_enum
- )
- {
- /* variables */
- unsigned char* img;
- unsigned int tex_id;
- unsigned int internal_texture_format = 0, original_texture_format = 0;
- int DXT_mode = SOIL_CAPABILITY_UNKNOWN;
- int max_supported_size;
- /* If the user wants to use the texture rectangle I kill a few flags */
- if( flags & SOIL_FLAG_TEXTURE_RECTANGLE )
- {
- /* well, the user asked for it, can we do that? */
- if( query_tex_rectangle_capability() == SOIL_CAPABILITY_PRESENT )
- {
- /* only allow this if the user in _NOT_ trying to do a cubemap! */
- if( opengl_texture_type == GL_TEXTURE_2D )
- {
- /* clean out the flags that cannot be used with texture rectangles */
- flags &= ~(
- SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS |
- SOIL_FLAG_TEXTURE_REPEATS
- );
- /* and change my target */
- opengl_texture_target = SOIL_TEXTURE_RECTANGLE_ARB;
- opengl_texture_type = SOIL_TEXTURE_RECTANGLE_ARB;
- } else
- {
- /* not allowed for any other uses (yes, I'm looking at you, cubemaps!) */
- flags &= ~SOIL_FLAG_TEXTURE_RECTANGLE;
- }
- } else
- {
- /* can't do it, and that is a breakable offense (uv coords use pixels instead of [0,1]!) */
- result_string_pointer = "Texture Rectangle extension unsupported";
- return 0;
- }
- }
- /* create a copy the image data */
- img = (unsigned char*)malloc( width*height*channels );
- memcpy( img, data, width*height*channels );
- /* does the user want me to invert the image? */
- if( flags & SOIL_FLAG_INVERT_Y )
- {
- int i, j;
- for( j = 0; j*2 < height; ++j )
- {
- int index1 = j * width * channels;
- int index2 = (height - 1 - j) * width * channels;
- for( i = width * channels; i > 0; --i )
- {
- unsigned char temp = img[index1];
- img[index1] = img[index2];
- img[index2] = temp;
- ++index1;
- ++index2;
- }
- }
- }
- /* does the user want me to scale the colors into the NTSC safe RGB range? */
- if( flags & SOIL_FLAG_NTSC_SAFE_RGB )
- {
- scale_image_RGB_to_NTSC_safe( img, width, height, channels );
- }
- /* does the user want me to convert from straight to pre-multiplied alpha?
- (and do we even _have_ alpha?) */
- if( flags & SOIL_FLAG_MULTIPLY_ALPHA )
- {
- int i;
- switch( channels )
- {
- case 2:
- for( i = 0; i < 2*width*height; i += 2 )
- {
- img[i] = (img[i] * img[i+1] + 128) >> 8;
- }
- break;
- case 4:
- for( i = 0; i < 4*width*height; i += 4 )
- {
- img[i+0] = (img[i+0] * img[i+3] + 128) >> 8;
- img[i+1] = (img[i+1] * img[i+3] + 128) >> 8;
- img[i+2] = (img[i+2] * img[i+3] + 128) >> 8;
- }
- break;
- default:
- /* no other number of channels contains alpha data */
- break;
- }
- }
- /* if the user can't support NPOT textures, make sure we force the POT option */
- if( (query_NPOT_capability() == SOIL_CAPABILITY_NONE) &&
- !(flags & SOIL_FLAG_TEXTURE_RECTANGLE) )
- {
- /* add in the POT flag */
- flags |= SOIL_FLAG_POWER_OF_TWO;
- }
- /* how large of a texture can this OpenGL implementation handle? */
- /* texture_check_size_enum will be GL_MAX_TEXTURE_SIZE or SOIL_MAX_CUBE_MAP_TEXTURE_SIZE */
- glGetIntegerv( texture_check_size_enum, &max_supported_size );
- /* do I need to make it a power of 2? */
- if(
- (flags & SOIL_FLAG_POWER_OF_TWO) || /* user asked for it */
- (flags & SOIL_FLAG_MIPMAPS) || /* need it for the MIP-maps */
- (width > max_supported_size) || /* it's too big, (make sure it's */
- (height > max_supported_size) ) /* 2^n for later down-sampling) */
- {
- int new_width = 1;
- int new_height = 1;
- while( new_width < width )
- {
- new_width *= 2;
- }
- while( new_height < height )
- {
- new_height *= 2;
- }
- /* still? */
- if( (new_width != width) || (new_height != height) )
- {
- /* yep, resize */
- unsigned char *resampled = (unsigned char*)malloc( channels*new_width*new_height );
- up_scale_image(
- img, width, height, channels,
- resampled, new_width, new_height );
- /* OJO this is for debug only! */
- /*
- SOIL_save_image( "\\showme.bmp", SOIL_SAVE_TYPE_BMP,
- new_width, new_height, channels,
- resampled );
- */
- /* nuke the old guy, then point it at the new guy */
- SOIL_free_image_data( img );
- img = resampled;
- width = new_width;
- height = new_height;
- }
- }
- /* now, if it is too large... */
- if( (width > max_supported_size) || (height > max_supported_size) )
- {
- /* I've already made it a power of two, so simply use the MIPmapping
- code to reduce its size to the allowable maximum. */
- unsigned char *resampled;
- int reduce_block_x = 1, reduce_block_y = 1;
- int new_width, new_height;
- if( width > max_supported_size )
- {
- reduce_block_x = width / max_supported_size;
- }
- if( height > max_supported_size )
- {
- reduce_block_y = height / max_supported_size;
- }
- new_width = width / reduce_block_x;
- new_height = height / reduce_block_y;
- resampled = (unsigned char*)malloc( channels*new_width*new_height );
- /* perform the actual reduction */
- mipmap_image( img, width, height, channels,
- resampled, reduce_block_x, reduce_block_y );
- /* nuke the old guy, then point it at the new guy */
- SOIL_free_image_data( img );
- img = resampled;
- width = new_width;
- height = new_height;
- }
- /* does the user want us to use YCoCg color space? */
- if( flags & SOIL_FLAG_CoCg_Y )
- {
- /* this will only work with RGB and RGBA images */
- convert_RGB_to_YCoCg( img, width, height, channels );
- /*
- save_image_as_DDS( "CoCg_Y.dds", width, height, channels, img );
- */
- }
- /* create the OpenGL texture ID handle
- (note: allowing a forced texture ID lets me reload a texture) */
- tex_id = reuse_texture_ID;
- if( tex_id == 0 )
- {
- glGenTextures( 1, &tex_id );
- }
- check_for_GL_errors( "glGenTextures" );
- /* Note: sometimes glGenTextures fails (usually no OpenGL context) */
- if( tex_id )
- {
- /* and what type am I using as the internal texture format? */
- switch( channels )
- {
- case 1:
- original_texture_format = GL_LUMINANCE;
- break;
- case 2:
- original_texture_format = GL_LUMINANCE_ALPHA;
- break;
- case 3:
- original_texture_format = GL_RGB;
- break;
- case 4:
- original_texture_format = GL_RGBA;
- break;
- }
- internal_texture_format = original_texture_format;
- /* does the user want me to, and can I, save as DXT? */
- if( flags & SOIL_FLAG_COMPRESS_TO_DXT )
- {
- DXT_mode = query_DXT_capability();
- if( DXT_mode == SOIL_CAPABILITY_PRESENT )
- {
- /* I can use DXT, whether I compress it or OpenGL does */
- if( (channels & 1) == 1 )
- {
- /* 1 or 3 channels = DXT1 */
- internal_texture_format = SOIL_RGB_S3TC_DXT1;
- } else
- {
- /* 2 or 4 channels = DXT5 */
- internal_texture_format = SOIL_RGBA_S3TC_DXT5;
- }
- }
- }
- /* bind an OpenGL texture ID */
- glBindTexture( opengl_texture_type, tex_id );
- check_for_GL_errors( "glBindTexture" );
- /* upload the main image */
- if( DXT_mode == SOIL_CAPABILITY_PRESENT )
- {
- /* user wants me to do the DXT conversion! */
- int DDS_size;
- unsigned char *DDS_data = NULL;
- if( (channels & 1) == 1 )
- {
- /* RGB, use DXT1 */
- DDS_data = convert_image_to_DXT1( img, width, height, channels, &DDS_size );
- } else
- {
- /* RGBA, use DXT5 */
- DDS_data = convert_image_to_DXT5( img, width, height, channels, &DDS_size );
- }
- if( DDS_data )
- {
- soilGlCompressedTexImage2D(
- opengl_texture_target, 0,
- internal_texture_format, width, height, 0,
- DDS_size, DDS_data );
- check_for_GL_errors( "glCompressedTexImage2D" );
- SOIL_free_image_data( DDS_data );
- /* printf( "Internal DXT compressor\n" ); */
- } else
- {
- /* my compression failed, try the OpenGL driver's version */
- glTexImage2D(
- opengl_texture_target, 0,
- internal_texture_format, width, height, 0,
- original_texture_format, GL_UNSIGNED_BYTE, img );
- check_for_GL_errors( "glTexImage2D" );
- /* printf( "OpenGL DXT compressor\n" ); */
- }
- } else
- {
- /* user want OpenGL to do all the work! */
- glTexImage2D(
- opengl_texture_target, 0,
- internal_texture_format, width, height, 0,
- original_texture_format, GL_UNSIGNED_BYTE, img );
- check_for_GL_errors( "glTexImage2D" );
- /*printf( "OpenGL DXT compressor\n" ); */
- }
- /* are any MIPmaps desired? */
- if( flags & SOIL_FLAG_MIPMAPS )
- {
- int MIPlevel = 1;
- int MIPwidth = (width+1) / 2;
- int MIPheight = (height+1) / 2;
- unsigned char *resampled = (unsigned char*)malloc( channels*MIPwidth*MIPheight );
- while( ((1<<MIPlevel) <= width) || ((1<<MIPlevel) <= height) )
- {
- /* do this MIPmap level */
- mipmap_image(
- img, width, height, channels,
- resampled,
- (1 << MIPlevel), (1 << MIPlevel) );
- /* upload the MIPmaps */
- if( DXT_mode == SOIL_CAPABILITY_PRESENT )
- {
- /* user wants me to do the DXT conversion! */
- int DDS_size;
- unsigned char *DDS_data = NULL;
- if( (channels & 1) == 1 )
- {
- /* RGB, use DXT1 */
- DDS_data = convert_image_to_DXT1(
- resampled, MIPwidth, MIPheight, channels, &DDS_size );
- } else
- {
- /* RGBA, use DXT5 */
- DDS_data = convert_image_to_DXT5(
- resampled, MIPwidth, MIPheight, channels, &DDS_size );
- }
- if( DDS_data )
- {
- soilGlCompressedTexImage2D(
- opengl_texture_target, MIPlevel,
- internal_texture_format, MIPwidth, MIPheight, 0,
- DDS_size, DDS_data );
- check_for_GL_errors( "glCompressedTexImage2D" );
- SOIL_free_image_data( DDS_data );
- } else
- {
- /* my compression failed, try the OpenGL driver's version */
- glTexImage2D(
- opengl_texture_target, MIPlevel,
- internal_texture_format, MIPwidth, MIPheight, 0,
- original_texture_format, GL_UNSIGNED_BYTE, resampled );
- check_for_GL_errors( "glTexImage2D" );
- }
- } else
- {
- /* user want OpenGL to do all the work! */
- glTexImage2D(
- opengl_texture_target, MIPlevel,
- internal_texture_format, MIPwidth, MIPheight, 0,
- original_texture_format, GL_UNSIGNED_BYTE, resampled );
- check_for_GL_errors( "glTexImage2D" );
- }
- /* prep for the next level */
- ++MIPlevel;
- MIPwidth = (MIPwidth + 1) / 2;
- MIPheight = (MIPheight + 1) / 2;
- }
- SOIL_free_image_data( resampled );
- /* instruct OpenGL to use the MIPmaps */
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
- check_for_GL_errors( "GL_TEXTURE_MIN/MAG_FILTER" );
- } else
- {
- /* instruct OpenGL _NOT_ to use the MIPmaps */
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- check_for_GL_errors( "GL_TEXTURE_MIN/MAG_FILTER" );
- }
- /* does the user want clamping, or wrapping? */
- if( flags & SOIL_FLAG_TEXTURE_REPEATS )
- {
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT );
- if( opengl_texture_type == SOIL_TEXTURE_CUBE_MAP )
- {
- /* SOIL_TEXTURE_WRAP_R is invalid if cubemaps aren't supported */
- glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, GL_REPEAT );
- }
- check_for_GL_errors( "GL_TEXTURE_WRAP_*" );
- } else
- {
- /* unsigned int clamp_mode = SOIL_CLAMP_TO_EDGE; */
- unsigned int clamp_mode = GL_CLAMP;
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, clamp_mode );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, clamp_mode );
- if( opengl_texture_type == SOIL_TEXTURE_CUBE_MAP )
- {
- /* SOIL_TEXTURE_WRAP_R is invalid if cubemaps aren't supported */
- glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, clamp_mode );
- }
- check_for_GL_errors( "GL_TEXTURE_WRAP_*" );
- }
- /* done */
- result_string_pointer = "Image loaded as an OpenGL texture";
- } else
- {
- /* failed */
- result_string_pointer = "Failed to generate an OpenGL texture name; missing OpenGL context?";
- }
- SOIL_free_image_data( img );
- return tex_id;
- }
- int
- SOIL_save_screenshot
- (
- const char *filename,
- int image_type,
- int x, int y,
- int width, int height
- )
- {
- unsigned char *pixel_data;
- int i, j;
- int save_result;
- /* error checks */
- if( (width < 1) || (height < 1) )
- {
- result_string_pointer = "Invalid screenshot dimensions";
- return 0;
- }
- if( (x < 0) || (y < 0) )
- {
- result_string_pointer = "Invalid screenshot location";
- return 0;
- }
- if( filename == NULL )
- {
- result_string_pointer = "Invalid screenshot filename";
- return 0;
- }
- /* Get the data from OpenGL */
- pixel_data = (unsigned char*)malloc( 3*width*height );
- glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixel_data);
- /* invert the image */
- for( j = 0; j*2 < height; ++j )
- {
- int index1 = j * width * 3;
- int index2 = (height - 1 - j) * width * 3;
- for( i = width * 3; i > 0; --i )
- {
- unsigned char temp = pixel_data[index1];
- pixel_data[index1] = pixel_data[index2];
- pixel_data[index2] = temp;
- ++index1;
- ++index2;
- }
- }
- /* save the image */
- save_result = SOIL_save_image( filename, image_type, width, height, 3, pixel_data);
- /* And free the memory */
- SOIL_free_image_data( pixel_data );
- return save_result;
- }
- #endif
- unsigned char *
- SOIL_load_image
- (
- const char *filename,
- int *width, int *height, int *channels,
- int force_channels
- )
- {
- stbi_uc *result = stbi_load( filename,
- width, height, channels, force_channels );
- if( result == NULL )
- {
- result_string_pointer = stbi_failure_reason();
- } else
- {
- result_string_pointer = "Image loaded";
- }
- return result;
- }
- unsigned char *
- SOIL_load_image_from_memory
- (
- const unsigned char *const buffer,
- int buffer_length,
- int *width, int *height, int *channels,
- int force_channels
- )
- {
- stbi_uc *result = stbi_load_from_memory(
- buffer, buffer_length,
- width, height, channels,
- force_channels );
- if( result == NULL )
- {
- result_string_pointer = stbi_failure_reason();
- } else
- {
- result_string_pointer = "Image loaded from memory";
- }
- return result;
- }
- int
- SOIL_save_image
- (
- const char *filename,
- int image_type,
- int width, int height, int channels,
- const unsigned char *const data
- )
- {
- int save_result;
- /* error check */
- if( (width < 1) || (height < 1) ||
- (channels < 1) || (channels > 4) ||
- (data == NULL) ||
- (filename == NULL) )
- {
- return 0;
- }
- if( image_type == SOIL_SAVE_TYPE_BMP )
- {
- save_result = stbi_write_bmp( filename,
- width, height, channels, (void*)data );
- } else
- if( image_type == SOIL_SAVE_TYPE_TGA )
- {
- save_result = stbi_write_tga( filename,
- width, height, channels, (void*)data );
- } else
- if( image_type == SOIL_SAVE_TYPE_DDS )
- {
- save_result = save_image_as_DDS( filename,
- width, height, channels, (const unsigned char *const)data );
- } else
- {
- save_result = 0;
- }
- if( save_result == 0 )
- {
- result_string_pointer = "Saving the image failed";
- } else
- {
- result_string_pointer = "Image saved";
- }
- return save_result;
- }
- void
- SOIL_free_image_data
- (
- unsigned char *img_data
- )
- {
- free( (void*)img_data );
- }
- const char*
- SOIL_last_result
- (
- void
- )
- {
- return result_string_pointer;
- }
- #if 0
- unsigned int SOIL_direct_load_DDS_from_memory(
- const unsigned char *const buffer,
- int buffer_length,
- unsigned int reuse_texture_ID,
- int flags,
- int loading_as_cubemap )
- {
- /* variables */
- DDS_header header;
- unsigned int buffer_index = 0;
- unsigned int tex_ID = 0;
- /* file reading variables */
- unsigned int S3TC_type = 0;
- unsigned char *DDS_data;
- unsigned int DDS_main_size;
- unsigned int DDS_full_size;
- unsigned int width, height;
- int mipmaps, cubemap, uncompressed, block_size = 16;
- unsigned int flag;
- unsigned int cf_target, ogl_target_start, ogl_target_end;
- unsigned int opengl_texture_type;
- int i;
- /* 1st off, does the filename even exist? */
- if( NULL == buffer )
- {
- /* we can't do it! */
- result_string_pointer = "NULL buffer";
- return 0;
- }
- if( buffer_length < sizeof( DDS_header ) )
- {
- /* we can't do it! */
- result_string_pointer = "DDS file was too small to contain the DDS header";
- return 0;
- }
- /* try reading in the header */
- memcpy ( (void*)(&header), (const void *)buffer, sizeof( DDS_header ) );
- buffer_index = sizeof( DDS_header );
- /* guilty until proven innocent */
- result_string_pointer = "Failed to read a known DDS header";
- /* validate the header (warning, "goto"'s ahead, shield your eyes!!) */
- flag = ('D'<<0)|('D'<<8)|('S'<<16)|(' '<<24);
- if( header.dwMagic != flag ) {goto quick_exit;}
- if( header.dwSize != 124 ) {goto quick_exit;}
- /* I need all of these */
- flag = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
- if( (header.dwFlags & flag) != flag ) {goto quick_exit;}
- /* According to the MSDN spec, the dwFlags should contain
- DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
- uncompressed. Some DDS writers do not conform to the
- spec, so I need to make my reader more tolerant */
- /* I need one of these */
- flag = DDPF_FOURCC | DDPF_RGB;
- if( (header.sPixelFormat.dwFlags & flag) == 0 ) {goto quick_exit;}
- if( header.sPixelFormat.dwSize != 32 ) {goto quick_exit;}
- if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) {goto quick_exit;}
- /* make sure it is a type we can upload */
- if( (header.sPixelFormat.dwFlags & DDPF_FOURCC) &&
- !(
- (header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) ||
- (header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('3'<<24))) ||
- (header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('5'<<24)))
- ) )
- {
- goto quick_exit;
- }
- /* OK, validated the header, let's load the image data */
- result_string_pointer = "DDS header loaded and validated";
- width = header.dwWidth;
- height = header.dwHeight;
- uncompressed = 1 - (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
- cubemap = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
- if( uncompressed )
- {
- S3TC_type = GL_RGB;
- block_size = 3;
- if( header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS )
- {
- S3TC_type = GL_RGBA;
- block_size = 4;
- }
- DDS_main_size = width * height * block_size;
- } else
- {
- /* can we even handle direct uploading to OpenGL DXT compressed images? */
- if( query_DXT_capability() != SOIL_CAPABILITY_PRESENT )
- {
- /* we can't do it! */
- result_string_pointer = "Direct upload of S3TC images not supported by the OpenGL driver";
- return 0;
- }
- /* well, we know it is DXT1/3/5, because we checked above */
- switch( (header.sPixelFormat.dwFourCC >> 24) - '0' )
- {
- case 1:
- S3TC_type = SOIL_RGBA_S3TC_DXT1;
- block_size = 8;
- break;
- case 3:
- S3TC_type = SOIL_RGBA_S3TC_DXT3;
- block_size = 16;
- break;
- case 5:
- S3TC_type = SOIL_RGBA_S3TC_DXT5;
- block_size = 16;
- break;
- }
- DDS_main_size = ((width+3)>>2)*((height+3)>>2)*block_size;
- }
- if( cubemap )
- {
- /* does the user want a cubemap? */
- if( !loading_as_cubemap )
- {
- /* we can't do it! */
- result_string_pointer = "DDS image was a cubemap";
- return 0;
- }
- /* can we even handle cubemaps with the OpenGL driver? */
- if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
- {
- /* we can't do it! */
- result_string_pointer = "Direct upload of cubemap images not supported by the OpenGL driver";
- return 0;
- }
- ogl_target_start = SOIL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ogl_target_end = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
- opengl_texture_type = SOIL_TEXTURE_CUBE_MAP;
- } else
- {
- /* does the user want a non-cubemap? */
- if( loading_as_cubemap )
- {
- /* we can't do it! */
- result_string_pointer = "DDS image was not a cubemap";
- return 0;
- }
- ogl_target_start = GL_TEXTURE_2D;
- ogl_target_end = GL_TEXTURE_2D;
- opengl_texture_type = GL_TEXTURE_2D;
- }
- if( (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1) )
- {
- int shift_offset;
- mipmaps = header.dwMipMapCount - 1;
- DDS_full_size = DDS_main_size;
- if( uncompressed )
- {
- /* uncompressed DDS, simple MIPmap size calculation */
- shift_offset = 0;
- } else
- {
- /* compressed DDS, MIPmap size calculation is block based */
- shift_offset = 2;
- }
- for( i = 1; i <= mipmaps; ++ i )
- {
- int w, h;
- w = width >> (shift_offset + i);
- h = height >> (shift_offset + i);
- if( w < 1 )
- {
- w = 1;
- }
- if( h < 1 )
- {
- h = 1;
- }
- DDS_full_size += w*h*block_size;
- }
- } else
- {
- mipmaps = 0;
- DDS_full_size = DDS_main_size;
- }
- DDS_data = (unsigned char*)malloc( DDS_full_size );
- /* got the image data RAM, create or use an existing OpenGL texture handle */
- tex_ID = reuse_texture_ID;
- if( tex_ID == 0 )
- {
- glGenTextures( 1, &tex_ID );
- }
- /* bind an OpenGL texture ID */
- glBindTexture( opengl_texture_type, tex_ID );
- /* do this for each face of the cubemap! */
- for( cf_target = ogl_target_start; cf_target <= ogl_target_end; ++cf_target )
- {
- if( buffer_index + DDS_full_size <= buffer_length )
- {
- unsigned int byte_offset = DDS_main_size;
- memcpy( (void*)DDS_data, (const void*)(&buffer[buffer_index]), DDS_full_size );
- buffer_index += DDS_full_size;
- /* upload the main chunk */
- if( uncompressed )
- {
- /* and remember, DXT uncompressed uses BGR(A),
- so swap to RGB(A) for ALL MIPmap levels */
- for( i = 0; i < DDS_full_size; i += block_size )
- {
- unsigned char temp = DDS_data[i];
- DDS_data[i] = DDS_data[i+2];
- DDS_data[i+2] = temp;
- }
- glTexImage2D(
- cf_target, 0,
- S3TC_type, width, height, 0,
- S3TC_type, GL_UNSIGNED_BYTE, DDS_data );
- } else
- {
- soilGlCompressedTexImage2D(
- cf_target, 0,
- S3TC_type, width, height, 0,
- DDS_main_size, DDS_data );
- }
- /* upload the mipmaps, if we have them */
- for( i = 1; i <= mipmaps; ++i )
- {
- int w, h, mip_size;
- w = width >> i;
- h = height >> i;
- if( w < 1 )
- {
- w = 1;
- }
- if( h < 1 )
- {
- h = 1;
- }
- /* upload this mipmap */
- if( uncompressed )
- {
- mip_size = w*h*block_size;
- glTexImage2D(
- cf_target, i,
- S3TC_type, w, h, 0,
- S3TC_type, GL_UNSIGNED_BYTE, &DDS_data[byte_offset] );
- } else
- {
- mip_size = ((w+3)/4)*((h+3)/4)*block_size;
- soilGlCompressedTexImage2D(
- cf_target, i,
- S3TC_type, w, h, 0,
- mip_size, &DDS_data[byte_offset] );
- }
- /* and move to the next mipmap */
- byte_offset += mip_size;
- }
- /* it worked! */
- result_string_pointer = "DDS file loaded";
- } else
- {
- glDeleteTextures( 1, & tex_ID );
- tex_ID = 0;
- cf_target = ogl_target_end + 1;
- result_string_pointer = "DDS file was too small for expected image data";
- }
- }/* end reading each face */
- SOIL_free_image_data( DDS_data );
- if( tex_ID )
- {
- /* did I have MIPmaps? */
- if( mipmaps > 0 )
- {
- /* instruct OpenGL to use the MIPmaps */
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
- } else
- {
- /* instruct OpenGL _NOT_ to use the MIPmaps */
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- }
- /* does the user want clamping, or wrapping? */
- if( flags & SOIL_FLAG_TEXTURE_REPEATS )
- {
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT );
- glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, GL_REPEAT );
- } else
- {
- /* unsigned int clamp_mode = SOIL_CLAMP_TO_EDGE; */
- unsigned int clamp_mode = GL_CLAMP;
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, clamp_mode );
- glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, clamp_mode );
- glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, clamp_mode );
- }
- }
- quick_exit:
- /* report success or failure */
- return tex_ID;
- }
- unsigned int SOIL_direct_load_DDS(
- const char *filename,
- unsigned int reuse_texture_ID,
- int flags,
- int loading_as_cubemap )
- {
- FILE *f;
- unsigned char *buffer;
- size_t buffer_length, bytes_read;
- unsigned int tex_ID = 0;
- /* error checks */
- if( NULL == filename )
- {
- result_string_pointer = "NULL filename";
- return 0;
- }
- f = fopen( filename, "rb" );
- if( NULL == f )
- {
- /* the file doesn't seem to exist (or be open-able) */
- result_string_pointer = "Can not find DDS file";
- return 0;
- }
- fseek( f, 0, SEEK_END );
- buffer_length = ftell( f );
- fseek( f, 0, SEEK_SET );
- buffer = (unsigned char *) malloc( buffer_length );
- if( NULL == buffer )
- {
- result_string_pointer = "malloc failed";
- fclose( f );
- return 0;
- }
- bytes_read = fread( (void*)buffer, 1, buffer_length, f );
- fclose( f );
- if( bytes_read < buffer_length )
- {
- /* huh? */
- buffer_length = bytes_read;
- }
- /* now try to do the loading */
- tex_ID = SOIL_direct_load_DDS_from_memory(
- (const unsigned char *const)buffer, buffer_length,
- reuse_texture_ID, flags, loading_as_cubemap );
- SOIL_free_image_data( buffer );
- return tex_ID;
- }
- int query_NPOT_capability( void )
- {
- /* check for the capability */
- if( has_NPOT_capability == SOIL_CAPABILITY_UNKNOWN )
- {
- /* we haven't yet checked for the capability, do so */
- if(
- (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
- "GL_ARB_texture_non_power_of_two" ) )
- )
- {
- /* not there, flag the failure */
- has_NPOT_capability = SOIL_CAPABILITY_NONE;
- } else
- {
- /* it's there! */
- has_NPOT_capability = SOIL_CAPABILITY_PRESENT;
- }
- }
- /* let the user know if we can do non-power-of-two textures or not */
- return has_NPOT_capability;
- }
- int query_tex_rectangle_capability( void )
- {
- /* check for the capability */
- if( has_tex_rectangle_capability == SOIL_CAPABILITY_UNKNOWN )
- {
- /* we haven't yet checked for the capability, do so */
- if(
- (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
- "GL_ARB_texture_rectangle" ) )
- &&
- (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
- "GL_EXT_texture_rectangle" ) )
- &&
- (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
- "GL_NV_texture_rectangle" ) )
- )
- {
- /* not there, flag the failure */
- has_tex_rectangle_capability = SOIL_CAPABILITY_NONE;
- } else
- {
- /* it's there! */
- has_tex_rectangle_capability = SOIL_CAPABILITY_PRESENT;
- }
- }
- /* let the user know if we can do texture rectangles or not */
- return has_tex_rectangle_capability;
- }
- int query_cubemap_capability( void )
- {
- /* check for the capability */
- if( has_cubemap_capability == SOIL_CAPABILITY_UNKNOWN )
- {
- /* we haven't yet checked for the capability, do so */
- if(
- (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
- "GL_ARB_texture_cube_map" ) )
- &&
- (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
- "GL_EXT_texture_cube_map" ) )
- )
- {
- /* not there, flag the failure */
- has_cubemap_capability = SOIL_CAPABILITY_NONE;
- } else
- {
- /* it's there! */
- has_cubemap_capability = SOIL_CAPABILITY_PRESENT;
- }
- }
- /* let the user know if we can do cubemaps or not */
- return has_cubemap_capability;
- }
- int query_DXT_capability( void )
- {
- /* check for the capability */
- if( has_DXT_capability == SOIL_CAPABILITY_UNKNOWN )
- {
- /* we haven't yet checked for the capability, do so */
- if( NULL == strstr(
- (char const*)glGetString( GL_EXTENSIONS ),
- "GL_EXT_texture_compression_s3tc" ) )
- {
- /* not there, flag the failure */
- has_DXT_capability = SOIL_CAPABILITY_NONE;
- } else
- {
- /* and find the address of the extension function */
- P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC ext_addr = NULL;
- #ifdef WIN32
- ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
- wglGetProcAddress
- (
- "glCompressedTexImage2DARB"
- );
- #elif defined(__APPLE__) || defined(__APPLE_CC__)
- /* I can't test this Apple stuff! */
- CFBundleRef bundle;
- CFURLRef bundleURL =
- CFURLCreateWithFileSystemPath(
- kCFAllocatorDefault,
- CFSTR("/System/Library/Frameworks/OpenGL.framework"),
- kCFURLPOSIXPathStyle,
- true );
- CFStringRef extensionName =
- CFStringCreateWithCString(
- kCFAllocatorDefault,
- "glCompressedTexImage2DARB",
- kCFStringEncodingASCII );
- bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
- assert( bundle != NULL );
- ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
- CFBundleGetFunctionPointerForName
- (
- bundle, extensionName
- );
- CFRelease( bundleURL );
- CFRelease( extensionName );
- CFRelease( bundle );
- #else
- ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
- glXGetProcAddressARB
- (
- (const GLubyte *)"glCompressedTexImage2DARB"
- );
- #endif
- /* Flag it so no checks needed later */
- if( NULL == ext_addr )
- {
- /* hmm, not good!! This should not happen, but does on my
- laptop's VIA chipset. The GL_EXT_texture_compression_s3tc
- spec requires that ARB_texture_compression be present too.
- this means I can upload and have the OpenGL drive do the
- conversion, but I can't use my own routines or load DDS files
- from disk and upload them directly [8^( */
- has_DXT_capability = SOIL_CAPABILITY_NONE;
- } else
- {
- /* all's well! */
- soilGlCompressedTexImage2D = ext_addr;
- has_DXT_capability = SOIL_CAPABILITY_PRESENT;
- }
- }
- }
- /* let the user know if we can do DXT or not */
- return has_DXT_capability;
- }
- #endif
|