Procházet zdrojové kódy

REVIEWED: example: shaders_mesh_instancing

Simplified example
Ray před 3 roky
rodič
revize
3879decb9f

+ 12 - 27
examples/models/rlights.h

@@ -11,7 +11,7 @@
 *
 *   LICENSE: zlib/libpng
 *
-*   Copyright (c) 2017-2020 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5)
+*   Copyright (c) 2017-2022 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5)
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   will the authors be held liable for any damages arising from the use of this software.
@@ -36,7 +36,7 @@
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
-#define         MAX_LIGHTS            4         // Max dynamic lights supported by shader
+#define MAX_LIGHTS  4         // Max dynamic lights supported by shader
 
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
@@ -45,22 +45,22 @@
 // Light data
 typedef struct {   
     int type;
+    bool enabled;
     Vector3 position;
     Vector3 target;
     Color color;
-    bool enabled;
     
     // Shader locations
     int enabledLoc;
     int typeLoc;
-    int posLoc;
+    int positionLoc;
     int targetLoc;
     int colorLoc;
 } Light;
 
 // Light type
 typedef enum {
-    LIGHT_DIRECTIONAL,
+    LIGHT_DIRECTIONAL = 0,
     LIGHT_POINT
 } LightType;
 
@@ -128,27 +128,12 @@ Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shade
         light.target = target;
         light.color = color;
 
-        // TODO: Below code doesn't look good to me, 
-        // it assumes a specific shader naming and structure
-        // Probably this implementation could be improved
-        char enabledName[32] = "lights[x].enabled\0";
-        char typeName[32] = "lights[x].type\0";
-        char posName[32] = "lights[x].position\0";
-        char targetName[32] = "lights[x].target\0";
-        char colorName[32] = "lights[x].color\0";
-        
-        // Set location name [x] depending on lights count
-        enabledName[7] = '0' + lightsCount;
-        typeName[7] = '0' + lightsCount;
-        posName[7] = '0' + lightsCount;
-        targetName[7] = '0' + lightsCount;
-        colorName[7] = '0' + lightsCount;
-
-        light.enabledLoc = GetShaderLocation(shader, enabledName);
-        light.typeLoc = GetShaderLocation(shader, typeName);
-        light.posLoc = GetShaderLocation(shader, posName);
-        light.targetLoc = GetShaderLocation(shader, targetName);
-        light.colorLoc = GetShaderLocation(shader, colorName);
+        // NOTE: Lighting shader naming must be the provided ones
+        light.enabledLoc = GetShaderLocation(shader, TextFormat("lights[%i].enabled", lightsCount));
+        light.typeLoc = GetShaderLocation(shader, TextFormat("lights[%i].type", lightsCount));
+        light.positionLoc = GetShaderLocation(shader, TextFormat("lights[%i].position", lightsCount));
+        light.targetLoc = GetShaderLocation(shader, TextFormat("lights[%i].target", lightsCount));
+        light.colorLoc = GetShaderLocation(shader, TextFormat("lights[%i].color", lightsCount));
 
         UpdateLightValues(shader, light);
         
@@ -168,7 +153,7 @@ void UpdateLightValues(Shader shader, Light light)
 
     // Send to shader light position values
     float position[3] = { light.position.x, light.position.y, light.position.z };
-    SetShaderValue(shader, light.posLoc, position, SHADER_UNIFORM_VEC3);
+    SetShaderValue(shader, light.positionLoc, position, SHADER_UNIFORM_VEC3);
 
     // Send to shader light target position values
     float target[3] = { light.target.x, light.target.y, light.target.z };

+ 0 - 0
examples/shaders/resources/shaders/glsl330/base_lighting_instanced.vs → examples/shaders/resources/shaders/glsl330/lighting_instancing.vs


+ 12 - 27
examples/shaders/rlights.h

@@ -11,7 +11,7 @@
 *
 *   LICENSE: zlib/libpng
 *
-*   Copyright (c) 2017-2020 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5)
+*   Copyright (c) 2017-2022 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5)
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   will the authors be held liable for any damages arising from the use of this software.
@@ -36,7 +36,7 @@
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
-#define         MAX_LIGHTS            4         // Max dynamic lights supported by shader
+#define MAX_LIGHTS  4         // Max dynamic lights supported by shader
 
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
@@ -45,22 +45,22 @@
 // Light data
 typedef struct {   
     int type;
+    bool enabled;
     Vector3 position;
     Vector3 target;
     Color color;
-    bool enabled;
     
     // Shader locations
     int enabledLoc;
     int typeLoc;
-    int posLoc;
+    int positionLoc;
     int targetLoc;
     int colorLoc;
 } Light;
 
 // Light type
 typedef enum {
-    LIGHT_DIRECTIONAL,
+    LIGHT_DIRECTIONAL = 0,
     LIGHT_POINT
 } LightType;
 
@@ -128,27 +128,12 @@ Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shade
         light.target = target;
         light.color = color;
 
-        // TODO: Below code doesn't look good to me, 
-        // it assumes a specific shader naming and structure
-        // Probably this implementation could be improved
-        char enabledName[32] = "lights[x].enabled\0";
-        char typeName[32] = "lights[x].type\0";
-        char posName[32] = "lights[x].position\0";
-        char targetName[32] = "lights[x].target\0";
-        char colorName[32] = "lights[x].color\0";
-        
-        // Set location name [x] depending on lights count
-        enabledName[7] = '0' + lightsCount;
-        typeName[7] = '0' + lightsCount;
-        posName[7] = '0' + lightsCount;
-        targetName[7] = '0' + lightsCount;
-        colorName[7] = '0' + lightsCount;
-
-        light.enabledLoc = GetShaderLocation(shader, enabledName);
-        light.typeLoc = GetShaderLocation(shader, typeName);
-        light.posLoc = GetShaderLocation(shader, posName);
-        light.targetLoc = GetShaderLocation(shader, targetName);
-        light.colorLoc = GetShaderLocation(shader, colorName);
+        // NOTE: Lighting shader naming must be the provided ones
+        light.enabledLoc = GetShaderLocation(shader, TextFormat("lights[%i].enabled", lightsCount));
+        light.typeLoc = GetShaderLocation(shader, TextFormat("lights[%i].type", lightsCount));
+        light.positionLoc = GetShaderLocation(shader, TextFormat("lights[%i].position", lightsCount));
+        light.targetLoc = GetShaderLocation(shader, TextFormat("lights[%i].target", lightsCount));
+        light.colorLoc = GetShaderLocation(shader, TextFormat("lights[%i].color", lightsCount));
 
         UpdateLightValues(shader, light);
         
@@ -168,7 +153,7 @@ void UpdateLightValues(Shader shader, Light light)
 
     // Send to shader light position values
     float position[3] = { light.position.x, light.position.y, light.position.z };
-    SetShaderValue(shader, light.posLoc, position, SHADER_UNIFORM_VEC3);
+    SetShaderValue(shader, light.positionLoc, position, SHADER_UNIFORM_VEC3);
 
     // Send to shader light target position values
     float target[3] = { light.target.x, light.target.y, light.target.z };

+ 39 - 122
examples/shaders/shaders_mesh_instancing.c

@@ -7,7 +7,7 @@
 *
 *   Example contributed by @seanpringle and reviewed by Max (@moliad) and Ramon Santamaria (@raysan5)
 *
-*   Copyright (c) 2020-2021 @seanpringle, Max (@moliad) and Ramon Santamaria (@raysan5)
+*   Copyright (c) 2020-2022 @seanpringle, Max (@moliad) and Ramon Santamaria (@raysan5)
 *
 ********************************************************************************************/
 
@@ -18,8 +18,8 @@
 #define RLIGHTS_IMPLEMENTATION
 #include "rlights.h"
 
-#include <stdlib.h>
-#include <math.h>
+#include <stdlib.h>         // Required for: calloc(), free()
+#include <math.h>           // Required for: 
 
 #if defined(PLATFORM_DESKTOP)
     #define GLSL_VERSION            330
@@ -27,7 +27,7 @@
     #define GLSL_VERSION            100
 #endif
 
-#define MAX_INSTANCES  10000
+#define MAX_INSTANCES  8000
 
 //------------------------------------------------------------------------------------
 // Program main entry point
@@ -38,18 +38,9 @@ int main(void)
     //--------------------------------------------------------------------------------------
     const int screenWidth = 800;
     const int screenHeight = 450;
-    const int fps = 60;
 
-    SetConfigFlags(FLAG_MSAA_4X_HINT);  // Enable Multi Sampling Anti Aliasing 4x (if available)
     InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mesh instancing");
 
-    int speed = 30;                 // Speed of jump animation
-    int groups = 2;                 // Count of separate groups jumping around
-    float amp = 10;                 // Maximum amplitude of jump
-    float variance = 0.8f;          // Global variance in jump height
-    float loop = 0.0f;              // Individual cube's computed loop timer
-    float x = 0.0f, y = 0.0f, z = 0.0f; // Used for various 3D coordinate & vector ops
-
     // Define the camera to look into our 3d world
     Camera camera = { 0 };
     camera.position = (Vector3){ -125.0f, 125.0f, -125.0f };
@@ -58,113 +49,64 @@ int main(void)
     camera.fovy = 45.0f;
     camera.projection = CAMERA_PERSPECTIVE;
 
+    // Define mesh to be instanced
     Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
 
-    Matrix *rotations = RL_MALLOC(MAX_INSTANCES*sizeof(Matrix));    // Rotation state of instances
-    Matrix *rotationsInc = RL_MALLOC(MAX_INSTANCES*sizeof(Matrix)); // Per-frame rotation animation of instances
-    Matrix *translations = RL_MALLOC(MAX_INSTANCES*sizeof(Matrix)); // Locations of instances
+    // Define transforms to be uploaded to GPU for instances
+    Matrix *transforms = (Matrix *)RL_CALLOC(MAX_INSTANCES, sizeof(Matrix));   // Pre-multiplied transformations passed to rlgl
 
-    // Scatter random cubes around
+    // Translate and rotate cubes randomly
     for (int i = 0; i < MAX_INSTANCES; i++)
     {
-        x = (float)GetRandomValue(-50, 50);
-        y = (float)GetRandomValue(-50, 50);
-        z = (float)GetRandomValue(-50, 50);
-        translations[i] = MatrixTranslate(x, y, z);
-
-        x = (float)GetRandomValue(0, 360);
-        y = (float)GetRandomValue(0, 360);
-        z = (float)GetRandomValue(0, 360);
-        Vector3 axis = Vector3Normalize((Vector3){ x, y, z });
+        Matrix translation = MatrixTranslate((float)GetRandomValue(-50, 50), (float)GetRandomValue(-50, 50), (float)GetRandomValue(-50, 50));
+        Vector3 axis = Vector3Normalize((Vector3){ (float)GetRandomValue(0, 360), (float)GetRandomValue(0, 360), (float)GetRandomValue(0, 360) });
         float angle = (float)GetRandomValue(0, 10)*DEG2RAD;
-
-        rotationsInc[i] = MatrixRotate(axis, angle);
-        rotations[i] = MatrixIdentity();
+        Matrix rotation = MatrixRotate(axis, angle);
+        
+        transforms[i] = MatrixMultiply(rotation, translation);
     }
 
-    Matrix *transforms = RL_MALLOC(MAX_INSTANCES*sizeof(Matrix));   // Pre-multiplied transformations passed to rlgl
-
-    Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/base_lighting_instanced.vs", GLSL_VERSION),
+    // Load lighting shader
+    Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/lighting_instancing.vs", GLSL_VERSION),
                                TextFormat("resources/shaders/glsl%i/lighting.fs", GLSL_VERSION));
-
-    // Get some shader loactions
+    // Get shader locations
     shader.locs[SHADER_LOC_MATRIX_MVP] = GetShaderLocation(shader, "mvp");
     shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
     shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocationAttrib(shader, "instanceTransform");
 
-    // Ambient light level
+    // Set shader value: ambient light level
     int ambientLoc = GetShaderLocation(shader, "ambient");
     SetShaderValue(shader, ambientLoc, (float[4]){ 0.2f, 0.2f, 0.2f, 1.0f }, SHADER_UNIFORM_VEC4);
 
+    // Create one light
     CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 50.0f, 50.0f, 0.0f }, Vector3Zero(), WHITE, shader);
 
     // NOTE: We are assigning the intancing shader to material.shader
     // to be used on mesh drawing with DrawMeshInstanced()
-    Material material = LoadMaterialDefault();
-    material.shader = shader;
-    material.maps[MATERIAL_MAP_DIFFUSE].color = RED;
+    Material matInstances = LoadMaterialDefault();
+    matInstances.shader = shader;
+    matInstances.maps[MATERIAL_MAP_DIFFUSE].color = RED;
 
-    SetCameraMode(camera, CAMERA_ORBITAL);  // Set an orbital camera mode
+    // Create a defult material with default internal shader for non-instanced mesh drawing
+    Material matDefault = LoadMaterialDefault();
+    matDefault.maps[MATERIAL_MAP_DIFFUSE].color = BLUE;
 
-    int textPositionY = 300;
-    int framesCounter = 0;                  // Simple frames counter to manage animation
+    // Set an orbital camera mode
+    SetCameraMode(camera, CAMERA_ORBITAL);  
 
-    SetTargetFPS(fps);                      // 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
     {
-
         // Update
         //----------------------------------------------------------------------------------
-        textPositionY = 300;
-        framesCounter++;
-
-        if (IsKeyDown(KEY_UP)) amp += 0.5f;
-        if (IsKeyDown(KEY_DOWN)) amp = (amp <= 1)? 1.0f : (amp - 1.0f);
-        if (IsKeyDown(KEY_LEFT))  variance = (variance <= 0.0f)? 0.0f : (variance - 0.01f);
-        if (IsKeyDown(KEY_RIGHT)) variance = (variance >= 1.0f)? 1.0f : (variance + 0.01f);
-        if (IsKeyDown(KEY_ONE)) groups = 1;
-        if (IsKeyDown(KEY_TWO)) groups = 2;
-        if (IsKeyDown(KEY_THREE)) groups = 3;
-        if (IsKeyDown(KEY_FOUR)) groups = 4;
-        if (IsKeyDown(KEY_FIVE)) groups = 5;
-        if (IsKeyDown(KEY_SIX)) groups = 6;
-        if (IsKeyDown(KEY_SEVEN)) groups = 7;
-        if (IsKeyDown(KEY_EIGHT)) groups = 8;
-        if (IsKeyDown(KEY_NINE)) groups = 9;
-        if (IsKeyDown(KEY_W)) { groups = 7; amp = 25; speed = 18; variance = 0.70f; }
-
-        if (IsKeyDown(KEY_EQUAL)) speed = (speed <= (fps*0.25f))? (int)(fps*0.25f) : (int)(speed*0.95f);
-        if (IsKeyDown(KEY_KP_ADD)) speed = (speed <= (fps*0.25f))? (int)(fps*0.25f) : (int)(speed*0.95f);
-
-        if (IsKeyDown(KEY_MINUS)) speed = (int)fmaxf(speed*1.02f, speed + 1);
-        if (IsKeyDown(KEY_KP_SUBTRACT)) speed = (int)fmaxf(speed*1.02f, speed + 1);
+        UpdateCamera(&camera);
 
         // Update the light shader with the camera view position
         float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
         SetShaderValue(shader, shader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3);
-
-        // Apply per-instance transformations
-        for (int i = 0; i < MAX_INSTANCES; i++)
-        {
-            rotations[i] = MatrixMultiply(rotations[i], rotationsInc[i]);
-            transforms[i] = MatrixMultiply(rotations[i], translations[i]);
-
-            // Get the animation cycle's framesCounter for this instance
-            loop = (float)((framesCounter + (int)(((float)(i%groups)/groups)*speed))%speed)/speed;
-
-            // Calculate the y according to loop cycle
-            y = (sinf(loop*PI*2))*amp*((1 - variance) + (variance*(float)(i%(groups*10))/(groups*10)));
-
-            // Clamp to floor
-            y = (y < 0)? 0.0f : y;
-
-            transforms[i] = MatrixMultiply(transforms[i], MatrixTranslate(0.0f, y, 0.0f));
-        }
-
-        UpdateCamera(&camera);
         //----------------------------------------------------------------------------------
 
         // Draw
@@ -174,40 +116,19 @@ int main(void)
             ClearBackground(RAYWHITE);
 
             BeginMode3D(camera);
-                //DrawMesh(cube, material, MatrixIdentity());
-                DrawMeshInstanced(cube, material, transforms, MAX_INSTANCES);
-            EndMode3D();
-
-            DrawText("A CUBE OF DANCING CUBES!", 490, 10, 20, MAROON);
-            DrawText("PRESS KEYS:", 10, textPositionY, 20, BLACK);
 
-            DrawText("1 - 9", 10, textPositionY += 25, 10, BLACK);
-            DrawText(": Number of groups", 50, textPositionY , 10, BLACK);
-            DrawText(TextFormat(": %d", groups), 160, textPositionY , 10, BLACK);
+                // Draw cube mesh with default material (BLUE)
+                DrawMesh(cube, matDefault, MatrixTranslate(-10.0f, 0.0f, 0.0f));
 
-            DrawText("UP", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": increase amplitude", 50, textPositionY, 10, BLACK);
-            DrawText(TextFormat(": %.2f", amp), 160, textPositionY , 10, BLACK);
+                // Draw meshes instanced using material containing instancing shader (RED + lighting),
+                // transforms[] for the instances should be provided, they are dynamically
+                // updated in GPU every frame, so we can animate the different mesh instances
+                DrawMeshInstanced(cube, matInstances, transforms, MAX_INSTANCES);
 
-            DrawText("DOWN", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": decrease amplitude", 50, textPositionY, 10, BLACK);
+                // Draw cube mesh with default material (BLUE)
+                DrawMesh(cube, matDefault, MatrixTranslate(10.0f, 0.0f, 0.0f));
 
-            DrawText("LEFT", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": decrease variance", 50, textPositionY, 10, BLACK);
-            DrawText(TextFormat(": %.2f", variance), 160, textPositionY , 10, BLACK);
-
-            DrawText("RIGHT", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": increase variance", 50, textPositionY, 10, BLACK);
-
-            DrawText("+/=", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": increase speed", 50, textPositionY, 10, BLACK);
-            DrawText(TextFormat(": %d = %f loops/sec", speed, ((float)fps / speed)), 160, textPositionY , 10, BLACK);
-
-            DrawText("-", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": decrease speed", 50, textPositionY, 10, BLACK);
-
-            DrawText("W", 10, textPositionY += 15, 10, BLACK);
-            DrawText(": Wild setup!", 50, textPositionY, 10, BLACK);
+            EndMode3D();
 
             DrawFPS(10, 10);
 
@@ -217,13 +138,9 @@ int main(void)
 
     // De-Initialization
     //--------------------------------------------------------------------------------------
-    // Free allocated matrices
-    RL_FREE(rotations);
-    RL_FREE(rotationsInc);
-    RL_FREE(translations);
-    RL_FREE(transforms);
+    RL_FREE(transforms);    // Free transforms
 
-    CloseWindow();        // Close window and OpenGL context
+    CloseWindow();          // Close window and OpenGL context
     //--------------------------------------------------------------------------------------
 
     return 0;