Browse Source

[examples] Add new example: `shaders_vertex_displacement` (#4186)

* shaders-vertex_displacement init

* implement simulation of wave in ocean

* update examples/README & add some comments

* update comments

* add gl100 shaders
Alex ZH 1 year ago
parent
commit
43b0c9410e

+ 2 - 1
examples/Makefile

@@ -612,7 +612,8 @@ SHADERS = \
     shaders/shaders_texture_outline \
     shaders/shaders_texture_outline \
     shaders/shaders_texture_tiling \
     shaders/shaders_texture_tiling \
     shaders/shaders_texture_waves \
     shaders/shaders_texture_waves \
-    shaders/shaders_write_depth
+    shaders/shaders_write_depth \
+	shaders/shaders_vertex_displacement
 
 
 AUDIO = \
 AUDIO = \
     audio/audio_mixed_processor \
     audio/audio_mixed_processor \

+ 2 - 1
examples/Makefile.Web

@@ -476,7 +476,8 @@ SHADERS = \
     shaders/shaders_texture_outline \
     shaders/shaders_texture_outline \
     shaders/shaders_texture_tiling \
     shaders/shaders_texture_tiling \
     shaders/shaders_texture_waves \
     shaders/shaders_texture_waves \
-    shaders/shaders_write_depth
+    shaders/shaders_write_depth \
+    shaders/shaders_vertex_displacement
 
 
 AUDIO = \
 AUDIO = \
     audio/audio_mixed_processor \
     audio/audio_mixed_processor \

+ 10 - 9
examples/README.md

@@ -178,6 +178,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete
 | 115 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | <img src="shaders/shaders_multi_sample2d.png" alt="shaders_multi_sample2d" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) |
 | 115 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | <img src="shaders/shaders_multi_sample2d.png" alt="shaders_multi_sample2d" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) |
 | 116 | [shaders_spotlight](shaders/shaders_spotlight.c) | <img src="shaders/shaders_spotlight.png" alt="shaders_spotlight" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) |
 | 116 | [shaders_spotlight](shaders/shaders_spotlight.c) | <img src="shaders/shaders_spotlight.png" alt="shaders_spotlight" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) |
 | 117 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | <img src="shaders/shaders_deferred_render.png" alt="shaders_deferred_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) |
 | 117 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | <img src="shaders/shaders_deferred_render.png" alt="shaders_deferred_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) |
+| 118 | [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | <img src="shaders/shaders_vertex_displacement.png" alt="shaders_deferred_render" width="80"> | ⭐️☆☆☆ | 1.5 | 1.5 | [Alex ZH](https://github.com/ZzzhHe) |
 
 
 ### category: audio
 ### category: audio
 
 
@@ -185,10 +186,10 @@ Examples using raylib audio functionality, including sound/music loading and pla
 
 
 | ## | example  | image  | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
 | ## | example  | image  | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
 |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
 |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
-| 118 | [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) |
-| 119 | [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
-| 120 | [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) |
-| 121 | [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) |
+| 119 | [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) |
+| 120 | [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
+| 121 | [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) |
+| 122 | [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) |
 
 
 ### category: others
 ### category: others
 
 
@@ -196,11 +197,11 @@ Examples showing raylib misc functionality that does not fit in other categories
 
 
 | ## | example  | image  | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
 | ## | example  | image  | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
 |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
 |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
-| 122 | [rlgl_standalone](others/rlgl_standalone.c) | <img src="others/rlgl_standalone.png" alt="rlgl_standalone" width="80"> | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) |
-| 123 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | <img src="others/rlgl_compute_shader.png" alt="rlgl_compute_shader" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) |
-| 124 | [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
-| 125 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) |
-| 126 | [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
+| 123 | [rlgl_standalone](others/rlgl_standalone.c) | <img src="others/rlgl_standalone.png" alt="rlgl_standalone" width="80"> | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) |
+| 124 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | <img src="others/rlgl_compute_shader.png" alt="rlgl_compute_shader" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) |
+| 125 | [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
+| 126 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) |
+| 127 | [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
 
 
 As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with!
 As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with!
 
 

+ 18 - 0
examples/shaders/resources/shaders/glsl100/vertex_displacement.fs

@@ -0,0 +1,18 @@
+#version 100
+
+precision mediump float;
+
+// Input vertex attributes (from fragment shader)
+varying vec2 fragTexCoord;
+varying float height;
+
+
+void main()
+{
+    vec4 darkblue = vec4(0.0, 0.13, 0.18, 1.0);
+    vec4 lightblue = vec4(1.0, 1.0, 1.0, 1.0);
+    // Interpolate between two colors based on height
+    vec4 finalColor = mix(darkblue, lightblue, height);
+
+    gl_FragColor = finalColor;
+}

+ 45 - 0
examples/shaders/resources/shaders/glsl100/vertex_displacement.vs

@@ -0,0 +1,45 @@
+#version 100
+
+precision mediump float;
+
+attribute vec3 vertexPosition;
+attribute vec2 vertexTexCoord;
+attribute vec3 vertexNormal;
+attribute vec4 vertexColor;
+
+uniform mat4 mvp;
+uniform mat4 matModel;
+uniform mat4 matNormal;
+
+uniform float time;
+
+uniform sampler2D perlinNoiseMap;
+
+varying vec3 fragPosition;
+varying vec2 fragTexCoord;
+varying vec3 fragNormal;
+varying float height;
+
+void main()
+{
+    // Calculate animated texture coordinates based on time and vertex position
+    vec2 animatedTexCoord = sin(vertexTexCoord + vec2(sin(time + vertexPosition.x * 0.1), cos(time + vertexPosition.z * 0.1)) * 0.3);
+
+    // Normalize animated texture coordinates to range [0, 1]
+    animatedTexCoord = animatedTexCoord * 0.5 + 0.5;
+
+    // Fetch displacement from the perlin noise map
+    float displacement = texture2D(perlinNoiseMap, animatedTexCoord).r * 7.0; // Amplified displacement
+
+    // Displace vertex position
+    vec3 displacedPosition = vertexPosition + vec3(0.0, displacement, 0.0);
+
+    // Send vertex attributes to fragment shader
+    fragPosition = vec3(matModel * vec4(displacedPosition, 1.0));
+    fragTexCoord = vertexTexCoord;
+    fragNormal = normalize(vec3(matNormal * vec4(vertexNormal, 1.0)));
+    height = displacedPosition.y * 0.2; // send height to fragment shader for coloring
+
+    // Calculate final vertex position
+    gl_Position = mvp * vec4(displacedPosition, 1.0);
+}

+ 16 - 0
examples/shaders/resources/shaders/glsl330/vertex_displacement.fs

@@ -0,0 +1,16 @@
+#version 330
+
+// Input fragment attributes (from fragment shader)
+in vec2 fragTexCoord;
+in float height;
+
+// Output fragment color
+out vec4 finalColor;
+
+void main()
+{
+    vec4 darkblue = vec4(0.0, 0.13, 0.18, 1.0);
+    vec4 lightblue = vec4(1.0, 1.0, 1.0, 1.0);
+    // interplate between two colors based on height
+    finalColor = mix(darkblue, lightblue, height);
+}

+ 46 - 0
examples/shaders/resources/shaders/glsl330/vertex_displacement.vs

@@ -0,0 +1,46 @@
+#version 330
+
+// Input vertex attributes
+in vec3 vertexPosition;
+in vec2 vertexTexCoord;
+in vec3 vertexNormal;
+in vec4 vertexColor;
+
+// Input uniform values
+uniform mat4 mvp;
+uniform mat4 matModel;
+uniform mat4 matNormal;
+
+uniform float time; 
+
+uniform sampler2D perlinNoiseMap;
+
+// Output vertex attributes (to fragment shader)
+out vec3 fragPosition;
+out vec2 fragTexCoord;
+out vec3 fragNormal;
+out float height;
+
+void main()
+{
+    // Calculate animated texture coordinates based on time and vertex position
+    vec2 animatedTexCoord = sin(vertexTexCoord + vec2(sin(time + vertexPosition.x * 0.1), cos(time + vertexPosition.z * 0.1)) * 0.3);
+
+    // Normalize animated texture coordinates to range [0, 1]
+    animatedTexCoord = animatedTexCoord * 0.5 + 0.5;
+
+    // Fetch displacement from the perlin noise map
+    float displacement = texture(perlinNoiseMap, animatedTexCoord).r * 7; // Amplified displacement
+
+    // Displace vertex position
+    vec3 displacedPosition = vertexPosition + vec3(0.0, displacement, 0.0);
+
+    // Send vertex attributes to fragment shader
+    fragPosition = vec3(matModel*vec4(displacedPosition, 1.0));
+    fragTexCoord = vertexTexCoord;
+    fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
+    height = displacedPosition.y * 0.2; // send height to fragment shader for coloring
+
+    // Calculate final vertex position
+    gl_Position = mvp*vec4(displacedPosition , 1.0);
+}

+ 122 - 0
examples/shaders/shaders_vertex_displacement.c

@@ -0,0 +1,122 @@
+/*******************************************************************************************
+*
+*   raylib [shaders] example - Vertex displacement
+*
+*   Example originally created with raylib 5.0, last time updated with raylib 4.5
+*
+*   Example contributed by <Alex ZH> (@ZzzhHe) and reviewed by Ramon Santamaria (@raysan5)
+*
+*   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+*   BSD-like license that allows static linking with closed source software
+*
+*   Copyright (c) 2023 <Alex ZH> (@ZzzhHe)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "raymath.h"
+#include "rlgl.h"
+
+#include <printf.h>
+
+#define RLIGHTS_IMPLEMENTATION
+#include "rlights.h"
+
+#if defined(PLATFORM_DESKTOP)
+    #define GLSL_VERSION            330
+#else   // PLATFORM_ANDROID, PLATFORM_WEB
+    #define GLSL_VERSION            100
+#endif
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib [shaders] example - vertex displacement");
+
+    // set up camera
+    Camera camera = {0};
+    camera.position = (Vector3) {20.0f, 5.0f, -20.0f};
+    camera.target = (Vector3) {0.0f, 0.0f, 0.0f};
+    camera.up = (Vector3) {0.0f, 1.0f, 0.0f};
+    camera.fovy = 60.0f;
+    camera.projection = CAMERA_PERSPECTIVE;
+
+    // Load vertex and fragment shaders
+    Shader shader = LoadShader(
+        TextFormat("resources/shaders/glsl%i/vertex_displacement.vs", GLSL_VERSION),
+        TextFormat("resources/shaders/glsl%i/vertex_displacement.fs", GLSL_VERSION)
+        );
+    
+    // Load perlin noise texture
+    Image perlinNoiseImage = GenImagePerlinNoise(512, 512, 0, 0, 1.0f);
+    Texture perlinNoiseMap = LoadTextureFromImage(perlinNoiseImage);
+    UnloadImage(perlinNoiseImage);
+
+    // Set shader uniform location
+    int perlinNoiseMapLoc = GetShaderLocation(shader, "perlinNoiseMap");
+    rlEnableShader(shader.id);
+    rlActiveTextureSlot(1);
+    rlEnableTexture(perlinNoiseMap.id);
+    rlSetUniformSampler(perlinNoiseMapLoc, 1);
+    
+    // Create a plane mesh and model
+    Mesh planeMesh = GenMeshPlane(50, 50, 50, 50);
+    Model planeModel = LoadModelFromMesh(planeMesh);
+    // Set plane model material
+    planeModel.materials[0].shader = shader;
+
+    float time = 0.0f;
+
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        UpdateCamera(&camera, CAMERA_FREE); // Update camera
+
+        time += GetFrameTime(); // Update time variable
+        SetShaderValue(shader, GetShaderLocation(shader, "time"), &time, SHADER_UNIFORM_FLOAT); // Send time value to shader
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+
+            BeginMode3D(camera);
+
+                BeginShaderMode(shader);
+                    // Draw plane model
+                    DrawModel(planeModel, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, (Color) {255, 255, 255, 255});
+                EndShaderMode();
+
+            EndMode3D();
+
+            DrawText("Vertex displacement", 10, 10, 20, DARKGRAY);
+            DrawFPS(10, 40);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+
+    UnloadShader(shader);
+    UnloadModel(planeModel);
+
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

BIN
examples/shaders/shaders_vertex_displacement.png