From be6d237b9ebbe245de4384c17b84e75dab0f4981 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 29 Mar 2019 20:22:50 +0100 Subject: Review models examples --- examples/models/models_cubicmap.c | 2 +- examples/models/models_heightmap.c | 2 +- examples/models/models_material_pbr.c | 14 +++++++------- examples/models/models_mesh_generation.c | 13 ++++++++++++- examples/models/models_mesh_picking.c | 6 +++--- examples/models/models_obj_loading.c | 2 +- examples/models/models_obj_viewer.c | 18 +++++++++--------- examples/models/models_skybox.c | 6 +++--- examples/models/models_yaw_pitch_roll.c | 6 +++--- 9 files changed, 40 insertions(+), 29 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index c8d62c46..ac24188e 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -31,7 +31,7 @@ int main() // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture + model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c index d131b127..e0475f18 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.c @@ -29,7 +29,7 @@ int main() 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 diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index f93c7a68..adb4762b 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -38,16 +38,16 @@ int main() // 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); + 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) + 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 @@ -64,7 +64,7 @@ int main() // 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 diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index d64889bd..2b4b75ab 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -39,7 +39,7 @@ int main() 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 }; @@ -65,6 +65,17 @@ int main() { 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 diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c index 9b12e98c..42028829 100644 --- a/examples/models/models_mesh_picking.c +++ b/examples/models/models_mesh_picking.c @@ -26,7 +26,7 @@ int main() // 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 @@ -36,10 +36,10 @@ int main() 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; diff --git a/examples/models/models_obj_loading.c b/examples/models/models_obj_loading.c index 7ec2d3f0..0251fd3e 100644 --- a/examples/models/models_obj_loading.c +++ b/examples/models/models_obj_loading.c @@ -30,7 +30,7 @@ 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 diff --git a/examples/models/models_obj_viewer.c b/examples/models/models_obj_viewer.c index 15f79549..ffa609e0 100644 --- a/examples/models/models_obj_viewer.c +++ b/examples/models/models_obj_viewer.c @@ -27,13 +27,13 @@ int main() 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 + 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.mesh); // Set model bounds - bool selected = false; // Selected object flag + 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 + SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode char objFilename[64] = "turret.obj"; @@ -54,15 +54,15 @@ int main() { if (IsFileExtension(droppedFiles[0], ".obj")) { - UnloadMesh(&model.mesh); - model.mesh = LoadMesh(droppedFiles[0]); - bounds = MeshBoundingBox(model.mesh); + UnloadMesh(&model.meshes[0]); + model.meshes[0] = LoadMesh(droppedFiles[0]); + 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])); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index c7f76ecf..759c79c6 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -29,8 +29,8 @@ int main() // 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); + skybox.materials[0].shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); + 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"); @@ -41,7 +41,7 @@ int main() // 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 diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 88b0a610..7eaaf0be 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -37,10 +37,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 -- cgit v1.2.3 From 26fb2e0f3a5047dd77bfea82543a341aa25dda7a Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 1 Apr 2019 00:15:14 +0200 Subject: Update cube.obj --- examples/models/resources/models/cube.obj | 44 +++++-------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) (limited to 'examples/models') 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 - - - - - - - -- cgit v1.2.3 From 38a13b76d13c6e4f6f6c02bfd63900de56de4a42 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 5 Apr 2019 13:13:42 +0200 Subject: Corrected issue with LoadMesh() --- examples/models/models_obj_loading.c | 2 +- examples/models/models_obj_viewer.c | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_obj_loading.c b/examples/models/models_obj_loading.c index 0251fd3e..74e7d08a 100644 --- a/examples/models/models_obj_loading.c +++ b/examples/models/models_obj_loading.c @@ -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 ffa609e0..0581df34 100644 --- a/examples/models/models_obj_viewer.c +++ b/examples/models/models_obj_viewer.c @@ -28,11 +28,11 @@ int main() Model model = LoadModel("resources/models/turret.obj"); // Load default model obj Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load default model texture 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 + 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"; @@ -49,13 +49,13 @@ int main() { int count = 0; char **droppedFiles = GetDroppedFiles(&count); - + if (count == 1) { if (IsFileExtension(droppedFiles[0], ".obj")) { - UnloadMesh(&model.meshes[0]); - model.meshes[0] = LoadMesh(droppedFiles[0]); + 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")) @@ -67,12 +67,12 @@ int main() 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 //-------------------------------------------------------------------------------------- -- cgit v1.2.3 From 92733d6695e0cdab3b42972f2cd6ed48d98ec689 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 5 Apr 2019 13:15:56 +0200 Subject: BIG UPDATE: New models functions for animations! Multiple functions added and some reviewed to adapt to the new multi-mesh, multi-material and animated models. --- examples/models/models_animation.c | 101 ++++++++++++++++++++++++++++++ examples/models/resources/guy/guy.blend | Bin 0 -> 665304 bytes examples/models/resources/guy/guy.iqm | Bin 0 -> 39408 bytes examples/models/resources/guy/guyanim.iqm | Bin 0 -> 18244 bytes examples/models/resources/guy/guytex.png | Bin 0 -> 302388 bytes 5 files changed, 101 insertions(+) create mode 100644 examples/models/models_animation.c create mode 100644 examples/models/resources/guy/guy.blend create mode 100644 examples/models/resources/guy/guy.iqm create mode 100644 examples/models/resources/guy/guyanim.iqm create mode 100644 examples/models/resources/guy/guytex.png (limited to 'examples/models') diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c new file mode 100644 index 00000000..a75241b3 --- /dev/null +++ b/examples/models/models_animation.c @@ -0,0 +1,101 @@ +/******************************************************************************************* +* +* 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) +* +* Copyright (c) 2019 Ramon Santamaria (@raysan5) and @culacant +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + 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/resources/guy/guy.blend b/examples/models/resources/guy/guy.blend new file mode 100644 index 00000000..3880467d Binary files /dev/null and b/examples/models/resources/guy/guy.blend differ diff --git a/examples/models/resources/guy/guy.iqm b/examples/models/resources/guy/guy.iqm new file mode 100644 index 00000000..36bed5e0 Binary files /dev/null and b/examples/models/resources/guy/guy.iqm differ diff --git a/examples/models/resources/guy/guyanim.iqm b/examples/models/resources/guy/guyanim.iqm new file mode 100644 index 00000000..824a68a3 Binary files /dev/null and b/examples/models/resources/guy/guyanim.iqm differ diff --git a/examples/models/resources/guy/guytex.png b/examples/models/resources/guy/guytex.png new file mode 100644 index 00000000..7f813552 Binary files /dev/null and b/examples/models/resources/guy/guytex.png differ -- cgit v1.2.3 From c600dd07668f301fc1a986326d807f341e6ecb78 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 5 Apr 2019 16:43:09 +0200 Subject: Review PBR shaders Issue was related to vertex tangent attibutes not uploaded to GPU, a quick solution was implemented for new vertex attributes loading for already existing meshes... I don't like it specially but it will work for now. --- examples/models/models_material_pbr.c | 8 ++++++++ examples/models/resources/shaders/brdf.fs | 4 ++-- examples/models/resources/shaders/irradiance.fs | 4 ++-- examples/models/resources/shaders/prefilter.fs | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index adb4762b..d393a20d 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -38,7 +38,11 @@ int main() // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); + + // 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 @@ -143,9 +147,13 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) #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); + printf("Loaded shader: cubemap\n"); Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + printf("Loaded shader: irradiance\n"); Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + printf("Loaded shader: prefilter\n"); Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + printf("Loaded shader: brdf\n"); // Setup required shader locations SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT); diff --git a/examples/models/resources/shaders/brdf.fs b/examples/models/resources/shaders/brdf.fs index 3e8777d2..d04bc661 100644 --- a/examples/models/resources/shaders/brdf.fs +++ b/examples/models/resources/shaders/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/irradiance.fs b/examples/models/resources/shaders/irradiance.fs index 87113673..b42d2143 100644 --- a/examples/models/resources/shaders/irradiance.fs +++ b/examples/models/resources/shaders/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/prefilter.fs b/examples/models/resources/shaders/prefilter.fs index f5cf64be..9439810d 100644 --- a/examples/models/resources/shaders/prefilter.fs +++ b/examples/models/resources/shaders/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; -- cgit v1.2.3 From 9282b8ba83909b353fd34a9f584597338c1928bd Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 5 Apr 2019 17:08:46 +0200 Subject: ADDED: SetShaderValueTexture() Some tweaks --- examples/models/models_material_pbr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'examples/models') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index d393a20d..c1d43a24 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -34,7 +34,12 @@ int main() 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"); -- cgit v1.2.3 From c23ceec338ac46c28d0b1fe2ab286775efc7f041 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 5 Apr 2019 17:29:30 +0200 Subject: Added missing include -_- --- examples/models/models_material_pbr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'examples/models') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index c1d43a24..5c308cfc 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 + #define RLIGHTS_IMPLEMENTATION #include "rlights.h" -- cgit v1.2.3 From f21761fbbb02f0b58b5b54342f0c3ad3abc0003e Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sun, 7 Apr 2019 17:49:12 +0200 Subject: Happy new year 2019 --- examples/models/models_obj_viewer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/models') diff --git a/examples/models/models_obj_viewer.c b/examples/models/models_obj_viewer.c index 0581df34..7d387441 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) * ********************************************************************************************/ -- cgit v1.2.3 From 600cdb61a306cd1d5dd78679c0acceb91287b193 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 23 Apr 2019 23:28:11 +0200 Subject: new example: models_first_person_maze -WIP- --- examples/models/models_first_person_maze.c | 84 +++++++++++++++++++++++++++ examples/models/models_first_person_maze.png | Bin 0 -> 327996 bytes 2 files changed, 84 insertions(+) create mode 100644 examples/models/models_first_person_maze.c create mode 100644 examples/models/models_first_person_maze.png (limited to 'examples/models') diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c new file mode 100644 index 00000000..4342b178 --- /dev/null +++ b/examples/models/models_first_person_maze.c @@ -0,0 +1,84 @@ +/******************************************************************************************* +* +* 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" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + 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 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); + UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM + + // 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 + + 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 + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + //---------------------------------------------------------------------------------- + + // 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); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + 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 Binary files /dev/null and b/examples/models/models_first_person_maze.png differ -- cgit v1.2.3 From d46160fb6e85403f67975457631ba4f19824fc6f Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 2 May 2019 12:22:15 +0200 Subject: example review: models_first_person_maze Added walls collision check --- examples/models/models_first_person_maze.c | 48 +++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index 4342b178..be101758 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -23,16 +23,19 @@ int main() // 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 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 }); + 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); - UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM // 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 @@ -46,7 +49,39 @@ int main() { // 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 @@ -64,6 +99,9 @@ int main() 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); @@ -73,6 +111,8 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- + free(mapPixels); // Unload color array + UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture UnloadModel(model); // Unload map model -- cgit v1.2.3 From beda4180cd03166d06f37ba50eb050283c4907e1 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 2 May 2019 13:15:05 +0200 Subject: Added missing include --- examples/models/models_first_person_maze.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'examples/models') diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index be101758..6e6b3214 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -11,6 +11,8 @@ #include "raylib.h" +#include "" // Required for: free() + int main() { // Initialization -- cgit v1.2.3 From 0b2bad4205d0322455ef4535342264dd675c1942 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 2 May 2019 13:24:02 +0200 Subject: Update models_first_person_maze.c --- examples/models/models_first_person_maze.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/models') diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index 6e6b3214..093334ba 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -11,7 +11,7 @@ #include "raylib.h" -#include "" // Required for: free() +#include // Required for: free() int main() { -- cgit v1.2.3 From 424d3ca8d9c5d612606444b2a2099cfad37f1888 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 14 May 2019 15:34:23 +0200 Subject: examples review Redesigns, deletes and renames Also noted authors propertly on contributed examples --- examples/models/models_orthographic_projection.c | 6 ++++-- examples/models/models_yaw_pitch_roll.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index f9b54b6d..3ad32b60 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -4,10 +4,12 @@ * * 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) * ********************************************************************************************/ diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 7eaaf0be..658be084 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) * ********************************************************************************************/ -- cgit v1.2.3 From 245cf2400e3f215b998d4e1f2ae1f9afefa0eb08 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 May 2019 20:03:04 +0200 Subject: Review shader examples --- examples/models/models_material_pbr.c | 44 +-- examples/models/models_skybox.c | 10 +- examples/models/resources/shaders/brdf.fs | 133 --------- examples/models/resources/shaders/brdf.vs | 25 -- examples/models/resources/shaders/cubemap.fs | 38 --- examples/models/resources/shaders/cubemap.vs | 28 -- examples/models/resources/shaders/glsl100/brdf.fs | 133 +++++++++ examples/models/resources/shaders/glsl100/brdf.vs | 25 ++ .../models/resources/shaders/glsl100/cubemap.fs | 38 +++ .../models/resources/shaders/glsl100/cubemap.vs | 28 ++ .../models/resources/shaders/glsl100/irradiance.fs | 58 ++++ examples/models/resources/shaders/glsl100/pbr.fs | 298 +++++++++++++++++++++ examples/models/resources/shaders/glsl100/pbr.vs | 49 ++++ .../models/resources/shaders/glsl100/prefilter.fs | 120 +++++++++ .../models/resources/shaders/glsl100/skybox.fs | 31 +++ .../models/resources/shaders/glsl100/skybox.vs | 32 +++ examples/models/resources/shaders/glsl330/brdf.fs | 133 +++++++++ examples/models/resources/shaders/glsl330/brdf.vs | 25 ++ .../models/resources/shaders/glsl330/cubemap.fs | 38 +++ .../models/resources/shaders/glsl330/cubemap.vs | 28 ++ .../models/resources/shaders/glsl330/irradiance.fs | 58 ++++ examples/models/resources/shaders/glsl330/pbr.fs | 298 +++++++++++++++++++++ examples/models/resources/shaders/glsl330/pbr.vs | 49 ++++ .../models/resources/shaders/glsl330/prefilter.fs | 120 +++++++++ .../models/resources/shaders/glsl330/skybox.fs | 31 +++ .../models/resources/shaders/glsl330/skybox.vs | 32 +++ examples/models/resources/shaders/irradiance.fs | 58 ---- examples/models/resources/shaders/pbr.fs | 298 --------------------- examples/models/resources/shaders/pbr.vs | 49 ---- examples/models/resources/shaders/prefilter.fs | 120 --------- examples/models/resources/shaders/skybox.fs | 31 --- examples/models/resources/shaders/skybox.vs | 32 --- 32 files changed, 1656 insertions(+), 834 deletions(-) delete mode 100644 examples/models/resources/shaders/brdf.fs delete mode 100644 examples/models/resources/shaders/brdf.vs delete mode 100644 examples/models/resources/shaders/cubemap.fs delete mode 100644 examples/models/resources/shaders/cubemap.vs create mode 100644 examples/models/resources/shaders/glsl100/brdf.fs create mode 100644 examples/models/resources/shaders/glsl100/brdf.vs create mode 100644 examples/models/resources/shaders/glsl100/cubemap.fs create mode 100644 examples/models/resources/shaders/glsl100/cubemap.vs create mode 100644 examples/models/resources/shaders/glsl100/irradiance.fs create mode 100644 examples/models/resources/shaders/glsl100/pbr.fs create mode 100644 examples/models/resources/shaders/glsl100/pbr.vs create mode 100644 examples/models/resources/shaders/glsl100/prefilter.fs create mode 100644 examples/models/resources/shaders/glsl100/skybox.fs create mode 100644 examples/models/resources/shaders/glsl100/skybox.vs create mode 100644 examples/models/resources/shaders/glsl330/brdf.fs create mode 100644 examples/models/resources/shaders/glsl330/brdf.vs create mode 100644 examples/models/resources/shaders/glsl330/cubemap.fs create mode 100644 examples/models/resources/shaders/glsl330/cubemap.vs create mode 100644 examples/models/resources/shaders/glsl330/irradiance.fs create mode 100644 examples/models/resources/shaders/glsl330/pbr.fs create mode 100644 examples/models/resources/shaders/glsl330/pbr.vs create mode 100644 examples/models/resources/shaders/glsl330/prefilter.fs create mode 100644 examples/models/resources/shaders/glsl330/skybox.fs create mode 100644 examples/models/resources/shaders/glsl330/skybox.vs delete mode 100644 examples/models/resources/shaders/irradiance.fs delete mode 100644 examples/models/resources/shaders/pbr.fs delete mode 100644 examples/models/resources/shaders/pbr.vs delete mode 100644 examples/models/resources/shaders/prefilter.fs delete mode 100644 examples/models/resources/shaders/skybox.fs delete mode 100644 examples/models/resources/shaders/skybox.vs (limited to 'examples/models') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 5c308cfc..b8d320c7 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -17,6 +17,12 @@ #define RLIGHTS_IMPLEMENTATION #include "rlights.h" +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + #define CUBEMAP_SIZE 512 // Cubemap texture size #define IRRADIANCE_SIZE 32 // Irradiance texture size #define PREFILTERED_SIZE 256 // Prefiltered HDR environment texture size @@ -114,10 +120,8 @@ 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); + mat.shader = LoadShader(FormatText("resources/shaders/glsl%i/pbr.vs", GLSL_VERSION), + FormatText("resources/shaders/glsl%i/pbr.fs", GLSL_VERSION)); // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code @@ -144,23 +148,21 @@ 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); - printf("Loaded shader: cubemap\n"); - Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - printf("Loaded shader: irradiance\n"); - Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - printf("Loaded shader: prefilter\n"); - Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - printf("Loaded shader: brdf\n"); + // Load equirectangular to cubemap shader + Shader shdrCubemap = LoadShader(FormatText("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION), + FormatText("resources/shaders/glsl%i/cubemap.fs", GLSL_VERSION)); + + // Load irradiance (GI) calculation shader + Shader shdrIrradiance = LoadShader(FormatText("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION), + FormatText("resources/shaders/glsl%i/irradiance.fs", GLSL_VERSION)); + + // Load reflection prefilter calculation shader + Shader shdrPrefilter = LoadShader(FormatText("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION), + FormatText("resources/shaders/glsl%i/prefilter.fs", GLSL_VERSION)); + + // Load bidirectional reflectance distribution function shader + Shader shdrBRDF = LoadShader(FormatText("resources/shaders/glsl%i/brdf.vs", GLSL_VERSION), + FormatText("resources/shaders/glsl%i/brdf.fs", GLSL_VERSION)); // Setup required shader locations SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 759c79c6..2d4d5710 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -11,6 +11,12 @@ #include "raylib.h" +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + int main() { // Initialization @@ -29,7 +35,9 @@ int main() // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading - skybox.materials[0].shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); + skybox.materials[0].shader = LoadShader(FormatText("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION), + FormatText("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION)); + 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 diff --git a/examples/models/resources/shaders/brdf.fs b/examples/models/resources/shaders/brdf.fs deleted file mode 100644 index d04bc661..00000000 --- a/examples/models/resources/shaders/brdf.fs +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************************* -* -* 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/brdf.vs b/examples/models/resources/shaders/brdf.vs deleted file mode 100644 index 06384673..00000000 --- a/examples/models/resources/shaders/brdf.vs +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************************* -* -* 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/cubemap.fs b/examples/models/resources/shaders/cubemap.fs deleted file mode 100644 index e8e28536..00000000 --- a/examples/models/resources/shaders/cubemap.fs +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************************* -* -* 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/cubemap.vs b/examples/models/resources/shaders/cubemap.vs deleted file mode 100644 index 5721eaa2..00000000 --- a/examples/models/resources/shaders/cubemap.vs +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************************* -* -* 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/glsl100/brdf.fs b/examples/models/resources/shaders/glsl100/brdf.fs new file mode 100644 index 00000000..d04bc661 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/brdf.vs b/examples/models/resources/shaders/glsl100/brdf.vs new file mode 100644 index 00000000..06384673 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/cubemap.fs b/examples/models/resources/shaders/glsl100/cubemap.fs new file mode 100644 index 00000000..e8e28536 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/cubemap.vs b/examples/models/resources/shaders/glsl100/cubemap.vs new file mode 100644 index 00000000..5721eaa2 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/irradiance.fs b/examples/models/resources/shaders/glsl100/irradiance.fs new file mode 100644 index 00000000..b42d2143 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/pbr.fs b/examples/models/resources/shaders/glsl100/pbr.fs new file mode 100644 index 00000000..38d56c5d --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/pbr.vs b/examples/models/resources/shaders/glsl100/pbr.vs new file mode 100644 index 00000000..8bd3faa1 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/prefilter.fs b/examples/models/resources/shaders/glsl100/prefilter.fs new file mode 100644 index 00000000..9439810d --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/skybox.fs b/examples/models/resources/shaders/glsl100/skybox.fs new file mode 100644 index 00000000..053a2517 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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/glsl100/skybox.vs b/examples/models/resources/shaders/glsl100/skybox.vs new file mode 100644 index 00000000..dcbe6c3d --- /dev/null +++ b/examples/models/resources/shaders/glsl100/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.xyww; +} 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..dcbe6c3d --- /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.xyww; +} diff --git a/examples/models/resources/shaders/irradiance.fs b/examples/models/resources/shaders/irradiance.fs deleted file mode 100644 index b42d2143..00000000 --- a/examples/models/resources/shaders/irradiance.fs +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************************* -* -* 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/pbr.fs b/examples/models/resources/shaders/pbr.fs deleted file mode 100644 index 38d56c5d..00000000 --- a/examples/models/resources/shaders/pbr.fs +++ /dev/null @@ -1,298 +0,0 @@ -/******************************************************************************************* -* -* 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/pbr.vs b/examples/models/resources/shaders/pbr.vs deleted file mode 100644 index 8bd3faa1..00000000 --- a/examples/models/resources/shaders/pbr.vs +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************************* -* -* 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/prefilter.fs b/examples/models/resources/shaders/prefilter.fs deleted file mode 100644 index 9439810d..00000000 --- a/examples/models/resources/shaders/prefilter.fs +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************************* -* -* 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/skybox.fs b/examples/models/resources/shaders/skybox.fs deleted file mode 100644 index 053a2517..00000000 --- a/examples/models/resources/shaders/skybox.fs +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************************* -* -* 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/skybox.vs b/examples/models/resources/shaders/skybox.vs deleted file mode 100644 index dcbe6c3d..00000000 --- a/examples/models/resources/shaders/skybox.vs +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************************* -* -* 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.xyww; -} -- cgit v1.2.3 From 6332bc039878c870538ce4c1ce47d3caaf3a40c4 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 18 May 2019 01:24:00 +0200 Subject: Corrected issue with shader loading When using FormatText() several times in same function, returned string is static and so, the same is returned, resulting in failures on shader loading. --- examples/models/models_material_pbr.c | 45 +++++++++++++--------- examples/models/models_skybox.c | 20 +++++----- .../models/resources/shaders/glsl330/skybox.vs | 2 +- 3 files changed, 38 insertions(+), 29 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index b8d320c7..af2fc5b9 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -17,12 +17,6 @@ #define RLIGHTS_IMPLEMENTATION #include "rlights.h" -#if defined(PLATFORM_DESKTOP) - #define GLSL_VERSION 330 -#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB - #define GLSL_VERSION 100 -#endif - #define CUBEMAP_SIZE 512 // Cubemap texture size #define IRRADIANCE_SIZE 32 // Irradiance texture size #define PREFILTERED_SIZE 256 // Prefiltered HDR environment texture size @@ -120,9 +114,12 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } - mat.shader = LoadShader(FormatText("resources/shaders/glsl%i/pbr.vs", GLSL_VERSION), - FormatText("resources/shaders/glsl%i/pbr.fs", GLSL_VERSION)); - +#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"); @@ -149,20 +146,32 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); // Load equirectangular to cubemap shader - Shader shdrCubemap = LoadShader(FormatText("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION), - FormatText("resources/shaders/glsl%i/cubemap.fs", GLSL_VERSION)); +#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 - Shader shdrIrradiance = LoadShader(FormatText("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION), - FormatText("resources/shaders/glsl%i/irradiance.fs", GLSL_VERSION)); +#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 - Shader shdrPrefilter = LoadShader(FormatText("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION), - FormatText("resources/shaders/glsl%i/prefilter.fs", GLSL_VERSION)); +#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 - Shader shdrBRDF = LoadShader(FormatText("resources/shaders/glsl%i/brdf.vs", GLSL_VERSION), - FormatText("resources/shaders/glsl%i/brdf.fs", GLSL_VERSION)); + // 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); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 2d4d5710..d3369b70 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -11,12 +11,6 @@ #include "raylib.h" -#if defined(PLATFORM_DESKTOP) - #define GLSL_VERSION 330 -#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB - #define GLSL_VERSION 100 -#endif - int main() { // Initialization @@ -35,13 +29,19 @@ int main() // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading - skybox.materials[0].shader = LoadShader(FormatText("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION), - FormatText("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION)); - +#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 diff --git a/examples/models/resources/shaders/glsl330/skybox.vs b/examples/models/resources/shaders/glsl330/skybox.vs index dcbe6c3d..4fe9a2c3 100644 --- a/examples/models/resources/shaders/glsl330/skybox.vs +++ b/examples/models/resources/shaders/glsl330/skybox.vs @@ -28,5 +28,5 @@ void main() vec4 clipPos = projection*rotView*vec4(vertexPosition, 1.0); // Calculate final vertex position - gl_Position = clipPos.xyww; + gl_Position = clipPos.xyzw; } -- cgit v1.2.3 From c1594fa445d038e40bae22eb69dfa04cc406aca4 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 18 May 2019 01:31:48 +0200 Subject: Tweaks --- examples/models/models_animation.png | Bin 0 -> 67020 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/models/models_animation.png (limited to 'examples/models') diff --git a/examples/models/models_animation.png b/examples/models/models_animation.png new file mode 100644 index 00000000..57e39dd3 Binary files /dev/null and b/examples/models/models_animation.png differ -- cgit v1.2.3 From b525039e0ab8bcaa2fd6bde34c72a6405f88ae49 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 May 2019 16:36:42 +0200 Subject: Review ALL examples --- examples/models/models_animation.c | 10 +-- examples/models/models_billboard.c | 16 ++--- examples/models/models_box_collisions.c | 58 ++++++++--------- examples/models/models_cubicmap.c | 18 +++--- examples/models/models_first_person_maze.c | 34 +++++----- examples/models/models_geometric_shapes.c | 8 +-- examples/models/models_heightmap.c | 12 ++-- examples/models/models_material_pbr.c | 28 ++++----- examples/models/models_mesh_generation.c | 36 +++++------ examples/models/models_mesh_picking.c | 79 ++++++++++++------------ examples/models/models_obj_loading.c | 8 +-- examples/models/models_obj_viewer.c | 8 +-- examples/models/models_orthographic_projection.c | 18 +++--- examples/models/models_rlgl_solar_system.c | 30 ++++----- examples/models/models_skybox.c | 20 +++--- examples/models/models_yaw_pitch_roll.c | 9 +-- 16 files changed, 194 insertions(+), 198 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c index a75241b3..294b07a5 100644 --- a/examples/models/models_animation.c +++ b/examples/models/models_animation.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 - model animation"); @@ -32,7 +32,7 @@ int main() 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 @@ -91,7 +91,7 @@ int main() //-------------------------------------------------------------------------------------- // Unload model animations data for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]); - + UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context 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..0dd0710e 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 }; - + 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 ac24188e..f399a56e 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.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 - cubesmap loading and drawing"); @@ -25,18 +25,18 @@ int main() Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) - + Mesh mesh = GenMeshCubicmap(image, (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 - + 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 index 093334ba..42363747 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -13,12 +13,12 @@ #include // Required for: free() -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 - first person maze"); @@ -29,18 +29,18 @@ int main() 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 @@ -52,23 +52,23 @@ int main() // 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++) @@ -76,7 +76,7 @@ int main() 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, + (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 @@ -98,10 +98,10 @@ int main() //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); @@ -114,7 +114,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- free(mapPixels); // Unload color array - + UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture UnloadModel(model); // Unload map model 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 e0475f18..e242db16 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.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 - heightmap loading and drawing"); @@ -25,7 +25,7 @@ int main() 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 @@ -33,7 +33,7 @@ int main() 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 af2fc5b9..8d51eefd 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -25,12 +25,12 @@ // 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"); @@ -45,7 +45,7 @@ int main() // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); - + // 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]); @@ -54,13 +54,13 @@ int main() // Define lights attributes // NOTE: Shader is passed to every light on creation to define shader bindings internally - Light lights[MAX_LIGHTS] = { + 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) + 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 @@ -72,7 +72,7 @@ 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.materials[0].shader, model.materials[0].shader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3); @@ -87,7 +87,7 @@ int main() BeginMode3D(camera); DrawModel(model, Vector3Zero(), 1.0f, WHITE); - + DrawGrid(10, 1.0f); EndMode3D(); @@ -137,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"); @@ -185,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 2b4b75ab..cfc3bdd6 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]; - + 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,7 +37,7 @@ 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].materials[0].maps[MAP_DIFFUSE].texture = texture; @@ -46,12 +46,12 @@ int main() // 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,14 +60,14 @@ 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; } @@ -91,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; @@ -115,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 42028829..26d9fa7e 100644 --- a/examples/models/models_mesh_picking.c +++ b/examples/models/models_mesh_picking.c @@ -15,12 +15,12 @@ #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"); @@ -33,22 +33,22 @@ int main() 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.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.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 +60,7 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - + // Display information about closest hit RayHitInfo nearestHit = { 0 }; char *hitObjectName = "None"; @@ -70,10 +70,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 +83,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 +92,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 +126,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 +139,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 +148,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 +194,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 74e7d08a..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"); @@ -33,7 +33,7 @@ int main() 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 diff --git a/examples/models/models_obj_viewer.c b/examples/models/models_obj_viewer.c index 7d387441..dc6787e7 100644 --- a/examples/models/models_obj_viewer.c +++ b/examples/models/models_obj_viewer.c @@ -13,12 +13,12 @@ #include // 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"); @@ -37,7 +37,7 @@ int main() 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 diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index 3ad32b60..ca9d83c9 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* 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 * @@ -18,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 }; - 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 @@ -38,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 d3369b70..1693d9bc 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -11,22 +11,22 @@ #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 }; - // 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 #if defined(PLATFORM_DESKTOP) @@ -43,17 +43,17 @@ int main() 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.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 @@ -76,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_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 658be084..0931c00e 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -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 //-------------------------------------------------------------------------------------- @@ -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 -- cgit v1.2.3 From e6ca2c4ba338fcb56949a3beb978a87803aa38b0 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 May 2019 09:57:17 +0200 Subject: Comment tweaks --- examples/models/models_mesh_picking.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c index 26d9fa7e..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) * ********************************************************************************************/ -- cgit v1.2.3 From 87774a0a21f8d2998b4dc13e989005270476ae92 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 May 2019 00:18:15 +0200 Subject: Review variables initialization --- examples/models/models_box_collisions.c | 2 +- examples/models/models_cubicmap.c | 2 +- examples/models/models_first_person_maze.c | 2 +- examples/models/models_heightmap.c | 2 +- examples/models/models_mesh_generation.c | 4 ++-- examples/models/models_obj_viewer.c | 2 +- examples/models/models_orthographic_projection.c | 2 +- examples/models/models_skybox.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c index 0dd0710e..7a937ea7 100644 --- a/examples/models/models_box_collisions.c +++ b/examples/models/models_box_collisions.c @@ -21,7 +21,7 @@ int main(void) 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 }; diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index f399a56e..f5087845 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -21,7 +21,7 @@ int main(void) 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) diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index 42363747..07c51b9a 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -23,7 +23,7 @@ int main(void) 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 }; + 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) diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c index e242db16..a2c2e310 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.c @@ -21,7 +21,7 @@ int main(void) 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) diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index cfc3bdd6..6c0ae653 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -27,7 +27,7 @@ int main(void) 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)); @@ -42,7 +42,7 @@ int main(void) 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 }; diff --git a/examples/models/models_obj_viewer.c b/examples/models/models_obj_viewer.c index dc6787e7..83c8f2f1 100644 --- a/examples/models/models_obj_viewer.c +++ b/examples/models/models_obj_viewer.c @@ -23,7 +23,7 @@ int main(void) 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 diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index ca9d83c9..8c9b5b1c 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -28,7 +28,7 @@ int main(void) 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 //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 1693d9bc..bad29b96 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -21,7 +21,7 @@ int main(void) 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 Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); -- cgit v1.2.3 From a9f33c9a8962735fed5dd1857709d159bc4056fc Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 31 May 2019 10:03:44 +0200 Subject: Reduce textures size --- .../models/resources/models/castle_diffuse.png | Bin 1538906 -> 444546 bytes examples/models/resources/pbr/trooper_albedo.png | Bin 7676508 -> 1838043 bytes examples/models/resources/pbr/trooper_ao.png | Bin 1832292 -> 559997 bytes examples/models/resources/pbr/trooper_normals.png | Bin 4959793 -> 1313366 bytes .../models/resources/pbr/trooper_roughness.png | Bin 2862048 -> 733780 bytes 5 files changed, 0 insertions(+), 0 deletions(-) (limited to 'examples/models') diff --git a/examples/models/resources/models/castle_diffuse.png b/examples/models/resources/models/castle_diffuse.png index b616e1dd..361144e9 100644 Binary files a/examples/models/resources/models/castle_diffuse.png and b/examples/models/resources/models/castle_diffuse.png differ diff --git a/examples/models/resources/pbr/trooper_albedo.png b/examples/models/resources/pbr/trooper_albedo.png index ac1422e4..9ba0f5a6 100644 Binary files a/examples/models/resources/pbr/trooper_albedo.png and b/examples/models/resources/pbr/trooper_albedo.png differ diff --git a/examples/models/resources/pbr/trooper_ao.png b/examples/models/resources/pbr/trooper_ao.png index 8567f7b4..442dd7fb 100644 Binary files a/examples/models/resources/pbr/trooper_ao.png and b/examples/models/resources/pbr/trooper_ao.png differ diff --git a/examples/models/resources/pbr/trooper_normals.png b/examples/models/resources/pbr/trooper_normals.png index 59c7bdc4..e04be883 100644 Binary files a/examples/models/resources/pbr/trooper_normals.png and b/examples/models/resources/pbr/trooper_normals.png differ diff --git a/examples/models/resources/pbr/trooper_roughness.png b/examples/models/resources/pbr/trooper_roughness.png index 53186d51..29f418f7 100644 Binary files a/examples/models/resources/pbr/trooper_roughness.png and b/examples/models/resources/pbr/trooper_roughness.png differ -- cgit v1.2.3 From 923f4b9bbd1af4bff0037807ec0f6e6514c043cd Mon Sep 17 00:00:00 2001 From: Codecat Date: Wed, 5 Jun 2019 10:35:20 +0200 Subject: Added waving cubes example --- examples/models/models_waving_cubes.c | 105 ++++++++++++++++++++++++++++++++ examples/models/models_waving_cubes.png | Bin 0 -> 37712 bytes 2 files changed, 105 insertions(+) create mode 100644 examples/models/models_waving_cubes.c create mode 100644 examples/models/models_waving_cubes.png (limited to 'examples/models') diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c new file mode 100644 index 00000000..0fefbcf2 --- /dev/null +++ b/examples/models/models_waving_cubes.c @@ -0,0 +1,105 @@ +/******************************************************************************************* +* +* 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) +* +* Copyright (c) 2019 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - waving cubes"); + + // Initialize the camera + Camera3D camera; + 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); + } + } + } + + DrawFPS(10, 10); + + EndMode3D(); + + 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 Binary files /dev/null and b/examples/models/models_waving_cubes.png differ -- cgit v1.2.3 From ddaa4a304d5a8fe8bf7fc6d4d94a2bcd01298119 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 5 Jun 2019 12:58:35 +0200 Subject: Review contributor info --- examples/models/models_animation.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'examples/models') diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c index 294b07a5..7f38b7f5 100644 --- a/examples/models/models_animation.c +++ b/examples/models/models_animation.c @@ -5,7 +5,9 @@ * 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) and @culacant +* Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Culacant (@culacant) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ -- cgit v1.2.3 From 03720b30a135d9acab1f008c7ffb2aa46f8dbffb Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 5 Jun 2019 12:58:53 +0200 Subject: Review contributed example --- examples/models/models_waving_cubes.c | 47 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'examples/models') diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c index 0fefbcf2..f6309bd6 100644 --- a/examples/models/models_waving_cubes.c +++ b/examples/models/models_waving_cubes.c @@ -5,7 +5,9 @@ * 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) +* Example contributed by Codecat (@codecat) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Codecat (@codecat) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -23,7 +25,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - waving cubes"); // Initialize the camera - Camera3D 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 }; @@ -40,16 +42,18 @@ int main() 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; + 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; - + double cameraTime = time*0.3; + camera.position.x = (float)cos(cameraTime)*40.0f; + camera.position.z = (float)sin(cameraTime)*40.0f; + //---------------------------------------------------------------------------------- + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -60,37 +64,40 @@ int main() 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++) { + 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; + 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)); + 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 + (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 }); + Color cubeColor = ColorFromHSV((Vector3){ (float)(((x + y + z)*18)%360), 0.75f, 0.9f }); // Calculate cube size - float cubeSize = (2.4f - scale) * blockScale; + float cubeSize = (2.4f - scale)*blockScale; // And finally, draw the cube! DrawCube(cubePos, cubeSize, cubeSize, cubeSize, cubeColor); } } } - - DrawFPS(10, 10); - + EndMode3D(); + + DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- -- cgit v1.2.3