From d0190af69feeedf802a1c885cc30fdc78d94866a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 22 May 2017 20:47:17 +0200 Subject: Renamed file (issues with Makefile) --- src/raylib_icon | Bin 107260 -> 0 bytes src/resources | Bin 0 -> 107260 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/raylib_icon create mode 100644 src/resources (limited to 'src') diff --git a/src/raylib_icon b/src/raylib_icon deleted file mode 100644 index 92ccf3a6..00000000 Binary files a/src/raylib_icon and /dev/null differ diff --git a/src/resources b/src/resources new file mode 100644 index 00000000..92ccf3a6 Binary files /dev/null and b/src/resources differ -- cgit v1.2.3 From f54501a355bea7bf6543c162da78761d8dc0a414 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 27 May 2017 14:40:05 +0200 Subject: Review gif recording (simplified) --- src/core.c | 9 +- src/external/gif.h | 282 +++++++++++++++++++++++++---------------------------- 2 files changed, 136 insertions(+), 155 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 07f3bb07..95f704d1 100644 --- a/src/core.c +++ b/src/core.c @@ -328,7 +328,6 @@ static char configFlags = 0; // Configuration flags (bit based) static bool showLogo = false; // Track if showing logo at init is enabled #if defined(SUPPORT_GIF_RECORDING) -static GifWriter gifWriter; static int gifFramesCounter = 0; static bool gifRecording = false; #endif @@ -538,7 +537,7 @@ void CloseWindow(void) #if defined(SUPPORT_GIF_RECORDING) if (gifRecording) { - GifEnd(&gifWriter); + GifEnd(); gifRecording = false; } #endif @@ -807,7 +806,7 @@ void EndDrawing(void) // Get image data for the current frame (from backbuffer) // NOTE: This process is very slow... :( unsigned char *screenData = rlglReadScreenPixels(screenWidth, screenHeight); - GifWriteFrame(&gifWriter, screenData, screenWidth, screenHeight, 10, 8, false); + GifWriteFrame(screenData, screenWidth, screenHeight, 10, 8, false); free(screenData); // Free image data } @@ -2454,7 +2453,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i { if (gifRecording) { - GifEnd(&gifWriter); + GifEnd(); gifRecording = false; TraceLog(INFO, "End animated GIF recording"); @@ -2466,7 +2465,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i // NOTE: delay represents the time between frames in the gif, if we capture a gif frame every // 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10. - GifBegin(&gifWriter, FormatText("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false); + GifBegin(FormatText("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false); screenshotCounter++; TraceLog(INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter)); diff --git a/src/external/gif.h b/src/external/gif.h index 1c0aeb18..c38cddb7 100644 --- a/src/external/gif.h +++ b/src/external/gif.h @@ -55,7 +55,6 @@ #define GIF_H #include // Required for: FILE -#include // Required for for integer typedefs //#define GIF_STATIC #ifdef GIF_STATIC @@ -68,33 +67,14 @@ #endif #endif -//---------------------------------------------------------------------------------- -// Defines and Macros -//---------------------------------------------------------------------------------- -//#define MAX_RESOURCES_SUPPORTED 256 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct GifWriter { - FILE *f; - uint8_t *oldImage; - bool firstFrame; -} GifWriter; - -//---------------------------------------------------------------------------------- -// Global variables -//---------------------------------------------------------------------------------- -//... - //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- // NOTE: By default use bitDepth = 8, dither = false -GIFDEF bool GifBegin(GifWriter *writer, const char *filename, uint32_t width, uint32_t height, uint32_t delay, int32_t bitDepth, bool dither); -GIFDEF bool GifWriteFrame(GifWriter *writer, const uint8_t *image, uint32_t width, uint32_t height, uint32_t delay, int bitDepth, bool dither); -GIFDEF bool GifEnd(GifWriter *writer); +GIFDEF bool GifBegin(const char *filename, unsigned int width, unsigned int height, unsigned int delay, unsigned int bitDepth, bool dither); +GIFDEF bool GifWriteFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int delay, int bitDepth, bool dither); +GIFDEF bool GifEnd(); #endif // GIF_H @@ -109,7 +89,6 @@ GIFDEF bool GifEnd(GifWriter *writer); #include // Required for: FILE, fopen(), fclose() #include // Required for: memcpy() -#include // Required for for integer typedefs // Define these macros to hook into a custom memory allocator. // GIF_TEMP_MALLOC and GIF_TEMP_FREE will only be called in stack fashion - frees in the reverse order of mallocs @@ -142,30 +121,30 @@ GIFDEF bool GifEnd(GifWriter *writer); // Types and Structures Definition //---------------------------------------------------------------------------------- -//Gif palette structure +// Gif palette structure typedef struct GifPalette { int bitDepth; - uint8_t r[256]; - uint8_t g[256]; - uint8_t b[256]; + unsigned char r[256]; + unsigned char g[256]; + unsigned char b[256]; // k-d tree over RGB space, organized in heap fashion // i.e. left child of node i is node i*2, right child is node i*2 + 1 // nodes 256-511 are implicitly the leaves, containing a color - uint8_t treeSplitElt[255]; - uint8_t treeSplit[255]; + unsigned char treeSplitElt[255]; + unsigned char treeSplit[255]; } GifPalette; // Simple structure to write out the LZW-compressed // portion of the imageone bit at a time typedef struct GifBitStatus { - uint8_t bitIndex; // how many bits in the partial byte written so far - uint8_t byte; // current partial byte + unsigned char bitIndex; // how many bits in the partial byte written so far + unsigned char byte; // current partial byte - uint32_t chunkIndex; - uint8_t chunk[256]; // bytes are written in here until we have 256 of them, then written to the file + unsigned int chunkIndex; + unsigned char chunk[256]; // bytes are written in here until we have 256 of them, then written to the file } GifBitStatus; // The LZW dictionary is a 256-ary tree constructed @@ -177,109 +156,111 @@ typedef struct GifLzwNode { //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -const int kGifTransIndex = 0; +const int gifTransparentIndex = 0; // Transparent color index + +static FILE *gifFile; +unsigned char *gifFrame; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int *bestInd, int *bestDiff, int treeRoot); -static void GifSwapPixels(uint8_t *image, int pixA, int pixB); -static int GifPartition(uint8_t *image, const int left, const int right, const int elt, int pivotIndex); -static void GifPartitionByMedian(uint8_t *image, int left, int right, int com, int neededCenter); -static void GifSplitPalette(uint8_t *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, int treeNode, bool buildForDither, GifPalette *pal); -static int GifPickChangedPixels(const uint8_t *lastFrame, uint8_t *frame, int numPixels); -static void GifMakePalette(const uint8_t *lastFrame, const uint8_t *nextFrame, uint32_t width, uint32_t height, int bitDepth, bool buildForDither, GifPalette *pPal); -static void GifDitherImage(const uint8_t *lastFrame, const uint8_t *nextFrame, uint8_t *outFrame, uint32_t width, uint32_t height, GifPalette *pPal); -static void GifThresholdImage(const uint8_t *lastFrame, const uint8_t *nextFrame, uint8_t *outFrame, uint32_t width, uint32_t height, GifPalette *pPal); -static void GifWriteBit(GifBitStatus *stat, uint32_t bit); +static void GifSwapPixels(unsigned char *image, int pixA, int pixB); +static int GifPartition(unsigned char *image, const int left, const int right, const int elt, int pivotIndex); +static void GifPartitionByMedian(unsigned char *image, int left, int right, int com, int neededCenter); +static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, int treeNode, bool buildForDither, GifPalette *pal); +static int GifPickChangedPixels(const unsigned char *lastFrame, unsigned char *frame, int numPixels); +static void GifMakePalette(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned int width, unsigned int height, int bitDepth, bool buildForDither, GifPalette *pPal); +static void GifDitherImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal); +static void GifThresholdImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal); +static void GifWriteBit(GifBitStatus *stat, unsigned int bit); static void GifWriteChunk(FILE *f, GifBitStatus *stat); -static void GifWriteCode(FILE *f, GifBitStatus *stat, uint32_t code, uint32_t length); +static void GifWriteCode(FILE *f, GifBitStatus *stat, unsigned int code, unsigned int length); static void GifWritePalette(const GifPalette *pPal, FILE *f); -static void GifWriteLzwImage(FILE *f, uint8_t *image, uint32_t left, uint32_t top, uint32_t width, uint32_t height, uint32_t delay, GifPalette *pPal); +static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, unsigned int top, unsigned int width, unsigned int height, unsigned int delay, GifPalette *pPal); //---------------------------------------------------------------------------------- // Module Functions Definition //---------------------------------------------------------------------------------- -// Creates a gif file. -// The input GIFWriter is assumed to be uninitialized. +// Creates a gif file +// NOTE: Initializes internal file pointer (only one gif recording at a time) // The delay value is the time between frames in hundredths of a second - note that not all viewers pay much attention to this value. -GIFDEF bool GifBegin(GifWriter *writer, const char *filename, uint32_t width, uint32_t height, uint32_t delay, int32_t bitDepth, bool dither) +GIFDEF bool GifBegin(const char *filename, unsigned int width, unsigned int height, unsigned int delay, unsigned int bitDepth, bool dither) { #if _MSC_VER >= 1400 - writer->f = 0; - fopen_s(&writer->f, filename, "wb"); + gifFile = 0; + fopen_s(&gifFile, filename, "wb"); #else - writer->f = fopen(filename, "wb"); + gifFile = fopen(filename, "wb"); #endif - if (!writer->f) return false; + + if (!gifFile) return false; - writer->firstFrame = true; + // Allocate space for one gif frame + gifFrame = (unsigned char *)GIF_MALLOC(width*height*4); - // allocate - writer->oldImage = (uint8_t*)GIF_MALLOC(width*height*4); + // GIF Header + fputs("GIF89a",gifFile); - fputs("GIF89a", writer->f); + // Reference: http://www.onicos.com/staff/iz/formats/gif.html - // screen descriptor - fputc(width & 0xff, writer->f); - fputc((width >> 8) & 0xff, writer->f); - fputc(height & 0xff, writer->f); - fputc((height >> 8) & 0xff, writer->f); + // GIF Screen Descriptor + fputc(width & 0xff, gifFile); + fputc((width >> 8) & 0xff, gifFile); // Screen width (2 byte) + fputc(height & 0xff, gifFile); + fputc((height >> 8) & 0xff, gifFile); // Screen height (2 byte) - fputc(0xf0, writer->f); // there is an unsorted global color table of 2 entries - fputc(0, writer->f); // background color - fputc(0, writer->f); // pixels are square (we need to specify this because it's 1989) + fputc(0xf0, gifFile); // Color table flags: unsorted global color table of 2 entries (1 byte, bit-flags) + fputc(0, gifFile); // Background color index + fputc(0, gifFile); // Pixel Aspect Ratio (square, we need to specify this because it's 1989) - // now the "global" palette (really just a dummy palette) - // color 0: black - fputc(0, writer->f); - fputc(0, writer->f); - fputc(0, writer->f); - // color 1: also black - fputc(0, writer->f); - fputc(0, writer->f); - fputc(0, writer->f); + // GIF Global Color table (just a dummy palette) + // Color 0: black + fputc(0, gifFile); + fputc(0, gifFile); + fputc(0, gifFile); + // Color 1: also black + fputc(0, gifFile); + fputc(0, gifFile); + fputc(0, gifFile); if (delay != 0) { - // animation header - fputc(0x21, writer->f); // extension - fputc(0xff, writer->f); // application specific - fputc(11, writer->f); // length 11 - fputs("NETSCAPE2.0", writer->f); // yes, really - fputc(3, writer->f); // 3 bytes of NETSCAPE2.0 data + // Application Extension Block (19 bytes long) + fputc(0x21, gifFile); // GIF Extension code + fputc(0xff, gifFile); // Application Extension Label + fputc(11, gifFile); // Length of Application Block (11 byte) + fputs("NETSCAPE2.0", gifFile); // Application Identifier (Netscape 2.0 block) - fputc(1, writer->f); // JUST BECAUSE - fputc(0, writer->f); // loop infinitely (byte 0) - fputc(0, writer->f); // loop infinitely (byte 1) + fputc(0x03, gifFile); // Length of Data Sub-Block (3 bytes) + fputc(0x01, gifFile); // 0x01 + fputc(0x00, gifFile); // This specifies the number of times, + fputc(0x00, gifFile); // the loop should be executed (infinitely) - fputc(0, writer->f); // block terminator + fputc(0x00, gifFile); // Data Sub-Block Terminator. } return true; } // Writes out a new frame to a GIF in progress. -// The GIFWriter should have been created by GIFBegin. +// NOTE: gifFile should have been initialized with GifBegin() // AFAIK, it is legal to use different bit depths for different frames of an image - // this may be handy to save bits in animations that don't change much. -GIFDEF bool GifWriteFrame(GifWriter *writer, const uint8_t *image, uint32_t width, uint32_t height, uint32_t delay, int bitDepth, bool dither) +GIFDEF bool GifWriteFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int delay, int bitDepth, bool dither) { - if (!writer->f) return false; + if (!gifFile) return false; - const uint8_t *oldImage = writer->firstFrame? NULL : writer->oldImage; - writer->firstFrame = false; + const unsigned char *oldImage = gifFrame; GifPalette pal; - GifMakePalette((dither? NULL : oldImage), image, width, height, bitDepth, dither, &pal); + GifMakePalette((dither ? NULL : oldImage), image, width, height, bitDepth, dither, &pal); - if (dither) - GifDitherImage(oldImage, image, writer->oldImage, width, height, &pal); - else - GifThresholdImage(oldImage, image, writer->oldImage, width, height, &pal); + if (dither) GifDitherImage(oldImage, image, gifFrame, width, height, &pal); + else GifThresholdImage(oldImage, image, gifFrame, width, height, &pal); - GifWriteLzwImage(writer->f, writer->oldImage, 0, 0, width, height, delay, &pal); + GifWriteLzwImage(gifFile, gifFrame, 0, 0, width, height, delay, &pal); return true; } @@ -287,16 +268,17 @@ GIFDEF bool GifWriteFrame(GifWriter *writer, const uint8_t *image, uint32_t widt // Writes the EOF code, closes the file handle, and frees temp memory used by a GIF. // Many if not most viewers will still display a GIF properly if the EOF code is missing, // but it's still a good idea to write it out. -GIFDEF bool GifEnd(GifWriter *writer) +GIFDEF bool GifEnd() { - if (!writer->f) return false; + if (!gifFile) return false; + + fputc(0x3b, gifFile); // Trailer (end of file) + fclose(gifFile); - fputc(0x3b, writer->f); // end of file - fclose(writer->f); - GIF_FREE(writer->oldImage); + GIF_FREE(gifFrame); - writer->f = NULL; - writer->oldImage = NULL; + gifFile = NULL; + gifFrame = NULL; return true; } @@ -314,7 +296,7 @@ static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int if (treeRoot > (1<bitDepth)-1) { int ind = treeRoot-(1<bitDepth); - if (ind == kGifTransIndex) return; + if (ind == gifTransparentIndex) return; // check whether this color is better than the current winner int r_err = r - ((int32_t)pPal->r[ind]); @@ -358,17 +340,17 @@ static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int } } -static void GifSwapPixels(uint8_t *image, int pixA, int pixB) +static void GifSwapPixels(unsigned char *image, int pixA, int pixB) { - uint8_t rA = image[pixA*4]; - uint8_t gA = image[pixA*4 + 1]; - uint8_t bA = image[pixA*4+2]; - uint8_t aA = image[pixA*4+3]; + unsigned char rA = image[pixA*4]; + unsigned char gA = image[pixA*4 + 1]; + unsigned char bA = image[pixA*4+2]; + unsigned char aA = image[pixA*4+3]; - uint8_t rB = image[pixB*4]; - uint8_t gB = image[pixB*4 + 1]; - uint8_t bB = image[pixB*4+2]; - uint8_t aB = image[pixA*4+3]; + unsigned char rB = image[pixB*4]; + unsigned char gB = image[pixB*4 + 1]; + unsigned char bB = image[pixB*4+2]; + unsigned char aB = image[pixA*4+3]; image[pixA*4] = rB; image[pixA*4 + 1] = gB; @@ -382,7 +364,7 @@ static void GifSwapPixels(uint8_t *image, int pixA, int pixB) } // just the partition operation from quicksort -static int GifPartition(uint8_t *image, const int left, const int right, const int elt, int pivotIndex) +static int GifPartition(unsigned char *image, const int left, const int right, const int elt, int pivotIndex) { const int pivotValue = image[(pivotIndex)*4+elt]; GifSwapPixels(image, pivotIndex, right-1); @@ -411,7 +393,7 @@ static int GifPartition(uint8_t *image, const int left, const int right, const i } // Perform an incomplete sort, finding all elements above and below the desired median -static void GifPartitionByMedian(uint8_t *image, int left, int right, int com, int neededCenter) +static void GifPartitionByMedian(unsigned char *image, int left, int right, int com, int neededCenter) { if (left < right-1) { @@ -429,7 +411,7 @@ static void GifPartitionByMedian(uint8_t *image, int left, int right, int com, i } // Builds a palette by creating a balanced k-d tree of all pixels in the image -static void GifSplitPalette(uint8_t *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, +static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, int treeNode, bool buildForDither, GifPalette *pal) { if (lastElt <= firstElt || numPixels == 0) @@ -446,7 +428,7 @@ static void GifSplitPalette(uint8_t *image, int numPixels, int firstElt, int las if (firstElt == 1) { // special case: the darkest color in the image - uint32_t r=255, g=255, b=255; + unsigned int r=255, g=255, b=255; for (int ii=0; iibitDepth)-1) { // special case: the lightest color in the image - uint32_t r=0, g=0, b=0; + unsigned int r=0, g=0, b=0; for (int ii=0; iir[firstElt] = (uint8_t)r; - pal->g[firstElt] = (uint8_t)g; - pal->b[firstElt] = (uint8_t)b; + pal->r[firstElt] = (unsigned char)r; + pal->g[firstElt] = (unsigned char)g; + pal->b[firstElt] = (unsigned char)b; return; } @@ -549,10 +531,10 @@ static void GifSplitPalette(uint8_t *image, int numPixels, int firstElt, int las // moves them to the fromt of th buffer. // This allows us to build a palette optimized for the colors of the // changed pixels only. -static int GifPickChangedPixels(const uint8_t *lastFrame, uint8_t *frame, int numPixels) +static int GifPickChangedPixels(const unsigned char *lastFrame, unsigned char *frame, int numPixels) { int numChanged = 0; - uint8_t *writeIter = frame; + unsigned char *writeIter = frame; for (int ii=0; iibitDepth = bitDepth; // SplitPalette is destructive (it sorts the pixels by color) so // we must create a copy of the image for it to destroy - int imageSize = width*height*4*sizeof(uint8_t); - uint8_t *destroyableImage = (uint8_t*)GIF_TEMP_MALLOC(imageSize); + int imageSize = width*height*4*sizeof(unsigned char); + unsigned char *destroyableImage = (unsigned char*)GIF_TEMP_MALLOC(imageSize); memcpy(destroyableImage, nextFrame, imageSize); int numPixels = width*height; @@ -605,7 +587,7 @@ static void GifMakePalette(const uint8_t *lastFrame, const uint8_t *nextFrame, u } // Implements Floyd-Steinberg dithering, writes palette value to alpha -static void GifDitherImage(const uint8_t *lastFrame, const uint8_t *nextFrame, uint8_t *outFrame, uint32_t width, uint32_t height, GifPalette *pPal) +static void GifDitherImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal) { int numPixels = width*height; @@ -616,17 +598,17 @@ static void GifDitherImage(const uint8_t *lastFrame, const uint8_t *nextFrame, u for (int ii=0; iibitIndex; @@ -781,9 +763,9 @@ static void GifWriteChunk(FILE *f, GifBitStatus *stat) stat->chunkIndex = 0; } -static void GifWriteCode(FILE *f, GifBitStatus *stat, uint32_t code, uint32_t length) +static void GifWriteCode(FILE *f, GifBitStatus *stat, unsigned int code, unsigned int length) { - for (uint32_t ii=0; ii> 1; @@ -804,9 +786,9 @@ static void GifWritePalette(const GifPalette *pPal, FILE *f) for (int ii=1; ii<(1 << pPal->bitDepth); ++ii) { - uint32_t r = pPal->r[ii]; - uint32_t g = pPal->g[ii]; - uint32_t b = pPal->b[ii]; + unsigned int r = pPal->r[ii]; + unsigned int g = pPal->g[ii]; + unsigned int b = pPal->b[ii]; fputc(r, f); fputc(g, f); @@ -815,7 +797,7 @@ static void GifWritePalette(const GifPalette *pPal, FILE *f) } // write the image header, LZW-compress and write out the image -static void GifWriteLzwImage(FILE *f, uint8_t *image, uint32_t left, uint32_t top, uint32_t width, uint32_t height, uint32_t delay, GifPalette *pPal) +static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, unsigned int top, unsigned int width, unsigned int height, unsigned int delay, GifPalette *pPal) { // graphics control extension fputc(0x21, f); @@ -824,7 +806,7 @@ static void GifWriteLzwImage(FILE *f, uint8_t *image, uint32_t left, uint32_t to fputc(0x05, f); // leave prev frame in place, this frame has transparency fputc(delay & 0xff, f); fputc((delay >> 8) & 0xff, f); - fputc(kGifTransIndex, f); // transparent color index + fputc(gifTransparentIndex, f); // transparent color index fputc(0, f); fputc(0x2c, f); // image descriptor block @@ -846,7 +828,7 @@ static void GifWriteLzwImage(FILE *f, uint8_t *image, uint32_t left, uint32_t to GifWritePalette(pPal, f); const int minCodeSize = pPal->bitDepth; - const uint32_t clearCode = 1 << pPal->bitDepth; + const unsigned int clearCode = 1 << pPal->bitDepth; fputc(minCodeSize, f); // min code size 8 bits @@ -854,8 +836,8 @@ static void GifWriteLzwImage(FILE *f, uint8_t *image, uint32_t left, uint32_t to memset(codetree, 0, sizeof(GifLzwNode)*4096); int32_t curCode = -1; - uint32_t codeSize = minCodeSize + 1; - uint32_t maxCode = clearCode + 1; + unsigned int codeSize = minCodeSize + 1; + unsigned int maxCode = clearCode + 1; GifBitStatus stat; stat.byte = 0; @@ -864,11 +846,11 @@ static void GifWriteLzwImage(FILE *f, uint8_t *image, uint32_t left, uint32_t to GifWriteCode(f, &stat, clearCode, codeSize); // start with a fresh LZW dictionary - for (uint32_t yy=0; yy Date: Mon, 29 May 2017 19:00:53 +0200 Subject: Accept external CFLAGS Some distributions build the programs with a specific set of CFLAGS. Lets allow that by adding raylibs flags. --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 1eac71f6..6579d424 100644 --- a/src/Makefile +++ b/src/Makefile @@ -198,7 +198,7 @@ endif # -fgnu89-inline declaring inline functions support (GCC optimized) # -Wno-missing-braces ignore invalid warning (GCC bug 53119) # -D_DEFAULT_SOURCE use with -std=c99 -CFLAGS = -O1 -Wall -std=c99 -D_DEFAULT_SOURCE -fgnu89-inline -Wno-missing-braces +CFLAGS += -O1 -Wall -std=c99 -D_DEFAULT_SOURCE -fgnu89-inline -Wno-missing-braces ifeq ($(PLATFORM),PLATFORM_WEB) CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 --profiling --preload-file resources -- cgit v1.2.3 From 9c524ee3a66953244b6a849f1161f43b22032724 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sun, 4 Jun 2017 23:21:41 +0200 Subject: Add meson files for basic Linux building --- .gitignore | 2 ++ meson.build | 14 ++++++++++++++ src/meson.build | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 meson.build create mode 100644 src/meson.build (limited to 'src') diff --git a/.gitignore b/.gitignore index 7e276829..99b04ee4 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,5 @@ src/libraylib.bc !release/rpi/libraylib.a !release/win32/mingw32/raylib.dll +# Meson build system +builddir/ diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..4ac6c317 --- /dev/null +++ b/meson.build @@ -0,0 +1,14 @@ +project('raylib', 'c', version: '1.7.0', + license: 'zlib', + meson_version: '>= 0.39.1') + +cc = meson.get_compiler('c') + +glfw_dep = dependency('glfw3') +gl_dep = dependency('gl') +openal_dep = dependency('openal') +x11_dep = dependency('x11') +m_dep = cc.find_library('m', required : false) + +subdir('src') + diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 00000000..f416e665 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,19 @@ +install_headers('raylib.h') + +source_c = [ + 'audio.c', + 'core.c', + 'models.c', + 'rlgl.c', + 'shapes.c', + 'text.c', + 'textures.c', + 'utils.c', + 'external/stb_vorbis.c', +] + +raylib = shared_library('raylib', + source_c, + dependencies : [ glfw_dep, gl_dep, openal_dep, m_dep, x11_dep], + install : true) + -- cgit v1.2.3 From 567831a693a98e9c6b021f58fa22ddc3da83c490 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Mon, 5 Jun 2017 14:35:44 +0200 Subject: Allow static/dynamic library building with meson Using the library() function instead of shared_library() allows changing of the library type via the default_library option. This allows for easy change between static and dynamic library building. Use 'meson --default-library=static builddir' to build as static, if no builddir yet exists. Use 'mesonconf -Ddefault_library=static builddir' to change the type for an existing builddir. --- src/meson.build | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/meson.build b/src/meson.build index f416e665..1b84e6f3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -12,8 +12,10 @@ source_c = [ 'external/stb_vorbis.c', ] -raylib = shared_library('raylib', - source_c, - dependencies : [ glfw_dep, gl_dep, openal_dep, m_dep, x11_dep], - install : true) +# use 'meson --default-library=static builddir' to build as static, if no builddir yet exists +# use 'mesonconf -Ddefault_library=static builddir' to change the type +raylib = library('raylib', + source_c, + dependencies : [ glfw_dep, gl_dep, openal_dep, m_dep, x11_dep], + install : true) -- cgit v1.2.3 From 43cb6414f6d579f891f4e0dec4440060a31981c5 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 5 Jun 2017 18:53:37 +0200 Subject: Added note about transposing --- src/raymath.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index 1dbebc07..2bde2042 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -413,6 +413,12 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat) v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; + + /* + v->x = mat.m0*x + mat.m1*y + mat.m2*z + mat.m3; + v->y = mat.m4*x + mat.m5*y + mat.m6*z + mat.m7; + v->z = mat.m8*x + mat.m9*y + mat.m10*z + mat.m11; + */ }; // Calculate linear interpolation between two vectors -- cgit v1.2.3 From 402a8bfd6842f15df940e7ed4f50fc36e0d73aff Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 5 Jun 2017 18:53:53 +0200 Subject: Added note about transposing --- src/raymath.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index 2bde2042..499f9eec 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -414,6 +414,7 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat) v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; + // TODO: Transposed matrix (?) /* v->x = mat.m0*x + mat.m1*y + mat.m2*z + mat.m3; v->y = mat.m4*x + mat.m5*y + mat.m6*z + mat.m7; -- cgit v1.2.3 From 1a61dc2c77dbf28efab8bc32a7485b567ced3d03 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Thu, 8 Jun 2017 17:03:25 +0200 Subject: Meson: build library with so version This should always be the number of the raylib release. Especially when the new version is ABI incompatible the major version should be bumped. --- src/meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/meson.build b/src/meson.build index 1b84e6f3..bdffb98e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -17,5 +17,6 @@ source_c = [ raylib = library('raylib', source_c, dependencies : [ glfw_dep, gl_dep, openal_dep, m_dep, x11_dep], - install : true) + install : true, + version : '1.7.0') -- cgit v1.2.3 From 272073785f17f9b202a5b2a62265bbbd2940b07e Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sun, 11 Jun 2017 11:20:30 +0200 Subject: Add define to have CLOCK_MONOTONIC work in c99 If we compile with c99 without gnu extensions (gnu99) we need this define, to have CLOCK_MONOTONIC and similar macros available --- src/core.c | 4 ++++ src/gestures.h | 5 +++-- src/physac.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 95f704d1..f2ecfa04 100644 --- a/src/core.c +++ b/src/core.c @@ -109,6 +109,10 @@ #include "external/gif.h" // Support GIF recording #endif +#if defined(__linux__) || defined(PLATFORM_WEB) + #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. +#endif + #include // Standard input / output lib #include // Required for: malloc(), free(), rand(), atexit() #include // Required for: typedef unsigned long long int uint64_t, used by hi-res timer diff --git a/src/gestures.h b/src/gestures.h index f04bf091..f4d38dfb 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -148,8 +148,9 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); #elif defined(__linux__) - #include // Required for: timespec - #include // Required for: clock_gettime() + #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. + #include // Required for: timespec + #include // Required for: clock_gettime() #endif //---------------------------------------------------------------------------------- diff --git a/src/physac.h b/src/physac.h index d3fdaca4..8c109935 100644 --- a/src/physac.h +++ b/src/physac.h @@ -253,6 +253,7 @@ PHYSACDEF void ClosePhysics(void); int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); #elif defined(__linux__) || defined(PLATFORM_WEB) + #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. //#define _DEFAULT_SOURCE // Enables BSD function definitions and C99 POSIX compliance #include // Required for: timespec #include // Required for: clock_gettime() -- cgit v1.2.3 From 5370fe18e08303afdffcb78b428b92e8205fbc76 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 11 Jun 2017 23:58:46 +0200 Subject: Additional check for bool header definition --- src/raylib.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index 0b1a6b19..6d597fef 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -296,9 +296,8 @@ //---------------------------------------------------------------------------------- #ifndef __cplusplus // Boolean type - #if !defined(_STDBOOL_H) + #if !defined(_STDBOOL_H) || !defined(__STDBOOL_H) // CLang uses second form typedef enum { false, true } bool; - #define _STDBOOL_H #endif #endif -- cgit v1.2.3 From 8c1f32f2fe25790b3ddd68e8743d488e5b353f8c Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 12 Jun 2017 14:21:50 +0200 Subject: Additional check on file open --- src/textures.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/textures.c b/src/textures.c index 81d36ef8..d249d2be 100644 --- a/src/textures.c +++ b/src/textures.c @@ -191,20 +191,23 @@ Image LoadImage(const char *fileName) int imgBpp = 0; FILE *imFile = fopen(fileName, "rb"); - - // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...) - image.data = stbi_load_from_file(imFile, &imgWidth, &imgHeight, &imgBpp, 0); - fclose(imFile); + if (imFile != NULL) + { + // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...) + image.data = stbi_load_from_file(imFile, &imgWidth, &imgHeight, &imgBpp, 0); + + fclose(imFile); - image.width = imgWidth; - image.height = imgHeight; - image.mipmaps = 1; + image.width = imgWidth; + image.height = imgHeight; + image.mipmaps = 1; - if (imgBpp == 1) image.format = UNCOMPRESSED_GRAYSCALE; - else if (imgBpp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA; - else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8; - else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8; + if (imgBpp == 1) image.format = UNCOMPRESSED_GRAYSCALE; + else if (imgBpp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA; + else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8; + else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8; + } } #if defined(SUPPORT_FILEFORMAT_HDR) else if (IsFileExtension(fileName, ".hdr")) -- cgit v1.2.3 From fcd13fd5d22219d8ed69b88e9cc1138b96b9a16d Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 12:56:04 +0200 Subject: Add some functions to generate images Namely: - GenImageHorizontalV - GenImageHorizontalH - GenImageChecked - GenImageWhiteNoise - GenImageCellular The gradient implementation may be a bit naive, for example it doesn't do any gamma correction. --- examples/textures/textures_image_generation.c | 57 ++++++++++ src/raylib.h | 7 ++ src/textures.c | 144 +++++++++++++++++++++++++- 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 examples/textures/textures_image_generation.c (limited to 'src') diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c new file mode 100644 index 00000000..9db64ef7 --- /dev/null +++ b/examples/textures/textures_image_generation.c @@ -0,0 +1,57 @@ +/******************************************************************************************* +* +* raylib [textures] example - Procedural images generation +* +* This example has been created using raylib 1.7 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2O17 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define TEXTURES_NUM 5 // for now we have 5 generation algorithms + +int main() +{ + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); + + Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); + Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); + Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); + Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); + Image cellular = GenImageCellular(screenWidth, screenHeight, 32); + + Texture2D textures[TEXTURES_NUM]; + textures[0] = LoadTextureFromImage(verticalGradient); + textures[1] = LoadTextureFromImage(horizontalGradient); + textures[2] = LoadTextureFromImage(checked); + textures[3] = LoadTextureFromImage(whiteNoise); + textures[4] = LoadTextureFromImage(cellular); + + int currentTexture = 0; + + while (!WindowShouldClose()) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + currentTexture = (currentTexture + 1) % TEXTURES_NUM; // cycle between the 5 textures + } + + BeginDrawing(); + ClearBackground(RAYWHITE); + DrawTexture(textures[currentTexture], 0, 0, WHITE); + EndDrawing(); + } + + for (int i = 0; i < TEXTURES_NUM; i++) // unload the textures + { + UnloadTexture(textures[i]); + } + + CloseWindow(); +} diff --git a/src/raylib.h b/src/raylib.h index 6d597fef..29cc5728 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -873,6 +873,13 @@ RLAPI void ImageColorGrayscale(Image *image); RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) +// Image generation functions +RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient +RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient +RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked +RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise +RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells + // Texture2D configuration functions RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture RLAPI void SetTextureFilter(Texture2D texture, int filterMode); // Set texture scaling filter mode diff --git a/src/textures.c b/src/textures.c index d249d2be..99392516 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1431,6 +1431,148 @@ void ImageColorBrightness(Image *image, int brightness) } #endif // SUPPORT_IMAGE_MANIPULATION +// Generate image: vertical gradient +Image GenImageGradientV(int width, int height, Color top, Color bottom) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int j = 0; j < height; j++) + { + float factor = (float)j / (float)height; + for (int i = 0; i < width; i++) + { + pixels[j*width + i].r = (int)((float)bottom.r * factor + (float)top.r * (1.f - factor)); + pixels[j*width + i].g = (int)((float)bottom.g * factor + (float)top.g * (1.f - factor)); + pixels[j*width + i].b = (int)((float)bottom.b * factor + (float)top.b * (1.f - factor)); + pixels[j*width + i].a = (int)((float)bottom.a * factor + (float)top.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: horizontal gradient +Image GenImageGradientH(int width, int height, Color left, Color right) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int i = 0; i < width; i++) + { + float factor = (float)i / (float)width; + for (int j = 0; j < height; j++) + { + pixels[j*width + i].r = (int)((float)right.r * factor + (float)left.r * (1.f - factor)); + pixels[j*width + i].g = (int)((float)right.g * factor + (float)left.g * (1.f - factor)); + pixels[j*width + i].b = (int)((float)right.b * factor + (float)left.b * (1.f - factor)); + pixels[j*width + i].a = (int)((float)right.a * factor + (float)left.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: checked +Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + if ((x/checksX + y/checksY) % 2 == 0) pixels[y*width + x] = col1; + else pixels[y*width + x] = col2; + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: white noise +Image GenImageWhiteNoise(int width, int height, float factor) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int i = 0; i < width*height; i++) + { + if (GetRandomValue(0, 99) < (int)(factor * 100.f)) pixels[i] = WHITE; + else pixels[i] = BLACK; + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: cellular algorithm. Bigger tileSize means bigger cells +Image GenImageCellular(int width, int height, int tileSize) +{ + Color *pixels = (Color*)malloc(width*height*sizeof(Color)); + + int seeds_per_row = width / tileSize; + int seeds_per_col = height / tileSize; + int seeds_count = seeds_per_row * seeds_per_col; + + Vector2* seeds = (Vector2*)malloc(seeds_count * sizeof(Vector2)); + + for (int i = 0; i < seeds_count; i++) + { + int y = (i / seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); + int x = (i % seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); + seeds[i] = (Vector2){x, y}; + } + + for (int y = 0; y < height; y++) + { + int tile_y = y / tileSize; + for (int x = 0; x < width; x++) + { + int tile_x = x / tileSize; + + float min_distance = strtod("Inf", NULL); + + // Check all adjacent tiles + for (int i = -1; i < 2; i++) + { + if (tile_x + i < 0 || tile_x + i >= seeds_per_row) continue; + + for (int j = -1; j < 2; j++) + { + if (tile_y + j < 0 || tile_y + j >= seeds_per_col) continue; + + Vector2 neighbor_seed = seeds[(tile_y+j) * seeds_per_row + tile_x+i]; + + float dist = hypot(x - (int)neighbor_seed.x, y - (int)neighbor_seed.y); + min_distance = fmin(min_distance, dist); + } + } + + // I made this up but it seems to give good results at all tile sizes + int intensity = (int)(min_distance * 256.f / tileSize); + if (intensity > 255) intensity = 255; + + Color c = {intensity, intensity, intensity, 255}; + pixels[y*width + x] = c; + } + } + free(seeds); + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate GPU mipmaps for a texture void GenTextureMipmaps(Texture2D *texture) { @@ -2250,4 +2392,4 @@ static Image LoadASTC(const char *fileName) return image; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 954757532a58113f36314cdf148e72dd1079e54a Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 14:32:18 +0200 Subject: Add the SaveImageAs function --- src/raylib.h | 3 ++- src/textures.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index 29cc5728..ee0d8ccc 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -835,7 +835,7 @@ RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Ve // Texture Loading and Drawing Functions (Module: textures) //------------------------------------------------------------------------------------ -// Image/Texture2D data loading/unloading functions +// Image/Texture2D data loading/unloading/saving functions RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageEx(Color *pixels, int width, int height); // Load image from Color array data (RGBA - 32bit) RLAPI Image LoadImagePro(void *data, int width, int height, int format); // Load image from raw data with parameters @@ -849,6 +849,7 @@ RLAPI void UnloadRenderTexture(RenderTexture2D target); RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data +RLAPI void SaveImageAs(Image image, const char *fileName); // Save image to a PNG file // Image manipulation functions RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) diff --git a/src/textures.c b/src/textures.c index 99392516..f1fcb12c 100644 --- a/src/textures.c +++ b/src/textures.c @@ -553,6 +553,18 @@ void UpdateTexture(Texture2D texture, const void *pixels) rlglUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); } +// Save image to a PNG file +void SaveImageAs(Image image, const char *fileName) +{ +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) + unsigned char* imgData = (unsigned char*)GetImageData(image); // this works since Color is just a container for the RGBA values + SavePNG(fileName, imgData, image.width, image.height, 4); + free(imgData); + + TraceLog(INFO, "Image saved: %s", fileName); +#endif +} + // Convert image data to desired format void ImageFormat(Image *image, int newFormat) { -- cgit v1.2.3 From a0ac8ee2c4ce14a23deedeccf9911977e119749d Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 15:29:56 +0200 Subject: Add more image generation functions: radial gradient and perlin noise --- examples/textures/gen | Bin 0 -> 13112 bytes examples/textures/textures_image_generation.c | 12 +- src/external/stb_perlin.h | 316 ++++++++++++++++++++++++++ src/raylib.h | 2 + src/textures.c | 55 +++++ 5 files changed, 381 insertions(+), 4 deletions(-) create mode 100755 examples/textures/gen create mode 100644 src/external/stb_perlin.h (limited to 'src') diff --git a/examples/textures/gen b/examples/textures/gen new file mode 100755 index 00000000..a0f5bf61 Binary files /dev/null and b/examples/textures/gen differ diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 9db64ef7..7525e8a2 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -11,7 +11,7 @@ #include "raylib.h" -#define TEXTURES_NUM 5 // for now we have 5 generation algorithms +#define TEXTURES_NUM 7 // for now we have 7 generation algorithms int main() { @@ -22,16 +22,20 @@ int main() Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); + Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); + Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); Image cellular = GenImageCellular(screenWidth, screenHeight, 32); Texture2D textures[TEXTURES_NUM]; textures[0] = LoadTextureFromImage(verticalGradient); textures[1] = LoadTextureFromImage(horizontalGradient); - textures[2] = LoadTextureFromImage(checked); - textures[3] = LoadTextureFromImage(whiteNoise); - textures[4] = LoadTextureFromImage(cellular); + textures[2] = LoadTextureFromImage(radialGradient); + textures[3] = LoadTextureFromImage(checked); + textures[4] = LoadTextureFromImage(whiteNoise); + textures[5] = LoadTextureFromImage(perlinNoise); + textures[6] = LoadTextureFromImage(cellular); int currentTexture = 0; diff --git a/src/external/stb_perlin.h b/src/external/stb_perlin.h new file mode 100644 index 00000000..5d762220 --- /dev/null +++ b/src/external/stb_perlin.h @@ -0,0 +1,316 @@ +// stb_perlin.h - v0.3 - perlin noise +// public domain single-file C implementation by Sean Barrett +// +// LICENSE +// +// See end of file. +// +// +// to create the implementation, +// #define STB_PERLIN_IMPLEMENTATION +// in *one* C/CPP file that includes this file. +// +// +// Documentation: +// +// float stb_perlin_noise3( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0) +// +// This function computes a random value at the coordinate (x,y,z). +// Adjacent random values are continuous but the noise fluctuates +// its randomness with period 1, i.e. takes on wholly unrelated values +// at integer points. Specifically, this implements Ken Perlin's +// revised noise function from 2002. +// +// The "wrap" parameters can be used to create wraparound noise that +// wraps at powers of two. The numbers MUST be powers of two. Specify +// 0 to mean "don't care". (The noise always wraps every 256 due +// details of the implementation, even if you ask for larger or no +// wrapping.) +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// float stb_perlin_ridge_noise3(float x, float y, float z, +// float lacunarity, float gain, float offset, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_fbm_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain,int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// + + +#ifdef __cplusplus +extern "C" { +#endif +extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +#ifdef __cplusplus +} +#endif + +#ifdef STB_PERLIN_IMPLEMENTATION + +// not same permutation table as Perlin's reference to avoid copyright issues; +// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ +// @OPTIMIZE: should this be unsigned char instead of int for cache? +static unsigned char stb__perlin_randtab[512] = +{ + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, + + // and a second copy so we don't need an extra mask or static initializer + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, +}; + +static float stb__perlin_lerp(float a, float b, float t) +{ + return a + (b-a) * t; +} + +static int stb__perlin_fastfloor(float a) +{ + int ai = (int) a; + return (a < ai) ? ai-1 : ai; +} + +// different grad function from Perlin's, but easy to modify to match reference +static float stb__perlin_grad(int hash, float x, float y, float z) +{ + static float basis[12][4] = + { + { 1, 1, 0 }, + { -1, 1, 0 }, + { 1,-1, 0 }, + { -1,-1, 0 }, + { 1, 0, 1 }, + { -1, 0, 1 }, + { 1, 0,-1 }, + { -1, 0,-1 }, + { 0, 1, 1 }, + { 0,-1, 1 }, + { 0, 1,-1 }, + { 0,-1,-1 }, + }; + + // perlin's gradient has 12 cases so some get used 1/16th of the time + // and some 2/16ths. We reduce bias by changing those fractions + // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight. + static unsigned char indices[64] = + { + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,9,1,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + }; + + // if you use reference permutation table, change 63 below to 15 to match reference + // (this is why the ordering of the table above is funky) + float *grad = basis[indices[hash & 63]]; + return grad[0]*x + grad[1]*y + grad[2]*z; +} + +float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + unsigned int x_mask = (x_wrap-1) & 255; + unsigned int y_mask = (y_wrap-1) & 255; + unsigned int z_mask = (z_wrap-1) & 255; + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x0 = px & x_mask, x1 = (px+1) & x_mask; + int y0 = py & y_mask, y1 = (py+1) & y_mask; + int z0 = pz & z_mask, z1 = (pz+1) & z_mask; + int r0,r1, r00,r01,r10,r11; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0]; + r1 = stb__perlin_randtab[x1]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} + +float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)); + r = r<0 ? -r : r; // fabs() + r = offset - r; + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + r = r<0 ? -r : r; // fabs() + sum += r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +#endif // STB_PERLIN_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/src/raylib.h b/src/raylib.h index 29cc5728..828c2fe9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -876,8 +876,10 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient +RLAPI Image GenImageRadialGradient(int width, int height, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise +RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells // Texture2D configuration functions diff --git a/src/textures.c b/src/textures.c index 99392516..be089a93 100644 --- a/src/textures.c +++ b/src/textures.c @@ -68,6 +68,9 @@ #include "utils.h" // Required for: fopen() Android mapping +#define STB_PERLIN_IMPLEMENTATION +#include "external/stb_perlin.h"// Required for: stb_perlin_fbm_noise3 + // Support only desired texture formats on stb_image #if !defined(SUPPORT_FILEFORMAT_BMP) #define STBI_NO_BMP @@ -1477,6 +1480,34 @@ Image GenImageGradientH(int width, int height, Color left, Color right) return image; } +// Generate image: radial gradient +Image GenImageRadialGradient(int width, int height, Color inner, Color outer) +{ + Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; + + float center_x = (float)width / 2.f; + float center_y = (float)height / 2.f; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + float dist = hypotf((float)x - center_x, (float)y - center_y); + float factor = dist / radius; + factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check + pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); + pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); + pixels[y*width + x].b = (int)((float)outer.b * factor + (float)inner.b * (1.f - factor)); + pixels[y*width + x].a = (int)((float)outer.a * factor + (float)inner.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate image: checked Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2) { @@ -1514,6 +1545,30 @@ Image GenImageWhiteNoise(int width, int height, float factor) return image; } +// Generate image: perlin noise +Image GenImagePerlinNoise(int width, int height, float scale) +{ + Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + float nx = (float)x * scale / (float)width; + float ny = (float)y * scale / (float)height; + // we need to translate the data from [-1; 1] to [0; 1] + float p = (stb_perlin_fbm_noise3(nx, ny, 1.f, 2.f, 0.5f, 6, 0, 0, 0) + 1.f) / 2.f; + int intensity = (int)(p * 255.f); + pixels[y*width + x] = (Color){intensity, intensity, intensity, 255}; + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate image: cellular algorithm. Bigger tileSize means bigger cells Image GenImageCellular(int width, int height, int tileSize) { -- cgit v1.2.3 From 3fe268d004c9b95f9853b0d399887cae185a11d4 Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 15:38:34 +0200 Subject: Swap the two parameters --- src/raylib.h | 2 +- src/textures.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index ee0d8ccc..aa55b776 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -849,7 +849,7 @@ RLAPI void UnloadRenderTexture(RenderTexture2D target); RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data -RLAPI void SaveImageAs(Image image, const char *fileName); // Save image to a PNG file +RLAPI void SaveImageAs(const char *fileName, Image image); // Save image to a PNG file // Image manipulation functions RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) diff --git a/src/textures.c b/src/textures.c index f1fcb12c..34c7453a 100644 --- a/src/textures.c +++ b/src/textures.c @@ -554,7 +554,7 @@ void UpdateTexture(Texture2D texture, const void *pixels) } // Save image to a PNG file -void SaveImageAs(Image image, const char *fileName) +void SaveImageAs(const char* fileName, Image image) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) unsigned char* imgData = (unsigned char*)GetImageData(image); // this works since Color is just a container for the RGBA values -- cgit v1.2.3 From 786cd63057d77e7987fe68986da6bca103c96415 Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 17:27:47 +0200 Subject: Add a density parameter to GenImageRadialGradient --- examples/textures/textures_image_generation.c | 2 +- src/raylib.h | 2 +- src/textures.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 7525e8a2..f6343297 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -22,7 +22,7 @@ int main() Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); - Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, WHITE, BLACK); + Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, 0.f, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); diff --git a/src/raylib.h b/src/raylib.h index a9483f31..0a4ce091 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -877,7 +877,7 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient -RLAPI Image GenImageRadialGradient(int width, int height, Color inner, Color outer); // Generate image: radial gradient +RLAPI Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise diff --git a/src/textures.c b/src/textures.c index 67d03d8d..9b0067cf 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1493,7 +1493,7 @@ Image GenImageGradientH(int width, int height, Color left, Color right) } // Generate image: radial gradient -Image GenImageRadialGradient(int width, int height, Color inner, Color outer) +Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer) { Color *pixels = (Color*)malloc(width * height * sizeof(Color)); float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; @@ -1505,7 +1505,8 @@ Image GenImageRadialGradient(int width, int height, Color inner, Color outer) for (int x = 0; x < width; x++) { float dist = hypotf((float)x - center_x, (float)y - center_y); - float factor = dist / radius; + float factor = (dist - radius * density) / (radius * (1.f - density)); + factor = fmax(factor, 0.f); factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); -- cgit v1.2.3 From aba3739c1354cac4ef302d9b43c3fc5e9699b373 Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Thu, 29 Jun 2017 10:29:01 +0200 Subject: Fix some typos in raymath.h --- src/raymath.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index 499f9eec..6961845c 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -124,7 +124,7 @@ RMDEF Vector2 Vector2Zero(void); // Vector with c RMDEF Vector2 Vector2One(void); // Vector with components value 1.0f RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2); // Add two vectors (v1 + v2) RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Subtract two vectors (v1 - v2) -RMDEF float Vector2Lenght(Vector2 v); // Calculate vector lenght +RMDEF float Vector2Lenght(Vector2 v); // Calculate vector length RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2); // Calculate two vectors dot product RMDEF float Vector2Distance(Vector2 v1, Vector2 v2); // Calculate distance between two vectors RMDEF float Vector2Angle(Vector2 v1, Vector2 v2); // Calculate angle between two vectors in X-axis @@ -142,7 +142,7 @@ RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vecto RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product RMDEF Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector -RMDEF float VectorLength(const Vector3 v); // Calculate vector lenght +RMDEF float VectorLength(const Vector3 v); // Calculate vector length RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product RMDEF float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points RMDEF void VectorScale(Vector3 *v, float scale); // Scale provided vector @@ -236,8 +236,8 @@ RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) return (Vector2){ v1.x - v2.x, v1.y - v2.y }; } -// Calculate vector lenght -RMDEF float Vector2Lenght(Vector2 v) +// Calculate vector length +RMDEF float Vector2Length(Vector2 v) { return sqrtf((v.x*v.x) + (v.y*v.y)); } @@ -348,7 +348,7 @@ RMDEF Vector3 VectorPerpendicular(Vector3 v) return result; } -// Calculate vector lenght +// Calculate vector length RMDEF float VectorLength(const Vector3 v) { return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); -- cgit v1.2.3 From 056a494baf3b4c450e734967c033919facfdec5c Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Thu, 29 Jun 2017 10:36:58 +0200 Subject: Fix some other typos --- docs/cheatsheet/raylib_models.c | 6 +++--- examples/others/standard_lighting.c | 4 ++-- src/raymath.h | 4 ++-- src/textures.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/docs/cheatsheet/raylib_models.c b/docs/cheatsheet/raylib_models.c index 909d7bee..d7540136 100644 --- a/docs/cheatsheet/raylib_models.c +++ b/docs/cheatsheet/raylib_models.c @@ -3,11 +3,11 @@ void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space - void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube + void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) - void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires + void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires void DrawCubeTexture(Texture2D texture, Vector3 position, float width, - float height, float lenght, Color color); // Draw cube textured + float height, float length, Color color); // Draw cube textured void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires diff --git a/examples/others/standard_lighting.c b/examples/others/standard_lighting.c index 14fda32e..a7f634e2 100644 --- a/examples/others/standard_lighting.c +++ b/examples/others/standard_lighting.c @@ -69,7 +69,7 @@ static void GetShaderLightsLocations(Shader shader); // Get shader locations static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights // Vector3 math functions -static float VectorLength(const Vector3 v); // Calculate vector lenght +static float VectorLength(const Vector3 v); // Calculate vector length static void VectorNormalize(Vector3 *v); // Normalize provided vector static Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors @@ -444,7 +444,7 @@ static void SetShaderLightsValues(Shader shader) } } -// Calculate vector lenght +// Calculate vector length float VectorLength(const Vector3 v) { float length; diff --git a/src/raymath.h b/src/raymath.h index 6961845c..c4db0f3f 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -124,7 +124,7 @@ RMDEF Vector2 Vector2Zero(void); // Vector with c RMDEF Vector2 Vector2One(void); // Vector with components value 1.0f RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2); // Add two vectors (v1 + v2) RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Subtract two vectors (v1 - v2) -RMDEF float Vector2Lenght(Vector2 v); // Calculate vector length +RMDEF float Vector2Length(Vector2 v); // Calculate vector length RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2); // Calculate two vectors dot product RMDEF float Vector2Distance(Vector2 v1, Vector2 v2); // Calculate distance between two vectors RMDEF float Vector2Angle(Vector2 v1, Vector2 v2); // Calculate angle between two vectors in X-axis @@ -287,7 +287,7 @@ RMDEF void Vector2Divide(Vector2 *v, float div) // Normalize provided vector RMDEF void Vector2Normalize(Vector2 *v) { - Vector2Divide(v, Vector2Lenght(*v)); + Vector2Divide(v, Vector2Length(*v)); } //---------------------------------------------------------------------------------- diff --git a/src/textures.c b/src/textures.c index 9b0067cf..5196b1e1 100644 --- a/src/textures.c +++ b/src/textures.c @@ -2397,7 +2397,7 @@ static Image LoadASTC(const char *fileName) unsigned char blockZ; // Block Z dimensions (1 for 2D images) unsigned char width[3]; // Image width in pixels (24bit value) unsigned char height[3]; // Image height in pixels (24bit value) - unsigned char lenght[3]; // Image Z-size (1 for 2D images) + unsigned char length[3]; // Image Z-size (1 for 2D images) } ASTCHeader; Image image; -- cgit v1.2.3 From e0c95ede50a5ca08cb5246acb9e9ae32236de234 Mon Sep 17 00:00:00 2001 From: Joel Davis Date: Fri, 30 Jun 2017 23:37:19 -0700 Subject: Prevent bogus triangle being added when there is whitespace at end of .OBJ file --- src/models.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/models.c b/src/models.c index 0a692f5c..8a70a811 100644 --- a/src/models.c +++ b/src/models.c @@ -1637,6 +1637,7 @@ static Mesh LoadOBJ(const char *fileName) // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face) while (!feof(objFile)) { + dataType = '\0'; fscanf(objFile, "%c", &dataType); switch (dataType) -- cgit v1.2.3 From 9f09f6f55023bf8f14a6889801520d80475d33be Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 2 Jul 2017 12:35:13 +0200 Subject: Rename enum LogType names... ...to avoid possible conflicting symbols --- src/audio.c | 145 +++++++++++++++++------------------- src/core.c | 146 ++++++++++++++++++------------------ src/models.c | 28 +++---- src/raylib.h | 15 ++-- src/rlgl.c | 231 ++++++++++++++++++++++++++++----------------------------- src/rlgl.h | 14 ++-- src/rres.h | 43 +++++------ src/text.c | 36 ++++----- src/textures.c | 126 +++++++++++++++---------------- src/utils.c | 30 ++++---- 10 files changed, 397 insertions(+), 417 deletions(-) (limited to 'src') diff --git a/src/audio.c b/src/audio.c index b81d5572..1b340377 100644 --- a/src/audio.c +++ b/src/audio.c @@ -170,7 +170,7 @@ typedef struct MusicData { } MusicData; #if defined(AUDIO_STANDALONE) -typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; +typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType; #endif //---------------------------------------------------------------------------------- @@ -193,7 +193,7 @@ static Wave LoadFLAC(const char *fileName); // Load FLAC file #if defined(AUDIO_STANDALONE) bool IsFileExtension(const char *fileName, const char *ext); // Check file extension -void TraceLog(int msgType, const char *text, ...); // Outputs trace log message (INFO, ERROR, WARNING) +void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) #endif //---------------------------------------------------------------------------------- @@ -206,7 +206,7 @@ void InitAudioDevice(void) // Open and initialize a device with default settings ALCdevice *device = alcOpenDevice(NULL); - if (!device) TraceLog(ERROR, "Audio device could not be opened"); + if (!device) TraceLog(LOG_ERROR, "Audio device could not be opened"); else { ALCcontext *context = alcCreateContext(device, NULL); @@ -217,11 +217,11 @@ void InitAudioDevice(void) alcCloseDevice(device); - TraceLog(ERROR, "Could not initialize audio context"); + TraceLog(LOG_ERROR, "Could not initialize audio context"); } else { - TraceLog(INFO, "Audio device and context initialized successfully: %s", alcGetString(device, ALC_DEVICE_SPECIFIER)); + TraceLog(LOG_INFO, "Audio device and context initialized successfully: %s", alcGetString(device, ALC_DEVICE_SPECIFIER)); // Listener definition (just for 2D) alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f); @@ -239,7 +239,7 @@ void CloseAudioDevice(void) ALCdevice *device; ALCcontext *context = alcGetCurrentContext(); - if (context == NULL) TraceLog(WARNING, "Could not get current audio context for closing"); + if (context == NULL) TraceLog(LOG_WARNING, "Could not get current audio context for closing"); device = alcGetContextsDevice(context); @@ -247,7 +247,7 @@ void CloseAudioDevice(void) alcDestroyContext(context); alcCloseDevice(device); - TraceLog(INFO, "Audio device closed successfully"); + TraceLog(LOG_INFO, "Audio device closed successfully"); } // Check if device has been initialized successfully @@ -298,12 +298,12 @@ Wave LoadWave(const char *fileName) // NOTE: Parameters for RRES_TYPE_WAVE are: sampleCount, sampleRate, sampleSize, channels if (rres[0].type == RRES_TYPE_WAVE) wave = LoadWaveEx(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3, rres[0].param4); - else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName); + else TraceLog(LOG_WARNING, "[%s] Resource file does not contain wave data", fileName); UnloadResource(rres); } #endif - else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); + else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); return wave; } @@ -358,7 +358,7 @@ Sound LoadSoundFromWave(Wave wave) case 8: format = AL_FORMAT_MONO8; break; case 16: format = AL_FORMAT_MONO16; break; case 32: format = AL_FORMAT_MONO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; + default: TraceLog(LOG_WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; } } else if (wave.channels == 2) @@ -368,10 +368,10 @@ Sound LoadSoundFromWave(Wave wave) case 8: format = AL_FORMAT_STEREO8; break; case 16: format = AL_FORMAT_STEREO16; break; case 32: format = AL_FORMAT_STEREO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; + default: TraceLog(LOG_WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; } } - else TraceLog(WARNING, "Wave number of channels not supported: %i", wave.channels); + else TraceLog(LOG_WARNING, "Wave number of channels not supported: %i", wave.channels); // Create an audio source ALuint source; @@ -396,7 +396,7 @@ Sound LoadSoundFromWave(Wave wave) // Attach sound buffer to source alSourcei(source, AL_BUFFER, buffer); - TraceLog(INFO, "[SND ID %i][BUFR ID %i] Sound data loaded successfully (%i Hz, %i bit, %s)", source, buffer, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[SND ID %i][BUFR ID %i] Sound data loaded successfully (%i Hz, %i bit, %s)", source, buffer, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); sound.source = source; sound.buffer = buffer; @@ -411,7 +411,7 @@ void UnloadWave(Wave wave) { if (wave.data != NULL) free(wave.data); - TraceLog(INFO, "Unloaded wave data from RAM"); + TraceLog(LOG_INFO, "Unloaded wave data from RAM"); } // Unload sound @@ -422,7 +422,7 @@ void UnloadSound(Sound sound) alDeleteSources(1, &sound.source); alDeleteBuffers(1, &sound.buffer); - TraceLog(INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer); + TraceLog(LOG_INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer); } // Update sound buffer with new data @@ -434,9 +434,9 @@ void UpdateSound(Sound sound, const void *data, int samplesCount) alGetBufferi(sound.buffer, AL_BITS, &sampleSize); // It could also be retrieved from sound.format alGetBufferi(sound.buffer, AL_CHANNELS, &channels); // It could also be retrieved from sound.format - TraceLog(DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); - TraceLog(DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); - TraceLog(DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); + TraceLog(LOG_DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); + TraceLog(LOG_DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); + TraceLog(LOG_DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); unsigned int dataSize = samplesCount*channels*sampleSize/8; // Size of data in bytes @@ -457,7 +457,7 @@ void PlaySound(Sound sound) { alSourcePlay(sound.source); // Play the sound - //TraceLog(INFO, "Playing sound"); + //TraceLog(LOG_INFO, "Playing sound"); // Find the current position of the sound being played // NOTE: Only work when the entire file is in a single buffer @@ -639,7 +639,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) free(wave->data); wave->data = data; } - else TraceLog(WARNING, "Wave crop range out of bounds"); + else TraceLog(LOG_WARNING, "Wave crop range out of bounds"); } // Get samples data from wave as a floats array @@ -675,7 +675,7 @@ Music LoadMusicStream(const char *fileName) // Open ogg audio stream music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL); - if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); + if (music->ctxOgg == NULL) TraceLog(LOG_WARNING, "[%s] OGG audio file could not be opened", fileName); else { stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg); // Get Ogg file info @@ -687,10 +687,10 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_AUDIO_OGG; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); - TraceLog(DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); - TraceLog(DEBUG, "[%s] OGG channels: %i", fileName, info.channels); - TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); + TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); + TraceLog(LOG_DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); + TraceLog(LOG_DEBUG, "[%s] OGG channels: %i", fileName, info.channels); + TraceLog(LOG_DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); } } #if defined(SUPPORT_FILEFORMAT_FLAC) @@ -698,7 +698,7 @@ Music LoadMusicStream(const char *fileName) { music->ctxFlac = drflac_open_file(fileName); - if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName); + if (music->ctxFlac == NULL) TraceLog(LOG_WARNING, "[%s] FLAC audio file could not be opened", fileName); else { music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels); @@ -707,10 +707,10 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_AUDIO_FLAC; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); - TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); - TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); - TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels); + TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); + TraceLog(LOG_DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); + TraceLog(LOG_DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); + TraceLog(LOG_DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels); } } #endif @@ -730,10 +730,10 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_MODULE_XM; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples); - TraceLog(DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); + TraceLog(LOG_DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples); + TraceLog(LOG_DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); } - else TraceLog(WARNING, "[%s] XM file could not be opened", fileName); + else TraceLog(LOG_WARNING, "[%s] XM file could not be opened", fileName); } #endif #if defined(SUPPORT_FILEFORMAT_MOD) @@ -749,13 +749,13 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_MODULE_MOD; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] MOD number of samples: %i", fileName, music->samplesLeft); - TraceLog(DEBUG, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); + TraceLog(LOG_DEBUG, "[%s] MOD number of samples: %i", fileName, music->samplesLeft); + TraceLog(LOG_DEBUG, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); } - else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName); + else TraceLog(LOG_WARNING, "[%s] MOD file could not be opened", fileName); } #endif - else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); + else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); return music; } @@ -799,7 +799,7 @@ void ResumeMusicStream(Music music) if (state == AL_PAUSED) { - TraceLog(INFO, "[AUD ID %i] Resume music stream playing", music->stream.source); + TraceLog(LOG_INFO, "[AUD ID %i] Resume music stream playing", music->stream.source); alSourcePlay(music->stream.source); } } @@ -992,7 +992,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un if ((channels > 0) && (channels < 3)) stream.channels = channels; else { - TraceLog(WARNING, "Init audio stream: Number of channels not supported: %i", channels); + TraceLog(LOG_WARNING, "Init audio stream: Number of channels not supported: %i", channels); stream.channels = 1; // Fallback to mono channel } @@ -1004,7 +1004,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un case 8: stream.format = AL_FORMAT_MONO8; break; case 16: stream.format = AL_FORMAT_MONO16; break; case 32: stream.format = AL_FORMAT_MONO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; + default: TraceLog(LOG_WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; } } else if (stream.channels == 2) @@ -1014,7 +1014,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un case 8: stream.format = AL_FORMAT_STEREO8; break; case 16: stream.format = AL_FORMAT_STEREO16; break; case 32: stream.format = AL_FORMAT_STEREO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; + default: TraceLog(LOG_WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; } } @@ -1041,7 +1041,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers); - TraceLog(INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo"); return stream; } @@ -1068,7 +1068,7 @@ void CloseAudioStream(AudioStream stream) alDeleteSources(1, &stream.source); alDeleteBuffers(MAX_STREAM_BUFFERS, stream.buffers); - TraceLog(INFO, "[AUD ID %i] Unloaded audio stream data", stream.source); + TraceLog(LOG_INFO, "[AUD ID %i] Unloaded audio stream data", stream.source); } // Update audio stream buffers with data @@ -1085,7 +1085,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) alBufferData(buffer, stream.format, data, samplesCount*stream.sampleSize/8*stream.channels, stream.sampleRate); alSourceQueueBuffers(stream.source, 1, &buffer); } - else TraceLog(WARNING, "[AUD ID %i] Audio buffer not available for unqueuing", stream.source); + else TraceLog(LOG_WARNING, "[AUD ID %i] Audio buffer not available for unqueuing", stream.source); } // Check if any audio stream buffers requires refill @@ -1168,7 +1168,7 @@ static Wave LoadWAV(const char *fileName) if (wavFile == NULL) { - TraceLog(WARNING, "[%s] WAV file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] WAV file could not be opened", fileName); wave.data = NULL; } else @@ -1180,7 +1180,7 @@ static Wave LoadWAV(const char *fileName) if (strncmp(wavRiffHeader.chunkID, "RIFF", 4) || strncmp(wavRiffHeader.format, "WAVE", 4)) { - TraceLog(WARNING, "[%s] Invalid RIFF or WAVE Header", fileName); + TraceLog(LOG_WARNING, "[%s] Invalid RIFF or WAVE Header", fileName); } else { @@ -1191,7 +1191,7 @@ static Wave LoadWAV(const char *fileName) if ((wavFormat.subChunkID[0] != 'f') || (wavFormat.subChunkID[1] != 'm') || (wavFormat.subChunkID[2] != 't') || (wavFormat.subChunkID[3] != ' ')) { - TraceLog(WARNING, "[%s] Invalid Wave format", fileName); + TraceLog(LOG_WARNING, "[%s] Invalid Wave format", fileName); } else { @@ -1205,7 +1205,7 @@ static Wave LoadWAV(const char *fileName) if ((wavData.subChunkID[0] != 'd') || (wavData.subChunkID[1] != 'a') || (wavData.subChunkID[2] != 't') || (wavData.subChunkID[3] != 'a')) { - TraceLog(WARNING, "[%s] Invalid data header", fileName); + TraceLog(LOG_WARNING, "[%s] Invalid data header", fileName); } else { @@ -1223,7 +1223,7 @@ static Wave LoadWAV(const char *fileName) // NOTE: Only support 8 bit, 16 bit and 32 bit sample sizes if ((wave.sampleSize != 8) && (wave.sampleSize != 16) && (wave.sampleSize != 32)) { - TraceLog(WARNING, "[%s] WAV sample size (%ibit) not supported, converted to 16bit", fileName, wave.sampleSize); + TraceLog(LOG_WARNING, "[%s] WAV sample size (%ibit) not supported, converted to 16bit", fileName, wave.sampleSize); WaveFormat(&wave, wave.sampleRate, 16, wave.channels); } @@ -1231,13 +1231,13 @@ static Wave LoadWAV(const char *fileName) if (wave.channels > 2) { WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2); - TraceLog(WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); + TraceLog(LOG_WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); } // NOTE: subChunkSize comes in bytes, we need to translate it to number of samples wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels; - TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); } } } @@ -1258,7 +1258,7 @@ static Wave LoadOGG(const char *fileName) stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL); - if (oggFile == NULL) TraceLog(WARNING, "[%s] OGG file could not be opened", fileName); + if (oggFile == NULL) TraceLog(LOG_WARNING, "[%s] OGG file could not be opened", fileName); else { stb_vorbis_info info = stb_vorbis_get_info(oggFile); @@ -1269,16 +1269,16 @@ static Wave LoadOGG(const char *fileName) wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); // Independent by channel float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); - if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); + if (totalSeconds > 10) TraceLog(LOG_WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short)); // NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!) int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, (short *)wave.data, wave.sampleCount*wave.channels); - TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg); + TraceLog(LOG_DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg); - TraceLog(INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); stb_vorbis_close(oggFile); } @@ -1302,10 +1302,10 @@ static Wave LoadFLAC(const char *fileName) wave.sampleSize = 16; // NOTE: Only support up to 2 channels (mono, stereo) - if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); + if (wave.channels > 2) TraceLog(LOG_WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); - if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName); - else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + if (wave.data == NULL) TraceLog(LOG_WARNING, "[%s] FLAC data could not be loaded", fileName); + else TraceLog(LOG_INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); return wave; } @@ -1327,35 +1327,26 @@ bool IsFileExtension(const char *fileName, const char *ext) return result; } -// Outputs a trace log message (INFO, ERROR, WARNING) -// NOTE: If a file has been init, output log is written there +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int msgType, const char *text, ...) { va_list args; - int traceDebugMsgs = 0; - -#if defined(DO_NOT_TRACE_DEBUG_MSGS) - traceDebugMsgs = 0; -#endif + va_start(args, text); switch (msgType) { - case INFO: fprintf(stdout, "INFO: "); break; - case ERROR: fprintf(stdout, "ERROR: "); break; - case WARNING: fprintf(stdout, "WARNING: "); break; - case DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break; + case LOG_INFO: fprintf(stdout, "INFO: "); break; + case LOG_ERROR: fprintf(stdout, "ERROR: "); break; + case LOG_WARNING: fprintf(stdout, "WARNING: "); break; + case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } - if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs))) - { - va_start(args, text); - vfprintf(stdout, text, args); - va_end(args); + vfprintf(stdout, text, args); + fprintf(stdout, "\n"); - fprintf(stdout, "\n"); - } + va_end(args); - if (msgType == ERROR) exit(1); // If ERROR message, exit program + if (msgType == LOG_ERROR) exit(1); } #endif diff --git a/src/core.c b/src/core.c index f2ecfa04..36180746 100644 --- a/src/core.c +++ b/src/core.c @@ -412,7 +412,7 @@ static void *GamepadThread(void *arg); // Mouse reading thread // Initialize window and OpenGL context void InitWindow(int width, int height, const char *title) { - TraceLog(INFO, "Initializing raylib (v1.7.0)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.7.0)"); // Store window title (could be useful...) windowTitle = title; @@ -475,7 +475,7 @@ void InitWindow(int width, int height, const char *title) // Initialize Android activity void InitWindow(int width, int height, void *state) { - TraceLog(INFO, "Initializing raylib (v1.7.0)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.7.0)"); app_dummy(); @@ -491,19 +491,19 @@ void InitWindow(int width, int height, void *state) int orientation = AConfiguration_getOrientation(app->config); - if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(INFO, "PORTRAIT window orientation"); - else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(INFO, "LANDSCAPE window orientation"); + if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(LOG_INFO, "PORTRAIT window orientation"); + else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(LOG_INFO, "LANDSCAPE window orientation"); // TODO: Automatic orientation doesn't seem to work if (width <= height) { AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_PORT); - TraceLog(WARNING, "Window set to portraid mode"); + TraceLog(LOG_WARNING, "Window set to portraid mode"); } else { AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_LAND); - TraceLog(WARNING, "Window set to landscape mode"); + TraceLog(LOG_WARNING, "Window set to landscape mode"); } //AConfiguration_getDensity(app->config); @@ -517,7 +517,7 @@ void InitWindow(int width, int height, void *state) InitAssetManager(app->activity->assetManager); - TraceLog(INFO, "Android app initialized successfully"); + TraceLog(LOG_INFO, "Android app initialized successfully"); // Wait for window to be initialized (display and context) while (!windowReady) @@ -596,7 +596,7 @@ void CloseWindow(void) pthread_join(gamepadThreadId, NULL); #endif - TraceLog(INFO, "Window closed successfully"); + TraceLog(LOG_INFO, "Window closed successfully"); } // Check if KEY_ESCAPE pressed or Close icon pressed @@ -636,7 +636,7 @@ void ToggleFullscreen(void) #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) - TraceLog(WARNING, "Could not toggle to windowed mode"); + TraceLog(LOG_WARNING, "Could not toggle to windowed mode"); #endif } @@ -677,9 +677,9 @@ void SetWindowMonitor(int monitor) if ((monitor >= 0) && (monitor < monitorCount)) { glfwSetWindowMonitor(window, monitors[monitor], 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE); - TraceLog(INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); + TraceLog(LOG_INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); } - else TraceLog(WARNING, "Selected monitor not found"); + else TraceLog(LOG_WARNING, "Selected monitor not found"); #endif } @@ -977,7 +977,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) // Store values in a vector Vector3 deviceCoords = { x, y, z }; - TraceLog(DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); + TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); // Calculate projection matrix (from perspective instead of frustum) Matrix matProj = MatrixPerspective(camera.fovy, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); @@ -1069,7 +1069,7 @@ void SetTargetFPS(int fps) if (fps < 1) targetTime = 0.0; else targetTime = 1.0/(double)fps; - TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000); + TraceLog(LOG_INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000); } // Returns current FPS @@ -1205,7 +1205,7 @@ void TakeScreenshot(const char *fileName) SavePNG(fileName, imgData, renderWidth, renderHeight, 4); // Save image as PNG free(imgData); - TraceLog(INFO, "Screenshot taken: %s", fileName); + TraceLog(LOG_INFO, "Screenshot taken: %s", fileName); #endif } @@ -1304,7 +1304,7 @@ void StorageSaveValue(int position, int value) // If file doesn't exist, create a new storage data file if (!storageFile) storageFile = fopen(path, "wb"); - if (!storageFile) TraceLog(WARNING, "Storage data file could not be created"); + if (!storageFile) TraceLog(LOG_WARNING, "Storage data file could not be created"); else { // Get file size @@ -1312,7 +1312,7 @@ void StorageSaveValue(int position, int value) int fileSize = ftell(storageFile); // Size in bytes fseek(storageFile, 0, SEEK_SET); - if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); + if (fileSize < (position*4)) TraceLog(LOG_WARNING, "Storage position could not be found"); else { fseek(storageFile, (position*4), SEEK_SET); @@ -1341,7 +1341,7 @@ int StorageLoadValue(int position) // Try open existing file to append data FILE *storageFile = fopen(path, "rb"); - if (!storageFile) TraceLog(WARNING, "Storage data file could not be found"); + if (!storageFile) TraceLog(LOG_WARNING, "Storage data file could not be found"); else { // Get file size @@ -1349,7 +1349,7 @@ int StorageLoadValue(int position) int fileSize = ftell(storageFile); // Size in bytes rewind(storageFile); - if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); + if (fileSize < (position*4)) TraceLog(LOG_WARNING, "Storage position could not be found"); else { fseek(storageFile, (position*4), SEEK_SET); @@ -1675,7 +1675,7 @@ Vector2 GetTouchPosition(int index) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) if (index < MAX_TOUCH_POINTS) position = touchPosition[index]; - else TraceLog(WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); + else TraceLog(LOG_WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { @@ -1716,7 +1716,7 @@ static void InitGraphicsDevice(int width, int height) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwSetErrorCallback(ErrorCallback); - if (!glfwInit()) TraceLog(ERROR, "Failed to initialize GLFW"); + if (!glfwInit()) TraceLog(LOG_ERROR, "Failed to initialize GLFW"); // NOTE: Getting video modes is not implemented in emscripten GLFW3 version #if defined(PLATFORM_DESKTOP) @@ -1752,7 +1752,7 @@ static void InitGraphicsDevice(int width, int height) if (configFlags & FLAG_MSAA_4X_HINT) { glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0 - TraceLog(INFO, "Trying to enable MSAA x4"); + TraceLog(LOG_INFO, "Trying to enable MSAA x4"); } //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits @@ -1805,7 +1805,7 @@ static void InitGraphicsDevice(int width, int height) } } - TraceLog(WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight); + TraceLog(LOG_WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight); // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3), @@ -1844,17 +1844,17 @@ static void InitGraphicsDevice(int width, int height) if (!window) { glfwTerminate(); - TraceLog(ERROR, "GLFW Failed to initialize Window"); + TraceLog(LOG_ERROR, "GLFW Failed to initialize Window"); } else { - TraceLog(INFO, "Display device initialized successfully"); + TraceLog(LOG_INFO, "Display device initialized successfully"); #if defined(PLATFORM_DESKTOP) - TraceLog(INFO, "Display size: %i x %i", displayWidth, displayHeight); + TraceLog(LOG_INFO, "Display size: %i x %i", displayWidth, displayHeight); #endif - TraceLog(INFO, "Render size: %i x %i", renderWidth, renderHeight); - TraceLog(INFO, "Screen size: %i x %i", screenWidth, screenHeight); - TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); + TraceLog(LOG_INFO, "Render size: %i x %i", renderWidth, renderHeight); + TraceLog(LOG_INFO, "Screen size: %i x %i", screenWidth, screenHeight); + TraceLog(LOG_INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); } glfwSetWindowSizeCallback(window, WindowSizeCallback); // NOTE: Resizing not allowed by default! @@ -1886,7 +1886,7 @@ static void InitGraphicsDevice(int width, int height) if (configFlags & FLAG_VSYNC_HINT) { glfwSwapInterval(1); - TraceLog(INFO, "Trying to enable VSYNC"); + TraceLog(LOG_INFO, "Trying to enable VSYNC"); } #endif // defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -1914,7 +1914,7 @@ static void InitGraphicsDevice(int width, int height) { samples = 4; sampleBuffer = 1; - TraceLog(INFO, "Trying to enable MSAA x4"); + TraceLog(LOG_INFO, "Trying to enable MSAA x4"); } const EGLint framebufferAttribs[] = @@ -2022,7 +2022,7 @@ static void InitGraphicsDevice(int width, int height) if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { - TraceLog(ERROR, "Unable to attach EGL rendering context to EGL surface"); + TraceLog(LOG_ERROR, "Unable to attach EGL rendering context to EGL surface"); } else { @@ -2030,11 +2030,11 @@ static void InitGraphicsDevice(int width, int height) //eglQuerySurface(display, surface, EGL_WIDTH, &renderWidth); //eglQuerySurface(display, surface, EGL_HEIGHT, &renderHeight); - TraceLog(INFO, "Display device initialized successfully"); - TraceLog(INFO, "Display size: %i x %i", displayWidth, displayHeight); - TraceLog(INFO, "Render size: %i x %i", renderWidth, renderHeight); - TraceLog(INFO, "Screen size: %i x %i", screenWidth, screenHeight); - TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); + TraceLog(LOG_INFO, "Display device initialized successfully"); + TraceLog(LOG_INFO, "Display size: %i x %i", displayWidth, displayHeight); + TraceLog(LOG_INFO, "Render size: %i x %i", renderWidth, renderHeight); + TraceLog(LOG_INFO, "Screen size: %i x %i", screenWidth, screenHeight); + TraceLog(LOG_INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); } #endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -2085,7 +2085,7 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var) if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { - TraceLog(WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight); + TraceLog(LOG_WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight); // Downscaling to fit display with border-bars float widthRatio = (float)displayWidth/(float)screenWidth; @@ -2116,12 +2116,12 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) renderWidth = displayWidth; renderHeight = displayHeight; - TraceLog(WARNING, "Downscale matrix generated, content will be rendered at: %i x %i", renderWidth, renderHeight); + TraceLog(LOG_WARNING, "Downscale matrix generated, content will be rendered at: %i x %i", renderWidth, renderHeight); } else if ((screenWidth < displayWidth) || (screenHeight < displayHeight)) { // Required screen size is smaller than display size - TraceLog(INFO, "UPSCALING: Required screen size: %i x %i -> Display size: %i x %i", screenWidth, screenHeight, displayWidth, displayHeight); + TraceLog(LOG_INFO, "UPSCALING: Required screen size: %i x %i -> Display size: %i x %i", screenWidth, screenHeight, displayWidth, displayHeight); // Upscaling to fit display with border-bars float displayRatio = (float)displayWidth/(float)displayHeight; @@ -2167,7 +2167,7 @@ static void InitTimer(void) { baseTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; } - else TraceLog(WARNING, "No hi-resolution timer available"); + else TraceLog(LOG_WARNING, "No hi-resolution timer available"); #endif previousTime = GetTime(); // Get time as double @@ -2397,7 +2397,7 @@ static void PollInputEvents(void) // NOTE: Never close window, native activity is controlled by the system! if (app->destroyRequested != 0) { - //TraceLog(INFO, "Closing Window..."); + //TraceLog(LOG_INFO, "Closing Window..."); //windowShouldClose = true; //ANativeActivity_finish(app->activity); } @@ -2431,7 +2431,7 @@ static void SwapBuffers(void) // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description) { - TraceLog(WARNING, "[GLFW3 Error] Code: %i Decription: %s", error, description); + TraceLog(LOG_WARNING, "[GLFW3 Error] Code: %i Decription: %s", error, description); } // GLFW3 Srolling Callback, runs on mouse wheel @@ -2460,7 +2460,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i GifEnd(); gifRecording = false; - TraceLog(INFO, "End animated GIF recording"); + TraceLog(LOG_INFO, "End animated GIF recording"); } else { @@ -2472,7 +2472,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i GifBegin(FormatText("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false); screenshotCounter++; - TraceLog(INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter)); + TraceLog(LOG_INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter)); } } else @@ -2557,7 +2557,7 @@ static void CharCallback(GLFWwindow *window, unsigned int key) { lastKeyPressed = key; - //TraceLog(INFO, "Char Callback Key pressed: %i\n", key); + //TraceLog(LOG_INFO, "Char Callback Key pressed: %i\n", key); } // GLFW3 CursorEnter Callback, when cursor enters the window @@ -2626,15 +2626,15 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) case APP_CMD_START: { //rendering = true; - TraceLog(INFO, "APP_CMD_START"); + TraceLog(LOG_INFO, "APP_CMD_START"); } break; case APP_CMD_RESUME: { - TraceLog(INFO, "APP_CMD_RESUME"); + TraceLog(LOG_INFO, "APP_CMD_RESUME"); } break; case APP_CMD_INIT_WINDOW: { - TraceLog(INFO, "APP_CMD_INIT_WINDOW"); + TraceLog(LOG_INFO, "APP_CMD_INIT_WINDOW"); if (app->window != NULL) { @@ -2691,18 +2691,18 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) } break; case APP_CMD_GAINED_FOCUS: { - TraceLog(INFO, "APP_CMD_GAINED_FOCUS"); + TraceLog(LOG_INFO, "APP_CMD_GAINED_FOCUS"); appEnabled = true; //ResumeMusicStream(); } break; case APP_CMD_PAUSE: { - TraceLog(INFO, "APP_CMD_PAUSE"); + TraceLog(LOG_INFO, "APP_CMD_PAUSE"); } break; case APP_CMD_LOST_FOCUS: { //DrawFrame(); - TraceLog(INFO, "APP_CMD_LOST_FOCUS"); + TraceLog(LOG_INFO, "APP_CMD_LOST_FOCUS"); appEnabled = false; //PauseMusicStream(); } break; @@ -2716,22 +2716,22 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) contextRebindRequired = true; - TraceLog(INFO, "APP_CMD_TERM_WINDOW"); + TraceLog(LOG_INFO, "APP_CMD_TERM_WINDOW"); } break; case APP_CMD_SAVE_STATE: { - TraceLog(INFO, "APP_CMD_SAVE_STATE"); + TraceLog(LOG_INFO, "APP_CMD_SAVE_STATE"); } break; case APP_CMD_STOP: { - TraceLog(INFO, "APP_CMD_STOP"); + TraceLog(LOG_INFO, "APP_CMD_STOP"); } break; case APP_CMD_DESTROY: { // TODO: Finish activity? //ANativeActivity_finish(app->activity); - TraceLog(INFO, "APP_CMD_DESTROY"); + TraceLog(LOG_INFO, "APP_CMD_DESTROY"); } break; case APP_CMD_CONFIG_CHANGED: { @@ -2740,7 +2740,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Check screen orientation here! - TraceLog(INFO, "APP_CMD_CONFIG_CHANGED"); + TraceLog(LOG_INFO, "APP_CMD_CONFIG_CHANGED"); } break; default: break; } @@ -2848,11 +2848,11 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte if (e->isFullscreen) { - TraceLog(INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + TraceLog(LOG_INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); } else { - TraceLog(INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + TraceLog(LOG_INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); } // TODO: Depending on scaling factor (screen vs element), calculate factor to scale mouse/touch input @@ -2885,7 +2885,7 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent { emscripten_exit_pointerlock(); emscripten_get_pointerlock_status(&plce); - //if (plce.isActive) TraceLog(WARNING, "Pointer lock exit did not work!"); + //if (plce.isActive) TraceLog(LOG_WARNING, "Pointer lock exit did not work!"); } toggleCursorLock = false; @@ -3011,7 +3011,7 @@ static void InitKeyboard(void) if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) { // NOTE: It could mean we are using a remote keyboard through ssh! - TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); + TraceLog(LOG_WARNING, "Could not change keyboard mode (SSH keyboard?)"); } else { @@ -3046,7 +3046,7 @@ static void ProcessKeyboard(void) // Fill all read bytes (looking for keys) for (int i = 0; i < bufferByteCount; i++) { - TraceLog(DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); + TraceLog(LOG_DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); //printf("Key(s) bytes: "); //for (int i = 0; i < bufferByteCount; i++) printf("0x%02x ", keysBuffer[i]); @@ -3107,7 +3107,7 @@ static void ProcessKeyboard(void) else if (keysBuffer[i] == 0x7f) currentKeyState[259] = 1; // raylib KEY_BACKSPACE else { - TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); + TraceLog(LOG_DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); // Translate lowercase a-z letters to A-Z if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122)) @@ -3145,7 +3145,7 @@ static void InitMouse(void) // NOTE: We can use /dev/input/mice to read from all available mice if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0) { - TraceLog(WARNING, "Mouse device could not be opened, no mouse available"); + TraceLog(LOG_WARNING, "Mouse device could not be opened, no mouse available"); } else { @@ -3153,8 +3153,8 @@ static void InitMouse(void) int error = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL); - if (error != 0) TraceLog(WARNING, "Error creating mouse input event thread"); - else TraceLog(INFO, "Mouse device initialized successfully"); + if (error != 0) TraceLog(LOG_WARNING, "Error creating mouse input event thread"); + else TraceLog(LOG_INFO, "Mouse device initialized successfully"); } } @@ -3224,7 +3224,7 @@ static void InitTouch(void) { if ((touchStream = open(DEFAULT_TOUCH_DEV, O_RDONLY|O_NONBLOCK)) < 0) { - TraceLog(WARNING, "Touch device could not be opened, no touchscreen available"); + TraceLog(LOG_WARNING, "Touch device could not be opened, no touchscreen available"); } else { @@ -3232,8 +3232,8 @@ static void InitTouch(void) int error = pthread_create(&touchThreadId, NULL, &TouchThread, NULL); - if (error != 0) TraceLog(WARNING, "Error creating touch input event thread"); - else TraceLog(INFO, "Touch device initialized successfully"); + if (error != 0) TraceLog(LOG_WARNING, "Error creating touch input event thread"); + else TraceLog(LOG_INFO, "Touch device initialized successfully"); } } @@ -3335,7 +3335,7 @@ static void InitGamepad(void) if ((gamepadStream[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0) { // NOTE: Only show message for first gamepad - if (i == 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); + if (i == 0) TraceLog(LOG_WARNING, "Gamepad device could not be opened, no gamepad available"); } else { @@ -3346,8 +3346,8 @@ static void InitGamepad(void) { int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL); - if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread"); - else TraceLog(INFO, "Gamepad device initialized successfully"); + if (error != 0) TraceLog(LOG_WARNING, "Error creating gamepad input event thread"); + else TraceLog(LOG_INFO, "Gamepad device initialized successfully"); } } } @@ -3381,7 +3381,7 @@ static void *GamepadThread(void *arg) // Process gamepad events by type if (gamepadEvent.type == JS_EVENT_BUTTON) { - TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + TraceLog(LOG_DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) { @@ -3394,7 +3394,7 @@ static void *GamepadThread(void *arg) } else if (gamepadEvent.type == JS_EVENT_AXIS) { - TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + TraceLog(LOG_DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); if (gamepadEvent.number < MAX_GAMEPAD_AXIS) { diff --git a/src/models.c b/src/models.c index 8a70a811..286581df 100644 --- a/src/models.c +++ b/src/models.c @@ -595,10 +595,10 @@ Mesh LoadMesh(const char *fileName) #if defined(SUPPORT_FILEFORMAT_OBJ) if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); #else - TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); + TraceLog(LOG_WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); #endif - if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); + if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) // TODO: Initialize default mesh data in case loading fails, maybe a cube? @@ -697,7 +697,7 @@ void UnloadModel(Model model) UnloadMesh(&model.mesh); UnloadMaterial(model.material); - TraceLog(INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); + TraceLog(LOG_INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); } // Load material data (from file) @@ -708,7 +708,7 @@ Material LoadMaterial(const char *fileName) #if defined(SUPPORT_FILEFORMAT_MTL) if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); #else - TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); + TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); #endif return material; @@ -1628,7 +1628,7 @@ static Mesh LoadOBJ(const char *fileName) if (objFile == NULL) { - TraceLog(WARNING, "[%s] OBJ file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] OBJ file could not be opened", fileName); return mesh; } @@ -1680,10 +1680,10 @@ static Mesh LoadOBJ(const char *fileName) } } - TraceLog(DEBUG, "[%s] Model vertices: %i", fileName, vertexCount); - TraceLog(DEBUG, "[%s] Model texcoords: %i", fileName, texcoordCount); - TraceLog(DEBUG, "[%s] Model normals: %i", fileName, normalCount); - TraceLog(DEBUG, "[%s] Model triangles: %i", fileName, triangleCount); + TraceLog(LOG_DEBUG, "[%s] Model vertices: %i", fileName, vertexCount); + TraceLog(LOG_DEBUG, "[%s] Model texcoords: %i", fileName, texcoordCount); + TraceLog(LOG_DEBUG, "[%s] Model normals: %i", fileName, normalCount); + TraceLog(LOG_DEBUG, "[%s] Model triangles: %i", fileName, triangleCount); // Once we know the number of vertices to store, we create required arrays Vector3 *midVertices = (Vector3 *)malloc(vertexCount*sizeof(Vector3)); @@ -1757,7 +1757,7 @@ static Mesh LoadOBJ(const char *fileName) rewind(objFile); // Return to the beginning of the file, to read again - if (normalCount == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); + if (normalCount == 0) TraceLog(LOG_INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); // Third reading pass: Get faces (triangles) data and fill VertexArray while (!feof(objFile)) @@ -1924,7 +1924,7 @@ static Mesh LoadOBJ(const char *fileName) free(midTexCoords); // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); + TraceLog(LOG_INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); return mesh; } @@ -1950,7 +1950,7 @@ static Material LoadMTL(const char *fileName) if (mtlFile == NULL) { - TraceLog(WARNING, "[%s] MTL file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] MTL file could not be opened", fileName); return material; } @@ -1965,7 +1965,7 @@ static Material LoadMTL(const char *fileName) // TODO: Support multiple materials in a single .mtl sscanf(buffer, "newmtl %s", mapFileName); - TraceLog(INFO, "[%s] Loading material...", mapFileName); + TraceLog(LOG_INFO, "[%s] Loading material...", mapFileName); } case 'i': // illum int Illumination model { @@ -2090,7 +2090,7 @@ static Material LoadMTL(const char *fileName) fclose(mtlFile); // NOTE: At this point we have all material data - TraceLog(INFO, "[%s] Material loaded successfully", fileName); + TraceLog(LOG_INFO, "[%s] Material loaded successfully", fileName); return material; } diff --git a/src/raylib.h b/src/raylib.h index 0a4ce091..3d09eff0 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v1.7.0 +* raylib v1.8.0 * * A simple and easy-to-use library to learn videogames programming (www.raylib.com) * @@ -533,11 +533,11 @@ typedef struct RRESData *RRES; //---------------------------------------------------------------------------------- // Trace log type typedef enum { - INFO = 0, - WARNING, - ERROR, - DEBUG, - OTHER + LOG_INFO = 0, + LOG_WARNING, + LOG_ERROR, + LOG_DEBUG, + LOG_OTHER } LogType; // Texture formats @@ -711,11 +711,10 @@ RLAPI float *MatrixToFloat(Matrix mat); // Converts Ma // Misc. functions RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags) RLAPI void SetConfigFlags(char flags); // Setup window configuration flags (view FLAGS) -RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (INFO, WARNING, ERROR, DEBUG) +RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (saved a .png) RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included) - // Files management functions RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension RLAPI const char *GetDirectoryPath(const char *fileName); // Get directory for a given fileName (with path) diff --git a/src/rlgl.c b/src/rlgl.c index a40836ca..e3576c30 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -415,7 +415,7 @@ void rlPushMatrix(void) { if (stackCounter == MATRIX_STACK_SIZE - 1) { - TraceLog(ERROR, "Stack Buffer Overflow (MAX %i Matrix)", MATRIX_STACK_SIZE); + TraceLog(LOG_ERROR, "Stack Buffer Overflow (MAX %i Matrix)", MATRIX_STACK_SIZE); } stack[stackCounter] = *currentMatrix; @@ -678,7 +678,7 @@ void rlVertex3f(float x, float y, float z) lines.vCounter++; } - else TraceLog(ERROR, "MAX_LINES_BATCH overflow"); + else TraceLog(LOG_ERROR, "MAX_LINES_BATCH overflow"); } break; case RL_TRIANGLES: @@ -692,7 +692,7 @@ void rlVertex3f(float x, float y, float z) triangles.vCounter++; } - else TraceLog(ERROR, "MAX_TRIANGLES_BATCH overflow"); + else TraceLog(LOG_ERROR, "MAX_TRIANGLES_BATCH overflow"); } break; case RL_QUADS: @@ -708,7 +708,7 @@ void rlVertex3f(float x, float y, float z) draws[drawsCounter - 1].vertexCount++; } - else TraceLog(ERROR, "MAX_QUADS_BATCH overflow"); + else TraceLog(LOG_ERROR, "MAX_QUADS_BATCH overflow"); } break; default: break; @@ -847,7 +847,7 @@ void rlTextureParameters(unsigned int id, int param, int value) case RL_TEXTURE_WRAP_S: case RL_TEXTURE_WRAP_T: { - if ((value == RL_WRAP_CLAMP_MIRROR) && !texClampMirrorSupported) TraceLog(WARNING, "Clamp mirror wrap mode not supported"); + if ((value == RL_WRAP_CLAMP_MIRROR) && !texClampMirrorSupported) TraceLog(LOG_WARNING, "Clamp mirror wrap mode not supported"); else glTexParameteri(GL_TEXTURE_2D, param, value); } break; case RL_TEXTURE_MAG_FILTER: @@ -857,10 +857,10 @@ void rlTextureParameters(unsigned int id, int param, int value) if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); else if (maxAnisotropicLevel > 0.0f) { - TraceLog(WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel); + TraceLog(LOG_WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); } - else TraceLog(WARNING, "Anisotropic filtering not supported"); + else TraceLog(LOG_WARNING, "Anisotropic filtering not supported"); } break; default: break; } @@ -934,7 +934,7 @@ void rlDeleteRenderTextures(RenderTexture2D target) if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); - TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); + TraceLog(LOG_INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); #endif } @@ -953,7 +953,7 @@ void rlDeleteVertexArrays(unsigned int id) if (vaoSupported) { if (id != 0) glDeleteVertexArrays(1, &id); - TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); + TraceLog(LOG_INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); } #endif } @@ -965,7 +965,7 @@ void rlDeleteBuffers(unsigned int id) if (id != 0) { glDeleteBuffers(1, &id); - if (!vaoSupported) TraceLog(INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); + if (!vaoSupported) TraceLog(LOG_INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); } #endif } @@ -1014,33 +1014,33 @@ void rlglInit(int width, int height) //------------------------------------------------------------------------------ // Print current OpenGL and GLSL version - TraceLog(INFO, "GPU: Vendor: %s", glGetString(GL_VENDOR)); - TraceLog(INFO, "GPU: Renderer: %s", glGetString(GL_RENDERER)); - TraceLog(INFO, "GPU: Version: %s", glGetString(GL_VERSION)); - TraceLog(INFO, "GPU: GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); + TraceLog(LOG_INFO, "GPU: Vendor: %s", glGetString(GL_VENDOR)); + TraceLog(LOG_INFO, "GPU: Renderer: %s", glGetString(GL_RENDERER)); + TraceLog(LOG_INFO, "GPU: Version: %s", glGetString(GL_VERSION)); + TraceLog(LOG_INFO, "GPU: GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); // NOTE: We can get a bunch of extra information about GPU capabilities (glGet*) //int maxTexSize; //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); - //TraceLog(INFO, "GL_MAX_TEXTURE_SIZE: %i", maxTexSize); + //TraceLog(LOG_INFO, "GL_MAX_TEXTURE_SIZE: %i", maxTexSize); //GL_MAX_TEXTURE_IMAGE_UNITS //GL_MAX_VIEWPORT_DIMS //int numAuxBuffers; //glGetIntegerv(GL_AUX_BUFFERS, &numAuxBuffers); - //TraceLog(INFO, "GL_AUX_BUFFERS: %i", numAuxBuffers); + //TraceLog(LOG_INFO, "GL_AUX_BUFFERS: %i", numAuxBuffers); //GLint numComp = 0; //GLint format[32] = { 0 }; //glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numComp); //glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, format); - //for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]); + //for (int i = 0; i < numComp; i++) TraceLog(LOG_INFO, "Supported compressed format: 0x%x", format[i]); // NOTE: We don't need that much data on screen... right now... #if defined(GRAPHICS_API_OPENGL_11) - //TraceLog(INFO, "OpenGL 1.1 (or driver default) profile initialized"); + //TraceLog(LOG_INFO, "OpenGL 1.1 (or driver default) profile initialized"); #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -1096,10 +1096,10 @@ void rlglInit(int width, int height) numExt -= 1; #endif - TraceLog(INFO, "Number of supported extensions: %i", numExt); + TraceLog(LOG_INFO, "Number of supported extensions: %i", numExt); // Show supported extensions - //for (int i = 0; i < numExt; i++) TraceLog(INFO, "Supported extension: %s", extList[i]); + //for (int i = 0; i < numExt; i++) TraceLog(LOG_INFO, "Supported extension: %s", extList[i]); // Check required extensions for (int i = 0; i < numExt; i++) @@ -1161,21 +1161,21 @@ void rlglInit(int width, int height) #endif #if defined(GRAPHICS_API_OPENGL_ES2) - if (vaoSupported) TraceLog(INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully"); - else TraceLog(WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); + if (vaoSupported) TraceLog(LOG_INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully"); + else TraceLog(LOG_WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); - if (texNPOTSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); - else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); + if (texNPOTSupported) TraceLog(LOG_INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); + else TraceLog(LOG_WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif - if (texCompDXTSupported) TraceLog(INFO, "[EXTENSION] DXT compressed textures supported"); - if (texCompETC1Supported) TraceLog(INFO, "[EXTENSION] ETC1 compressed textures supported"); - if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported"); - if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported"); - if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported"); + if (texCompDXTSupported) TraceLog(LOG_INFO, "[EXTENSION] DXT compressed textures supported"); + if (texCompETC1Supported) TraceLog(LOG_INFO, "[EXTENSION] ETC1 compressed textures supported"); + if (texCompETC2Supported) TraceLog(LOG_INFO, "[EXTENSION] ETC2/EAC compressed textures supported"); + if (texCompPVRTSupported) TraceLog(LOG_INFO, "[EXTENSION] PVRT compressed textures supported"); + if (texCompASTCSupported) TraceLog(LOG_INFO, "[EXTENSION] ASTC compressed textures supported"); - if (texAnisotropicFilterSupported) TraceLog(INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel); - if (texClampMirrorSupported) TraceLog(INFO, "[EXTENSION] Clamp mirror wrap texture mode supported"); + if (texAnisotropicFilterSupported) TraceLog(LOG_INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel); + if (texClampMirrorSupported) TraceLog(LOG_INFO, "[EXTENSION] Clamp mirror wrap texture mode supported"); // Initialize buffers, default shaders and default textures //---------------------------------------------------------- @@ -1185,8 +1185,8 @@ void rlglInit(int width, int height) whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); - if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); - else TraceLog(WARNING, "Base white texture could not be loaded"); + if (whiteTexture != 0) TraceLog(LOG_INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); + else TraceLog(LOG_WARNING, "Base white texture could not be loaded"); // Init default Shader (customized for GL 3.3 and ES2) defaultShader = LoadDefaultShader(); @@ -1254,7 +1254,7 @@ void rlglInit(int width, int height) screenWidth = width; screenHeight = height; - TraceLog(INFO, "OpenGL default states initialized successfully"); + TraceLog(LOG_INFO, "OpenGL default states initialized successfully"); } // Vertex Buffer Object deinitialization (memory free) @@ -1266,7 +1266,7 @@ void rlglClose(void) // Delete default white texture glDeleteTextures(1, &whiteTexture); - TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); + TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); free(draws); #endif @@ -1292,14 +1292,14 @@ void rlglLoadExtensions(void *loader) #if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) #if !defined(__APPLE__) - if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); - else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); + if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(LOG_WARNING, "GLAD: Cannot load OpenGL extensions"); + else TraceLog(LOG_INFO, "GLAD: OpenGL extensions loaded successfully"); #if defined(GRAPHICS_API_OPENGL_21) - if (GLAD_GL_VERSION_2_1) TraceLog(INFO, "OpenGL 2.1 profile supported"); + if (GLAD_GL_VERSION_2_1) TraceLog(LOG_INFO, "OpenGL 2.1 profile supported"); #elif defined(GRAPHICS_API_OPENGL_33) - if(GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported"); - else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported"); + if(GLAD_GL_VERSION_3_3) TraceLog(LOG_INFO, "OpenGL 3.3 Core profile supported"); + else TraceLog(LOG_ERROR, "OpenGL 3.3 Core profile not supported"); #endif #endif @@ -1342,7 +1342,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int #if defined(GRAPHICS_API_OPENGL_11) if (format >= COMPRESSED_DXT1_RGB) { - TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); + TraceLog(LOG_WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); return id; } #endif @@ -1350,31 +1350,31 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int if ((!texCompDXTSupported) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) || (format == COMPRESSED_DXT3_RGBA) || (format == COMPRESSED_DXT5_RGBA))) { - TraceLog(WARNING, "DXT compressed texture format not supported"); + TraceLog(LOG_WARNING, "DXT compressed texture format not supported"); return id; } #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if ((!texCompETC1Supported) && (format == COMPRESSED_ETC1_RGB)) { - TraceLog(WARNING, "ETC1 compressed texture format not supported"); + TraceLog(LOG_WARNING, "ETC1 compressed texture format not supported"); return id; } if ((!texCompETC2Supported) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA))) { - TraceLog(WARNING, "ETC2 compressed texture format not supported"); + TraceLog(LOG_WARNING, "ETC2 compressed texture format not supported"); return id; } if ((!texCompPVRTSupported) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA))) { - TraceLog(WARNING, "PVRT compressed texture format not supported"); + TraceLog(LOG_WARNING, "PVRT compressed texture format not supported"); return id; } if ((!texCompASTCSupported) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA))) { - TraceLog(WARNING, "ASTC compressed texture format not supported"); + TraceLog(LOG_WARNING, "ASTC compressed texture format not supported"); return id; } #endif @@ -1411,7 +1411,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - TraceLog(INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id); + TraceLog(LOG_INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id); } break; case UNCOMPRESSED_GRAY_ALPHA: { @@ -1438,7 +1438,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - default: TraceLog(WARNING, "Texture format not recognized"); break; + default: TraceLog(LOG_WARNING, "Texture format not recognized"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA @@ -1465,7 +1465,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 #endif - default: TraceLog(WARNING, "Texture format not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format not supported"); break; } #endif @@ -1508,8 +1508,8 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int // Unbind current texture glBindTexture(GL_TEXTURE_2D, 0); - if (id > 0) TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height); - else TraceLog(WARNING, "Texture could not be created"); + if (id > 0) TraceLog(LOG_INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height); + else TraceLog(LOG_WARNING, "Texture could not be created"); return id; } @@ -1584,16 +1584,16 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) if (status != GL_FRAMEBUFFER_COMPLETE) { - TraceLog(WARNING, "Framebuffer object could not be created..."); + TraceLog(LOG_WARNING, "Framebuffer object could not be created..."); switch (status) { - case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break; + case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(LOG_WARNING, "Framebuffer is unsupported"); break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(LOG_WARNING, "Framebuffer incomplete attachment"); break; #if defined(GRAPHICS_API_OPENGL_ES2) - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(LOG_WARNING, "Framebuffer incomplete dimensions"); break; #endif - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(LOG_WARNING, "Framebuffer incomplete missing attachment"); break; default: break; } @@ -1601,7 +1601,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) glDeleteTextures(1, &target.depth.id); glDeleteFramebuffers(1, &target.id); } - else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", target.id); + else TraceLog(LOG_INFO, "[FBO ID %i] Framebuffer object created successfully", target.id); glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif @@ -1624,7 +1624,7 @@ void rlglUpdateTexture(unsigned int id, int width, int height, int format, const case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(WARNING, "Texture format updating not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA @@ -1637,7 +1637,7 @@ void rlglUpdateTexture(unsigned int id, int width, int height, int format, const case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(WARNING, "Texture format updating not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; } #endif } @@ -1681,7 +1681,7 @@ void rlglGenerateMipmaps(Texture2D *texture) mipHeight /= 2; } - TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture->id); + TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture->id); // NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data free(data); @@ -1692,7 +1692,7 @@ void rlglGenerateMipmaps(Texture2D *texture) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically - TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture->id); + TraceLog(LOG_INFO, "[TEX ID %i] Mipmaps generated automatically", texture->id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps @@ -1703,7 +1703,7 @@ void rlglGenerateMipmaps(Texture2D *texture) texture->mipmaps = 1 + (int)floor(log(MAX(texture->width, texture->height))/log(2)); #endif } - else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture->id); + else TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps can not be generated", texture->id); glBindTexture(GL_TEXTURE_2D, 0); } @@ -1834,13 +1834,13 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) if (vaoId > 0) { mesh->vaoId = vaoId; - TraceLog(INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); + TraceLog(LOG_INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); } - else TraceLog(WARNING, "Mesh could not be uploaded to VRAM (GPU)"); + else TraceLog(LOG_WARNING, "Mesh could not be uploaded to VRAM (GPU)"); } else { - TraceLog(INFO, "[VBOs] Mesh uploaded successfully to VRAM (GPU)"); + TraceLog(LOG_INFO, "[VBOs] Mesh uploaded successfully to VRAM (GPU)"); } #endif } @@ -2219,7 +2219,7 @@ void *rlglReadTexturePixels(Texture2D texture) case UNCOMPRESSED_R5G5B5A1: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1; break; // 16 bpp (1 bit alpha) case UNCOMPRESSED_R4G4B4A4: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; break; // 16 bpp (4 bit alpha) case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; // 32 bpp - default: TraceLog(WARNING, "Texture data retrieval, format not suported"); break; + default: TraceLog(LOG_WARNING, "Texture data retrieval, format not suported"); break; } // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding. @@ -2369,7 +2369,7 @@ char *LoadText(const char *fileName) fclose(textFile); } - else TraceLog(WARNING, "[%s] Text file could not be opened", fileName); + else TraceLog(LOG_WARNING, "[%s] Text file could not be opened", fileName); } return text; @@ -2399,7 +2399,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) if (shader.id == 0) { - TraceLog(WARNING, "Custom shader could not be loaded"); + TraceLog(LOG_WARNING, "Custom shader could not be loaded"); shader = defaultShader; } #endif @@ -2413,7 +2413,7 @@ void UnloadShader(Shader shader) if (shader.id != 0) { rlDeleteShader(shader.id); - TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); + TraceLog(LOG_INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); } } @@ -2455,7 +2455,7 @@ int GetShaderLocation(Shader shader, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shader.id, uniformName); - if (location == -1) TraceLog(DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); + if (location == -1) TraceLog(LOG_DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); #endif return location; } @@ -2470,7 +2470,7 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) else if (size == 2) glUniform2fv(uniformLoc, 1, value); // Shader uniform type: vec2 else if (size == 3) glUniform3fv(uniformLoc, 1, value); // Shader uniform type: vec3 else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4 - else TraceLog(WARNING, "Shader value float array size not supported"); + else TraceLog(LOG_WARNING, "Shader value float array size not supported"); //glUseProgram(0); // Avoid reseting current shader program, in case other uniforms are set #endif @@ -2486,7 +2486,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) else if (size == 2) glUniform2iv(uniformLoc, 1, value); // Shader uniform type: ivec2 else if (size == 3) glUniform3iv(uniformLoc, 1, value); // Shader uniform type: ivec3 else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 - else TraceLog(WARNING, "Shader value int array size not supported"); + else TraceLog(LOG_WARNING, "Shader value int array size not supported"); //glUseProgram(0); #endif @@ -2572,7 +2572,7 @@ void InitVrSimulator(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - TraceLog(INFO, "Initializing VR Simulator (Oculus Rift DK2)"); + TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift DK2)"); } else if ((vrDevice == HMD_DEFAULT_DEVICE) || (vrDevice == HMD_OCULUS_RIFT_CV1)) { @@ -2599,12 +2599,12 @@ void InitVrSimulator(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - TraceLog(INFO, "Initializing VR Simulator (Oculus Rift CV1)"); + TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift CV1)"); } else { - TraceLog(WARNING, "VR Simulator doesn't support selected device parameters,"); - TraceLog(WARNING, "using default VR Simulator parameters"); + TraceLog(LOG_WARNING, "VR Simulator doesn't support selected device parameters,"); + TraceLog(LOG_WARNING, "using default VR Simulator parameters"); } // Initialize framebuffer and textures for stereo rendering @@ -2623,7 +2623,7 @@ void InitVrSimulator(int vrDevice) #endif #if defined(GRAPHICS_API_OPENGL_11) - TraceLog(WARNING, "VR Simulator not supported on OpenGL 1.1"); + TraceLog(LOG_WARNING, "VR Simulator not supported on OpenGL 1.1"); #endif } @@ -2843,7 +2843,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade if (success != GL_TRUE) { - TraceLog(WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); + TraceLog(LOG_WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); int maxLength = 0; int length; @@ -2857,13 +2857,13 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade #endif glGetShaderInfoLog(vertexShader, maxLength, &length, log); - TraceLog(INFO, "%s", log); + TraceLog(LOG_INFO, "%s", log); #ifdef _MSC_VER free(log); #endif } - else TraceLog(INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader); + else TraceLog(LOG_INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader); glCompileShader(fragmentShader); @@ -2871,7 +2871,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade if (success != GL_TRUE) { - TraceLog(WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader); + TraceLog(LOG_WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader); int maxLength = 0; int length; @@ -2885,13 +2885,13 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade #endif glGetShaderInfoLog(fragmentShader, maxLength, &length, log); - TraceLog(INFO, "%s", log); + TraceLog(LOG_INFO, "%s", log); #ifdef _MSC_VER free(log); #endif } - else TraceLog(INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader); + else TraceLog(LOG_INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader); program = glCreateProgram(); @@ -2916,7 +2916,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade if (success == GL_FALSE) { - TraceLog(WARNING, "[SHDR ID %i] Failed to link shader program...", program); + TraceLog(LOG_WARNING, "[SHDR ID %i] Failed to link shader program...", program); int maxLength = 0; int length; @@ -2930,7 +2930,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade #endif glGetProgramInfoLog(program, maxLength, &length, log); - TraceLog(INFO, "%s", log); + TraceLog(LOG_INFO, "%s", log); #ifdef _MSC_VER free(log); @@ -2939,7 +2939,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade program = 0; } - else TraceLog(INFO, "[SHDR ID %i] Shader program loaded successfully", program); + else TraceLog(LOG_INFO, "[SHDR ID %i] Shader program loaded successfully", program); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); @@ -3015,8 +3015,8 @@ static Shader LoadDefaultShader(void) shader.id = LoadShaderProgram(vDefaultShaderStr, fDefaultShaderStr); - if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); - else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); + if (shader.id != 0) TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); + else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); if (shader.id != 0) LoadDefaultShaderLocations(&shader); @@ -3135,7 +3135,7 @@ static void LoadDefaultBuffers(void) quads.tcCounter = 0; quads.cCounter = 0; - TraceLog(INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)"); + TraceLog(LOG_INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)"); //-------------------------------------------------------------------------------------------- // [GPU] Upload vertex data and initialize VAOs/VBOs (lines, triangles, quads) @@ -3165,8 +3165,8 @@ static void LoadDefaultBuffers(void) glEnableVertexAttribArray(currentShader.colorLoc); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]); + if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId); + else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]); // Upload and link triangles vertex buffers if (vaoSupported) @@ -3191,8 +3191,8 @@ static void LoadDefaultBuffers(void) glEnableVertexAttribArray(currentShader.colorLoc); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]); + if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId); + else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]); // Upload and link quads vertex buffers if (vaoSupported) @@ -3233,8 +3233,8 @@ static void LoadDefaultBuffers(void) glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); #endif - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (quads)", quads.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (quads)", quads.vboId[0], quads.vboId[1], quads.vboId[2], quads.vboId[3]); + if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (quads)", quads.vaoId); + else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (quads)", quads.vboId[0], quads.vboId[1], quads.vboId[2], quads.vboId[3]); // Unbind the current VAO if (vaoSupported) glBindVertexArray(0); @@ -3432,14 +3432,14 @@ static void DrawDefaultBuffers() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } - //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); + //TraceLog(LOG_DEBUG, "Draws required per frame: %i", drawsCounter); for (int i = 0; i < drawsCounter; i++) { quadsCount = draws[i].vertexCount/4; numIndicesToProcess = quadsCount*6; // Get number of Quads*6 index by Quad - //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); + //TraceLog(LOG_DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); glBindTexture(GL_TEXTURE_2D, draws[i].textureId); @@ -3450,7 +3450,7 @@ static void DrawDefaultBuffers() glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset)); #endif //GLenum err; - //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! + //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(LOG_INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! indicesOffset += draws[i].vertexCount/4*6; } @@ -3557,17 +3557,17 @@ static void SetStereoConfig(VrDeviceInfo hmd) hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; - TraceLog(DEBUG, "VR: Distortion Scale: %f", distortionScale); + TraceLog(LOG_DEBUG, "VR: Distortion Scale: %f", distortionScale); float normScreenWidth = 0.5f; float normScreenHeight = 1.0f; float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect }; float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale }; - TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); - TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); - TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); - TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); #if defined(SUPPORT_DISTORTION_SHADER) // Update distortion shader with lens and distortion-scale parameters @@ -3645,20 +3645,20 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) if (width != 1) width /= 2; if (height != 1) height /= 2; - TraceLog(DEBUG, "Next mipmap size: %i x %i", width, height); + TraceLog(LOG_DEBUG, "Next mipmap size: %i x %i", width, height); mipmapCount++; size += (width*height*4); // Add mipmap size (in bytes) } - TraceLog(DEBUG, "Total mipmaps required: %i", mipmapCount); - TraceLog(DEBUG, "Total size of data required: %i", size); + TraceLog(LOG_DEBUG, "Total mipmaps required: %i", mipmapCount); + TraceLog(LOG_DEBUG, "Total size of data required: %i", size); unsigned char *temp = realloc(data, size); if (temp != NULL) data = temp; - else TraceLog(WARNING, "Mipmaps required memory could not be allocated"); + else TraceLog(LOG_WARNING, "Mipmaps required memory could not be allocated"); width = baseWidth; height = baseHeight; @@ -3680,7 +3680,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) j++; } - TraceLog(DEBUG, "Mipmap base (%ix%i)", width, height); + TraceLog(LOG_DEBUG, "Mipmap base (%ix%i)", width, height); for (int mip = 1; mip < mipmapCount; mip++) { @@ -3751,15 +3751,14 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) } } - TraceLog(DEBUG, "Mipmap generated successfully (%ix%i)", width, height); + TraceLog(LOG_DEBUG, "Mipmap generated successfully (%ix%i)", width, height); return mipmap; } #endif #if defined(RLGL_STANDALONE) -// Output a trace log message -// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int msgType, const char *text, ...) { va_list args; @@ -3767,10 +3766,10 @@ void TraceLog(int msgType, const char *text, ...) switch (msgType) { - case INFO: fprintf(stdout, "INFO: "); break; - case ERROR: fprintf(stdout, "ERROR: "); break; - case WARNING: fprintf(stdout, "WARNING: "); break; - case DEBUG: fprintf(stdout, "DEBUG: "); break; + case LOG_INFO: fprintf(stdout, "INFO: "); break; + case LOG_ERROR: fprintf(stdout, "ERROR: "); break; + case LOG_WARNING: fprintf(stdout, "WARNING: "); break; + case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } @@ -3779,7 +3778,7 @@ void TraceLog(int msgType, const char *text, ...) va_end(args); - if (msgType == ERROR) exit(1); + if (msgType == LOG_ERROR) exit(1); } // Converts Matrix to float array diff --git a/src/rlgl.h b/src/rlgl.h index 6d6ad516..57e77c7d 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -236,11 +236,11 @@ typedef unsigned char byte; // TraceLog message types typedef enum { - INFO = 0, - ERROR, - WARNING, - DEBUG, - OTHER + LOG_INFO = 0, + LOG_ERROR, + LOG_WARNING, + LOG_DEBUG, + LOG_OTHER } TraceLogType; // Texture formats (support depends on OpenGL version) @@ -416,8 +416,8 @@ void EndShaderMode(void); // End custo void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) void EndBlendMode(void); // End blending mode (reset to default: alpha blending) -void TraceLog(int msgType, const char *text, ...); -float *MatrixToFloat(Matrix mat); +void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) +float *MatrixToFloat(Matrix mat); // Get float array from Matrix data void InitVrSimulator(int vrDevice); // Init VR simulator for selected device void CloseVrSimulator(void); // Close VR simulator for current device diff --git a/src/rres.h b/src/rres.h index 65ebdbba..93d1c395 100644 --- a/src/rres.h +++ b/src/rres.h @@ -252,7 +252,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) FILE *rresFile = fopen(fileName, "rb"); - if (rresFile == NULL) TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", fileName); + if (rresFile == NULL) TraceLog(LOG_WARNING, "[%s] rRES raylib resource file could not be opened", fileName); else { // Read rres file info header @@ -266,7 +266,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) // Verify "rRES" identifier if ((fileHeader.id[0] != 'r') && (fileHeader.id[1] != 'R') && (fileHeader.id[2] != 'E') && (fileHeader.id[3] != 'S')) { - TraceLog(WARNING, "[%s] This is not a valid raylib resource file", fileName); + TraceLog(LOG_WARNING, "[%s] This is not a valid raylib resource file", fileName); } else { @@ -305,7 +305,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) } else rres[k].data = data; - if (rres[k].data != NULL) TraceLog(INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id); + if (rres[k].data != NULL) TraceLog(LOG_INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id); // Read next part fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile); @@ -318,7 +318,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) } } - if (rres[0].data == NULL) TraceLog(WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId); + if (rres[0].data == NULL) TraceLog(LOG_WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId); } fclose(rresFile); @@ -349,7 +349,7 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i // Check correct memory allocation if (uncompData == NULL) { - TraceLog(WARNING, "Out of memory while decompressing data"); + TraceLog(LOG_WARNING, "Out of memory while decompressing data"); } else { @@ -358,18 +358,18 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i if (tempUncompSize == -1) { - TraceLog(WARNING, "Data decompression failed"); + TraceLog(LOG_WARNING, "Data decompression failed"); RRES_FREE(uncompData); } if (uncompSize != (int)tempUncompSize) { - TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted"); - TraceLog(WARNING, " -- Expected uncompressed size: %i", uncompSize); - TraceLog(WARNING, " -- Returned uncompressed size: %i", tempUncompSize); + TraceLog(LOG_WARNING, "Expected uncompressed size do not match, data may be corrupted"); + TraceLog(LOG_WARNING, " -- Expected uncompressed size: %i", uncompSize); + TraceLog(LOG_WARNING, " -- Returned uncompressed size: %i", tempUncompSize); } - TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize); + TraceLog(LOG_INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize); } return uncompData; @@ -377,36 +377,27 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i // Some required functions for rres standalone module version #if defined(RRES_STANDALONE) -// Outputs a trace log message (INFO, ERROR, WARNING) -// NOTE: If a file has been init, output log is written there +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int logType, const char *text, ...) { va_list args; - int traceDebugMsgs = 0; - -#ifdef DO_NOT_TRACE_DEBUG_MSGS - traceDebugMsgs = 0; -#endif + va_start(args, text); switch (msgType) { case LOG_INFO: fprintf(stdout, "INFO: "); break; case LOG_ERROR: fprintf(stdout, "ERROR: "); break; case LOG_WARNING: fprintf(stdout, "WARNING: "); break; - case LOG_DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break; + case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } - if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs))) - { - va_start(args, text); - vfprintf(stdout, text, args); - va_end(args); + vfprintf(stdout, text, args); + fprintf(stdout, "\n"); - fprintf(stdout, "\n"); - } + va_end(args); - if (msgType == ERROR) exit(1); // If ERROR message, exit program + if (msgType == LOG_ERROR) exit(1); } #endif diff --git a/src/text.c b/src/text.c index 027701de..7ef01c11 100644 --- a/src/text.c +++ b/src/text.c @@ -256,7 +256,7 @@ extern void LoadDefaultFont(void) defaultFont.baseSize = defaultFont.chars[0].rec.height; - TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); + TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); } // Unload raylib default font @@ -330,7 +330,7 @@ SpriteFont LoadSpriteFont(const char *fileName) if (spriteFont.texture.id == 0) { - TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); + TraceLog(LOG_WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); spriteFont = GetDefaultFont(); } else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance) @@ -364,7 +364,7 @@ SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, if (spriteFont.texture.id == 0) { - TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName); + TraceLog(LOG_WARNING, "[%s] SpriteFont could not be generated, using default font", fileName); spriteFont = GetDefaultFont(); } @@ -380,7 +380,7 @@ void UnloadSpriteFont(SpriteFont spriteFont) UnloadTexture(spriteFont.texture); free(spriteFont.chars); - TraceLog(DEBUG, "Unloaded sprite font data"); + TraceLog(LOG_DEBUG, "Unloaded sprite font data"); } } @@ -677,7 +677,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) xPosToRead = charSpacing; } - TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); + TraceLog(LOG_DEBUG, "SpriteFont data parsed correctly from image"); // NOTE: We need to remove key color borders from image to avoid weird // artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR @@ -713,7 +713,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) spriteFont.baseSize = spriteFont.chars[0].rec.height; - TraceLog(INFO, "Image file loaded correctly as SpriteFont"); + TraceLog(LOG_INFO, "Image file loaded correctly as SpriteFont"); return spriteFont; } @@ -743,7 +743,7 @@ static SpriteFont LoadBMFont(const char *fileName) if (fntFile == NULL) { - TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] FNT file could not be opened", fileName); return font; } @@ -756,20 +756,20 @@ static SpriteFont LoadBMFont(const char *fileName) searchPoint = strstr(buffer, "lineHeight"); sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight); - TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize); - TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight); + TraceLog(LOG_DEBUG, "[%s] Font size: %i", fileName, fontSize); + TraceLog(LOG_DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight); fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "file"); sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName); - TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName); + TraceLog(LOG_DEBUG, "[%s] Font texture filename: %s", fileName, texFileName); fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "count"); sscanf(searchPoint, "count=%i", &charsCount); - TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, charsCount); + TraceLog(LOG_DEBUG, "[%s] Font num chars: %i", fileName, charsCount); // Compose correct path using route of .fnt file (fileName) and texFileName char *texPath = NULL; @@ -785,7 +785,7 @@ static SpriteFont LoadBMFont(const char *fileName) strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1); strncat(texPath, texFileName, strlen(texFileName)); - TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); + TraceLog(LOG_DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); Image imFont = LoadImage(texPath); @@ -832,7 +832,7 @@ static SpriteFont LoadBMFont(const char *fileName) UnloadSpriteFont(font); font = GetDefaultFont(); } - else TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName); + else TraceLog(LOG_INFO, "[%s] SpriteFont loaded successfully", fileName); return font; } @@ -853,7 +853,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount)); int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT - TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); + TraceLog(LOG_INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); unsigned char *ttfBuffer = (unsigned char *)malloc(MAX_TTF_SIZE*1024*1024); unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned! @@ -865,22 +865,22 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in if (ttfFile == NULL) { - TraceLog(WARNING, "[%s] TTF file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName); return font; } // NOTE: We try reading up to 16 MB of elements of 1 byte fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile); - if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); + if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... // TODO: Replace this function by a proper packing method and support random chars order, // we already receive a list (fontChars) with the ordered expected characters int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData); - //if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); - if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font"); + //if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); + if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font"); free(ttfBuffer); diff --git a/src/textures.c b/src/textures.c index 5196b1e1..28bc27f8 100644 --- a/src/textures.c +++ b/src/textures.c @@ -167,7 +167,7 @@ Image LoadImage(const char *fileName) // NOTE: Parameters for RRES_TYPE_IMAGE are: width, height, format, mipmaps if (rres[0].type == RRES_TYPE_IMAGE) image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3); - else TraceLog(WARNING, "[%s] Resource file does not contain image data", fileName); + else TraceLog(LOG_WARNING, "[%s] Resource file does not contain image data", fileName); UnloadResource(rres); } @@ -234,7 +234,7 @@ Image LoadImage(const char *fileName) else { // TODO: Support different number of channels at 32 bit float - TraceLog(WARNING, "[%s] Image fileformat not supported (only 3 channel 32 bit floats)", fileName); + TraceLog(LOG_WARNING, "[%s] Image fileformat not supported (only 3 channel 32 bit floats)", fileName); UnloadImage(image); } } @@ -254,10 +254,10 @@ Image LoadImage(const char *fileName) #if defined(SUPPORT_FILEFORMAT_ASTC) else if (IsFileExtension(fileName, ".astc")) image = LoadASTC(fileName); #endif - else TraceLog(WARNING, "[%s] Image fileformat not supported", fileName); + else TraceLog(LOG_WARNING, "[%s] Image fileformat not supported", fileName); - if (image.data != NULL) TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); - else TraceLog(WARNING, "[%s] Image could not be loaded", fileName); + if (image.data != NULL) TraceLog(LOG_INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); + else TraceLog(LOG_WARNING, "[%s] Image could not be loaded", fileName); return image; } @@ -315,7 +315,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int if (rawFile == NULL) { - TraceLog(WARNING, "[%s] RAW image file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] RAW image file could not be opened", fileName); } else { @@ -333,7 +333,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int case UNCOMPRESSED_R4G4B4A4: image.data = (unsigned short *)malloc(size); break; // 16 bpp (4 bit alpha) case UNCOMPRESSED_R8G8B8A8: image.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp case UNCOMPRESSED_R32G32B32: image.data = (float *)malloc(size*12); size *= 12; break; // 4 byte per channel (12 byte) - default: TraceLog(WARNING, "Image format not suported"); break; + default: TraceLog(LOG_WARNING, "Image format not suported"); break; } // NOTE: fread() returns num read elements instead of bytes, @@ -343,7 +343,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int // Check if data has been read successfully if (bytes < size) { - TraceLog(WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); + TraceLog(LOG_WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); if (image.data != NULL) free(image.data); } @@ -373,7 +373,7 @@ Texture2D LoadTexture(const char *fileName) texture = LoadTextureFromImage(image); UnloadImage(image); } - else TraceLog(WARNING, "Texture could not be created"); + else TraceLog(LOG_WARNING, "Texture could not be created"); return texture; } @@ -391,7 +391,7 @@ Texture2D LoadTextureFromImage(Image image) texture.mipmaps = image.mipmaps; texture.format = image.format; - TraceLog(DEBUG, "[TEX ID %i] Parameters: %ix%i, %i mips, format %i", texture.id, texture.width, texture.height, texture.mipmaps, texture.format); + TraceLog(LOG_DEBUG, "[TEX ID %i] Parameters: %ix%i, %i mips, format %i", texture.id, texture.width, texture.height, texture.mipmaps, texture.format); return texture; } @@ -410,7 +410,7 @@ void UnloadImage(Image image) free(image.data); // NOTE: It becomes anoying every time a texture is loaded - //TraceLog(INFO, "Unloaded image data"); + //TraceLog(LOG_INFO, "Unloaded image data"); } // Unload texture from GPU memory (VRAM) @@ -420,7 +420,7 @@ void UnloadTexture(Texture2D texture) { rlDeleteTextures(texture.id); - TraceLog(INFO, "[TEX ID %i] Unloaded texture data from VRAM (GPU)", texture.id); + TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data from VRAM (GPU)", texture.id); } } @@ -510,7 +510,7 @@ Color *GetImageData(Image image) k += 3; } break; - default: TraceLog(WARNING, "Format not supported for pixel data retrieval"); break; + default: TraceLog(LOG_WARNING, "Format not supported for pixel data retrieval"); break; } } @@ -540,11 +540,11 @@ Image GetTextureData(Texture2D texture) } else image.format = texture.format; - TraceLog(INFO, "Texture pixel data obtained successfully"); + TraceLog(LOG_INFO, "Texture pixel data obtained successfully"); } - else TraceLog(WARNING, "Texture pixel data could not be obtained"); + else TraceLog(LOG_WARNING, "Texture pixel data could not be obtained"); } - else TraceLog(WARNING, "Compressed texture data could not be obtained"); + else TraceLog(LOG_WARNING, "Compressed texture data could not be obtained"); return image; } @@ -564,7 +564,7 @@ void SaveImageAs(const char* fileName, Image image) SavePNG(fileName, imgData, image.width, image.height, 4); free(imgData); - TraceLog(INFO, "Image saved: %s", fileName); + TraceLog(LOG_INFO, "Image saved: %s", fileName); #endif } @@ -697,7 +697,7 @@ void ImageFormat(Image *image, int newFormat) free(pixels); } - else TraceLog(WARNING, "Image data format is compressed, can not be converted"); + else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted"); } } @@ -708,11 +708,11 @@ void ImageAlphaMask(Image *image, Image alphaMask) { if ((image->width != alphaMask.width) || (image->height != alphaMask.height)) { - TraceLog(WARNING, "Alpha mask must be same size as image"); + TraceLog(LOG_WARNING, "Alpha mask must be same size as image"); } else if (image->format >= COMPRESSED_DXT1_RGB) { - TraceLog(WARNING, "Alpha mask can not be applied to compressed data formats"); + TraceLog(LOG_WARNING, "Alpha mask can not be applied to compressed data formats"); } else { @@ -775,7 +775,7 @@ void ImageToPOT(Image *image, Color fillColor) } } - TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight); + TraceLog(LOG_WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight); free(pixels); // Free pixels data free(image->data); // Free old image data @@ -821,7 +821,7 @@ Image ImageCopy(Image image) case COMPRESSED_PVRT_RGB: case COMPRESSED_PVRT_RGBA: byteSize /= 2; break; // 4 bpp case COMPRESSED_ASTC_8x8_RGBA: byteSize /= 4; break;// 2 bpp - default: TraceLog(WARNING, "Image format not recognized"); break; + default: TraceLog(LOG_WARNING, "Image format not recognized"); break; } newImage.data = malloc(byteSize); @@ -848,13 +848,13 @@ void ImageCrop(Image *image, Rectangle crop) if ((crop.x + crop.width) > image->width) { crop.width = image->width - crop.x; - TraceLog(WARNING, "Crop rectangle width out of bounds, rescaled crop width: %i", crop.width); + TraceLog(LOG_WARNING, "Crop rectangle width out of bounds, rescaled crop width: %i", crop.width); } if ((crop.y + crop.height) > image->height) { crop.height = image->height - crop.y; - TraceLog(WARNING, "Crop rectangle height out of bounds, rescaled crop height: %i", crop.height); + TraceLog(LOG_WARNING, "Crop rectangle height out of bounds, rescaled crop height: %i", crop.height); } if ((crop.x < image->width) && (crop.y < image->height)) @@ -886,7 +886,7 @@ void ImageCrop(Image *image, Rectangle crop) } else { - TraceLog(WARNING, "Image can not be cropped, crop rectangle out of bounds"); + TraceLog(LOG_WARNING, "Image can not be cropped, crop rectangle out of bounds"); } } @@ -961,13 +961,13 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) if ((srcRec.x + srcRec.width) > src.width) { srcRec.width = src.width - srcRec.x; - TraceLog(WARNING, "Source rectangle width out of bounds, rescaled width: %i", srcRec.width); + TraceLog(LOG_WARNING, "Source rectangle width out of bounds, rescaled width: %i", srcRec.width); } if ((srcRec.y + srcRec.height) > src.height) { srcRec.height = src.height - srcRec.y; - TraceLog(WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); + TraceLog(LOG_WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); cropRequired = true; } @@ -988,14 +988,14 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) if ((dstRec.x + dstRec.width) > dst->width) { dstRec.width = dst->width - dstRec.x; - TraceLog(WARNING, "Destination rectangle width out of bounds, rescaled width: %i", dstRec.width); + TraceLog(LOG_WARNING, "Destination rectangle width out of bounds, rescaled width: %i", dstRec.width); cropRequired = true; } if ((dstRec.y + dstRec.height) > dst->height) { dstRec.height = dst->height - dstRec.y; - TraceLog(WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); + TraceLog(LOG_WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); cropRequired = true; } @@ -1098,7 +1098,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing if (fontSize > imSize.y) { float scaleFactor = fontSize/imSize.y; - TraceLog(INFO, "Scalefactor: %f", scaleFactor); + TraceLog(LOG_INFO, "Scalefactor: %f", scaleFactor); // Using nearest-neighbor scaling algorithm for default font if (font.texture.id == GetDefaultFont().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); @@ -1186,13 +1186,13 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) { if (image->format >= COMPRESSED_DXT1_RGB) { - TraceLog(WARNING, "Compressed data formats can not be dithered"); + TraceLog(LOG_WARNING, "Compressed data formats can not be dithered"); return; } if ((rBpp+gBpp+bBpp+aBpp) > 16) { - TraceLog(WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp)); + TraceLog(LOG_WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp)); } else { @@ -1202,7 +1202,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8)) { - TraceLog(WARNING, "Image format is already 16bpp or lower, dithering could have no effect"); + TraceLog(LOG_WARNING, "Image format is already 16bpp or lower, dithering could have no effect"); } // Define new image format, check if desired bpp match internal known format @@ -1212,7 +1212,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) else { image->format = 0; - TraceLog(WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp); + TraceLog(LOG_WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp); } // NOTE: We will store the dithered data as unsigned short (16bpp) @@ -1652,7 +1652,7 @@ void GenTextureMipmaps(Texture2D *texture) // Check if texture is POT if ((potWidth != texture->width) || (potHeight != texture->height)) { - TraceLog(WARNING, "Limited NPOT support, no mipmaps available for NPOT textures"); + TraceLog(LOG_WARNING, "Limited NPOT support, no mipmaps available for NPOT textures"); } else rlglGenerateMipmaps(texture); #else @@ -1712,7 +1712,7 @@ void SetTextureFilter(Texture2D texture, int filterMode) } else { - TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); + TraceLog(LOG_WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR); @@ -1887,7 +1887,7 @@ static Image LoadDDS(const char *fileName) if (ddsFile == NULL) { - TraceLog(WARNING, "[%s] DDS file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] DDS file could not be opened", fileName); } else { @@ -1898,7 +1898,7 @@ static Image LoadDDS(const char *fileName) if (strncmp(filecode, "DDS ", 4) != 0) { - TraceLog(WARNING, "[%s] DDS file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] DDS file does not seem to be a valid image", fileName); } else { @@ -1907,11 +1907,11 @@ static Image LoadDDS(const char *fileName) // Get the image header fread(&ddsHeader, sizeof(DDSHeader), 1, ddsFile); - TraceLog(DEBUG, "[%s] DDS file header size: %i", fileName, sizeof(DDSHeader)); - TraceLog(DEBUG, "[%s] DDS file pixel format size: %i", fileName, ddsHeader.ddspf.size); - TraceLog(DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, ddsHeader.ddspf.flags); - TraceLog(DEBUG, "[%s] DDS file format: 0x%x", fileName, ddsHeader.ddspf.fourCC); - TraceLog(DEBUG, "[%s] DDS file bit count: 0x%x", fileName, ddsHeader.ddspf.rgbBitCount); + TraceLog(LOG_DEBUG, "[%s] DDS file header size: %i", fileName, sizeof(DDSHeader)); + TraceLog(LOG_DEBUG, "[%s] DDS file pixel format size: %i", fileName, ddsHeader.ddspf.size); + TraceLog(LOG_DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, ddsHeader.ddspf.flags); + TraceLog(LOG_DEBUG, "[%s] DDS file format: 0x%x", fileName, ddsHeader.ddspf.fourCC); + TraceLog(LOG_DEBUG, "[%s] DDS file bit count: 0x%x", fileName, ddsHeader.ddspf.rgbBitCount); image.width = ddsHeader.width; image.height = ddsHeader.height; @@ -1999,7 +1999,7 @@ static Image LoadDDS(const char *fileName) if (ddsHeader.mipmapCount > 1) size = ddsHeader.pitchOrLinearSize*2; else size = ddsHeader.pitchOrLinearSize; - TraceLog(DEBUG, "Pitch or linear size: %i", ddsHeader.pitchOrLinearSize); + TraceLog(LOG_DEBUG, "Pitch or linear size: %i", ddsHeader.pitchOrLinearSize); image.data = (unsigned char*)malloc(size*sizeof(unsigned char)); @@ -2073,7 +2073,7 @@ static Image LoadPKM(const char *fileName) if (pkmFile == NULL) { - TraceLog(WARNING, "[%s] PKM file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] PKM file could not be opened", fileName); } else { @@ -2084,7 +2084,7 @@ static Image LoadPKM(const char *fileName) if (strncmp(pkmHeader.id, "PKM ", 4) != 0) { - TraceLog(WARNING, "[%s] PKM file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] PKM file does not seem to be a valid image", fileName); } else { @@ -2093,9 +2093,9 @@ static Image LoadPKM(const char *fileName) pkmHeader.width = ((pkmHeader.width & 0x00FF) << 8) | ((pkmHeader.width & 0xFF00) >> 8); pkmHeader.height = ((pkmHeader.height & 0x00FF) << 8) | ((pkmHeader.height & 0xFF00) >> 8); - TraceLog(DEBUG, "PKM (ETC) image width: %i", pkmHeader.width); - TraceLog(DEBUG, "PKM (ETC) image height: %i", pkmHeader.height); - TraceLog(DEBUG, "PKM (ETC) image format: %i", pkmHeader.format); + TraceLog(LOG_DEBUG, "PKM (ETC) image width: %i", pkmHeader.width); + TraceLog(LOG_DEBUG, "PKM (ETC) image height: %i", pkmHeader.height); + TraceLog(LOG_DEBUG, "PKM (ETC) image format: %i", pkmHeader.format); image.width = pkmHeader.width; image.height = pkmHeader.height; @@ -2167,7 +2167,7 @@ static Image LoadKTX(const char *fileName) if (ktxFile == NULL) { - TraceLog(WARNING, "[%s] KTX image file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] KTX image file could not be opened", fileName); } else { @@ -2179,7 +2179,7 @@ static Image LoadKTX(const char *fileName) if ((ktxHeader.id[1] != 'K') || (ktxHeader.id[2] != 'T') || (ktxHeader.id[3] != 'X') || (ktxHeader.id[4] != ' ') || (ktxHeader.id[5] != '1') || (ktxHeader.id[6] != '1')) { - TraceLog(WARNING, "[%s] KTX file does not seem to be a valid file", fileName); + TraceLog(LOG_WARNING, "[%s] KTX file does not seem to be a valid file", fileName); } else { @@ -2187,9 +2187,9 @@ static Image LoadKTX(const char *fileName) image.height = ktxHeader.height; image.mipmaps = ktxHeader.mipmapLevels; - TraceLog(DEBUG, "KTX (ETC) image width: %i", ktxHeader.width); - TraceLog(DEBUG, "KTX (ETC) image height: %i", ktxHeader.height); - TraceLog(DEBUG, "KTX (ETC) image format: 0x%x", ktxHeader.glInternalFormat); + TraceLog(LOG_DEBUG, "KTX (ETC) image width: %i", ktxHeader.width); + TraceLog(LOG_DEBUG, "KTX (ETC) image height: %i", ktxHeader.height); + TraceLog(LOG_DEBUG, "KTX (ETC) image format: 0x%x", ktxHeader.glInternalFormat); unsigned char unused; @@ -2288,7 +2288,7 @@ static Image LoadPVR(const char *fileName) if (pvrFile == NULL) { - TraceLog(WARNING, "[%s] PVR file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] PVR file could not be opened", fileName); } else { @@ -2307,7 +2307,7 @@ static Image LoadPVR(const char *fileName) if ((pvrHeader.id[0] != 'P') || (pvrHeader.id[1] != 'V') || (pvrHeader.id[2] != 'R') || (pvrHeader.id[3] != 3)) { - TraceLog(WARNING, "[%s] PVR file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] PVR file does not seem to be a valid image", fileName); } else { @@ -2368,7 +2368,7 @@ static Image LoadPVR(const char *fileName) fread(image.data, dataSize, 1, pvrFile); } } - else if (pvrVersion == 52) TraceLog(INFO, "PVR v2 not supported, update your files to PVR v3"); + else if (pvrVersion == 52) TraceLog(LOG_INFO, "PVR v2 not supported, update your files to PVR v3"); fclose(pvrFile); // Close file pointer } @@ -2412,7 +2412,7 @@ static Image LoadASTC(const char *fileName) if (astcFile == NULL) { - TraceLog(WARNING, "[%s] ASTC file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] ASTC file could not be opened", fileName); } else { @@ -2423,7 +2423,7 @@ static Image LoadASTC(const char *fileName) if ((astcHeader.id[3] != 0x5c) || (astcHeader.id[2] != 0xa1) || (astcHeader.id[1] != 0xab) || (astcHeader.id[0] != 0x13)) { - TraceLog(WARNING, "[%s] ASTC file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] ASTC file does not seem to be a valid image", fileName); } else { @@ -2434,9 +2434,9 @@ static Image LoadASTC(const char *fileName) // NOTE: ASTC format only contains one mipmap level image.mipmaps = 1; - TraceLog(DEBUG, "ASTC image width: %i", image.width); - TraceLog(DEBUG, "ASTC image height: %i", image.height); - TraceLog(DEBUG, "ASTC image blocks: %ix%i", astcHeader.blockX, astcHeader.blockY); + TraceLog(LOG_DEBUG, "ASTC image width: %i", image.width); + TraceLog(LOG_DEBUG, "ASTC image height: %i", image.height); + TraceLog(LOG_DEBUG, "ASTC image blocks: %ix%i", astcHeader.blockX, astcHeader.blockY); // NOTE: Each block is always stored in 128bit so we can calculate the bpp int bpp = 128/(astcHeader.blockX*astcHeader.blockY); @@ -2452,7 +2452,7 @@ static Image LoadASTC(const char *fileName) if (bpp == 8) image.format = COMPRESSED_ASTC_4x4_RGBA; else if (bpp == 2) image.format = COMPRESSED_ASTC_4x4_RGBA; } - else TraceLog(WARNING, "[%s] ASTC block size configuration not supported", fileName); + else TraceLog(LOG_WARNING, "[%s] ASTC block size configuration not supported", fileName); } fclose(astcFile); diff --git a/src/utils.c b/src/utils.c index c86c9c82..cd4638af 100644 --- a/src/utils.c +++ b/src/utils.c @@ -14,10 +14,10 @@ * * #define SUPPORT_TRACELOG * Show TraceLog() output messages -* NOTE: By default DEBUG traces not shown +* NOTE: By default LOG_DEBUG traces not shown * * #define SUPPORT_TRACELOG_DEBUG -* Show TraceLog() DEBUG messages +* Show TraceLog() LOG_DEBUG messages * * DEPENDENCIES: * stb_image_write - BMP/PNG writting functions @@ -45,7 +45,7 @@ **********************************************************************************************/ #define SUPPORT_TRACELOG // Output tracelog messages -//#define SUPPORT_TRACELOG_DEBUG // Avoid DEBUG messages tracing +//#define SUPPORT_TRACELOG_DEBUG // Avoid LOG_DEBUG messages tracing #include "utils.h" @@ -89,7 +89,7 @@ static int android_close(void *cookie); // Module Functions Definition - Utilities //---------------------------------------------------------------------------------- -// Output trace log messages +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int msgType, const char *text, ...) { #if defined(SUPPORT_TRACELOG) @@ -102,10 +102,10 @@ void TraceLog(int msgType, const char *text, ...) switch(msgType) { - case INFO: strcpy(buffer, "INFO: "); break; - case ERROR: strcpy(buffer, "ERROR: "); break; - case WARNING: strcpy(buffer, "WARNING: "); break; - case DEBUG: strcpy(buffer, "DEBUG: "); break; + case LOG_INFO: strcpy(buffer, "INFO: "); break; + case LOG_ERROR: strcpy(buffer, "ERROR: "); break; + case LOG_WARNING: strcpy(buffer, "WARNING: "); break; + case LOG_DEBUG: strcpy(buffer, "DEBUG: "); break; default: break; } @@ -118,19 +118,19 @@ void TraceLog(int msgType, const char *text, ...) #if defined(PLATFORM_ANDROID) switch(msgType) { - case INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break; - case ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break; - case WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break; - case DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break; + case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break; + case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break; + case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break; + case LOG_DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break; default: break; } #else - if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs))) vprintf(buffer, args); + if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs))) vprintf(buffer, args); #endif va_end(args); - if (msgType == ERROR) exit(1); // If ERROR message, exit program + if (msgType == LOG_ERROR) exit(1); // If LOG_ERROR message, exit program #endif // SUPPORT_TRACELOG } @@ -195,7 +195,7 @@ static int android_read(void *cookie, char *buf, int size) static int android_write(void *cookie, const char *buf, int size) { - TraceLog(ERROR, "Can't provide write access to the APK"); + TraceLog(LOG_ERROR, "Can't provide write access to the APK"); return EACCES; } -- cgit v1.2.3 From 6589c808b578732bc710c46fbc74ae73d427f99e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 2 Jul 2017 19:29:01 +0200 Subject: Review some formatting for consistency --- .gitignore | 2 +- examples/textures/textures_image_generation.c | 44 ++++++++--- examples/textures/textures_image_generation.png | Bin 0 -> 222595 bytes src/raylib.h | 2 +- src/textures.c | 100 +++++++++++++----------- 5 files changed, 87 insertions(+), 61 deletions(-) create mode 100644 examples/textures/textures_image_generation.png (limited to 'src') diff --git a/.gitignore b/.gitignore index 99b04ee4..016b8fa3 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,7 @@ Thumbs.db *.sbr *.sdf obj/ -# [Rr]elease/ +[Rr]elease/ [Rr]elease.win32/ _ReSharper*/ [Tt]est[Rr]esult* diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 0dc78f5a..8f87e689 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -2,28 +2,29 @@ * * raylib [textures] example - Procedural images generation * -* This example has been created using raylib 1.7 (www.raylib.com) +* This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2O17 Ramon Santamaria (@raysan5) +* Copyright (c) 2O17 Wilhem Barbier (@nounoursheureux) * ********************************************************************************************/ #include "raylib.h" -#define TEXTURES_NUM 7 // for now we have 7 generation algorithms +#define TEXTURES_NUM 7 // for now we have 7 generation algorithms int main() { + // Initialization + //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); - SetTargetFPS(60); Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); - Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, 0.f, WHITE, BLACK); + Image radialGradient = GenImageGradientRadial(screenWidth, screenHeight, 0.f, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); @@ -39,20 +40,37 @@ int main() textures[6] = LoadTextureFromImage(cellular); int currentTexture = 0; - + + SetTargetFPS(60); + //--------------------------------------------------------------------------------------- + + // Main game loop while (!WindowShouldClose()) { + // Update + //---------------------------------------------------------------------------------- if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { currentTexture = (currentTexture + 1) % TEXTURES_NUM; // cycle between the 5 textures } + //---------------------------------------------------------------------------------- + // Draw + //---------------------------------------------------------------------------------- BeginDrawing(); + ClearBackground(RAYWHITE); + DrawTexture(textures[currentTexture], 0, 0, WHITE); + EndDrawing(); + //---------------------------------------------------------------------------------- } + // De-Initialization + //-------------------------------------------------------------------------------------- + + // Unload image data (CPU RAM) UnloadImage(verticalGradient); UnloadImage(horizontalGradient); UnloadImage(radialGradient); @@ -60,10 +78,12 @@ int main() UnloadImage(whiteNoise); UnloadImage(perlinNoise); UnloadImage(cellular); - for (int i = 0; i < TEXTURES_NUM; i++) // unload the textures - { - UnloadTexture(textures[i]); - } - - CloseWindow(); + + // Unload textures data (GPU VRAM) + for (int i = 0; i < TEXTURES_NUM; i++) UnloadTexture(textures[i]); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; } diff --git a/examples/textures/textures_image_generation.png b/examples/textures/textures_image_generation.png new file mode 100644 index 00000000..a272b405 Binary files /dev/null and b/examples/textures/textures_image_generation.png differ diff --git a/src/raylib.h b/src/raylib.h index 3d09eff0..04aa3b5a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -876,7 +876,7 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient -RLAPI Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient +RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise diff --git a/src/textures.c b/src/textures.c index 28bc27f8..0a8d7591 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1453,13 +1453,13 @@ Image GenImageGradientV(int width, int height, Color top, Color bottom) for (int j = 0; j < height; j++) { - float factor = (float)j / (float)height; + float factor = (float)j/(float)height; for (int i = 0; i < width; i++) { - pixels[j*width + i].r = (int)((float)bottom.r * factor + (float)top.r * (1.f - factor)); - pixels[j*width + i].g = (int)((float)bottom.g * factor + (float)top.g * (1.f - factor)); - pixels[j*width + i].b = (int)((float)bottom.b * factor + (float)top.b * (1.f - factor)); - pixels[j*width + i].a = (int)((float)bottom.a * factor + (float)top.a * (1.f - factor)); + pixels[j*width + i].r = (int)((float)bottom.r*factor + (float)top.r*(1.f - factor)); + pixels[j*width + i].g = (int)((float)bottom.g*factor + (float)top.g*(1.f - factor)); + pixels[j*width + i].b = (int)((float)bottom.b*factor + (float)top.b*(1.f - factor)); + pixels[j*width + i].a = (int)((float)bottom.a*factor + (float)top.a*(1.f - factor)); } } @@ -1476,13 +1476,13 @@ Image GenImageGradientH(int width, int height, Color left, Color right) for (int i = 0; i < width; i++) { - float factor = (float)i / (float)width; + float factor = (float)i/(float)width; for (int j = 0; j < height; j++) { - pixels[j*width + i].r = (int)((float)right.r * factor + (float)left.r * (1.f - factor)); - pixels[j*width + i].g = (int)((float)right.g * factor + (float)left.g * (1.f - factor)); - pixels[j*width + i].b = (int)((float)right.b * factor + (float)left.b * (1.f - factor)); - pixels[j*width + i].a = (int)((float)right.a * factor + (float)left.a * (1.f - factor)); + pixels[j*width + i].r = (int)((float)right.r*factor + (float)left.r*(1.f - factor)); + pixels[j*width + i].g = (int)((float)right.g*factor + (float)left.g*(1.f - factor)); + pixels[j*width + i].b = (int)((float)right.b*factor + (float)left.b*(1.f - factor)); + pixels[j*width + i].a = (int)((float)right.a*factor + (float)left.a*(1.f - factor)); } } @@ -1493,25 +1493,28 @@ Image GenImageGradientH(int width, int height, Color left, Color right) } // Generate image: radial gradient -Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer) +Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer) { - Color *pixels = (Color*)malloc(width * height * sizeof(Color)); - float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + float radius = (width < height) ? (float)width/2.0f : (float)height/2.0f; - float center_x = (float)width / 2.f; - float center_y = (float)height / 2.f; + float centerX = (float)width/2.0f; + float centerY = (float)height/2.0f; + for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - float dist = hypotf((float)x - center_x, (float)y - center_y); - float factor = (dist - radius * density) / (radius * (1.f - density)); + float dist = hypotf((float)x - centerX, (float)y - centerY); + float factor = (dist - radius*density)/(radius*(1.0f - density)); + factor = fmax(factor, 0.f); factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check - pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); - pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); - pixels[y*width + x].b = (int)((float)outer.b * factor + (float)inner.b * (1.f - factor)); - pixels[y*width + x].a = (int)((float)outer.a * factor + (float)inner.a * (1.f - factor)); + + pixels[y*width + x].r = (int)((float)outer.r*factor + (float)inner.r*(1.0f - factor)); + pixels[y*width + x].g = (int)((float)outer.g*factor + (float)inner.g*(1.0f - factor)); + pixels[y*width + x].b = (int)((float)outer.b*factor + (float)inner.b*(1.0f - factor)); + pixels[y*width + x].a = (int)((float)outer.a*factor + (float)inner.a*(1.0f - factor)); } } @@ -1530,7 +1533,7 @@ Image GenImageChecked(int width, int height, int checksX, int checksY, Color col { for (int x = 0; x < width; x++) { - if ((x/checksX + y/checksY) % 2 == 0) pixels[y*width + x] = col1; + if ((x/checksX + y/checksY)%2 == 0) pixels[y*width + x] = col1; else pixels[y*width + x] = col2; } } @@ -1548,7 +1551,7 @@ Image GenImageWhiteNoise(int width, int height, float factor) for (int i = 0; i < width*height; i++) { - if (GetRandomValue(0, 99) < (int)(factor * 100.f)) pixels[i] = WHITE; + if (GetRandomValue(0, 99) < (int)(factor*100.0f)) pixels[i] = WHITE; else pixels[i] = BLACK; } @@ -1561,17 +1564,19 @@ Image GenImageWhiteNoise(int width, int height, float factor) // Generate image: perlin noise Image GenImagePerlinNoise(int width, int height, float scale) { - Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - float nx = (float)x * scale / (float)width; - float ny = (float)y * scale / (float)height; + float nx = (float)x*scale/(float)width; + float ny = (float)y*scale/(float)height; + // we need to translate the data from [-1; 1] to [0; 1] - float p = (stb_perlin_fbm_noise3(nx, ny, 1.f, 2.f, 0.5f, 6, 0, 0, 0) + 1.f) / 2.f; - int intensity = (int)(p * 255.f); + float p = (stb_perlin_fbm_noise3(nx, ny, 1.0f, 2.0f, 0.5f, 6, 0, 0, 0) + 1.0f) / 2.0f; + + int intensity = (int)(p * 255.0f); pixels[y*width + x] = (Color){intensity, intensity, intensity, 255}; } } @@ -1585,54 +1590,55 @@ Image GenImagePerlinNoise(int width, int height, float scale) // Generate image: cellular algorithm. Bigger tileSize means bigger cells Image GenImageCellular(int width, int height, int tileSize) { - Color *pixels = (Color*)malloc(width*height*sizeof(Color)); + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); - int seeds_per_row = width / tileSize; - int seeds_per_col = height / tileSize; - int seeds_count = seeds_per_row * seeds_per_col; + int seedsPerRow = width/tileSize; + int seedsPerCol = height/tileSize; + int seedsCount = seedsPerRow * seedsPerCol; - Vector2* seeds = (Vector2*)malloc(seeds_count * sizeof(Vector2)); + Vector2 *seeds = (Vector2 *)malloc(seedsCount*sizeof(Vector2)); - for (int i = 0; i < seeds_count; i++) + for (int i = 0; i < seedsCount; i++) { - int y = (i / seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); - int x = (i % seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); + int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1); + int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1); seeds[i] = (Vector2){x, y}; } for (int y = 0; y < height; y++) { - int tile_y = y / tileSize; + int tileY = y/tileSize; + for (int x = 0; x < width; x++) { - int tile_x = x / tileSize; + int tileX = x/tileSize; - float min_distance = strtod("Inf", NULL); + float minDistance = strtod("Inf", NULL); // Check all adjacent tiles for (int i = -1; i < 2; i++) { - if (tile_x + i < 0 || tile_x + i >= seeds_per_row) continue; + if ((tileX + i < 0) || (tileX + i >= seedsPerRow)) continue; for (int j = -1; j < 2; j++) { - if (tile_y + j < 0 || tile_y + j >= seeds_per_col) continue; + if ((tileY + j < 0) || (tileY + j >= seedsPerCol)) continue; - Vector2 neighbor_seed = seeds[(tile_y+j) * seeds_per_row + tile_x+i]; + Vector2 neighborSeed = seeds[(tileY + j)*seedsPerRow + tileX + i]; - float dist = hypot(x - (int)neighbor_seed.x, y - (int)neighbor_seed.y); - min_distance = fmin(min_distance, dist); + float dist = hypot(x - (int)neighborSeed.x, y - (int)neighborSeed.y); + minDistance = fmin(minDistance, dist); } } // I made this up but it seems to give good results at all tile sizes - int intensity = (int)(min_distance * 256.f / tileSize); + int intensity = (int)(minDistance*256.0f/tileSize); if (intensity > 255) intensity = 255; - Color c = {intensity, intensity, intensity, 255}; - pixels[y*width + x] = c; + pixels[y*width + x] = (Color){ intensity, intensity, intensity, 255 }; } } + free(seeds); Image image = LoadImageEx(pixels, width, height); -- cgit v1.2.3 From 36fcffeaaef30cfece6694ce8976b92fd9b106c6 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 2 Jul 2017 19:29:21 +0200 Subject: Incremented version number for reference --- src/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 36180746..a447d750 100644 --- a/src/core.c +++ b/src/core.c @@ -412,7 +412,7 @@ static void *GamepadThread(void *arg); // Mouse reading thread // Initialize window and OpenGL context void InitWindow(int width, int height, const char *title) { - TraceLog(LOG_INFO, "Initializing raylib (v1.7.0)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.8.0)"); // Store window title (could be useful...) windowTitle = title; @@ -475,7 +475,7 @@ void InitWindow(int width, int height, const char *title) // Initialize Android activity void InitWindow(int width, int height, void *state) { - TraceLog(LOG_INFO, "Initializing raylib (v1.7.0)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.8.0)"); app_dummy(); -- cgit v1.2.3 From 53fbeeea718db5ab0a5ff16fc7971144588685cd Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 8 Jul 2017 14:19:27 +0200 Subject: Corected some issues with jar_xm Problems when compiling with VS2015 Probably DEBUG(...) macro is not the best naming... --- src/external/jar_xm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/external/jar_xm.h b/src/external/jar_xm.h index 7f0517df..15b31fd0 100644 --- a/src/external/jar_xm.h +++ b/src/external/jar_xm.h @@ -308,7 +308,7 @@ uint64_t jar_xm_get_remaining_samples(jar_xm_context_t* ctx); #include #include -#ifdef JAR_XM_DEBUG +#if JAR_XM_DEBUG //JAR_XM_DEBUG defined as 0 #include #define DEBUG(fmt, ...) do { \ fprintf(stderr, "%s(): " fmt "\n", __func__, __VA_ARGS__); \ @@ -782,7 +782,7 @@ uint64_t jar_xm_get_latest_trigger_of_channel(jar_xm_context_t* ctx, uint16_t ch #define READ_U32(offset) ((uint32_t)READ_U16(offset) | ((uint32_t)READ_U16((offset) + 2) << 16)) #define READ_MEMCPY(ptr, offset, length) memcpy_pad(ptr, length, moddata, moddata_length, offset) -static inline void memcpy_pad(void* dst, size_t dst_len, const void* src, size_t src_len, size_t offset) { +static void memcpy_pad(void* dst, size_t dst_len, const void* src, size_t src_len, size_t offset) { uint8_t* dst_c = dst; const uint8_t* src_c = src; -- cgit v1.2.3 From 8ca85507390132ed65d02bd3ac2f6c72fbb90c1c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 8 Jul 2017 14:22:48 +0200 Subject: Removed function reference --- src/rlgl.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/rlgl.h b/src/rlgl.h index 57e77c7d..36ff7889 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -400,7 +400,6 @@ Shader LoadShader(char *vsFileName, char *fsFileName); // Load a cu void UnloadShader(Shader shader); // Unload a custom shader from memory Shader GetDefaultShader(void); // Get default shader -Shader GetStandardShader(void); // Get default shader Texture2D GetDefaultTexture(void); // Get default texture int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location -- cgit v1.2.3 From 6546474fa45234ed0a84f62be705d9a9aee43079 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 17 Jul 2017 00:33:40 +0200 Subject: Manual integration of material-pbr into develop --- examples/models/models_cubicmap.c | 10 +- examples/models/models_material_pbr.c | 185 +++++++ examples/models/models_material_pbr.png | Bin 0 -> 193874 bytes examples/models/models_skybox.c | 89 +++ examples/models/models_skybox.png | Bin 0 -> 723949 bytes examples/shaders/shaders_model_shader.c | 2 +- src/core.c | 10 +- src/models.c | 535 +++++++++++++----- src/raylib.h | 125 +++-- src/rlgl.c | 952 +++++++++++++++++++++++--------- src/rlgl.h | 205 ++++--- src/shapes.c | 10 +- src/textures.c | 22 +- 13 files changed, 1597 insertions(+), 548 deletions(-) create mode 100644 examples/models/models_material_pbr.c create mode 100644 examples/models/models_material_pbr.png create mode 100644 examples/models/models_skybox.c create mode 100644 examples/models/models_skybox.png (limited to 'src') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 0e613029..ceef6378 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -25,11 +25,13 @@ int main() Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) - Model map = LoadCubicmap(image); // Load cubicmap model (generate model from image) + + Mesh mesh = GenMeshCubicmap(image, VectorOne()); + Model model = LoadModelFromMesh(mesh, false); // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - map.material.texDiffuse = texture; // Set map diffuse texture + model.material.maps[TEXMAP_DIFFUSE].tex = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position @@ -56,7 +58,7 @@ int main() Begin3dMode(camera); - DrawModel(map, mapPosition, 1.0f, WHITE); + DrawModel(model, mapPosition, 1.0f, WHITE); End3dMode(); @@ -76,7 +78,7 @@ int main() //-------------------------------------------------------------------------------------- UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture - UnloadModel(map); // Unload map model + UnloadModel(model); // Unload map model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c new file mode 100644 index 00000000..9380bd91 --- /dev/null +++ b/examples/models/models_material_pbr.c @@ -0,0 +1,185 @@ +/******************************************************************************************* +* +* raylib [models] example - PBR material +* +* This example has been created using raylib 1.8 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2017 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +#define MAX_LIGHTS 4 // Max lights supported by shader +#define LIGHT_DISTANCE 3.5f // Light distance from world center +#define LIGHT_HEIGHT 1.0f // Light height position + +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +typedef struct { + bool enabled; + LightType type; + Vector3 position; + Vector3 target; + Color color; + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +int lightsCount = 0; // Current amount of created lights + +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader +void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) + InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material"); + + // Define the camera to look into our 3d world + Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; + + // Load model and PBR material + Model model = LoadModel("resources/pbr/trooper.obj"); + + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); + + SetMaterialTexture(&model.material, TEXMAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&model.material, TEXMAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&model.material, TEXMAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&model.material, TEXMAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&model.material, TEXMAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + + // Set textures filtering for better quality + SetTextureFilter(model.material.maps[TEXMAP_ALBEDO].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_NORMAL].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_METALNESS].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_ROUGHNESS].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_OCCLUSION].tex, FILTER_BILINEAR); + + int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); + SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode + + // Define lights attributes + Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.material.shader), + CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.material.shader), + CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.material.shader), + CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.material.shader) }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + + // Send to material PBR shader camera view position + float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; + SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, 3); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(model, VectorZero(), 1.0f, WHITE); + + DrawGrid(10, 1.0f); + + End3dMode(); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(model); // Unload skybox model + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +// Defines a light and get locations from PBR shader +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = pos; + light.target = targ; + light.color = color; + + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + lightsCount++; + } + + return light; +} + +// Send to PBR shader light values +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); + SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, 3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, 3); + + // Send to shader light color values + float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, diff, 4); +} diff --git a/examples/models/models_material_pbr.png b/examples/models/models_material_pbr.png new file mode 100644 index 00000000..cde171b9 Binary files /dev/null and b/examples/models/models_material_pbr.png differ diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c new file mode 100644 index 00000000..8b302b1c --- /dev/null +++ b/examples/models/models_skybox.c @@ -0,0 +1,89 @@ +/******************************************************************************************* +* +* raylib [models] example - Skybox loading and drawing +* +* This example has been created using raylib 1.8 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2017 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing"); + + // Define the camera to look into our 3d world + Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; + + // Load skybox model and shader + Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); + Model skybox = LoadModelFromMesh(cube, false); + skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); + + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + skybox.material.maps[TEXMAP_CUBEMAP].tex = rlGenMapCubemap(texHDR, 512); + SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ TEXMAP_CUBEMAP }, 1); + + // Get skybox shader locations + skybox.material.shader.locs[LOC_MATRIX_PROJECTION] = GetShaderLocation(skybox.material.shader, "projection"); + skybox.material.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(skybox.material.shader, "view"); + + // Then before rendering, configure the viewport to the actual screen dimensions + Matrix proj = MatrixPerspective(60.0, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); + MatrixTranspose(&proj); + SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_PROJECTION], proj); + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + + Matrix view = MatrixLookAt(camera.position, camera.target, camera.up); + SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_VIEW], view); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(skybox, VectorZero(), 1.0f, RED); + + DrawGrid(10, 1.0f); + + End3dMode(); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(skybox); // Unload skybox model + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/models/models_skybox.png b/examples/models/models_skybox.png new file mode 100644 index 00000000..31694fa5 Binary files /dev/null and b/examples/models/models_skybox.png differ diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index 51e9c1b3..ef5665d2 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -38,7 +38,7 @@ int main() "resources/shaders/glsl330/grayscale.fs"); // Load model shader dwarf.material.shader = shader; // Set shader effect to 3d model - dwarf.material.texDiffuse = texture; // Bind texture to model + dwarf.material.maps[TEXMAP_DIFFUSE].tex = texture; // Bind texture to model Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position diff --git a/src/core.c b/src/core.c index a447d750..ad905d4e 100644 --- a/src/core.c +++ b/src/core.c @@ -809,7 +809,7 @@ void EndDrawing(void) { // Get image data for the current frame (from backbuffer) // NOTE: This process is very slow... :( - unsigned char *screenData = rlglReadScreenPixels(screenWidth, screenHeight); + unsigned char *screenData = rlReadScreenPixels(screenWidth, screenHeight); GifWriteFrame(screenData, screenWidth, screenHeight, 10, 8, false); free(screenData); // Free image data @@ -994,10 +994,10 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) MatrixTranspose(&matView); //#define USE_RLGL_UNPROJECT -#if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlglUnproject() +#if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlUnproject() - Vector3 nearPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); - Vector3 farPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); + Vector3 nearPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); + Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); #else // OPTION 2: Compute unprojection directly here @@ -1201,7 +1201,7 @@ void SetConfigFlags(char flags) void TakeScreenshot(const char *fileName) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) - unsigned char *imgData = rlglReadScreenPixels(renderWidth, renderHeight); + unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight); SavePNG(fileName, imgData, renderWidth, renderHeight, 4); // Save image as PNG free(imgData); diff --git a/src/models.c b/src/models.c index 286581df..d9404c12 100644 --- a/src/models.c +++ b/src/models.c @@ -76,9 +76,6 @@ static Mesh LoadOBJ(const char *fileName); // Load OBJ mesh data static Material LoadMTL(const char *fileName); // Load MTL material data #endif -static Mesh GenMeshHeightmap(Image image, Vector3 size); -static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); - //---------------------------------------------------------------------------------- // Module Functions Definition //---------------------------------------------------------------------------------- @@ -587,110 +584,32 @@ void DrawGizmo(Vector3 position) rlPopMatrix(); } -// Load mesh from file -Mesh LoadMesh(const char *fileName) -{ - Mesh mesh = { 0 }; - -#if defined(SUPPORT_FILEFORMAT_OBJ) - if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); -#else - TraceLog(LOG_WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); -#endif - - if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); - else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - - // TODO: Initialize default mesh data in case loading fails, maybe a cube? - - return mesh; -} - -// Load mesh from vertex data -// NOTE: All vertex data arrays must be same size: vertexCount -Mesh LoadMeshEx(int vertexCount, float *vData, float *vtData, float *vnData, Color *cData) -{ - Mesh mesh = { 0 }; - - mesh.vertexCount = vertexCount; - mesh.triangleCount = vertexCount/3; - mesh.vertices = vData; - mesh.texcoords = vtData; - mesh.texcoords2 = NULL; - mesh.normals = vnData; - mesh.tangents = NULL; - mesh.colors = (unsigned char *)cData; - mesh.indices = NULL; - - rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - - return mesh; -} - -// Load model from file +// Load model from files (mesh and material) Model LoadModel(const char *fileName) { Model model = { 0 }; model.mesh = LoadMesh(fileName); model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); - - return model; -} - -// Load model from mesh data -Model LoadModelFromMesh(Mesh data, bool dynamic) -{ - Model model = { 0 }; - - model.mesh = data; - - rlglLoadMesh(&model.mesh, dynamic); // Upload vertex data to GPU - - model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); + model.material = LoadMaterialDefault(); return model; } -// Load heightmap model from image data -// NOTE: model map size is defined in generic units -Model LoadHeightmap(Image heightmap, Vector3 size) +// Load model from generated mesh +Model LoadModelFromMesh(Mesh mesh, bool dynamic) { Model model = { 0 }; - - model.mesh = GenMeshHeightmap(heightmap, size); - - rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - - model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); - - return model; -} - -// Load cubes-based map model from image data -Model LoadCubicmap(Image cubicmap) -{ - Model model = { 0 }; - - model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0f, 1.5f, 1.0f }); - - rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - + + rlLoadMesh(&mesh, dynamic); + + model.mesh = mesh; model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); + model.material = LoadMaterialDefault(); return model; } -// Unload mesh from memory (RAM and/or VRAM) -void UnloadMesh(Mesh *mesh) -{ - rlglUnloadMesh(mesh); -} - // Unload model from memory (RAM and/or VRAM) void UnloadModel(Model model) { @@ -700,49 +619,190 @@ void UnloadModel(Model model) TraceLog(LOG_INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); } -// Load material data (from file) -Material LoadMaterial(const char *fileName) +// Load mesh from file +Mesh LoadMesh(const char *fileName) { - Material material = { 0 }; + Mesh mesh = { 0 }; -#if defined(SUPPORT_FILEFORMAT_MTL) - if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); +#if defined(SUPPORT_FILEFORMAT_OBJ) + if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); #else - TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); + TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); #endif - return material; -} - -// Load default material (uses default models shader) -Material LoadDefaultMaterial(void) -{ - Material material = { 0 }; + if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); + else rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - material.shader = GetDefaultShader(); - material.texDiffuse = GetDefaultTexture(); // White texture (1x1 pixel) - //material.texNormal; // NOTE: By default, not set - //material.texSpecular; // NOTE: By default, not set - - material.colDiffuse = WHITE; // Diffuse color - material.colAmbient = WHITE; // Ambient color - material.colSpecular = WHITE; // Specular color + // TODO: Initialize default mesh data in case loading fails, maybe a cube? - material.glossiness = 100.0f; // Glossiness level + return mesh; +} - return material; +// Unload mesh from memory (RAM and/or VRAM) +void UnloadMesh(Mesh *mesh) +{ + rlUnloadMesh(mesh); } -// Unload material from memory -void UnloadMaterial(Material material) +// Generated cuboid mesh +Mesh GenMeshCube(float width, float height, float length) { - rlDeleteTextures(material.texDiffuse.id); - rlDeleteTextures(material.texNormal.id); - rlDeleteTextures(material.texSpecular.id); + Mesh mesh = { 0 }; + /* + float vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + */ + float vertices[] = { + -width/2, -height/2, length/2, + width/2, -height/2, length/2, + width/2, height/2, length/2, + -width/2, height/2, length/2, + -width/2, -height/2, -length/2, + -width/2, height/2, -length/2, + width/2, height/2, -length/2, + width/2, -height/2, -length/2, + -width/2, height/2, -length/2, + -width/2, height/2, length/2, + width/2, height/2, length/2, + width/2, height/2, -length/2, + -width/2, -height/2, -length/2, + width/2, -height/2, -length/2, + width/2, -height/2, length/2, + -width/2, -height/2, length/2, + width/2, -height/2, -length/2, + width/2, height/2, -length/2, + width/2, height/2, length/2, + width/2, -height/2, length/2, + -width/2, -height/2, -length/2, + -width/2, -height/2, length/2, + -width/2, height/2, length/2, + -width/2, height/2, -length/2 + }; + + float texcoords[] = { + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f + }; + + float normals[] = { + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f + }; + + mesh.vertices = (float *)malloc(24*3*sizeof(float)); + memcpy(mesh.vertices, vertices, 24*3*sizeof(float)); + + mesh.texcoords = (float *)malloc(24*2*sizeof(float)); + memcpy(mesh.texcoords, texcoords, 24*2*sizeof(float)); + + mesh.normals = (float *)malloc(24*3*sizeof(float)); + memcpy(mesh.normals, normals, 24*3*sizeof(float)); + + mesh.indices = (unsigned short *)malloc(36*sizeof(unsigned short)); + + int k = 0; + + // Indices can be initialized right now + for (int i = 0; i < 36; i+=6) + { + mesh.indices[i] = 4*k; + mesh.indices[i+1] = 4*k+1; + mesh.indices[i+2] = 4*k+2; + mesh.indices[i+3] = 4*k; + mesh.indices[i+4] = 4*k+2; + mesh.indices[i+5] = 4*k+3; + + k++; + } + + mesh.vertexCount = 24; + mesh.triangleCount = 12; + + return mesh; } // Generate a mesh from heightmap -static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) +Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) @@ -847,7 +907,7 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) return mesh; } -static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) +Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { Mesh mesh = { 0 }; @@ -1201,6 +1261,202 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) return mesh; } +// Load material data (from file) +Material LoadMaterial(const char *fileName) +{ + Material material = { 0 }; + +#if defined(SUPPORT_FILEFORMAT_MTL) + if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); +#else + TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); +#endif + + return material; +} + +// Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) +Material LoadMaterialDefault(void) +{ + Material material = { 0 }; + + material.shader = GetShaderDefault(); + material.maps[TEXMAP_DIFFUSE].tex = GetTextureDefault(); // White texture (1x1 pixel) + //material.maps[TEXMAP_NORMAL].tex; // NOTE: By default, not set + //material.maps[TEXMAP_SPECULAR].tex; // NOTE: By default, not set + + material.maps[TEXMAP_DIFFUSE].color = WHITE; // Diffuse color + material.maps[TEXMAP_SPECULAR].color = WHITE; // Specular color + + return material; +} + +// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) +Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) +{ + Material mat = { 0 }; + + #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader + #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader + + mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); + + // Get required locations points for PBR material + // NOTE: Those location names must be available and used in the shader code + mat.shader.locs[LOC_TEXMAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_TEXMAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_TEXMAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_TEXMAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_TEXMAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_TEXMAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_TEXMAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_TEXMAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_TEXMAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_TEXMAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + + // Set view matrix location + mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); + mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); + mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); + + // Set up material properties color + mat.maps[TEXMAP_ALBEDO].color = albedo; + mat.maps[TEXMAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[TEXMAP_METALNESS].value = metalness; + mat.maps[TEXMAP_ROUGHNESS].value = roughness; + mat.maps[TEXMAP_OCCLUSION].value = 1.0f; + mat.maps[TEXMAP_EMISSION].value = 0.0f; + mat.maps[TEXMAP_HEIGHT].value = 0.0f; + + #define CUBEMAP_SIZE 1024 // Cubemap texture size + #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size + #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size + #define BRDF_SIZE 512 // BRDF LUT texture map size + + // Set up environment materials cubemap + Texture2D cubemap = rlGenMapCubemap(hdr, CUBEMAP_SIZE); + mat.maps[TEXMAP_IRRADIANCE].tex = rlGenMapIrradiance(cubemap, IRRADIANCE_SIZE); + mat.maps[TEXMAP_PREFILTER].tex = rlGenMapPrefilter(cubemap, PREFILTERED_SIZE); + mat.maps[TEXMAP_BRDF].tex = rlGenMapBRDF(cubemap, BRDF_SIZE); + UnloadTexture(cubemap); + + // NOTE: All maps textures are set to { 0 } + + // Reset viewport dimensions to default + rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + return mat; +} + +// Unload material from memory +void UnloadMaterial(Material material) +{ + // Unload material shader + UnloadShader(material.shader); + + // Unload loaded texture maps + for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + { + // NOTE: We already check for (tex.id > 0) inside function + rlDeleteTextures(material.maps[i].tex.id); + } +} + +// Set material texture +void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) +{ + mat->maps[texmapType].tex = texture; + + // Update MaterialProperty use sampler state to use texture fetch instead of color attribute + int location = -1; + switch (texmapType) + { + case TEXMAP_ALBEDO: + { + location = GetShaderLocation(mat->shader, "albedo.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_NORMAL: + { + location = GetShaderLocation(mat->shader, "normals.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_METALNESS: + { + location = GetShaderLocation(mat->shader, "metalness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_ROUGHNESS: + { + location = GetShaderLocation(mat->shader, "roughness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_OCCLUSION: + { + location = GetShaderLocation(mat->shader, "occlusion.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_EMISSION: + { + location = GetShaderLocation(mat->shader, "emission.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_HEIGHT: + { + location = GetShaderLocation(mat->shader, "height.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + } +} + +// Unset texture from material and unload it from GPU +void UnsetMaterialTexture(Material *mat, int texmapType) +{ + UnloadTexture(mat->maps[texmapType].tex); + mat->maps[texmapType].tex = (Texture2D){ 0 }; + + // Update MaterialProperty use sampler state to use texture fetch instead of color attribute + int location = -1; + switch (texmapType) + { + case TEXMAP_ALBEDO: + { + location = GetShaderLocation(mat->shader, "albedo.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_NORMAL: + { + location = GetShaderLocation(mat->shader, "normals.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_METALNESS: + { + location = GetShaderLocation(mat->shader, "metalness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_ROUGHNESS: + { + location = GetShaderLocation(mat->shader, "roughness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_OCCLUSION: + { + location = GetShaderLocation(mat->shader, "occlusion.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_EMISSION: + { + location = GetShaderLocation(mat->shader, "emission.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_HEIGHT: + { + location = GetShaderLocation(mat->shader, "height.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + } +} + // Draw a model (with texture if set) void DrawModel(Model model, Vector3 position, float scale, Color tint) { @@ -1225,9 +1481,9 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(model.transform, matTransform); - model.material.colDiffuse = tint; // TODO: Multiply tint color by diffuse color? + model.material.maps[TEXMAP_DIFFUSE].color = tint; // TODO: Multiply tint color by diffuse color? - rlglDrawMesh(model.mesh, model.material, model.transform); + rlDrawMesh(model.mesh, model.material, model.transform); } // Draw a model wires (with texture if set) @@ -1980,23 +2236,24 @@ static Material LoadMTL(const char *fileName) case 'a': // Ka float float float Ambient color (RGB) { sscanf(buffer, "Ka %f %f %f", &color.x, &color.y, &color.z); - material.colAmbient.r = (unsigned char)(color.x*255); - material.colAmbient.g = (unsigned char)(color.y*255); - material.colAmbient.b = (unsigned char)(color.z*255); + // TODO: Support ambient color + //material.colAmbient.r = (unsigned char)(color.x*255); + //material.colAmbient.g = (unsigned char)(color.y*255); + //material.colAmbient.b = (unsigned char)(color.z*255); } break; case 'd': // Kd float float float Diffuse color (RGB) { sscanf(buffer, "Kd %f %f %f", &color.x, &color.y, &color.z); - material.colDiffuse.r = (unsigned char)(color.x*255); - material.colDiffuse.g = (unsigned char)(color.y*255); - material.colDiffuse.b = (unsigned char)(color.z*255); + material.maps[TEXMAP_DIFFUSE].color.r = (unsigned char)(color.x*255); + material.maps[TEXMAP_DIFFUSE].color.g = (unsigned char)(color.y*255); + material.maps[TEXMAP_DIFFUSE].color.b = (unsigned char)(color.z*255); } break; case 's': // Ks float float float Specular color (RGB) { sscanf(buffer, "Ks %f %f %f", &color.x, &color.y, &color.z); - material.colSpecular.r = (unsigned char)(color.x*255); - material.colSpecular.g = (unsigned char)(color.y*255); - material.colSpecular.b = (unsigned char)(color.z*255); + material.maps[TEXMAP_SPECULAR].color.r = (unsigned char)(color.x*255); + material.maps[TEXMAP_SPECULAR].color.g = (unsigned char)(color.y*255); + material.maps[TEXMAP_SPECULAR].color.b = (unsigned char)(color.z*255); } break; case 'e': // Ke float float float Emmisive color (RGB) { @@ -2012,7 +2269,7 @@ static Material LoadMTL(const char *fileName) int shininess = 0; sscanf(buffer, "Ns %i", &shininess); - material.glossiness = (float)shininess; + //material.params[PARAM_GLOSSINES] = (float)shininess; } else if (buffer[1] == 'i') // Ni int Refraction index. { @@ -2028,12 +2285,12 @@ static Material LoadMTL(const char *fileName) if (buffer[5] == 'd') // map_Kd string Diffuse color texture map. { result = sscanf(buffer, "map_Kd %s", mapFileName); - if (result != EOF) material.texDiffuse = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_DIFFUSE].tex = LoadTexture(mapFileName); } else if (buffer[5] == 's') // map_Ks string Specular color texture map. { result = sscanf(buffer, "map_Ks %s", mapFileName); - if (result != EOF) material.texSpecular = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_SPECULAR].tex = LoadTexture(mapFileName); } else if (buffer[5] == 'a') // map_Ka string Ambient color texture map. { @@ -2043,12 +2300,12 @@ static Material LoadMTL(const char *fileName) case 'B': // map_Bump string Bump texture map. { result = sscanf(buffer, "map_Bump %s", mapFileName); - if (result != EOF) material.texNormal = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); } break; case 'b': // map_bump string Bump texture map. { result = sscanf(buffer, "map_bump %s", mapFileName); - if (result != EOF) material.texNormal = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); } break; case 'd': // map_d string Opacity texture map. { @@ -2063,7 +2320,7 @@ static Material LoadMTL(const char *fileName) { float alpha = 1.0f; sscanf(buffer, "d %f", &alpha); - material.colDiffuse.a = (unsigned char)(alpha*255); + material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)(alpha*255); } else if (buffer[1] == 'i') // disp string Displacement map { @@ -2073,13 +2330,13 @@ static Material LoadMTL(const char *fileName) case 'b': // bump string Bump texture map { result = sscanf(buffer, "bump %s", mapFileName); - if (result != EOF) material.texNormal = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); } break; case 'T': // Tr float Transparency Tr (alpha). Tr is inverse of d { float ialpha = 0.0f; sscanf(buffer, "Tr %f", &ialpha); - material.colDiffuse.a = (unsigned char)((1.0f - ialpha)*255); + material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)((1.0f - ialpha)*255); } break; case 'r': // refl string Reflection texture map diff --git a/src/raylib.h b/src/raylib.h index 04aa3b5a..c84d6ce4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -291,6 +291,11 @@ #define MAGENTA CLITERAL{ 255, 0, 255, 255 } // Magenta #define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo) +// Shader and material limits +#define MAX_SHADER_LOCATIONS 32 +#define MAX_MATERIAL_TEXTURE_MAPS 12 +#define MAX_MATERIAL_PARAMS 8 + //---------------------------------------------------------------------------------- // Structures Definition //---------------------------------------------------------------------------------- @@ -420,43 +425,24 @@ typedef struct Mesh { unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; -// Shader type (generic shader) +// Shader type (generic) typedef struct Shader { unsigned int id; // Shader program id - - // Vertex attributes locations (default locations) - int vertexLoc; // Vertex attribute location point (default-location = 0) - int texcoordLoc; // Texcoord attribute location point (default-location = 1) - int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) - int normalLoc; // Normal attribute location point (default-location = 2) - int tangentLoc; // Tangent attribute location point (default-location = 4) - int colorLoc; // Color attibute location point (default-location = 3) - - // Uniform locations - int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int colDiffuseLoc; // Diffuse color uniform location point (fragment shader) - int colAmbientLoc; // Ambient color uniform location point (fragment shader) - int colSpecularLoc; // Specular color uniform location point (fragment shader) - - // Texture map locations (generic for any kind of map) - int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) - int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) - int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) + int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS } Shader; -// Material type -typedef struct Material { - Shader shader; // Standard shader (supports 3 map textures) - - Texture2D texDiffuse; // Diffuse texture (binded to shader mapTexture0Loc) - Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) - Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) +// Material texture map +typedef struct TextureMap { + Texture2D tex; + Color color; + float value; +} TextureMap; - Color colDiffuse; // Diffuse color - Color colAmbient; // Ambient color - Color colSpecular; // Specular color - - float glossiness; // Glossiness level (Ranges from 0 to 1000) +// Material type (generic) +typedef struct Material { + Shader shader; + TextureMap maps[MAX_MATERIAL_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_TEXTURE_MAPS + float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS } Material; // Model type @@ -540,6 +526,54 @@ typedef enum { LOG_OTHER } LogType; +typedef enum { + LOC_VERTEX_POSITION = 0, + LOC_VERTEX_TEXCOORD01, + LOC_VERTEX_TEXCOORD02, + LOC_VERTEX_NORMAL, + LOC_VERTEX_TANGENT, + LOC_VERTEX_COLOR, + LOC_MATRIX_MVP, + LOC_MATRIX_MODEL, + LOC_MATRIX_VIEW, + LOC_MATRIX_PROJECTION, + LOC_VECTOR_VIEW, + LOC_COLOR_DIFFUSE, + LOC_COLOR_SPECULAR, + LOC_COLOR_AMBIENT, + LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE + LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR + LOC_TEXMAP_NORMAL, + LOC_TEXMAP_ROUGHNESS, + LOC_TEXMAP_OCCUSION, + LOC_TEXMAP_EMISSION, + LOC_TEXMAP_HEIGHT, + LOC_TEXMAP_CUBEMAP, + LOC_TEXMAP_IRRADIANCE, + LOC_TEXMAP_PREFILTER, + LOC_TEXMAP_BRDF +} ShaderLocationIndex; + +#define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO +#define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS + +typedef enum { + TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE + TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR + TEXMAP_NORMAL = 2, + TEXMAP_ROUGHNESS = 3, + TEXMAP_OCCLUSION, + TEXMAP_EMISSION, + TEXMAP_HEIGHT, + TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_BRDF +} TexmapIndex; + +#define TEXMAP_DIFFUSE TEXMAP_ALBEDO +#define TEXMAP_SPECULAR TEXMAP_METALNESS + // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -944,19 +978,26 @@ RLAPI void DrawGizmo(Vector3 position); //------------------------------------------------------------------------------------ // Model loading/unloading functions +RLAPI Model LoadModel(const char *fileName); // Load model from files (mesh and material) +RLAPI Model LoadModelFromMesh(Mesh mesh, bool dynamic); // Load model from generated mesh +RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) + +// Mesh loading/unloading functions RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file -RLAPI Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData); // Load mesh from vertex data -RLAPI Model LoadModel(const char *fileName); // Load model from file -RLAPI Model LoadModelFromMesh(Mesh data, bool dynamic); // Load model from mesh data -RLAPI Model LoadHeightmap(Image heightmap, Vector3 size); // Load heightmap model from image data -RLAPI Model LoadCubicmap(Image cubicmap); // Load cubes-based map model from image data +//RLAPI void UpdateMesh(Mesh *mesh, int type, void *data); // Update mesh data (CPU and GPU) RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM) -RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) + +RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh +RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data +RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data // Material loading/unloading functions RLAPI Material LoadMaterial(const char *fileName); // Load material from file -RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader) +RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) +RLAPI Material LoadMaterialPBR(Texture2D cubemap, Color albedo, float metalness, float roughness); // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS...) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) +RLAPI void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture); // Set material texture +RLAPI void UnsetMaterialTexture(Material *mat, int texmapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -993,8 +1034,10 @@ RLAPI char *LoadText(const char *fileName); // Loa RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Load shader from files and bind default locations RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) -RLAPI Shader GetDefaultShader(void); // Get default shader -RLAPI Texture2D GetDefaultTexture(void); // Get default texture +RLAPI Shader GetShaderDefault(void); // Get default shader +RLAPI Texture2D GetTextureDefault(void); // Get default texture + +RLAPI Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture // Shader configuration functions RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location diff --git a/src/rlgl.c b/src/rlgl.c index e3576c30..7f349347 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -333,18 +333,21 @@ static int screenHeight; // Default framebuffer height // Module specific Functions Declaration //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat); +static void LoadTextureCompressed(unsigned char *data, int width, int height, int compressedFormat, int mipmapCount); static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id -static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring) -static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) -static void UnloadDefaultShader(void); // Unload default shader +static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring) +static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) +static void UnLoadShaderDefault(void); // Unload default shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +static void RenderCube(void); +static void RenderQuad(void); + #if defined(SUPPORT_VR_SIMULATOR) static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); // Set internal projection and modelview matrix depending on eye @@ -923,16 +926,16 @@ void rlDisableWireMode(void) // Unload texture from GPU memory void rlDeleteTextures(unsigned int id) { - if (id != 0) glDeleteTextures(1, &id); + if (id > 0) glDeleteTextures(1, &id); } // Unload render texture from GPU memory void rlDeleteRenderTextures(RenderTexture2D target) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (target.id != 0) glDeleteFramebuffers(1, &target.id); - if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); - if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); + if (target.id > 0) glDeleteFramebuffers(1, &target.id); + if (target.texture.id > 0) glDeleteTextures(1, &target.texture.id); + if (target.depth.id > 0) glDeleteTextures(1, &target.depth.id); TraceLog(LOG_INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); #endif @@ -1003,6 +1006,29 @@ int rlGetVersion(void) #endif } +// Get world coordinates from screen coordinates +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view) +{ + Vector3 result = { 0.0f, 0.0f, 0.0f }; + + // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it + Matrix matProjView = MatrixMultiply(proj, view); + MatrixInvert(&matProjView); + + // Create quaternion from source point + Quaternion quat = { source.x, source.y, source.z, 1.0f }; + + // Multiply quat point by unproject matrix + QuaternionTransform(&quat, matProjView); + + // Normalized world points in vectors + result.x = quat.x/quat.w; + result.y = quat.y/quat.w; + result.z = quat.z/quat.w; + + return result; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - rlgl Functions //---------------------------------------------------------------------------------- @@ -1183,13 +1209,13 @@ void rlglInit(int width, int height) // Init default white texture unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) - whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); + whiteTexture = rlLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); if (whiteTexture != 0) TraceLog(LOG_INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); else TraceLog(LOG_WARNING, "Base white texture could not be loaded"); // Init default Shader (customized for GL 3.3 and ES2) - defaultShader = LoadDefaultShader(); + defaultShader = LoadShaderDefault(); currentShader = defaultShader; // Init default vertex arrays buffers (lines, triangles, quads) @@ -1261,7 +1287,7 @@ void rlglInit(int width, int height) void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - UnloadDefaultShader(); + UnloadShaderDefault(); UnloadDefaultBuffers(); // Delete default white texture @@ -1277,7 +1303,7 @@ void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: In a future version, models could be stored in a stack... - //for (int i = 0; i < modelsCount; i++) rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); + //for (int i = 0; i < modelsCount; i++) rlDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); // NOTE: Default buffers upload and draw UpdateDefaultBuffers(); @@ -1308,31 +1334,8 @@ void rlglLoadExtensions(void *loader) #endif } -// Get world coordinates from screen coordinates -Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) -{ - Vector3 result = { 0.0f, 0.0f, 0.0f }; - - // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it - Matrix matProjView = MatrixMultiply(proj, view); - MatrixInvert(&matProjView); - - // Create quaternion from source point - Quaternion quat = { source.x, source.y, source.z, 1.0f }; - - // Multiply quat point by unproject matrix - QuaternionTransform(&quat, matProjView); - - // Normalized world points in vectors - result.x = quat.x/quat.w; - result.y = quat.y/quat.w; - result.z = quat.z/quat.w; - - return result; -} - // Convert image data to OpenGL texture (returns OpenGL valid Id) -unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount) +unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount) { glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding @@ -1427,17 +1430,17 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; - case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; - case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break; - case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 - case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break; + case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break; + case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_ETC1_RGB8_OES, mipmapCount); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB8_ETC2, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA8_ETC2_EAC, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 default: TraceLog(LOG_WARNING, "Texture format not recognized"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) @@ -1452,18 +1455,18 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; #if defined(GRAPHICS_API_OPENGL_ES2) - case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; // Requries extension OES_texture_float - case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; // NOTE: Not supported by WebGL - case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break; // NOTE: Not supported by WebGL - case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 - case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; // NOTE: Requires extension OES_texture_float + case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break; // NOTE: Not supported by WebGL + case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break; // NOTE: Not supported by WebGL + case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_ETC1_RGB8_OES, mipmapCount); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB8_ETC2, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA8_ETC2_EAC, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 #endif default: TraceLog(LOG_WARNING, "Texture format not supported"); break; } @@ -1514,8 +1517,48 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int return id; } +// Update already loaded texture in GPU with new data +void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data) +{ + glBindTexture(GL_TEXTURE_2D, id); + +#if defined(GRAPHICS_API_OPENGL_33) + switch (format) + { + case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + default: TraceLog(WARNING, "Texture format updating not supported"); break; + } +#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA + switch (format) + { + case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + default: TraceLog(WARNING, "Texture format updating not supported"); break; + } +#endif +} + +// Unload texture from GPU memory +void rlUnloadTexture(unsigned int id) +{ + if (id > 0) glDeleteTextures(1, &id); +} + + // Load a texture to be used for rendering (fbo with color and depth attachments) -RenderTexture2D rlglLoadRenderTexture(int width, int height) +RenderTexture2D rlLoadRenderTexture(int width, int height) { RenderTexture2D target; @@ -1609,41 +1652,8 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) return target; } -// Update already loaded texture in GPU with new data -void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data) -{ - glBindTexture(GL_TEXTURE_2D, id); - -#if defined(GRAPHICS_API_OPENGL_33) - switch (format) - { - case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; - case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; - } -#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA - switch (format) - { - case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; - case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; - } -#endif -} - // Generate mipmap data for selected texture -void rlglGenerateMipmaps(Texture2D *texture) +void rlGenerateMipmaps(Texture2D *texture) { glBindTexture(GL_TEXTURE_2D, texture->id); @@ -1657,7 +1667,7 @@ void rlglGenerateMipmaps(Texture2D *texture) { #if defined(GRAPHICS_API_OPENGL_11) // Compute required mipmaps - void *data = rlglReadTexturePixels(*texture); + void *data = rlReadTexturePixels(*texture); // NOTE: data size is reallocated to fit mipmaps data // NOTE: CPU mipmap generation only supports RGBA 32bit data @@ -1708,8 +1718,425 @@ void rlglGenerateMipmaps(Texture2D *texture) glBindTexture(GL_TEXTURE_2D, 0); } +// Generated cubemap texture +Texture2D rlGenMapCubemap(Texture2D skyHDR, int size) +{ + Texture2D cubemap = { 0 }; + + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + + Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + + // Get cubemap shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 + + // Set up depth face culling and cubemap seamless + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Set up cubemap to render and attach to framebuffer + // NOTE: faces are stored with 16 bit floating point values + glGenTextures(1, &cubemap.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Convert HDR equirectangular environment map to cubemap equivalent + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, skyHDR.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + cubemap.width = size; + cubemap.height = size; + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + //glEnable(GL_CULL_FACE); + + return cubemap; +} + +Texture2D rlGenMapIrradiance(Texture2D cubemap, int size) +{ + Texture2D irradiance = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + + // Get irradiance shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + // Set up shaders constant values + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale + glGenTextures(1, &irradiance.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Solve diffuse integral by convolution to create an irradiance cubemap + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + irradiance.width = size; + irradiance.height = size; + + return irradiance; +} + +Texture2D rlGenMapPrefilter(Texture2D cubemap, int size) +{ + Texture2D prefilter = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + + // Get prefilter shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int roughnessLoc = GetShaderLocation(shader, "roughness"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create a prefiltered HDR environment map + glGenTextures(1, &prefilter.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Generate mipmaps for the prefiltered HDR texture + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Prefilter HDR and store data into mipmap levels + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps + + for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) + { + // Resize framebuffer according to mip-level size. + unsigned int mipWidth = size*powf(0.5f, mip); + unsigned int mipHeight = size*powf(0.5f, mip); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); + glViewport(0, 0, mipWidth, mipHeight); + + float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); + glUniform1f(roughnessLoc, roughness); + + for (unsigned int i = 0; i < 6; ++i) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderCube(); + } + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + prefilter.width = size; + prefilter.height = size; + + return prefilter; +} + +Texture2D rlGenMapBRDF(Texture2D cubemap, int size) +{ + Texture2D brdf = { 0 }; + + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + + // Generate BRDF convolution texture + glGenTextures(1, &brdf.id); + glBindTexture(GL_TEXTURE_2D, brdf.id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, size, size, 0, GL_RG, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Render BRDF LUT into a quad using FBO + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); + + rlViewport(0, 0, size, size); + glUseProgram(shader.id); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderQuad(); + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + brdf.width = size; + brdf.height = size; + + return brdf; +} + +// Renders a 1x1 3D cube in NDC +GLuint cubeVAO = 0; +GLuint cubeVBO = 0; +static void RenderCube(void) +{ + // Initialize if it is not yet + if (cubeVAO == 0) + { + GLfloat vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + // Render cube + glBindVertexArray(cubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); +} + +// Renders a 1x1 XY quad in NDC +GLuint quadVAO = 0; +GLuint quadVBO; +static void RenderQuad(void) +{ + // Initialize if it is not yet + if (quadVAO == 0) + { + GLfloat quadVertices[] = { + // Positions // Texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + // Set up plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + + // Link vertex attributes + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + } + + // Render quad + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); +} + + + // Upload vertex data into a VAO (if supported) and VBO -void rlglLoadMesh(Mesh *mesh, bool dynamic) +// TODO: Check if mesh has already been loaded in GPU +void rlLoadMesh(Mesh *mesh, bool dynamic) { mesh->vaoId = 0; // Vertex Array Object mesh->vboId[0] = 0; // Vertex positions VBO @@ -1846,7 +2273,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) } // Update vertex data on GPU (upload new data to one buffer) -void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) +void rlUpdateMesh(Mesh mesh, int buffer, int numVertex) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Activate mesh VAO @@ -1908,11 +2335,11 @@ void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) } // Draw a 3d mesh with material and transform -void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) +void rlDrawMesh(Mesh mesh, Material material, Matrix transform) { #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); + glBindTexture(GL_TEXTURE_2D, material.maps[TEXMAP_DIFFUSE].tex.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array @@ -1943,16 +2370,28 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(material.shader.id); + // Bind shader program + glUseProgram(material.shader.id); + + // Matrices and other values required by shader + //----------------------------------------------------- + + // Calculate and send to shader model matrix (used by PBR shader) + SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); + // Upload to shader material.colDiffuse - glUniform4f(material.shader.colDiffuseLoc, (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255); - - // Upload to shader material.colAmbient (if available) - if (material.shader.colAmbientLoc != -1) glUniform4f(material.shader.colAmbientLoc, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[TEXMAP_DIFFUSE].color.r/255, + (float)material.maps[TEXMAP_DIFFUSE].color.g/255, + (float)material.maps[TEXMAP_DIFFUSE].color.b/255, + (float)material.maps[TEXMAP_DIFFUSE].color.a/255); // Upload to shader material.colSpecular (if available) - if (material.shader.colSpecularLoc != -1) glUniform4f(material.shader.colSpecularLoc, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); + if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[TEXMAP_SPECULAR].color.r/255, + (float)material.maps[TEXMAP_SPECULAR].color.g/255, + (float)material.maps[TEXMAP_SPECULAR].color.b/255, + (float)material.maps[TEXMAP_SPECULAR].color.a/255); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -1961,118 +2400,80 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Calculate model-view matrix combining matModel and matView Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates + //----------------------------------------------------- - // If not using default shader, we check for some additional location points - // NOTE: This method is quite inefficient... it's a temporal solution while looking for a better one - if (material.shader.id != defaultShader.id) + // Bind active texture maps (if available) + for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) { - // Check if model matrix is located in shader and upload value - int modelMatrixLoc = glGetUniformLocation(material.shader.id, "modelMatrix"); - if (modelMatrixLoc != -1) + if (material.maps[i].tex.id > 0) { - // Transpose and inverse model transformations matrix for fragment normal calculations - Matrix transInvTransform = transform; - MatrixTranspose(&transInvTransform); - MatrixInvert(&transInvTransform); + glActiveTexture(GL_TEXTURE0 + i); + if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].tex.id); + else glBindTexture(GL_TEXTURE_2D, material.maps[i].tex.id); - // Send model transformations matrix to shader - glUniformMatrix4fv(modelMatrixLoc, 1, false, MatrixToFloat(transInvTransform)); + glUniform1i(material.shader.locs[LOC_TEXMAP_DIFFUSE + i], i); } - - // Check if view direction is located in shader and upload value - // NOTE: View matrix values m8, m9 and m10 are view direction vector axis (target - position) - int viewDirLoc = glGetUniformLocation(material.shader.id, "viewDir"); - if (viewDirLoc != -1) glUniform3f(viewDirLoc, matView.m8, matView.m9, matView.m10); - - // Check if glossiness is located in shader and upload value - int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness"); - if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness); - } - - // Set shader textures (diffuse, normal, specular) - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); - glUniform1i(material.shader.mapTexture0Loc, 0); // Diffuse texture fits in active texture unit 0 - - if ((material.texNormal.id != 0) && (material.shader.mapTexture1Loc != -1)) - { - // Upload to shader specular map flag - glUniform1i(glGetUniformLocation(material.shader.id, "useNormal"), 1); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, material.texNormal.id); - glUniform1i(material.shader.mapTexture1Loc, 1); // Normal texture fits in active texture unit 1 - } - - if ((material.texSpecular.id != 0) && (material.shader.mapTexture2Loc != -1)) - { - // Upload to shader specular map flag - glUniform1i(glGetUniformLocation(material.shader.id, "useSpecular"), 1); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); - glUniform1i(material.shader.mapTexture2Loc, 2); // Specular texture fits in active texture unit 2 } - if (vaoSupported) - { - glBindVertexArray(mesh.vaoId); - } + // Bind vertex array objects (or VBOs) + if (vaoSupported) glBindVertexArray(mesh.vaoId); else { + // TODO: Simplify VBO binding into a for loop + // Bind mesh VBO data: vertex position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); - glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.vertexLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_POSITION]); // Bind mesh VBO data: vertex texcoords (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); - glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.texcoordLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TEXCOORD01]); // Bind mesh VBO data: vertex normals (shader-location = 2, if available) - if (material.shader.normalLoc != -1) + if (material.shader.locs[LOC_VERTEX_NORMAL] != -1) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); - glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.normalLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_NORMAL]); } // Bind mesh VBO data: vertex colors (shader-location = 3, if available) - if (material.shader.colorLoc != -1) + if (material.shader.locs[LOC_VERTEX_COLOR] != -1) { if (mesh.vboId[3] != 0) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); - glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(material.shader.colorLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_COLOR]); } else { // Set default value for unused attribute // NOTE: Required when using default shader and no VAO support - glVertexAttrib4f(material.shader.colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); - glDisableVertexAttribArray(material.shader.colorLoc); + glVertexAttrib4f(material.shader.locs[LOC_VERTEX_COLOR], 1.0f, 1.0f, 1.0f, 1.0f); + glDisableVertexAttribArray(material.shader.locs[LOC_VERTEX_COLOR]); } } // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) - if (material.shader.tangentLoc != -1) + if (material.shader.locs[LOC_VERTEX_TANGENT] != -1) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); - glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.tangentLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TANGENT], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TANGENT]); } // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) - if (material.shader.texcoord2Loc != -1) + if (material.shader.locs[LOC_VERTEX_TEXCOORD02] != -1) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); - glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.texcoord2Loc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TEXCOORD02], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TEXCOORD02]); } - if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vboId[6]); } int eyesCount = 1; @@ -2091,45 +2492,41 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates // Send combined model-view-projection matrix to shader - glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); // Draw call! if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); } - - if (material.texNormal.id != 0) - { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - } - - if (material.texSpecular.id != 0) + + // Unbind all binded texture maps + for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0 + i); // Set shader active texture + if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + else glBindTexture(GL_TEXTURE_2D, 0); // Unbind current active texture } - glActiveTexture(GL_TEXTURE0); // Set shader active texture to default 0 - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures - - if (vaoSupported) glBindVertexArray(0); // Unbind VAO + // Unind vertex array objects (or VBOs) + if (vaoSupported) glBindVertexArray(0); else { - glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + glBindBuffer(GL_ARRAY_BUFFER, 0); if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - glUseProgram(0); // Unbind shader program + // Unbind shader program + glUseProgram(0); // Restore projection/modelview matrices + // NOTE: In stereo rendering matrices are being modified to fit every eye projection = matProjection; modelview = matView; #endif } // Unload mesh data from CPU and GPU -void rlglUnloadMesh(Mesh *mesh) +void rlUnloadMesh(Mesh *mesh) { if (mesh->vertices != NULL) free(mesh->vertices); if (mesh->texcoords != NULL) free(mesh->texcoords); @@ -2151,7 +2548,7 @@ void rlglUnloadMesh(Mesh *mesh) } // Read screen pixel data (color buffer) -unsigned char *rlglReadScreenPixels(int width, int height) +unsigned char *rlReadScreenPixels(int width, int height) { unsigned char *screenData = (unsigned char *)calloc(width*height*4, sizeof(unsigned char)); @@ -2182,7 +2579,7 @@ unsigned char *rlglReadScreenPixels(int width, int height) // Read texture pixel data // NOTE: glGetTexImage() is not available on OpenGL ES 2.0 // Texture2D width and height are required on OpenGL ES 2.0. There is no way to get it from texture id. -void *rlglReadTexturePixels(Texture2D texture) +void *rlReadTexturePixels(Texture2D texture) { void *pixels = NULL; @@ -2235,7 +2632,7 @@ void *rlglReadTexturePixels(Texture2D texture) #if defined(GRAPHICS_API_OPENGL_ES2) - RenderTexture2D fbo = rlglLoadRenderTexture(texture.width, texture.height); + RenderTexture2D fbo = rlLoadRenderTexture(texture.width, texture.height); // NOTE: Two possible Options: // 1 - Bind texture to color fbo attachment and glReadPixels() @@ -2306,7 +2703,7 @@ void *rlglReadTexturePixels(Texture2D texture) /* // TODO: Record draw calls to be processed in batch // NOTE: Global state must be kept -void rlglRecordDraw(void) +void rlRecordDraw(void) { // TODO: Before adding a new draw, check if anything changed from last stored draw #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2328,7 +2725,7 @@ void rlglRecordDraw(void) //---------------------------------------------------------------------------------- // Get default internal texture (white texture) -Texture2D GetDefaultTexture(void) +Texture2D GetTextureDefault(void) { Texture2D texture; @@ -2389,8 +2786,8 @@ Shader LoadShader(char *vsFileName, char *fsFileName) { shader.id = LoadShaderProgram(vShaderStr, fShaderStr); - // After shader loading, we try to load default location names - if (shader.id != 0) LoadDefaultShaderLocations(&shader); + // After shader loading, we TRY to set default location names + if (shader.id > 0) SetShaderDefaultLocations(&shader); // Shader strings must be freed free(vShaderStr); @@ -2402,6 +2799,32 @@ Shader LoadShader(char *vsFileName, char *fsFileName) TraceLog(LOG_WARNING, "Custom shader could not be loaded"); shader = defaultShader; } + + + // Get available shader uniforms + // NOTE: This information is useful for debug... + int uniformCount = -1; + + glGetProgramiv(shader.id, GL_ACTIVE_UNIFORMS, &uniformCount); + + for(int i = 0; i < uniformCount; i++) + { + int namelen = -1; + int num = -1; + char name[256]; // Assume no variable names longer than 256 + GLenum type = GL_ZERO; + + // Get the name of the uniforms + glGetActiveUniform(shader.id, i,sizeof(name) - 1, &namelen, &num, &type, name); + + name[namelen] = 0; + + // Get the location of the named uniform + GLuint location = glGetUniformLocation(shader.id, name); + + TraceLog(LOG_INFO, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); + } + #endif return shader; @@ -2410,7 +2833,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Unload shader from GPU memory (VRAM) void UnloadShader(Shader shader) { - if (shader.id != 0) + if (shader.id > 0) { rlDeleteShader(shader.id); TraceLog(LOG_INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); @@ -2438,7 +2861,7 @@ void EndShaderMode(void) } // Get default shader -Shader GetDefaultShader(void) +Shader GetShaderDefault(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) return defaultShader; @@ -2455,7 +2878,8 @@ int GetShaderLocation(Shader shader, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shader.id, uniformName); - if (location == -1) TraceLog(LOG_DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); + if (location == -1) TraceLog(LOG_WARNING, "[SHDR ID %i] Shader uniform [%s] COULD NOT BE FOUND", shader.id, uniformName); + else TraceLog(LOG_INFO, "[SHDR ID %i] Shader uniform [%s] set at location: %i", shader.id, uniformName, location); #endif return location; } @@ -2609,12 +3033,12 @@ void InitVrSimulator(int vrDevice) // Initialize framebuffer and textures for stereo rendering // NOTE: screen size should match HMD aspect ratio - vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); + vrConfig.stereoFbo = rlLoadRenderTexture(screenWidth, screenHeight); #if defined(SUPPORT_DISTORTION_SHADER) // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); - if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); + if (vrConfig.distortionShader.id > 0) SetShaderDefaultLocations(&vrConfig.distortionShader); #endif SetStereoConfig(hmd); @@ -2727,7 +3151,7 @@ void EndVrDrawing(void) // Draw RenderTexture (stereoFbo) using distortion shader currentShader = vrConfig.distortionShader; #else - currentShader = GetDefaultShader(); + currentShader = GetShaderDefault(); #endif rlEnableTexture(vrConfig.stereoFbo.texture.id); @@ -2783,7 +3207,7 @@ void EndVrDrawing(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Convert image data to OpenGL texture (returns OpenGL valid Id) // NOTE: Expected compressed image data and POT image -static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat) +static void LoadTextureCompressed(unsigned char *data, int width, int height, int compressedFormat, int mipmapCount) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -2950,7 +3374,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade // Load default shader (just vertex positioning and texture coloring) // NOTE: This shader program is used for batch buffers (lines, triangles, quads) -static Shader LoadDefaultShader(void) +static Shader LoadShaderDefault(void) { Shader shader; @@ -3015,17 +3439,29 @@ static Shader LoadDefaultShader(void) shader.id = LoadShaderProgram(vDefaultShaderStr, fDefaultShaderStr); - if (shader.id != 0) TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); - else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); - - if (shader.id != 0) LoadDefaultShaderLocations(&shader); + if (shader.id > 0) + { + TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); + + // Set default shader locations + // Get handles to GLSL input attibute locations + shader.locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader.id, "vertexPosition"); + shader.locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader.id, "vertexTexCoord"); + shader.locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader.id, "vertexColor"); + + // Get handles to GLSL uniform locations + shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); + shader.locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); + } + else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); return shader; } // Get location handlers to for shader attributes and uniforms // NOTE: If any location is not found, loc point becomes -1 -static void LoadDefaultShaderLocations(Shader *shader) +static void SetShaderDefaultLocations(Shader *shader) { // NOTE: Default shader attrib locations have been fixed before linking: // vertex position location = 0 @@ -3036,30 +3472,27 @@ static void LoadDefaultShaderLocations(Shader *shader) // vertex texcoord2 location = 5 // Get handles to GLSL input attibute locations - shader->vertexLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); - shader->texcoordLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME); - shader->texcoord2Loc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD2_NAME); - shader->normalLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_NORMAL_NAME); - shader->tangentLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TANGENT_NAME); - shader->colorLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME); + shader->locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); + shader->locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME); + shader->locs[LOC_VERTEX_TEXCOORD02] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD2_NAME); + shader->locs[LOC_VERTEX_NORMAL] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_NORMAL_NAME); + shader->locs[LOC_VERTEX_TANGENT] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TANGENT_NAME); + shader->locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME); // Get handles to GLSL uniform locations (vertex shader) - shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); + shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); // Get handles to GLSL uniform locations (fragment shader) - shader->colDiffuseLoc = glGetUniformLocation(shader->id, "colDiffuse"); - shader->colAmbientLoc = glGetUniformLocation(shader->id, "colAmbient"); - shader->colSpecularLoc = glGetUniformLocation(shader->id, "colSpecular"); - - shader->mapTexture0Loc = glGetUniformLocation(shader->id, "texture0"); - shader->mapTexture1Loc = glGetUniformLocation(shader->id, "texture1"); - shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2"); + shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); + shader->locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); + shader->locs[LOC_TEXMAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); + shader->locs[LOC_TEXMAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) } // Unload default shader -static void UnloadDefaultShader(void) +static void UnloadShaderDefault(void) { glUseProgram(0); @@ -3155,15 +3588,15 @@ static void LoadDefaultBuffers(void) glGenBuffers(2, &lines.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(2, &lines.vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId); else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]); @@ -3181,15 +3614,15 @@ static void LoadDefaultBuffers(void) glGenBuffers(1, &triangles.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(1, &triangles.vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId); else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]); @@ -3207,22 +3640,22 @@ static void LoadDefaultBuffers(void) glGenBuffers(1, &quads.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex texcoord buffer (shader-location = 1) glGenBuffers(1, &quads.vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.texcoordLoc); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(1, &quads.vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer glGenBuffers(1, &quads.vboId[3]); @@ -3338,9 +3771,9 @@ static void DrawDefaultBuffers() // Create modelview-projection matrix Matrix matMVP = MatrixMultiply(modelview, projection); - glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - glUniform4f(currentShader.colDiffuseLoc, 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(currentShader.mapTexture0Loc, 0); + glUniformMatrix4fv(currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); + glUniform4f(currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(currentShader.locs[LOC_TEXMAP_DIFFUSE], 0); // NOTE: Additional map textures not considered for default buffers drawing } @@ -3348,6 +3781,7 @@ static void DrawDefaultBuffers() // Draw lines buffers if (lines.vCounter > 0) { + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, whiteTexture); if (vaoSupported) @@ -3358,13 +3792,13 @@ static void DrawDefaultBuffers() { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); } glDrawArrays(GL_LINES, 0, lines.vCounter); @@ -3376,6 +3810,7 @@ static void DrawDefaultBuffers() // Draw triangles buffers if (triangles.vCounter > 0) { + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, whiteTexture); if (vaoSupported) @@ -3386,13 +3821,13 @@ static void DrawDefaultBuffers() { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); } glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); @@ -3416,18 +3851,18 @@ static void DrawDefaultBuffers() { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: texcoord (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.texcoordLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_TEXCOORD01]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } @@ -3441,6 +3876,7 @@ static void DrawDefaultBuffers() //TraceLog(LOG_DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, draws[i].textureId); // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process diff --git a/src/rlgl.h b/src/rlgl.h index 36ff7889..3adf81a5 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -145,6 +145,54 @@ typedef unsigned char byte; // Boolean type typedef enum { false, true } bool; #endif + + typedef enum { + LOC_VERTEX_POSITION = 0, + LOC_VERTEX_TEXCOORD01, + LOC_VERTEX_TEXCOORD02, + LOC_VERTEX_NORMAL, + LOC_VERTEX_TANGENT, + LOC_VERTEX_COLOR, + LOC_MATRIX_MVP, + LOC_MATRIX_MODEL, + LOC_MATRIX_VIEW, + LOC_MATRIX_PROJECTION, + LOC_VECTOR_VIEW, + LOC_COLOR_DIFFUSE, + LOC_COLOR_SPECULAR, + LOC_COLOR_AMBIENT, + LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE + LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR + LOC_TEXMAP_NORMAL, + LOC_TEXMAP_ROUGHNESS, + LOC_TEXMAP_OCCUSION, + LOC_TEXMAP_EMISSION, + LOC_TEXMAP_HEIGHT, + LOC_TEXMAP_CUBEMAP, + LOC_TEXMAP_IRRADIANCE, + LOC_TEXMAP_PREFILTER, + LOC_TEXMAP_BRDF + } ShaderLocationIndex; + + #define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO + #define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS + + typedef enum { + TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE + TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR + TEXMAP_NORMAL = 2, + TEXMAP_ROUGHNESS = 3, + TEXMAP_OCCLUSION, + TEXMAP_EMISSION, + TEXMAP_HEIGHT, + TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_BRDF + } TexmapIndex; + + #define TEXMAP_DIFFUSE TEXMAP_ALBEDO + #define TEXMAP_SPECULAR TEXMAP_METALNESS // Color type, RGBA (32bit) typedef struct Color { @@ -186,44 +234,30 @@ typedef unsigned char byte; unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; - - // Shader type (generic shader) + + // Shader and material limits + #define MAX_SHADER_LOCATIONS 32 + #define MAX_MATERIAL_TEXTURE_MAPS 12 + #define MAX_MATERIAL_PARAMS 8 + + // Shader type (generic) typedef struct Shader { unsigned int id; // Shader program id - - // Vertex attributes locations (default locations) - int vertexLoc; // Vertex attribute location point (default-location = 0) - int texcoordLoc; // Texcoord attribute location point (default-location = 1) - int normalLoc; // Normal attribute location point (default-location = 2) - int colorLoc; // Color attibute location point (default-location = 3) - int tangentLoc; // Tangent attribute location point (default-location = 4) - int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) - - // Uniform locations - int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int colDiffuseLoc; // Color uniform location point (fragment shader) - int colAmbientLoc; // Ambient color uniform location point (fragment shader) - int colSpecularLoc; // Specular color uniform location point (fragment shader) - - // Texture map locations (generic for any kind of map) - int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) - int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) - int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) + int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS } Shader; - // Material type - typedef struct Material { - Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) - - Texture2D texDiffuse; // Diffuse texture - Texture2D texNormal; // Normal texture - Texture2D texSpecular; // Specular texture + // Material texture map + typedef struct TextureMap { + Texture2D tex; + Color color; + float value; + } TextureMap; - Color colDiffuse; // Diffuse color - Color colAmbient; // Ambient color - Color colSpecular; // Specular color - - float glossiness; // Glossiness level (Ranges from 0 to 1000) + // Material type (generic) + typedef struct Material { + Shader shader; + TextureMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS + float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS } Material; // Camera type, defines a camera position/orientation in 3d space @@ -343,23 +377,24 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) // Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2) // NOTE: This functions are used to completely abstract raylib code from OpenGL layer //------------------------------------------------------------------------------------ -void rlEnableTexture(unsigned int id); // Enable texture usage -void rlDisableTexture(void); // Disable texture usage +void rlEnableTexture(unsigned int id); // Enable texture usage +void rlDisableTexture(void); // Disable texture usage void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap) -void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo) -void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer -void rlEnableDepthTest(void); // Enable depth test -void rlDisableDepthTest(void); // Disable depth test -void rlEnableWireMode(void); // Enable wire mode -void rlDisableWireMode(void); // Disable wire mode -void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU +void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo) +void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer +void rlEnableDepthTest(void); // Enable depth test +void rlDisableDepthTest(void); // Disable depth test +void rlEnableWireMode(void); // Enable wire mode +void rlDisableWireMode(void); // Disable wire mode +void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU -void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU -void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory -void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory -void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color -void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) -int rlGetVersion(void); // Returns current OpenGL version +void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU +void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory +void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory +void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color +void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) +int rlGetVersion(void); // Returns current OpenGL version +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates //------------------------------------------------------------------------------------ // Functions Declaration - rlgl functionality @@ -369,24 +404,26 @@ void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglLoadExtensions(void *loader); // Load OpenGL extensions -unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU -RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) -void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data -void rlglGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture - -void rlglLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids -void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer) -void rlglDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform -void rlglUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU - -Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates - -unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) -void *rlglReadTexturePixels(Texture2D texture); // Read texture pixel data - -// VR functions exposed to core module but not to raylib users -void BeginVrDrawing(void); // Begin VR drawing configuration -void EndVrDrawing(void); // End VR drawing process (and desktop mirror) +// Textures data management +unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU +void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data +void rlUnloadTexture(unsigned int id); +void rlGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture +void *rlReadTexturePixels(Texture2D texture); // Read texture pixel data +unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) +RenderTexture2D rlLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) + +// Vertex data management +void rlLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids +void rlUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer) +void rlDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform +void rlUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU + +// Texture maps generation (PBR) +Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture +Texture2D rlGenMapIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map +Texture2D rlGenMapPrefilter(Texture2D cubemap, int size); // Generate prefilter texture map +Texture2D rlGenMapBRDF(Texture2D cubemap, int size); // Generate BRDF texture map // NOTE: There is a set of shader related functions that are available to end user, // to avoid creating function wrappers through core module, they have been directly declared in raylib.h @@ -396,34 +433,34 @@ void EndVrDrawing(void); // End VR drawing process (and deskt // Shaders System Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 //------------------------------------------------------------------------------------ -Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations -void UnloadShader(Shader shader); // Unload a custom shader from memory +Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations +void UnloadShader(Shader shader); // Unload a custom shader from memory -Shader GetDefaultShader(void); // Get default shader -Texture2D GetDefaultTexture(void); // Get default texture +Shader GetShaderDefault(void); // Get default shader +Texture2D GetTextureDefault(void); // Get default texture int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) -void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) -void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) -void BeginShaderMode(Shader shader); // Begin custom shader drawing -void EndShaderMode(void); // End custom shader drawing (use default shader) -void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) -void EndBlendMode(void); // End blending mode (reset to default: alpha blending) +void BeginShaderMode(Shader shader); // Begin custom shader drawing +void EndShaderMode(void); // End custom shader drawing (use default shader) +void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) +void EndBlendMode(void); // End blending mode (reset to default: alpha blending) -void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) -float *MatrixToFloat(Matrix mat); // Get float array from Matrix data +void InitVrSimulator(int vrDevice); // Init VR simulator for selected device +void CloseVrSimulator(void); // Close VR simulator for current device +void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera +void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) +void BeginVrDrawing(void); // Begin VR stereo rendering +void EndVrDrawing(void); // End VR stereo rendering -void InitVrSimulator(int vrDevice); // Init VR simulator for selected device -void CloseVrSimulator(void); // Close VR simulator for current device -void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera -void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) -void BeginVrDrawing(void); // Begin VR stereo rendering -void EndVrDrawing(void); // End VR stereo rendering +void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) +float *MatrixToFloat(Matrix mat); // Converts Matrix to float array #endif #ifdef __cplusplus diff --git a/src/shapes.c b/src/shapes.c index 2a924476..25ed93aa 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -119,7 +119,7 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) float d = sqrtf(dx*dx + dy*dy); float angle = asinf(dy/d); - rlEnableTexture(GetDefaultTexture().id); + rlEnableTexture(GetTextureDefault().id); rlPushMatrix(); rlTranslatef((float)startPos.x, (float)startPos.y, 0); @@ -203,7 +203,7 @@ void DrawCircleV(Vector2 center, float radius, Color color) } else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(GetDefaultTexture().id); // Default white texture + rlEnableTexture(GetTextureDefault().id); // Default white texture rlBegin(RL_QUADS); for (int i = 0; i < 360; i += 20) @@ -253,7 +253,7 @@ void DrawRectangleRec(Rectangle rec, Color color) void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color) { - rlEnableTexture(GetDefaultTexture().id); + rlEnableTexture(GetTextureDefault().id); rlPushMatrix(); rlTranslatef((float)rec.x, (float)rec.y, 0); @@ -309,7 +309,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color) } else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(GetDefaultTexture().id); // Default white texture + rlEnableTexture(GetTextureDefault().id); // Default white texture rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); @@ -376,7 +376,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) } else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(GetDefaultTexture().id); // Default white texture + rlEnableTexture(GetTextureDefault().id); // Default white texture rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); diff --git a/src/textures.c b/src/textures.c index 0a8d7591..1436111f 100644 --- a/src/textures.c +++ b/src/textures.c @@ -63,8 +63,8 @@ #include // Required for: strcmp(), strrchr(), strncmp() #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 - // Required for: rlglLoadTexture() rlDeleteTextures(), - // rlglGenerateMipmaps(), some funcs for DrawTexturePro() + // Required for: rlLoadTexture() rlDeleteTextures(), + // rlGenerateMipmaps(), some funcs for DrawTexturePro() #include "utils.h" // Required for: fopen() Android mapping @@ -384,7 +384,7 @@ Texture2D LoadTextureFromImage(Image image) { Texture2D texture = { 0 }; - texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); + texture.id = rlLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); texture.width = image.width; texture.height = image.height; @@ -399,7 +399,7 @@ Texture2D LoadTextureFromImage(Image image) // Load texture for rendering (framebuffer) RenderTexture2D LoadRenderTexture(int width, int height) { - RenderTexture2D target = rlglLoadRenderTexture(width, height); + RenderTexture2D target = rlLoadRenderTexture(width, height); return target; } @@ -416,7 +416,7 @@ void UnloadImage(Image image) // Unload texture from GPU memory (VRAM) void UnloadTexture(Texture2D texture) { - if (texture.id != 0) + if (texture.id > 0) { rlDeleteTextures(texture.id); @@ -427,7 +427,7 @@ void UnloadTexture(Texture2D texture) // Unload render texture from GPU memory (VRAM) void UnloadRenderTexture(RenderTexture2D target) { - if (target.id != 0) rlDeleteRenderTextures(target); + if (target.id > 0) rlDeleteRenderTextures(target); } // Get pixel data from image in the form of Color struct array @@ -525,7 +525,7 @@ Image GetTextureData(Texture2D texture) if (texture.format < 8) { - image.data = rlglReadTexturePixels(texture); + image.data = rlReadTexturePixels(texture); if (image.data != NULL) { @@ -553,7 +553,7 @@ Image GetTextureData(Texture2D texture) // NOTE: pixels data must match texture.format void UpdateTexture(Texture2D texture, const void *pixels) { - rlglUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); + rlUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); } // Save image to a PNG file @@ -1660,9 +1660,9 @@ void GenTextureMipmaps(Texture2D *texture) { TraceLog(LOG_WARNING, "Limited NPOT support, no mipmaps available for NPOT textures"); } - else rlglGenerateMipmaps(texture); + else rlGenerateMipmaps(texture); #else - rlglGenerateMipmaps(texture); + rlGenerateMipmaps(texture); #endif } @@ -1792,7 +1792,7 @@ void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Co void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint) { // Check if texture is valid - if (texture.id != 0) + if (texture.id > 0) { if (sourceRec.width < 0) sourceRec.x -= sourceRec.width; if (sourceRec.height < 0) sourceRec.y -= sourceRec.height; -- cgit v1.2.3 From e893f3629e85ec018955d188916c00c3c07c44c0 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 17 Jul 2017 12:02:46 +0200 Subject: Corrected some issues --- examples/models/models_cubicmap.c | 2 +- src/models.c | 6 +++--- src/rlgl.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index ceef6378..8abc7d48 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -26,7 +26,7 @@ int main() Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) - Mesh mesh = GenMeshCubicmap(image, VectorOne()); + Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f }); Model model = LoadModelFromMesh(mesh, false); // NOTE: By default each cube is mapped to one part of texture atlas diff --git a/src/models.c b/src/models.c index d9404c12..0865e8d7 100644 --- a/src/models.c +++ b/src/models.c @@ -627,10 +627,10 @@ Mesh LoadMesh(const char *fileName) #if defined(SUPPORT_FILEFORMAT_OBJ) if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); #else - TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); + TraceLog(LOG_WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); #endif - if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); + if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); else rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) // TODO: Initialize default mesh data in case loading fails, maybe a cube? @@ -1269,7 +1269,7 @@ Material LoadMaterial(const char *fileName) #if defined(SUPPORT_FILEFORMAT_MTL) if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); #else - TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); + TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); #endif return material; diff --git a/src/rlgl.c b/src/rlgl.c index 7f349347..742b0ed5 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -338,7 +338,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring) static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) -static void UnLoadShaderDefault(void); // Unload default shader +static void UnloadShaderDefault(void); // Unload default shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data @@ -1532,7 +1532,7 @@ void rlUpdateTexture(unsigned int id, int width, int height, int format, const v case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(WARNING, "Texture format updating not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA @@ -1545,7 +1545,7 @@ void rlUpdateTexture(unsigned int id, int width, int height, int format, const v case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(WARNING, "Texture format updating not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; } #endif } @@ -3454,7 +3454,7 @@ static Shader LoadShaderDefault(void) shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); shader.locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); } - else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); + else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); return shader; } -- cgit v1.2.3 From 8f569e59b177e879fe350027a706c6f731f86c4a Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 17 Jul 2017 14:16:23 +0200 Subject: Review shared library generation --- src/Makefile | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 6579d424..35949d89 100644 --- a/src/Makefile +++ b/src/Makefile @@ -215,7 +215,6 @@ endif ifeq ($(SHARED_RAYLIB),YES) CFLAGS += -fPIC SHAREDFLAG = BUILDING_DLL - SHAREDLIBS = -Lexternal/glfw3/lib/win32 -Lexternal/openal_soft/lib/win32 -lglfw3 -lgdi32 else SHAREDFLAG = BUILDING_STATIC endif @@ -317,15 +316,20 @@ ifeq ($(PLATFORM),PLATFORM_WEB) @echo "libraylib.bc generated (web version)!" else ifeq ($(SHARED_RAYLIB),YES) + # NOTE: If using OpenAL Soft as static library, all its dependencies must be also linked in the shared library + ifeq ($(PLATFORM_OS),WINDOWS) + $(CC) -shared -o $(OUTPUT_PATH)/raylib.dll $(OBJS) $(SHAREDLIBS) -Lexternal/glfw3/lib/win32 -Lexternal/openal_soft/lib/win32 -lglfw3 -lgdi32 -Wl,--out-implib,$(OUTPUT_PATH)/libraylibdll.a + @echo "raylib dynamic library (raylib.dll) and import library (libraylibdll.a) generated!" + endif ifeq ($(PLATFORM_OS),LINUX) # compile raylib to shared library version for GNU/Linux. # WARNING: you should type "make clean" before doing this target - $(CC) -shared -o $(OUTPUT_PATH)/libraylib.so $(OBJS) - @echo "raylib shared library (libraylib.so) generated!" + $(CC) -shared -o $(OUTPUT_PATH)/libraylib.so $(OBJS) -lglfw3 -lGL -lopenal -lm -lpthread -ldl + @echo "raylib shared library generated (libraylib.so)!" endif - ifeq ($(PLATFORM_OS),WINDOWS) - $(CC) -shared -o $(OUTPUT_PATH)/raylib.dll $(OBJS) $(SHAREDLIBS) -Wl,--out-implib,$(OUTPUT_PATH)/libraylibdll.a - @echo "raylib dynamic library (raylib.dll) and import library (libraylibdll.a) generated!" + ifeq ($(PLATFORM_OS),OSX) + $(CC) -shared -o $(OUTPUT_PATH)/libraylib.so $(OBJS) -lglfw -framework OpenGL -framework OpenAL -framework Cocoa + @echo "raylib shared library generated (libraylib.so)!" endif ifeq ($(PLATFORM),PLATFORM_ANDROID) $(CC) -shared -o $(OUTPUT_PATH)/libraylib.so $(OBJS) -- cgit v1.2.3 From ba32d6a753877da5c22d223e794701f087cd7654 Mon Sep 17 00:00:00 2001 From: "Benjamin N. Summerton" Date: Tue, 18 Jul 2017 22:23:43 -0400 Subject: Able to make a .dylib for OS X --- src/Makefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 35949d89..6d0318c1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -145,6 +145,14 @@ endif # default gcc compiler CC = gcc + +# For OS X +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),OSX) + CC = clang + endif +endif + # Android toolchain compiler ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(ANDROID_ARCH),ARM) @@ -328,8 +336,9 @@ else @echo "raylib shared library generated (libraylib.so)!" endif ifeq ($(PLATFORM_OS),OSX) - $(CC) -shared -o $(OUTPUT_PATH)/libraylib.so $(OBJS) -lglfw -framework OpenGL -framework OpenAL -framework Cocoa - @echo "raylib shared library generated (libraylib.so)!" + $(CC) -dynamiclib -o $(OUTPUT_PATH)/libraylib.dylib $(OBJS) -L/usr/local/Cellar/glfw/3.2.1/lib -lglfw -framework OpenGL -framework OpenAL -framework Cocoa + install_name_tool -id "libraylib.dylib" $(OUTPUT_PATH)/libraylib.dylib + @echo "raylib shared library generated (libraylib.dylib)!" endif ifeq ($(PLATFORM),PLATFORM_ANDROID) $(CC) -shared -o $(OUTPUT_PATH)/libraylib.so $(OBJS) -- cgit v1.2.3 From d368403a131522a53c0dedd1ae4f24301898e96e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 10:09:34 +0200 Subject: Working on PBR materials, renamed some data --- examples/models/models_cubicmap.c | 2 +- examples/models/models_material_pbr.c | 20 +- examples/models/models_skybox.c | 6 +- src/core.c | 2 +- src/models.c | 127 ++--- src/raylib.h | 110 ++-- src/rlgl.c | 1009 +++++++++++++++++---------------- src/rlgl.h | 84 +-- 8 files changed, 689 insertions(+), 671 deletions(-) (limited to 'src') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 8abc7d48..177cf890 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -31,7 +31,7 @@ int main() // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - model.material.maps[TEXMAP_DIFFUSE].tex = texture; // Set map diffuse texture + model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 9380bd91..5761b2af 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -58,18 +58,18 @@ int main() Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - SetMaterialTexture(&model.material, TEXMAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); - SetMaterialTexture(&model.material, TEXMAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); - SetMaterialTexture(&model.material, TEXMAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); - SetMaterialTexture(&model.material, TEXMAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); - SetMaterialTexture(&model.material, TEXMAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + SetMaterialTexture(&model.material, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&model.material, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&model.material, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&model.material, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&model.material, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); // Set textures filtering for better quality - SetTextureFilter(model.material.maps[TEXMAP_ALBEDO].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_NORMAL].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_METALNESS].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_ROUGHNESS].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_OCCLUSION].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_NORMAL].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_METALNESS].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 8b302b1c..d347854f 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -30,8 +30,8 @@ int main() skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - skybox.material.maps[TEXMAP_CUBEMAP].tex = rlGenMapCubemap(texHDR, 512); - SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ TEXMAP_CUBEMAP }, 1); + skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(texHDR, 512); + SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, 1); // Get skybox shader locations skybox.material.shader.locs[LOC_MATRIX_PROJECTION] = GetShaderLocation(skybox.material.shader, "projection"); @@ -66,7 +66,7 @@ int main() Begin3dMode(camera); - DrawModel(skybox, VectorZero(), 1.0f, RED); + DrawModel(skybox, VectorZero(), 1.0f, WHITE); DrawGrid(10, 1.0f); diff --git a/src/core.c b/src/core.c index ad905d4e..5cdd8e6b 100644 --- a/src/core.c +++ b/src/core.c @@ -1878,7 +1878,7 @@ static void InitGraphicsDevice(int width, int height) #if defined(PLATFORM_DESKTOP) // Load OpenGL 3.3 extensions // NOTE: GLFW loader function is passed as parameter - rlglLoadExtensions(glfwGetProcAddress); + rlLoadExtensions(glfwGetProcAddress); #endif // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) diff --git a/src/models.c b/src/models.c index 0865e8d7..660ecc79 100644 --- a/src/models.c +++ b/src/models.c @@ -1281,12 +1281,12 @@ Material LoadMaterialDefault(void) Material material = { 0 }; material.shader = GetShaderDefault(); - material.maps[TEXMAP_DIFFUSE].tex = GetTextureDefault(); // White texture (1x1 pixel) - //material.maps[TEXMAP_NORMAL].tex; // NOTE: By default, not set - //material.maps[TEXMAP_SPECULAR].tex; // NOTE: By default, not set + material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel) + //material.maps[MAP_NORMAL].tex; // NOTE: By default, not set + //material.maps[MAP_SPECULAR].tex; // NOTE: By default, not set - material.maps[TEXMAP_DIFFUSE].color = WHITE; // Diffuse color - material.maps[TEXMAP_SPECULAR].color = WHITE; // Specular color + material.maps[MAP_DIFFUSE].color = WHITE; // Diffuse color + material.maps[MAP_SPECULAR].color = WHITE; // Specular color return material; } @@ -1294,7 +1294,7 @@ Material LoadMaterialDefault(void) // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) { - Material mat = { 0 }; + Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader @@ -1303,16 +1303,16 @@ Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float rou // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code - mat.shader.locs[LOC_TEXMAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); - mat.shader.locs[LOC_TEXMAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); - mat.shader.locs[LOC_TEXMAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); - mat.shader.locs[LOC_TEXMAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); - mat.shader.locs[LOC_TEXMAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); - mat.shader.locs[LOC_TEXMAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); - mat.shader.locs[LOC_TEXMAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); - mat.shader.locs[LOC_TEXMAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); - mat.shader.locs[LOC_TEXMAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); - mat.shader.locs[LOC_TEXMAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); // Set view matrix location mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); @@ -1320,30 +1320,25 @@ Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float rou mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); // Set up material properties color - mat.maps[TEXMAP_ALBEDO].color = albedo; - mat.maps[TEXMAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; - mat.maps[TEXMAP_METALNESS].value = metalness; - mat.maps[TEXMAP_ROUGHNESS].value = roughness; - mat.maps[TEXMAP_OCCLUSION].value = 1.0f; - mat.maps[TEXMAP_EMISSION].value = 0.0f; - mat.maps[TEXMAP_HEIGHT].value = 0.0f; + mat.maps[MAP_ALBEDO].color = albedo; + mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[MAP_METALNESS].value = metalness; + mat.maps[MAP_ROUGHNESS].value = roughness; + mat.maps[MAP_OCCLUSION].value = 1.0f; + mat.maps[MAP_EMISSION].value = 0.0f; + mat.maps[MAP_HEIGHT].value = 0.0f; - #define CUBEMAP_SIZE 1024 // Cubemap texture size + #define CUBEMAP_SIZE 512 // Cubemap texture size #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size #define BRDF_SIZE 512 // BRDF LUT texture map size // Set up environment materials cubemap - Texture2D cubemap = rlGenMapCubemap(hdr, CUBEMAP_SIZE); - mat.maps[TEXMAP_IRRADIANCE].tex = rlGenMapIrradiance(cubemap, IRRADIANCE_SIZE); - mat.maps[TEXMAP_PREFILTER].tex = rlGenMapPrefilter(cubemap, PREFILTERED_SIZE); - mat.maps[TEXMAP_BRDF].tex = rlGenMapBRDF(cubemap, BRDF_SIZE); + Texture2D cubemap = GenTextureCubemap(hdr, CUBEMAP_SIZE); + mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(cubemap, IRRADIANCE_SIZE); + mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(cubemap, PREFILTERED_SIZE); + mat.maps[MAP_BRDF].texture = GenTextureBRDF(cubemap, BRDF_SIZE); UnloadTexture(cubemap); - - // NOTE: All maps textures are set to { 0 } - - // Reset viewport dimensions to default - rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); return mat; } @@ -1355,53 +1350,53 @@ void UnloadMaterial(Material material) UnloadShader(material.shader); // Unload loaded texture maps - for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { // NOTE: We already check for (tex.id > 0) inside function - rlDeleteTextures(material.maps[i].tex.id); + rlDeleteTextures(material.maps[i].texture.id); } } // Set material texture void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) { - mat->maps[texmapType].tex = texture; + mat->maps[texmapType].texture = texture; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; switch (texmapType) { - case TEXMAP_ALBEDO: + case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_NORMAL: + case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_METALNESS: + case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_ROUGHNESS: + case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_OCCLUSION: + case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_EMISSION: + case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_HEIGHT: + case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); @@ -1412,44 +1407,44 @@ void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) // Unset texture from material and unload it from GPU void UnsetMaterialTexture(Material *mat, int texmapType) { - UnloadTexture(mat->maps[texmapType].tex); - mat->maps[texmapType].tex = (Texture2D){ 0 }; + UnloadTexture(mat->maps[texmapType].texture); + mat->maps[texmapType].texture = (Texture2D){ 0 }; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; switch (texmapType) { - case TEXMAP_ALBEDO: + case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_NORMAL: + case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_METALNESS: + case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_ROUGHNESS: + case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_OCCLUSION: + case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_EMISSION: + case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_HEIGHT: + case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); @@ -1481,7 +1476,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(model.transform, matTransform); - model.material.maps[TEXMAP_DIFFUSE].color = tint; // TODO: Multiply tint color by diffuse color? + model.material.maps[MAP_DIFFUSE].color = tint; // TODO: Multiply tint color by diffuse color? rlDrawMesh(model.mesh, model.material, model.transform); } @@ -2244,16 +2239,16 @@ static Material LoadMTL(const char *fileName) case 'd': // Kd float float float Diffuse color (RGB) { sscanf(buffer, "Kd %f %f %f", &color.x, &color.y, &color.z); - material.maps[TEXMAP_DIFFUSE].color.r = (unsigned char)(color.x*255); - material.maps[TEXMAP_DIFFUSE].color.g = (unsigned char)(color.y*255); - material.maps[TEXMAP_DIFFUSE].color.b = (unsigned char)(color.z*255); + material.maps[MAP_DIFFUSE].color.r = (unsigned char)(color.x*255); + material.maps[MAP_DIFFUSE].color.g = (unsigned char)(color.y*255); + material.maps[MAP_DIFFUSE].color.b = (unsigned char)(color.z*255); } break; case 's': // Ks float float float Specular color (RGB) { sscanf(buffer, "Ks %f %f %f", &color.x, &color.y, &color.z); - material.maps[TEXMAP_SPECULAR].color.r = (unsigned char)(color.x*255); - material.maps[TEXMAP_SPECULAR].color.g = (unsigned char)(color.y*255); - material.maps[TEXMAP_SPECULAR].color.b = (unsigned char)(color.z*255); + material.maps[MAP_SPECULAR].color.r = (unsigned char)(color.x*255); + material.maps[MAP_SPECULAR].color.g = (unsigned char)(color.y*255); + material.maps[MAP_SPECULAR].color.b = (unsigned char)(color.z*255); } break; case 'e': // Ke float float float Emmisive color (RGB) { @@ -2285,12 +2280,12 @@ static Material LoadMTL(const char *fileName) if (buffer[5] == 'd') // map_Kd string Diffuse color texture map. { result = sscanf(buffer, "map_Kd %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_DIFFUSE].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_DIFFUSE].texture = LoadTexture(mapFileName); } else if (buffer[5] == 's') // map_Ks string Specular color texture map. { result = sscanf(buffer, "map_Ks %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_SPECULAR].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_SPECULAR].texture = LoadTexture(mapFileName); } else if (buffer[5] == 'a') // map_Ka string Ambient color texture map. { @@ -2300,12 +2295,12 @@ static Material LoadMTL(const char *fileName) case 'B': // map_Bump string Bump texture map. { result = sscanf(buffer, "map_Bump %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_NORMAL].texture = LoadTexture(mapFileName); } break; case 'b': // map_bump string Bump texture map. { result = sscanf(buffer, "map_bump %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_NORMAL].texture = LoadTexture(mapFileName); } break; case 'd': // map_d string Opacity texture map. { @@ -2320,7 +2315,7 @@ static Material LoadMTL(const char *fileName) { float alpha = 1.0f; sscanf(buffer, "d %f", &alpha); - material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)(alpha*255); + material.maps[MAP_DIFFUSE].color.a = (unsigned char)(alpha*255); } else if (buffer[1] == 'i') // disp string Displacement map { @@ -2330,13 +2325,13 @@ static Material LoadMTL(const char *fileName) case 'b': // bump string Bump texture map { result = sscanf(buffer, "bump %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_NORMAL].texture = LoadTexture(mapFileName); } break; case 'T': // Tr float Transparency Tr (alpha). Tr is inverse of d { float ialpha = 0.0f; sscanf(buffer, "Tr %f", &ialpha); - material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)((1.0f - ialpha)*255); + material.maps[MAP_DIFFUSE].color.a = (unsigned char)((1.0f - ialpha)*255); } break; case 'r': // refl string Reflection texture map diff --git a/src/raylib.h b/src/raylib.h index c84d6ce4..8d93a214 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -292,9 +292,8 @@ #define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo) // Shader and material limits -#define MAX_SHADER_LOCATIONS 32 -#define MAX_MATERIAL_TEXTURE_MAPS 12 -#define MAX_MATERIAL_PARAMS 8 +#define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct +#define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct //---------------------------------------------------------------------------------- // Structures Definition @@ -405,21 +404,22 @@ typedef struct Camera2D { // Bounding box type typedef struct BoundingBox { - Vector3 min; // minimum vertex box-corner - Vector3 max; // maximum vertex box-corner + Vector3 min; // Minimum vertex box-corner + Vector3 max; // Maximum vertex box-corner } BoundingBox; // Vertex data definning a mesh typedef struct Mesh { - int vertexCount; // number of vertices stored in arrays - int triangleCount; // number of triangles stored (indexed or not) - float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) - float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) - float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) - float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) - float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) - unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) - unsigned short *indices;// vertex indices (in case vertex data comes indexed) + int vertexCount; // Number of vertices stored in arrays + int triangleCount; // Number of triangles stored (indexed or not) + + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) + float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2) + float *tangents; // Vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) + unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices;// Vertex indices (in case vertex data comes indexed) unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) @@ -427,22 +427,22 @@ typedef struct Mesh { // Shader type (generic) typedef struct Shader { - unsigned int id; // Shader program id - int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS + unsigned int id; // Shader program id + int locs[MAX_SHADER_LOCATIONS]; // Shader locations array } Shader; // Material texture map -typedef struct TextureMap { - Texture2D tex; - Color color; - float value; -} TextureMap; +typedef struct MaterialMap { + Texture2D texture; // Material map texture + Color color; // Material map color + float value; // Material map value +} MaterialMap; // Material type (generic) typedef struct Material { - Shader shader; - TextureMap maps[MAX_MATERIAL_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_TEXTURE_MAPS - float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS + Shader shader; // Material shader + MaterialMap maps[MAX_MATERIAL_MAPS]; // Material maps + float *params; // Material generic parameters (if required) } Material; // Model type @@ -526,6 +526,7 @@ typedef enum { LOG_OTHER } LogType; +// Shader location point type typedef enum { LOC_VERTEX_POSITION = 0, LOC_VERTEX_TEXCOORD01, @@ -541,38 +542,39 @@ typedef enum { LOC_COLOR_DIFFUSE, LOC_COLOR_SPECULAR, LOC_COLOR_AMBIENT, - LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE - LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR - LOC_TEXMAP_NORMAL, - LOC_TEXMAP_ROUGHNESS, - LOC_TEXMAP_OCCUSION, - LOC_TEXMAP_EMISSION, - LOC_TEXMAP_HEIGHT, - LOC_TEXMAP_CUBEMAP, - LOC_TEXMAP_IRRADIANCE, - LOC_TEXMAP_PREFILTER, - LOC_TEXMAP_BRDF + LOC_MAP_ALBEDO, // LOC_MAP_DIFFUSE + LOC_MAP_METALNESS, // LOC_MAP_SPECULAR + LOC_MAP_NORMAL, + LOC_MAP_ROUGHNESS, + LOC_MAP_OCCUSION, + LOC_MAP_EMISSION, + LOC_MAP_HEIGHT, + LOC_MAP_CUBEMAP, + LOC_MAP_IRRADIANCE, + LOC_MAP_PREFILTER, + LOC_MAP_BRDF } ShaderLocationIndex; -#define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO -#define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS +#define LOC_MAP_DIFFUSE LOC_MAP_ALBEDO +#define LOC_MAP_SPECULAR LOC_MAP_METALNESS +// Material map type typedef enum { - TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE - TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR - TEXMAP_NORMAL = 2, - TEXMAP_ROUGHNESS = 3, - TEXMAP_OCCLUSION, - TEXMAP_EMISSION, - TEXMAP_HEIGHT, - TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_BRDF + MAP_ALBEDO = 0, // MAP_DIFFUSE + MAP_METALNESS = 1, // MAP_SPECULAR + MAP_NORMAL = 2, + MAP_ROUGHNESS = 3, + MAP_OCCLUSION, + MAP_EMISSION, + MAP_HEIGHT, + MAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_BRDF } TexmapIndex; -#define TEXMAP_DIFFUSE TEXMAP_ALBEDO -#define TEXMAP_SPECULAR TEXMAP_METALNESS +#define MAP_DIFFUSE MAP_ALBEDO +#define MAP_SPECULAR MAP_METALNESS // Texture formats // NOTE: Support depends on OpenGL version and platform @@ -1037,8 +1039,6 @@ RLAPI void UnloadShader(Shader shader); // Unl RLAPI Shader GetShaderDefault(void); // Get default shader RLAPI Texture2D GetTextureDefault(void); // Get default texture -RLAPI Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture - // Shader configuration functions RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) @@ -1047,6 +1047,12 @@ RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +// Texture maps generation (PBR) +RLAPI Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture +RLAPI Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture using cubemap data +RLAPI Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture using cubemap data +RLAPI Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture using cubemap data + // Shading begin/end functions RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader) diff --git a/src/rlgl.c b/src/rlgl.c index 742b0ed5..b9576b9b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -340,13 +340,13 @@ static Shader LoadShaderDefault(void); // Load default shader (just vertex static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) static void UnloadShaderDefault(void); // Unload default shader -static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) -static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data -static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data -static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +static void LoadBuffersDefault(void); // Load default internal buffers (lines, triangles, quads) +static void UpdateBuffersDefault(void); // Update default internal buffers (VAOs/VBOs) with vertex data +static void DrawBuffersDefault(void); // Draw default internal buffers vertex data +static void UnloadBuffersDefault(void); // Unload default internal buffers vertex data from CPU and GPU -static void RenderCube(void); -static void RenderQuad(void); +static void GenDrawCube(void); // Generate and draw cube +static void GenDrawQuad(void); // Generate and draw quad #if defined(SUPPORT_VR_SIMULATOR) static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters @@ -1219,7 +1219,7 @@ void rlglInit(int width, int height) currentShader = defaultShader; // Init default vertex arrays buffers (lines, triangles, quads) - LoadDefaultBuffers(); + LoadBuffersDefault(); // Init temp vertex buffer, used when transformation required (translate, rotate, scale) tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); @@ -1288,7 +1288,7 @@ void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UnloadShaderDefault(); - UnloadDefaultBuffers(); + UnloadBuffersDefault(); // Delete default white texture glDeleteTextures(1, &whiteTexture); @@ -1306,14 +1306,14 @@ void rlglDraw(void) //for (int i = 0; i < modelsCount; i++) rlDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); // NOTE: Default buffers upload and draw - UpdateDefaultBuffers(); - DrawDefaultBuffers(); // NOTE: Stereo rendering is checked inside + UpdateBuffersDefault(); + DrawBuffersDefault(); // NOTE: Stereo rendering is checked inside #endif } // Load OpenGL extensions // NOTE: External loader function could be passed as a pointer -void rlglLoadExtensions(void *loader) +void rlLoadExtensions(void *loader) { #if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) @@ -1718,422 +1718,6 @@ void rlGenerateMipmaps(Texture2D *texture) glBindTexture(GL_TEXTURE_2D, 0); } -// Generated cubemap texture -Texture2D rlGenMapCubemap(Texture2D skyHDR, int size) -{ - Texture2D cubemap = { 0 }; - - #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader - #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader - - Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); - - // Get cubemap shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); - int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); - - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 - - // Set up depth face culling and cubemap seamless - glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - // Setup framebuffer - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - - // Set up cubemap to render and attach to framebuffer - // NOTE: faces are stored with 16 bit floating point values - glGenTextures(1, &cubemap.id); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - for (unsigned int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); - Matrix fboViews[6] = { - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) - }; - - // Convert HDR equirectangular environment map to cubemap equivalent - glUseProgram(shader.id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, skyHDR.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); - - // Note: don't forget to configure the viewport to the capture dimensions - glViewport(0, 0, size, size); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - for (unsigned int i = 0; i < 6; i++) - { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderCube(); - } - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - cubemap.width = size; - cubemap.height = size; - - // Reset viewport dimensions to default - glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - //glEnable(GL_CULL_FACE); - - return cubemap; -} - -Texture2D rlGenMapIrradiance(Texture2D cubemap, int size) -{ - Texture2D irradiance = { 0 }; - - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - - // Get irradiance shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); - int texmapLoc = GetShaderLocation(shader, "environmentMap"); - - // Set up shaders constant values - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); - - // Setup framebuffer - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - - // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale - glGenTextures(1, &irradiance.id); - glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); - for (unsigned int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); - Matrix fboViews[6] = { - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) - }; - - // Solve diffuse integral by convolution to create an irradiance cubemap - glUseProgram(shader.id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); - - // Note: don't forget to configure the viewport to the capture dimensions - glViewport(0, 0, size, size); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - for (unsigned int i = 0; i < 6; i++) - { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderCube(); - } - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - irradiance.width = size; - irradiance.height = size; - - return irradiance; -} - -Texture2D rlGenMapPrefilter(Texture2D cubemap, int size) -{ - Texture2D prefilter = { 0 }; - - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - - // Get prefilter shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); - int roughnessLoc = GetShaderLocation(shader, "roughness"); - int texmapLoc = GetShaderLocation(shader, "environmentMap"); - - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); - - // Setup framebuffer - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - - // Create a prefiltered HDR environment map - glGenTextures(1, &prefilter.id); - glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); - for (unsigned int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Generate mipmaps for the prefiltered HDR texture - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - - // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); - Matrix fboViews[6] = { - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) - }; - - // Prefilter HDR and store data into mipmap levels - glUseProgram(shader.id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); - - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps - - for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) - { - // Resize framebuffer according to mip-level size. - unsigned int mipWidth = size*powf(0.5f, mip); - unsigned int mipHeight = size*powf(0.5f, mip); - - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); - glViewport(0, 0, mipWidth, mipHeight); - - float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); - glUniform1f(roughnessLoc, roughness); - - for (unsigned int i = 0; i < 6; ++i) - { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderCube(); - } - } - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - prefilter.width = size; - prefilter.height = size; - - return prefilter; -} - -Texture2D rlGenMapBRDF(Texture2D cubemap, int size) -{ - Texture2D brdf = { 0 }; - - #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader - #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader - - Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - - // Generate BRDF convolution texture - glGenTextures(1, &brdf.id); - glBindTexture(GL_TEXTURE_2D, brdf.id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, size, size, 0, GL_RG, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Render BRDF LUT into a quad using FBO - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); - - rlViewport(0, 0, size, size); - glUseProgram(shader.id); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderQuad(); - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - brdf.width = size; - brdf.height = size; - - return brdf; -} - -// Renders a 1x1 3D cube in NDC -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; -static void RenderCube(void) -{ - // Initialize if it is not yet - if (cubeVAO == 0) - { - GLfloat vertices[] = { - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f - }; - - // Set up cube VAO - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - // Link vertex attributes - glBindVertexArray(cubeVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - - // Render cube - glBindVertexArray(cubeVAO); - glDrawArrays(GL_TRIANGLES, 0, 36); - glBindVertexArray(0); -} - -// Renders a 1x1 XY quad in NDC -GLuint quadVAO = 0; -GLuint quadVBO; -static void RenderQuad(void) -{ - // Initialize if it is not yet - if (quadVAO == 0) - { - GLfloat quadVertices[] = { - // Positions // Texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - }; - - // Set up plane VAO - glGenVertexArrays(1, &quadVAO); - glGenBuffers(1, &quadVBO); - glBindVertexArray(quadVAO); - - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, quadVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); - - // Link vertex attributes - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - } - - // Render quad - glBindVertexArray(quadVAO); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); -} - - - // Upload vertex data into a VAO (if supported) and VBO // TODO: Check if mesh has already been loaded in GPU void rlLoadMesh(Mesh *mesh, bool dynamic) @@ -2339,7 +1923,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) { #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, material.maps[TEXMAP_DIFFUSE].tex.id); + glBindTexture(GL_TEXTURE_2D, material.maps[MAP_DIFFUSE].tex.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array @@ -2381,17 +1965,17 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); // Upload to shader material.colDiffuse - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[TEXMAP_DIFFUSE].color.r/255, - (float)material.maps[TEXMAP_DIFFUSE].color.g/255, - (float)material.maps[TEXMAP_DIFFUSE].color.b/255, - (float)material.maps[TEXMAP_DIFFUSE].color.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, + (float)material.maps[MAP_DIFFUSE].color.g/255, + (float)material.maps[MAP_DIFFUSE].color.b/255, + (float)material.maps[MAP_DIFFUSE].color.a/255); // Upload to shader material.colSpecular (if available) if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) - glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[TEXMAP_SPECULAR].color.r/255, - (float)material.maps[TEXMAP_SPECULAR].color.g/255, - (float)material.maps[TEXMAP_SPECULAR].color.b/255, - (float)material.maps[TEXMAP_SPECULAR].color.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255, + (float)material.maps[MAP_SPECULAR].color.g/255, + (float)material.maps[MAP_SPECULAR].color.b/255, + (float)material.maps[MAP_SPECULAR].color.a/255); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -2403,15 +1987,15 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) //----------------------------------------------------- // Bind active texture maps (if available) - for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { - if (material.maps[i].tex.id > 0) + if (material.maps[i].texture.id > 0) { glActiveTexture(GL_TEXTURE0 + i); - if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].tex.id); - else glBindTexture(GL_TEXTURE_2D, material.maps[i].tex.id); + if ((i == MAP_IRRADIANCE) || (i == MAP_PREFILTER) || (i == MAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].texture.id); + else glBindTexture(GL_TEXTURE_2D, material.maps[i].texture.id); - glUniform1i(material.shader.locs[LOC_TEXMAP_DIFFUSE + i], i); + glUniform1i(material.shader.locs[LOC_MAP_DIFFUSE + i], i); } } @@ -2500,10 +2084,10 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) } // Unbind all binded texture maps - for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { glActiveTexture(GL_TEXTURE0 + i); // Set shader active texture - if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + if ((i == MAP_IRRADIANCE) || (i == MAP_PREFILTER) || (i == MAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); else glBindTexture(GL_TEXTURE_2D, 0); // Unbind current active texture } @@ -2738,6 +2322,17 @@ Texture2D GetTextureDefault(void) return texture; } +// Get default shader +Shader GetShaderDefault(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + return defaultShader; +#else + Shader shader = { 0 }; + return shader; +#endif +} + // Load text data from file // NOTE: text chars array should be freed manually char *LoadText(const char *fileName) @@ -2860,17 +2455,6 @@ void EndShaderMode(void) #endif } -// Get default shader -Shader GetShaderDefault(void) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return defaultShader; -#else - Shader shader = { 0 }; - return shader; -#endif -} - // Get shader uniform location int GetShaderLocation(Shader shader, const char *uniformName) { @@ -2900,48 +2484,363 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) #endif } -// Set shader uniform value (int) -void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) +// Set shader uniform value (int) +void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); + + if (size == 1) glUniform1iv(uniformLoc, 1, value); // Shader uniform type: int + else if (size == 2) glUniform2iv(uniformLoc, 1, value); // Shader uniform type: ivec2 + else if (size == 3) glUniform3iv(uniformLoc, 1, value); // Shader uniform type: ivec3 + else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 + else TraceLog(LOG_WARNING, "Shader value int array size not supported"); + + //glUseProgram(0); +#endif +} + +// Set shader uniform value (matrix 4x4) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); + + glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + + //glUseProgram(0); +#endif +} + +// Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixProjection(Matrix proj) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + projection = proj; +#endif +} + +// Set a custom modelview matrix (replaces internal modelview matrix) +void SetMatrixModelview(Matrix view) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + modelview = view; +#endif +} + +// Generate cubemap texture from HDR texture +Texture2D GenTextureCubemap(Texture2D skyHDR, int size) +{ + Texture2D cubemap = { 0 }; + + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + + Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + + // Get cubemap shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 + + // Set up depth face culling and cubemap seamless + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Set up cubemap to render and attach to framebuffer + // NOTE: faces are stored with 16 bit floating point values + glGenTextures(1, &cubemap.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Convert HDR equirectangular environment map to cubemap equivalent + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, skyHDR.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + //glEnable(GL_CULL_FACE); + + UnloadShader(shader); + + cubemap.width = size; + cubemap.height = size; + + return cubemap; +} + +// Generate irradiance texture using cubemap data +Texture2D GenTextureIrradiance(Texture2D cubemap, int size) +{ + Texture2D irradiance = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + + // Get irradiance shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + // Set up shaders constant values + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale + glGenTextures(1, &irradiance.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Solve diffuse integral by convolution to create an irradiance cubemap + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + UnloadShader(shader); + + irradiance.width = size; + irradiance.height = size; + + return irradiance; +} + +// Generate prefilter texture using cubemap data +Texture2D GenTexturePrefilter(Texture2D cubemap, int size) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + Texture2D prefilter = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + + // Get prefilter shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int roughnessLoc = GetShaderLocation(shader, "roughness"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create a prefiltered HDR environment map + glGenTextures(1, &prefilter.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Generate mipmaps for the prefiltered HDR texture + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Prefilter HDR and store data into mipmap levels glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); - if (size == 1) glUniform1iv(uniformLoc, 1, value); // Shader uniform type: int - else if (size == 2) glUniform2iv(uniformLoc, 1, value); // Shader uniform type: ivec2 - else if (size == 3) glUniform3iv(uniformLoc, 1, value); // Shader uniform type: ivec3 - else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 - else TraceLog(LOG_WARNING, "Shader value int array size not supported"); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps - //glUseProgram(0); -#endif -} + for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) + { + // Resize framebuffer according to mip-level size. + unsigned int mipWidth = size*powf(0.5f, mip); + unsigned int mipHeight = size*powf(0.5f, mip); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); + glViewport(0, 0, mipWidth, mipHeight); -// Set shader uniform value (matrix 4x4) -void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(shader.id); + float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); + glUniform1f(roughnessLoc, roughness); - glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + for (unsigned int i = 0; i < 6; ++i) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawCube(); + } + } - //glUseProgram(0); -#endif + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + UnloadShader(shader); + + prefilter.width = size; + prefilter.height = size; + + return prefilter; } -// Set a custom projection matrix (replaces internal projection matrix) -void SetMatrixProjection(Matrix proj) +// Generate BRDF texture using cubemap data +Texture2D GenTextureBRDF(Texture2D cubemap, int size) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - projection = proj; -#endif -} + Texture2D brdf = { 0 }; + + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + + // Generate BRDF convolution texture + glGenTextures(1, &brdf.id); + glBindTexture(GL_TEXTURE_2D, brdf.id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, size, size, 0, GL_RG, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// Set a custom modelview matrix (replaces internal modelview matrix) -void SetMatrixModelview(Matrix view) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - modelview = view; -#endif + // Render BRDF LUT into a quad using FBO + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); + + glViewport(0, 0, size, size); + glUseProgram(shader.id); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawQuad(); + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + UnloadShader(shader); + + brdf.width = size; + brdf.height = size; + + return brdf; } // Begin blending mode (alpha, additive, multiplied) @@ -3182,8 +3081,8 @@ void EndVrDrawing(void) rlDisableTexture(); // Update and draw render texture fbo with distortion to backbuffer - UpdateDefaultBuffers(); - DrawDefaultBuffers(); + UpdateBuffersDefault(); + DrawBuffersDefault(); // Restore defaultShader currentShader = defaultShader; @@ -3452,7 +3351,7 @@ static Shader LoadShaderDefault(void) // Get handles to GLSL uniform locations shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvpMatrix"); shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); - shader.locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); + shader.locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); } else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); @@ -3484,9 +3383,9 @@ static void SetShaderDefaultLocations(Shader *shader) // Get handles to GLSL uniform locations (fragment shader) shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); - shader->locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); - shader->locs[LOC_TEXMAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); - shader->locs[LOC_TEXMAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); + shader->locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); + shader->locs[LOC_MAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); + shader->locs[LOC_MAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) } @@ -3504,7 +3403,7 @@ static void UnloadShaderDefault(void) } // Load default internal buffers (lines, triangles, quads) -static void LoadDefaultBuffers(void) +static void LoadBuffersDefault(void) { // [CPU] Allocate and initialize float array buffers to store vertex data (lines, triangles, quads) //-------------------------------------------------------------------------------------------- @@ -3677,7 +3576,7 @@ static void LoadDefaultBuffers(void) // Update default internal buffers (VAOs/VBOs) with vertex array data // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required) -static void UpdateDefaultBuffers(void) +static void UpdateBuffersDefault(void) { // Update lines vertex buffers if (lines.vCounter > 0) @@ -3747,7 +3646,7 @@ static void UpdateDefaultBuffers(void) // Draw default internal buffers vertex data // NOTE: We draw in this order: lines, triangles, quads -static void DrawDefaultBuffers() +static void DrawBuffersDefault() { Matrix matProjection = projection; Matrix matModelView = modelview; @@ -3773,7 +3672,7 @@ static void DrawDefaultBuffers() glUniformMatrix4fv(currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); glUniform4f(currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(currentShader.locs[LOC_TEXMAP_DIFFUSE], 0); + glUniform1i(currentShader.locs[LOC_MAP_DIFFUSE], 0); // NOTE: Additional map textures not considered for default buffers drawing } @@ -3897,10 +3796,10 @@ static void DrawDefaultBuffers() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures } - if (vaoSupported) glBindVertexArray(0); // Unbind VAO + if (vaoSupported) glBindVertexArray(0); // Unbind VAO glUseProgram(0); // Unbind shader program } @@ -3928,7 +3827,7 @@ static void DrawDefaultBuffers() } // Unload default internal buffers vertex data from CPU and GPU -static void UnloadDefaultBuffers(void) +static void UnloadBuffersDefault(void) { // Unbind everything if (vaoSupported) glBindVertexArray(0); @@ -3970,6 +3869,120 @@ static void UnloadDefaultBuffers(void) free(quads.indices); } +// Renders a 1x1 XY quad in NDC +static void GenDrawQuad(void) +{ + unsigned int quadVAO = 0; + unsigned int quadVBO = 0; + + float vertices[] = { + // Positions // Texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + // Set up plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + + // Draw quad + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); + + glDeleteBuffers(1, &quadVBO); + glDeleteVertexArrays(1, &quadVAO); +} + +// Renders a 1x1 3D cube in NDC +GLuint cubeVAO = 0; +GLuint cubeVBO = 0; +static void GenDrawCube(void) +{ + // Lazy initialization + if (cubeVAO == 0) + { + GLfloat vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + // Draw cube + glBindVertexArray(cubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); + + //glDeleteBuffers(1, &cubeVBO); + //glDeleteVertexArrays(1, &cubeVAO); +} + #if defined(SUPPORT_VR_SIMULATOR) // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetStereoConfig(VrDeviceInfo hmd) diff --git a/src/rlgl.h b/src/rlgl.h index 3adf81a5..a509068e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -146,6 +146,7 @@ typedef unsigned char byte; typedef enum { false, true } bool; #endif + // Shader location point type typedef enum { LOC_VERTEX_POSITION = 0, LOC_VERTEX_TEXCOORD01, @@ -161,38 +162,39 @@ typedef unsigned char byte; LOC_COLOR_DIFFUSE, LOC_COLOR_SPECULAR, LOC_COLOR_AMBIENT, - LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE - LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR - LOC_TEXMAP_NORMAL, - LOC_TEXMAP_ROUGHNESS, - LOC_TEXMAP_OCCUSION, - LOC_TEXMAP_EMISSION, - LOC_TEXMAP_HEIGHT, - LOC_TEXMAP_CUBEMAP, - LOC_TEXMAP_IRRADIANCE, - LOC_TEXMAP_PREFILTER, - LOC_TEXMAP_BRDF + LOC_MAP_ALBEDO, // LOC_MAP_DIFFUSE + LOC_MAP_METALNESS, // LOC_MAP_SPECULAR + LOC_MAP_NORMAL, + LOC_MAP_ROUGHNESS, + LOC_MAP_OCCUSION, + LOC_MAP_EMISSION, + LOC_MAP_HEIGHT, + LOC_MAP_CUBEMAP, + LOC_MAP_IRRADIANCE, + LOC_MAP_PREFILTER, + LOC_MAP_BRDF } ShaderLocationIndex; - #define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO - #define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS + #define LOC_MAP_DIFFUSE LOC_MAP_ALBEDO + #define LOC_MAP_SPECULAR LOC_MAP_METALNESS + // Material map type typedef enum { - TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE - TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR - TEXMAP_NORMAL = 2, - TEXMAP_ROUGHNESS = 3, - TEXMAP_OCCLUSION, - TEXMAP_EMISSION, - TEXMAP_HEIGHT, - TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_BRDF + MAP_ALBEDO = 0, // MAP_DIFFUSE + MAP_METALNESS = 1, // MAP_SPECULAR + MAP_NORMAL = 2, + MAP_ROUGHNESS = 3, + MAP_OCCLUSION, + MAP_EMISSION, + MAP_HEIGHT, + MAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_BRDF } TexmapIndex; - #define TEXMAP_DIFFUSE TEXMAP_ALBEDO - #define TEXMAP_SPECULAR TEXMAP_METALNESS + #define MAP_DIFFUSE MAP_ALBEDO + #define MAP_SPECULAR MAP_METALNESS // Color type, RGBA (32bit) typedef struct Color { @@ -237,8 +239,7 @@ typedef unsigned char byte; // Shader and material limits #define MAX_SHADER_LOCATIONS 32 - #define MAX_MATERIAL_TEXTURE_MAPS 12 - #define MAX_MATERIAL_PARAMS 8 + #define MAX_MATERIAL_MAPS 12 // Shader type (generic) typedef struct Shader { @@ -247,16 +248,16 @@ typedef unsigned char byte; } Shader; // Material texture map - typedef struct TextureMap { + typedef struct MaterialMap { Texture2D tex; Color color; float value; - } TextureMap; + } MaterialMap; // Material type (generic) typedef struct Material { Shader shader; - TextureMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS + MaterialMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS } Material; @@ -400,9 +401,10 @@ Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coo // Functions Declaration - rlgl functionality //------------------------------------------------------------------------------------ void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states) -void rlglClose(void); // De-init rlgl -void rlglDraw(void); // Draw VAO/VBO -void rlglLoadExtensions(void *loader); // Load OpenGL extensions +void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures) +void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads) + +void rlLoadExtensions(void *loader); // Load OpenGL extensions // Textures data management unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU @@ -419,12 +421,6 @@ void rlUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update ve void rlDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform void rlUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU -// Texture maps generation (PBR) -Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture -Texture2D rlGenMapIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map -Texture2D rlGenMapPrefilter(Texture2D cubemap, int size); // Generate prefilter texture map -Texture2D rlGenMapBRDF(Texture2D cubemap, int size); // Generate BRDF texture map - // NOTE: There is a set of shader related functions that are available to end user, // to avoid creating function wrappers through core module, they have been directly declared in raylib.h @@ -447,11 +443,19 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +// Texture maps generation (PBR) +Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture +Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map +Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture map +Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture map + +// Shading and blending void BeginShaderMode(Shader shader); // Begin custom shader drawing void EndShaderMode(void); // End custom shader drawing (use default shader) void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) void EndBlendMode(void); // End blending mode (reset to default: alpha blending) +// VR simulator functionality void InitVrSimulator(int vrDevice); // Init VR simulator for selected device void CloseVrSimulator(void); // Close VR simulator for current device void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera -- cgit v1.2.3 From 76c6f0b1e695b4090fd1e98d7f2d7ff7dea25641 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 18:55:26 +0200 Subject: Working on PBR system Moved PBR material loading to example, right decision? --- examples/models/models_material_pbr.c | 195 ++++++++++++++--------------- examples/models/resources/shaders/pbr.fs | 3 +- examples/models/rlights.h | 177 ++++++++++++++++++++++++++ src/models.c | 103 ++++----------- src/raylib.h | 14 +-- src/rlgl.c | 207 ++++++++++++++----------------- 6 files changed, 398 insertions(+), 301 deletions(-) create mode 100644 examples/models/rlights.h (limited to 'src') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 5761b2af..49a905a8 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -12,32 +12,16 @@ #include "raylib.h" #include "raymath.h" -#define MAX_LIGHTS 4 // Max lights supported by shader -#define LIGHT_DISTANCE 3.5f // Light distance from world center -#define LIGHT_HEIGHT 1.0f // Light height position - -typedef enum { - LIGHT_DIRECTIONAL, - LIGHT_POINT -} LightType; - -typedef struct { - bool enabled; - LightType type; - Vector3 position; - Vector3 target; - Color color; - int enabledLoc; - int typeLoc; - int posLoc; - int targetLoc; - int colorLoc; -} Light; - -int lightsCount = 0; // Current amount of created lights - -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader -void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" + +#define CUBEMAP_SIZE 512 // Cubemap texture size +#define IRRADIANCE_SIZE 32 // Irradiance texture size +#define PREFILTERED_SIZE 256 // Prefiltered HDR environment texture size +#define BRDF_SIZE 512 // BRDF LUT texture size + +// PBR material loading +static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); int main() { @@ -54,33 +38,15 @@ int main() // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); - - Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - - SetMaterialTexture(&model.material, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); - SetMaterialTexture(&model.material, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); - SetMaterialTexture(&model.material, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); - SetMaterialTexture(&model.material, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); - SetMaterialTexture(&model.material, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); - - // Set textures filtering for better quality - SetTextureFilter(model.material.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_NORMAL].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_METALNESS].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); - - int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); - SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); + model.material = LoadMaterialPBR((Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode - // Define lights attributes Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.material.shader), CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.material.shader), CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.material.shader), CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.material.shader) }; + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -127,59 +93,88 @@ int main() return 0; } -// Defines a light and get locations from PBR shader -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) +// NOTE: PBR shader is loaded inside this function +static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { - Light light = { 0 }; - - if (lightsCount < MAX_LIGHTS) - { - light.enabled = true; - light.type = type; - light.position = pos; - light.target = targ; - light.color = color; - - char enabledName[32] = "lights[x].enabled\0"; - char typeName[32] = "lights[x].type\0"; - char posName[32] = "lights[x].position\0"; - char targetName[32] = "lights[x].target\0"; - char colorName[32] = "lights[x].color\0"; - enabledName[7] = '0' + lightsCount; - typeName[7] = '0' + lightsCount; - posName[7] = '0' + lightsCount; - targetName[7] = '0' + lightsCount; - colorName[7] = '0' + lightsCount; - - light.enabledLoc = GetShaderLocation(shader, enabledName); - light.typeLoc = GetShaderLocation(shader, typeName); - light.posLoc = GetShaderLocation(shader, posName); - light.targetLoc = GetShaderLocation(shader, targetName); - light.colorLoc = GetShaderLocation(shader, colorName); - - UpdateLightValues(shader, light); - lightsCount++; - } - - return light; -} - -// Send to PBR shader light values -void UpdateLightValues(Shader shader, Light light) -{ - // Send to shader light enabled state and type - SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); - SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); - - // Send to shader light position values - float position[3] = { light.position.x, light.position.y, light.position.z }; - SetShaderValue(shader, light.posLoc, position, 3); - - // Send to shader light target position values - float target[3] = { light.target.x, light.target.y, light.target.z }; - SetShaderValue(shader, light.targetLoc, target, 3); + Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } + + #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader + #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader + + mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); + + // Get required locations points for PBR material + // NOTE: Those location names must be available and used in the shader code + mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + + // Set view matrix location + mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); + mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); + mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); + + // Set PBR standard maps + SetMaterialTexture(&mat, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&mat, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&mat, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&mat, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&mat, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + + // Set environment maps + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - // Send to shader light color values - float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; - SetShaderValue(shader, light.colorLoc, diff, 4); + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); + SetMaterialTexture(&mat, MAP_IRRADIANCE, GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE)); + SetMaterialTexture(&mat, MAP_PREFILTER, GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE)); + SetMaterialTexture(&mat, MAP_BRDF, GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE)); + UnloadTexture(cubemap); + UnloadTexture(texHDR); + + UnloadShader(shdrCubemap); + UnloadShader(shdrIrradiance); + UnloadShader(shdrPrefilter); + UnloadShader(shdrBRDF); + + // Set textures filtering for better quality + SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); + + int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); + SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1); + + // Set up material properties color + mat.maps[MAP_ALBEDO].color = albedo; + mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[MAP_METALNESS].value = metalness; + mat.maps[MAP_ROUGHNESS].value = roughness; + mat.maps[MAP_OCCLUSION].value = 1.0f; + mat.maps[MAP_EMISSION].value = 0.5f; + mat.maps[MAP_HEIGHT].value = 0.5f; + + return mat; } diff --git a/examples/models/resources/shaders/pbr.fs b/examples/models/resources/shaders/pbr.fs index 06814823..38d56c5d 100644 --- a/examples/models/resources/shaders/pbr.fs +++ b/examples/models/resources/shaders/pbr.fs @@ -8,10 +8,11 @@ #version 330 -#define MAX_LIGHTS 4 #define MAX_REFLECTION_LOD 4.0 #define MAX_DEPTH_LAYER 20 #define MIN_DEPTH_LAYER 10 + +#define MAX_LIGHTS 4 #define LIGHT_DIRECTIONAL 0 #define LIGHT_POINT 1 diff --git a/examples/models/rlights.h b/examples/models/rlights.h new file mode 100644 index 00000000..0da3e2cb --- /dev/null +++ b/examples/models/rlights.h @@ -0,0 +1,177 @@ +/********************************************************************************************** +* +* raylib.lights - Some useful functions to deal with lights data +* +* CONFIGURATION: +* +* #define RLIGHTS_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2017 Victor Fisac and Ramon Santamaria +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RLIGHTS_H +#define RLIGHTS_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 4 // Max lights supported by shader +#define LIGHT_DISTANCE 3.5f // Light distance from world center +#define LIGHT_HEIGHT 1.0f // Light height position + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +typedef struct { + bool enabled; + LightType type; + Vector3 position; + Vector3 target; + Color color; + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +int lightsCount = 0; // Current amount of created lights + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader +void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values + +#ifdef __cplusplus +} +#endif + +#endif // RLIGHTS_H + + +/*********************************************************************************** +* +* RLIGHTS IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RLIGHTS_IMPLEMENTATION) + +#include "raylib.h" + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Defines a light and get locations from PBR shader +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = pos; + light.target = targ; + light.color = color; + + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + lightsCount++; + } + + return light; +} + +// Send to PBR shader light values +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); + SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, 3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, 3); + + // Send to shader light color values + float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, diff, 4); +} + +#endif // RLIGHTS_IMPLEMENTATION \ No newline at end of file diff --git a/src/models.c b/src/models.c index 660ecc79..34156b61 100644 --- a/src/models.c +++ b/src/models.c @@ -1272,6 +1272,9 @@ Material LoadMaterial(const char *fileName) TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); #endif + // Our material uses the default shader (DIFFUSE, SPECULAR, NORMAL) + material.shader = GetShaderDefault(); + return material; } @@ -1282,8 +1285,8 @@ Material LoadMaterialDefault(void) material.shader = GetShaderDefault(); material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel) - //material.maps[MAP_NORMAL].tex; // NOTE: By default, not set - //material.maps[MAP_SPECULAR].tex; // NOTE: By default, not set + //material.maps[MAP_NORMAL].texture; // NOTE: By default, not set + //material.maps[MAP_SPECULAR].texture; // NOTE: By default, not set material.maps[MAP_DIFFUSE].color = WHITE; // Diffuse color material.maps[MAP_SPECULAR].color = WHITE; // Specular color @@ -1291,58 +1294,6 @@ Material LoadMaterialDefault(void) return material; } -// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) -Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) -{ - Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } - - #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader - #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader - - mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); - - // Get required locations points for PBR material - // NOTE: Those location names must be available and used in the shader code - mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); - mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); - mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); - mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); - mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); - mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); - mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); - mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); - mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); - mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); - - // Set view matrix location - mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); - mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); - mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); - - // Set up material properties color - mat.maps[MAP_ALBEDO].color = albedo; - mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; - mat.maps[MAP_METALNESS].value = metalness; - mat.maps[MAP_ROUGHNESS].value = roughness; - mat.maps[MAP_OCCLUSION].value = 1.0f; - mat.maps[MAP_EMISSION].value = 0.0f; - mat.maps[MAP_HEIGHT].value = 0.0f; - - #define CUBEMAP_SIZE 512 // Cubemap texture size - #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size - #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size - #define BRDF_SIZE 512 // BRDF LUT texture map size - - // Set up environment materials cubemap - Texture2D cubemap = GenTextureCubemap(hdr, CUBEMAP_SIZE); - mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(cubemap, IRRADIANCE_SIZE); - mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(cubemap, PREFILTERED_SIZE); - mat.maps[MAP_BRDF].texture = GenTextureBRDF(cubemap, BRDF_SIZE); - UnloadTexture(cubemap); - - return mat; -} - // Unload material from memory void UnloadMaterial(Material material) { @@ -1358,96 +1309,96 @@ void UnloadMaterial(Material material) } // Set material texture -void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) +void SetMaterialTexture(Material *mat, int mapType, Texture2D texture) { - mat->maps[texmapType].texture = texture; + mat->maps[mapType].texture = texture; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; - switch (texmapType) + switch (mapType) { case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; } } // Unset texture from material and unload it from GPU -void UnsetMaterialTexture(Material *mat, int texmapType) +void UnsetMaterialTexture(Material *mat, int mapType) { - UnloadTexture(mat->maps[texmapType].texture); - mat->maps[texmapType].texture = (Texture2D){ 0 }; + UnloadTexture(mat->maps[mapType].texture); + mat->maps[mapType].texture = (Texture2D){ 0 }; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; - switch (texmapType) + switch (mapType) { case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; } } @@ -2188,7 +2139,7 @@ static Material LoadMTL(const char *fileName) { #define MAX_BUFFER_SIZE 128 - Material material = { 0 }; // LoadDefaultMaterial(); + Material material = { 0 }; char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; diff --git a/src/raylib.h b/src/raylib.h index 8d93a214..22ef06cb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -996,10 +996,9 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Material loading/unloading functions RLAPI Material LoadMaterial(const char *fileName); // Load material from file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) -RLAPI Material LoadMaterialPBR(Texture2D cubemap, Color albedo, float metalness, float roughness); // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS...) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) -RLAPI void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture); // Set material texture -RLAPI void UnsetMaterialTexture(Material *mat, int texmapType); // Unset texture from material and unload it from GPU +RLAPI void SetMaterialTexture(Material *mat, int mapType, Texture2D texture); // Set material texture +RLAPI void UnsetMaterialTexture(Material *mat, int mapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -1048,10 +1047,11 @@ RLAPI void SetMatrixProjection(Matrix proj); // Set RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) // Texture maps generation (PBR) -RLAPI Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture -RLAPI Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture using cubemap data -RLAPI Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture using cubemap data -RLAPI Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture using cubemap data +// NOTE: Required shaders should be provided +RLAPI Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture +RLAPI Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data +RLAPI Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data +RLAPI Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size); // Generate BRDF texture using cubemap data // Shading begin/end functions RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing diff --git a/src/rlgl.c b/src/rlgl.c index b9576b9b..e6d1bbfb 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1957,15 +1957,14 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) // Bind shader program glUseProgram(material.shader.id); - // Matrices and other values required by shader //----------------------------------------------------- - // Calculate and send to shader model matrix (used by PBR shader) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); // Upload to shader material.colDiffuse - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, + if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, (float)material.maps[MAP_DIFFUSE].color.g/255, (float)material.maps[MAP_DIFFUSE].color.b/255, (float)material.maps[MAP_DIFFUSE].color.a/255); @@ -1976,6 +1975,9 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) (float)material.maps[MAP_SPECULAR].color.g/255, (float)material.maps[MAP_SPECULAR].color.b/255, (float)material.maps[MAP_SPECULAR].color.a/255); + + if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview); + if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -2417,7 +2419,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Get the location of the named uniform GLuint location = glGetUniformLocation(shader.id, name); - TraceLog(LOG_INFO, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); + TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); } #endif @@ -2529,18 +2531,13 @@ void SetMatrixModelview(Matrix view) } // Generate cubemap texture from HDR texture -Texture2D GenTextureCubemap(Texture2D skyHDR, int size) +Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; - #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader - #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader - - Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); - // Get cubemap shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 @@ -2586,7 +2583,7 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, skyHDR.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); // Note: don't forget to configure the viewport to the capture dimensions glViewport(0, 0, size, size); @@ -2594,7 +2591,7 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) for (unsigned int i = 0; i < 6; i++) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2607,8 +2604,6 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); //glEnable(GL_CULL_FACE); - UnloadShader(shader); - cubemap.width = size; cubemap.height = size; @@ -2616,18 +2611,13 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) } // Generate irradiance texture using cubemap data -Texture2D GenTextureIrradiance(Texture2D cubemap, int size) +Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - // Get irradiance shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int texmapLoc = GetShaderLocation(shader, "environmentMap"); // Set up shaders constant values @@ -2669,7 +2659,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); // Note: don't forget to configure the viewport to the capture dimensions glViewport(0, 0, size, size); @@ -2677,7 +2667,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) for (unsigned int i = 0; i < 6; i++) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2688,9 +2678,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - - UnloadShader(shader); - + irradiance.width = size; irradiance.height = size; @@ -2698,18 +2686,13 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) } // Generate prefilter texture using cubemap data -Texture2D GenTexturePrefilter(Texture2D cubemap, int size) +Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - // Get prefilter shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int roughnessLoc = GetShaderLocation(shader, "roughness"); int texmapLoc = GetShaderLocation(shader, "environmentMap"); @@ -2754,7 +2737,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -2775,7 +2758,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) for (unsigned int i = 0; i < 6; ++i) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2787,9 +2770,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - - UnloadShader(shader); - + prefilter.width = size; prefilter.height = size; @@ -2797,15 +2778,10 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) } // Generate BRDF texture using cubemap data -Texture2D GenTextureBRDF(Texture2D cubemap, int size) +Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) { Texture2D brdf = { 0 }; - #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader - #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader - - Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - // Generate BRDF convolution texture glGenTextures(1, &brdf.id); glBindTexture(GL_TEXTURE_2D, brdf.id); @@ -2835,8 +2811,6 @@ Texture2D GenTextureBRDF(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - UnloadShader(shader); - brdf.width = size; brdf.height = size; @@ -3380,6 +3354,8 @@ static void SetShaderDefaultLocations(Shader *shader) // Get handles to GLSL uniform locations (vertex shader) shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); + shader->locs[LOC_MATRIX_PROJECTION] = glGetUniformLocation(shader->id, "projection"); + shader->locs[LOC_MATRIX_VIEW] = glGetUniformLocation(shader->id, "view"); // Get handles to GLSL uniform locations (fragment shader) shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); @@ -3894,9 +3870,9 @@ static void GenDrawQuad(void) // Link vertex attributes glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Draw quad glBindVertexArray(quadVAO); @@ -3908,79 +3884,76 @@ static void GenDrawQuad(void) } // Renders a 1x1 3D cube in NDC -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; static void GenDrawCube(void) { - // Lazy initialization - if (cubeVAO == 0) - { - GLfloat vertices[] = { - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f - }; - - // Set up cube VAO - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - // Link vertex attributes - glBindVertexArray(cubeVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } + unsigned int cubeVAO = 0; + unsigned int cubeVBO = 0; + + float vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); // Draw cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - //glDeleteBuffers(1, &cubeVBO); - //glDeleteVertexArrays(1, &cubeVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteVertexArrays(1, &cubeVAO); } #if defined(SUPPORT_VR_SIMULATOR) -- cgit v1.2.3 From 0dabb2708bf80989a309b409aced4a313e27c5cd Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 19:53:53 +0200 Subject: Reorganized a couple of functions --- src/rlgl.c | 83 +++++++++++++++++++++++++++++++------------------------------- src/rlgl.h | 26 ++++++++++---------- 2 files changed, 54 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index e6d1bbfb..10b349ee 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -992,43 +992,6 @@ void rlClearScreenBuffers(void) //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Stencil buffer not used... } -// Returns current OpenGL version -int rlGetVersion(void) -{ -#if defined(GRAPHICS_API_OPENGL_11) - return OPENGL_11; -#elif defined(GRAPHICS_API_OPENGL_21) - return OPENGL_21; -#elif defined(GRAPHICS_API_OPENGL_33) - return OPENGL_33; -#elif defined(GRAPHICS_API_OPENGL_ES2) - return OPENGL_ES_20; -#endif -} - -// Get world coordinates from screen coordinates -Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view) -{ - Vector3 result = { 0.0f, 0.0f, 0.0f }; - - // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it - Matrix matProjView = MatrixMultiply(proj, view); - MatrixInvert(&matProjView); - - // Create quaternion from source point - Quaternion quat = { source.x, source.y, source.z, 1.0f }; - - // Multiply quat point by unproject matrix - QuaternionTransform(&quat, matProjView); - - // Normalized world points in vectors - result.x = quat.x/quat.w; - result.y = quat.y/quat.w; - result.z = quat.z/quat.w; - - return result; -} - //---------------------------------------------------------------------------------- // Module Functions Definition - rlgl Functions //---------------------------------------------------------------------------------- @@ -1287,11 +1250,10 @@ void rlglInit(int width, int height) void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - UnloadShaderDefault(); - UnloadBuffersDefault(); - - // Delete default white texture - glDeleteTextures(1, &whiteTexture); + UnloadShaderDefault(); // Unload default shader + UnloadBuffersDefault(); // Unload default buffers (lines, triangles, quads) + glDeleteTextures(1, &whiteTexture); // Unload default texture + TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); free(draws); @@ -1311,6 +1273,20 @@ void rlglDraw(void) #endif } +// Returns current OpenGL version +int rlGetVersion(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) + return OPENGL_11; +#elif defined(GRAPHICS_API_OPENGL_21) + return OPENGL_21; +#elif defined(GRAPHICS_API_OPENGL_33) + return OPENGL_33; +#elif defined(GRAPHICS_API_OPENGL_ES2) + return OPENGL_ES_20; +#endif +} + // Load OpenGL extensions // NOTE: External loader function could be passed as a pointer void rlLoadExtensions(void *loader) @@ -1334,6 +1310,29 @@ void rlLoadExtensions(void *loader) #endif } +// Get world coordinates from screen coordinates +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view) +{ + Vector3 result = { 0.0f, 0.0f, 0.0f }; + + // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it + Matrix matProjView = MatrixMultiply(proj, view); + MatrixInvert(&matProjView); + + // Create quaternion from source point + Quaternion quat = { source.x, source.y, source.z, 1.0f }; + + // Multiply quat point by unproject matrix + QuaternionTransform(&quat, matProjView); + + // Normalized world points in vectors + result.x = quat.x/quat.w; + result.y = quat.y/quat.w; + result.z = quat.z/quat.w; + + return result; +} + // Convert image data to OpenGL texture (returns OpenGL valid Id) unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount) { diff --git a/src/rlgl.h b/src/rlgl.h index a509068e..d1b495b6 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -238,27 +238,27 @@ typedef unsigned char byte; } Mesh; // Shader and material limits - #define MAX_SHADER_LOCATIONS 32 - #define MAX_MATERIAL_MAPS 12 + #define MAX_SHADER_LOCATIONS 32 + #define MAX_MATERIAL_MAPS 12 // Shader type (generic) typedef struct Shader { - unsigned int id; // Shader program id - int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS + unsigned int id; // Shader program id + int locs[MAX_SHADER_LOCATIONS]; // Shader locations array } Shader; // Material texture map typedef struct MaterialMap { - Texture2D tex; - Color color; - float value; + Texture2D texture; // Material map texture + Color color; // Material map color + float value; // Material map value } MaterialMap; // Material type (generic) typedef struct Material { - Shader shader; - MaterialMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS - float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS + Shader shader; // Material shader + MaterialMap maps[MAX_MATERIAL_MAPS]; // Material maps + float *params; // Material generic parameters (if required) } Material; // Camera type, defines a camera position/orientation in 3d space @@ -394,17 +394,17 @@ void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (V void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) -int rlGetVersion(void); // Returns current OpenGL version -Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates //------------------------------------------------------------------------------------ // Functions Declaration - rlgl functionality //------------------------------------------------------------------------------------ void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states) void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures) -void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads) +void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads) +int rlGetVersion(void); // Returns current OpenGL version void rlLoadExtensions(void *loader); // Load OpenGL extensions +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates // Textures data management unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU -- cgit v1.2.3 From 52cd5c63243df8be4a13d3500d2701d368c731c5 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 20 Jul 2017 12:26:25 +0200 Subject: Corrected some issues Corrected compilation for OpenGL 1.1 Review mesh data uploading to GPU --- src/models.c | 45 ++++---------------------------------- src/rlgl.c | 71 ++++++++++++++++++++++++------------------------------------ 2 files changed, 32 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/models.c b/src/models.c index 34156b61..7c325c5e 100644 --- a/src/models.c +++ b/src/models.c @@ -592,6 +592,8 @@ Model LoadModel(const char *fileName) model.mesh = LoadMesh(fileName); model.transform = MatrixIdentity(); model.material = LoadMaterialDefault(); + + rlLoadMesh(&model.mesh, false); // Upload mesh data to GPU (static) return model; } @@ -620,6 +622,7 @@ void UnloadModel(Model model) } // Load mesh from file +// NOTE: Mesh data loaded in CPU, not GPU Mesh LoadMesh(const char *fileName) { Mesh mesh = { 0 }; @@ -631,7 +634,6 @@ Mesh LoadMesh(const char *fileName) #endif if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); - else rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) // TODO: Initialize default mesh data in case loading fails, maybe a cube? @@ -648,46 +650,7 @@ void UnloadMesh(Mesh *mesh) Mesh GenMeshCube(float width, float height, float length) { Mesh mesh = { 0 }; - /* - float vertices[] = { - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f - }; - */ + float vertices[] = { -width/2, -height/2, length/2, width/2, -height/2, length/2, diff --git a/src/rlgl.c b/src/rlgl.c index 10b349ee..0700c926 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -317,7 +317,7 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; // Compressed textures support flags static bool texCompDXTSupported = false; // DDS texture compression support -static bool texNPOTSupported = false; // NPOT textures full support +static bool texNPOTSupported = false; // NPOT textures full support static bool texFloatSupported = false; // float textures support (32 bit per channel) static int blendMode = 0; // Track current blending mode @@ -1734,28 +1734,25 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) int drawHint = GL_STATIC_DRAW; if (dynamic) drawHint = GL_DYNAMIC_DRAW; - GLuint vaoId = 0; // Vertex Array Objects (VAO) - GLuint vboId[7] = { 0 }; // Vertex Buffer Objects (VBOs) - if (vaoSupported) { // Initialize Quads VAO (Buffer A) - glGenVertexArrays(1, &vaoId); - glBindVertexArray(vaoId); + glGenVertexArrays(1, &mesh->vaoId); + glBindVertexArray(mesh->vaoId); } // NOTE: Attributes must be uploaded considering default locations points // Enable vertex attributes: position (shader-location = 0) - glGenBuffers(1, &vboId[0]); - glBindBuffer(GL_ARRAY_BUFFER, vboId[0]); + glGenBuffers(1, &mesh->vboId[0]); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->vertices, drawHint); glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(0); // Enable vertex attributes: texcoords (shader-location = 1) - glGenBuffers(1, &vboId[1]); - glBindBuffer(GL_ARRAY_BUFFER, vboId[1]); + glGenBuffers(1, &mesh->vboId[1]); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords, drawHint); glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(1); @@ -1763,8 +1760,8 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) // Enable vertex attributes: normals (shader-location = 2) if (mesh->normals != NULL) { - glGenBuffers(1, &vboId[2]); - glBindBuffer(GL_ARRAY_BUFFER, vboId[2]); + glGenBuffers(1, &mesh->vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[2]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, drawHint); glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(2); @@ -1779,8 +1776,8 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) // Default color vertex attribute (shader-location = 3) if (mesh->colors != NULL) { - glGenBuffers(1, &vboId[3]); - glBindBuffer(GL_ARRAY_BUFFER, vboId[3]); + glGenBuffers(1, &mesh->vboId[3]); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[3]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh->vertexCount, mesh->colors, drawHint); glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); glEnableVertexAttribArray(3); @@ -1795,8 +1792,8 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) // Default tangent vertex attribute (shader-location = 4) if (mesh->tangents != NULL) { - glGenBuffers(1, &vboId[4]); - glBindBuffer(GL_ARRAY_BUFFER, vboId[4]); + glGenBuffers(1, &mesh->vboId[4]); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[4]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->tangents, drawHint); glVertexAttribPointer(4, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(4); @@ -1811,8 +1808,8 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) // Default texcoord2 vertex attribute (shader-location = 5) if (mesh->texcoords2 != NULL) { - glGenBuffers(1, &vboId[5]); - glBindBuffer(GL_ARRAY_BUFFER, vboId[5]); + glGenBuffers(1, &mesh->vboId[5]); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[5]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords2, drawHint); glVertexAttribPointer(5, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(5); @@ -1826,26 +1823,14 @@ void rlLoadMesh(Mesh *mesh, bool dynamic) if (mesh->indices != NULL) { - glGenBuffers(1, &vboId[6]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[6]); + glGenBuffers(1, &mesh->vboId[6]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vboId[6]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->triangleCount*3, mesh->indices, GL_STATIC_DRAW); } - mesh->vboId[0] = vboId[0]; // Vertex position VBO - mesh->vboId[1] = vboId[1]; // Texcoords VBO - mesh->vboId[2] = vboId[2]; // Normals VBO - mesh->vboId[3] = vboId[3]; // Colors VBO - mesh->vboId[4] = vboId[4]; // Tangents VBO - mesh->vboId[5] = vboId[5]; // Texcoords2 VBO - mesh->vboId[6] = vboId[6]; // Indices VBO - if (vaoSupported) { - if (vaoId > 0) - { - mesh->vaoId = vaoId; - TraceLog(LOG_INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); - } + if (mesh->vaoId > 0) TraceLog(LOG_INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); else TraceLog(LOG_WARNING, "Mesh could not be uploaded to VRAM (GPU)"); } else @@ -1922,7 +1907,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) { #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, material.maps[MAP_DIFFUSE].tex.id); + glBindTexture(GL_TEXTURE_2D, material.maps[MAP_DIFFUSE].texture.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array @@ -1937,7 +1922,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) rlPushMatrix(); rlMultMatrixf(MatrixToFloat(transform)); - rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); + rlColor4ub(material.maps[MAP_DIFFUSE].color.r, material.maps[MAP_DIFFUSE].color.g, material.maps[MAP_DIFFUSE].color.b, material.maps[MAP_DIFFUSE].color.a); if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); @@ -2533,7 +2518,7 @@ void SetMatrixModelview(Matrix view) Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; - +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Get cubemap shader locations //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() @@ -2605,7 +2590,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) cubemap.width = size; cubemap.height = size; - +#endif return cubemap; } @@ -2613,7 +2598,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; - +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Get irradiance shader locations //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() @@ -2680,7 +2665,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) irradiance.width = size; irradiance.height = size; - +#endif return irradiance; } @@ -2688,7 +2673,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; - +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Get prefilter shader locations //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() @@ -2772,7 +2757,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) prefilter.width = size; prefilter.height = size; - +#endif return prefilter; } @@ -2780,7 +2765,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) { Texture2D brdf = { 0 }; - +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Generate BRDF convolution texture glGenTextures(1, &brdf.id); glBindTexture(GL_TEXTURE_2D, brdf.id); @@ -2812,7 +2797,7 @@ Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) brdf.width = size; brdf.height = size; - +#endif return brdf; } -- cgit v1.2.3 From 4c06725461227d90feb169b30208e5bc3cec9c4d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 20 Jul 2017 14:27:17 +0200 Subject: Removed useless functions SetMaterialTexture() and UnsetMaterialTexture()... too shader dependant... --- examples/models/models_material_pbr.c | 32 ++++++----- src/models.c | 100 +--------------------------------- 2 files changed, 21 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 49a905a8..f443e245 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -111,8 +111,8 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); - mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); - mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + //mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + //mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); @@ -122,19 +122,18 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); - // Set PBR standard maps - SetMaterialTexture(&mat, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); - SetMaterialTexture(&mat, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); - SetMaterialTexture(&mat, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); - SetMaterialTexture(&mat, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); - SetMaterialTexture(&mat, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + // Set PBR standard maps + mat.maps[MAP_ALBEDO].texture = LoadTexture("resources/pbr/trooper_albedo.png"); + mat.maps[MAP_NORMAL].texture = LoadTexture("resources/pbr/trooper_normals.png"); + mat.maps[MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png"); + mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png"); + mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); // Set environment maps #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader @@ -146,9 +145,9 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); - SetMaterialTexture(&mat, MAP_IRRADIANCE, GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE)); - SetMaterialTexture(&mat, MAP_PREFILTER, GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE)); - SetMaterialTexture(&mat, MAP_BRDF, GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE)); + mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE); + mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE); + mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE); UnloadTexture(cubemap); UnloadTexture(texHDR); @@ -164,6 +163,13 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); + // Enable sample usage in shader for assigned textures + SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, 1); + SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, 1); + SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, 1); + SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, 1); + SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, 1); + int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1); @@ -177,4 +183,4 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.maps[MAP_HEIGHT].value = 0.5f; return mat; -} +} \ No newline at end of file diff --git a/src/models.c b/src/models.c index 7c325c5e..03e0cb45 100644 --- a/src/models.c +++ b/src/models.c @@ -592,8 +592,6 @@ Model LoadModel(const char *fileName) model.mesh = LoadMesh(fileName); model.transform = MatrixIdentity(); model.material = LoadMaterialDefault(); - - rlLoadMesh(&model.mesh, false); // Upload mesh data to GPU (static) return model; } @@ -622,7 +620,7 @@ void UnloadModel(Model model) } // Load mesh from file -// NOTE: Mesh data loaded in CPU, not GPU +// NOTE: Mesh data loaded in CPU and GPU Mesh LoadMesh(const char *fileName) { Mesh mesh = { 0 }; @@ -634,6 +632,7 @@ Mesh LoadMesh(const char *fileName) #endif if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); + else rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) // TODO: Initialize default mesh data in case loading fails, maybe a cube? @@ -1271,101 +1270,6 @@ void UnloadMaterial(Material material) } } -// Set material texture -void SetMaterialTexture(Material *mat, int mapType, Texture2D texture) -{ - mat->maps[mapType].texture = texture; - - // Update MaterialProperty use sampler state to use texture fetch instead of color attribute - int location = -1; - switch (mapType) - { - case MAP_ALBEDO: - { - location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - case MAP_NORMAL: - { - location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - case MAP_METALNESS: - { - location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - case MAP_ROUGHNESS: - { - location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - case MAP_OCCLUSION: - { - location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - case MAP_EMISSION: - { - location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - case MAP_HEIGHT: - { - location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); - } break; - } -} - -// Unset texture from material and unload it from GPU -void UnsetMaterialTexture(Material *mat, int mapType) -{ - UnloadTexture(mat->maps[mapType].texture); - mat->maps[mapType].texture = (Texture2D){ 0 }; - - // Update MaterialProperty use sampler state to use texture fetch instead of color attribute - int location = -1; - switch (mapType) - { - case MAP_ALBEDO: - { - location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - case MAP_NORMAL: - { - location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - case MAP_METALNESS: - { - location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - case MAP_ROUGHNESS: - { - location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - case MAP_OCCLUSION: - { - location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - case MAP_EMISSION: - { - location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - case MAP_HEIGHT: - { - location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); - } break; - } -} - // Draw a model (with texture if set) void DrawModel(Model model, Vector3 position, float scale, Color tint) { -- cgit v1.2.3 From 63fd96354e7ceffcdf292a1aac6d564dc694377c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 20 Jul 2017 14:27:59 +0200 Subject: Simplify a bit GenTexture*() functions Still shader dependant, locations set should be moved out --- src/rlgl.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index 0700c926..44b20b61 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2519,10 +2519,9 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Get cubemap shader locations - //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() - //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() - int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); + // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader + // TODO: Locations should be taken out of this function... too shader dependant... + SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 @@ -2598,14 +2597,11 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Get irradiance shader locations - //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() - //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() - int texmapLoc = GetShaderLocation(shader, "environmentMap"); - // Set up shaders constant values - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader + // TODO: Locations should be taken out of this function... too shader dependant... + SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); // Setup framebuffer unsigned int fbo, rbo; @@ -2673,14 +2669,12 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Get prefilter shader locations - //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() - //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() - int roughnessLoc = GetShaderLocation(shader, "roughness"); - int texmapLoc = GetShaderLocation(shader, "environmentMap"); - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader + // TODO: Locations should be taken out of this function... too shader dependant... + int roughnessLoc = GetShaderLocation(shader, "roughness"); + SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); // Setup framebuffer unsigned int fbo, rbo; -- cgit v1.2.3 From 2679c4ae9b2fefdb0c150a7cd576d5d3297b027b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 09:34:09 +0200 Subject: Review mesh loading and textures generation --- examples/models/models_cubicmap.c | 2 +- examples/models/models_material_pbr.c | 5 +++++ examples/models/models_skybox.c | 31 ++++++++++++++----------------- src/models.c | 20 +++++++++++++++++--- src/raylib.h | 13 ++++++++----- src/rlgl.c | 12 ++++-------- 6 files changed, 49 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 177cf890..268d480a 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -27,7 +27,7 @@ int main() Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f }); - Model model = LoadModelFromMesh(mesh, false); + Model model = LoadModelFromMesh(mesh); // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index f443e245..d55aa773 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -142,6 +142,11 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + + // Setup required shader locations + SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1); + SetShaderValuei(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, 1); + SetShaderValuei(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, 1); Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index d347854f..500cb19b 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -24,24 +24,24 @@ int main() // Define the camera to look into our 3d world Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; - // Load skybox model and shader + // Load skybox model Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); - Model skybox = LoadModelFromMesh(cube, false); + Model skybox = LoadModelFromMesh(cube); + + // Load skybox shader and set required locations + // NOTE: Some locations are automatically set at shader loading skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); - - Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(texHDR, 512); SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, 1); - // Get skybox shader locations - skybox.material.shader.locs[LOC_MATRIX_PROJECTION] = GetShaderLocation(skybox.material.shader, "projection"); - skybox.material.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(skybox.material.shader, "view"); - - // Then before rendering, configure the viewport to the actual screen dimensions - Matrix proj = MatrixPerspective(60.0, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); - MatrixTranspose(&proj); - SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_PROJECTION], proj); - + // Load cubemap shader and setup required shader locations + Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs"); + SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "environmentMap"), (int[1]){ 0 }, 1); + + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512); + + UnloadShader(shdrCubemap); // Cubemap generation shader not required any more + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -53,9 +53,6 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - - Matrix view = MatrixLookAt(camera.position, camera.target, camera.up); - SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_VIEW], view); //---------------------------------------------------------------------------------- // Draw diff --git a/src/models.c b/src/models.c index 03e0cb45..7dce9fa6 100644 --- a/src/models.c +++ b/src/models.c @@ -597,12 +597,13 @@ Model LoadModel(const char *fileName) } // Load model from generated mesh -Model LoadModelFromMesh(Mesh mesh, bool dynamic) +// WARNING: A shallow copy of mesh is generated, passed by value, +// as long as struct contains pointers to data and some values, we get a copy +// of mesh pointing to same data as original version... be careful! +Model LoadModelFromMesh(Mesh mesh) { Model model = { 0 }; - rlLoadMesh(&mesh, dynamic); - model.mesh = mesh; model.transform = MatrixIdentity(); model.material = LoadMaterialDefault(); @@ -646,6 +647,7 @@ void UnloadMesh(Mesh *mesh) } // Generated cuboid mesh +// NOTE: Vertex data is uploaded to GPU Mesh GenMeshCube(float width, float height, float length) { Mesh mesh = { 0 }; @@ -759,11 +761,15 @@ Mesh GenMeshCube(float width, float height, float length) mesh.vertexCount = 24; mesh.triangleCount = 12; + + // Upload vertex data to GPU (static mesh) + rlLoadMesh(&mesh, false); return mesh; } // Generate a mesh from heightmap +// NOTE: Vertex data is uploaded to GPU Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) @@ -865,10 +871,15 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size) } free(pixels); + + // Upload vertex data to GPU (static mesh) + rlLoadMesh(&mesh, false); return mesh; } +// Generate a cubes mesh from pixel data +// NOTE: Vertex data is uploaded to GPU Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { Mesh mesh = { 0 }; @@ -1219,6 +1230,9 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) free(mapTexcoords); free(cubicmapPixels); // Free image pixel data + + // Upload vertex data to GPU (static mesh) + rlLoadMesh(&mesh, false); return mesh; } diff --git a/src/raylib.h b/src/raylib.h index 22ef06cb..cc5b0bb6 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -409,10 +409,11 @@ typedef struct BoundingBox { } BoundingBox; // Vertex data definning a mesh +// NOTE: Data stored in CPU memory (and GPU) typedef struct Mesh { int vertexCount; // Number of vertices stored in arrays int triangleCount; // Number of triangles stored (indexed or not) - + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) @@ -981,15 +982,19 @@ RLAPI void DrawGizmo(Vector3 position); // Model loading/unloading functions RLAPI Model LoadModel(const char *fileName); // Load model from files (mesh and material) -RLAPI Model LoadModelFromMesh(Mesh mesh, bool dynamic); // Load model from generated mesh +RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) // Mesh loading/unloading functions RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file -//RLAPI void UpdateMesh(Mesh *mesh, int type, void *data); // Update mesh data (CPU and GPU) RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM) +//RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with desired subdivisions) RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh +//RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere) +//RLAPI Mesh GenMeshCylinder(float radiusTop, float radiusBottom, float height, int slices); // Generate cylinder mesh +//RLAPI Mesh GenMeshTorus(float radius1, float radius2, int radSeg, int sides); // Generate torus mesh +//RLAPI Mesh GenMeshTube(float radius1, float radius2, float height, int sides); // Generate tube mesh RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data @@ -997,8 +1002,6 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); RLAPI Material LoadMaterial(const char *fileName); // Load material from file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) -RLAPI void SetMaterialTexture(Material *mat, int mapType, Texture2D texture); // Set material texture -RLAPI void UnsetMaterialTexture(Material *mat, int mapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) diff --git a/src/rlgl.c b/src/rlgl.c index 44b20b61..3160c744 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2520,10 +2520,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) Texture2D cubemap = { 0 }; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader - // TODO: Locations should be taken out of this function... too shader dependant... - SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); - - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 + // Other locations should be setup externally in shader before calling the function // Set up depth face culling and cubemap seamless glDisable(GL_CULL_FACE); @@ -2600,8 +2597,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader - // TODO: Locations should be taken out of this function... too shader dependant... - SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); + // Other locations should be setup externally in shader before calling the function // Setup framebuffer unsigned int fbo, rbo; @@ -2672,9 +2668,9 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader + // Other locations should be setup externally in shader before calling the function // TODO: Locations should be taken out of this function... too shader dependant... - int roughnessLoc = GetShaderLocation(shader, "roughness"); - SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); + int roughnessLoc = GetShaderLocation(shader, "roughness"); // Setup framebuffer unsigned int fbo, rbo; -- cgit v1.2.3 From 84aff31973667e6bec29915d60971f9a5bb02a44 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 10:42:41 +0200 Subject: MatrixPerspective() angle required in radians Consistent with similar functions in raymath --- src/core.c | 4 ++-- src/raymath.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 5cdd8e6b..fc653195 100644 --- a/src/core.c +++ b/src/core.c @@ -980,7 +980,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); // Calculate projection matrix (from perspective instead of frustum) - Matrix matProj = MatrixPerspective(camera.fovy, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); + Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); // Calculate view matrix from camera look at Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); @@ -1033,7 +1033,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) Vector2 GetWorldToScreen(Vector3 position, Camera camera) { // Calculate projection matrix (from perspective instead of frustum - Matrix matProj = MatrixPerspective(camera.fovy, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); + Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); // Calculate view matrix from camera look at (and transpose it) Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); diff --git a/src/raymath.h b/src/raymath.h index c4db0f3f..70d1bedd 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -873,9 +873,10 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, } // Returns perspective projection matrix +// NOTE: Angle should be provided in radians RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far) { - double top = near*tan(fovy*PI/360.0); + double top = near*tan(fovy); double right = top*aspect; return MatrixFrustum(-right, right, -top, top, near, far); -- cgit v1.2.3 From 980d9d4cd4ab941afc53bf8a83ea2a18d28ee4e2 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 10:42:57 +0200 Subject: rlgl usable as standalone library --- examples/others/rlgl_standalone.c | 4 ++-- src/rlgl.c | 16 ++++++++-------- src/rlgl.h | 15 ++++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/examples/others/rlgl_standalone.c b/examples/others/rlgl_standalone.c index 70cffee1..5de77bc2 100644 --- a/examples/others/rlgl_standalone.c +++ b/examples/others/rlgl_standalone.c @@ -91,7 +91,7 @@ int main(void) glfwSwapInterval(1); // Load OpenGL 3.3 supported extensions - rlglLoadExtensions(glfwGetProcAddress); + rlLoadExtensions(glfwGetProcAddress); //-------------------------------------------------------- // Initialize OpenGL context (states and resources) @@ -130,7 +130,7 @@ int main(void) rlClearScreenBuffers(); // Clear current framebuffer // Calculate projection matrix (from perspective) and view matrix from camera look at - Matrix matProj = MatrixPerspective(camera.fovy, (double)screenWidth/(double)screenHeight, 0.01, 1000.0); + Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, (double)screenWidth/(double)screenHeight, 0.01, 1000.0); MatrixTranspose(&matProj); Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); diff --git a/src/rlgl.c b/src/rlgl.c index 3160c744..a27645dd 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2548,7 +2548,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); MatrixTranspose(&fboProjection); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -2581,7 +2581,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + glViewport(0, 0, screenWidth, screenHeight); //glEnable(GL_CULL_FACE); cubemap.width = size; @@ -2620,7 +2620,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); MatrixTranspose(&fboProjection); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -2653,7 +2653,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + glViewport(0, 0, screenWidth, screenHeight); irradiance.width = size; irradiance.height = size; @@ -2696,7 +2696,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) glGenerateMipmap(GL_TEXTURE_CUBE_MAP); // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); MatrixTranspose(&fboProjection); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -2743,7 +2743,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + glViewport(0, 0, screenWidth, screenHeight); prefilter.width = size; prefilter.height = size; @@ -2783,7 +2783,7 @@ Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) glBindFramebuffer(GL_FRAMEBUFFER, 0); // Reset viewport dimensions to default - glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + glViewport(0, 0, screenWidth, screenHeight); brdf.width = size; brdf.height = size; @@ -3985,7 +3985,7 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] - Matrix proj = MatrixPerspective(fovy, aspect, 0.01, 1000.0); + Matrix proj = MatrixPerspective(fovy*DEG2RAD, aspect, 0.01, 1000.0); vrConfig.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); vrConfig.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); diff --git a/src/rlgl.h b/src/rlgl.h index d1b495b6..a9ee6ec6 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -435,19 +435,20 @@ void UnloadShader(Shader shader); // Unload a custom shade Shader GetShaderDefault(void); // Get default shader Texture2D GetTextureDefault(void); // Get default texture +// Shader configuration functions int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) - -void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) -void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) // Texture maps generation (PBR) -Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture -Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map -Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture map -Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture map +// NOTE: Required shaders should be provided +Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture +Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data +Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data +Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size); // Generate BRDF texture using cubemap data // Shading and blending void BeginShaderMode(Shader shader); // Begin custom shader drawing -- cgit v1.2.3 From 38d9fcb08ef81cd5a3ab93df825eac7714d03e45 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 15:25:35 +0200 Subject: Moved some functions to raymath Exposed some raymath useful functions to raylib API --- src/core.c | 39 --------------------------------------- src/raylib.h | 9 +++++++-- src/raymath.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/rlgl.c | 38 +++----------------------------------- src/rlgl.h | 1 - 5 files changed, 52 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index fc653195..32d4666b 100644 --- a/src/core.c +++ b/src/core.c @@ -1098,45 +1098,6 @@ float *ColorToFloat(Color color) return buffer; } -// Converts Vector3 to float array -float *VectorToFloat(Vector3 vec) -{ - static float buffer[3]; - - buffer[0] = vec.x; - buffer[1] = vec.y; - buffer[2] = vec.z; - - return buffer; -} - -// NOTE: Returned vector is a transposed version of the Matrix struct, -// it should be this way because, despite raymath use OpenGL column-major convention, -// Matrix struct memory alignment and variables naming are not coherent -float *MatrixToFloat(Matrix mat) -{ - static float buffer[16]; - - buffer[0] = mat.m0; - buffer[1] = mat.m4; - buffer[2] = mat.m8; - buffer[3] = mat.m12; - buffer[4] = mat.m1; - buffer[5] = mat.m5; - buffer[6] = mat.m9; - buffer[7] = mat.m13; - buffer[8] = mat.m2; - buffer[9] = mat.m6; - buffer[10] = mat.m10; - buffer[11] = mat.m14; - buffer[12] = mat.m3; - buffer[13] = mat.m7; - buffer[14] = mat.m11; - buffer[15] = mat.m15; - - return buffer; -} - // Returns a Color struct from hexadecimal value Color GetColor(int hexValue) { diff --git a/src/raylib.h b/src/raylib.h index cc5b0bb6..ec5e61fd 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -742,8 +742,13 @@ RLAPI int GetHexValue(Color color); // Returns hex RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes -RLAPI float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array -RLAPI float *MatrixToFloat(Matrix mat); // Converts Matrix to float array + +// Math useful functions (available from raymath.h) +RLAPI float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array +RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array +RLAPI Vector3 VectorZero(void); // Vector with components value 0.0f +RLAPI Vector3 VectorOne(void); // Vector with components value 1.0f +RLAPI Matrix MatrixIdentity(void); // Returns identity matrix // Misc. functions RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags) diff --git a/src/raymath.h b/src/raymath.h index 70d1bedd..ec824408 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -154,6 +154,7 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate ref RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc +RMDEF float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -177,6 +178,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far); // Returns perspective projection matrix RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); // Returns orthographic projection matrix RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up); // Returns camera look-at matrix (view matrix) +RMDEF float *MatrixToFloat(Matrix mat); // Returns float array of Matrix data //------------------------------------------------------------------------------------ // Functions Declaration to work with Quaternions @@ -502,6 +504,18 @@ RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) return result; } +// Returns Vector3 as float array +RMDEF float *VectorToFloat(Vector3 vec) +{ + static float buffer[3]; + + buffer[0] = vec.x; + buffer[1] = vec.y; + buffer[2] = vec.z; + + return buffer; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- @@ -943,6 +957,34 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) return result; } +// Returns float array of matrix data +// NOTE: Returned vector is a transposed version of the Matrix struct, +// it should be this way because, despite raymath use OpenGL column-major convention, +// Matrix struct memory alignment and variables naming are not coherent +RMDEF float *MatrixToFloat(Matrix mat) +{ + static float buffer[16]; + + buffer[0] = mat.m0; + buffer[1] = mat.m4; + buffer[2] = mat.m8; + buffer[3] = mat.m12; + buffer[4] = mat.m1; + buffer[5] = mat.m5; + buffer[6] = mat.m9; + buffer[7] = mat.m13; + buffer[8] = mat.m2; + buffer[9] = mat.m6; + buffer[10] = mat.m10; + buffer[11] = mat.m14; + buffer[12] = mat.m3; + buffer[13] = mat.m7; + buffer[14] = mat.m11; + buffer[15] = mat.m15; + + return buffer; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Quaternion math //---------------------------------------------------------------------------------- diff --git a/src/rlgl.c b/src/rlgl.c index a27645dd..54b30b90 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -360,10 +360,6 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight); static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight); #endif -#if defined(RLGL_STANDALONE) -float *MatrixToFloat(Matrix mat); // Converts Matrix to float array -#endif - //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix operations //---------------------------------------------------------------------------------- @@ -477,15 +473,15 @@ void rlScalef(float x, float y, float z) } // Multiply the current matrix by another matrix -void rlMultMatrixf(float *m) +void rlMultMatrixf(float *mat) { // Matrix creation from array - Matrix mat = { m[0], m[1], m[2], m[3], + Matrix mat2 = { m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] }; - *currentMatrix = MatrixMultiply(*currentMatrix, mat); + *currentMatrix = MatrixMultiply(*currentMatrix, mat2); } // Multiply the current matrix by a perspective matrix generated by parameters @@ -4176,32 +4172,4 @@ void TraceLog(int msgType, const char *text, ...) if (msgType == LOG_ERROR) exit(1); } - -// Converts Matrix to float array -// NOTE: Returned vector is a transposed version of the Matrix struct, -// it should be this way because, despite raymath use OpenGL column-major convention, -// Matrix struct memory alignment and variables naming are not coherent -float *MatrixToFloat(Matrix mat) -{ - static float buffer[16]; - - buffer[0] = mat.m0; - buffer[1] = mat.m4; - buffer[2] = mat.m8; - buffer[3] = mat.m12; - buffer[4] = mat.m1; - buffer[5] = mat.m5; - buffer[6] = mat.m9; - buffer[7] = mat.m13; - buffer[8] = mat.m2; - buffer[9] = mat.m6; - buffer[10] = mat.m10; - buffer[11] = mat.m14; - buffer[12] = mat.m3; - buffer[13] = mat.m7; - buffer[14] = mat.m11; - buffer[15] = mat.m15; - - return buffer; -} #endif diff --git a/src/rlgl.h b/src/rlgl.h index a9ee6ec6..84ece706 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -465,7 +465,6 @@ void BeginVrDrawing(void); // Begin VR stereo rende void EndVrDrawing(void); // End VR stereo rendering void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) -float *MatrixToFloat(Matrix mat); // Converts Matrix to float array #endif #ifdef __cplusplus -- cgit v1.2.3 From e52032f64660008fdcf0c8d707ef6aed1e6fc32f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 17:19:28 +0200 Subject: Complete review of raymath Now it should be coherent with OpenGL math standards --- src/core.c | 7 +++-- src/models.c | 30 ++++++++++----------- src/raymath.h | 83 +++++++++++++++++++++++++++++------------------------------ src/rlgl.c | 35 +++++++++---------------- src/rlgl.h | 2 +- 5 files changed, 71 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 32d4666b..5e7cc811 100644 --- a/src/core.c +++ b/src/core.c @@ -895,8 +895,8 @@ void Begin3dMode(Camera camera) rlLoadIdentity(); // Reset current matrix (MODELVIEW) // Setup Camera view - Matrix cameraView = MatrixLookAt(camera.position, camera.target, camera.up); - rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) + Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); + rlMultMatrixf(MatrixToFloat(matView)); // Multiply MODELVIEW matrix by view matrix (camera) rlEnableDepthTest(); // Enable DEPTH_TEST for 3D } @@ -991,7 +991,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) // For example, if you get view matrix, transpose and inverted and you transform it // to a vector, you will get its 3d world position coordinates (camera.position). // If you don't transpose, final position will be wrong. - MatrixTranspose(&matView); + //MatrixTranspose(&matView); //#define USE_RLGL_UNPROJECT #if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlUnproject() @@ -1037,7 +1037,6 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera) // Calculate view matrix from camera look at (and transpose it) Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - MatrixTranspose(&matView); // Convert world position vector to quaternion Quaternion worldPos = { position.x, position.y, position.z, 1.0f }; diff --git a/src/models.c b/src/models.c index 7dce9fa6..cfcefc2f 100644 --- a/src/models.c +++ b/src/models.c @@ -119,10 +119,10 @@ void DrawCube(Vector3 position, float width, float height, float length, Color c rlPushMatrix(); - // NOTE: Be careful! Function order matters (rotate -> scale -> translate) + // NOTE: Be careful! Function order matters (scale -> rotate -> translate) + rlScalef(1.0f, 3.0f, 1.0f); + rlRotatef(45, 0, 1, 0); rlTranslatef(position.x, position.y, position.z); - //rlScalef(2.0f, 2.0f, 2.0f); - //rlRotatef(45, 0, 1, 0); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -199,8 +199,8 @@ void DrawCubeWires(Vector3 position, float width, float height, float length, Co rlPushMatrix(); - rlTranslatef(position.x, position.y, position.z); //rlRotatef(45, 0, 1, 0); + rlTranslatef(position.x, position.y, position.z); rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -271,10 +271,10 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei rlEnableTexture(texture.id); //rlPushMatrix(); - // NOTE: Be careful! Function order matters (scale, translate, rotate) + // NOTE: Be careful! Function order matters (scale -> rotate -> translate) //rlScalef(2.0f, 2.0f, 2.0f); - //rlTranslatef(2.0f, 0.0f, 0.0f); //rlRotatef(45, 0, 1, 0); + //rlTranslatef(2.0f, 0.0f, 0.0f); rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); @@ -330,8 +330,8 @@ void DrawSphere(Vector3 centerPos, float radius, Color color) void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color) { rlPushMatrix(); - rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -369,8 +369,8 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color) { rlPushMatrix(); - rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -496,8 +496,8 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Color color) { // NOTE: Plane is always created on XZ ground rlPushMatrix(); - rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(size.x, 1.0f, size.y); + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -567,9 +567,8 @@ void DrawGizmo(Vector3 position) float length = 1.0f; rlPushMatrix(); - rlTranslatef(position.x, position.y, position.z); - //rlRotatef(rotation, 0, 1, 0); rlScalef(length, length, length); + rlTranslatef(position.x, position.y, position.z); rlBegin(RL_LINES); rlColor3f(1.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f); @@ -1347,11 +1346,10 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec // NOTE: Billboard size will maintain sourceRec aspect ratio, size will represent billboard width Vector2 sizeRatio = { size, size*(float)sourceRec.height/sourceRec.width }; - Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up); - MatrixTranspose(&viewMatrix); + Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 }; - //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; + Vector3 right = { matView.m0, matView.m4, matView.m8 }; + //Vector3 up = { matView.m1, matView.m5, matView.m9 }; // NOTE: Billboard locked on axis-Y Vector3 up = { 0.0f, 1.0f, 0.0f }; @@ -1660,7 +1658,7 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) } // Calculate mesh bounding box limits -// NOTE: minVertex and maxVertex should be transformed by model transform matrix (position, scale, rotate) +// NOTE: minVertex and maxVertex should be transformed by model transform matrix BoundingBox CalculateBoundingBox(Mesh mesh) { // Get min and max vertex to construct bounds (AABB) diff --git a/src/raymath.h b/src/raymath.h index ec824408..a4f3f895 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -706,10 +706,10 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right) // Returns translation matrix RMDEF Matrix MatrixTranslate(float x, float y, float z) { - Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - x, y, z, 1.0f }; + Matrix result = { 1.0f, 0.0f, 0.0f, x, + 0.0f, 1.0f, 0.0f, y, + 0.0f, 0.0f, 1.0f, z, + 0.0f, 0.0f, 0.0f, 1.0f }; return result; } @@ -834,22 +834,22 @@ RMDEF Matrix MatrixMultiply(Matrix left, Matrix right) { Matrix result; - result.m0 = right.m0*left.m0 + right.m1*left.m4 + right.m2*left.m8 + right.m3*left.m12; - result.m1 = right.m0*left.m1 + right.m1*left.m5 + right.m2*left.m9 + right.m3*left.m13; - result.m2 = right.m0*left.m2 + right.m1*left.m6 + right.m2*left.m10 + right.m3*left.m14; - result.m3 = right.m0*left.m3 + right.m1*left.m7 + right.m2*left.m11 + right.m3*left.m15; - result.m4 = right.m4*left.m0 + right.m5*left.m4 + right.m6*left.m8 + right.m7*left.m12; - result.m5 = right.m4*left.m1 + right.m5*left.m5 + right.m6*left.m9 + right.m7*left.m13; - result.m6 = right.m4*left.m2 + right.m5*left.m6 + right.m6*left.m10 + right.m7*left.m14; - result.m7 = right.m4*left.m3 + right.m5*left.m7 + right.m6*left.m11 + right.m7*left.m15; - result.m8 = right.m8*left.m0 + right.m9*left.m4 + right.m10*left.m8 + right.m11*left.m12; - result.m9 = right.m8*left.m1 + right.m9*left.m5 + right.m10*left.m9 + right.m11*left.m13; - result.m10 = right.m8*left.m2 + right.m9*left.m6 + right.m10*left.m10 + right.m11*left.m14; - result.m11 = right.m8*left.m3 + right.m9*left.m7 + right.m10*left.m11 + right.m11*left.m15; - result.m12 = right.m12*left.m0 + right.m13*left.m4 + right.m14*left.m8 + right.m15*left.m12; - result.m13 = right.m12*left.m1 + right.m13*left.m5 + right.m14*left.m9 + right.m15*left.m13; - result.m14 = right.m12*left.m2 + right.m13*left.m6 + right.m14*left.m10 + right.m15*left.m14; - result.m15 = right.m12*left.m3 + right.m13*left.m7 + right.m14*left.m11 + right.m15*left.m15; + result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; + result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; + result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; + result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; + result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; + result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; + result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; + result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; + result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; + result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; + result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; + result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; + result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; + result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; + result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; + result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; return result; } @@ -936,50 +936,49 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) VectorNormalize(&x); Vector3 y = VectorCrossProduct(z, x); VectorNormalize(&y); - + result.m0 = x.x; result.m1 = x.y; result.m2 = x.z; - result.m3 = -((x.x*eye.x) + (x.y*eye.y) + (x.z*eye.z)); + result.m3 = 0.0f; result.m4 = y.x; result.m5 = y.y; result.m6 = y.z; - result.m7 = -((y.x*eye.x) + (y.y*eye.y) + (y.z*eye.z)); + result.m7 = 0.0f; result.m8 = z.x; result.m9 = z.y; result.m10 = z.z; - result.m11 = -((z.x*eye.x) + (z.y*eye.y) + (z.z*eye.z)); - result.m12 = 0.0f; - result.m13 = 0.0f; - result.m14 = 0.0f; + result.m11 = 0.0f; + result.m12 = eye.x; + result.m13 = eye.y; + result.m14 = eye.z; result.m15 = 1.0f; + MatrixInvert(&result); + return result; } // Returns float array of matrix data -// NOTE: Returned vector is a transposed version of the Matrix struct, -// it should be this way because, despite raymath use OpenGL column-major convention, -// Matrix struct memory alignment and variables naming are not coherent RMDEF float *MatrixToFloat(Matrix mat) { static float buffer[16]; buffer[0] = mat.m0; - buffer[1] = mat.m4; - buffer[2] = mat.m8; - buffer[3] = mat.m12; - buffer[4] = mat.m1; + buffer[1] = mat.m1; + buffer[2] = mat.m2; + buffer[3] = mat.m3; + buffer[4] = mat.m4; buffer[5] = mat.m5; - buffer[6] = mat.m9; - buffer[7] = mat.m13; - buffer[8] = mat.m2; - buffer[9] = mat.m6; + buffer[6] = mat.m6; + buffer[7] = mat.m7; + buffer[8] = mat.m8; + buffer[9] = mat.m9; buffer[10] = mat.m10; - buffer[11] = mat.m14; - buffer[12] = mat.m3; - buffer[13] = mat.m7; - buffer[14] = mat.m11; + buffer[11] = mat.m11; + buffer[12] = mat.m12; + buffer[13] = mat.m13; + buffer[14] = mat.m14; buffer[15] = mat.m15; return buffer; diff --git a/src/rlgl.c b/src/rlgl.c index 54b30b90..93612896 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -395,7 +395,7 @@ void rlLoadIdentity(void) { glLoadIdentity(); } void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); } void rlRotatef(float angleDeg, float x, float y, float z) { glRotatef(angleDeg, x, y, z); } void rlScalef(float x, float y, float z) { glScalef(x, y, z); } -void rlMultMatrixf(float *mat) { glMultMatrixf(mat); } +void rlMultMatrixf(float *matf) { glMultMatrixf(matf); } #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -445,7 +445,6 @@ void rlLoadIdentity(void) void rlTranslatef(float x, float y, float z) { Matrix matTranslation = MatrixTranslate(x, y, z); - MatrixTranspose(&matTranslation); *currentMatrix = MatrixMultiply(*currentMatrix, matTranslation); } @@ -458,7 +457,6 @@ void rlRotatef(float angleDeg, float x, float y, float z) Vector3 axis = (Vector3){ x, y, z }; VectorNormalize(&axis); matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); - MatrixTranspose(&matRotation); *currentMatrix = MatrixMultiply(*currentMatrix, matRotation); } @@ -467,28 +465,26 @@ void rlRotatef(float angleDeg, float x, float y, float z) void rlScalef(float x, float y, float z) { Matrix matScale = MatrixScale(x, y, z); - MatrixTranspose(&matScale); *currentMatrix = MatrixMultiply(*currentMatrix, matScale); } // Multiply the current matrix by another matrix -void rlMultMatrixf(float *mat) +void rlMultMatrixf(float *matf) { // Matrix creation from array - Matrix mat2 = { m[0], m[1], m[2], m[3], - m[4], m[5], m[6], m[7], - m[8], m[9], m[10], m[11], - m[12], m[13], m[14], m[15] }; + Matrix mat = { matf[0], matf[4], matf[8], matf[12], + matf[1], matf[5], matf[9], matf[13], + matf[2], matf[6], matf[10], matf[14], + matf[3], matf[7], matf[11], matf[15] }; - *currentMatrix = MatrixMultiply(*currentMatrix, mat2); + *currentMatrix = MatrixMultiply(*currentMatrix, mat); } // Multiply the current matrix by a perspective matrix generated by parameters void rlFrustum(double left, double right, double bottom, double top, double near, double far) { Matrix matPerps = MatrixFrustum(left, right, bottom, top, near, far); - MatrixTranspose(&matPerps); *currentMatrix = MatrixMultiply(*currentMatrix, matPerps); } @@ -497,7 +493,6 @@ void rlFrustum(double left, double right, double bottom, double top, double near void rlOrtho(double left, double right, double bottom, double top, double near, double far) { Matrix matOrtho = MatrixOrtho(left, right, bottom, top, near, far); - MatrixTranspose(&matOrtho); *currentMatrix = MatrixMultiply(*currentMatrix, matOrtho); } @@ -2545,7 +2540,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) // Create projection (transposed) and different views for each face Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); + //MatrixTranspose(&fboProjection); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -2617,7 +2612,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) // Create projection (transposed) and different views for each face Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); + //MatrixTranspose(&fboProjection); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -2693,7 +2688,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) // Create projection (transposed) and different views for each face Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); + //MatrixTranspose(&fboProjection); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -2931,7 +2926,6 @@ void ToggleVrMode(void) // Reset viewport and default projection-modelview matrices rlViewport(0, 0, screenWidth, screenHeight); projection = MatrixOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); - MatrixTranspose(&projection); modelview = MatrixIdentity(); } else vrStereoRender = true; @@ -3034,7 +3028,6 @@ void EndVrDrawing(void) // Reset viewport and default projection-modelview matrices rlViewport(0, 0, screenWidth, screenHeight); projection = MatrixOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); - MatrixTranspose(&projection); modelview = MatrixIdentity(); rlDisableDepthTest(); @@ -3977,18 +3970,14 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG // ...but with lens distortion it is increased (see Oculus SDK Documentation) //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? - float fovy = 2.0f*(float)atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; + float fovy = 2.0f*(float)atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance); // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] - Matrix proj = MatrixPerspective(fovy*DEG2RAD, aspect, 0.01, 1000.0); + Matrix proj = MatrixPerspective(fovy, aspect, 0.01, 1000.0); vrConfig.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); vrConfig.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); - // NOTE: Projection matrices must be transposed due to raymath convention - MatrixTranspose(&vrConfig.eyesProjection[0]); - MatrixTranspose(&vrConfig.eyesProjection[1]); - // Compute camera transformation matrices // NOTE: Camera movement might seem more natural if we model the head. // Our axis of rotation is the base of our head, so we might want to add diff --git a/src/rlgl.h b/src/rlgl.h index 84ece706..b9ea0f43 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -355,7 +355,7 @@ void rlLoadIdentity(void); // Reset current matrix to ident void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix void rlRotatef(float angleDeg, float x, float y, float z); // Multiply the current matrix by a rotation matrix void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix -void rlMultMatrixf(float *mat); // Multiply the current matrix by another matrix +void rlMultMatrixf(float *matf); // Multiply the current matrix by another matrix void rlFrustum(double left, double right, double bottom, double top, double near, double far); void rlOrtho(double left, double right, double bottom, double top, double near, double far); void rlViewport(int x, int y, int width, int height); // Set the viewport area -- cgit v1.2.3 From c6cd07c373541f3b112e99f924b2213196625dc7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 17:46:44 +0200 Subject: Some tweaks raymath related --- examples/models/models_skybox.c | 1 - src/models.c | 2 +- src/raymath.h | 12 ++---------- 3 files changed, 3 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 25b01e9c..30ee8e2e 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -10,7 +10,6 @@ ********************************************************************************************/ #include "raylib.h" -#include "raymath.h" int main() { diff --git a/src/models.c b/src/models.c index cfcefc2f..7df9a10b 100644 --- a/src/models.c +++ b/src/models.c @@ -1297,8 +1297,8 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota { // Calculate transformation matrix from function parameters // Get transform matrix (rotation -> scale -> translation) - Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); + Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); diff --git a/src/raymath.h b/src/raymath.h index a4f3f895..270441a5 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raymath v1.0 - Math functions to work with Vector3, Matrix and Quaternions +* raymath v1.1 - Math functions to work with Vector3, Matrix and Quaternions * * CONFIGURATION: * @@ -19,7 +19,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -405,7 +405,6 @@ RMDEF void VectorNormalize(Vector3 *v) } // Transforms a Vector3 by a given Matrix -// TODO: Review math (matrix transpose required?) RMDEF void VectorTransform(Vector3 *v, Matrix mat) { float x = v->x; @@ -415,13 +414,6 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat) v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; - - // TODO: Transposed matrix (?) - /* - v->x = mat.m0*x + mat.m1*y + mat.m2*z + mat.m3; - v->y = mat.m4*x + mat.m5*y + mat.m6*z + mat.m7; - v->z = mat.m8*x + mat.m9*y + mat.m10*z + mat.m11; - */ }; // Calculate linear interpolation between two vectors -- cgit v1.2.3 From 00d2768bc910ca0b6749878f0d142b62d30d55c1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 10:35:41 +0200 Subject: Corrected bug on MatrixPerspective() Some other tweaks... --- src/core.c | 2 +- src/models.c | 4 ++-- src/raymath.h | 2 +- src/rlgl.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 5e7cc811..028d7b14 100644 --- a/src/core.c +++ b/src/core.c @@ -885,7 +885,7 @@ void Begin3dMode(Camera camera) // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.01*tan(camera.fovy*PI/360.0); + double top = 0.01*tan(camera.fovy*0.5*DEG2RAD); double right = top*aspect; // NOTE: zNear and zFar values are important when computing depth buffer values diff --git a/src/models.c b/src/models.c index 7df9a10b..47175b2c 100644 --- a/src/models.c +++ b/src/models.c @@ -120,8 +120,8 @@ void DrawCube(Vector3 position, float width, float height, float length, Color c rlPushMatrix(); // NOTE: Be careful! Function order matters (scale -> rotate -> translate) - rlScalef(1.0f, 3.0f, 1.0f); - rlRotatef(45, 0, 1, 0); + //rlScalef(1.0f, 3.0f, 1.0f); + //rlRotatef(45, 0, 1, 0); rlTranslatef(position.x, position.y, position.z); rlBegin(RL_TRIANGLES); diff --git a/src/raymath.h b/src/raymath.h index 270441a5..93ae90ae 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -882,7 +882,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, // NOTE: Angle should be provided in radians RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far) { - double top = near*tan(fovy); + double top = near*tan(fovy*0.5); double right = top*aspect; return MatrixFrustum(-right, right, -top, top, near, far); diff --git a/src/rlgl.c b/src/rlgl.c index 93612896..ac4ad20d 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -3585,7 +3585,7 @@ static void UpdateBuffersDefault(void) // Draw default internal buffers vertex data // NOTE: We draw in this order: lines, triangles, quads -static void DrawBuffersDefault() +static void DrawBuffersDefault(void) { Matrix matProjection = projection; Matrix matModelView = modelview; @@ -3967,9 +3967,9 @@ static void SetStereoConfig(VrDeviceInfo hmd) SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); #endif - // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG + // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance) // ...but with lens distortion it is increased (see Oculus SDK Documentation) - //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? + //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance); // Really need distortionScale? float fovy = 2.0f*(float)atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance); // Compute camera projection matrices -- cgit v1.2.3 From c756227e11ec3a16b6c3ce09826e5c8162cfd031 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 10:44:24 +0200 Subject: Remove BOM from file encoding --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index ec5e61fd..72a8f763 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,4 +1,4 @@ -/********************************************************************************************** +/********************************************************************************************** * * raylib v1.8.0 * -- cgit v1.2.3 From cbb134946c73c3857d1f3185c25a5398fad3fa5d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 11:02:40 +0200 Subject: Corrected GetMouseRay() and rlUnproject() Now it works great with reviewed maths --- src/core.c | 33 ++------------------------------- src/rlgl.c | 8 ++++---- 2 files changed, 6 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 028d7b14..48c46dfd 100644 --- a/src/core.c +++ b/src/core.c @@ -979,45 +979,16 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); - // Calculate projection matrix (from perspective instead of frustum) + // Calculate projection matrix from perspective Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); // Calculate view matrix from camera look at Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - // Do I need to transpose it? It seems that yes... - // NOTE: matrix order may be incorrect... In OpenGL to get world position from - // camera view it just needs to get inverted, but here we need to transpose it too. - // For example, if you get view matrix, transpose and inverted and you transform it - // to a vector, you will get its 3d world position coordinates (camera.position). - // If you don't transpose, final position will be wrong. - //MatrixTranspose(&matView); - -//#define USE_RLGL_UNPROJECT -#if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlUnproject() - + // Unproject far/near points Vector3 nearPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); -#else // OPTION 2: Compute unprojection directly here - - // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it - Matrix matProjView = MatrixMultiply(matProj, matView); - MatrixInvert(&matProjView); - - // Calculate far and near points - Quaternion qNear = { deviceCoords.x, deviceCoords.y, 0.0f, 1.0f }; - Quaternion qFar = { deviceCoords.x, deviceCoords.y, 1.0f, 1.0f }; - - // Multiply points by unproject matrix - QuaternionTransform(&qNear, matProjView); - QuaternionTransform(&qFar, matProjView); - - // Calculate normalized world points in vectors - Vector3 nearPoint = { qNear.x/qNear.w, qNear.y/qNear.w, qNear.z/qNear.w}; - Vector3 farPoint = { qFar.x/qFar.w, qFar.y/qFar.w, qFar.z/qFar.w}; -#endif - // Calculate normalized direction vector Vector3 direction = VectorSubtract(farPoint, nearPoint); VectorNormalize(&direction); diff --git a/src/rlgl.c b/src/rlgl.c index ac4ad20d..244badc9 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1306,15 +1306,15 @@ Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view) { Vector3 result = { 0.0f, 0.0f, 0.0f }; - // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it - Matrix matProjView = MatrixMultiply(proj, view); - MatrixInvert(&matProjView); + // Calculate unproject matrix (multiply view patrix by projection matrix) and invert it + Matrix matViewProj = MatrixMultiply(view, proj); + MatrixInvert(&matViewProj); // Create quaternion from source point Quaternion quat = { source.x, source.y, source.z, 1.0f }; // Multiply quat point by unproject matrix - QuaternionTransform(&quat, matProjView); + QuaternionTransform(&quat, matViewProj); // Normalized world points in vectors result.x = quat.x/quat.w; -- cgit v1.2.3 From 2227742e9643e46e50b23efd88d7b54cb3431aa3 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 18:10:34 +0200 Subject: Corrected bug on texture rotation --- src/textures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/textures.c b/src/textures.c index 1436111f..23935bf1 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1800,9 +1800,9 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V rlEnableTexture(texture.id); rlPushMatrix(); - rlTranslatef((float)destRec.x, (float)destRec.y, 0); - rlRotatef(rotation, 0, 0, 1); rlTranslatef(-origin.x, -origin.y, 0); + rlRotatef(rotation, 0, 0, 1); + rlTranslatef((float)destRec.x, (float)destRec.y, 0); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, tint.a); -- cgit v1.2.3 From 3655c6e4663d62e93099cdf4871a03a4b0944c6a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 22:13:26 +0200 Subject: Renamed Vector*() functions to Vector3*() For consistency! --- src/raymath.h | 125 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index 93ae90ae..e85367c2 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -136,25 +136,26 @@ RMDEF void Vector2Normalize(Vector2 *v); // Normalize pro //------------------------------------------------------------------------------------ // Functions Declaration to work with Vector3 //------------------------------------------------------------------------------------ -RMDEF Vector3 VectorZero(void); // Vector with components value 0.0f -RMDEF Vector3 VectorOne(void); // Vector with components value 1.0f -RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors -RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors -RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product -RMDEF Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector -RMDEF float VectorLength(const Vector3 v); // Calculate vector length -RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product -RMDEF float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points -RMDEF void VectorScale(Vector3 *v, float scale); // Scale provided vector -RMDEF void VectorNegate(Vector3 *v); // Negate provided vector (invert direction) -RMDEF void VectorNormalize(Vector3 *v); // Normalize provided vector -RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix -RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors -RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal -RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components -RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components -RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc -RMDEF float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array +RMDEF Vector3 Vector3Zero(void); // Vector with components value 0.0f +RMDEF Vector3 Vector3One(void); // Vector with components value 1.0f +RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2); // Add two vectors +RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar); // Multiply vector by scalar +RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2); // Substract two vectors +RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product +RMDEF Vector3 Vector3Perpendicular(Vector3 v); // Calculate one vector perpendicular vector +RMDEF float Vector3Length(const Vector3 v); // Calculate vector length +RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product +RMDEF float Vector3Distance(Vector3 v1, Vector3 v2); // Calculate distance between two points +RMDEF void Vector3Scale(Vector3 *v, float scale); // Scale provided vector +RMDEF void Vector3Negate(Vector3 *v); // Negate provided vector (invert direction) +RMDEF void Vector3Normalize(Vector3 *v); // Normalize provided vector +RMDEF void Vector3Transform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix +RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors +RMDEF Vector3 Vector3Reflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal +RMDEF Vector3 Vector3Min(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components +RMDEF Vector3 Vector3Max(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components +RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc +RMDEF float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -297,25 +298,35 @@ RMDEF void Vector2Normalize(Vector2 *v) //---------------------------------------------------------------------------------- // Vector with components value 0.0f -RMDEF Vector3 VectorZero(void) { return (Vector3){ 0.0f, 0.0f, 0.0f }; } +RMDEF Vector3 Vector3Zero(void) { return (Vector3){ 0.0f, 0.0f, 0.0f }; } // Vector with components value 1.0f -RMDEF Vector3 VectorOne(void) { return (Vector3){ 1.0f, 1.0f, 1.0f }; } +RMDEF Vector3 Vector3One(void) { return (Vector3){ 1.0f, 1.0f, 1.0f }; } // Add two vectors -RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2) +RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2) { return (Vector3){ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; } // Substract two vectors -RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2) +RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) { return (Vector3){ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; } +// Multiply vector by scalar +RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar) +{ + v.x *= scalar; + v.y *= scalar; + v.z *= scalar; + + return v; +} + // Calculate two vectors cross product -RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2) +RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2) { Vector3 result; @@ -327,7 +338,7 @@ RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2) } // Calculate one vector perpendicular vector -RMDEF Vector3 VectorPerpendicular(Vector3 v) +RMDEF Vector3 Vector3Perpendicular(Vector3 v) { Vector3 result; @@ -345,25 +356,25 @@ RMDEF Vector3 VectorPerpendicular(Vector3 v) cardinalAxis = (Vector3){0.0f, 0.0f, 1.0f}; } - result = VectorCrossProduct(v, cardinalAxis); + result = Vector3CrossProduct(v, cardinalAxis); return result; } // Calculate vector length -RMDEF float VectorLength(const Vector3 v) +RMDEF float Vector3Length(const Vector3 v) { return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); } // Calculate two vectors dot product -RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2) +RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2) { return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); } // Calculate distance between two vectors -RMDEF float VectorDistance(Vector3 v1, Vector3 v2) +RMDEF float Vector3Distance(Vector3 v1, Vector3 v2) { float dx = v2.x - v1.x; float dy = v2.y - v1.y; @@ -373,7 +384,7 @@ RMDEF float VectorDistance(Vector3 v1, Vector3 v2) } // Scale provided vector -RMDEF void VectorScale(Vector3 *v, float scale) +RMDEF void Vector3Scale(Vector3 *v, float scale) { v->x *= scale; v->y *= scale; @@ -381,7 +392,7 @@ RMDEF void VectorScale(Vector3 *v, float scale) } // Negate provided vector (invert direction) -RMDEF void VectorNegate(Vector3 *v) +RMDEF void Vector3Negate(Vector3 *v) { v->x = -v->x; v->y = -v->y; @@ -389,11 +400,11 @@ RMDEF void VectorNegate(Vector3 *v) } // Normalize provided vector -RMDEF void VectorNormalize(Vector3 *v) +RMDEF void Vector3Normalize(Vector3 *v) { float length, ilength; - length = VectorLength(*v); + length = Vector3Length(*v); if (length == 0.0f) length = 1.0f; @@ -405,7 +416,7 @@ RMDEF void VectorNormalize(Vector3 *v) } // Transforms a Vector3 by a given Matrix -RMDEF void VectorTransform(Vector3 *v, Matrix mat) +RMDEF void Vector3Transform(Vector3 *v, Matrix mat) { float x = v->x; float y = v->y; @@ -417,7 +428,7 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat) }; // Calculate linear interpolation between two vectors -RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount) +RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) { Vector3 result; @@ -429,7 +440,7 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount) } // Calculate reflected vector to normal -RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal) +RMDEF Vector3 Vector3Reflect(Vector3 vector, Vector3 normal) { // I is the original vector // N is the normal of the incident plane @@ -437,7 +448,7 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal) Vector3 result; - float dotProduct = VectorDotProduct(vector, normal); + float dotProduct = Vector3DotProduct(vector, normal); result.x = vector.x - (2.0f*normal.x)*dotProduct; result.y = vector.y - (2.0f*normal.y)*dotProduct; @@ -447,7 +458,7 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal) } // Return min value for each pair of components -RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2) +RMDEF Vector3 Vector3Min(Vector3 vec1, Vector3 vec2) { Vector3 result; @@ -459,7 +470,7 @@ RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2) } // Return max value for each pair of components -RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) +RMDEF Vector3 Vector3Max(Vector3 vec1, Vector3 vec2) { Vector3 result; @@ -472,18 +483,18 @@ RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) // Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c) // NOTE: Assumes P is on the plane of the triangle -RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) +RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) { //Vector v0 = b - a, v1 = c - a, v2 = p - a; - Vector3 v0 = VectorSubtract(b, a); - Vector3 v1 = VectorSubtract(c, a); - Vector3 v2 = VectorSubtract(p, a); - float d00 = VectorDotProduct(v0, v0); - float d01 = VectorDotProduct(v0, v1); - float d11 = VectorDotProduct(v1, v1); - float d20 = VectorDotProduct(v2, v0); - float d21 = VectorDotProduct(v2, v1); + Vector3 v0 = Vector3Subtract(b, a); + Vector3 v1 = Vector3Subtract(c, a); + Vector3 v2 = Vector3Subtract(p, a); + float d00 = Vector3DotProduct(v0, v0); + float d01 = Vector3DotProduct(v0, v1); + float d11 = Vector3DotProduct(v1, v1); + float d20 = Vector3DotProduct(v2, v0); + float d21 = Vector3DotProduct(v2, v1); float denom = d00*d11 - d01*d01; @@ -497,7 +508,7 @@ RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) } // Returns Vector3 as float array -RMDEF float *VectorToFloat(Vector3 vec) +RMDEF float *Vector3ToFloat(Vector3 vec) { static float buffer[3]; @@ -922,12 +933,12 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) { Matrix result; - Vector3 z = VectorSubtract(eye, target); - VectorNormalize(&z); - Vector3 x = VectorCrossProduct(up, z); - VectorNormalize(&x); - Vector3 y = VectorCrossProduct(z, x); - VectorNormalize(&y); + Vector3 z = Vector3Subtract(eye, target); + Vector3Normalize(&z); + Vector3 x = Vector3CrossProduct(up, z); + Vector3Normalize(&x); + Vector3 y = Vector3CrossProduct(z, x); + Vector3Normalize(&y); result.m0 = x.x; result.m1 = x.y; @@ -1176,11 +1187,11 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; - if (VectorLength(axis) != 0.0f) + if (Vector3Length(axis) != 0.0f) angle *= 0.5f; - VectorNormalize(&axis); + Vector3Normalize(&axis); float sinres = sinf(angle); float cosres = cosf(angle); -- cgit v1.2.3 From a766e2c4808a554f5b6cfd07e6c4dceef711c9f8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 22:15:50 +0200 Subject: Updated Vector math to new naming --- src/core.c | 4 +-- src/models.c | 80 ++++++++++++++++++++++++++++++------------------------------ src/raylib.h | 4 +-- src/rlgl.c | 6 ++--- 4 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 48c46dfd..4a95c660 100644 --- a/src/core.c +++ b/src/core.c @@ -990,8 +990,8 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); // Calculate normalized direction vector - Vector3 direction = VectorSubtract(farPoint, nearPoint); - VectorNormalize(&direction); + Vector3 direction = Vector3Subtract(farPoint, nearPoint); + Vector3Normalize(&direction); // Apply calculated vectors to ray ray.position = camera.position; diff --git a/src/models.c b/src/models.c index 47175b2c..4ab27926 100644 --- a/src/models.c +++ b/src/models.c @@ -1360,16 +1360,16 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec | | d-------c */ - VectorScale(&right, sizeRatio.x/2); - VectorScale(&up, sizeRatio.y/2); + Vector3Scale(&right, sizeRatio.x/2); + Vector3Scale(&up, sizeRatio.y/2); - Vector3 p1 = VectorAdd(right, up); - Vector3 p2 = VectorSubtract(right, up); + Vector3 p1 = Vector3Add(right, up); + Vector3 p2 = Vector3Subtract(right, up); - Vector3 a = VectorSubtract(center, p2); - Vector3 b = VectorAdd(center, p1); - Vector3 c = VectorAdd(center, p2); - Vector3 d = VectorSubtract(center, p1); + Vector3 a = Vector3Subtract(center, p2); + Vector3 b = Vector3Add(center, p1); + Vector3 c = Vector3Add(center, p2); + Vector3 d = Vector3Subtract(center, p1); rlEnableTexture(texture.id); @@ -1468,9 +1468,9 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius { bool collision = false; - Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); - float distance = VectorLength(raySpherePos); - float vector = VectorDotProduct(raySpherePos, ray.direction); + Vector3 raySpherePos = Vector3Subtract(spherePosition, ray.position); + float distance = Vector3Length(raySpherePos); + float vector = Vector3DotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); if (d >= 0.0f) collision = true; @@ -1483,9 +1483,9 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi { bool collision = false; - Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); - float distance = VectorLength(raySpherePos); - float vector = VectorDotProduct(raySpherePos, ray.direction); + Vector3 raySpherePos = Vector3Subtract(spherePosition, ray.position); + float distance = Vector3Length(raySpherePos); + float vector = Vector3DotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); if (d >= 0.0f) collision = true; @@ -1498,8 +1498,8 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi if (distance < sphereRadius) collisionDistance = vector + sqrtf(d); else collisionDistance = vector - sqrtf(d); - VectorScale(&offset, collisionDistance); - Vector3 cPoint = VectorAdd(ray.position, offset); + Vector3Scale(&offset, collisionDistance); + Vector3 cPoint = Vector3Add(ray.position, offset); collisionPoint->x = cPoint.x; collisionPoint->y = cPoint.y; @@ -1582,14 +1582,14 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) RayHitInfo result = {0}; // Find vectors for two edges sharing V1 - edge1 = VectorSubtract(p2, p1); - edge2 = VectorSubtract(p3, p1); + edge1 = Vector3Subtract(p2, p1); + edge2 = Vector3Subtract(p3, p1); // Begin calculating determinant - also used to calculate u parameter - p = VectorCrossProduct(ray.direction, edge2); + p = Vector3CrossProduct(ray.direction, edge2); // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle - det = VectorDotProduct(edge1, p); + det = Vector3DotProduct(edge1, p); // Avoid culling! if ((det > -EPSILON) && (det < EPSILON)) return result; @@ -1597,24 +1597,24 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) invDet = 1.0f/det; // Calculate distance from V1 to ray origin - tv = VectorSubtract(ray.position, p1); + tv = Vector3Subtract(ray.position, p1); // Calculate u parameter and test bound - u = VectorDotProduct(tv, p)*invDet; + u = Vector3DotProduct(tv, p)*invDet; // The intersection lies outside of the triangle if ((u < 0.0f) || (u > 1.0f)) return result; // Prepare to test v parameter - q = VectorCrossProduct(tv, edge1); + q = Vector3CrossProduct(tv, edge1); // Calculate V parameter and test bound - v = VectorDotProduct(ray.direction, q)*invDet; + v = Vector3DotProduct(ray.direction, q)*invDet; // The intersection lies outside of the triangle if ((v < 0.0f) || ((u + v) > 1.0f)) return result; - t = VectorDotProduct(edge2, q)*invDet; + t = Vector3DotProduct(edge2, q)*invDet; if (t > EPSILON) { @@ -1622,11 +1622,11 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) result.hit = true; result.distance = t; result.hit = true; - result.normal = VectorCrossProduct(edge1, edge2); - VectorNormalize(&result.normal); + result.normal = Vector3CrossProduct(edge1, edge2); + Vector3Normalize(&result.normal); Vector3 rayDir = ray.direction; - VectorScale(&rayDir, t); - result.position = VectorAdd(ray.position, rayDir); + Vector3Scale(&rayDir, t); + result.position = Vector3Add(ray.position, rayDir); } return result; @@ -1646,11 +1646,11 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) if (t >= 0.0) { Vector3 rayDir = ray.direction; - VectorScale(&rayDir, t); + Vector3Scale(&rayDir, t); result.hit = true; result.distance = t; result.normal = (Vector3){ 0.0, 1.0, 0.0 }; - result.position = VectorAdd(ray.position, rayDir); + result.position = Vector3Add(ray.position, rayDir); } } @@ -1672,8 +1672,8 @@ BoundingBox CalculateBoundingBox(Mesh mesh) for (int i = 1; i < mesh.vertexCount; i++) { - minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); - maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + minVertex = Vector3Min(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + maxVertex = Vector3Max(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); } } @@ -1888,8 +1888,8 @@ static Mesh LoadOBJ(const char *fileName) else { // If normals not defined, they are calculated from the 3 vertices [N = (V2 - V1) x (V3 - V1)] - Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vCount[1]-1], midVertices[vCount[0]-1]), VectorSubtract(midVertices[vCount[2]-1], midVertices[vCount[0]-1])); - VectorNormalize(&norm); + Vector3 norm = Vector3CrossProduct(Vector3Subtract(midVertices[vCount[1]-1], midVertices[vCount[0]-1]), Vector3Subtract(midVertices[vCount[2]-1], midVertices[vCount[0]-1])); + Vector3Normalize(&norm); mesh.normals[nCounter] = norm.x; mesh.normals[nCounter + 1] = norm.y; @@ -1949,8 +1949,8 @@ static Mesh LoadOBJ(const char *fileName) Vector2 uv2 = { mesh.texcoords[uvCount + 4], mesh.texcoords[uvCount + 5] }; // Calculate edges of the triangle (position delta) - Vector3 deltaPos1 = VectorSubtract(v1, v0); - Vector3 deltaPos2 = VectorSubtract(v2, v0); + Vector3 deltaPos1 = Vector3Subtract(v1, v0); + Vector3 deltaPos2 = Vector3Subtract(v2, v0); // UV delta Vector2 deltaUV1 = { uv1.x - uv0.x, uv1.y - uv0.y }; @@ -1963,8 +1963,8 @@ static Mesh LoadOBJ(const char *fileName) // Vector3 b2 = { deltaPos1.x*deltaUV2.x, deltaPos1.y*deltaUV2.x, deltaPos1.z*deltaUV2.x }; // Calculate vertex tangent - Vector3 tangent = VectorSubtract(t1, t2); - VectorScale(&tangent, r); + Vector3 tangent = Vector3Subtract(t1, t2); + Vector3Scale(&tangent, r); // Apply calculated tangents data to mesh struct mesh.tangents[vCount + 0] = tangent.x; @@ -1980,7 +1980,7 @@ static Mesh LoadOBJ(const char *fileName) // TODO: add binormals to mesh struct and assign buffers id and locations properly /* // Calculate vertex binormal Vector3 binormal = VectorSubtract(b1, b2); - VectorScale(&binormal, r); + Vector3Scale(&binormal, r); // Apply calculated binormals data to mesh struct mesh.binormals[vCount + 0] = binormal.x; diff --git a/src/raylib.h b/src/raylib.h index 72a8f763..bad711d9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -746,8 +746,8 @@ RLAPI float *ColorToFloat(Color color); // Converts Co // Math useful functions (available from raymath.h) RLAPI float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array -RLAPI Vector3 VectorZero(void); // Vector with components value 0.0f -RLAPI Vector3 VectorOne(void); // Vector with components value 1.0f +RLAPI Vector3 Vector3Zero(void); // Vector with components value 0.0f +RLAPI Vector3 Vector3One(void); // Vector with components value 1.0f RLAPI Matrix MatrixIdentity(void); // Returns identity matrix // Misc. functions diff --git a/src/rlgl.c b/src/rlgl.c index 244badc9..e681ad50 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -455,7 +455,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) Matrix matRotation = MatrixIdentity(); Vector3 axis = (Vector3){ x, y, z }; - VectorNormalize(&axis); + Vector3Normalize(&axis); matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); *currentMatrix = MatrixMultiply(*currentMatrix, matRotation); @@ -553,7 +553,7 @@ void rlEnd(void) // This way, rlTranslatef(), rlRotatef()... behaviour is the same than OpenGL 1.1 // Apply transformation matrix to all temp vertices - for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], *currentMatrix); + for (int i = 0; i < tempBufferCount; i++) Vector3Transform(&tempBuffer[i], *currentMatrix); // Deactivate tempBuffer usage to allow rlVertex3f do its job useTempBuffer = false; @@ -1178,7 +1178,7 @@ void rlglInit(int width, int height) // Init temp vertex buffer, used when transformation required (translate, rotate, scale) tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); - for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = VectorZero(); + for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = Vector3Zero(); // Init draw calls tracking system draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE); -- cgit v1.2.3 From f57367e786089e9bb53f0b245f15e989822fcdb1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 23 Jul 2017 13:20:35 +0200 Subject: Implemented some changes --- src/raymath.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index e85367c2..855f97b0 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -184,11 +184,15 @@ RMDEF float *MatrixToFloat(Matrix mat); // Returns float //------------------------------------------------------------------------------------ // Functions Declaration to work with Quaternions //------------------------------------------------------------------------------------ +RMDEF Quaternion QuaternionIdentity(void); // Returns identity quaternion RMDEF float QuaternionLength(Quaternion quat); // Compute the length of a quaternion RMDEF void QuaternionNormalize(Quaternion *q); // Normalize provided quaternion RMDEF void QuaternionInvert(Quaternion *quat); // Invert provided quaternion RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calculate two quaternion multiplication -RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions +RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount); // Calculate linear interpolation between two quaternions +RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount); // Calculates spherical linear interpolation between two quaternions +RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount); // Calculate slerp-optimized interpolation between two quaternions +RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to); // Calculate quaternion based on the rotation from one vector to another RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle and axis @@ -991,6 +995,12 @@ RMDEF float *MatrixToFloat(Matrix mat) // Module Functions Definition - Quaternion math //---------------------------------------------------------------------------------- +// Returns identity quaternion +RMDEF Quaternion QuaternionIdentity(void) +{ + return (Quaternion){ 0.0f, 0.0f, 0.0f, 1.0f }; +} + // Computes the length of a quaternion RMDEF float QuaternionLength(Quaternion quat) { @@ -1047,6 +1057,19 @@ RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) return result; } +// Calculate linear interpolation between two quaternions +RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) +{ + Quaternion result; + + result.x = q1.x + amount*(q2.x - q1.x); + result.y = q1.y + amount*(q2.y - q1.y); + result.z = q1.z + amount*(q2.z - q1.z); + result.w = q1.w + amount*(q2.w - q1.w); + + return result; +} + // Calculates spherical linear interpolation between two quaternions RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) { @@ -1055,6 +1078,7 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; if (fabs(cosHalfTheta) >= 1.0f) result = q1; + else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount); else { float halfTheta = acos(cosHalfTheta); @@ -1082,6 +1106,35 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) return result; } +// Calculate slerp-optimized interpolation between two quaternions +RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) +{ + Quaternion result = QuaternionLerp(q1, q2, amount); + QuaternionNormalize(&result); + + return result; +} + +// Calculate quaternion based on the rotation from one vector to another +RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) +{ + Quaternion q = { 0 }; + + float cos2Theta = Vector3DotProduct(from, to); + Vector3 cross = Vector3CrossProduct(from, to); + + q.x = cross.x; + q.y = cross.y; + q.z = cross.y; + q.w = 1.0f + cos2Theta; + + QuaternionNormalize(&q); + + Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f); + + return result; +} + // Returns a quaternion for a given rotation matrix RMDEF Quaternion QuaternionFromMatrix(Matrix matrix) { @@ -1148,18 +1201,21 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) float x2 = x + x; float y2 = y + y; float z2 = z + z; + + float length = QuaternionLength(q); + float lenghtSquared = length*length; - float xx = x*x2; - float xy = x*y2; - float xz = x*z2; + float xx = x*x2/lenghtSquared; + float xy = x*y2/lenghtSquared; + float xz = x*z2/lenghtSquared; - float yy = y*y2; - float yz = y*z2; - float zz = z*z2; + float yy = y*y2/lenghtSquared; + float yz = y*z2/lenghtSquared; + float zz = z*z2/lenghtSquared; - float wx = w*x2; - float wy = w*y2; - float wz = w*z2; + float wx = w*x2/lenghtSquared; + float wy = w*y2/lenghtSquared; + float wz = w*z2/lenghtSquared; result.m0 = 1.0f - (yy + zz); result.m1 = xy - wz; @@ -1255,7 +1311,7 @@ RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw) } // Return the Euler angles equivalent to quaternion (roll, pitch, yaw) -// NOTE: Angles are returned in a Vector3 struct and in degrees +// NOTE: Angles are returned in a Vector3 struct in degrees RMDEF Vector3 QuaternionToEuler(Quaternion q) { Vector3 v = { 0 }; -- cgit v1.2.3 From b2712b6db7c184aff47436f387f2012cf77f4f67 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 23 Jul 2017 17:29:51 +0200 Subject: Corrected issue on QuaternionFromVector3ToVector3() --- src/raymath.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index 855f97b0..cd45c0b5 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1126,13 +1126,15 @@ RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) q.x = cross.x; q.y = cross.y; q.z = cross.y; - q.w = 1.0f + cos2Theta; - - QuaternionNormalize(&q); + q.w = 1.0f + cos2Theta; // NOTE: Added QuaternioIdentity() + + // Normalize to essentially nlerp the original and identity to 0.5 + QuaternionNormalize(&q); - Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f); + // Above lines are equivalent to: + //Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f); - return result; + return q; } // Returns a quaternion for a given rotation matrix -- cgit v1.2.3 From c764b3d03eb85ea303192a48f36797ca0cd77067 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 25 Jul 2017 18:09:58 +0200 Subject: Some tweaks --- examples/models/models_cubicmap.c | 2 +- examples/models/models_material_pbr.c | 2 +- src/models.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 268d480a..a8faa7c0 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -31,7 +31,7 @@ int main() // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture + model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index d55aa773..1f069468 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -71,7 +71,7 @@ int main() Begin3dMode(camera); - DrawModel(model, VectorZero(), 1.0f, WHITE); + DrawModel(model, Vector3Zero(), 1.0f, WHITE); DrawGrid(10, 1.0f); diff --git a/src/models.c b/src/models.c index 4ab27926..accab7e8 100644 --- a/src/models.c +++ b/src/models.c @@ -1979,7 +1979,7 @@ static Mesh LoadOBJ(const char *fileName) // TODO: add binormals to mesh struct and assign buffers id and locations properly /* // Calculate vertex binormal - Vector3 binormal = VectorSubtract(b1, b2); + Vector3 binormal = Vector3Subtract(b1, b2); Vector3Scale(&binormal, r); // Apply calculated binormals data to mesh struct -- cgit v1.2.3 From 2a263f7b5f6110dbcbfe8c5cc1be23d17fe534b6 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 28 Jul 2017 19:59:04 +0200 Subject: Corrected compilation on OpenGL ES 2.0 --- src/rlgl.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index e681ad50..dc8a37ac 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2506,16 +2506,20 @@ void SetMatrixModelview(Matrix view) } // Generate cubemap texture from HDR texture +// TODO: OpenGL ES 2.0 does not support GL_RGB16F texture format, neither GL_DEPTH_COMPONENT24 Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader // Other locations should be setup externally in shader before calling the function // Set up depth face culling and cubemap seamless glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#if defined(GRAPHICS_API_OPENGL_33) + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Flag not supported on OpenGL ES 2.0 +#endif + // Setup framebuffer unsigned int fbo, rbo; @@ -2534,7 +2538,9 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); +#if defined(GRAPHICS_API_OPENGL_33) + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); // Flag not supported on OpenGL ES 2.0 +#endif glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -2582,11 +2588,12 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) } // Generate irradiance texture using cubemap data +// TODO: OpenGL ES 2.0 does not support GL_RGB16F texture format, neither GL_DEPTH_COMPONENT24 Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader // Other locations should be setup externally in shader before calling the function @@ -2653,11 +2660,12 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) } // Generate prefilter texture using cubemap data +// TODO: OpenGL ES 2.0 does not support GL_RGB16F texture format, neither GL_DEPTH_COMPONENT24 Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader // Other locations should be setup externally in shader before calling the function // TODO: Locations should be taken out of this function... too shader dependant... @@ -2743,10 +2751,11 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) } // Generate BRDF texture using cubemap data +// TODO: OpenGL ES 2.0 does not support GL_RGB16F texture format, neither GL_DEPTH_COMPONENT24 Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) { Texture2D brdf = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // Generate BRDF convolution texture glGenTextures(1, &brdf.id); glBindTexture(GL_TEXTURE_2D, brdf.id); -- cgit v1.2.3 From d071418cba7491ce6302ba14ed84acb8cc5f2063 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 28 Jul 2017 20:58:38 +0200 Subject: Added Vector3MultiplyV() To multiply Vector3 by Vector3 --- src/raymath.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index cd45c0b5..a06a4f9e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -140,6 +140,7 @@ RMDEF Vector3 Vector3Zero(void); // Vector with RMDEF Vector3 Vector3One(void); // Vector with components value 1.0f RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2); // Add two vectors RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar); // Multiply vector by scalar +RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2); // Multiply vector by vector RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2); // Substract two vectors RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product RMDEF Vector3 Vector3Perpendicular(Vector3 v); // Calculate one vector perpendicular vector @@ -329,6 +330,18 @@ RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar) return v; } +// Multiply vector by vector +RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2) +{ + Vector3 result; + + result.x = v1.x * v2.x; + result.y = v1.y * v2.y; + result.z = v1.z * v2.z; + + return result; +} + // Calculate two vectors cross product RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2) { -- cgit v1.2.3 From 71d9426565e37b9182be03fdd3706ce1e963bf7d Mon Sep 17 00:00:00 2001 From: Benjamin Summerton Date: Sun, 30 Jul 2017 23:56:58 -0400 Subject: Make physac work on OS X Physac wasn't working on OS X. It looks like the necessary timing code wasn't being compiled in by the preprocessor. fixes #340 --- src/physac.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/physac.h b/src/physac.h index 8c109935..5ecd2815 100644 --- a/src/physac.h +++ b/src/physac.h @@ -252,7 +252,7 @@ PHYSACDEF void ClosePhysics(void); // Functions required to query time on Windows int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); -#elif defined(__linux__) || defined(PLATFORM_WEB) +#elif defined(__linux__) || defined(__APPLE__) || defined(PLATFORM_WEB) #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. //#define _DEFAULT_SOURCE // Enables BSD function definitions and C99 POSIX compliance #include // Required for: timespec @@ -282,7 +282,7 @@ static pthread_t physicsThreadId; // Physics thread id static unsigned int usedMemory = 0; // Total allocated dynamic memory static bool physicsThreadEnabled = false; // Physics thread enabled state static double currentTime = 0; // Current time in milliseconds -#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(__linux__) || defined(PLATFORM_WEB) +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(__linux__) || defined(__APPLE__) || defined(PLATFORM_WEB) static double baseTime = 0; // Android and RPI platforms base time #endif static double startTime = 0; // Start time in milliseconds @@ -1907,7 +1907,7 @@ static double GetCurrentTime(void) time = (double)((double)currentTime/clockFrequency)*1000; #endif - #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(__linux__) || defined(PLATFORM_WEB) + #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(__linux__) || defined(__APPLE__) || defined(PLATFORM_WEB) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); uint64_t temp = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec; -- cgit v1.2.3 From 2ec888019779d2e2638eed005383c8b7548ff005 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 4 Aug 2017 12:58:39 +0200 Subject: Updated stb libs to latest version --- src/external/stb_image.h | 184 +++++++------- src/external/stb_image_resize.h | 13 +- src/external/stb_image_write.h | 378 +++++++++++++++++++++++++++- src/external/stb_rect_pack.h | 11 - src/external/stb_truetype.h | 529 +++++++++++++++++++++++++++++++++++++++- src/external/stb_vorbis.c | 1 + src/external/stb_vorbis.h | 5 +- 7 files changed, 998 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/external/stb_image.h b/src/external/stb_image.h index ae2ada6a..a056138d 100644 --- a/src/external/stb_image.h +++ b/src/external/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.15 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.16 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes @@ -58,10 +59,6 @@ RECENT REVISION HISTORY: correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) partial animated GIF support - limited 16-bit PSD support - minor bugs, code cleanup, and compiler warnings See end of file for full revision history. @@ -83,6 +80,7 @@ RECENT REVISION HISTORY: Optimizations & bugfixes Fabian "ryg" Giesen Arseny Kapoulkine + John-Mark Allen Bug & warning fixes Marc LeBlanc David Woo Guillaume George Martins Mozeiko @@ -98,7 +96,7 @@ RECENT REVISION HISTORY: Michaelangel007@github Philipp Wiesemann Dale Weiler github:grim210 Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:sammyhw Blazej Dariusz Roszkowski Gregory Mullen github:phprus - + Christian Floisand Kevin Schmidt github:poppolopoppo */ #ifndef STBI_INCLUDE_STB_IMAGE_H @@ -134,11 +132,12 @@ RECENT REVISION HISTORY: // with each pixel consisting of N interleaved 8-bit components; the first // pixel pointed to is top-left-most in the image. There is no padding between // image scanlines or between pixels, regardless of format. The number of -// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. -// If req_comp is non-zero, *comp has the number of components that _would_ -// have been output otherwise. E.g. if you set req_comp to 4, you will always -// get RGBA output, but you can check *comp to see if it's trivially opaque -// because e.g. there were only 3 channels in the source image. +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. // // An output image with N components has the following components interleaved // in this order in each pixel: @@ -150,10 +149,10 @@ RECENT REVISION HISTORY: // 4 red, green, blue, alpha // // If image loading fails for any reason, the return value will be NULL, -// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() -// can be queried for an extremely brief, end-user unfriendly explanation -// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid -// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly // more user-friendly ones. // // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. @@ -310,7 +309,7 @@ RECENT REVISION HISTORY: enum { - STBI_default = 0, // only used for req_comp + STBI_default = 0, // only used for desired_channels STBI_grey = 1, STBI_grey_alpha = 2, @@ -352,12 +351,12 @@ typedef struct // 8-bits-per-channel interface // -STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); // for stbi_load_from_file, file pointer is left pointing immediately after image #endif @@ -366,22 +365,24 @@ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_i // 16-bits-per-channel interface // -STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + #ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif -// @TODO the other variants //////////////////////////////////// // // float-per-channel interface // #ifndef STBI_NO_LINEAR - STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif #endif @@ -639,7 +640,7 @@ static int stbi__cpuid3(void) #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name -static int stbi__sse2_available() +static int stbi__sse2_available(void) { int info3 = stbi__cpuid3(); return ((info3 >> 26) & 1) != 0; @@ -647,7 +648,7 @@ static int stbi__sse2_available() #else // assume GCC-style if not VC++ #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) -static int stbi__sse2_available() +static int stbi__sse2_available(void) { // If we're even attempting to compile this on GCC/Clang, that means // -msse2 is on, which means the compiler is allowed to use SSE2 @@ -1029,6 +1030,30 @@ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int chan return enlarged; } +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; @@ -1046,21 +1071,8 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, // @TODO: move stbi__convert_format to here if (stbi__vertically_flip_on_load) { - int w = *x, h = *y; int channels = req_comp ? req_comp : *comp; - int row,col,z; - stbi_uc *image = (stbi_uc *) result; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < channels; z++) { - stbi_uc temp = image[(row * w + col) * channels + z]; - image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z]; - image[((h - row - 1) * w + col) * channels + z] = temp; - } - } - } + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); } return (unsigned char *) result; @@ -1084,21 +1096,8 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision if (stbi__vertically_flip_on_load) { - int w = *x, h = *y; int channels = req_comp ? req_comp : *comp; - int row,col,z; - stbi__uint16 *image = (stbi__uint16 *) result; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < channels; z++) { - stbi__uint16 temp = image[(row * w + col) * channels + z]; - image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z]; - image[((h - row - 1) * w + col) * channels + z] = temp; - } - } - } + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); } return (stbi__uint16 *) result; @@ -1108,21 +1107,8 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { - int w = *x, h = *y; - int depth = req_comp ? req_comp : *comp; - int row,col,z; - float temp; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < depth; z++) { - temp = result[(row * w + col) * depth + z]; - result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; - result[((h - row - 1) * w + col) * depth + z] = temp; - } - } - } + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); } } #endif @@ -1191,6 +1177,20 @@ STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, i #endif //!STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; @@ -2806,7 +2806,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m) if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = sixteen ? stbi__get16be(z->s) : stbi__get8(z->s); + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); L -= (sixteen ? 129 : 65); } return L==0; @@ -3611,20 +3611,20 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } else if (z->s->img_n == 4) { if (z->app14_color_transform == 0) { // CMYK for (i=0; i < z->s->img_x; ++i) { - stbi_uc k = coutput[3][i]; - out[0] = stbi__blinn_8x8(coutput[0][i], k); - out[1] = stbi__blinn_8x8(coutput[1][i], k); - out[2] = stbi__blinn_8x8(coutput[2][i], k); + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); out[3] = 255; out += n; } } else if (z->app14_color_transform == 2) { // YCCK z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); for (i=0; i < z->s->img_x; ++i) { - stbi_uc k = coutput[3][i]; - out[0] = stbi__blinn_8x8(255 - out[0], k); - out[1] = stbi__blinn_8x8(255 - out[1], k); - out[2] = stbi__blinn_8x8(255 - out[2], k); + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); out += n; } } else { // YCbCr + alpha? Ignore the fourth channel for now @@ -3649,10 +3649,10 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { for (i=0; i < z->s->img_x; ++i) { - stbi_uc k = coutput[3][i]; - stbi_uc r = stbi__blinn_8x8(coutput[0][i], k); - stbi_uc g = stbi__blinn_8x8(coutput[1][i], k); - stbi_uc b = stbi__blinn_8x8(coutput[2][i], k); + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); out[0] = stbi__compute_y(r, g, b); out[1] = 255; out += n; @@ -4297,11 +4297,10 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_len = (img_width_bytes + 1) * y; - if (s->img_x == x && s->img_y == y) { - if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); - } else { // interlaced: - if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); - } + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; @@ -4654,9 +4653,10 @@ static void stbi__de_iphone(stbi__png *z) stbi_uc a = p[3]; stbi_uc t = p[0]; if (a) { - p[0] = p[2] * 255 / a; - p[1] = p[1] * 255 / a; - p[2] = t * 255 / a; + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; } else { p[0] = p[2]; p[2] = t; @@ -4819,6 +4819,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (req_comp >= 3) s->img_out_n = req_comp; if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; } STBI_FREE(z->expanded); z->expanded = NULL; return 1; @@ -6966,6 +6969,13 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; warning fixes; disable run-time SSE detection on gcc; uniform handling of optional "return" values; diff --git a/src/external/stb_image_resize.h b/src/external/stb_image_resize.h index b507e049..031ca99d 100644 --- a/src/external/stb_image_resize.h +++ b/src/external/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.94 - public domain image resizing +/* stb_image_resize - v0.95 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -156,8 +156,10 @@ Jorge L Rodriguez: Implementation Sean Barrett: API design, optimizations Aras Pranckevicius: bugfix - + Nathan Reed: warning fixes + REVISIONS + 0.95 (2017-07-23) fixed warnings 0.94 (2017-03-18) fixed warnings 0.93 (2017-03-03) fixed bug with certain combinations of heights 0.92 (2017-01-02) fix integer overflow on large (>2GB) images @@ -393,8 +395,9 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int #ifndef STBIR_MALLOC #include -#define STBIR_MALLOC(size,c) malloc(size) -#define STBIR_FREE(ptr,c) free(ptr) +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) #endif #ifndef _MSC_VER @@ -983,7 +986,7 @@ static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) return (m); } - return n; // NOTREACHED + // NOTREACHED default: STBIR_ASSERT(!"Unimplemented edge type"); diff --git a/src/external/stb_image_write.h b/src/external/stb_image_write.h index df623393..9d553e0d 100644 --- a/src/external/stb_image_write.h +++ b/src/external/stb_image_write.h @@ -1,5 +1,5 @@ -/* stb_image_write - v1.05 - public domain - http://nothings.org/stb/stb_image_write.h - writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 +/* stb_image_write - v1.07 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk Before #including, @@ -35,6 +35,7 @@ USAGE: int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data); There are also four equivalent functions that use an arbitrary write function. You are expected to open/close your file-equivalent before and after calling these: @@ -43,6 +44,7 @@ USAGE: int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); where the callback is: void stbi_write_func(void *context, void *data, int size); @@ -79,6 +81,10 @@ USAGE: TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). CREDITS: @@ -94,6 +100,9 @@ CREDITS: Alan Hickman initial file IO callback implementation Emmanuel Julien + JPEG + Jon Olick (original jo_jpeg.cpp code) + Daniel Gibson bugfixes: github:Chribba Guillaume Chereau @@ -131,6 +140,7 @@ STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); #endif typedef void stbi_write_func(void *context, void *data, int size); @@ -139,6 +149,7 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); #ifdef __cplusplus } @@ -277,6 +288,11 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) va_end(v); } +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) { unsigned char arr[3]; @@ -450,7 +466,7 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v return 1; } -int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { stbi__write_context s; stbi__start_write_callbacks(&s, func, context); @@ -458,7 +474,7 @@ int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, i } #ifndef STBI_WRITE_NO_STDIO -int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { stbi__write_context s; if (stbi__start_write_file(&s,filename)) { @@ -620,7 +636,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f } } -int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) { stbi__write_context s; stbi__start_write_callbacks(&s, func, context); @@ -628,7 +644,7 @@ int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, i } #ifndef STBI_WRITE_NO_STDIO -int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { stbi__write_context s; if (stbi__start_write_file(&s,filename)) { @@ -1013,9 +1029,359 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, return 1; } + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + const unsigned char *imageData = (const unsigned char *)data; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + int x, y, pos; + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float YDU[64], UDU[64], VDU[64]; + for(row = y, pos = 0; row < y+8; ++row) { + for(col = x; col < x+8; ++col, ++pos) { + int p = row*width*comp + col*comp; + float r, g, b; + if(row >= height) { + p -= width*comp*(row+1 - height); + } + if(col >= width) { + p -= comp*(col+1 - width); + } + + r = imageData[p+0]; + g = imageData[p+ofsG]; + b = imageData[p+ofsB]; + YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; + UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; + VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? 1.04 (2017-03-03) monochrome BMP expansion 1.03 ??? diff --git a/src/external/stb_rect_pack.h b/src/external/stb_rect_pack.h index f5eb8d33..9faf5783 100644 --- a/src/external/stb_rect_pack.h +++ b/src/external/stb_rect_pack.h @@ -524,17 +524,6 @@ static int rect_height_compare(const void *a, const void *b) return (p->w > q->w) ? -1 : (p->w < q->w); } -static int rect_width_compare(const void *a, const void *b) -{ - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - if (p->w > q->w) - return -1; - if (p->w < q->w) - return 1; - return (p->h > q->h) ? -1 : (p->h < q->h); -} - static int rect_original_order(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; diff --git a/src/external/stb_truetype.h b/src/external/stb_truetype.h index fc5b9782..cec24254 100644 --- a/src/external/stb_truetype.h +++ b/src/external/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.15 - public domain +// stb_truetype.h - v1.17 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -6,6 +6,7 @@ // extract glyph metrics // extract glyph shapes // render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) // // Todo: // non-MS cmaps @@ -26,9 +27,10 @@ // Ryan Gordon // Simon Glass // github:IntellectualKitty +// Imanol Celaya // // Bug/warning reports/fixes: -// "Zer" on mollyrocket (with fix) +// "Zer" on mollyrocket // Cass Everitt // stoiko (Haemimont Games) // Brian Hook @@ -51,9 +53,12 @@ // Thomas Fields // Derek Vinyard // Cort Stratton +// github:oyvindjam // // VERSION HISTORY // +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const // 1.14 (2017-01-16) num-fonts-in-TTC function // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts @@ -92,7 +97,7 @@ // Improved 3D API (more shippable): // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() -// stbtt_PackSetOversample() -- for improved quality on small fonts +// stbtt_PackSetOversampling() -- for improved quality on small fonts // stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() @@ -110,6 +115,7 @@ // Character advance/positioning // stbtt_GetCodepointHMetrics() // stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() // stbtt_GetCodepointKernAdvance() // // Starting with version 1.06, the rasterizer was replaced with a new, @@ -407,6 +413,18 @@ int main(int arg, char **argv) #ifndef STBTT_sqrt #include #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) #endif #ifndef STBTT_fabs @@ -432,7 +450,7 @@ int main(int arg, char **argv) #endif #ifndef STBTT_memcpy - #include + #include #define STBTT_memcpy memcpy #define STBTT_memset memset #endif @@ -548,7 +566,7 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); #define STBTT_POINT_SIZE(x) (-(x)) -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range @@ -573,7 +591,7 @@ typedef struct unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple @@ -715,6 +733,12 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters @@ -809,6 +833,10 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place @@ -826,6 +854,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); @@ -848,6 +877,64 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap int invert, // if non-zero, vertically flip shape void *userdata); // context for to STBTT_MALLOC +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshhold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + ////////////////////////////////////////////////////////////////////////////// // // Finding the right font... @@ -2201,6 +2288,17 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); @@ -2693,19 +2791,18 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // from the other y segment, and it might ignored as an empty segment. to avoid // that, we need to explicitly produce segments based on x positions. - // rename variables to clear pairs + // rename variables to clearly-defined pairs float y0 = y_top; float x1 = (float) (x); float x2 = (float) (x+1); float x3 = xb; float y3 = y_bottom; - float y1,y2; // x = e->x + e->dx * (y-y_top) // (y-y_top) = (x - e->x) / e->dx // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; if (x0 < x1 && x3 > x2) { // three segments descending down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); @@ -3600,6 +3697,29 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb return k; } +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + // rects array must be big enough to accommodate all characters in the given ranges STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { @@ -3688,7 +3808,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i,j,n, return_value = 1; @@ -3724,7 +3844,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd return return_value; } -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; @@ -3763,6 +3883,387 @@ STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int *xpos += b->xadvance; } +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + orig[0] = x; + orig[1] = y; + + // make sure y never passes through a vertex of the shape + y_frac = (float) fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + c*x^2 + b*x + a = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + // if one scale is 0, use same scale for both + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) return NULL; // if both scales are 0, return NULL + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve + float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (verts[i].type == STBTT_vline) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3],px,py,t,it; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} ////////////////////////////////////////////////////////////////////////////// // @@ -3970,6 +4471,10 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) allow user-defined fabs() replacement diff --git a/src/external/stb_vorbis.c b/src/external/stb_vorbis.c index 21638bcd..5f2e0814 100644 --- a/src/external/stb_vorbis.c +++ b/src/external/stb_vorbis.c @@ -193,6 +193,7 @@ #undef __forceinline #endif #define __forceinline + #define alloca __builtin_alloca #elif !defined(_MSC_VER) #if __GNUC__ #define __forceinline inline diff --git a/src/external/stb_vorbis.h b/src/external/stb_vorbis.h index 9394e813..1cdca652 100644 --- a/src/external/stb_vorbis.h +++ b/src/external/stb_vorbis.h @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.10 - public domain +// Ogg Vorbis audio decoder - v1.11 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -29,9 +29,10 @@ // Bernhard Wodo Evan Balster alxprd@github // Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Phillip Bennefall Rohit Thiago Goulart -// manxorist@github saga musix +// manxorist@github saga musix github:infatum // // Partial history: +// 1.11 - 2017/07/23 - fix MinGW compilation // 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory // 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version // 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame -- cgit v1.2.3 From eeca607506b22f154a7b31ef8308d3ecd30ad383 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 4 Aug 2017 18:34:51 +0200 Subject: Review transforms to match OpenGL 1.1 --- src/core.c | 2 - src/models.c | 189 ++++++++++++++++++++++++++++----------------------------- src/rlgl.c | 9 ++- src/shapes.c | 2 +- src/textures.c | 4 +- 5 files changed, 103 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 4a95c660..78c0a7ef 100644 --- a/src/core.c +++ b/src/core.c @@ -912,8 +912,6 @@ void End3dMode(void) rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) - //rlTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode) - rlDisableDepthTest(); // Disable DEPTH_TEST for 2D } diff --git a/src/models.c b/src/models.c index accab7e8..315b51d4 100644 --- a/src/models.c +++ b/src/models.c @@ -118,68 +118,67 @@ void DrawCube(Vector3 position, float width, float height, float length, Color c float z = 0.0f; rlPushMatrix(); - - // NOTE: Be careful! Function order matters (scale -> rotate -> translate) - //rlScalef(1.0f, 3.0f, 1.0f); - //rlRotatef(45, 0, 1, 0); + // NOTE: Transformation is applied in inverse order (scale -> rotate -> translate) rlTranslatef(position.x, position.y, position.z); + //rlRotatef(45, 0, 1, 0); + //rlScalef(1.0f, 1.0f, 1.0f); // NOTE: Vertices are directly scaled on definition rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); - // Front Face ----------------------------------------------------- - rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - - rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right - - // Back Face ------------------------------------------------------ - rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - - rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right - rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + // Front face + rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left + rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right + rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left - // Top Face ------------------------------------------------------- - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left - rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left - rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right + rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right + rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left + rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left - rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right + // Back face + rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left + rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left + rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right - // Bottom Face ---------------------------------------------------- - rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right - rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right + rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right + rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right - rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left + // Top face + rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left + rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left + rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right - // Right face ----------------------------------------------------- - rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right - rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right + rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left + rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left + // Bottom face + rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left + rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right + rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left - // Left Face ------------------------------------------------------ - rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Right + rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right + rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right + // Right face + rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right + rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right + rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left + + rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left + rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right + rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left + + // Left face + rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right + rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left + rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right + + rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left + rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left + rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right rlEnd(); rlPopMatrix(); } @@ -198,8 +197,6 @@ void DrawCubeWires(Vector3 position, float width, float height, float length, Co float z = 0.0f; rlPushMatrix(); - - //rlRotatef(45, 0, 1, 0); rlTranslatef(position.x, position.y, position.z); rlBegin(RL_LINES); @@ -271,49 +268,49 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei rlEnableTexture(texture.id); //rlPushMatrix(); - // NOTE: Be careful! Function order matters (scale -> rotate -> translate) - //rlScalef(2.0f, 2.0f, 2.0f); - //rlRotatef(45, 0, 1, 0); + // NOTE: Transformation is applied in inverse order (scale -> rotate -> translate) //rlTranslatef(2.0f, 0.0f, 0.0f); + //rlRotatef(45, 0, 1, 0); + //rlScalef(2.0f, 2.0f, 2.0f); rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); // Front Face rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad // Back Face - rlNormal3f(0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Left Of The Texture and Quad + rlNormal3f(0.0f, 0.0f, - 1.0f); // Normal Pointing Away From Viewer + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad // Top Face rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad // Bottom Face - rlNormal3f(0.0f,-1.0f, 0.0f); // Normal Pointing Down - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad + rlNormal3f(0.0f, - 1.0f, 0.0f); // Normal Pointing Down + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad // Right face rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad // Left Face - rlNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad + rlNormal3f( - 1.0f, 0.0f, 0.0f); // Normal Pointing Left + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlEnd(); //rlPopMatrix(); @@ -330,8 +327,9 @@ void DrawSphere(Vector3 centerPos, float radius, Color color) void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color) { rlPushMatrix(); - rlScalef(radius, radius, radius); + // NOTE: Transformation is applied in inverse order (scale -> translate) rlTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlScalef(radius, radius, radius); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -369,8 +367,9 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color) { rlPushMatrix(); - rlScalef(radius, radius, radius); + // NOTE: Transformation is applied in inverse order (scale -> translate) rlTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlScalef(radius, radius, radius); rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -423,12 +422,12 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360/sides))*radiusBottom); //Bottom Right + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360/sides))*radiusTop); //Top Right rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); //Top Left rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360/sides))*radiusTop); //Top Right } // Draw Cap -------------------------------------------------------------------------------------- @@ -436,7 +435,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h { rlVertex3f(0, height, 0); rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360/sides))*radiusTop); } } else @@ -446,7 +445,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h { rlVertex3f(0, height, 0); rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360/sides))*radiusBottom); } } @@ -454,7 +453,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, 0, 0); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360/sides))*radiusBottom); rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); } rlEnd(); @@ -476,12 +475,12 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360/sides))*radiusBottom); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360/sides))*radiusTop); - rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sinf(DEG2RAD*(i + 360/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360/sides))*radiusTop); rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); @@ -496,8 +495,8 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Color color) { // NOTE: Plane is always created on XZ ground rlPushMatrix(); - rlScalef(size.x, 1.0f, size.y); rlTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlScalef(size.x, 1.0f, size.y); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -567,8 +566,8 @@ void DrawGizmo(Vector3 position) float length = 1.0f; rlPushMatrix(); - rlScalef(length, length, length); rlTranslatef(position.x, position.y, position.z); + rlScalef(length, length, length); rlBegin(RL_LINES); rlColor3f(1.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f); diff --git a/src/rlgl.c b/src/rlgl.c index dc8a37ac..cf57bcf1 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -446,7 +446,8 @@ void rlTranslatef(float x, float y, float z) { Matrix matTranslation = MatrixTranslate(x, y, z); - *currentMatrix = MatrixMultiply(*currentMatrix, matTranslation); + // NOTE: We transpose matrix with multiplication order + *currentMatrix = MatrixMultiply(matTranslation, *currentMatrix); } // Multiply the current matrix by a rotation matrix @@ -458,7 +459,8 @@ void rlRotatef(float angleDeg, float x, float y, float z) Vector3Normalize(&axis); matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); - *currentMatrix = MatrixMultiply(*currentMatrix, matRotation); + // NOTE: We transpose matrix with multiplication order + *currentMatrix = MatrixMultiply(matRotation, *currentMatrix); } // Multiply the current matrix by a scaling matrix @@ -466,7 +468,8 @@ void rlScalef(float x, float y, float z) { Matrix matScale = MatrixScale(x, y, z); - *currentMatrix = MatrixMultiply(*currentMatrix, matScale); + // NOTE: We transpose matrix with multiplication order + *currentMatrix = MatrixMultiply(matScale, *currentMatrix); } // Multiply the current matrix by another matrix diff --git a/src/shapes.c b/src/shapes.c index 25ed93aa..0e544718 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -123,7 +123,7 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) rlPushMatrix(); rlTranslatef((float)startPos.x, (float)startPos.y, 0); - rlRotatef(-RAD2DEG*angle, 0, 0, 1); + rlRotatef(RAD2DEG*angle, 0, 0, 1); rlTranslatef(0, -thick/2.0f, 0); rlBegin(RL_QUADS); diff --git a/src/textures.c b/src/textures.c index 23935bf1..1436111f 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1800,9 +1800,9 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V rlEnableTexture(texture.id); rlPushMatrix(); - rlTranslatef(-origin.x, -origin.y, 0); - rlRotatef(rotation, 0, 0, 1); rlTranslatef((float)destRec.x, (float)destRec.y, 0); + rlRotatef(rotation, 0, 0, 1); + rlTranslatef(-origin.x, -origin.y, 0); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, tint.a); -- cgit v1.2.3 From 6369b47f1190c1106448383ec557b9bb9be3dfcc Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 4 Aug 2017 19:18:55 +0200 Subject: Force OpenGL 3.3 on OSX if selected OpenGL 2.1 --- src/rlgl.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index cf57bcf1..184277d0 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -87,12 +87,12 @@ #if defined(__APPLE__) #include // OpenGL 3 library for OSX #else - #define GLAD_IMPLEMENTATION - #if defined(RLGL_STANDALONE) - #include "glad.h" // GLAD extensions loading library, includes OpenGL headers - #else - #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers - #endif + #define GLAD_IMPLEMENTATION + #if defined(RLGL_STANDALONE) + #include "glad.h" // GLAD extensions loading library, includes OpenGL headers + #else + #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers + #endif #endif #endif @@ -1273,7 +1273,11 @@ int rlGetVersion(void) #if defined(GRAPHICS_API_OPENGL_11) return OPENGL_11; #elif defined(GRAPHICS_API_OPENGL_21) - return OPENGL_21; + #if defined(__APPLE__) + return OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX + #else + return OPENGL_21; + #endif #elif defined(GRAPHICS_API_OPENGL_33) return OPENGL_33; #elif defined(GRAPHICS_API_OPENGL_ES2) -- cgit v1.2.3 From 0169b72bdca6890426f1e7f1824e7225afcb18ee Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 6 Aug 2017 10:43:43 +0200 Subject: Minor tweaks --- src/textures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/textures.c b/src/textures.c index 1436111f..0d8727db 100644 --- a/src/textures.c +++ b/src/textures.c @@ -407,7 +407,7 @@ RenderTexture2D LoadRenderTexture(int width, int height) // Unload image from CPU memory (RAM) void UnloadImage(Image image) { - free(image.data); + if (image.data != NULL) free(image.data); // NOTE: It becomes anoying every time a texture is loaded //TraceLog(LOG_INFO, "Unloaded image data"); @@ -1759,7 +1759,7 @@ void SetTextureWrap(Texture2D texture, int wrapMode) // Draw a Texture2D void DrawTexture(Texture2D texture, int posX, int posY, Color tint) { - DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY }, 0, 1.0f, tint); + DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY }, 0.0f, 1.0f, tint); } // Draw a Texture2D with position defined as Vector2 -- cgit v1.2.3 From 88839b093c47a478979eaf9a26a7341ff37d8b63 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 6 Aug 2017 10:44:50 +0200 Subject: Added function DrawRectangleT() Usefult to draw rectangles using default font texture --- src/raylib.h | 1 + src/text.c | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index bad711d9..85499eb1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -952,6 +952,7 @@ RLAPI void DrawFPS(int posX, int posY); RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters float fontSize, int spacing, Color tint); +RLAPI void DrawRectangleT(int posX, int posY, int width, int height, Color color); // Draw rectangle using text character // Text misc. functions RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font diff --git a/src/text.c b/src/text.c index 7ef01c11..fe00ce86 100644 --- a/src/text.c +++ b/src/text.c @@ -139,10 +139,10 @@ extern void LoadDefaultFont(void) 0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820, 0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0, 0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000, - 0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000, - 0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000, - 0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03, + 0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000f01, 0x00000000, 0x06000000, 0x24000000, 0x00000f01, 0x00000000, 0x09108000, + 0x24fa28a2, 0x00000f01, 0x00000000, 0x013e0000, 0x2242252a, 0x00000f52, 0x00000000, 0x038a8000, 0x2422222a, 0x00000f29, 0x00000000, 0x010a8000, + 0x2412252a, 0x00000f01, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000f01, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000, + 0x0003e000, 0x00000f00, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03, 0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202, 0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002, 0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002, @@ -255,7 +255,7 @@ extern void LoadDefaultFont(void) } defaultFont.baseSize = defaultFont.chars[0].rec.height; - + TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); } @@ -457,6 +457,14 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float } } +// Draw rectangle using text character (char: 127) +// NOTE: Useful to avoid changing to default white texture +void DrawRectangleT(int posX, int posY, int width, int height, Color color) +{ + DrawTexturePro(GetDefaultFont().texture, GetDefaultFont().chars[95].rec, + (Rectangle){ posX, posY, width, height }, (Vector2){ 0, 0 }, 0.0f, color); +} + // Formatting of text with variables to 'embed' const char *FormatText(const char *text, ...) { @@ -632,6 +640,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) { if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break; } + if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break; } -- cgit v1.2.3 From 18bf0ac044e2642ed82f226ba58b0331d0a86ba6 Mon Sep 17 00:00:00 2001 From: Michael Campagnaro Date: Wed, 23 Aug 2017 22:55:43 -0400 Subject: Fix typo in raymath.h --- src/raymath.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/raymath.h b/src/raymath.h index a06a4f9e..fe0b8947 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1218,19 +1218,19 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) float z2 = z + z; float length = QuaternionLength(q); - float lenghtSquared = length*length; + float lengthSquared = length*length; - float xx = x*x2/lenghtSquared; - float xy = x*y2/lenghtSquared; - float xz = x*z2/lenghtSquared; + float xx = x*x2/lengthSquared; + float xy = x*y2/lengthSquared; + float xz = x*z2/lengthSquared; - float yy = y*y2/lenghtSquared; - float yz = y*z2/lenghtSquared; - float zz = z*z2/lenghtSquared; + float yy = y*y2/lengthSquared; + float yz = y*z2/lengthSquared; + float zz = z*z2/lengthSquared; - float wx = w*x2/lenghtSquared; - float wy = w*y2/lenghtSquared; - float wz = w*z2/lenghtSquared; + float wx = w*x2/lengthSquared; + float wy = w*y2/lengthSquared; + float wz = w*z2/lengthSquared; result.m0 = 1.0f - (yy + zz); result.m1 = xy - wz; -- cgit v1.2.3 From b0adac96b75a9e58b313e1684fc57798457bc0fc Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 24 Aug 2017 20:33:30 +0200 Subject: Review issue with mipmaps setup On DDS files mipmapCount header parameter could be unused and set to 0, resulting in a wrong mipmap count and wrong compressed texture loading. --- src/textures.c | 53 ++++++++++++----------------------------------------- 1 file changed, 12 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/textures.c b/src/textures.c index 0d8727db..9322004b 100644 --- a/src/textures.c +++ b/src/textures.c @@ -53,6 +53,7 @@ // Default configuration flags (supported features) //------------------------------------------------- #define SUPPORT_FILEFORMAT_PNG +#define SUPPORT_FILEFORMAT_DDS #define SUPPORT_FILEFORMAT_HDR #define SUPPORT_IMAGE_MANIPULATION //------------------------------------------------- @@ -351,7 +352,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int { image.width = width; image.height = height; - image.mipmaps = 0; + image.mipmaps = 1; image.format = format; } @@ -1881,13 +1882,7 @@ static Image LoadDDS(const char *fileName) unsigned int reserved2; } DDSHeader; - Image image; - - image.data = NULL; - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; FILE *ddsFile = fopen(fileName, "rb"); @@ -1921,7 +1916,9 @@ static Image LoadDDS(const char *fileName) image.width = ddsHeader.width; image.height = ddsHeader.height; - image.mipmaps = 1; // Default value, could be changed (ddsHeader.mipmapCount) + + if (ddsHeader.mipmapCount == 0) image.mipmaps = 1; // Parameter not used + else image.mipmaps = ddsHeader.mipmapCount; if (ddsHeader.ddspf.rgbBitCount == 16) // 16bit mode, no compressed { @@ -2011,8 +2008,6 @@ static Image LoadDDS(const char *fileName) fread(image.data, size, 1, ddsFile); - image.mipmaps = ddsHeader.mipmapCount; - switch (ddsHeader.ddspf.fourCC) { case FOURCC_DXT1: @@ -2067,13 +2062,7 @@ static Image LoadPKM(const char *fileName) // NOTE: The extended width and height are the widths rounded up to a multiple of 4. // NOTE: ETC is always 4bit per pixel (64 bit for each 4x4 block of pixels) - Image image; - - image.data = NULL; - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; FILE *pkmFile = fopen(fileName, "rb"); @@ -2162,12 +2151,7 @@ static Image LoadKTX(const char *fileName) // NOTE: Before start of every mipmap data block, we have: unsigned int dataSize - Image image; - - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; FILE *ktxFile = fopen(fileName, "rb"); @@ -2282,13 +2266,7 @@ static Image LoadPVR(const char *fileName) } PVRMetadata; #endif - Image image; - - image.data = NULL; - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; FILE *pvrFile = fopen(fileName, "rb"); @@ -2406,13 +2384,7 @@ static Image LoadASTC(const char *fileName) unsigned char length[3]; // Image Z-size (1 for 2D images) } ASTCHeader; - Image image; - - image.data = NULL; - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; FILE *astcFile = fopen(fileName, "rb"); @@ -2437,12 +2409,11 @@ static Image LoadASTC(const char *fileName) image.width = 0x00000000 | ((int)astcHeader.width[2] << 16) | ((int)astcHeader.width[1] << 8) | ((int)astcHeader.width[0]); image.height = 0x00000000 | ((int)astcHeader.height[2] << 16) | ((int)astcHeader.height[1] << 8) | ((int)astcHeader.height[0]); - // NOTE: ASTC format only contains one mipmap level - image.mipmaps = 1; - TraceLog(LOG_DEBUG, "ASTC image width: %i", image.width); TraceLog(LOG_DEBUG, "ASTC image height: %i", image.height); TraceLog(LOG_DEBUG, "ASTC image blocks: %ix%i", astcHeader.blockX, astcHeader.blockY); + + image.mipmaps = 1; // NOTE: ASTC format only contains one mipmap level // NOTE: Each block is always stored in 128bit so we can calculate the bpp int bpp = 128/(astcHeader.blockX*astcHeader.blockY); -- cgit v1.2.3 From 0fc1323c80c2501c36741c05fd771ac1d001d049 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 25 Aug 2017 01:43:55 +0200 Subject: Renamed modelviewprojection matrix --- examples/models/resources/shaders/pbr.vs | 4 ++-- examples/shaders/resources/shaders/glsl100/base.vs | 4 ++-- examples/shaders/resources/shaders/glsl330/base.vs | 4 ++-- src/rlgl.c | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/examples/models/resources/shaders/pbr.vs b/examples/models/resources/shaders/pbr.vs index 6a0fb238..e852ac1a 100644 --- a/examples/models/resources/shaders/pbr.vs +++ b/examples/models/resources/shaders/pbr.vs @@ -15,7 +15,7 @@ in vec3 vertexNormal; in vec3 vertexTangent; // Input uniform values -uniform mat4 mvpMatrix; +uniform mat4 mvp; uniform mat4 mMatrix; // Output vertex attributes (to fragment shader) @@ -45,5 +45,5 @@ void main() fragBinormal = cross(fragNormal, fragTangent); // Calculate final vertex position - gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvp*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/base.vs b/examples/shaders/resources/shaders/glsl100/base.vs index e9386939..4be76b9e 100644 --- a/examples/shaders/resources/shaders/glsl100/base.vs +++ b/examples/shaders/resources/shaders/glsl100/base.vs @@ -7,7 +7,7 @@ attribute vec3 vertexNormal; attribute vec4 vertexColor; // Input uniform values -uniform mat4 mvpMatrix; +uniform mat4 mvp; // Output vertex attributes (to fragment shader) varying vec2 fragTexCoord; @@ -22,5 +22,5 @@ void main() fragColor = vertexColor; // Calculate final vertex position - gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvp*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/base.vs b/examples/shaders/resources/shaders/glsl330/base.vs index 638cb8ae..f3099e82 100644 --- a/examples/shaders/resources/shaders/glsl330/base.vs +++ b/examples/shaders/resources/shaders/glsl330/base.vs @@ -7,7 +7,7 @@ in vec3 vertexNormal; in vec4 vertexColor; // Input uniform values -uniform mat4 mvpMatrix; +uniform mat4 mvp; // Output vertex attributes (to fragment shader) out vec2 fragTexCoord; @@ -22,5 +22,5 @@ void main() fragColor = vertexColor; // Calculate final vertex position - gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvp*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/src/rlgl.c b/src/rlgl.c index 184277d0..373dada9 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -3251,12 +3251,12 @@ static Shader LoadShaderDefault(void) "out vec2 fragTexCoord; \n" "out vec4 fragColor; \n" #endif - "uniform mat4 mvpMatrix; \n" + "uniform mat4 mvp; \n" "void main() \n" "{ \n" " fragTexCoord = vertexTexCoord; \n" " fragColor = vertexColor; \n" - " gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" + " gl_Position = mvp*vec4(vertexPosition, 1.0); \n" "} \n"; // Fragment shader directly defined, no external file required @@ -3302,7 +3302,7 @@ static Shader LoadShaderDefault(void) shader.locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader.id, "vertexColor"); // Get handles to GLSL uniform locations - shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvp"); shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); shader.locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); } @@ -3332,7 +3332,7 @@ static void SetShaderDefaultLocations(Shader *shader) shader->locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME); // Get handles to GLSL uniform locations (vertex shader) - shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); + shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvp"); shader->locs[LOC_MATRIX_PROJECTION] = glGetUniformLocation(shader->id, "projection"); shader->locs[LOC_MATRIX_VIEW] = glGetUniformLocation(shader->id, "view"); -- cgit v1.2.3