diff --git a/examples/android/example/bootstrap.sh b/examples/android/example/bootstrap.sh old mode 100755 new mode 100644 diff --git a/raylib/core.c b/raylib/core.c index d8b7dc6..173b219 100644 --- a/raylib/core.c +++ b/raylib/core.c @@ -3,17 +3,18 @@ * raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms * * PLATFORMS SUPPORTED: -* - Windows (win32/Win64) +* - Windows (Win32, Win64) * - Linux (tested on Ubuntu) -* - OSX (Mac) -* - Android (ARM or ARM64) +* - FreeBSD +* - OSX/macOS +* - Android (ARM, ARM64) * - Raspberry Pi (Raspbian) * - HTML5 (Chrome, Firefox) * * CONFIGURATION: * * #define PLATFORM_DESKTOP -* Windowing and input system configured for desktop platforms: Windows, Linux, OSX (managed by GLFW3 library) +* Windowing and input system configured for desktop platforms: Windows, Linux, OSX, FreeBSD (managed by GLFW3 library) * NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for mirror rendering - View [rlgl] module to enable it * * #define PLATFORM_ANDROID @@ -278,10 +279,11 @@ static int renderOffsetY = 0; // Offset Y from render area (must b static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP) static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) -static const char *windowTitle; // Window text title... -static bool cursorOnScreen = false; // Tracks if cursor is inside client area static bool cursorHidden = false; // Track if cursor is hidden + +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) +static const char *windowTitle = NULL; // Window text title... +static bool cursorOnScreen = false; // Tracks if cursor is inside client area static int screenshotCounter = 0; // Screenshots counter // Register mouse states @@ -408,12 +410,13 @@ static void *GamepadThread(void *arg); // Mouse reading thread //---------------------------------------------------------------------------------- #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // Initialize window and OpenGL context -void InitWindow(int width, int height, const char *title) +// NOTE: data parameter could be used to pass any kind of required data to the initialization +void InitWindow(int width, int height, void *data) { TraceLog(LOG_INFO, "Initializing raylib (v1.8.0)"); - // Store window title (could be useful...) - windowTitle = title; + // Input data is window title char data + windowTitle = (char *)data; // Init graphics device (display device and OpenGL context) InitGraphicsDevice(width, height); @@ -470,15 +473,17 @@ void InitWindow(int width, int height, const char *title) #endif #if defined(PLATFORM_ANDROID) -// Initialize Android activity -void InitWindow(int width, int height, void *state) +// Initialize window and OpenGL context (and Android activity) +// NOTE: data parameter could be used to pass any kind of required data to the initialization +void InitWindow(int width, int height, void *data) { TraceLog(LOG_INFO, "Initializing raylib (v1.8.0)"); screenWidth = width; screenHeight = height; - app = (struct android_app *)state; + // Input data is android app pointer + app = (struct android_app *)data; internalDataPath = app->activity->internalDataPath; // Set desired windows flags before initializing anything @@ -507,7 +512,6 @@ void InitWindow(int width, int height, void *state) //AConfiguration_getScreenSize(app->config); //AConfiguration_getScreenLong(app->config); - //state->userData = &engine; app->onAppCmd = AndroidCommandCallback; app->onInputEvent = AndroidInputCallback; @@ -708,7 +712,6 @@ int GetScreenHeight(void) return screenHeight; } -#if !defined(PLATFORM_ANDROID) // Show mouse cursor void ShowCursor() { @@ -771,7 +774,6 @@ void DisableCursor() #endif cursorHidden = true; } -#endif // !defined(PLATFORM_ANDROID) // Set background color (framebuffer clear color) void ClearBackground(Color color) @@ -1108,9 +1110,7 @@ Color Fade(Color color, float alpha) if (alpha < 0.0f) alpha = 0.0f; else if (alpha > 1.0f) alpha = 1.0f; - float colorAlpha = (float)color.a*alpha; - - return (Color){color.r, color.g, color.b, (unsigned char)colorAlpha}; + return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)}; } // Activate raylib logo at startup (can be done with flags) @@ -2525,6 +2525,8 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height) rlClearScreenBuffers(); // Clear screen buffers (color and depth) // Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode()) + // NOTE: Be careful! GLFW3 will choose the closest fullscreen resolution supported by current monitor, + // for example, if reescaling back to 800x450 (desired), it could set 720x480 (closest fullscreen supported) screenWidth = width; screenHeight = height; renderWidth = width; @@ -2776,8 +2778,16 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) ProcessGestureEvent(gestureEvent); #else - // TODO: Support only simple touch position - + // Support only simple touch position + if (flags == AMOTION_EVENT_ACTION_DOWN) + { + // Get first touch position + touchPosition[0].x = AMotionEvent_getX(event, 0); + touchPosition[0].y = AMotionEvent_getY(event, 0); + + touchPosition[0].x /= (float)GetScreenWidth(); + touchPosition[0].y /= (float)GetScreenHeight(); + } #endif return 0; diff --git a/raylib/core.go b/raylib/core.go index cb9fe9c..9aa0a7c 100644 --- a/raylib/core.go +++ b/raylib/core.go @@ -624,7 +624,7 @@ func GetHexValue(color Color) int32 { return v } -// ColorToFloat - Converts Color to float array and normalizes +// ColorToFloat - Converts Color to float32 slice and normalizes func ColorToFloat(color Color) []float32 { data := make([]float32, 0) data[0] = float32(color.R) / 255 @@ -635,8 +635,8 @@ func ColorToFloat(color Color) []float32 { return data } -// VectorToFloat - Converts Vector3 to float array -func VectorToFloat(vec Vector3) []float32 { +// Vector3ToFloat - Converts Vector3 to float32 slice +func Vector3ToFloat(vec Vector3) []float32 { data := make([]float32, 0) data[0] = vec.X data[1] = vec.Y @@ -645,7 +645,7 @@ func VectorToFloat(vec Vector3) []float32 { return data } -// MatrixToFloat - Converts Matrix to float array +// MatrixToFloat - Converts Matrix to float32 slice func MatrixToFloat(mat Matrix) []float32 { data := make([]float32, 0) diff --git a/raylib/external/rgif.h b/raylib/external/rgif.h index f26f67d..e524b37 100644 --- a/raylib/external/rgif.h +++ b/raylib/external/rgif.h @@ -150,7 +150,7 @@ typedef struct GifBitStatus { // The LZW dictionary is a 256-ary tree constructed // as the file is encoded, this is one node typedef struct GifLzwNode { - uint16_t m_next[256]; + unsigned short m_next[256]; } GifLzwNode; //---------------------------------------------------------------------------------- @@ -299,9 +299,9 @@ static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int if (ind == gifTransparentIndex) return; // check whether this color is better than the current winner - int r_err = r - ((int32_t)pPal->r[ind]); - int g_err = g - ((int32_t)pPal->g[ind]); - int b_err = b - ((int32_t)pPal->b[ind]); + int r_err = r - ((int)pPal->r[ind]); + int g_err = g - ((int)pPal->g[ind]); + int b_err = b - ((int)pPal->b[ind]); int diff = GIFABS(r_err)+GIFABS(g_err)+GIFABS(b_err); if (diff < *bestDiff) @@ -463,7 +463,7 @@ static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, i } // otherwise, take the average of all colors in this subcube - uint64_t r=0, g=0, b=0; + unsigned long long r=0, g=0, b=0; for (int ii=0; iir[bestInd])*256; - int32_t g_err = nextPix[1] - (int32_t)(pPal->g[bestInd])*256; - int32_t b_err = nextPix[2] - (int32_t)(pPal->b[bestInd])*256; + int r_err = nextPix[0] - (int)(pPal->r[bestInd])*256; + int g_err = nextPix[1] - (int)(pPal->g[bestInd])*256; + int b_err = nextPix[2] - (int)(pPal->b[bestInd])*256; nextPix[0] = pPal->r[bestInd]; nextPix[1] = pPal->g[bestInd]; @@ -654,7 +654,7 @@ static void GifDitherImage(const unsigned char *lastFrame, const unsigned char * if (quantloc_7 < numPixels) { - int32_t *pix7 = quantPixels+4*quantloc_7; + int *pix7 = quantPixels+4*quantloc_7; pix7[0] += GIFMAX(-pix7[0], r_err*7 / 16); pix7[1] += GIFMAX(-pix7[1], g_err*7 / 16); pix7[2] += GIFMAX(-pix7[2], b_err*7 / 16); @@ -662,7 +662,7 @@ static void GifDitherImage(const unsigned char *lastFrame, const unsigned char * if (quantloc_3 < numPixels) { - int32_t *pix3 = quantPixels+4*quantloc_3; + int *pix3 = quantPixels+4*quantloc_3; pix3[0] += GIFMAX(-pix3[0], r_err*3 / 16); pix3[1] += GIFMAX(-pix3[1], g_err*3 / 16); pix3[2] += GIFMAX(-pix3[2], b_err*3 / 16); @@ -670,7 +670,7 @@ static void GifDitherImage(const unsigned char *lastFrame, const unsigned char * if (quantloc_5 < numPixels) { - int32_t *pix5 = quantPixels+4*quantloc_5; + int *pix5 = quantPixels+4*quantloc_5; pix5[0] += GIFMAX(-pix5[0], r_err*5 / 16); pix5[1] += GIFMAX(-pix5[1], g_err*5 / 16); pix5[2] += GIFMAX(-pix5[2], b_err*5 / 16); @@ -678,7 +678,7 @@ static void GifDitherImage(const unsigned char *lastFrame, const unsigned char * if (quantloc_1 < numPixels) { - int32_t *pix1 = quantPixels+4*quantloc_1; + int *pix1 = quantPixels+4*quantloc_1; pix1[0] += GIFMAX(-pix1[0], r_err / 16); pix1[1] += GIFMAX(-pix1[1], g_err / 16); pix1[2] += GIFMAX(-pix1[2], b_err / 16); @@ -716,8 +716,8 @@ static void GifThresholdImage(const unsigned char *lastFrame, const unsigned cha else { // palettize the pixel - int32_t bestDiff = 1000000; - int32_t bestInd = 1; + int bestDiff = 1000000; + int bestInd = 1; GifGetClosestPaletteColor(pPal, nextFrame[0], nextFrame[1], nextFrame[2], &bestInd, &bestDiff, 1); // Write the resulting color to the output buffer @@ -835,7 +835,7 @@ static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, u GifLzwNode *codetree = (GifLzwNode *)GIF_TEMP_MALLOC(sizeof(GifLzwNode)*4096); memset(codetree, 0, sizeof(GifLzwNode)*4096); - int32_t curCode = -1; + int curCode = -1; unsigned int codeSize = minCodeSize + 1; unsigned int maxCode = clearCode + 1; diff --git a/raylib/platform_arm.go b/raylib/platform_arm.go index 1cd8f8f..0139729 100644 --- a/raylib/platform_arm.go +++ b/raylib/platform_arm.go @@ -21,8 +21,9 @@ func InitWindow(width int32, height int32, t interface{}) { title, ok := t.(string) if ok { ctitle := C.CString(title) - defer C.free(unsafe.Pointer(ctitle)) - C.InitWindow(cwidth, cheight, ctitle) + cptitle := unsafe.Pointer(ctitle) + defer C.free(cptitle) + C.InitWindow(cwidth, cheight, cptitle) } } diff --git a/raylib/platform_desktop.go b/raylib/platform_desktop.go index 867debe..3994cd8 100644 --- a/raylib/platform_desktop.go +++ b/raylib/platform_desktop.go @@ -21,8 +21,9 @@ func InitWindow(width int32, height int32, t interface{}) { title, ok := t.(string) if ok { ctitle := C.CString(title) - defer C.free(unsafe.Pointer(ctitle)) - C.InitWindow(cwidth, cheight, ctitle) + cptitle := unsafe.Pointer(ctitle) + defer C.free(cptitle) + C.InitWindow(cwidth, cheight, cptitle) } } diff --git a/raylib/raylib.go b/raylib/raylib.go index 3e9bde9..46892cd 100644 --- a/raylib/raylib.go +++ b/raylib/raylib.go @@ -39,6 +39,62 @@ import ( "runtime" ) +// CallQueueCap is the capacity of the call queue. +// +// The default value is 16. +var CallQueueCap = 16 + +// callInMain calls a function in the main thread. It is only properly initialized inside raylib.Main(..). +// As a default, it panics. +var callInMain = func(f func()) { + panic("raylib.Main(main func()) must be called before raylib.Do(f func())") +} + func init() { + // Make sure the main goroutine is bound to the main thread. runtime.LockOSThread() } + +// Main entry point. Run this function at the beginning of main(), and pass your own main body to it as a function. E.g.: +// +// func main() { +// raylib.Main(func() { +// // Your code here.... +// // [....] +// +// // Calls to raylib can be made by any goroutine, but always guarded by raylib.Do() +// raylib.Do(func() { +// raylib.DrawTexture(..) +// }) +// }) +// } +func Main(main func()) { + // Queue of functions that are thread-sensitive + callQueue := make(chan func(), CallQueueCap) + + done := make(chan bool, 1) + + // Properly initialize callInMain for use by raylib.Do(..) + callInMain = func(f func()) { + callQueue <- func() { + f() + done <- true + } + <-done + } + + go func() { + main() + + close(callQueue) + }() + + for f := range callQueue { + f() + } +} + +// Do queues function f on the main thread and blocks until the function f finishes +func Do(f func()) { + callInMain(f) +} diff --git a/raylib/raylib.h b/raylib/raylib.h index 3decb46..e5ad8a9 100644 --- a/raylib/raylib.h +++ b/raylib/raylib.h @@ -72,20 +72,6 @@ #ifndef RAYLIB_H #define RAYLIB_H -// Choose your platform here or just define it at compile time: -DPLATFORM_DESKTOP -//#define PLATFORM_DESKTOP // Windows, Linux or OSX -//#define PLATFORM_ANDROID // Android device -//#define PLATFORM_RPI // Raspberry Pi -//#define PLATFORM_WEB // HTML5 (emscripten, asm.js) - -// Security check in case no PLATFORM_* defined -#if !defined(PLATFORM_DESKTOP) && \ - !defined(PLATFORM_ANDROID) && \ - !defined(PLATFORM_RPI) && \ - !defined(PLATFORM_WEB) - #define PLATFORM_DESKTOP -#endif - #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) #define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll) #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) @@ -179,13 +165,11 @@ #define KEY_Y 89 #define KEY_Z 90 -#if defined(PLATFORM_ANDROID) - // Android Physical Buttons - #define KEY_BACK 4 - #define KEY_MENU 82 - #define KEY_VOLUME_UP 24 - #define KEY_VOLUME_DOWN 25 -#endif +// Android Physical Buttons +#define KEY_BACK 4 +#define KEY_MENU 82 +#define KEY_VOLUME_UP 24 +#define KEY_VOLUME_DOWN 25 // Mouse Buttons #define MOUSE_LEFT_BUTTON 0 @@ -710,11 +694,7 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ // Window-related functions -#if defined(PLATFORM_ANDROID) -RLAPI void InitWindow(int width, int height, void *state); // Initialize Android activity -#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) -RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context -#endif +RLAPI void InitWindow(int width, int height, void *data); // Initialize window and OpenGL context RLAPI void CloseWindow(void); // Close window and unload OpenGL context RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed RLAPI bool IsWindowMinimized(void); // Check if window has been minimized (or lost focus) @@ -727,14 +707,12 @@ RLAPI void SetWindowMinSize(int width, int height); // Set window RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height -#if !defined(PLATFORM_ANDROID) // Cursor-related functions RLAPI void ShowCursor(void); // Shows cursor RLAPI void HideCursor(void); // Hides cursor RLAPI bool IsCursorHidden(void); // Check if cursor is not visible RLAPI void EnableCursor(void); // Enables cursor (unlock cursor) RLAPI void DisableCursor(void); // Disables cursor (lock cursor) -#endif // Drawing-related functions RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color) @@ -764,7 +742,7 @@ RLAPI Color Fade(Color color, float alpha); // Color fade- RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes // Math useful functions (available from raymath.h) -RLAPI float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array +RLAPI float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array RLAPI Vector3 Vector3Zero(void); // Vector with components value 0.0f RLAPI Vector3 Vector3One(void); // Vector with components value 1.0f @@ -1075,8 +1053,8 @@ RLAPI Texture2D GetTextureDefault(void); // Get // 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) -RLAPI void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) +RLAPI void SetShaderValue(Shader shader, int uniformLoc, const float *value, int size); // Set shader uniform value (float) +RLAPI void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int size); // Set shader uniform value (int) RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) 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) @@ -1095,14 +1073,15 @@ RLAPI void BeginBlendMode(int mode); // Beg RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending) // VR control functions -VrDeviceInfo GetVrDeviceInfo(int vrDeviceType); // Get VR device information for some standard devices -void InitVrSimulator(VrDeviceInfo info); // Init VR simulator for selected device parameters -RLAPI void CloseVrSimulator(void); // Close VR simulator for current device -RLAPI bool IsVrSimulatorReady(void); // Detect if VR simulator is ready -RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera -RLAPI void ToggleVrMode(void); // Enable/Disable VR experience -RLAPI void BeginVrDrawing(void); // Begin VR simulator stereo rendering -RLAPI void EndVrDrawing(void); // End VR simulator stereo rendering +RLAPI VrDeviceInfo GetVrDeviceInfo(int vrDeviceType); // Get VR device information for some standard devices +RLAPI void InitVrSimulator(VrDeviceInfo info); // Init VR simulator for selected device parameters +RLAPI void CloseVrSimulator(void); // Close VR simulator for current device +RLAPI bool IsVrSimulatorReady(void); // Detect if VR simulator is ready +RLAPI void SetVrDistortionShader(Shader shader); // Set VR distortion shader for stereoscopic rendering +RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera +RLAPI void ToggleVrMode(void); // Enable/Disable VR experience +RLAPI void BeginVrDrawing(void); // Begin VR simulator stereo rendering +RLAPI void EndVrDrawing(void); // End VR simulator stereo rendering //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) diff --git a/raylib/rlgl.c b/raylib/rlgl.c index 35c812a..f273e55 100644 --- a/raylib/rlgl.c +++ b/raylib/rlgl.c @@ -170,6 +170,11 @@ #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 #endif +#if defined(GRAPHICS_API_OPENGL_21) + #define GL_LUMINANCE 0x1909 + #define GL_LUMINANCE_ALPHA 0x190A +#endif + #if defined(GRAPHICS_API_OPENGL_ES2) #define glClearDepth glClearDepthf #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER @@ -227,7 +232,7 @@ typedef struct DrawCall { typedef struct VrStereoConfig { RenderTexture2D stereoFbo; // VR stereo rendering framebuffer Shader distortionShader; // VR stereo rendering distortion shader - //Rectangle eyesViewport[2]; // VR stereo rendering eyes viewports + Rectangle eyesViewport[2]; // VR stereo rendering eyes viewports Matrix eyesProjection[2]; // VR stereo rendering eyes projection matrices Matrix eyesViewOffset[2]; // VR stereo rendering eyes view offset matrices } VrStereoConfig; @@ -262,7 +267,9 @@ static Vector3 *tempBuffer; static int tempBufferCount = 0; static bool useTempBuffer = false; -// Shader Programs +// Shaders +static unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program) +static unsigned int defaultFShaderId; // Default fragment shader Id (used by default shader program) static Shader defaultShader; // Basic shader, support vertex color and diffuse texture static Shader currentShader; // Shader to be used on rendering (by default, defaultShader) @@ -319,7 +326,9 @@ static int screenHeight; // Default framebuffer height //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) 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 unsigned int CompileShader(const char *shaderStr, int type); // Compile custom shader and return shader id +static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program 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) @@ -1378,7 +1387,40 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi glBindTexture(GL_TEXTURE_2D, id); -#if defined(GRAPHICS_API_OPENGL_33) +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || 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: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + 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_21) + 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; + #endif + #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; // 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; + } +#elif defined(GRAPHICS_API_OPENGL_33) // NOTE: We define internal (GPU) format as GL_RGBA8 (probably BGRA8 in practice, driver takes care) // NOTE: On embedded systems, we let the driver choose the best internal format @@ -1431,33 +1473,6 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi 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) - // 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: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_GRAY_ALPHA: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; - 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; // 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; - } #endif // Texture parameters configuration @@ -1575,10 +1590,10 @@ RenderTexture2D rlLoadRenderTexture(int width, int height) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); -#if defined(GRAPHICS_API_OPENGL_33) - #define USE_DEPTH_TEXTURE -#else +#if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2) #define USE_DEPTH_RENDERBUFFER +#else + #define USE_DEPTH_TEXTURE #endif #if defined(USE_DEPTH_RENDERBUFFER) @@ -1937,17 +1952,17 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) // Upload to shader material.colDiffuse if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1) - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, - (float)material.maps[MAP_DIFFUSE].color.g/255, - (float)material.maps[MAP_DIFFUSE].color.b/255, - (float)material.maps[MAP_DIFFUSE].color.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255.0f, + (float)material.maps[MAP_DIFFUSE].color.g/255.0f, + (float)material.maps[MAP_DIFFUSE].color.b/255.0f, + (float)material.maps[MAP_DIFFUSE].color.a/255.0f); // 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[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); + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255.0f, + (float)material.maps[MAP_SPECULAR].color.g/255.0f, + (float)material.maps[MAP_SPECULAR].color.b/255.0f, + (float)material.maps[MAP_SPECULAR].color.a/255.0f); if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview); if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection); @@ -2226,8 +2241,8 @@ void *rlReadTexturePixels(Texture2D texture) glEnable(GL_DEPTH_TEST); //glDisable(GL_BLEND); - glViewport(0, 0, width, height); - rlOrtho(0.0, width, height, 0.0, 0.0, 1.0); + glViewport(0, 0, texture.width, texture.height); + rlOrtho(0.0, texture.width, texture.height, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(GetShaderDefault().id); @@ -2340,33 +2355,47 @@ char *LoadText(const char *fileName) } // Load shader from files and bind default locations +// NOTE: If shader string is NULL, using default vertex/fragment shaders Shader LoadShader(char *vsFileName, char *fsFileName) { Shader shader = { 0 }; + + // NOTE: All locations must be reseted to -1 (no location) + for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Shaders loading from external text file - char *vShaderStr = LoadText(vsFileName); - char *fShaderStr = LoadText(fsFileName); - if ((vShaderStr != NULL) && (fShaderStr != NULL)) + unsigned int vertexShaderId, fragmentShaderId; + + if (vsFileName == NULL) vertexShaderId = defaultVShaderId; + else { - shader.id = LoadShaderProgram(vShaderStr, fShaderStr); - - // After shader loading, we TRY to set default location names - if (shader.id > 0) SetShaderDefaultLocations(&shader); - - // Shader strings must be freed + char *vShaderStr = LoadText(vsFileName); + vertexShaderId = CompileShader(vShaderStr, GL_VERTEX_SHADER); free(vShaderStr); + } + + if (fsFileName == NULL) fragmentShaderId = defaultVShaderId; + else + { + char* fShaderStr = LoadText(fsFileName); + fragmentShaderId = CompileShader(fShaderStr, GL_FRAGMENT_SHADER); free(fShaderStr); } + shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId); + + if (vertexShaderId != defaultVShaderId) glDeleteShader(vertexShaderId); + if (fragmentShaderId != defaultFShaderId) glDeleteShader(fragmentShaderId); + if (shader.id == 0) { TraceLog(LOG_WARNING, "Custom shader could not be loaded"); shader = defaultShader; } + // After shader loading, we TRY to set default location names + if (shader.id > 0) SetShaderDefaultLocations(&shader); // Get available shader uniforms // NOTE: This information is useful for debug... @@ -2391,7 +2420,6 @@ Shader LoadShader(char *vsFileName, char *fsFileName) TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); } - #endif return shader; @@ -2441,7 +2469,7 @@ int GetShaderLocation(Shader shader, const char *uniformName) } // Set shader uniform value (float) -void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) +void SetShaderValue(Shader shader, int uniformLoc, const float *value, int size) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glUseProgram(shader.id); @@ -2457,7 +2485,7 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) } // Set shader uniform value (int) -void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) +void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int size) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glUseProgram(shader.id); @@ -2898,11 +2926,15 @@ void InitVrSimulator(VrDeviceInfo info) 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); + // Load distortion shader + unsigned int vertexShaderId = CompileShader(distortionVShaderStr, GL_VERTEX_SHADER); + unsigned int fragmentShaderId = CompileShader(distortionFShaderStr, GL_FRAGMENT_SHADER); + + vrConfig.distortionShader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId); if (vrConfig.distortionShader.id > 0) SetShaderDefaultLocations(&vrConfig.distortionShader); #endif + // Set VR configutarion parameters, including distortion shader SetStereoConfig(info); vrSimulatorReady = true; @@ -2927,18 +2959,6 @@ void CloseVrSimulator(void) #endif } -// TODO: Review VR system to be more flexible, -// move distortion shader to user side, -// SetStereoConfig() must be reviewed... -/* -// Set VR view distortion shader -void SetVrDistortionShader(Shader shader) -{ - vrConfig.distortionShader = shader; - SetStereoConfig(info); -} -*/ - // Detect if VR simulator is running bool IsVrSimulatorReady(void) { @@ -2949,6 +2969,15 @@ bool IsVrSimulatorReady(void) #endif } +// Set VR distortion shader for stereoscopic rendering +// TODO: Review VR system to be more flexible, move distortion shader to user side +void SetVrDistortionShader(Shader shader) +{ + vrConfig.distortionShader = shader; + + //SetStereoConfig(info); // TODO: Must be reviewed to set new distortion shader uniform values... +} + // Enable/Disable VR experience (device or simulator) void ToggleVrMode(void) { @@ -3113,86 +3142,53 @@ static void LoadTextureCompressed(unsigned char *data, int width, int height, in } } +// Compile custom shader and return shader id +static unsigned int CompileShader(const char *shaderStr, int type) +{ + unsigned int shader = glCreateShader(type); + glShaderSource(shader, 1, &shaderStr, NULL); + + GLint success = 0; + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + + if (success != GL_TRUE) + { + TraceLog(LOG_WARNING, "[SHDR ID %i] Failed to compile shader...", shader); + int maxLength = 0; + int length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + +#ifdef _MSC_VER + char *log = malloc(maxLength); +#else + char log[maxLength]; +#endif + glGetShaderInfoLog(shader, maxLength, &length, log); + + TraceLog(LOG_INFO, "%s", log); + +#ifdef _MSC_VER + free(log); +#endif + } + else TraceLog(LOG_INFO, "[SHDR ID %i] Shader compiled successfully", shader); + + return shader; +} + // Load custom shader strings and return program id -static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr) +static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) { unsigned int program = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - GLuint vertexShader; - GLuint fragmentShader; - - vertexShader = glCreateShader(GL_VERTEX_SHADER); - fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - - const char *pvs = vShaderStr; - const char *pfs = fShaderStr; - - glShaderSource(vertexShader, 1, &pvs, NULL); - glShaderSource(fragmentShader, 1, &pfs, NULL); GLint success = 0; - - glCompileShader(vertexShader); - - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); - - if (success != GL_TRUE) - { - TraceLog(LOG_WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); - - int maxLength = 0; - int length; - - glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength); - -#ifdef _MSC_VER - char *log = malloc(maxLength); -#else - char log[maxLength]; -#endif - glGetShaderInfoLog(vertexShader, maxLength, &length, log); - - TraceLog(LOG_INFO, "%s", log); - -#ifdef _MSC_VER - free(log); -#endif - } - else TraceLog(LOG_INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader); - - glCompileShader(fragmentShader); - - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); - - if (success != GL_TRUE) - { - TraceLog(LOG_WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader); - - int maxLength = 0; - int length; - - glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength); - -#ifdef _MSC_VER - char *log = malloc(maxLength); -#else - char log[maxLength]; -#endif - glGetShaderInfoLog(fragmentShader, maxLength, &length, log); - - TraceLog(LOG_INFO, "%s", log); - -#ifdef _MSC_VER - free(log); -#endif - } - else TraceLog(LOG_INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader); - program = glCreateProgram(); - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); + glAttachShader(program, vShaderId); + glAttachShader(program, fShaderId); // NOTE: Default attribute shader locations must be binded before linking glBindAttribLocation(program, 0, DEFAULT_ATTRIB_POSITION_NAME); @@ -3236,9 +3232,6 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade program = 0; } else TraceLog(LOG_INFO, "[SHDR ID %i] Shader program loaded successfully", program); - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); #endif return program; } @@ -3248,10 +3241,13 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade // NOTE: This shader program is used for batch buffers (lines, triangles, quads) static Shader LoadShaderDefault(void) { - Shader shader; + Shader shader = { 0 }; + + // NOTE: All locations must be reseted to -1 (no location) + for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; // Vertex shader directly defined, no external file required - char vDefaultShaderStr[] = + char defaultVShaderStr[] = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" #elif defined(GRAPHICS_API_OPENGL_ES2) @@ -3280,7 +3276,7 @@ static Shader LoadShaderDefault(void) "} \n"; // Fragment shader directly defined, no external file required - char fDefaultShaderStr[] = + char defaultFShaderStr[] = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" #elif defined(GRAPHICS_API_OPENGL_ES2) @@ -3309,22 +3305,29 @@ static Shader LoadShaderDefault(void) #endif "} \n"; - shader.id = LoadShaderProgram(vDefaultShaderStr, fDefaultShaderStr); + // NOTE: Compiled vertex/fragment shaders are kept for re-use + defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader + defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader + + shader.id = LoadShaderProgram(defaultVShaderId, defaultFShaderId); 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 + + // Set default shader locations: attributes 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 + // Set default shader locations: uniform locations shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvp"); shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); shader.locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); + + // NOTE: We could also use below function but in case DEFAULT_ATTRIB_* points are + // changed for external custom shaders, we just use direct bindings above + //SetShaderDefaultLocations(&shader); } else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); @@ -3368,10 +3371,10 @@ static void UnloadShaderDefault(void) { glUseProgram(0); - //glDetachShader(defaultShader, vertexShader); - //glDetachShader(defaultShader, fragmentShader); - //glDeleteShader(vertexShader); // Already deleted on shader compilation - //glDeleteShader(fragmentShader); // Already deleted on shader compilation + glDetachShader(defaultShader.id, defaultVShaderId); + glDetachShader(defaultShader.id, defaultFShaderId); + glDeleteShader(defaultVShaderId); + glDeleteShader(defaultFShaderId); glDeleteProgram(defaultShader.id); } @@ -4021,8 +4024,8 @@ static void SetStereoConfig(VrDeviceInfo hmd) vrConfig.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); // Compute eyes Viewports - //vrConfig.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; - //vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; + vrConfig.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; + vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; } // Set internal projection and modelview matrix depending on eyes tracking data diff --git a/raylib/rlgl.h b/raylib/rlgl.h index 3f06a69..2e67c69 100644 --- a/raylib/rlgl.h +++ b/raylib/rlgl.h @@ -145,56 +145,6 @@ typedef unsigned char byte; // Boolean type typedef enum { false, true } bool; #endif - - // Shader location point type - 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_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_MAP_DIFFUSE LOC_MAP_ALBEDO - #define LOC_MAP_SPECULAR LOC_MAP_METALNESS - - // Material map type - typedef enum { - 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 MAP_DIFFUSE MAP_ALBEDO - #define MAP_SPECULAR MAP_METALNESS // Color type, RGBA (32bit) typedef struct Color { @@ -204,6 +154,14 @@ typedef unsigned char byte; unsigned char a; } Color; + // Rectangle type + typedef struct Rectangle { + int x; + int y; + int width; + int height; + } Rectangle; + // Texture2D type // NOTE: Data stored in GPU memory typedef struct Texture2D { @@ -341,6 +299,56 @@ typedef unsigned char byte; BLEND_MULTIPLIED } BlendMode; + // Shader location point type + 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_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_MAP_DIFFUSE LOC_MAP_ALBEDO + #define LOC_MAP_SPECULAR LOC_MAP_METALNESS + + // Material map type + typedef enum { + 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 MAP_DIFFUSE MAP_ALBEDO + #define MAP_SPECULAR MAP_METALNESS + // VR Head Mounted Display devices typedef enum { HMD_DEFAULT_DEVICE = 0, diff --git a/raylib/shader_distortion.h b/raylib/shader_distortion.h index 7a2c994..3b37c63 100644 --- a/raylib/shader_distortion.h +++ b/raylib/shader_distortion.h @@ -1,6 +1,6 @@ // Vertex shader definition to embed, no external file required -static const char vDistortionShaderStr[] = +static const char distortionVShaderStr[] = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" #elif defined(GRAPHICS_API_OPENGL_ES2) @@ -29,7 +29,7 @@ static const char vDistortionShaderStr[] = "} \n"; // Fragment shader definition to embed, no external file required -static const char fDistortionShaderStr[] = +static const char distortionFShaderStr[] = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" #elif defined(GRAPHICS_API_OPENGL_ES2)