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 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/core.c') 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)); -- 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/core.c') 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 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/core.c') 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 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/core.c') 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 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/core.c') 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 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/core.c') 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 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/core.c') 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 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/core.c') 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/core.c') 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 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/core.c') 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 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/core.c') 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 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/core.c') 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 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/core.c') 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