diff options
| author | Ray <[email protected]> | 2017-04-08 23:31:58 +0200 |
|---|---|---|
| committer | Ray <[email protected]> | 2017-04-08 23:31:58 +0200 |
| commit | 20d205cae5bf78d00fb03c266999c33488cbd2c8 (patch) | |
| tree | 8aafb630d19f3a2a827bf212e16c531a0c672d41 /examples/others | |
| parent | 5fd83708cf860db358d843cb30f99a88aaf3bd2c (diff) | |
| download | raylib-20d205cae5bf78d00fb03c266999c33488cbd2c8.tar.gz raylib-20d205cae5bf78d00fb03c266999c33488cbd2c8.zip | |
Working on examples...
Diffstat (limited to 'examples/others')
40 files changed, 1906 insertions, 393 deletions
diff --git a/examples/others/font_selector.c b/examples/others/font_selector.c new file mode 100644 index 00000000..5891bef7 --- /dev/null +++ b/examples/others/font_selector.c @@ -0,0 +1,158 @@ +/******************************************************************************************* +* +* raylib [text] example - Font selector +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [text] example - font selector"); + + // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) + SpriteFont fonts[8]; // SpriteFont array + + fonts[0] = LoadSpriteFont("resources/fonts/alagard.rbmf"); // SpriteFont loading + fonts[1] = LoadSpriteFont("resources/fonts/pixelplay.rbmf"); // SpriteFont loading + fonts[2] = LoadSpriteFont("resources/fonts/mecha.rbmf"); // SpriteFont loading + fonts[3] = LoadSpriteFont("resources/fonts/setback.rbmf"); // SpriteFont loading + fonts[4] = LoadSpriteFont("resources/fonts/romulus.rbmf"); // SpriteFont loading + fonts[5] = LoadSpriteFont("resources/fonts/pixantiqua.rbmf"); // SpriteFont loading + fonts[6] = LoadSpriteFont("resources/fonts/alpha_beta.rbmf"); // SpriteFont loading + fonts[7] = LoadSpriteFont("resources/fonts/jupiter_crash.rbmf"); // SpriteFont loading + + int currentFont = 0; // Selected font + + Color colors[8] = { MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, LIME, GOLD, RED }; + + const char fontNames[8][20] = { "[0] Alagard", "[1] PixelPlay", "[2] MECHA", "[3] Setback", + "[4] Romulus", "[5] PixAntiqua", "[6] Alpha Beta", "[7] Jupiter Crash" }; + + const char text[50] = "THIS is THE FONT you SELECTED!"; // Main text + + Vector2 textSize = MeasureTextEx(fonts[currentFont], text, fonts[currentFont].baseSize*3, 1); + + Vector2 mousePoint; + + Color btnNextOutColor = DARKBLUE; // Button color (outside line) + Color btnNextInColor = SKYBLUE; // Button color (inside) + + int framesCounter = 0; // Useful to count frames button is 'active' = clicked + + int positionY = 180; // Text selector and button Y position + + Rectangle btnNextRec = { 673, positionY, 109, 44 }; // Button rectangle (useful for collision) + + 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 + //---------------------------------------------------------------------------------- + + // Keyboard-based font selection (easy) + if (IsKeyPressed(KEY_RIGHT)) + { + if (currentFont < 7) currentFont++; + } + + if (IsKeyPressed(KEY_LEFT)) + { + if (currentFont > 0) currentFont--; + } + + if (IsKeyPressed('0')) currentFont = 0; + else if (IsKeyPressed('1')) currentFont = 1; + else if (IsKeyPressed('2')) currentFont = 2; + else if (IsKeyPressed('3')) currentFont = 3; + else if (IsKeyPressed('4')) currentFont = 4; + else if (IsKeyPressed('5')) currentFont = 5; + else if (IsKeyPressed('6')) currentFont = 6; + else if (IsKeyPressed('7')) currentFont = 7; + + // Mouse-based font selection (NEXT button logic) + mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, btnNextRec)) + { + // Mouse hover button logic + if (framesCounter == 0) + { + btnNextOutColor = DARKPURPLE; + btnNextInColor = PURPLE; + } + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + framesCounter = 20; // Frames button is 'active' + btnNextOutColor = MAROON; + btnNextInColor = RED; + } + } + else + { + // Mouse not hover button + btnNextOutColor = DARKBLUE; + btnNextInColor = SKYBLUE; + } + + if (framesCounter > 0) framesCounter--; + + if (framesCounter == 1) // We change font on frame 1 + { + currentFont++; + if (currentFont > 7) currentFont = 0; + } + + // Text measurement for better positioning on screen + textSize = MeasureTextEx(fonts[currentFont], text, fonts[currentFont].baseSize*3, 1); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("font selector - use arroys, button or numbers", 160, 80, 20, DARKGRAY); + DrawLine(120, 120, 680, 120, DARKGRAY); + + DrawRectangle(18, positionY, 644, 44, DARKGRAY); + DrawRectangle(20, positionY + 2, 640, 40, LIGHTGRAY); + DrawText(fontNames[currentFont], 30, positionY + 13, 20, BLACK); + DrawText("< >", 610, positionY + 8, 30, BLACK); + + DrawRectangleRec(btnNextRec, btnNextOutColor); + DrawRectangle(675, positionY + 2, 105, 40, btnNextInColor); + DrawText("NEXT", 700, positionY + 13, 20, btnNextOutColor); + + DrawTextEx(fonts[currentFont], text, (Vector2){ screenWidth/2 - textSize.x/2, + 260 + (70 - textSize.y)/2 }, fonts[currentFont].baseSize*3, + 1, colors[currentFont]); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + for (int i = 0; i < 8; i++) UnloadSpriteFont(fonts[i]); // SpriteFont(s) unloading + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +}
\ No newline at end of file diff --git a/examples/others/image_formats_loading.c b/examples/others/image_formats_loading.c new file mode 100644 index 00000000..446f3f3e --- /dev/null +++ b/examples/others/image_formats_loading.c @@ -0,0 +1,244 @@ +/******************************************************************************************* +* +* raylib [textures] example - texture formats loading (compressed and uncompressed) +* +* NOTE: This example requires raylib OpenGL 3.3+ or ES2 versions for compressed textures, +* OpenGL 1.1 does not support compressed textures, only uncompressed ones. +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define NUM_TEXTURES 24 + +typedef enum { + PNG_R8G8B8A8 = 0, + PVR_GRAYSCALE, + PVR_GRAY_ALPHA, + PVR_R5G6B5, + PVR_R5G5B5A1, + PVR_R4G4B4A4, + DDS_R5G6B5, + DDS_R5G5B5A1, + DDS_R4G4B4A4, + DDS_R8G8B8A8, + DDS_DXT1_RGB, + DDS_DXT1_RGBA, + DDS_DXT3_RGBA, + DDS_DXT5_RGBA, + PKM_ETC1_RGB, + PKM_ETC2_RGB, + PKM_ETC2_EAC_RGBA, + KTX_ETC1_RGB, + KTX_ETC2_RGB, + KTX_ETC2_EAC_RGBA, + ASTC_4x4_LDR, + ASTC_8x8_LDR, + PVR_PVRT_RGB, + PVR_PVRT_RGBA + +} TextureFormats; + +static const char *formatText[] = { + "PNG_R8G8B8A8", + "PVR_GRAYSCALE", + "PVR_GRAY_ALPHA", + "PVR_R5G6B5", + "PVR_R5G5B5A1", + "PVR_R4G4B4A4", + "DDS_R5G6B5", + "DDS_R5G5B5A1", + "DDS_R4G4B4A4", + "DDS_R8G8B8A8", + "DDS_DXT1_RGB", + "DDS_DXT1_RGBA", + "DDS_DXT3_RGBA", + "DDS_DXT5_RGBA", + "PKM_ETC1_RGB", + "PKM_ETC2_RGB", + "PKM_ETC2_EAC_RGBA", + "KTX_ETC1_RGB", + "KTX_ETC2_RGB", + "KTX_ETC2_EAC_RGBA", + "ASTC_4x4_LDR", + "ASTC_8x8_LDR", + "PVR_PVRT_RGB", + "PVR_PVRT_RGBA" +}; + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture formats loading"); + + // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) + + Texture2D sonic[NUM_TEXTURES]; + + sonic[PNG_R8G8B8A8] = LoadTexture("resources/formats/sonic.png"); + + // Load UNCOMPRESSED PVR texture data + sonic[PVR_GRAYSCALE] = LoadTexture("resources/formats/sonic_GRAYSCALE.pvr"); + sonic[PVR_GRAY_ALPHA] = LoadTexture("resources/formats/sonic_L8A8.pvr"); + sonic[PVR_R5G6B5] = LoadTexture("resources/formats/sonic_R5G6B5.pvr"); + sonic[PVR_R5G5B5A1] = LoadTexture("resources/formats/sonic_R5G5B5A1.pvr"); + sonic[PVR_R4G4B4A4] = LoadTexture("resources/formats/sonic_R4G4B4A4.pvr"); + + // Load UNCOMPRESSED DDS texture data + sonic[DDS_R5G6B5] = LoadTexture("resources/formats/sonic_R5G6B5.dds"); + sonic[DDS_R5G5B5A1] = LoadTexture("resources/formats/sonic_A1R5G5B5.dds"); + sonic[DDS_R4G4B4A4] = LoadTexture("resources/formats/sonic_A4R4G4B4.dds"); + sonic[DDS_R8G8B8A8] = LoadTexture("resources/formats/sonic_A8R8G8B8.dds"); + + // Load COMPRESSED DXT DDS texture data (if supported) + sonic[DDS_DXT1_RGB] = LoadTexture("resources/formats/sonic_DXT1_RGB.dds"); + sonic[DDS_DXT1_RGBA] = LoadTexture("resources/formats/sonic_DXT1_RGBA.dds"); + sonic[DDS_DXT3_RGBA] = LoadTexture("resources/formats/sonic_DXT3_RGBA.dds"); + sonic[DDS_DXT5_RGBA] = LoadTexture("resources/formats/sonic_DXT5_RGBA.dds"); + + // Load COMPRESSED ETC texture data (if supported) + sonic[PKM_ETC1_RGB] = LoadTexture("resources/formats/sonic_ETC1_RGB.pkm"); + sonic[PKM_ETC2_RGB] = LoadTexture("resources/formats/sonic_ETC2_RGB.pkm"); + sonic[PKM_ETC2_EAC_RGBA] = LoadTexture("resources/formats/sonic_ETC2_EAC_RGBA.pkm"); + + sonic[KTX_ETC1_RGB] = LoadTexture("resources/formats/sonic_ETC1_RGB.ktx"); + sonic[KTX_ETC2_RGB] = LoadTexture("resources/formats/sonic_ETC2_RGB.ktx"); + sonic[KTX_ETC2_EAC_RGBA] = LoadTexture("resources/formats/sonic_ETC2_EAC_RGBA.ktx"); + + // Load COMPRESSED ASTC texture data (if supported) + sonic[ASTC_4x4_LDR] = LoadTexture("resources/formats/sonic_ASTC_4x4_ldr.astc"); + sonic[ASTC_8x8_LDR] = LoadTexture("resources/formats/sonic_ASTC_8x8_ldr.astc"); + + // Load COMPRESSED PVR texture data (if supported) + sonic[PVR_PVRT_RGB] = LoadTexture("resources/formats/sonic_PVRT_RGB.pvr"); + sonic[PVR_PVRT_RGBA] = LoadTexture("resources/formats/sonic_PVRT_RGBA.pvr"); + + int selectedFormat = PNG_R8G8B8A8; + + Rectangle selectRecs[NUM_TEXTURES]; + + for (int i = 0; i < NUM_TEXTURES; i++) + { + if (i < NUM_TEXTURES/2) selectRecs[i] = (Rectangle){ 40, 30 + 32*i, 150, 30 }; + else selectRecs[i] = (Rectangle){ 40 + 152, 30 + 32*(i - NUM_TEXTURES/2), 150, 30 }; + } + + // Texture sizes in KB + float textureSizes[NUM_TEXTURES] = { + 512*512*32/8/1024, //PNG_R8G8B8A8 (32 bpp) + 512*512*8/8/1024, //PVR_GRAYSCALE (8 bpp) + 512*512*16/8/1024, //PVR_GRAY_ALPHA (16 bpp) + 512*512*16/8/1024, //PVR_R5G6B5 (16 bpp) + 512*512*16/8/1024, //PVR_R5G5B5A1 (16 bpp) + 512*512*16/8/1024, //PVR_R4G4B4A4 (16 bpp) + 512*512*16/8/1024, //DDS_R5G6B5 (16 bpp) + 512*512*16/8/1024, //DDS_R5G5B5A1 (16 bpp) + 512*512*16/8/1024, //DDS_R4G4B4A4 (16 bpp) + 512*512*32/8/1024, //DDS_R8G8B8A8 (32 bpp) + 512*512*4/8/1024, //DDS_DXT1_RGB (4 bpp) -Compressed- + 512*512*4/8/1024, //DDS_DXT1_RGBA (4 bpp) -Compressed- + 512*512*8/8/1024, //DDS_DXT3_RGBA (8 bpp) -Compressed- + 512*512*8/8/1024, //DDS_DXT5_RGBA (8 bpp) -Compressed- + 512*512*4/8/1024, //PKM_ETC1_RGB (4 bpp) -Compressed- + 512*512*4/8/1024, //PKM_ETC2_RGB (4 bpp) -Compressed- + 512*512*8/8/1024, //PKM_ETC2_EAC_RGBA (8 bpp) -Compressed- + 512*512*4/8/1024, //KTX_ETC1_RGB (4 bpp) -Compressed- + 512*512*4/8/1024, //KTX_ETC2_RGB (4 bpp) -Compressed- + 512*512*8/8/1024, //KTX_ETC2_EAC_RGBA (8 bpp) -Compressed- + 512*512*8/8/1024, //ASTC_4x4_LDR (8 bpp) -Compressed- + 512*512*2/8/1024, //ASTC_8x8_LDR (2 bpp) -Compressed- + 512*512*4/8/1024, //PVR_PVRT_RGB (4 bpp) -Compressed- + 512*512*4/8/1024, //PVR_PVRT_RGBA (4 bpp) -Compressed- + }; + + 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 + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_DOWN)) + { + selectedFormat++; + if (selectedFormat >= NUM_TEXTURES) selectedFormat = 0; + } + else if (IsKeyPressed(KEY_UP)) + { + selectedFormat--; + if (selectedFormat < 0) selectedFormat = NUM_TEXTURES - 1; + } + else if (IsKeyPressed(KEY_RIGHT)) + { + if (selectedFormat < NUM_TEXTURES/2) selectedFormat += NUM_TEXTURES/2; + } + else if (IsKeyPressed(KEY_LEFT)) + { + if (selectedFormat >= NUM_TEXTURES/2) selectedFormat -= NUM_TEXTURES/2; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw rectangles + for (int i = 0; i < NUM_TEXTURES; i++) + { + if (i == selectedFormat) + { + DrawRectangleRec(selectRecs[i], SKYBLUE); + DrawRectangleLines(selectRecs[i].x, selectRecs[i].y, selectRecs[i].width, selectRecs[i].height, BLUE); + DrawText(formatText[i], selectRecs[i].x + selectRecs[i].width/2 - MeasureText(formatText[i], 10)/2, selectRecs[i].y + 11, 10, DARKBLUE); + } + else + { + DrawRectangleRec(selectRecs[i], LIGHTGRAY); + DrawRectangleLines(selectRecs[i].x, selectRecs[i].y, selectRecs[i].width, selectRecs[i].height, GRAY); + DrawText(formatText[i], selectRecs[i].x + selectRecs[i].width/2 - MeasureText(formatText[i], 10)/2, selectRecs[i].y + 11, 10, DARKGRAY); + } + } + + // Draw selected texture + if (sonic[selectedFormat].id != 0) + { + DrawTexture(sonic[selectedFormat], 350, -10, WHITE); + } + else + { + DrawRectangleLines(488, 165, 200, 110, DARKGRAY); + DrawText("FORMAT", 550, 180, 20, MAROON); + DrawText("NOT SUPPORTED", 500, 210, 20, MAROON); + DrawText("ON YOUR GPU", 520, 240, 20, MAROON); + } + + DrawText("Select texture format (use cursor keys):", 40, 10, 10, DARKGRAY); + DrawText("Required GPU memory size (VRAM):", 40, 427, 10, DARKGRAY); + DrawText(FormatText("%4.0f KB", textureSizes[selectedFormat]), 240, 420, 20, DARKBLUE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + for (int i = 0; i < NUM_TEXTURES; i++) UnloadTexture(sonic[i]); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +}
\ No newline at end of file diff --git a/examples/others/oculus_rift.c b/examples/others/oculus_rift.c new file mode 100644 index 00000000..f1b0bd3b --- /dev/null +++ b/examples/others/oculus_rift.c @@ -0,0 +1,538 @@ +/******************************************************************************************* +* +* raylib [core] example - Oculus Rift CV1 +* +* Compile example using: +* gcc -o $(NAME_PART).exe $(FILE_NAME) -I..\src\external -I..\src\external\OculusSDK\LibOVR\Include / +* -L. -L..\src\external\OculusSDK\LibOVR -lLibOVRRT32_1 -lraylib -lglfw3 -lopengl32 -lgdi32 -std=c99 / +* -Wl,-allow-multiple-definition +* +* #define SUPPORT_OCULUS_RIFT_CV1 / RLGL_OCULUS_SUPPORT +* Enable Oculus Rift CV1 functionality +* +* This example has been created using raylib 1.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "glad.h" // Required for: OpenGL types and functions declarations +#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality + +#include <string.h> // Required for: memset() +#include <stdlib.h> // Required for: exit() +#include <stdio.h> // required for: vfprintf() +#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() + +#define RLGL_OCULUS_SUPPORT // Enable Oculus Rift code +#if defined(RLGL_OCULUS_SUPPORT) + #include "OVR_CAPI_GL.h" // Oculus SDK for OpenGL +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +// TraceLog message types +typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; + +#if defined(RLGL_OCULUS_SUPPORT) +// Oculus buffer type +typedef struct OculusBuffer { + ovrTextureSwapChain textureChain; + GLuint depthId; + GLuint fboId; + int width; + int height; +} OculusBuffer; + +// Oculus mirror texture type +typedef struct OculusMirror { + ovrMirrorTexture texture; + GLuint fboId; + int width; + int height; +} OculusMirror; + +// Oculus layer type +typedef struct OculusLayer { + ovrViewScaleDesc viewScaleDesc; + ovrLayerEyeFov eyeLayer; // layer 0 + //ovrLayerQuad quadLayer; // TODO: layer 1: '2D' quad for GUI + Matrix eyeProjections[2]; + int width; + int height; +} OculusLayer; +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +#if defined(RLGL_OCULUS_SUPPORT) +// OVR device variables +static ovrSession session; // Oculus session (pointer to ovrHmdStruct) +static ovrHmdDesc hmdDesc; // Oculus device descriptor parameters +static ovrGraphicsLuid luid; // Oculus locally unique identifier for the program (64 bit) +static OculusLayer layer; // Oculus drawing layer (similar to photoshop) +static OculusBuffer buffer; // Oculus internal buffers (texture chain and fbo) +static OculusMirror mirror; // Oculus mirror texture and fbo +static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain +#endif + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +#if defined(RLGL_OCULUS_SUPPORT) +static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) +static void CloseOculusDevice(void); // Close Oculus device +static void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking +static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing +static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror + +static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers +static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); // Unload texture required buffers +static OculusMirror LoadOculusMirror(ovrSession session, int width, int height); // Load Oculus mirror buffers +static void UnloadOculusMirror(ovrSession session, OculusMirror mirror); // Unload Oculus mirror buffers +static void BlitOculusMirror(ovrSession session, OculusMirror mirror); // Copy Oculus screen buffer to mirror texture +static OculusLayer InitOculusLayer(ovrSession session); // Init Oculus layer (similar to photoshop) +static Matrix FromOvrMatrix(ovrMatrix4f ovrM); // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct +#endif + +static void TraceLog(int msgType, const char *text, ...); + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 1080; + int screenHeight = 600; + + // NOTE: screenWidth/screenHeight should match VR device aspect ratio + + InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift"); + + bool vrDeviceReady = InitOculusDevice(); // Init VR device Oculus Rift CV1 + + if (!vrDeviceReady) InitVrSimulator(HMD_OCULUS_RIFT_CV1); // Init VR simulator if device fails + + // Define the camera to look into our 3d world + Camera camera; + camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 60.0f; // Camera field-of-view Y + + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; + + SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode + + SetTargetFPS(90); // Set our game to run at 90 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (!vrDeviceReady) UpdateCamera(&camera); // Update camera (simulator mode) + else UpdateOculusTracking(&camera); // Update camera with device tracking data + + if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); // Toggle VR mode + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (vrDeviceReady) BeginOculusDrawing(); + else BeginVrDrawing(); + + Begin3dMode(camera); + + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); + + DrawGrid(40, 1.0f); + + End3dMode(); + + if (vrDeviceReady) EndOculusDrawing(); + else EndVrDrawing(); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + if (vrDeviceReady) CloseOculusDevice(); + else CloseVrSimulator(); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +#if defined(RLGL_OCULUS_SUPPORT) +// Set internal projection and modelview matrix depending on eyes tracking data +static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) +{ + Matrix eyeProjection = matProjection; + Matrix eyeModelView = matModelView; + + glViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, + layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h); + + Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, + layer.eyeLayer.RenderPose[eye].Orientation.y, + layer.eyeLayer.RenderPose[eye].Orientation.z, + layer.eyeLayer.RenderPose[eye].Orientation.w }; + QuaternionInvert(&eyeRenderPose); + Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); + Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, + -layer.eyeLayer.RenderPose[eye].Position.y, + -layer.eyeLayer.RenderPose[eye].Position.z); + + Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement + eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement + + eyeProjection = layer.eyeProjections[eye]; +} + +// Initialize Oculus device (returns true if success) +static bool InitOculusDevice(void) +{ + bool oculusReady = false; + + ovrResult result = ovr_Initialize(NULL); + + if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device"); + else + { + result = ovr_Create(&session, &luid); + if (OVR_FAILURE(result)) + { + TraceLog(WARNING, "OVR: Could not create Oculus session"); + ovr_Shutdown(); + } + else + { + hmdDesc = ovr_GetHmdDesc(session); + + TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName); + TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); + TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId); + TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); + //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber); + TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); + + // NOTE: Oculus mirror is set to defined screenWidth and screenHeight... + // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2) + + // Initialize Oculus Buffers + layer = InitOculusLayer(session); + buffer = LoadOculusBuffer(session, layer.width, layer.height); + mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); // NOTE: hardcoded... + layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); + + // Recenter OVR tracking origin + ovr_RecenterTrackingOrigin(session); + + oculusReady = true; + } + } + + return oculusReady; +} + +// Close Oculus device (and unload buffers) +static void CloseOculusDevice(void) +{ + UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer + UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers + + ovr_Destroy(session); // Free Oculus session data + ovr_Shutdown(); // Close Oculus device connection +} + +// Update Oculus head position-orientation tracking +static void UpdateOculusTracking(Camera *camera) +{ + frameIndex++; + + ovrPosef eyePoses[2]; + ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); + + layer.eyeLayer.RenderPose[0] = eyePoses[0]; + layer.eyeLayer.RenderPose[1] = eyePoses[1]; + + // TODO: Update external camera with eyePoses data (position, orientation) + // NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later + // it will be useful for the user to draw, lets say, billboards oriented to camera + + // Get session status information + ovrSessionStatus sessionStatus; + ovr_GetSessionStatus(session, &sessionStatus); + + if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); + if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); + //if (sessionStatus.HmdPresent) // HMD is present. + //if (sessionStatus.DisplayLost) // HMD was unplugged or the display driver was manually disabled or encountered a TDR. + //if (sessionStatus.HmdMounted) // HMD is on the user's head. + //if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD. +} + +// Setup Oculus buffers for drawing +static void BeginOculusDrawing(void) +{ + GLuint currentTexId; + int currentIndex; + + ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex); + ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0); + //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded +} + +// Finish Oculus drawing and blit framebuffer to mirror +static void EndOculusDrawing(void) +{ + // Unbind current framebuffer (Oculus buffer) + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + ovr_CommitTextureSwapChain(session, buffer.textureChain); + + ovrLayerHeader *layers = &layer.eyeLayer.Header; + ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1); + + // Blit mirror texture to back buffer + BlitOculusMirror(session, mirror); +} + +// Load Oculus required buffers: texture-swap-chain, fbo, texture-depth +static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) +{ + OculusBuffer buffer; + buffer.width = width; + buffer.height = height; + + // Create OVR texture chain + ovrTextureSwapChainDesc desc = {}; + desc.Type = ovrTexture_2D; + desc.ArraySize = 1; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; // Requires glEnable(GL_FRAMEBUFFER_SRGB); + desc.SampleCount = 1; + desc.StaticImage = ovrFalse; + + ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain); + + if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer"); + + int textureCount = 0; + ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount); + + if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures"); + + for (int i = 0; i < textureCount; ++i) + { + GLuint chainTexId; + ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, i, &chainTexId); + glBindTexture(GL_TEXTURE_2D, chainTexId); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glBindTexture(GL_TEXTURE_2D, 0); + + /* + // Setup framebuffer object (using depth texture) + glGenFramebuffers(1, &buffer.fboId); + glGenTextures(1, &buffer.depthId); + glBindTexture(GL_TEXTURE_2D, buffer.depthId); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + */ + + // Setup framebuffer object (using depth renderbuffer) + glGenFramebuffers(1, &buffer.fboId); + glGenRenderbuffers(1, &buffer.depthId); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId); + glBindRenderbuffer(GL_RENDERBUFFER, buffer.depthId); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, buffer.width, buffer.height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer.depthId); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + return buffer; +} + +// Unload texture required buffers +static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer) +{ + if (buffer.textureChain) + { + ovr_DestroyTextureSwapChain(session, buffer.textureChain); + buffer.textureChain = NULL; + } + + if (buffer.depthId != 0) glDeleteTextures(1, &buffer.depthId); + if (buffer.fboId != 0) glDeleteFramebuffers(1, &buffer.fboId); +} + +// Load Oculus mirror buffers +static OculusMirror LoadOculusMirror(ovrSession session, int width, int height) +{ + OculusMirror mirror; + mirror.width = width; + mirror.height = height; + + ovrMirrorTextureDesc mirrorDesc; + memset(&mirrorDesc, 0, sizeof(mirrorDesc)); + mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + mirrorDesc.Width = mirror.width; + mirrorDesc.Height = mirror.height; + + if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture"); + + glGenFramebuffers(1, &mirror.fboId); + + return mirror; +} + +// Unload Oculus mirror buffers +static void UnloadOculusMirror(ovrSession session, OculusMirror mirror) +{ + if (mirror.fboId != 0) glDeleteFramebuffers(1, &mirror.fboId); + if (mirror.texture) ovr_DestroyMirrorTexture(session, mirror.texture); +} + +// Copy Oculus screen buffer to mirror texture +static void BlitOculusMirror(ovrSession session, OculusMirror mirror) +{ + GLuint mirrorTextureId; + + ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0); +#if defined(GRAPHICS_API_OPENGL_33) + // NOTE: glBlitFramebuffer() requires extension: GL_EXT_framebuffer_blit (not available in OpenGL ES 2.0) + glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); +#endif + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +} + +// Init Oculus layer (similar to photoshop) +static OculusLayer InitOculusLayer(ovrSession session) +{ + OculusLayer layer = { 0 }; + + layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; + + memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov)); + layer.eyeLayer.Header.Type = ovrLayerType_EyeFov; + layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + + ovrEyeRenderDesc eyeRenderDescs[2]; + + for (int eye = 0; eye < 2; eye++) + { + eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]); + ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 10000.0f, ovrProjection_None); //ovrProjection_ClipRangeOpenGL); + layer.eyeProjections[eye] = FromOvrMatrix(ovrPerspectiveProjection); // NOTE: struct ovrMatrix4f { float M[4][4] } --> struct Matrix + + layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset; + layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov; + + ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f); + layer.eyeLayer.Viewport[eye].Size = eyeSize; + layer.eyeLayer.Viewport[eye].Pos.x = layer.width; + layer.eyeLayer.Viewport[eye].Pos.y = 0; + + layer.height = eyeSize.h; //std::max(renderTargetSize.y, (uint32_t)eyeSize.h); + layer.width += eyeSize.w; + } + + return layer; +} + +// Convert from Oculus ovrMatrix4f struct to raymath Matrix struct +static Matrix FromOvrMatrix(ovrMatrix4f ovrmat) +{ + Matrix rmat; + + rmat.m0 = ovrmat.M[0][0]; + rmat.m1 = ovrmat.M[1][0]; + rmat.m2 = ovrmat.M[2][0]; + rmat.m3 = ovrmat.M[3][0]; + rmat.m4 = ovrmat.M[0][1]; + rmat.m5 = ovrmat.M[1][1]; + rmat.m6 = ovrmat.M[2][1]; + rmat.m7 = ovrmat.M[3][1]; + rmat.m8 = ovrmat.M[0][2]; + rmat.m9 = ovrmat.M[1][2]; + rmat.m10 = ovrmat.M[2][2]; + rmat.m11 = ovrmat.M[3][2]; + rmat.m12 = ovrmat.M[0][3]; + rmat.m13 = ovrmat.M[1][3]; + rmat.m14 = ovrmat.M[2][3]; + rmat.m15 = ovrmat.M[3][3]; + + MatrixTranspose(&rmat); + + return rmat; +} +#endif + +// Output a trace log message +// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning +static void TraceLog(int msgType, const char *text, ...) +{ + va_list args; + 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: fprintf(stdout, "DEBUG: "); break; + default: break; + } + + vfprintf(stdout, text, args); + fprintf(stdout, "\n"); + + va_end(args); + + if (msgType == ERROR) exit(1); +} + diff --git a/examples/others/particles_trail_blending.c b/examples/others/particles_trail_blending.c new file mode 100644 index 00000000..0b47c790 --- /dev/null +++ b/examples/others/particles_trail_blending.c @@ -0,0 +1,135 @@ +/******************************************************************************************* +* +* raylib example - particles trail blending +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define MAX_PARTICLES 200 + +// Particle structure with basic data +typedef struct { + Vector2 position; + Color color; + float alpha; + float size; + float rotation; + bool active; // NOTE: Use it to activate/deactive particle +} Particle; + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles trail blending"); + + // Particles pool, reuse them! + Particle mouseTail[MAX_PARTICLES]; + + // Initialize particles + for (int i = 0; i < MAX_PARTICLES; i++) + { + mouseTail[i].position = (Vector2){ 0, 0 }; + mouseTail[i].color = (Color){ GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }; + mouseTail[i].alpha = 1.0f; + mouseTail[i].size = (float)GetRandomValue(1, 30)/20.0f; + mouseTail[i].rotation = GetRandomValue(0, 360); + mouseTail[i].active = false; + } + + float gravity = 3.0f; + + Texture2D smoke = LoadTexture("resources/smoke.png"); + + int blending = BLEND_ALPHA; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + // Activate one particle every frame and Update active particles + // NOTE: Particles initial position should be mouse position when activated + // NOTE: Particles fall down with gravity and rotation... and disappear after 2 seconds (alpha = 0) + // NOTE: When a particle disappears, active = false and it can be reused. + for (int i = 0; i < MAX_PARTICLES; i++) + { + if (!mouseTail[i].active) + { + mouseTail[i].active = true; + mouseTail[i].alpha = 1.0f; + mouseTail[i].position = GetMousePosition(); + i = MAX_PARTICLES; + } + } + + for (int i = 0; i < MAX_PARTICLES; i++) + { + if (mouseTail[i].active) + { + mouseTail[i].position.y += gravity; + mouseTail[i].alpha -= 0.01f; + + if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false; + + mouseTail[i].rotation += 5.0f; + } + } + + if (IsKeyPressed(KEY_SPACE)) + { + if (blending == BLEND_ALPHA) blending = BLEND_ADDITIVE; + else blending = BLEND_ALPHA; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(DARKGRAY); + + BeginBlendMode(blending); + + // Draw active particles + for (int i = 0; i < MAX_PARTICLES; i++) + { + if (mouseTail[i].active) DrawTexturePro(smoke, (Rectangle){ 0, 0, smoke.width, smoke.height }, + (Rectangle){ mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size }, + (Vector2){ smoke.width*mouseTail[i].size/2, smoke.height*mouseTail[i].size/2 }, mouseTail[i].rotation, + Fade(mouseTail[i].color, mouseTail[i].alpha)); + } + + EndBlendMode(); + + DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK); + + if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK); + else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(smoke); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +}
\ No newline at end of file diff --git a/examples/others/resources/formats/sonic.png b/examples/others/resources/formats/sonic.png Binary files differnew file mode 100644 index 00000000..7a096847 --- /dev/null +++ b/examples/others/resources/formats/sonic.png diff --git a/examples/others/resources/formats/sonic_A1R5G5B5.dds b/examples/others/resources/formats/sonic_A1R5G5B5.dds Binary files differnew file mode 100644 index 00000000..5e2347db --- /dev/null +++ b/examples/others/resources/formats/sonic_A1R5G5B5.dds diff --git a/examples/others/resources/formats/sonic_A4R4G4B4.dds b/examples/others/resources/formats/sonic_A4R4G4B4.dds Binary files differnew file mode 100644 index 00000000..c5ccaf0c --- /dev/null +++ b/examples/others/resources/formats/sonic_A4R4G4B4.dds diff --git a/examples/others/resources/formats/sonic_A8R8G8B8.dds b/examples/others/resources/formats/sonic_A8R8G8B8.dds Binary files differnew file mode 100644 index 00000000..fb71b7be --- /dev/null +++ b/examples/others/resources/formats/sonic_A8R8G8B8.dds diff --git a/examples/others/resources/formats/sonic_ASTC_4x4_ldr.astc b/examples/others/resources/formats/sonic_ASTC_4x4_ldr.astc Binary files differnew file mode 100644 index 00000000..9a98d9a0 --- /dev/null +++ b/examples/others/resources/formats/sonic_ASTC_4x4_ldr.astc diff --git a/examples/others/resources/formats/sonic_ASTC_8x8_ldr.astc b/examples/others/resources/formats/sonic_ASTC_8x8_ldr.astc Binary files differnew file mode 100644 index 00000000..360a264a --- /dev/null +++ b/examples/others/resources/formats/sonic_ASTC_8x8_ldr.astc diff --git a/examples/others/resources/formats/sonic_DXT1_RGB.dds b/examples/others/resources/formats/sonic_DXT1_RGB.dds Binary files differnew file mode 100644 index 00000000..9d0b4598 --- /dev/null +++ b/examples/others/resources/formats/sonic_DXT1_RGB.dds diff --git a/examples/others/resources/formats/sonic_DXT1_RGBA.dds b/examples/others/resources/formats/sonic_DXT1_RGBA.dds Binary files differnew file mode 100644 index 00000000..102bae7f --- /dev/null +++ b/examples/others/resources/formats/sonic_DXT1_RGBA.dds diff --git a/examples/others/resources/formats/sonic_DXT3_RGBA.dds b/examples/others/resources/formats/sonic_DXT3_RGBA.dds Binary files differnew file mode 100644 index 00000000..46d965cb --- /dev/null +++ b/examples/others/resources/formats/sonic_DXT3_RGBA.dds diff --git a/examples/others/resources/formats/sonic_DXT5_RGBA.dds b/examples/others/resources/formats/sonic_DXT5_RGBA.dds Binary files differnew file mode 100644 index 00000000..b3a59a79 --- /dev/null +++ b/examples/others/resources/formats/sonic_DXT5_RGBA.dds diff --git a/examples/others/resources/formats/sonic_ETC1_RGB.ktx b/examples/others/resources/formats/sonic_ETC1_RGB.ktx Binary files differnew file mode 100644 index 00000000..66241b9d --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC1_RGB.ktx diff --git a/examples/others/resources/formats/sonic_ETC1_RGB.pkm b/examples/others/resources/formats/sonic_ETC1_RGB.pkm Binary files differnew file mode 100644 index 00000000..c6fc6df4 --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC1_RGB.pkm diff --git a/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.ktx b/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.ktx Binary files differnew file mode 100644 index 00000000..b01812cb --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.ktx diff --git a/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.old.pkm b/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.old.pkm Binary files differnew file mode 100644 index 00000000..61ac48ce --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.old.pkm diff --git a/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.pkm b/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.pkm Binary files differnew file mode 100644 index 00000000..61ac48ce --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC2_EAC_RGBA.pkm diff --git a/examples/others/resources/formats/sonic_ETC2_RGB.ktx b/examples/others/resources/formats/sonic_ETC2_RGB.ktx Binary files differnew file mode 100644 index 00000000..7f1207f7 --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC2_RGB.ktx diff --git a/examples/others/resources/formats/sonic_ETC2_RGB.pkm b/examples/others/resources/formats/sonic_ETC2_RGB.pkm Binary files differnew file mode 100644 index 00000000..f290f019 --- /dev/null +++ b/examples/others/resources/formats/sonic_ETC2_RGB.pkm diff --git a/examples/others/resources/formats/sonic_GRAYSCALE.pvr b/examples/others/resources/formats/sonic_GRAYSCALE.pvr Binary files differnew file mode 100644 index 00000000..d31e2651 --- /dev/null +++ b/examples/others/resources/formats/sonic_GRAYSCALE.pvr diff --git a/examples/others/resources/formats/sonic_L8A8.pvr b/examples/others/resources/formats/sonic_L8A8.pvr Binary files differnew file mode 100644 index 00000000..ccf5932e --- /dev/null +++ b/examples/others/resources/formats/sonic_L8A8.pvr diff --git a/examples/others/resources/formats/sonic_PVRT_RGB.pvr b/examples/others/resources/formats/sonic_PVRT_RGB.pvr Binary files differnew file mode 100644 index 00000000..22f3f66a --- /dev/null +++ b/examples/others/resources/formats/sonic_PVRT_RGB.pvr diff --git a/examples/others/resources/formats/sonic_PVRT_RGBA.pvr b/examples/others/resources/formats/sonic_PVRT_RGBA.pvr Binary files differnew file mode 100644 index 00000000..feb9aeaf --- /dev/null +++ b/examples/others/resources/formats/sonic_PVRT_RGBA.pvr diff --git a/examples/others/resources/formats/sonic_PVRT_RGBA_2bpp.pvr b/examples/others/resources/formats/sonic_PVRT_RGBA_2bpp.pvr Binary files differnew file mode 100644 index 00000000..9147e1bb --- /dev/null +++ b/examples/others/resources/formats/sonic_PVRT_RGBA_2bpp.pvr diff --git a/examples/others/resources/formats/sonic_PVRT_RGB_2bpp.pvr b/examples/others/resources/formats/sonic_PVRT_RGB_2bpp.pvr Binary files differnew file mode 100644 index 00000000..2a8aea8c --- /dev/null +++ b/examples/others/resources/formats/sonic_PVRT_RGB_2bpp.pvr diff --git a/examples/others/resources/formats/sonic_R4G4B4A4.pvr b/examples/others/resources/formats/sonic_R4G4B4A4.pvr Binary files differnew file mode 100644 index 00000000..3f7368a3 --- /dev/null +++ b/examples/others/resources/formats/sonic_R4G4B4A4.pvr diff --git a/examples/others/resources/formats/sonic_R5G5B5A1.pvr b/examples/others/resources/formats/sonic_R5G5B5A1.pvr Binary files differnew file mode 100644 index 00000000..c7fa098d --- /dev/null +++ b/examples/others/resources/formats/sonic_R5G5B5A1.pvr diff --git a/examples/others/resources/formats/sonic_R5G6B5.dds b/examples/others/resources/formats/sonic_R5G6B5.dds Binary files differnew file mode 100644 index 00000000..217da954 --- /dev/null +++ b/examples/others/resources/formats/sonic_R5G6B5.dds diff --git a/examples/others/resources/formats/sonic_R5G6B5.pvr b/examples/others/resources/formats/sonic_R5G6B5.pvr Binary files differnew file mode 100644 index 00000000..9bb8320e --- /dev/null +++ b/examples/others/resources/formats/sonic_R5G6B5.pvr diff --git a/examples/others/resources/formats/sonic_R8G8B8.pvr b/examples/others/resources/formats/sonic_R8G8B8.pvr Binary files differnew file mode 100644 index 00000000..072cf3ef --- /dev/null +++ b/examples/others/resources/formats/sonic_R8G8B8.pvr diff --git a/examples/others/resources/formats/sonic_R8G8B8A8.pvr b/examples/others/resources/formats/sonic_R8G8B8A8.pvr Binary files differnew file mode 100644 index 00000000..f82534f9 --- /dev/null +++ b/examples/others/resources/formats/sonic_R8G8B8A8.pvr diff --git a/examples/others/resources/formats/sonic_R8G8B8A8.raw b/examples/others/resources/formats/sonic_R8G8B8A8.raw Binary files differnew file mode 100644 index 00000000..fc5858e7 --- /dev/null +++ b/examples/others/resources/formats/sonic_R8G8B8A8.raw diff --git a/examples/others/resources/shaders/glsl100/standard.fs b/examples/others/resources/shaders/glsl100/standard.fs new file mode 100644 index 00000000..fe604e2a --- /dev/null +++ b/examples/others/resources/shaders/glsl100/standard.fs @@ -0,0 +1,152 @@ +#version 100 + +precision mediump float; + +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +uniform sampler2D texture0; +uniform sampler2D texture1; +uniform sampler2D texture2; + +uniform vec4 colAmbient; +uniform vec4 colDiffuse; +uniform vec4 colSpecular; +uniform float glossiness; + +uniform int useNormal; +uniform int useSpecular; + +uniform mat4 modelMatrix; +uniform vec3 viewDir; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 direction; + vec4 diffuse; + float intensity; + float radius; + float coneAngle; +}; + +const int maxLights = 8; +uniform Light lights[maxLights]; + +vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s) +{ + vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0)); + vec3 surfaceToLight = l.position - surfacePos; + + // Diffuse shading + float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0); + float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity; + + // Specular shading + float spec = 0.0; + if (diff > 0.0) + { + vec3 h = normalize(-l.direction + v); + spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s; + } + + return (diff*l.diffuse.rgb + spec*colSpecular.rgb); +} + +vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s) +{ + vec3 lightDir = normalize(-l.direction); + + // Diffuse shading + float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; + + // Specular shading + float spec = 0.0; + if (diff > 0.0) + { + vec3 h = normalize(lightDir + v); + spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s; + } + + // Combine results + return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); +} + +vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s) +{ + vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); + vec3 lightToSurface = normalize(surfacePos - l.position); + vec3 lightDir = normalize(-l.direction); + + // Diffuse shading + float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; + + // Spot attenuation + float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0); + attenuation = dot(lightToSurface, -lightDir); + + float lightToSurfaceAngle = degrees(acos(attenuation)); + if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; + + float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle; + + // Combine diffuse and attenuation + float diffAttenuation = diff*attenuation; + + // Specular shading + float spec = 0.0; + if (diffAttenuation > 0.0) + { + vec3 h = normalize(lightDir + v); + spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s; + } + + return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); +} + +void main() +{ + // Calculate fragment normal in screen space + // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale) + mat3 normalMatrix = mat3(modelMatrix); + vec3 normal = normalize(normalMatrix*fragNormal); + + // Normalize normal and view direction vectors + vec3 n = normalize(normal); + vec3 v = normalize(viewDir); + + // Calculate diffuse texture color fetching + vec4 texelColor = texture2D(texture0, fragTexCoord); + vec3 lighting = colAmbient.rgb; + + // Calculate normal texture color fetching or set to maximum normal value by default + if (useNormal == 1) + { + n *= texture2D(texture1, fragTexCoord).rgb; + n = normalize(n); + } + + // Calculate specular texture color fetching or set to maximum specular value by default + float spec = 1.0; + if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r; + + for (int i = 0; i < maxLights; i++) + { + // Check if light is enabled + if (lights[i].enabled == 1) + { + // Calculate lighting based on light type + if(lights[i].type == 0) lighting += ComputeLightPoint(lights[i], n, v, spec); + else if(lights[i].type == 1) lighting += ComputeLightDirectional(lights[i], n, v, spec); + else if(lights[i].type == 2) lighting += ComputeLightSpot(lights[i], n, v, spec); + + // NOTE: It seems that too many ComputeLight*() operations inside for loop breaks the shader on RPI + } + } + + // Calculate final fragment color + gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); +} diff --git a/examples/others/resources/shaders/glsl100/standard.vs b/examples/others/resources/shaders/glsl100/standard.vs new file mode 100644 index 00000000..49c5a3eb --- /dev/null +++ b/examples/others/resources/shaders/glsl100/standard.vs @@ -0,0 +1,23 @@ +#version 100 + +attribute vec3 vertexPosition; +attribute vec3 vertexNormal; +attribute vec2 vertexTexCoord; +attribute vec4 vertexColor; + +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +uniform mat4 mvpMatrix; + +void main() +{ + fragPosition = vertexPosition; + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + fragNormal = vertexNormal; + + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); +}
\ No newline at end of file diff --git a/examples/others/resources/shaders/glsl330/standard.fs b/examples/others/resources/shaders/glsl330/standard.fs new file mode 100644 index 00000000..0d461484 --- /dev/null +++ b/examples/others/resources/shaders/glsl330/standard.fs @@ -0,0 +1,150 @@ +#version 330 + +in vec3 fragPosition; +in vec2 fragTexCoord; +in vec4 fragColor; +in vec3 fragNormal; + +out vec4 finalColor; + +uniform sampler2D texture0; +uniform sampler2D texture1; +uniform sampler2D texture2; + +uniform vec4 colAmbient; +uniform vec4 colDiffuse; +uniform vec4 colSpecular; +uniform float glossiness; + +uniform int useNormal; +uniform int useSpecular; + +uniform mat4 modelMatrix; +uniform vec3 viewDir; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 direction; + vec4 diffuse; + float intensity; + float radius; + float coneAngle; +}; + +const int maxLights = 8; +uniform Light lights[maxLights]; + +vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s) +{ + vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); + vec3 surfaceToLight = l.position - surfacePos; + + // Diffuse shading + float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0); + float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity; + + // Specular shading + float spec = 0.0; + if (diff > 0.0) + { + vec3 h = normalize(-l.direction + v); + spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s; + } + + return (diff*l.diffuse.rgb + spec*colSpecular.rgb); +} + +vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s) +{ + vec3 lightDir = normalize(-l.direction); + + // Diffuse shading + float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; + + // Specular shading + float spec = 0.0; + if (diff > 0.0) + { + vec3 h = normalize(lightDir + v); + spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s; + } + + // Combine results + return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); +} + +vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s) +{ + vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); + vec3 lightToSurface = normalize(surfacePos - l.position); + vec3 lightDir = normalize(-l.direction); + + // Diffuse shading + float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; + + // Spot attenuation + float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0); + attenuation = dot(lightToSurface, -lightDir); + + float lightToSurfaceAngle = degrees(acos(attenuation)); + if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; + + float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle; + + // Combine diffuse and attenuation + float diffAttenuation = diff*attenuation; + + // Specular shading + float spec = 0.0; + if (diffAttenuation > 0.0) + { + vec3 h = normalize(lightDir + v); + spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s; + } + + return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); +} + +void main() +{ + // Calculate fragment normal in screen space + // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale) + mat3 normalMatrix = mat3(modelMatrix); + vec3 normal = normalize(normalMatrix*fragNormal); + + // Normalize normal and view direction vectors + vec3 n = normalize(normal); + vec3 v = normalize(viewDir); + + // Calculate diffuse texture color fetching + vec4 texelColor = texture(texture0, fragTexCoord); + vec3 lighting = colAmbient.rgb; + + // Calculate normal texture color fetching or set to maximum normal value by default + if (useNormal == 1) + { + n *= texture(texture1, fragTexCoord).rgb; + n = normalize(n); + } + + // Calculate specular texture color fetching or set to maximum specular value by default + float spec = 1.0; + if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r; + + for (int i = 0; i < maxLights; i++) + { + // Check if light is enabled + if (lights[i].enabled == 1) + { + // Calculate lighting based on light type + if (lights[i].type == 0) lighting += ComputeLightPoint(lights[i], n, v, spec); + else if (lights[i].type == 1) lighting += ComputeLightDirectional(lights[i], n, v, spec); + else if (lights[i].type == 2) lighting += ComputeLightSpot(lights[i], n, v, spec); + } + } + + // Calculate final fragment color + finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); +} diff --git a/examples/others/resources/shaders/glsl330/standard.vs b/examples/others/resources/shaders/glsl330/standard.vs new file mode 100644 index 00000000..fc0a5ff4 --- /dev/null +++ b/examples/others/resources/shaders/glsl330/standard.vs @@ -0,0 +1,23 @@ +#version 330 + +in vec3 vertexPosition; +in vec3 vertexNormal; +in vec2 vertexTexCoord; +in vec4 vertexColor; + +out vec3 fragPosition; +out vec2 fragTexCoord; +out vec4 fragColor; +out vec3 fragNormal; + +uniform mat4 mvpMatrix; + +void main() +{ + fragPosition = vertexPosition; + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + fragNormal = vertexNormal; + + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); +}
\ No newline at end of file diff --git a/examples/others/rlgl_oculus_rift.c b/examples/others/rlgl_oculus_rift.c deleted file mode 100644 index 30ef6f3b..00000000 --- a/examples/others/rlgl_oculus_rift.c +++ /dev/null @@ -1,393 +0,0 @@ -/******************************************************************************************* -* -* raylib [rlgl] example - Oculus minimum sample -* -* NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support, -* OpenGL 1.1 does not support shaders but it can also be used. -* -* Compile rlgl module using: -* gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33 -DRLGL_OCULUS_SUPPORT -* -* NOTE 1: rlgl module requires the following header-only files: -* external/glad.h - OpenGL extensions loader (stripped to only required extensions) -* shader_standard.h - Standard shader for materials and lighting -* shader_distortion.h - Distortion shader for VR -* raymath.h - Vector and matrix math functions -* -* NOTE 2: rlgl requires LibOVR (Oculus PC SDK) to support Oculus Rift CV1 -* -* Compile example using: -* gcc -o rlgl_oculus_rift.exe rlgl_oculus_rift.c rlgl.o -L. -lLibOVRRT32_1 -lglfw3 -lopengl32 -lgdi32 -std=c99 -* -* NOTE: Example must be linked against LibOVRRT32_1.dll that comes with Oculus Rift runtime. -* -* This example has been created using raylib 1.5 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include <stdlib.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include <GLFW/glfw3.h> // Windows/Context and inputs management - -#define RLGL_STANDALONE -#include "rlgl.h" // rlgl library: OpenGL 1.1 immediate-mode style coding - -#define RED (Color){ 230, 41, 55, 255 } // Red -#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo) -#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray - -//---------------------------------------------------------------------------------- -// Module specific Functions Declaration -//---------------------------------------------------------------------------------- -static void ErrorCallback(int error, const char* description); -static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); - -// Drawing functions (uses rlgl functionality) -static void DrawGrid(int slices, float spacing); -static void DrawCube(Vector3 position, float width, float height, float length, Color color); -static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); -static void DrawRectangleV(Vector2 position, Vector2 size, Color color); - -//---------------------------------------------------------------------------------- -// Main Entry point -//---------------------------------------------------------------------------------- -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 1080; // Mirror screen width (set to hmdDesc.Resolution.w/2) - int screenHeight = 600; // Mirror screen height (set to hmdDesc.Resolution.h/2) - - // NOTE: Mirror screen size can be set to any desired resolution! - - // GLFW3 Initialization + OpenGL 3.3 Context + Extensions - //-------------------------------------------------------- - glfwSetErrorCallback(ErrorCallback); - - if (!glfwInit()) - { - TraceLog(WARNING, "GLFW3: Can not initialize GLFW"); - return 1; - } - else TraceLog(INFO, "GLFW3: GLFW initialized successfully"); - - glfwWindowHint(GLFW_SAMPLES, 4); - glfwWindowHint(GLFW_DEPTH_BITS, 16); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); - - GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl oculus rift", NULL, NULL); - - if (!window) - { - glfwTerminate(); - return 2; - } - else TraceLog(INFO, "GLFW3: Window created successfully"); - - glfwSetKeyCallback(window, KeyCallback); - - glfwMakeContextCurrent(window); - glfwSwapInterval(0); - - // Load OpenGL 3.3 supported extensions - rlglLoadExtensions(glfwGetProcAddress); - //-------------------------------------------------------- - - // Initialize OpenGL context (states and resources) - rlglInit(screenWidth, screenHeight); - - rlClearColor(245, 245, 245, 255); // Define clear color - rlEnableDepthTest(); // Enable DEPTH_TEST for 3D - - // Define custom camera to initialize projection and view matrices - Camera camera; - camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - - // Initialize viewport and internal projection/modelview matrices - rlViewport(0, 0, screenWidth, screenHeight); - rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix - rlLoadIdentity(); // Reset current matrix (PROJECTION) - - // Setup perspective projection - float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.01*tan(camera.fovy*PI/360.0); - double right = top*aspect; - rlFrustum(-right, right, -top, top, 0.01, 1000.0); - - rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix - 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) - - InitOculusDevice(); // Initialize Oculus Rift CV1 - - Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!glfwWindowShouldClose(window)) - { - // Update - //---------------------------------------------------------------------------------- - UpdateOculusTracking(&camera); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginOculusDrawing(); - - rlClearScreenBuffers(); // Clear current framebuffer(s) - - DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); - DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, RAYWHITE); - DrawGrid(10, 1.0f); - - // NOTE: Internal buffers drawing (3D data) - rlglDraw(); - - EndOculusDrawing(); - - glfwSwapBuffers(window); - glfwPollEvents(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseOculusDevice(); // Close Oculus device and clear resources - - rlglClose(); // Unload rlgl internal buffers and default shader/texture - - glfwDestroyWindow(window); // Close window - glfwTerminate(); // Free GLFW3 resources - //-------------------------------------------------------------------------------------- - - return 0; -} - -//---------------------------------------------------------------------------------- -// Module specific Functions Definitions -//---------------------------------------------------------------------------------- - -// GLFW3: Error callback -static void ErrorCallback(int error, const char* description) -{ - TraceLog(ERROR, description); -} - -// GLFW3: Keyboard callback -static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - { - glfwSetWindowShouldClose(window, GL_TRUE); - } -} - -// Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally) -static void DrawRectangleV(Vector2 position, Vector2 size, Color color) -{ - rlBegin(RL_TRIANGLES); - rlColor4ub(color.r, color.g, color.b, color.a); - - rlVertex2i(position.x, position.y); - rlVertex2i(position.x, position.y + size.y); - rlVertex2i(position.x + size.x, position.y + size.y); - - rlVertex2i(position.x, position.y); - rlVertex2i(position.x + size.x, position.y + size.y); - rlVertex2i(position.x + size.x, position.y); - rlEnd(); -} - -// Draw a grid centered at (0, 0, 0) -static void DrawGrid(int slices, float spacing) -{ - int halfSlices = slices / 2; - - rlBegin(RL_LINES); - for(int i = -halfSlices; i <= halfSlices; i++) - { - if (i == 0) - { - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - } - else - { - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - } - - rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); - rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing); - - rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing); - rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing); - } - rlEnd(); -} - -// Draw cube -// NOTE: Cube position is the center position -void DrawCube(Vector3 position, float width, float height, float length, Color color) -{ - float x = 0.0f; - float y = 0.0f; - float z = 0.0f; - - rlPushMatrix(); - - // NOTE: Be careful! Function order matters (rotate -> scale -> translate) - 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); - - // 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 - - // 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 - - // 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 - - // 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(); -} - -// Draw cube wires -void DrawCubeWires(Vector3 position, float width, float height, float length, Color color) -{ - float x = 0.0f; - float y = 0.0f; - float z = 0.0f; - - rlPushMatrix(); - - rlTranslatef(position.x, position.y, position.z); - //rlRotatef(45, 0, 1, 0); - - rlBegin(RL_LINES); - rlColor4ub(color.r, color.g, color.b, color.a); - - // Front Face ----------------------------------------------------- - // Bottom Line - rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right - - // Left Line - rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right - - // Top Line - rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - - // Right Line - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left - - // Back Face ------------------------------------------------------ - // Bottom Line - rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - - // Left Line - rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right - - // Top Line - rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left - - // Right Line - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left - - // Top Face ------------------------------------------------------- - // Left Line - rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Front - rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Back - - // Right Line - rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Front - rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Back - - // Bottom Face --------------------------------------------------- - // Left Line - rlVertex3f(x-width/2, y-height/2, z+length/2); // Top Left Front - rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left Back - - // Right Line - rlVertex3f(x+width/2, y-height/2, z+length/2); // Top Right Front - rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right Back - rlEnd(); - rlPopMatrix(); -}
\ No newline at end of file diff --git a/examples/others/standard_lighting.c b/examples/others/standard_lighting.c new file mode 100644 index 00000000..14fda32e --- /dev/null +++ b/examples/others/standard_lighting.c @@ -0,0 +1,483 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Standard lighting (materials and lights) +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example +* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders +* raylib comes with shaders ready for both versions, check raylib/shaders install folder +* +* This example has been created using raylib 1.7 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016-2017 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include <stdlib.h> // Required for: NULL +#include <string.h> // Required for: strcpy() +#include <math.h> // Required for: vector math + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 8 // Max lights supported by standard shader + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +// Light type +typedef struct LightData { + unsigned int id; // Light unique id + bool enabled; // Light enabled + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + + Vector3 position; // Light position + Vector3 target; // Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) + + Color diffuse; // Light diffuse color + float intensity; // Light intensity level + + float coneAngle; // Light cone max angle: LIGHT_SPOT +} LightData, *Light; + +// Light types +typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static Light lights[MAX_LIGHTS]; // Lights pool +static int lightsCount = 0; // Enabled lights counter +static int lightsLocs[MAX_LIGHTS][8]; // Lights location points in shader: 8 possible points per light: + // enabled, type, position, target, radius, diffuse, intensity, coneAngle + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +static Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool +static void DestroyLight(Light light); // Destroy a light and take it out of the list +static void DrawLight(Light light); // Draw light in 3D world + +static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS) +static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights + +// Vector3 math functions +static float VectorLength(const Vector3 v); // Calculate vector lenght +static void VectorNormalize(Vector3 *v); // Normalize provided vector +static Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors + + +//https://www.gamedev.net/topic/655969-speed-gluniform-vs-uniform-buffer-objects/ +//https://www.reddit.com/r/opengl/comments/4ri20g/is_gluniform_more_expensive_than_glprogramuniform/ +//http://cg.alexandra.dk/?p=3778 - AZDO +//https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +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 [shaders] example - model shader"); + + // Define the camera to look into our 3d world + Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position + + Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model + + Material material;// = LoadStandardMaterial(); + + material.shader = LoadShader("resources/shaders/glsl330/standard.vs", + "resources/shaders/glsl330/standard.fs"); + + // Try to get lights location points (if available) + GetShaderLightsLocations(material.shader); + + material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture + material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture + material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture + material.colDiffuse = WHITE; + material.colAmbient = (Color){0, 0, 10, 255}; + material.colSpecular = WHITE; + material.glossiness = 50.0f; + + dwarf.material = material; // Apply material to model + + Light spotLight = CreateLight(LIGHT_SPOT, (Vector3){3.0f, 5.0f, 2.0f}, (Color){255, 255, 255, 255}); + spotLight->target = (Vector3){0.0f, 0.0f, 0.0f}; + spotLight->intensity = 2.0f; + spotLight->diffuse = (Color){255, 100, 100, 255}; + spotLight->coneAngle = 60.0f; + + Light dirLight = CreateLight(LIGHT_DIRECTIONAL, (Vector3){0.0f, -3.0f, -3.0f}, (Color){255, 255, 255, 255}); + dirLight->target = (Vector3){1.0f, -2.0f, -2.0f}; + dirLight->intensity = 2.0f; + dirLight->diffuse = (Color){100, 255, 100, 255}; + + Light pointLight = CreateLight(LIGHT_POINT, (Vector3){0.0f, 4.0f, 5.0f}, (Color){255, 255, 255, 255}); + pointLight->intensity = 2.0f; + pointLight->diffuse = (Color){100, 100, 255, 255}; + pointLight->radius = 3.0f; + + // Set shader lights values for enabled lights + // NOTE: If values are not changed in real time, they can be set at initialization!!! + SetShaderLightsValues(material.shader); + + //SetShaderActive(0); + + // Setup orbital camera + 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 + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture + + DrawLight(spotLight); // Draw spot light + DrawLight(dirLight); // Draw directional light + DrawLight(pointLight); // Draw point light + + DrawGrid(10, 1.0f); // Draw a grid + + End3dMode(); + + DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadMaterial(material); // Unload material and assigned textures + UnloadModel(dwarf); // Unload model + + // Destroy all created lights + DestroyLight(pointLight); + DestroyLight(dirLight); + DestroyLight(spotLight); + + // Unload lights + if (lightsCount > 0) + { + for (int i = 0; i < lightsCount; i++) free(lights[i]); + lightsCount = 0; + } + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------------- +// Module Functions Definitions +//-------------------------------------------------------------------------------------------- + +// Create a new light, initialize it and add to pool +Light CreateLight(int type, Vector3 position, Color diffuse) +{ + Light light = NULL; + + if (lightsCount < MAX_LIGHTS) + { + // Allocate dynamic memory + light = (Light)malloc(sizeof(LightData)); + + // Initialize light values with generic values + light->id = lightsCount; + light->type = type; + light->enabled = true; + + light->position = position; + light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; + light->intensity = 1.0f; + light->diffuse = diffuse; + + // Add new light to the array + lights[lightsCount] = light; + + // Increase enabled lights count + lightsCount++; + } + else + { + // NOTE: Returning latest created light to avoid crashes + light = lights[lightsCount]; + } + + return light; +} + +// Destroy a light and take it out of the list +void DestroyLight(Light light) +{ + if (light != NULL) + { + int lightId = light->id; + + // Free dynamic memory allocation + free(lights[lightId]); + + // Remove *obj from the pointers array + for (int i = lightId; i < lightsCount; i++) + { + // Resort all the following pointers of the array + if ((i + 1) < lightsCount) + { + lights[i] = lights[i + 1]; + lights[i]->id = lights[i + 1]->id; + } + } + + // Decrease enabled physic objects count + lightsCount--; + } +} + +// Draw light in 3D world +void DrawLight(Light light) +{ + switch (light->type) + { + case LIGHT_POINT: + { + DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); + + DrawCircle3D(light->position, light->radius, (Vector3){ 0, 0, 0 }, 0.0f, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 1, 0, 0 }, 90.0f, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 0, 1, 0 },90.0f, (light->enabled ? light->diffuse : GRAY)); + } break; + case LIGHT_DIRECTIONAL: + { + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); + + DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); + } break; + case LIGHT_SPOT: + { + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); + + Vector3 dir = VectorSubtract(light->target, light->position); + VectorNormalize(&dir); + + DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY)); + + //DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); + } break; + default: break; + } +} + +// Get shader locations for lights (up to MAX_LIGHTS) +static void GetShaderLightsLocations(Shader shader) +{ + char locName[32] = "lights[x].\0"; + char locNameUpdated[64]; + + for (int i = 0; i < MAX_LIGHTS; i++) + { + locName[7] = '0' + i; + + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "enabled\0"); + lightsLocs[i][0] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "type\0"); + lightsLocs[i][1] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "position\0"); + lightsLocs[i][2] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "direction\0"); + lightsLocs[i][3] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "radius\0"); + lightsLocs[i][4] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "diffuse\0"); + lightsLocs[i][5] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "intensity\0"); + lightsLocs[i][6] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "coneAngle\0"); + lightsLocs[i][7] = GetShaderLocation(shader, locNameUpdated); + } +} + +// Set shader uniform values for lights +// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0 +// TODO: Replace glUniform1i(), glUniform1f(), glUniform3f(), glUniform4f(): +//SetShaderValue(Shader shader, int uniformLoc, float *value, int size) +//SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) +static void SetShaderLightsValues(Shader shader) +{ + int tempInt[8] = { 0 }; + float tempFloat[8] = { 0.0f }; + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (i < lightsCount) + { + tempInt[0] = lights[i]->enabled; + SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], lights[i]->enabled); + + tempInt[0] = lights[i]->type; + SetShaderValuei(shader, lightsLocs[i][1], tempInt, 1); //glUniform1i(lightsLocs[i][1], lights[i]->type); + + tempFloat[0] = (float)lights[i]->diffuse.r/255.0f; + tempFloat[1] = (float)lights[i]->diffuse.g/255.0f; + tempFloat[2] = (float)lights[i]->diffuse.b/255.0f; + tempFloat[3] = (float)lights[i]->diffuse.a/255.0f; + SetShaderValue(shader, lightsLocs[i][5], tempFloat, 4); + //glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); + + tempFloat[0] = lights[i]->intensity; + SetShaderValue(shader, lightsLocs[i][6], tempFloat, 1); + + switch (lights[i]->type) + { + case LIGHT_POINT: + { + tempFloat[0] = lights[i]->position.x; + tempFloat[1] = lights[i]->position.y; + tempFloat[2] = lights[i]->position.z; + SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3); + + tempFloat[0] = lights[i]->radius; + SetShaderValue(shader, lightsLocs[i][4], tempFloat, 1); + + //glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + //glUniform1f(lightsLocs[i][4], lights[i]->radius); + } break; + case LIGHT_DIRECTIONAL: + { + Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); + VectorNormalize(&direction); + + tempFloat[0] = direction.x; + tempFloat[1] = direction.y; + tempFloat[2] = direction.z; + SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3); + + //glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); + } break; + case LIGHT_SPOT: + { + tempFloat[0] = lights[i]->position.x; + tempFloat[1] = lights[i]->position.y; + tempFloat[2] = lights[i]->position.z; + SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3); + + //glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); + VectorNormalize(&direction); + + tempFloat[0] = direction.x; + tempFloat[1] = direction.y; + tempFloat[2] = direction.z; + SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3); + //glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); + + tempFloat[0] = lights[i]->coneAngle; + SetShaderValue(shader, lightsLocs[i][7], tempFloat, 1); + //glUniform1f(lightsLocs[i][7], lights[i]->coneAngle); + } break; + default: break; + } + } + else + { + tempInt[0] = 0; + SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], 0); // Light disabled + } + } +} + +// Calculate vector lenght +float VectorLength(const Vector3 v) +{ + float length; + + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + + return length; +} + +// Normalize provided vector +void VectorNormalize(Vector3 *v) +{ + float length, ilength; + + length = VectorLength(*v); + + if (length == 0.0f) length = 1.0f; + + ilength = 1.0f/length; + + v->x *= ilength; + v->y *= ilength; + v->z *= ilength; +} + +// Substract two vectors +Vector3 VectorSubtract(Vector3 v1, Vector3 v2) +{ + Vector3 result; + + result.x = v1.x - v2.x; + result.y = v1.y - v2.y; + result.z = v1.z - v2.z; + + return result; +} |
