aboutsummaryrefslogtreecommitdiff
path: root/examples/models
diff options
context:
space:
mode:
authorDarkElvenAngel <jb_rotavele@yahoo.com>2019-06-10 16:12:06 -0400
committerGitHub <noreply@github.com>2019-06-10 16:12:06 -0400
commitd7f4be071579e6f00974c0940f021272f22fbc54 (patch)
tree6ee389e6617c494d272e9bc82415fbc3618e7a28 /examples/models
parent8a21830b77eaa76ffe0c31df5f96aecd6bd2eecc (diff)
parentbaf7d7d19ad8d6bfbfc201169e4ed4f49a9576a6 (diff)
downloadraylib-d7f4be071579e6f00974c0940f021272f22fbc54.tar.gz
raylib-d7f4be071579e6f00974c0940f021272f22fbc54.zip
Merge pull request #1 from raysan5/master
Update
Diffstat (limited to 'examples/models')
-rw-r--r--examples/models/models_animation.c103
-rw-r--r--examples/models/models_animation.pngbin0 -> 67020 bytes
-rw-r--r--examples/models/models_billboard.c16
-rw-r--r--examples/models/models_box_collisions.c60
-rw-r--r--examples/models/models_cubicmap.c22
-rw-r--r--examples/models/models_first_person_maze.c126
-rw-r--r--examples/models/models_first_person_maze.pngbin0 -> 327996 bytes
-rw-r--r--examples/models/models_geometric_shapes.c8
-rw-r--r--examples/models/models_heightmap.c16
-rw-r--r--examples/models/models_material_pbr.c102
-rw-r--r--examples/models/models_mesh_generation.c49
-rw-r--r--examples/models/models_mesh_picking.c90
-rw-r--r--examples/models/models_obj_loading.c12
-rw-r--r--examples/models/models_obj_viewer.c54
-rw-r--r--examples/models/models_orthographic_projection.c26
-rw-r--r--examples/models/models_rlgl_solar_system.c30
-rw-r--r--examples/models/models_skybox.c38
-rw-r--r--examples/models/models_waving_cubes.c112
-rw-r--r--examples/models/models_waving_cubes.pngbin0 -> 37712 bytes
-rw-r--r--examples/models/models_yaw_pitch_roll.c19
-rw-r--r--examples/models/resources/guy/guy.blendbin0 -> 665304 bytes
-rw-r--r--examples/models/resources/guy/guy.iqmbin0 -> 39408 bytes
-rw-r--r--examples/models/resources/guy/guyanim.iqmbin0 -> 18244 bytes
-rw-r--r--examples/models/resources/guy/guytex.pngbin0 -> 302388 bytes
-rw-r--r--examples/models/resources/models/castle_diffuse.pngbin1538906 -> 444546 bytes
-rw-r--r--examples/models/resources/models/cube.obj44
-rw-r--r--examples/models/resources/pbr/trooper_albedo.pngbin7676508 -> 1838043 bytes
-rw-r--r--examples/models/resources/pbr/trooper_ao.pngbin1832292 -> 559997 bytes
-rw-r--r--examples/models/resources/pbr/trooper_normals.pngbin4959793 -> 1313366 bytes
-rw-r--r--examples/models/resources/pbr/trooper_roughness.pngbin2862048 -> 733780 bytes
-rw-r--r--examples/models/resources/shaders/glsl100/brdf.fs (renamed from examples/models/resources/shaders/brdf.fs)4
-rw-r--r--examples/models/resources/shaders/glsl100/brdf.vs (renamed from examples/models/resources/shaders/brdf.vs)0
-rw-r--r--examples/models/resources/shaders/glsl100/cubemap.fs (renamed from examples/models/resources/shaders/cubemap.fs)0
-rw-r--r--examples/models/resources/shaders/glsl100/cubemap.vs (renamed from examples/models/resources/shaders/cubemap.vs)0
-rw-r--r--examples/models/resources/shaders/glsl100/irradiance.fs (renamed from examples/models/resources/shaders/irradiance.fs)4
-rw-r--r--examples/models/resources/shaders/glsl100/pbr.fs (renamed from examples/models/resources/shaders/pbr.fs)0
-rw-r--r--examples/models/resources/shaders/glsl100/pbr.vs (renamed from examples/models/resources/shaders/pbr.vs)0
-rw-r--r--examples/models/resources/shaders/glsl100/prefilter.fs (renamed from examples/models/resources/shaders/prefilter.fs)4
-rw-r--r--examples/models/resources/shaders/glsl100/skybox.fs (renamed from examples/models/resources/shaders/skybox.fs)0
-rw-r--r--examples/models/resources/shaders/glsl100/skybox.vs (renamed from examples/models/resources/shaders/skybox.vs)0
-rw-r--r--examples/models/resources/shaders/glsl330/brdf.fs133
-rw-r--r--examples/models/resources/shaders/glsl330/brdf.vs25
-rw-r--r--examples/models/resources/shaders/glsl330/cubemap.fs38
-rw-r--r--examples/models/resources/shaders/glsl330/cubemap.vs28
-rw-r--r--examples/models/resources/shaders/glsl330/irradiance.fs58
-rw-r--r--examples/models/resources/shaders/glsl330/pbr.fs298
-rw-r--r--examples/models/resources/shaders/glsl330/pbr.vs49
-rw-r--r--examples/models/resources/shaders/glsl330/prefilter.fs120
-rw-r--r--examples/models/resources/shaders/glsl330/skybox.fs31
-rw-r--r--examples/models/resources/shaders/glsl330/skybox.vs32
50 files changed, 1459 insertions, 292 deletions
diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c
new file mode 100644
index 00000000..7f38b7f5
--- /dev/null
+++ b/examples/models/models_animation.c
@@ -0,0 +1,103 @@
+/*******************************************************************************************
+*
+* raylib [models] example - Load 3d model with animations and play them
+*
+* This example has been created using raylib 2.5 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Copyright (c) 2019 Culacant (@culacant) and Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [models] example - model animation");
+
+ // Define the camera to look into our 3d world
+ Camera camera = { 0 };
+ camera.position = (Vector3){ 10.0f, 10.0f, 10.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
+ camera.type = CAMERA_PERSPECTIVE; // Camera mode type
+
+
+ Model model = LoadModel("resources/guy/guy.iqm"); // Load the animated model mesh and basic data
+ Texture2D texture = LoadTexture("resources/guy/guytex.png"); // Load model texture and set material
+ SetMaterialTexture(&model.materials[0], MAP_DIFFUSE, texture); // Set model material map texture
+
+ Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
+
+ // Load animation data
+ int animsCount = 0;
+ ModelAnimation *anims = LoadModelAnimations("resources/guy/guyanim.iqm", &animsCount);
+ int animFrameCounter = 0;
+
+ SetCameraMode(camera, CAMERA_FREE); // Set free 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);
+
+ // Play animation when spacebar is held down
+ if (IsKeyDown(KEY_SPACE))
+ {
+ animFrameCounter++;
+ UpdateModelAnimation(model, anims[0], animFrameCounter);
+ if (animFrameCounter >= anims[0].frameCount) animFrameCounter = 0;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+
+ DrawModelEx(model, position, (Vector3){ 1.0f, 0.0f, 0.0f }, -90.0f, (Vector3){ 1.0f, 1.0f, 1.0f }, WHITE);
+
+ for (int i = 0; i < model.boneCount; i++)
+ {
+ DrawCube(anims[0].framePoses[animFrameCounter][i].translation, 0.2f, 0.2f, 0.2f, RED);
+ }
+
+ DrawGrid(10, 1.0f); // Draw a grid
+
+ EndMode3D();
+
+ DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, 10, 20, MAROON);
+ DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ // Unload model animations data
+ for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]);
+
+ UnloadModel(model); // Unload model
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/models/models_animation.png b/examples/models/models_animation.png
new file mode 100644
index 00000000..57e39dd3
--- /dev/null
+++ b/examples/models/models_animation.png
Binary files differ
diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c
index 59655714..597e9a60 100644
--- a/examples/models/models_billboard.c
+++ b/examples/models/models_billboard.c
@@ -11,12 +11,12 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards");
@@ -27,10 +27,10 @@ int main()
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.type = CAMERA_PERSPECTIVE;
-
+
Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard
Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard
-
+
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@@ -51,11 +51,11 @@ int main()
ClearBackground(RAYWHITE);
BeginMode3D(camera);
-
+
DrawGrid(10, 1.0f); // Draw a grid
-
+
DrawBillboard(camera, bill, billPosition, 2.0f, WHITE);
-
+
EndMode3D();
DrawFPS(10, 10);
diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c
index 41f6056c..7a937ea7 100644
--- a/examples/models/models_box_collisions.c
+++ b/examples/models/models_box_collisions.c
@@ -11,31 +11,31 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions");
// Define the camera to look into our 3d world
- Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
-
+ Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+
Vector3 playerPosition = { 0.0f, 1.0f, 2.0f };
Vector3 playerSize = { 1.0f, 2.0f, 1.0f };
Color playerColor = GREEN;
-
+
Vector3 enemyBoxPos = { -4.0f, 1.0f, 0.0f };
Vector3 enemyBoxSize = { 2.0f, 2.0f, 2.0f };
-
+
Vector3 enemySpherePos = { 4.0f, 0.0f, 0.0f };
float enemySphereSize = 1.5f;
-
+
bool collision = false;
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@@ -43,40 +43,40 @@ int main()
{
// Update
//----------------------------------------------------------------------------------
-
+
// Move player
if (IsKeyDown(KEY_RIGHT)) playerPosition.x += 0.2f;
else if (IsKeyDown(KEY_LEFT)) playerPosition.x -= 0.2f;
else if (IsKeyDown(KEY_DOWN)) playerPosition.z += 0.2f;
else if (IsKeyDown(KEY_UP)) playerPosition.z -= 0.2f;
-
+
collision = false;
-
+
// Check collisions player vs enemy-box
if (CheckCollisionBoxes(
- (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2,
- playerPosition.y - playerSize.y/2,
- playerPosition.z - playerSize.z/2 },
+ (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2,
+ playerPosition.y - playerSize.y/2,
+ playerPosition.z - playerSize.z/2 },
(Vector3){ playerPosition.x + playerSize.x/2,
- playerPosition.y + playerSize.y/2,
+ playerPosition.y + playerSize.y/2,
playerPosition.z + playerSize.z/2 }},
- (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2,
- enemyBoxPos.y - enemyBoxSize.y/2,
- enemyBoxPos.z - enemyBoxSize.z/2 },
+ (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2,
+ enemyBoxPos.y - enemyBoxSize.y/2,
+ enemyBoxPos.z - enemyBoxSize.z/2 },
(Vector3){ enemyBoxPos.x + enemyBoxSize.x/2,
- enemyBoxPos.y + enemyBoxSize.y/2,
+ enemyBoxPos.y + enemyBoxSize.y/2,
enemyBoxPos.z + enemyBoxSize.z/2 }})) collision = true;
-
+
// Check collisions player vs enemy-sphere
if (CheckCollisionBoxSphere(
- (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2,
- playerPosition.y - playerSize.y/2,
- playerPosition.z - playerSize.z/2 },
+ (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2,
+ playerPosition.y - playerSize.y/2,
+ playerPosition.z - playerSize.z/2 },
(Vector3){ playerPosition.x + playerSize.x/2,
- playerPosition.y + playerSize.y/2,
- playerPosition.z + playerSize.z/2 }},
+ playerPosition.y + playerSize.y/2,
+ playerPosition.z + playerSize.z/2 }},
enemySpherePos, enemySphereSize)) collision = true;
-
+
if (collision) playerColor = RED;
else playerColor = GREEN;
//----------------------------------------------------------------------------------
@@ -92,18 +92,18 @@ int main()
// Draw enemy-box
DrawCube(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, GRAY);
DrawCubeWires(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, DARKGRAY);
-
+
// Draw enemy-sphere
DrawSphere(enemySpherePos, enemySphereSize, GRAY);
DrawSphereWires(enemySpherePos, enemySphereSize, 16, 16, DARKGRAY);
-
+
// Draw player
DrawCubeV(playerPosition, playerSize, playerColor);
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D();
-
+
DrawText("Move player with cursors to collide", 220, 40, 20, GRAY);
DrawFPS(10, 10);
diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c
index c8d62c46..f5087845 100644
--- a/examples/models/models_cubicmap.c
+++ b/examples/models/models_cubicmap.c
@@ -11,32 +11,32 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing");
// Define the camera to look into our 3d world
- Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+ Camera camera = { { 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM)
-
+
Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f });
Model model = LoadModelFromMesh(mesh);
-
+
// NOTE: By default each cube is mapped to one part of texture atlas
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
- model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
-
+ model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
+
Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position
UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM
-
+
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@@ -61,10 +61,10 @@ int main()
DrawModel(model, mapPosition, 1.0f, WHITE);
EndMode3D();
-
+
DrawTextureEx(cubicmap, (Vector2){ screenWidth - cubicmap.width*4 - 20, 20 }, 0.0f, 4.0f, WHITE);
DrawRectangleLines(screenWidth - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN);
-
+
DrawText("cubicmap image used to", 658, 90, 10, GRAY);
DrawText("generate map 3d model", 658, 104, 10, GRAY);
diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c
new file mode 100644
index 00000000..07c51b9a
--- /dev/null
+++ b/examples/models/models_first_person_maze.c
@@ -0,0 +1,126 @@
+/*******************************************************************************************
+*
+* raylib [models] example - first person maze
+*
+* This example has been created using raylib 2.5 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2019 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <stdlib.h> // Required for: free()
+
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [models] example - first person maze");
+
+ // Define the camera to look into our 3d world
+ Camera camera = { { 0.2f, 0.4f, 0.2f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+
+ Image imMap = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
+ Texture2D cubicmap = LoadTextureFromImage(imMap); // Convert image to texture to display (VRAM)
+ Mesh mesh = GenMeshCubicmap(imMap, (Vector3){ 1.0f, 1.0f, 1.0f });
+ Model model = LoadModelFromMesh(mesh);
+
+ // NOTE: By default each cube is mapped to one part of texture atlas
+ Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
+ model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
+
+ // Get map image data to be used for collision detection
+ Color *mapPixels = GetImageData(imMap);
+ UnloadImage(imMap); // Unload image from RAM
+
+ Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position
+ Vector3 playerPosition = camera.position; // Set player position
+
+ SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set 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
+ //----------------------------------------------------------------------------------
+ Vector3 oldCamPos = camera.position; // Store old camera position
+
+ UpdateCamera(&camera); // Update camera
+
+ // Check player collision (we simplify to 2D collision detection)
+ Vector2 playerPos = { camera.position.x, camera.position.z };
+ float playerRadius = 0.1f; // Collision radius (player is modelled as a cilinder for collision)
+
+ int playerCellX = (int)(playerPos.x - mapPosition.x + 0.5f);
+ int playerCellY = (int)(playerPos.y - mapPosition.z + 0.5f);
+
+ // Out-of-limits security check
+ if (playerCellX < 0) playerCellX = 0;
+ else if (playerCellX >= cubicmap.width) playerCellX = cubicmap.width - 1;
+
+ if (playerCellY < 0) playerCellY = 0;
+ else if (playerCellY >= cubicmap.height) playerCellY = cubicmap.height - 1;
+
+ // Check map collisions using image data and player position
+ // TODO: Improvement: Just check player surrounding cells for collision
+ for (int y = 0; y < cubicmap.height; y++)
+ {
+ for (int x = 0; x < cubicmap.width; x++)
+ {
+ if ((mapPixels[y*cubicmap.width + x].r == 255) && // Collision: white pixel, only check R channel
+ (CheckCollisionCircleRec(playerPos, playerRadius,
+ (Rectangle){ mapPosition.x - 0.5f + x*1.0f, mapPosition.z - 0.5f + y*1.0f, 1.0f, 1.0f })))
+ {
+ // Collision detected, reset camera position
+ camera.position = oldCamPos;
+ }
+ }
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+
+ DrawModel(model, mapPosition, 1.0f, WHITE); // Draw maze map
+ //DrawCubeV(playerPosition, (Vector3){ 0.2f, 0.4f, 0.2f }, RED); // Draw player
+
+ EndMode3D();
+
+ DrawTextureEx(cubicmap, (Vector2){ GetScreenWidth() - cubicmap.width*4 - 20, 20 }, 0.0f, 4.0f, WHITE);
+ DrawRectangleLines(GetScreenWidth() - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN);
+
+ // Draw player position radar
+ DrawRectangle(GetScreenWidth() - cubicmap.width*4 - 20 + playerCellX*4, 20 + playerCellY*4, 4, 4, RED);
+
+ DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ free(mapPixels); // Unload color array
+
+ UnloadTexture(cubicmap); // Unload cubicmap texture
+ UnloadTexture(texture); // Unload map texture
+ UnloadModel(model); // Unload map model
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/models/models_first_person_maze.png b/examples/models/models_first_person_maze.png
new file mode 100644
index 00000000..ed6047e1
--- /dev/null
+++ b/examples/models/models_first_person_maze.png
Binary files differ
diff --git a/examples/models/models_geometric_shapes.c b/examples/models/models_geometric_shapes.c
index 82ca4c60..39477927 100644
--- a/examples/models/models_geometric_shapes.c
+++ b/examples/models/models_geometric_shapes.c
@@ -11,12 +11,12 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes");
@@ -28,7 +28,7 @@ int main()
camera.fovy = 45.0f;
camera.type = CAMERA_PERSPECTIVE;
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c
index d131b127..a2c2e310 100644
--- a/examples/models/models_heightmap.c
+++ b/examples/models/models_heightmap.c
@@ -11,29 +11,29 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing");
// Define our custom camera to look into our 3d world
- Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+ Camera camera = { { 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM)
Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM)
-
+
Mesh mesh = GenMeshHeightmap(image, (Vector3){ 16, 8, 16 }); // Generate heightmap mesh (RAM and VRAM)
Model model = LoadModelFromMesh(mesh); // Load model from generated mesh
- model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
+ model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Define model position
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
-
+
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@@ -60,7 +60,7 @@ int main()
DrawGrid(20, 1.0f);
EndMode3D();
-
+
DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE);
DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN);
diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c
index f93c7a68..8d51eefd 100644
--- a/examples/models/models_material_pbr.c
+++ b/examples/models/models_material_pbr.c
@@ -12,6 +12,8 @@
#include "raylib.h"
#include "raymath.h"
+#include <stdio.h>
+
#define RLIGHTS_IMPLEMENTATION
#include "rlights.h"
@@ -23,33 +25,42 @@
// PBR material loading
static Material LoadMaterialPBR(Color albedo, float metalness, float roughness);
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available)
InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material");
// Define the camera to look into our 3d world
- Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+ Camera camera = { 0 };
+ camera.position = (Vector3){ 4.0f, 4.0f, 4.0f }; // Camera position
+ camera.target = (Vector3){ 0.0f, 0.5f, 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
+ camera.type = CAMERA_PERSPECTIVE; // Camera mode type
// Load model and PBR material
Model model = LoadModel("resources/pbr/trooper.obj");
- MeshTangents(&model.mesh);
- model.material = LoadMaterialPBR((Color){ 255, 255, 255, 255 }, 1.0f, 1.0f);
+
+ // Mesh tangents are generated... and uploaded to GPU
+ // NOTE: New VBO for tangents is generated at default location and also binded to mesh VAO
+ MeshTangents(&model.meshes[0]);
+
+ model.materials[0] = LoadMaterialPBR((Color){ 255, 255, 255, 255 }, 1.0f, 1.0f);
// Define lights attributes
// NOTE: Shader is passed to every light on creation to define shader bindings internally
- Light lights[MAX_LIGHTS] = {
- CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.material.shader),
- CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.material.shader),
- CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.material.shader),
- CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.material.shader)
+ Light lights[MAX_LIGHTS] = {
+ CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.materials[0].shader),
+ CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.materials[0].shader),
+ CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.materials[0].shader),
+ CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.materials[0].shader)
};
-
+
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@@ -61,10 +72,10 @@ int main()
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update camera
-
+
// Send to material PBR shader camera view position
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
- SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3);
+ SetShaderValue(model.materials[0].shader, model.materials[0].shader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3);
//----------------------------------------------------------------------------------
// Draw
@@ -76,7 +87,7 @@ int main()
BeginMode3D(camera);
DrawModel(model, Vector3Zero(), 1.0f, WHITE);
-
+
DrawGrid(10, 1.0f);
EndMode3D();
@@ -103,11 +114,12 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
{
Material mat = { 0 }; // NOTE: All maps textures are set to { 0 }
- #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader
- #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader
-
- mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS);
-
+#if defined(PLATFORM_DESKTOP)
+ mat.shader = LoadShader("resources/shaders/glsl330/pbr.vs", "resources/shaders/glsl330/pbr.fs");
+#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+ mat.shader = LoadShader("resources/shaders/glsl100/pbr.vs", "resources/shaders/glsl100/pbr.fs");
+#endif
+
// Get required locations points for PBR material
// NOTE: Those location names must be available and used in the shader code
mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler");
@@ -125,7 +137,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "matModel");
mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view");
mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos");
-
+
// Set PBR standard maps
mat.maps[MAP_ALBEDO].texture = LoadTexture("resources/pbr/trooper_albedo.png");
mat.maps[MAP_NORMAL].texture = LoadTexture("resources/pbr/trooper_normals.png");
@@ -133,19 +145,33 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png");
mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png");
- // Set environment maps
- #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader
- #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader
- #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader
- #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader
- #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader
- #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader
- #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader
-
- Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS);
- Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS);
- Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS);
- Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS);
+ // Load equirectangular to cubemap shader
+#if defined(PLATFORM_DESKTOP)
+ Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs");
+#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+ Shader shdrCubemap = LoadShader("resources/shaders/glsl100/cubemap.vs", "resources/shaders/glsl100/cubemap.fs");
+#endif
+
+ // Load irradiance (GI) calculation shader
+#if defined(PLATFORM_DESKTOP)
+ Shader shdrIrradiance = LoadShader("resources/shaders/glsl330/skybox.vs", "resources/shaders/glsl330/irradiance.fs");
+#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+ Shader shdrIrradiance = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/irradiance.fs");
+#endif
+
+ // Load reflection prefilter calculation shader
+#if defined(PLATFORM_DESKTOP)
+ Shader shdrPrefilter = LoadShader("resources/shaders/glsl330/skybox.vs", "resources/shaders/glsl330/prefilter.fs");
+#else
+ Shader shdrPrefilter = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/prefilter.fs");
+#endif
+
+ // Load bidirectional reflectance distribution function shader
+#if defined(PLATFORM_DESKTOP)
+ Shader shdrBRDF = LoadShader("resources/shaders/glsl330/brdf.vs", "resources/shaders/glsl330/brdf.fs");
+#else
+ Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs");
+#endif
// Setup required shader locations
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
@@ -159,27 +185,27 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, BRDF_SIZE);
UnloadTexture(cubemap);
UnloadTexture(texHDR);
-
+
// Unload already used shaders (to create specific textures)
UnloadShader(shdrCubemap);
UnloadShader(shdrIrradiance);
UnloadShader(shdrPrefilter);
UnloadShader(shdrBRDF);
-
+
// Set textures filtering for better quality
SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR);
SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR);
SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR);
SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR);
SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR);
-
+
// Enable sample usage in shader for assigned textures
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
-
+
int renderModeLoc = GetShaderLocation(mat.shader, "renderMode");
SetShaderValue(mat.shader, renderModeLoc, (int[1]){ 0 }, UNIFORM_INT);
diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c
index d64889bd..6c0ae653 100644
--- a/examples/models/models_mesh_generation.c
+++ b/examples/models/models_mesh_generation.c
@@ -11,24 +11,24 @@
#include "raylib.h"
-#define NUM_MODELS 8 // We generate 8 parametric 3d shapes
+#define NUM_MODELS 8 // Parametric 3d shapes to generate
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh generation");
-
+
// We generate a checked image for texturing
Image checked = GenImageChecked(2, 2, 1, 1, RED, GREEN);
Texture2D texture = LoadTextureFromImage(checked);
UnloadImage(checked);
-
- Model models[NUM_MODELS];
-
+
+ Model models[NUM_MODELS] = { 0 };
+
models[0] = LoadModelFromMesh(GenMeshPlane(2, 2, 5, 5));
models[1] = LoadModelFromMesh(GenMeshCube(2.0f, 1.0f, 2.0f));
models[2] = LoadModelFromMesh(GenMeshSphere(2, 32, 32));
@@ -37,21 +37,21 @@ int main()
models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32));
models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128));
models[7] = LoadModelFromMesh(GenMeshPoly(5, 2.0f));
-
+
// Set checked texture as default diffuse component for all models material
- for (int i = 0; i < NUM_MODELS; i++) models[i].material.maps[MAP_DIFFUSE].texture = texture;
+ for (int i = 0; i < NUM_MODELS; i++) models[i].materials[0].maps[MAP_DIFFUSE].texture = texture;
// Define the camera to look into our 3d world
- Camera camera = {{ 5.0f, 5.0f, 5.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+ Camera camera = { { 5.0f, 5.0f, 5.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
// Model drawing position
Vector3 position = { 0.0f, 0.0f, 0.0f };
-
+
int currentModel = 0;
-
+
SetCameraMode(camera, CAMERA_ORBITAL); // Set a orbital camera mode
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@@ -60,11 +60,22 @@ int main()
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera
-
+
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
currentModel = (currentModel + 1)%NUM_MODELS; // Cycle between the textures
}
+
+ if (IsKeyPressed(KEY_RIGHT))
+ {
+ currentModel++;
+ if (currentModel >= NUM_MODELS) currentModel = 0;
+ }
+ else if (IsKeyPressed(KEY_LEFT))
+ {
+ currentModel--;
+ if (currentModel < 0) currentModel = NUM_MODELS - 1;
+ }
//----------------------------------------------------------------------------------
// Draw
@@ -80,11 +91,11 @@ int main()
DrawGrid(10, 1.0);
EndMode3D();
-
+
DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f));
DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, BLUE);
-
+
switch(currentModel)
{
case 0: DrawText("PLANE", 680, 10, 20, DARKBLUE); break;
@@ -104,10 +115,10 @@ int main()
// De-Initialization
//--------------------------------------------------------------------------------------
-
+
// Unload models data (GPU VRAM)
for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]);
-
+
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c
index 9b12e98c..0bf95dd1 100644
--- a/examples/models/models_mesh_picking.c
+++ b/examples/models/models_mesh_picking.c
@@ -5,8 +5,9 @@
* 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) 2015 Ramon Santamaria (@raysan5)
-* Example contributed by Joel Davis (@joeld42)
+* Example contributed by Joel Davis (@joeld42) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Copyright (c) 2017 Joel Davis (@joeld42) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -15,40 +16,40 @@
#define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh picking");
// Define the camera to look into our 3d world
Camera camera = { 0 };
- camera.position = (Vector3){ 20.0f, 20.0f, 20.0f }; // Camera position
+ camera.position = (Vector3){ 20.0f, 20.0f, 20.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 8.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.type = CAMERA_PERSPECTIVE; // Camera mode type
Ray ray = { 0 }; // Picking ray
-
+
Model tower = LoadModel("resources/models/turret.obj"); // Load OBJ model
Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load model texture
- tower.material.maps[MAP_DIFFUSE].texture = texture; // Set model diffuse texture
-
+ tower.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set model diffuse texture
+
Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position
- BoundingBox towerBBox = MeshBoundingBox(tower.mesh); // Get mesh bounding box
+ BoundingBox towerBBox = MeshBoundingBox(tower.meshes[0]); // Get mesh bounding box
bool hitMeshBBox = false;
bool hitTriangle = false;
// Test triangle
- Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 };
+ Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 };
Vector3 tb = (Vector3){ -4.0, 2.5, 1.0 };
Vector3 tc = (Vector3){ -8.0, 6.5, 0.0 };
- Vector3 bary = { 0.0f, 0.0f, 0.0f };
+ Vector3 bary = { 0.0f, 0.0f, 0.0f };
SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
@@ -60,7 +61,7 @@ int main()
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update camera
-
+
// Display information about closest hit
RayHitInfo nearestHit = { 0 };
char *hitObjectName = "None";
@@ -70,10 +71,10 @@ int main()
// Get ray and test against ground, triangle, and mesh
ray = GetMouseRay(GetMousePosition(), camera);
-
+
// Check ray collision aginst ground plane
RayHitInfo groundHitInfo = GetCollisionRayGround(ray, 0.0f);
-
+
if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance))
{
nearestHit = groundHitInfo;
@@ -83,8 +84,8 @@ int main()
// Check ray collision against test triangle
RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, ta, tb, tc);
-
- if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance))
+
+ if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance))
{
nearestHit = triHitInfo;
cursorColor = PURPLE;
@@ -92,32 +93,31 @@ int main()
bary = Vector3Barycenter(nearestHit.position, ta, tb, tc);
hitTriangle = true;
- }
+ }
else hitTriangle = false;
RayHitInfo meshHitInfo = { 0 };
// Check ray collision against bounding box first, before trying the full ray-mesh test
- if (CheckCollisionRayBox(ray, towerBBox))
+ if (CheckCollisionRayBox(ray, towerBBox))
{
hitMeshBBox = true;
-
+
// Check ray collision against model
// NOTE: It considers model.transform matrix!
- meshHitInfo = GetCollisionRayModel(ray, &tower);
-
- if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance))
+ meshHitInfo = GetCollisionRayModel(ray, &tower);
+
+ if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance))
{
nearestHit = meshHitInfo;
cursorColor = ORANGE;
hitObjectName = "Mesh";
}
-
- }
-
- hitMeshBBox = false;
+ }
+
+ hitMeshBBox = false;
//----------------------------------------------------------------------------------
-
+
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
@@ -127,10 +127,10 @@ int main()
BeginMode3D(camera);
// Draw the tower
- // WARNING: If scale is different than 1.0f,
+ // WARNING: If scale is different than 1.0f,
// not considered by GetCollisionRayModel()
DrawModel(tower, towerPos, 1.0f, WHITE);
-
+
// Draw the test triangle
DrawLine3D(ta, tb, PURPLE);
DrawLine3D(tb, tc, PURPLE);
@@ -140,7 +140,7 @@ int main()
if (hitMeshBBox) DrawBoundingBox(towerBBox, LIME);
// If we hit something, draw the cursor at the hit point
- if (nearestHit.hit)
+ if (nearestHit.hit)
{
DrawCube(nearestHit.position, 0.3, 0.3, 0.3, cursorColor);
DrawCubeWires(nearestHit.position, 0.3, 0.3, 0.3, RED);
@@ -149,40 +149,40 @@ int main()
normalEnd.x = nearestHit.position.x + nearestHit.normal.x;
normalEnd.y = nearestHit.position.y + nearestHit.normal.y;
normalEnd.z = nearestHit.position.z + nearestHit.normal.z;
-
+
DrawLine3D(nearestHit.position, normalEnd, RED);
}
DrawRay(ray, MAROON);
-
+
DrawGrid(10, 10.0f);
EndMode3D();
-
+
// Draw some debug GUI text
DrawText(FormatText("Hit Object: %s", hitObjectName), 10, 50, 10, BLACK);
- if (nearestHit.hit)
+ if (nearestHit.hit)
{
int ypos = 70;
DrawText(FormatText("Distance: %3.2f", nearestHit.distance), 10, ypos, 10, BLACK);
-
- DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f",
- nearestHit.position.x,
- nearestHit.position.y,
+
+ DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f",
+ nearestHit.position.x,
+ nearestHit.position.y,
nearestHit.position.z), 10, ypos + 15, 10, BLACK);
-
- DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f",
- nearestHit.normal.x,
- nearestHit.normal.y,
+
+ DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f",
+ nearestHit.normal.x,
+ nearestHit.normal.y,
nearestHit.normal.z), 10, ypos + 30, 10, BLACK);
if (hitTriangle) DrawText(FormatText("Barycenter: %3.2f %3.2f %3.2f", bary.x, bary.y, bary.z), 10, ypos + 45, 10, BLACK);
}
DrawText("Use Mouse to Move Camera", 10, 430, 10, GRAY);
-
+
DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
@@ -195,7 +195,7 @@ int main()
//--------------------------------------------------------------------------------------
UnloadModel(tower); // Unload model
UnloadTexture(texture); // Unload texture
-
+
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/models/models_obj_loading.c b/examples/models/models_obj_loading.c
index 7ec2d3f0..51578bc1 100644
--- a/examples/models/models_obj_loading.c
+++ b/examples/models/models_obj_loading.c
@@ -11,12 +11,12 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading");
@@ -30,10 +30,10 @@ int main()
Model model = LoadModel("resources/models/castle.obj"); // Load OBJ model
Texture2D texture = LoadTexture("resources/models/castle_diffuse.png"); // Load model texture
- model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
+ model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@@ -59,7 +59,7 @@ int main()
DrawGizmo(position); // Draw gizmo
EndMode3D();
-
+
DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
diff --git a/examples/models/models_obj_viewer.c b/examples/models/models_obj_viewer.c
index 15f79549..83c8f2f1 100644
--- a/examples/models/models_obj_viewer.c
+++ b/examples/models/models_obj_viewer.c
@@ -5,7 +5,7 @@
* This example has been created using raylib 2.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
-* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
+* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -13,31 +13,31 @@
#include <string.h> // Required for: strcpy()
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib example - obj viewer");
// Define the camera to look into our 3d world
- Camera camera = {{ 30.0f, 30.0f, 30.0f }, { 0.0f, 10.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+ Camera camera = { { 30.0f, 30.0f, 30.0f }, { 0.0f, 10.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
Model model = LoadModel("resources/models/turret.obj"); // Load default model obj
Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load default model texture
- model.material.maps[MAP_DIFFUSE].texture = texture; // Bind texture to model
-
- Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position
- BoundingBox bounds = MeshBoundingBox(model.mesh); // Set model bounds
- bool selected = false; // Selected object flag
-
- SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
+ model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Bind texture to model
+
+ Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position
+ BoundingBox bounds = MeshBoundingBox(model.meshes[0]); // Set model bounds
+ bool selected = false; // Selected object flag
+
+ SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
char objFilename[64] = "turret.obj";
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@@ -49,30 +49,30 @@ int main()
{
int count = 0;
char **droppedFiles = GetDroppedFiles(&count);
-
+
if (count == 1)
{
if (IsFileExtension(droppedFiles[0], ".obj"))
{
- UnloadMesh(&model.mesh);
- model.mesh = LoadMesh(droppedFiles[0]);
- bounds = MeshBoundingBox(model.mesh);
+ for (int i = 0; i < model.meshCount; i++) UnloadMesh(&model.meshes[i]);
+ model.meshes = LoadMeshes(droppedFiles[0], &model.meshCount);
+ bounds = MeshBoundingBox(model.meshes[0]);
}
else if (IsFileExtension(droppedFiles[0], ".png"))
{
UnloadTexture(texture);
texture = LoadTexture(droppedFiles[0]);
- model.material.maps[MAP_DIFFUSE].texture = texture;
+ model.materials[0].maps[MAP_DIFFUSE].texture = texture;
}
strcpy(objFilename, GetFileName(droppedFiles[0]));
}
-
+
ClearDroppedFiles(); // Clear internal buffers
}
-
+
UpdateCamera(&camera);
-
+
// Select model on mouse click
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
@@ -93,21 +93,21 @@ int main()
DrawModel(model, position, 1.0f, WHITE); // Draw 3d model with texture
DrawGrid(20.0, 10.0); // Draw a grid
-
+
if (selected) DrawBoundingBox(bounds, GREEN);
-
+
EndMode3D();
-
+
DrawText("Free camera default controls:", 10, 20, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out", 20, 40, 10, GRAY);
DrawText("- Mouse Wheel Pressed to Pan", 20, 60, 10, GRAY);
DrawText("- Alt + Mouse Wheel Pressed to Rotate", 20, 80, 10, GRAY);
DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 20, 100, 10, GRAY);
-
+
DrawText("Drag & drop .obj/.png to load mesh/texture.", 10, GetScreenHeight() - 20, 10, DARKGRAY);
DrawText(FormatText("Current file: %s", objFilename), 250, GetScreenHeight() - 20, 10, GRAY);
if (selected) DrawText("MODEL SELECTED", GetScreenWidth() - 110, 10, 10, GREEN);
-
+
DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
EndDrawing();
@@ -119,7 +119,7 @@ int main()
UnloadModel(model); // Unload model
ClearDroppedFiles(); // Clear internal buffers
-
+
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c
index f9b54b6d..8c9b5b1c 100644
--- a/examples/models/models_orthographic_projection.c
+++ b/examples/models/models_orthographic_projection.c
@@ -1,13 +1,15 @@
/*******************************************************************************************
*
-* raylib [models] example - Show the difference between perspective and orthographic projection
+* raylib [models] example - Show the difference between perspective and orthographic projection
*
* This program is heavily based on the geometric objects example
*
-* This example has been created using raylib 1.9.7 (www.raylib.com)
+* This example has been created using raylib 2.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
-* Copyright (c) 2018 Max Danielsson & Ramon Santamaria (@raysan5)
+* Example contributed by Max Danielsson (@autious) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Copyright (c) 2018 Max Danielsson (@autious) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -16,19 +18,19 @@
#define FOVY_PERSPECTIVE 45.0f
#define WIDTH_ORTHOGRAPHIC 10.0f
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes");
// Define the camera to look into our 3d world
- Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE };
+ Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE };
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@@ -36,14 +38,14 @@ int main()
{
// Update
//----------------------------------------------------------------------------------
- if (IsKeyPressed(KEY_SPACE))
+ if (IsKeyPressed(KEY_SPACE))
{
- if (camera.type == CAMERA_PERSPECTIVE)
+ if (camera.type == CAMERA_PERSPECTIVE)
{
camera.fovy = WIDTH_ORTHOGRAPHIC;
camera.type = CAMERA_ORTHOGRAPHIC;
- }
- else
+ }
+ else
{
camera.fovy = FOVY_PERSPECTIVE;
camera.type = CAMERA_PERSPECTIVE;
diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c
index 7193d6f8..cb9289ad 100644
--- a/examples/models/models_rlgl_solar_system.c
+++ b/examples/models/models_rlgl_solar_system.c
@@ -22,13 +22,13 @@ void DrawSphereBasic(Color color); // Draw sphere without any matrix transf
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
-
+
const float sunRadius = 4.0f;
const float earthRadius = 0.6f;
const float earthOrbitRadius = 8.0f;
@@ -44,26 +44,26 @@ int main()
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.type = CAMERA_PERSPECTIVE;
-
+
SetCameraMode(camera, CAMERA_FREE);
-
+
float rotationSpeed = 0.2f; // General system rotation speed
-
+
float earthRotation = 0.0f; // Rotation of earth around itself (days) in degrees
float earthOrbitRotation = 0.0f; // Rotation of earth around the Sun (years) in degrees
float moonRotation = 0.0f; // Rotation of moon around itself
float moonOrbitRotation = 0.0f; // Rotation of moon around earth in degrees
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
- while (!WindowShouldClose()) // Detect window close button or ESC key
+ while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera);
-
+
earthRotation += (5.0f*rotationSpeed);
earthOrbitRotation += (365/360.0f*(5.0f*rotationSpeed)*rotationSpeed);
moonRotation += (2.0f*rotationSpeed);
@@ -77,12 +77,12 @@ int main()
ClearBackground(RAYWHITE);
BeginMode3D(camera);
-
+
rlPushMatrix();
rlScalef(sunRadius, sunRadius, sunRadius); // Scale Sun
DrawSphereBasic(GOLD); // Draw the Sun
rlPopMatrix();
-
+
rlPushMatrix();
rlRotatef(earthOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Earth orbit around Sun
rlTranslatef(earthOrbitRadius, 0.0f, 0.0f); // Translation for Earth orbit
@@ -91,19 +91,19 @@ int main()
rlPushMatrix();
rlRotatef(earthRotation, 0.25, 1.0, 0.0); // Rotation for Earth itself
rlScalef(earthRadius, earthRadius, earthRadius);// Scale Earth
-
+
DrawSphereBasic(BLUE); // Draw the Earth
rlPopMatrix();
-
+
rlRotatef(moonOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon orbit around Earth
rlTranslatef(moonOrbitRadius, 0.0f, 0.0f); // Translation for Moon orbit
rlRotatef(-moonOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon orbit around Earth inverted
rlRotatef(moonRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon itself
rlScalef(moonRadius, moonRadius, moonRadius); // Scale Moon
-
+
DrawSphereBasic(LIGHTGRAY); // Draw the Moon
rlPopMatrix();
-
+
// Some reference elements (not affected by previous matrix transformations)
DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, earthOrbitRadius, (Vector3){ 1, 0, 0 }, 90.0f, Fade(RED, 0.5f));
DrawGrid(20, 1.0f);
@@ -135,7 +135,7 @@ void DrawSphereBasic(Color color)
{
int rings = 16;
int slices = 16;
-
+
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c
index c7f76ecf..bad29b96 100644
--- a/examples/models/models_skybox.c
+++ b/examples/models/models_skybox.c
@@ -11,41 +11,49 @@
#include "raylib.h"
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
+ const int screenWidth = 800;
+ const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing");
// Define the camera to look into our 3d world
- Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 4.0f, 1.0f, 4.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+ Camera camera = { { 1.0f, 1.0f, 1.0f }, { 4.0f, 1.0f, 4.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
- // Load skybox model
+ // Load skybox model
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
Model skybox = LoadModelFromMesh(cube);
-
+
// Load skybox shader and set required locations
// NOTE: Some locations are automatically set at shader loading
- skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs");
- SetShaderValue(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, UNIFORM_INT);
+#if defined(PLATFORM_DESKTOP)
+ skybox.materials[0].shader = LoadShader("resources/shaders/glsl330/skybox.vs", "resources/shaders/glsl330/skybox.fs");
+#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+ skybox.materials[0].shader = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/skybox.fs");
+#endif
+ SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, UNIFORM_INT);
// Load cubemap shader and setup required shader locations
- Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs");
+#if defined(PLATFORM_DESKTOP)
+ Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs");
+#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+ Shader shdrCubemap = LoadShader("resources/shaders/glsl100/cubemap.vs", "resources/shaders/glsl100/cubemap.fs");
+#endif
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
-
+
// Load HDR panorama (sphere) texture
Texture2D texHDR = LoadTexture("resources/dresden_square.hdr");
-
+
// Generate cubemap (texture with 6 quads-cube-mapping) from panorama HDR texture
// NOTE: New texture is generated rendering to texture, shader computes the sphre->cube coordinates mapping
- skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512);
-
+ skybox.materials[0].maps[MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512);
+
UnloadTexture(texHDR); // Texture not required anymore, cubemap already generated
UnloadShader(shdrCubemap); // Unload cubemap generation shader, not required anymore
-
+
SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set a first person camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@@ -68,7 +76,7 @@ int main()
BeginMode3D(camera);
DrawModel(skybox, (Vector3){0, 0, 0}, 1.0f, WHITE);
-
+
DrawGrid(10, 1.0f);
EndMode3D();
diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c
new file mode 100644
index 00000000..f6309bd6
--- /dev/null
+++ b/examples/models/models_waving_cubes.c
@@ -0,0 +1,112 @@
+/*******************************************************************************************
+*
+* raylib [models] example - Waving cubes
+*
+* This example has been created using raylib 2.5 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Example contributed by Codecat (@codecat) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Copyright (c) 2019 Codecat (@codecat) and Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <math.h>
+
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [models] example - waving cubes");
+
+ // Initialize the camera
+ Camera3D camera = { 0 };
+ camera.position = (Vector3){ 30.0f, 20.0f, 30.0f };
+ camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
+ camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
+ camera.fovy = 70.0f;
+ camera.type = CAMERA_PERSPECTIVE;
+
+ // Specify the amount of blocks in each direction
+ const int numBlocks = 15;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ double time = GetTime();
+
+ // Calculate time scale for cube position and size
+ float scale = (2.0f + (float)sin(time))*0.7f;
+
+ // Move camera around the scene
+ double cameraTime = time*0.3;
+ camera.position.x = (float)cos(cameraTime)*40.0f;
+ camera.position.z = (float)sin(cameraTime)*40.0f;
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+
+ DrawGrid(10, 5.0f);
+
+ for (int x = 0; x < numBlocks; x++)
+ {
+ for (int y = 0; y < numBlocks; y++)
+ {
+ for (int z = 0; z < numBlocks; z++)
+ {
+ // Scale of the blocks depends on x/y/z positions
+ float blockScale = (x + y + z)/30.0f;
+
+ // Scatter makes the waving effect by adding blockScale over time
+ float scatter = sinf(blockScale*20.0f + (float)(time*4.0f));
+
+ // Calculate the cube position
+ Vector3 cubePos = {
+ (float)(x - numBlocks/2)*(scale*3.0f) + scatter,
+ (float)(y - numBlocks/2)*(scale*2.0f) + scatter,
+ (float)(z - numBlocks/2)*(scale*3.0f) + scatter
+ };
+
+ // Pick a color with a hue depending on cube position for the rainbow color effect
+ Color cubeColor = ColorFromHSV((Vector3){ (float)(((x + y + z)*18)%360), 0.75f, 0.9f });
+
+ // Calculate cube size
+ float cubeSize = (2.4f - scale)*blockScale;
+
+ // And finally, draw the cube!
+ DrawCube(cubePos, cubeSize, cubeSize, cubeSize, cubeColor);
+ }
+ }
+ }
+
+ EndMode3D();
+
+ DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/models/models_waving_cubes.png b/examples/models/models_waving_cubes.png
new file mode 100644
index 00000000..37a1761e
--- /dev/null
+++ b/examples/models/models_waving_cubes.png
Binary files differ
diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c
index 88b0a610..0931c00e 100644
--- a/examples/models/models_yaw_pitch_roll.c
+++ b/examples/models/models_yaw_pitch_roll.c
@@ -5,9 +5,9 @@
* This example has been created using raylib 1.8 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
-* Example based on Berni work on Raspberry Pi.
+* Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5)
*
-* Copyright (c) 2017 Ramon Santamaria (@raysan5)
+* Copyright (c) 2017 Berni (@Berni8k) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -17,10 +17,7 @@
// Draw angle gauge controls
void DrawAngleGauge(Texture2D angleGauge, int x, int y, float angle, char title[], Color color);
-//----------------------------------------------------------------------------------
-// Main entry point
-//----------------------------------------------------------------------------------
-int main()
+int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
@@ -37,10 +34,10 @@ int main()
RenderTexture2D framebuffer = LoadRenderTexture(192, 192);
// Model loading
- Model model = LoadModel("resources/plane.obj"); // Load OBJ model
- model.material.maps[MAP_DIFFUSE].texture = LoadTexture("resources/plane_diffuse.png"); // Set map diffuse texture
+ Model model = LoadModel("resources/plane.obj"); // Load OBJ model
+ model.materials[0].maps[MAP_DIFFUSE].texture = LoadTexture("resources/plane_diffuse.png"); // Set map diffuse texture
- GenTextureMipmaps(&model.material.maps[MAP_DIFFUSE].texture);
+ GenTextureMipmaps(&model.materials[0].maps[MAP_DIFFUSE].texture);
Camera camera = { 0 };
camera.position = (Vector3){ 0.0f, 60.0f, -120.0f };// Camera position perspective
@@ -53,10 +50,10 @@ int main()
float roll = 0.0f;
float yaw = 0.0f;
- SetTargetFPS(60);
+ 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
diff --git a/examples/models/resources/guy/guy.blend b/examples/models/resources/guy/guy.blend
new file mode 100644
index 00000000..3880467d
--- /dev/null
+++ b/examples/models/resources/guy/guy.blend
Binary files differ
diff --git a/examples/models/resources/guy/guy.iqm b/examples/models/resources/guy/guy.iqm
new file mode 100644
index 00000000..36bed5e0
--- /dev/null
+++ b/examples/models/resources/guy/guy.iqm
Binary files differ
diff --git a/examples/models/resources/guy/guyanim.iqm b/examples/models/resources/guy/guyanim.iqm
new file mode 100644
index 00000000..824a68a3
--- /dev/null
+++ b/examples/models/resources/guy/guyanim.iqm
Binary files differ
diff --git a/examples/models/resources/guy/guytex.png b/examples/models/resources/guy/guytex.png
new file mode 100644
index 00000000..7f813552
--- /dev/null
+++ b/examples/models/resources/guy/guytex.png
Binary files differ
diff --git a/examples/models/resources/models/castle_diffuse.png b/examples/models/resources/models/castle_diffuse.png
index b616e1dd..361144e9 100644
--- a/examples/models/resources/models/castle_diffuse.png
+++ b/examples/models/resources/models/castle_diffuse.png
Binary files differ
diff --git a/examples/models/resources/models/cube.obj b/examples/models/resources/models/cube.obj
index 0e9d6597..bf7e3bee 100644
--- a/examples/models/resources/models/cube.obj
+++ b/examples/models/resources/models/cube.obj
@@ -1,7 +1,7 @@
# reference material
-mtllib myCube.mtl
+#mtllib cube.mtl
-# object Pau_Box
+# object box
# vertex (XZY)
v 5.5 0 1.5
@@ -14,85 +14,55 @@ v 5.5 3 -1.5
v 8.5 3 -1.5
# normals (XYZ)
-# red
vn 0 -1 0
-#blue
vn 0 1 0
-#top
vn 0 0 1
-#yellow
vn 1 0 0
-#bottom
vn 0 0 -1
-#green
vn -1 0 0
-
# UVs (XY)
-# yellow (1234)
vt 0.5 0 0
vt 1 0 0
vt 1 0.5 0
vt 0.5 0.5 0
-# red (5678)
vt 0.5 0.5 0
vt 1 0.5 0
vt 0.5 1 0
vt 1 1 0
-#bottom (9101112)
vt 0 0.5 0
vt 1 0.5 0
vt 1 0 0
vt 0 0 0
-#top (13141516)
vt 0 0.5 0
vt 1 0.5 0
vt 1 1 0
vt 0 1 0
-#green (17181920)
vt 0.5 0 0
vt 0 0 0
vt 0 0.5 0
vt 0.5 0.5 0
-#blue (21222324)
vt 0 0.5 0
vt 0.5 0.5 0
vt 0.5 1 0
vt 0 1 0
# merger
-g Pau_Box
+g box
# reference material
-usemtl Material_1
-
-# bottom
-f 1/9/1 3/10/1 4/11/1
-f 4/11/1 2/12/1 1/9/1
+#usemtl mat01
-# top
+# faces
+f 1/9/1 3/10/1 4/11/1
+f 4/11/1 2/12/1 1/9/1
f 5/13/2 6/14/2 8/15/2
f 8/15/2 7/16/2 5/13/2
-
-# front-yellow
f 1/17/6 2/18/6 6/19/6
f 6/19/6 5/20/6 1/17/6
-
-# right-blue
f 2/6/1 4/5/1 8/7/1
f 8/7/1 6/8/1 2/6/1
-
-# back-green
f 4/2/3 3/1/3 7/4/3
f 7/4/3 8/3/3 4/2/3
-
-# left-red
f 3/22/5 1/21/5 5/24/5
f 5/24/5 7/23/5 3/22/5
-
-
-
-
-
-
-
diff --git a/examples/models/resources/pbr/trooper_albedo.png b/examples/models/resources/pbr/trooper_albedo.png
index ac1422e4..9ba0f5a6 100644
--- a/examples/models/resources/pbr/trooper_albedo.png
+++ b/examples/models/resources/pbr/trooper_albedo.png
Binary files differ
diff --git a/examples/models/resources/pbr/trooper_ao.png b/examples/models/resources/pbr/trooper_ao.png
index 8567f7b4..442dd7fb 100644
--- a/examples/models/resources/pbr/trooper_ao.png
+++ b/examples/models/resources/pbr/trooper_ao.png
Binary files differ
diff --git a/examples/models/resources/pbr/trooper_normals.png b/examples/models/resources/pbr/trooper_normals.png
index 59c7bdc4..e04be883 100644
--- a/examples/models/resources/pbr/trooper_normals.png
+++ b/examples/models/resources/pbr/trooper_normals.png
Binary files differ
diff --git a/examples/models/resources/pbr/trooper_roughness.png b/examples/models/resources/pbr/trooper_roughness.png
index 53186d51..29f418f7 100644
--- a/examples/models/resources/pbr/trooper_roughness.png
+++ b/examples/models/resources/pbr/trooper_roughness.png
Binary files differ
diff --git a/examples/models/resources/shaders/brdf.fs b/examples/models/resources/shaders/glsl100/brdf.fs
index 3e8777d2..d04bc661 100644
--- a/examples/models/resources/shaders/brdf.fs
+++ b/examples/models/resources/shaders/glsl100/brdf.fs
@@ -10,13 +10,13 @@
#version 330
-#define MAX_SAMPLES 1024u
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
// Constant values
const float PI = 3.14159265359;
+const uint MAX_SAMPLES = 1024u;
// Output fragment color
out vec4 finalColor;
@@ -93,7 +93,7 @@ vec2 IntegrateBRDF(float NdotV, float roughness)
vec3 V = vec3(sqrt(1.0 - NdotV*NdotV), 0.0, NdotV);
vec3 N = vec3(0.0, 0.0, 1.0);
- for (int i = 0; i < MAX_SAMPLES; i++)
+ for (uint i = 0u; i < MAX_SAMPLES; i++)
{
// Generate a sample vector that's biased towards the preferred alignment direction (importance sampling)
diff --git a/examples/models/resources/shaders/brdf.vs b/examples/models/resources/shaders/glsl100/brdf.vs
index 06384673..06384673 100644
--- a/examples/models/resources/shaders/brdf.vs
+++ b/examples/models/resources/shaders/glsl100/brdf.vs
diff --git a/examples/models/resources/shaders/cubemap.fs b/examples/models/resources/shaders/glsl100/cubemap.fs
index e8e28536..e8e28536 100644
--- a/examples/models/resources/shaders/cubemap.fs
+++ b/examples/models/resources/shaders/glsl100/cubemap.fs
diff --git a/examples/models/resources/shaders/cubemap.vs b/examples/models/resources/shaders/glsl100/cubemap.vs
index 5721eaa2..5721eaa2 100644
--- a/examples/models/resources/shaders/cubemap.vs
+++ b/examples/models/resources/shaders/glsl100/cubemap.vs
diff --git a/examples/models/resources/shaders/irradiance.fs b/examples/models/resources/shaders/glsl100/irradiance.fs
index 87113673..b42d2143 100644
--- a/examples/models/resources/shaders/irradiance.fs
+++ b/examples/models/resources/shaders/glsl100/irradiance.fs
@@ -9,7 +9,7 @@
#version 330
// Input vertex attributes (from vertex shader)
-in vec3 fragPos;
+in vec3 fragPosition;
// Input uniform values
uniform samplerCube environmentMap;
@@ -23,7 +23,7 @@ out vec4 finalColor;
void main()
{
// The sample direction equals the hemisphere's orientation
- vec3 normal = normalize(fragPos);
+ vec3 normal = normalize(fragPosition);
vec3 irradiance = vec3(0.0);
diff --git a/examples/models/resources/shaders/pbr.fs b/examples/models/resources/shaders/glsl100/pbr.fs
index 38d56c5d..38d56c5d 100644
--- a/examples/models/resources/shaders/pbr.fs
+++ b/examples/models/resources/shaders/glsl100/pbr.fs
diff --git a/examples/models/resources/shaders/pbr.vs b/examples/models/resources/shaders/glsl100/pbr.vs
index 8bd3faa1..8bd3faa1 100644
--- a/examples/models/resources/shaders/pbr.vs
+++ b/examples/models/resources/shaders/glsl100/pbr.vs
diff --git a/examples/models/resources/shaders/prefilter.fs b/examples/models/resources/shaders/glsl100/prefilter.fs
index f5cf64be..9439810d 100644
--- a/examples/models/resources/shaders/prefilter.fs
+++ b/examples/models/resources/shaders/glsl100/prefilter.fs
@@ -11,7 +11,7 @@
#define CUBEMAP_RESOLUTION 1024.0
// Input vertex attributes (from vertex shader)
-in vec3 fragPos;
+in vec3 fragPosition;
// Input uniform values
uniform samplerCube environmentMap;
@@ -79,7 +79,7 @@ vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
void main()
{
// Make the simplyfying assumption that V equals R equals the normal
- vec3 N = normalize(fragPos);
+ vec3 N = normalize(fragPosition);
vec3 R = N;
vec3 V = R;
diff --git a/examples/models/resources/shaders/skybox.fs b/examples/models/resources/shaders/glsl100/skybox.fs
index 053a2517..053a2517 100644
--- a/examples/models/resources/shaders/skybox.fs
+++ b/examples/models/resources/shaders/glsl100/skybox.fs
diff --git a/examples/models/resources/shaders/skybox.vs b/examples/models/resources/shaders/glsl100/skybox.vs
index dcbe6c3d..dcbe6c3d 100644
--- a/examples/models/resources/shaders/skybox.vs
+++ b/examples/models/resources/shaders/glsl100/skybox.vs
diff --git a/examples/models/resources/shaders/glsl330/brdf.fs b/examples/models/resources/shaders/glsl330/brdf.fs
new file mode 100644
index 00000000..d04bc661
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/brdf.fs
@@ -0,0 +1,133 @@
+/*******************************************************************************************
+*
+* BRDF LUT Generation - Bidirectional reflectance distribution function fragment shader
+*
+* REF: https://github.com/HectorMF/BRDFGenerator
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+
+// Input vertex attributes (from vertex shader)
+in vec2 fragTexCoord;
+
+// Constant values
+const float PI = 3.14159265359;
+const uint MAX_SAMPLES = 1024u;
+
+// Output fragment color
+out vec4 finalColor;
+
+vec2 Hammersley(uint i, uint N);
+float RadicalInverseVdC(uint bits);
+float GeometrySchlickGGX(float NdotV, float roughness);
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness);
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);
+vec2 IntegrateBRDF(float NdotV, float roughness);
+
+float RadicalInverseVdC(uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+// Compute Hammersley coordinates
+vec2 Hammersley(uint i, uint N)
+{
+ return vec2(float(i)/float(N), RadicalInverseVdC(i));
+}
+
+// Integrate number of importance samples for (roughness and NoV)
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
+{
+ float a = roughness*roughness;
+ float phi = 2.0 * PI * Xi.x;
+ float cosTheta = sqrt((1.0 - Xi.y)/(1.0 + (a*a - 1.0)*Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
+
+ // Transform from spherical coordinates to cartesian coordinates (halfway vector)
+ vec3 H = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta);
+
+ // Transform from tangent space H vector to world space sample vector
+ vec3 up = ((abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0));
+ vec3 tangent = normalize(cross(up, N));
+ vec3 bitangent = cross(N, tangent);
+ vec3 sampleVec = tangent*H.x + bitangent*H.y + N*H.z;
+
+ return normalize(sampleVec);
+}
+
+float GeometrySchlickGGX(float NdotV, float roughness)
+{
+ // For IBL k is calculated different
+ float k = (roughness*roughness)/2.0;
+
+ float nom = NdotV;
+ float denom = NdotV*(1.0 - k) + k;
+
+ return nom/denom;
+}
+
+// Compute the geometry term for the BRDF given roughness squared, NoV, NoL
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
+{
+ float NdotV = max(dot(N, V), 0.0);
+ float NdotL = max(dot(N, L), 0.0);
+ float ggx2 = GeometrySchlickGGX(NdotV, roughness);
+ float ggx1 = GeometrySchlickGGX(NdotL, roughness);
+
+ return ggx1*ggx2;
+}
+
+vec2 IntegrateBRDF(float NdotV, float roughness)
+{
+ float A = 0.0;
+ float B = 0.0;
+ vec3 V = vec3(sqrt(1.0 - NdotV*NdotV), 0.0, NdotV);
+ vec3 N = vec3(0.0, 0.0, 1.0);
+
+ for (uint i = 0u; i < MAX_SAMPLES; i++)
+ {
+ // Generate a sample vector that's biased towards the preferred alignment direction (importance sampling)
+
+ vec2 Xi = Hammersley(i, MAX_SAMPLES); // Compute a Hammersely coordinate
+ vec3 H = ImportanceSampleGGX(Xi, N, roughness); // Integrate number of importance samples for (roughness and NoV)
+ vec3 L = normalize(2.0*dot(V, H)*H - V); // Compute reflection vector L
+
+ float NdotL = max(L.z, 0.0); // Compute normal dot light
+ float NdotH = max(H.z, 0.0); // Compute normal dot half
+ float VdotH = max(dot(V, H), 0.0); // Compute view dot half
+
+ if (NdotL > 0.0)
+ {
+ float G = GeometrySmith(N, V, L, roughness); // Compute the geometry term for the BRDF given roughness squared, NoV, NoL
+ float GVis = (G*VdotH)/(NdotH*NdotV); // Compute the visibility term given G, VoH, NoH, NoV, NoL
+ float Fc = pow(1.0 - VdotH, 5.0); // Compute the fresnel term given VoH
+
+ A += (1.0 - Fc)*GVis; // Sum the result given fresnel, geometry, visibility
+ B += Fc*GVis;
+ }
+ }
+
+ // Calculate brdf average sample
+ A /= float(MAX_SAMPLES);
+ B /= float(MAX_SAMPLES);
+
+ return vec2(A, B);
+}
+
+void main()
+{
+ // Calculate brdf based on texture coordinates
+ vec2 brdf = IntegrateBRDF(fragTexCoord.x, fragTexCoord.y);
+
+ // Calculate final fragment color
+ finalColor = vec4(brdf.r, brdf.g, 0.0, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/brdf.vs b/examples/models/resources/shaders/glsl330/brdf.vs
new file mode 100644
index 00000000..06384673
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/brdf.vs
@@ -0,0 +1,25 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Bidirectional reflectance distribution function vertex shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes
+in vec3 vertexPosition;
+in vec2 vertexTexCoord;
+
+// Output vertex attributes (to fragment shader)
+out vec2 fragTexCoord;
+
+void main()
+{
+ // Calculate fragment position based on model transformations
+ fragTexCoord = vertexTexCoord;
+
+ // Calculate final vertex position
+ gl_Position = vec4(vertexPosition, 1.0);
+} \ No newline at end of file
diff --git a/examples/models/resources/shaders/glsl330/cubemap.fs b/examples/models/resources/shaders/glsl330/cubemap.fs
new file mode 100644
index 00000000..e8e28536
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/cubemap.fs
@@ -0,0 +1,38 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Equirectangular to cubemap fragment shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes (from vertex shader)
+in vec3 fragPosition;
+
+// Input uniform values
+uniform sampler2D equirectangularMap;
+
+// Output fragment color
+out vec4 finalColor;
+
+vec2 SampleSphericalMap(vec3 v)
+{
+ vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
+ uv *= vec2(0.1591, 0.3183);
+ uv += 0.5;
+ return uv;
+}
+
+void main()
+{
+ // Normalize local position
+ vec2 uv = SampleSphericalMap(normalize(fragPosition));
+
+ // Fetch color from texture map
+ vec3 color = texture(equirectangularMap, uv).rgb;
+
+ // Calculate final fragment color
+ finalColor = vec4(color, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/cubemap.vs b/examples/models/resources/shaders/glsl330/cubemap.vs
new file mode 100644
index 00000000..5721eaa2
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/cubemap.vs
@@ -0,0 +1,28 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Equirectangular to cubemap vertex shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes
+in vec3 vertexPosition;
+
+// Input uniform values
+uniform mat4 projection;
+uniform mat4 view;
+
+// Output vertex attributes (to fragment shader)
+out vec3 fragPosition;
+
+void main()
+{
+ // Calculate fragment position based on model transformations
+ fragPosition = vertexPosition;
+
+ // Calculate final vertex position
+ gl_Position = projection*view*vec4(vertexPosition, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/irradiance.fs b/examples/models/resources/shaders/glsl330/irradiance.fs
new file mode 100644
index 00000000..b42d2143
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/irradiance.fs
@@ -0,0 +1,58 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Irradiance cubemap fragment shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes (from vertex shader)
+in vec3 fragPosition;
+
+// Input uniform values
+uniform samplerCube environmentMap;
+
+// Constant values
+const float PI = 3.14159265359f;
+
+// Output fragment color
+out vec4 finalColor;
+
+void main()
+{
+ // The sample direction equals the hemisphere's orientation
+ vec3 normal = normalize(fragPosition);
+
+ vec3 irradiance = vec3(0.0);
+
+ vec3 up = vec3(0.0, 1.0, 0.0);
+ vec3 right = cross(up, normal);
+ up = cross(normal, right);
+
+ float sampleDelta = 0.025f;
+ float nrSamples = 0.0f;
+
+ for (float phi = 0.0; phi < 2.0*PI; phi += sampleDelta)
+ {
+ for (float theta = 0.0; theta < 0.5*PI; theta += sampleDelta)
+ {
+ // Spherical to cartesian (in tangent space)
+ vec3 tangentSample = vec3(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta));
+
+ // tangent space to world
+ vec3 sampleVec = tangentSample.x*right + tangentSample.y*up + tangentSample.z*normal;
+
+ // Fetch color from environment cubemap
+ irradiance += texture(environmentMap, sampleVec).rgb*cos(theta)*sin(theta);
+ nrSamples++;
+ }
+ }
+
+ // Calculate irradiance average value from samples
+ irradiance = PI*irradiance*(1.0/float(nrSamples));
+
+ // Calculate final fragment color
+ finalColor = vec4(irradiance, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/pbr.fs b/examples/models/resources/shaders/glsl330/pbr.fs
new file mode 100644
index 00000000..38d56c5d
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/pbr.fs
@@ -0,0 +1,298 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Physically based rendering fragment shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+#define MAX_REFLECTION_LOD 4.0
+#define MAX_DEPTH_LAYER 20
+#define MIN_DEPTH_LAYER 10
+
+#define MAX_LIGHTS 4
+#define LIGHT_DIRECTIONAL 0
+#define LIGHT_POINT 1
+
+struct MaterialProperty {
+ vec3 color;
+ int useSampler;
+ sampler2D sampler;
+};
+
+struct Light {
+ int enabled;
+ int type;
+ vec3 position;
+ vec3 target;
+ vec4 color;
+};
+
+// Input vertex attributes (from vertex shader)
+in vec3 fragPosition;
+in vec2 fragTexCoord;
+in vec3 fragNormal;
+in vec3 fragTangent;
+in vec3 fragBinormal;
+
+// Input material values
+uniform MaterialProperty albedo;
+uniform MaterialProperty normals;
+uniform MaterialProperty metalness;
+uniform MaterialProperty roughness;
+uniform MaterialProperty occlusion;
+uniform MaterialProperty emission;
+uniform MaterialProperty height;
+
+// Input uniform values
+uniform samplerCube irradianceMap;
+uniform samplerCube prefilterMap;
+uniform sampler2D brdfLUT;
+
+// Input lighting values
+uniform Light lights[MAX_LIGHTS];
+
+// Other uniform values
+uniform int renderMode;
+uniform vec3 viewPos;
+vec2 texCoord;
+
+// Constant values
+const float PI = 3.14159265359;
+
+// Output fragment color
+out vec4 finalColor;
+
+vec3 ComputeMaterialProperty(MaterialProperty property);
+float DistributionGGX(vec3 N, vec3 H, float roughness);
+float GeometrySchlickGGX(float NdotV, float roughness);
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness);
+vec3 fresnelSchlick(float cosTheta, vec3 F0);
+vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness);
+vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir);
+
+vec3 ComputeMaterialProperty(MaterialProperty property)
+{
+ vec3 result = vec3(0.0, 0.0, 0.0);
+
+ if (property.useSampler == 1) result = texture(property.sampler, texCoord).rgb;
+ else result = property.color;
+
+ return result;
+}
+
+float DistributionGGX(vec3 N, vec3 H, float roughness)
+{
+ float a = roughness*roughness;
+ float a2 = a*a;
+ float NdotH = max(dot(N, H), 0.0);
+ float NdotH2 = NdotH*NdotH;
+
+ float nom = a2;
+ float denom = (NdotH2*(a2 - 1.0) + 1.0);
+ denom = PI*denom*denom;
+
+ return nom/denom;
+}
+
+float GeometrySchlickGGX(float NdotV, float roughness)
+{
+ float r = (roughness + 1.0);
+ float k = r*r/8.0;
+
+ float nom = NdotV;
+ float denom = NdotV*(1.0 - k) + k;
+
+ return nom/denom;
+}
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
+{
+ float NdotV = max(dot(N, V), 0.0);
+ float NdotL = max(dot(N, L), 0.0);
+ float ggx2 = GeometrySchlickGGX(NdotV, roughness);
+ float ggx1 = GeometrySchlickGGX(NdotL, roughness);
+
+ return ggx1*ggx2;
+}
+
+vec3 fresnelSchlick(float cosTheta, vec3 F0)
+{
+ return F0 + (1.0 - F0)*pow(1.0 - cosTheta, 5.0);
+}
+
+vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
+{
+ return F0 + (max(vec3(1.0 - roughness), F0) - F0)*pow(1.0 - cosTheta, 5.0);
+}
+
+vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir)
+{
+ // Calculate the number of depth layers and calculate the size of each layer
+ float numLayers = mix(MAX_DEPTH_LAYER, MIN_DEPTH_LAYER, abs(dot(vec3(0.0, 0.0, 1.0), viewDir)));
+ float layerDepth = 1.0/numLayers;
+
+ // Calculate depth of current layer
+ float currentLayerDepth = 0.0;
+
+ // Calculate the amount to shift the texture coordinates per layer (from vector P)
+ // Note: height amount is stored in height material attribute color R channel (sampler use is independent)
+ vec2 P = viewDir.xy*height.color.r;
+ vec2 deltaTexCoords = P/numLayers;
+
+ // Store initial texture coordinates and depth values
+ vec2 currentTexCoords = texCoords;
+ float currentDepthMapValue = texture(height.sampler, currentTexCoords).r;
+
+ while (currentLayerDepth < currentDepthMapValue)
+ {
+ // Shift texture coordinates along direction of P
+ currentTexCoords -= deltaTexCoords;
+
+ // Get depth map value at current texture coordinates
+ currentDepthMapValue = texture(height.sampler, currentTexCoords).r;
+
+ // Get depth of next layer
+ currentLayerDepth += layerDepth;
+ }
+
+ // Get texture coordinates before collision (reverse operations)
+ vec2 prevTexCoords = currentTexCoords + deltaTexCoords;
+
+ // Get depth after and before collision for linear interpolation
+ float afterDepth = currentDepthMapValue - currentLayerDepth;
+ float beforeDepth = texture(height.sampler, prevTexCoords).r - currentLayerDepth + layerDepth;
+
+ // Interpolation of texture coordinates
+ float weight = afterDepth/(afterDepth - beforeDepth);
+ vec2 finalTexCoords = prevTexCoords*weight + currentTexCoords*(1.0 - weight);
+
+ return finalTexCoords;
+}
+
+void main()
+{
+ // Calculate TBN and RM matrices
+ mat3 TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
+
+ // Calculate lighting required attributes
+ vec3 normal = normalize(fragNormal);
+ vec3 view = normalize(viewPos - fragPosition);
+ vec3 refl = reflect(-view, normal);
+
+ // Check if parallax mapping is enabled and calculate texture coordinates to use based on height map
+ // NOTE: remember that 'texCoord' variable must be assigned before calling any ComputeMaterialProperty() function
+ if (height.useSampler == 1) texCoord = ParallaxMapping(fragTexCoord, view);
+ else texCoord = fragTexCoord; // Use default texture coordinates
+
+ // Fetch material values from texture sampler or color attributes
+ vec3 color = ComputeMaterialProperty(albedo);
+ vec3 metal = ComputeMaterialProperty(metalness);
+ vec3 rough = ComputeMaterialProperty(roughness);
+ vec3 emiss = ComputeMaterialProperty(emission);
+ vec3 ao = ComputeMaterialProperty(occlusion);
+
+ // Check if normal mapping is enabled
+ if (normals.useSampler == 1)
+ {
+ // Fetch normal map color and transform lighting values to tangent space
+ normal = ComputeMaterialProperty(normals);
+ normal = normalize(normal*2.0 - 1.0);
+ normal = normalize(normal*TBN);
+
+ // Convert tangent space normal to world space due to cubemap reflection calculations
+ refl = normalize(reflect(-view, normal));
+ }
+
+ // Calculate reflectance at normal incidence
+ vec3 F0 = vec3(0.04);
+ F0 = mix(F0, color, metal.r);
+
+ // Calculate lighting for all lights
+ vec3 Lo = vec3(0.0);
+ vec3 lightDot = vec3(0.0);
+
+ for (int i = 0; i < MAX_LIGHTS; i++)
+ {
+ if (lights[i].enabled == 1)
+ {
+ // Calculate per-light radiance
+ vec3 light = vec3(0.0);
+ vec3 radiance = lights[i].color.rgb;
+ if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position);
+ else if (lights[i].type == LIGHT_POINT)
+ {
+ light = normalize(lights[i].position - fragPosition);
+ float distance = length(lights[i].position - fragPosition);
+ float attenuation = 1.0/(distance*distance);
+ radiance *= attenuation;
+ }
+
+ // Cook-torrance BRDF
+ vec3 high = normalize(view + light);
+ float NDF = DistributionGGX(normal, high, rough.r);
+ float G = GeometrySmith(normal, view, light, rough.r);
+ vec3 F = fresnelSchlick(max(dot(high, view), 0.0), F0);
+ vec3 nominator = NDF*G*F;
+ float denominator = 4*max(dot(normal, view), 0.0)*max(dot(normal, light), 0.0) + 0.001;
+ vec3 brdf = nominator/denominator;
+
+ // Store to kS the fresnel value and calculate energy conservation
+ vec3 kS = F;
+ vec3 kD = vec3(1.0) - kS;
+
+ // Multiply kD by the inverse metalness such that only non-metals have diffuse lighting
+ kD *= 1.0 - metal.r;
+
+ // Scale light by dot product between normal and light direction
+ float NdotL = max(dot(normal, light), 0.0);
+
+ // Add to outgoing radiance Lo
+ // Note: BRDF is already multiplied by the Fresnel so it doesn't need to be multiplied again
+ Lo += (kD*color/PI + brdf)*radiance*NdotL*lights[i].color.a;
+ lightDot += radiance*NdotL + brdf*lights[i].color.a;
+ }
+ }
+
+ // Calculate ambient lighting using IBL
+ vec3 F = fresnelSchlickRoughness(max(dot(normal, view), 0.0), F0, rough.r);
+ vec3 kS = F;
+ vec3 kD = 1.0 - kS;
+ kD *= 1.0 - metal.r;
+
+ // Calculate indirect diffuse
+ vec3 irradiance = texture(irradianceMap, fragNormal).rgb;
+ vec3 diffuse = color*irradiance;
+
+ // Sample both the prefilter map and the BRDF lut and combine them together as per the Split-Sum approximation
+ vec3 prefilterColor = textureLod(prefilterMap, refl, rough.r*MAX_REFLECTION_LOD).rgb;
+ vec2 brdf = texture(brdfLUT, vec2(max(dot(normal, view), 0.0), rough.r)).rg;
+ vec3 reflection = prefilterColor*(F*brdf.x + brdf.y);
+
+ // Calculate final lighting
+ vec3 ambient = (kD*diffuse + reflection)*ao;
+
+ // Calculate fragment color based on render mode
+ vec3 fragmentColor = ambient + Lo + emiss; // Physically Based Rendering
+
+ if (renderMode == 1) fragmentColor = color; // Albedo
+ else if (renderMode == 2) fragmentColor = normal; // Normals
+ else if (renderMode == 3) fragmentColor = metal; // Metalness
+ else if (renderMode == 4) fragmentColor = rough; // Roughness
+ else if (renderMode == 5) fragmentColor = ao; // Ambient Occlusion
+ else if (renderMode == 6) fragmentColor = emiss; // Emission
+ else if (renderMode == 7) fragmentColor = lightDot; // Lighting
+ else if (renderMode == 8) fragmentColor = kS; // Fresnel
+ else if (renderMode == 9) fragmentColor = irradiance; // Irradiance
+ else if (renderMode == 10) fragmentColor = reflection; // Reflection
+
+ // Apply HDR tonemapping
+ fragmentColor = fragmentColor/(fragmentColor + vec3(1.0));
+
+ // Apply gamma correction
+ fragmentColor = pow(fragmentColor, vec3(1.0/2.2));
+
+ // Calculate final fragment color
+ finalColor = vec4(fragmentColor, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/pbr.vs b/examples/models/resources/shaders/glsl330/pbr.vs
new file mode 100644
index 00000000..8bd3faa1
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/pbr.vs
@@ -0,0 +1,49 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Physically based rendering vertex shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes
+in vec3 vertexPosition;
+in vec2 vertexTexCoord;
+in vec3 vertexNormal;
+in vec4 vertexTangent;
+
+// Input uniform values
+uniform mat4 mvp;
+uniform mat4 matModel;
+
+// Output vertex attributes (to fragment shader)
+out vec3 fragPosition;
+out vec2 fragTexCoord;
+out vec3 fragNormal;
+out vec3 fragTangent;
+out vec3 fragBinormal;
+
+void main()
+{
+ // Calculate binormal from vertex normal and tangent
+ vec3 vertexBinormal = cross(vertexNormal, vec3(vertexTangent));
+
+ // Calculate fragment normal based on normal transformations
+ mat3 normalMatrix = transpose(inverse(mat3(matModel)));
+
+ // Calculate fragment position based on model transformations
+ fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
+
+ // Send vertex attributes to fragment shader
+ fragTexCoord = vertexTexCoord;
+ fragNormal = normalize(normalMatrix*vertexNormal);
+ fragTangent = normalize(normalMatrix*vec3(vertexTangent));
+ fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
+ fragBinormal = normalize(normalMatrix*vertexBinormal);
+ fragBinormal = cross(fragNormal, fragTangent);
+
+ // Calculate final vertex position
+ gl_Position = mvp*vec4(vertexPosition, 1.0);
+} \ No newline at end of file
diff --git a/examples/models/resources/shaders/glsl330/prefilter.fs b/examples/models/resources/shaders/glsl330/prefilter.fs
new file mode 100644
index 00000000..9439810d
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/prefilter.fs
@@ -0,0 +1,120 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Prefiltered environment for reflections fragment shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+#define MAX_SAMPLES 1024u
+#define CUBEMAP_RESOLUTION 1024.0
+
+// Input vertex attributes (from vertex shader)
+in vec3 fragPosition;
+
+// Input uniform values
+uniform samplerCube environmentMap;
+uniform float roughness;
+
+// Constant values
+const float PI = 3.14159265359f;
+
+// Output fragment color
+out vec4 finalColor;
+
+float DistributionGGX(vec3 N, vec3 H, float roughness);
+float RadicalInverse_VdC(uint bits);
+vec2 Hammersley(uint i, uint N);
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);
+
+float DistributionGGX(vec3 N, vec3 H, float roughness)
+{
+ float a = roughness*roughness;
+ float a2 = a*a;
+ float NdotH = max(dot(N, H), 0.0);
+ float NdotH2 = NdotH*NdotH;
+
+ float nom = a2;
+ float denom = (NdotH2*(a2 - 1.0) + 1.0);
+ denom = PI*denom*denom;
+
+ return nom/denom;
+}
+
+float RadicalInverse_VdC(uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+vec2 Hammersley(uint i, uint N)
+{
+ return vec2(float(i)/float(N), RadicalInverse_VdC(i));
+}
+
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
+{
+ float a = roughness*roughness;
+ float phi = 2.0 * PI * Xi.x;
+ float cosTheta = sqrt((1.0 - Xi.y)/(1.0 + (a*a - 1.0)*Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
+
+ // Transform from spherical coordinates to cartesian coordinates (halfway vector)
+ vec3 H = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta);
+
+ // Transform from tangent space H vector to world space sample vector
+ vec3 up = ((abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0));
+ vec3 tangent = normalize(cross(up, N));
+ vec3 bitangent = cross(N, tangent);
+ vec3 sampleVec = tangent*H.x + bitangent*H.y + N*H.z;
+
+ return normalize(sampleVec);
+}
+
+void main()
+{
+ // Make the simplyfying assumption that V equals R equals the normal
+ vec3 N = normalize(fragPosition);
+ vec3 R = N;
+ vec3 V = R;
+
+ vec3 prefilteredColor = vec3(0.0);
+ float totalWeight = 0.0;
+
+ for (uint i = 0u; i < MAX_SAMPLES; i++)
+ {
+ // Generate a sample vector that's biased towards the preferred alignment direction (importance sampling)
+ vec2 Xi = Hammersley(i, MAX_SAMPLES);
+ vec3 H = ImportanceSampleGGX(Xi, N, roughness);
+ vec3 L = normalize(2.0*dot(V, H)*H - V);
+
+ float NdotL = max(dot(N, L), 0.0);
+ if(NdotL > 0.0)
+ {
+ // Sample from the environment's mip level based on roughness/pdf
+ float D = DistributionGGX(N, H, roughness);
+ float NdotH = max(dot(N, H), 0.0);
+ float HdotV = max(dot(H, V), 0.0);
+ float pdf = D*NdotH/(4.0*HdotV) + 0.0001;
+
+ float resolution = CUBEMAP_RESOLUTION;
+ float saTexel = 4.0*PI/(6.0*resolution*resolution);
+ float saSample = 1.0/(float(MAX_SAMPLES)*pdf + 0.0001);
+ float mipLevel = ((roughness == 0.0) ? 0.0 : 0.5*log2(saSample/saTexel));
+
+ prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb*NdotL;
+ totalWeight += NdotL;
+ }
+ }
+
+ // Calculate prefilter average color
+ prefilteredColor = prefilteredColor/totalWeight;
+
+ // Calculate final fragment color
+ finalColor = vec4(prefilteredColor, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/skybox.fs b/examples/models/resources/shaders/glsl330/skybox.fs
new file mode 100644
index 00000000..053a2517
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/skybox.fs
@@ -0,0 +1,31 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Background skybox fragment shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes (from vertex shader)
+in vec3 fragPosition;
+
+// Input uniform values
+uniform samplerCube environmentMap;
+
+// Output fragment color
+out vec4 finalColor;
+
+void main()
+{
+ // Fetch color from texture map
+ vec3 color = texture(environmentMap, fragPosition).rgb;
+
+ // Apply gamma correction
+ color = color/(color + vec3(1.0));
+ color = pow(color, vec3(1.0/2.2));
+
+ // Calculate final fragment color
+ finalColor = vec4(color, 1.0);
+}
diff --git a/examples/models/resources/shaders/glsl330/skybox.vs b/examples/models/resources/shaders/glsl330/skybox.vs
new file mode 100644
index 00000000..4fe9a2c3
--- /dev/null
+++ b/examples/models/resources/shaders/glsl330/skybox.vs
@@ -0,0 +1,32 @@
+/*******************************************************************************************
+*
+* rPBR [shader] - Background skybox vertex shader
+*
+* Copyright (c) 2017 Victor Fisac
+*
+**********************************************************************************************/
+
+#version 330
+
+// Input vertex attributes
+in vec3 vertexPosition;
+
+// Input uniform values
+uniform mat4 projection;
+uniform mat4 view;
+
+// Output vertex attributes (to fragment shader)
+out vec3 fragPosition;
+
+void main()
+{
+ // Calculate fragment position based on model transformations
+ fragPosition = vertexPosition;
+
+ // Remove translation from the view matrix
+ mat4 rotView = mat4(mat3(view));
+ vec4 clipPos = projection*rotView*vec4(vertexPosition, 1.0);
+
+ // Calculate final vertex position
+ gl_Position = clipPos.xyzw;
+}