feat: backporting existing raylib-cs examples and new official raylib examples to WASM, adopting raylib's original code style
This commit is contained in:
parent
6aa91e3097
commit
f804ab7773
234 changed files with 38997 additions and 10578 deletions
166
Examples/Shaders/AsciiRendering.cs
Normal file
166
Examples/Shaders/AsciiRendering.cs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - ascii rendering
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Maicon Santana (@maiconpintoabreu) 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) 2025 Maicon Santana (@maiconpintoabreu)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class AsciiRendering : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Ascii Rendering";
|
||||
|
||||
public string Title => "raylib [shaders] example - ascii rendering";
|
||||
|
||||
private Texture2D fudesumi;
|
||||
private Texture2D raysan;
|
||||
private Shader shader;
|
||||
private int resolutionLoc;
|
||||
private int fontSizeLoc;
|
||||
private float fontSize;
|
||||
private Vector2 circlePos;
|
||||
private float circleSpeed;
|
||||
private RenderTexture2D target;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Texture to test static drawing
|
||||
fudesumi = LoadTexture("resources/fudesumi.png");
|
||||
// Texture to test moving drawing
|
||||
raysan = LoadTexture("resources/raysan.png");
|
||||
|
||||
// Load shader to be used on postprocessing
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/ascii.fs");
|
||||
|
||||
// These locations are used to send data to the GPU
|
||||
resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
fontSizeLoc = GetShaderLocation(shader, "fontSize");
|
||||
|
||||
// Set the character size for the ASCII effect
|
||||
// Fontsize should be 9 or more
|
||||
fontSize = 9.0f;
|
||||
|
||||
// Send the updated values to the shader
|
||||
var resolution = new[] { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
|
||||
circlePos = new Vector2(40.0f, screenHeight * 0.5f);
|
||||
circleSpeed = 1.0f;
|
||||
|
||||
// RenderTexture to apply the postprocessing later
|
||||
target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
circlePos.X += circleSpeed;
|
||||
if ((circlePos.X > 200.0f) || (circlePos.X < 40.0f))
|
||||
{
|
||||
circleSpeed *= -1; // Revert speed
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Left) && (fontSize > 9.0))
|
||||
{
|
||||
fontSize -= 1; // Reduce fontSize
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.Right) && (fontSize < 15.0))
|
||||
{
|
||||
fontSize += 1; // Increase fontSize
|
||||
}
|
||||
|
||||
// Set fontsize for the shader
|
||||
Raylib.SetShaderValue(shader, fontSizeLoc, fontSize, ShaderUniformDataType.Float);
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
// Draw scene in our render texture
|
||||
DrawTexture(fudesumi, 500, -30, Color.White);
|
||||
DrawTextureV(raysan, circlePos, Color.White);
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
// Draw the scene texture (that we rendered earlier) to the screen
|
||||
// The shader will process every pixel of this texture
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0, 0),
|
||||
Color.White
|
||||
);
|
||||
EndShaderMode();
|
||||
|
||||
DrawRectangle(0, 0, screenWidth, 40, Color.Black);
|
||||
DrawText($"Ascii effect - FontSize:{fontSize,2:F0} - [Left] -1 [Right] +1 ", 120, 10, 20, Color.LightGray);
|
||||
DrawFPS(10, 10);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(fudesumi); // Unload texture
|
||||
UnloadTexture(raysan); // Unload texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - ascii rendering");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new AsciiRendering();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,26 +2,21 @@
|
|||
*
|
||||
* raylib [shaders] example - basic lighting
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3).
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 3.0, last time updated with raylib 4.2
|
||||
*
|
||||
* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Chris Camacho (@codifies - http://bedroomcoders.co.uk/) notes:
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* This is based on the PBR lighting example, but greatly simplified to aid learning...
|
||||
* actually there is very little of the PBR example left!
|
||||
* When I first looked at the bewildering complexity of the PBR example I feared
|
||||
* I would never understand how I could do simple lighting with raylib however its
|
||||
* a testement to the authors of raylib (including rlights.h) that the example
|
||||
* came together fairly quickly.
|
||||
*
|
||||
* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -31,52 +26,55 @@ using Examples.Shared;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class BasicLighting
|
||||
public class BasicLighting : IExample
|
||||
{
|
||||
const int GLSL_VERSION = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public unsafe static int Main()
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Basic Lighting";
|
||||
|
||||
public string Title => "raylib [shaders] example - basic lighting";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Shader shader;
|
||||
private Light[] lights;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(2.0f, 4.0f, 6.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(2.0f, 4.0f, 6.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Load plane model from a generated mesh
|
||||
Model model = LoadModelFromMesh(GenMeshPlane(10.0f, 10.0f, 3, 3));
|
||||
Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 4.0f, 2.0f));
|
||||
|
||||
Shader shader = LoadShader(
|
||||
"resources/shaders/glsl330/lighting.vs",
|
||||
"resources/shaders/glsl330/lighting.fs"
|
||||
// Load basic lighting shader
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/lighting.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/lighting.fs"
|
||||
);
|
||||
|
||||
// Get some required shader loactions
|
||||
// Get some required shader locations
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(shader, "viewPos");
|
||||
// NOTE: "matModel" location name is automatically assigned on shader loading,
|
||||
// no need to get the location again if using that uniform name
|
||||
//shader.Locs[(int)ShaderLocationIndex.MatrixModel] = GetShaderLocation(shader, "matModel");
|
||||
|
||||
// ambient light level
|
||||
int ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
float[] ambient = new[] { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
// Ambient light level (some basic lighting)
|
||||
var ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
var ambient = new[] { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
Raylib.SetShaderValue(shader, ambientLoc, ambient, ShaderUniformDataType.Vec4);
|
||||
|
||||
// Assign out lighting shader to model
|
||||
model.Materials[0].Shader = shader;
|
||||
cube.Materials[0].Shader = shader;
|
||||
|
||||
// Using 4 point lights: Color.gold, Color.red, Color.green and Color.blue
|
||||
Light[] lights = new Light[4];
|
||||
// Create lights
|
||||
lights = new Light[4];
|
||||
lights[0] = Rlights.CreateLight(
|
||||
0,
|
||||
LightType.Point,
|
||||
|
|
@ -109,114 +107,116 @@ public class BasicLighting
|
|||
Color.Blue,
|
||||
shader
|
||||
);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
// Check key inputs to enable/disable lights
|
||||
if (IsKeyPressed(KeyboardKey.Y))
|
||||
{
|
||||
lights[0].Enabled = !lights[0].Enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
lights[1].Enabled = !lights[1].Enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.G))
|
||||
{
|
||||
lights[2].Enabled = !lights[2].Enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.B))
|
||||
{
|
||||
lights[3].Enabled = !lights[3].Enabled;
|
||||
}
|
||||
|
||||
// Update light values (actually, only enable/disable them)
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
Rlights.UpdateLightValues(shader, lights[i]);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawPlane(Vector3.Zero, new Vector2(10.0f, 10.0f), Color.White);
|
||||
DrawCube(Vector3.Zero, 2.0f, 4.0f, 2.0f, Color.White);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
// Draw spheres to show where the lights are
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
if (lights[i].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[i].Position, 0.2f, 8, 8, lights[i].Color);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[i].Position, 0.2f, 8, 8, ColorAlpha(lights[i].Color, 0.3f));
|
||||
}
|
||||
}
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText("Use keys [Y][R][G][B] to toggle lights", 10, 40, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new BasicLighting();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Y))
|
||||
{
|
||||
lights[0].Enabled = !lights[0].Enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
lights[1].Enabled = !lights[1].Enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.G))
|
||||
{
|
||||
lights[2].Enabled = !lights[2].Enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.B))
|
||||
{
|
||||
lights[3].Enabled = !lights[3].Enabled;
|
||||
}
|
||||
|
||||
// Update light values (actually, only enable/disable them)
|
||||
Rlights.UpdateLightValues(shader, lights[0]);
|
||||
Rlights.UpdateLightValues(shader, lights[1]);
|
||||
Rlights.UpdateLightValues(shader, lights[2]);
|
||||
Rlights.UpdateLightValues(shader, lights[3]);
|
||||
|
||||
// Update the light shader with the camera view position
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(model, Vector3.Zero, 1.0f, Color.White);
|
||||
DrawModel(cube, Vector3.Zero, 1.0f, Color.White);
|
||||
|
||||
// Draw markers to show where the lights are
|
||||
if (lights[0].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[0].Position, 0.2f, 8, 8, Color.Yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[0].Position, 0.2f, 8, 8, ColorAlpha(Color.Yellow, 0.3f));
|
||||
}
|
||||
|
||||
if (lights[1].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[1].Position, 0.2f, 8, 8, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[1].Position, 0.2f, 8, 8, ColorAlpha(Color.Red, 0.3f));
|
||||
}
|
||||
|
||||
if (lights[2].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[2].Position, 0.2f, 8, 8, Color.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[2].Position, 0.2f, 8, 8, ColorAlpha(Color.Green, 0.3f));
|
||||
}
|
||||
|
||||
if (lights[3].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[3].Position, 0.2f, 8, 8, Color.Blue);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[3].Position, 0.2f, 8, 8, ColorAlpha(Color.Blue, 0.3f));
|
||||
}
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
DrawText("Use keys [Y][R][G][B] to toggle lights", 10, 40, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModel(model);
|
||||
UnloadModel(cube);
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Basic PBR
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.1-dev
|
||||
*
|
||||
* Example contributed by Afan OLOVCIC (@_DevDad) 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-2024 Afan OLOVCIC (@_DevDad)
|
||||
*
|
||||
* Model: "Old Rusty Car" (https://skfb.ly/LxRy) by Renafox,
|
||||
* licensed under Creative Commons Attribution-NonCommercial
|
||||
* (http://creativecommons.org/licenses/by-nc/4.0/)
|
||||
*
|
||||
********************************************************************************************/
|
||||
*
|
||||
* raylib [shaders] example - basic pbr
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Afan OLOVCIC (@_DevDad) 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-2025 Afan OLOVCIC (@_DevDad)
|
||||
*
|
||||
* Model: "Old Rusty Car" (https://skfb.ly/LxRy) by Renafox,
|
||||
* licensed under Creative Commons Attribution-NonCommercial
|
||||
* (http://creativecommons.org/licenses/by-nc/4.0/)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using Examples.Shared;
|
||||
|
|
@ -23,31 +25,50 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class BasicPbr
|
||||
public class BasicPbr : IExample
|
||||
{
|
||||
private const int GLSL_VERSION = 330;
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public static unsafe int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Shaders / Basic PBR";
|
||||
|
||||
public string Title => "raylib [shaders] example - basic pbr";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Shader shader;
|
||||
private Model car;
|
||||
private Model floor;
|
||||
private PbrLight[] lights;
|
||||
|
||||
private int metallicValueLoc;
|
||||
private int roughnessValueLoc;
|
||||
private int emissiveIntensityLoc;
|
||||
private int emissiveColorLoc;
|
||||
private int textureTilingLoc;
|
||||
|
||||
private Vector2 carTextureTiling;
|
||||
private Vector2 floorTextureTiling;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic pbr");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(2.0f, 4.0f, 6.0f);
|
||||
camera = new();
|
||||
camera.Position = new Vector3(2.0f, 2.0f, 6.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
// Load PBR shader and setup all required locations
|
||||
var shader = LoadShader("resources/shaders/glsl330/pbr.vs", "resources/shaders/glsl330/pbr.fs");
|
||||
shader = LoadShader($"resources/shaders/glsl{GlslVersion}/pbr.vs", $"resources/shaders/glsl{GlslVersion}/pbr.fs");
|
||||
|
||||
shader.Locs[(int)ShaderLocationIndex.MapAlbedo] = GetShaderLocation(shader, "albedoMap");
|
||||
// WARNING: Metalness, roughness, and ambient occlusion are all packed into a MRA texture
|
||||
|
|
@ -75,23 +96,25 @@ public class BasicPbr
|
|||
SetShaderValue(shader, GetShaderLocation(shader, "ambient"), &ambientIntensity, ShaderUniformDataType.Float);
|
||||
|
||||
// Get location for shader parameters that can be modified in real time
|
||||
var emissiveIntensityLoc = GetShaderLocation(shader, "emissivePower");
|
||||
var emissiveColorLoc = GetShaderLocation(shader, "emissiveColor");
|
||||
var textureTilingLoc = GetShaderLocation(shader, "tiling");
|
||||
metallicValueLoc = GetShaderLocation(shader, "metallicValue");
|
||||
roughnessValueLoc = GetShaderLocation(shader, "roughnessValue");
|
||||
emissiveIntensityLoc = GetShaderLocation(shader, "emissivePower");
|
||||
emissiveColorLoc = GetShaderLocation(shader, "emissiveColor");
|
||||
textureTilingLoc = GetShaderLocation(shader, "tiling");
|
||||
|
||||
// Load old car model using PBR maps and shader
|
||||
// WARNING: We know this model consists of a single model.meshes[0] and
|
||||
// that model.materials[0] is by default assigned to that mesh
|
||||
// There could be more complex models consisting of multiple meshes and
|
||||
// multiple materials defined for those meshes... but always 1 mesh = 1 material
|
||||
var car = LoadModel("resources/models/gltf/old_car_new.glb");
|
||||
car = LoadModel("resources/models/gltf/old_car_new.glb");
|
||||
|
||||
// Assign already setup PBR shader to model.materials[0], used by models.meshes[0]
|
||||
car.Materials[0].Shader = shader;
|
||||
|
||||
// Setup materials[0].maps default parameters
|
||||
car.Materials[0].Maps[(int)MaterialMapIndex.Albedo].Color = Color.White;
|
||||
car.Materials[0].Maps[(int)MaterialMapIndex.Metalness].Value = 0.0f;
|
||||
car.Materials[0].Maps[(int)MaterialMapIndex.Metalness].Value = 1.0f;
|
||||
car.Materials[0].Maps[(int)MaterialMapIndex.Roughness].Value = 0.0f;
|
||||
car.Materials[0].Maps[(int)MaterialMapIndex.Occlusion].Value = 1.0f;
|
||||
car.Materials[0].Maps[(int)MaterialMapIndex.Emission].Color = new Color(255, 162, 0, 255);
|
||||
|
|
@ -104,7 +127,7 @@ public class BasicPbr
|
|||
|
||||
// Load floor model mesh and assign material parameters
|
||||
// NOTE: A basic plane shape can be generated instead of being loaded from a model file
|
||||
var floor = LoadModel("resources/models/gltf/plane.glb");
|
||||
floor = LoadModel("resources/models/gltf/plane.glb");
|
||||
//Mesh floorMesh = GenMeshPlane(10, 10, 10, 10);
|
||||
//GenMeshTangents(&floorMesh); // TODO: Review tangents generation
|
||||
//Model floor = LoadModelFromMesh(floorMesh);
|
||||
|
|
@ -113,8 +136,8 @@ public class BasicPbr
|
|||
floor.Materials[0].Shader = shader;
|
||||
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Albedo].Color = Color.White;
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Metalness].Value = 0.0f;
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Roughness].Value = 0.0f;
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Metalness].Value = 0.8f;
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Roughness].Value = 0.1f;
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Occlusion].Value = 1.0f;
|
||||
floor.Materials[0].Maps[(int)MaterialMapIndex.Emission].Color = Color.Black;
|
||||
|
||||
|
|
@ -124,11 +147,11 @@ public class BasicPbr
|
|||
|
||||
// Models texture tiling parameter can be stored in the Material struct if required (CURRENTLY NOT USED)
|
||||
// NOTE: Material.params[4] are available for generic parameters storage (float)
|
||||
var carTextureTiling = new Vector2(0.5f, 0.5f);
|
||||
var floorTextureTiling = new Vector2(0.5f, 0.5f);
|
||||
carTextureTiling = new Vector2(0.5f, 0.5f);
|
||||
floorTextureTiling = new Vector2(0.5f, 0.5f);
|
||||
|
||||
// Create some lights
|
||||
var lights = new PbrLight[4];
|
||||
lights = new PbrLight[4];
|
||||
lights[0] = PbrLights.CreateLight(
|
||||
0,
|
||||
PbrLightType.Point,
|
||||
|
|
@ -167,104 +190,113 @@ public class BasicPbr
|
|||
SetShaderValue(shader, GetShaderLocation(shader, "useTexNormal"), &usage, ShaderUniformDataType.Int);
|
||||
SetShaderValue(shader, GetShaderLocation(shader, "useTexMRA"), &usage, ShaderUniformDataType.Int);
|
||||
SetShaderValue(shader, GetShaderLocation(shader, "useTexEmissive"), &usage, ShaderUniformDataType.Int);
|
||||
}
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||
var cameraPos = camera.Position;
|
||||
SetShaderValue(shader, shader.Locs[(int)ShaderLocationIndex.VectorView], cameraPos, ShaderUniformDataType.Vec3);
|
||||
|
||||
// Check key inputs to enable/disable lights
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera, CameraMode.Orbital);
|
||||
|
||||
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||
var cameraPos = camera.Position;
|
||||
SetShaderValue(shader, shader.Locs[(int)ShaderLocationIndex.VectorView], cameraPos, ShaderUniformDataType.Vec3);
|
||||
|
||||
// Check key inputs to enable/disable lights
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
lights[2].Enabled = !lights[2].Enabled;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
lights[1].Enabled = !lights[1].Enabled;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
lights[3].Enabled = !lights[3].Enabled;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Four))
|
||||
{
|
||||
lights[0].Enabled = !lights[0].Enabled;
|
||||
}
|
||||
|
||||
// Update light values on shader (actually, only enable/disable them)
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
UpdateLight(shader, lights[i]);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Set floor model texture tiling and emissive color parameters on shader
|
||||
SetShaderValue(shader, textureTilingLoc, &floorTextureTiling, ShaderUniformDataType.Vec2);
|
||||
var floorEmissiveColor = ColorNormalize(floor.Materials[0].Maps[(int)MaterialMapIndex.Emission].Color);
|
||||
SetShaderValue(shader, emissiveColorLoc, &floorEmissiveColor, ShaderUniformDataType.Vec4);
|
||||
|
||||
DrawModel(floor, Vector3.Zero, 5.0f, Color.White); // Draw floor model
|
||||
|
||||
// Set old car model texture tiling, emissive color and emissive intensity parameters on shader
|
||||
SetShaderValue(shader, textureTilingLoc, &carTextureTiling, ShaderUniformDataType.Vec2);
|
||||
var carEmissiveColor = ColorNormalize(car.Materials[0].Maps[(int)MaterialMapIndex.Emission].Color);
|
||||
SetShaderValue(shader, emissiveColorLoc, &carEmissiveColor, ShaderUniformDataType.Vec4);
|
||||
var emissiveIntensity = 0.01f;
|
||||
SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, ShaderUniformDataType.Float);
|
||||
|
||||
DrawModel(car, Vector3.Zero, 0.25f, Color.White); // Draw car model
|
||||
|
||||
// Draw spheres to show the lights positions
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
var color = lights[i].Color;
|
||||
var lightColor = new Color((byte)(color.X * 255), (byte)(color.Y * 255), (byte)(color.Z * 255),
|
||||
(byte)(color.W * 255));
|
||||
|
||||
if (lights[i].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[i].Position, 0.2f, 8, 8, lightColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[i].Position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f));
|
||||
}
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Toggle lights: [1][2][3][4]", 10, 40, 20, Color.LightGray);
|
||||
|
||||
DrawText("(c) Old Rusty Car model by Renafox (https://skfb.ly/LxRy)", screenWidth - 320, screenHeight - 20, 10, Color.LightGray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
lights[2].Enabled = !lights[2].Enabled;
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
lights[1].Enabled = !lights[1].Enabled;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
lights[3].Enabled = !lights[3].Enabled;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Four))
|
||||
{
|
||||
lights[0].Enabled = !lights[0].Enabled;
|
||||
}
|
||||
|
||||
// Update light values on shader (actually, only enable/disable them)
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
UpdateLight(shader, lights[i]);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Set floor model texture tiling and emissive color parameters on shader
|
||||
SetShaderValue(shader, textureTilingLoc, floorTextureTiling, ShaderUniformDataType.Vec2);
|
||||
var floorEmissiveColor = ColorNormalize(floor.Materials[0].Maps[(int)MaterialMapIndex.Emission].Color);
|
||||
SetShaderValue(shader, emissiveColorLoc, &floorEmissiveColor, ShaderUniformDataType.Vec4);
|
||||
|
||||
// Set floor metallic and roughness values
|
||||
var floorMetallicValue = floor.Materials[0].Maps[(int)MaterialMapIndex.Metalness].Value;
|
||||
SetShaderValue(shader, metallicValueLoc, &floorMetallicValue, ShaderUniformDataType.Float);
|
||||
var floorRoughnessValue = floor.Materials[0].Maps[(int)MaterialMapIndex.Roughness].Value;
|
||||
SetShaderValue(shader, roughnessValueLoc, &floorRoughnessValue, ShaderUniformDataType.Float);
|
||||
|
||||
DrawModel(floor, Vector3.Zero, 5.0f, Color.White); // Draw floor model
|
||||
|
||||
// Set old car model texture tiling, emissive color and emissive intensity parameters on shader
|
||||
SetShaderValue(shader, textureTilingLoc, carTextureTiling, ShaderUniformDataType.Vec2);
|
||||
var carEmissiveColor = ColorNormalize(car.Materials[0].Maps[(int)MaterialMapIndex.Emission].Color);
|
||||
SetShaderValue(shader, emissiveColorLoc, &carEmissiveColor, ShaderUniformDataType.Vec4);
|
||||
var emissiveIntensity = 0.01f;
|
||||
SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, ShaderUniformDataType.Float);
|
||||
|
||||
// Set old car metallic and roughness values
|
||||
var carMetallicValue = car.Materials[0].Maps[(int)MaterialMapIndex.Metalness].Value;
|
||||
SetShaderValue(shader, metallicValueLoc, &carMetallicValue, ShaderUniformDataType.Float);
|
||||
var carRoughnessValue = car.Materials[0].Maps[(int)MaterialMapIndex.Roughness].Value;
|
||||
SetShaderValue(shader, roughnessValueLoc, &carRoughnessValue, ShaderUniformDataType.Float);
|
||||
|
||||
DrawModel(car, Vector3.Zero, 0.25f, Color.White); // Draw car model
|
||||
|
||||
// Draw spheres to show the lights positions
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
var color = lights[i].Color;
|
||||
var lightColor = new Color((byte)(color.X * 255), (byte)(color.Y * 255), (byte)(color.Z * 255),
|
||||
(byte)(color.W * 255));
|
||||
|
||||
if (lights[i].Enabled)
|
||||
{
|
||||
DrawSphereEx(lights[i].Position, 0.2f, 8, 8, lightColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereWires(lights[i].Position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f));
|
||||
}
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Toggle lights: [1][2][3][4]", 10, 40, 20, Color.LightGray);
|
||||
|
||||
DrawText("(c) Old Rusty Car model by Renafox (https://skfb.ly/LxRy)", screenWidth - 320, screenHeight - 20, 10, Color.LightGray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public unsafe void Unload()
|
||||
{
|
||||
// Unbind (disconnect) shader from car.material[0]
|
||||
// to avoid UnloadMaterial() trying to unload it automatically
|
||||
car.Materials[0].Shader = new();
|
||||
|
|
@ -278,7 +310,32 @@ public class BasicPbr
|
|||
UnloadModel(floor);
|
||||
|
||||
UnloadShader(shader);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic pbr");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
var game = new BasicPbr();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -287,8 +344,8 @@ public class BasicPbr
|
|||
|
||||
private static void UpdateLight(Shader shader, PbrLight light)
|
||||
{
|
||||
SetShaderValue(shader, light.EnabledLoc, light.Enabled, ShaderUniformDataType.Int);
|
||||
SetShaderValue(shader, light.TypeLoc, light.Type, ShaderUniformDataType.Int);
|
||||
SetShaderValue(shader, light.EnabledLoc, light.Enabled ? 1 : 0, ShaderUniformDataType.Int);
|
||||
SetShaderValue(shader, light.TypeLoc, (int)light.Type, ShaderUniformDataType.Int);
|
||||
|
||||
// Send to shader light position values
|
||||
SetShaderValue(shader, light.PositionLoc, light.Position, ShaderUniformDataType.Vec3);
|
||||
|
|
|
|||
252
Examples/Shaders/CelShading.cs
Normal file
252
Examples/Shaders/CelShading.cs
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - cel shading
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* Example contributed by Gleb A (@ggrizzly) 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) 2026 Gleb A (@ggrizzly)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Raymath;
|
||||
using static Raylib_cs.Rlgl;
|
||||
using Examples.Shared;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class CelShading : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private const int MaxLights = 4;
|
||||
|
||||
// rlgl cull face modes (rlgl.h: RL_CULL_FACE_FRONT = 0, RL_CULL_FACE_BACK = 1)
|
||||
private const int CullFaceFront = 0;
|
||||
private const int CullFaceBack = 1;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Cel Shading";
|
||||
|
||||
public string Title => "raylib [shaders] example - cel shading";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Model model;
|
||||
private Shader celShader;
|
||||
private Shader defaultShader;
|
||||
private Shader outlineShader;
|
||||
private float numBands;
|
||||
private int numBandsLoc;
|
||||
private int outlineThicknessLoc;
|
||||
private Light[] lights;
|
||||
private bool celEnabled;
|
||||
private bool outlineEnabled;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
camera = new();
|
||||
camera.Position = new Vector3(9.0f, 6.0f, 9.0f);
|
||||
camera.Target = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
// Load model
|
||||
model = LoadModel("resources/models/old_car_new.glb");
|
||||
|
||||
// Load cel shader
|
||||
celShader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/cel.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/cel.fs"
|
||||
);
|
||||
celShader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(celShader, "viewPos");
|
||||
|
||||
// Apply cel shader to model, keep copy of default shader
|
||||
defaultShader = model.Materials[0].Shader;
|
||||
model.Materials[0].Shader = celShader;
|
||||
|
||||
// numBands: controls toon quantization steps (2 = hard binary, 20 = near-smooth)
|
||||
numBands = 10.0f;
|
||||
numBandsLoc = GetShaderLocation(celShader, "numBands");
|
||||
Raylib.SetShaderValue(celShader, numBandsLoc, numBands, ShaderUniformDataType.Float);
|
||||
|
||||
// Inverted-hull outline shader: draws back faces extruded along normals
|
||||
outlineShader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/outline_hull.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/outline_hull.fs"
|
||||
);
|
||||
outlineThicknessLoc = GetShaderLocation(outlineShader, "outlineThickness");
|
||||
|
||||
// Single directional white light, angled so toon bands are visible on the model sides.
|
||||
// Spins opposite to CAMERA_ORBITAL (0.5 rad/s) so lighting changes as you watch.
|
||||
lights = new Light[MaxLights];
|
||||
lights[0] = Rlights.CreateLight(
|
||||
0,
|
||||
LightType.Directorional,
|
||||
new Vector3(50.0f, 50.0f, 50.0f),
|
||||
Vector3.Zero,
|
||||
Color.White,
|
||||
celShader
|
||||
);
|
||||
|
||||
celEnabled = true;
|
||||
outlineEnabled = true;
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
Raylib.SetShaderValue(
|
||||
celShader,
|
||||
celShader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
// [Z] Toggle cel shading on/off
|
||||
if (IsKeyPressed(KeyboardKey.Z))
|
||||
{
|
||||
celEnabled = !celEnabled;
|
||||
if (celEnabled)
|
||||
{
|
||||
model.Materials[0].Shader = celShader; // Apply cel shader to model
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Materials[0].Shader = defaultShader; // Apply default shader to model
|
||||
}
|
||||
}
|
||||
|
||||
// [C] Toggle outline on/off
|
||||
if (IsKeyPressed(KeyboardKey.C))
|
||||
{
|
||||
outlineEnabled = !outlineEnabled;
|
||||
}
|
||||
|
||||
// [Q/E] Decrease/increase toon band count (press or hold to repeat)
|
||||
if (IsKeyPressed(KeyboardKey.E) || IsKeyPressedRepeat(KeyboardKey.E))
|
||||
{
|
||||
numBands = Clamp(numBands + 1.0f, 2.0f, 20.0f);
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.Q) || IsKeyPressedRepeat(KeyboardKey.Q))
|
||||
{
|
||||
numBands = Clamp(numBands - 1.0f, 2.0f, 20.0f);
|
||||
}
|
||||
Raylib.SetShaderValue(celShader, numBandsLoc, numBands, ShaderUniformDataType.Float);
|
||||
|
||||
// Spin light opposite to CAMERA_ORBITAL (0.5 rad/s), angled 45 degrees off vertical
|
||||
float t = (float)GetTime();
|
||||
lights[0].Position = new Vector3(MathF.Sin(-t * 0.3f) * 5.0f, 5.0f, MathF.Cos(-t * 0.3f) * 5.0f);
|
||||
|
||||
for (var i = 0; i < MaxLights; i++)
|
||||
{
|
||||
Rlights.UpdateLightValues(celShader, lights[i]);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
if (outlineEnabled)
|
||||
{
|
||||
// Outline pass: cull front faces, draw extruded back faces as silhouette
|
||||
float thickness = 0.005f;
|
||||
Raylib.SetShaderValue(outlineShader, outlineThicknessLoc, thickness, ShaderUniformDataType.Float);
|
||||
|
||||
SetCullFace(CullFaceFront);
|
||||
|
||||
model.Materials[0].Shader = outlineShader;
|
||||
|
||||
DrawModel(model, Vector3.Zero, 0.75f, Color.White);
|
||||
|
||||
if (celEnabled)
|
||||
{
|
||||
model.Materials[0].Shader = celShader; // Apply cel shader to model
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Materials[0].Shader = defaultShader; // Apply default shader to model
|
||||
}
|
||||
|
||||
SetCullFace(CullFaceBack);
|
||||
}
|
||||
|
||||
DrawModel(model, Vector3.Zero, 0.75f, Color.White);
|
||||
DrawSphereEx(lights[0].Position, 0.2f, 50, 50, Color.Yellow); // Light position indicator
|
||||
DrawGrid(10, 10.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
DrawText($"Cel: {(celEnabled ? "ON" : "OFF")} [Z]", 10, 65, 20, celEnabled ? Color.DarkGreen : Color.DarkGray);
|
||||
DrawText($"Outline: {(outlineEnabled ? "ON" : "OFF")} [C]", 10, 90, 20, outlineEnabled ? Color.DarkGreen : Color.DarkGray);
|
||||
DrawText($"Bands: {numBands:0} [Q/E]", 10, 115, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadModel(model);
|
||||
UnloadShader(celShader);
|
||||
UnloadShader(outlineShader);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - cel shading");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new CelShading();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
184
Examples/Shaders/ColorCorrection.cs
Normal file
184
Examples/Shaders/ColorCorrection.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - color correction
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Jordi Santonja (@JordSant) 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) 2025 Jordi Santonja (@JordSant)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class ColorCorrection : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int MaxTextures = 4;
|
||||
|
||||
public string Name => "Shaders / Color Correction";
|
||||
|
||||
public string Title => "raylib [shaders] example - color correction";
|
||||
|
||||
private Texture2D[] texture;
|
||||
private Shader shdrColorCorrection;
|
||||
private int imageIndex;
|
||||
private int resetButtonClicked;
|
||||
private float contrast;
|
||||
private float saturation;
|
||||
private float brightness;
|
||||
private int contrastLoc;
|
||||
private int saturationLoc;
|
||||
private int brightnessLoc;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
texture = new[]
|
||||
{
|
||||
LoadTexture("resources/parrots.png"),
|
||||
LoadTexture("resources/cat.png"),
|
||||
LoadTexture("resources/mandrill.png"),
|
||||
LoadTexture("resources/fudesumi.png")
|
||||
};
|
||||
|
||||
shdrColorCorrection = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/color_correction.fs");
|
||||
|
||||
imageIndex = 0;
|
||||
resetButtonClicked = 0;
|
||||
|
||||
contrast = 0.0f;
|
||||
saturation = 0.0f;
|
||||
brightness = 0.0f;
|
||||
|
||||
// Get shader locations
|
||||
contrastLoc = GetShaderLocation(shdrColorCorrection, "contrast");
|
||||
saturationLoc = GetShaderLocation(shdrColorCorrection, "saturation");
|
||||
brightnessLoc = GetShaderLocation(shdrColorCorrection, "brightness");
|
||||
|
||||
// Set shader values (they can be changed later)
|
||||
Raylib.SetShaderValue(shdrColorCorrection, contrastLoc, contrast, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shdrColorCorrection, saturationLoc, saturation, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shdrColorCorrection, brightnessLoc, brightness, ShaderUniformDataType.Float);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Select texture to draw
|
||||
if (IsKeyPressed(KeyboardKey.One)) imageIndex = 0;
|
||||
else if (IsKeyPressed(KeyboardKey.Two)) imageIndex = 1;
|
||||
else if (IsKeyPressed(KeyboardKey.Three)) imageIndex = 2;
|
||||
else if (IsKeyPressed(KeyboardKey.Four)) imageIndex = 3;
|
||||
|
||||
// Reset values to 0
|
||||
if (IsKeyPressed(KeyboardKey.R) || resetButtonClicked != 0)
|
||||
{
|
||||
contrast = 0.0f;
|
||||
saturation = 0.0f;
|
||||
brightness = 0.0f;
|
||||
}
|
||||
|
||||
// Send the values to the shader
|
||||
Raylib.SetShaderValue(shdrColorCorrection, contrastLoc, contrast, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shdrColorCorrection, saturationLoc, saturation, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shdrColorCorrection, brightnessLoc, brightness, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shdrColorCorrection);
|
||||
|
||||
DrawTexture(texture[imageIndex], 580 / 2 - texture[imageIndex].Width / 2, GetScreenHeight() / 2 - texture[imageIndex].Height / 2, Color.White);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
DrawLine(580, 0, 580, GetScreenHeight(), new Color(218, 218, 218, 255));
|
||||
DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), new Color(232, 232, 232, 255));
|
||||
|
||||
// Draw UI info text
|
||||
DrawText("Color Correction", 585, 40, 20, Color.Gray);
|
||||
|
||||
DrawText("Picture", 602, 75, 10, Color.Gray);
|
||||
DrawText("Press [1] - [4] to Change Picture", 600, 230, 8, Color.Gray);
|
||||
DrawText("Press [R] to Reset Values", 600, 250, 8, Color.Gray);
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
// NOTE: raygui is not bound in raylib-cs; controls are kept for reference. Use
|
||||
// keyboard shortcuts ([1]-[4], [R]) to interact with the example.
|
||||
/*GuiToggleGroup(new Rectangle( 645, 70, 20, 20 ), "1;2;3;4", ref imageIndex);
|
||||
|
||||
GuiSliderBar(new Rectangle( 645, 100, 120, 20 ), "Contrast", TextFormat("%.0f", contrast), ref contrast, -100.0f, 100.0f);
|
||||
GuiSliderBar(new Rectangle( 645, 130, 120, 20 ), "Saturation", TextFormat("%.0f", saturation), ref saturation, -100.0f, 100.0f);
|
||||
GuiSliderBar(new Rectangle( 645, 160, 120, 20 ), "Brightness", TextFormat("%.0f", brightness), ref brightness, -100.0f, 100.0f);
|
||||
|
||||
resetButtonClicked = GuiButton(new Rectangle( 645, 190, 40, 20 ), "Reset");*/
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DrawFPS(710, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
for (var i = 0; i < MaxTextures; i++)
|
||||
{
|
||||
UnloadTexture(texture[i]);
|
||||
}
|
||||
UnloadShader(shdrColorCorrection);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - color correction");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ColorCorrection();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Apply a postprocessing shader and connect a custom uniform variable
|
||||
* raylib [shaders] example - custom uniform
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.0
|
||||
*
|
||||
* Copyright (c) 2015 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -21,123 +25,156 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class CustomUniform
|
||||
public class CustomUniform : IExample
|
||||
{
|
||||
public static int Main()
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Shaders / Custom Uniform";
|
||||
|
||||
public string Title => "raylib [shaders] example - custom uniform";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Model model;
|
||||
private Texture2D texture;
|
||||
private Vector3 position;
|
||||
private Shader shader;
|
||||
private int swirlCenterLoc;
|
||||
private float[] swirlCenter;
|
||||
private RenderTexture2D target;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - custom uniform variable");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(8.0f, 8.0f, 8.0f);
|
||||
camera.Target = new Vector3(0.0f, 1.5f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(8.0f, 8.0f, 8.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 1.5f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
Model model = LoadModel("resources/models/obj/barracks.obj");
|
||||
Texture2D texture = LoadTexture("resources/models/obj/barracks_diffuse.png");
|
||||
model = LoadModel("resources/models/obj/barracks.obj"); // Load OBJ model
|
||||
texture = LoadTexture("resources/models/obj/barracks_diffuse.png"); // Load model texture (diffuse map)
|
||||
|
||||
// Set model diffuse texture
|
||||
Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Albedo, ref texture);
|
||||
|
||||
Vector3 position = new(0.0f, 0.0f, 0.0f);
|
||||
position = new(0.0f, 0.0f, 0.0f); // Set model position
|
||||
|
||||
// Load postpro shader
|
||||
Shader shader = LoadShader("resources/shaders/glsl330/base.vs",
|
||||
"resources/shaders/glsl330/swirl.fs");
|
||||
// Load postprocessing shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/swirl.fs");
|
||||
|
||||
// Get variable (uniform) location on the shader to connect with the program
|
||||
// NOTE: If uniform variable could not be found in the shader, function returns -1
|
||||
int swirlCenterLoc = GetShaderLocation(shader, "center");
|
||||
swirlCenterLoc = GetShaderLocation(shader, "center");
|
||||
|
||||
float[] swirlCenter = new float[2] { (float)screenWidth / 2, (float)screenHeight / 2 };
|
||||
swirlCenter = new float[2] { (float)screenWidth / 2, (float)screenHeight / 2 };
|
||||
|
||||
// Create a RenderTexture2D to be used for render to texture
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
var mousePosition = GetMousePosition();
|
||||
|
||||
swirlCenter[0] = mousePosition.X;
|
||||
swirlCenter[1] = screenHeight - mousePosition.Y;
|
||||
|
||||
// Send new value to the shader to be used on drawing
|
||||
Raylib.SetShaderValue(shader, swirlCenterLoc, swirlCenter, ShaderUniformDataType.Vec2);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target); // Enable drawing to texture
|
||||
ClearBackground(Color.RayWhite); // Clear texture background
|
||||
|
||||
BeginMode3D(camera); // Begin 3d mode drawing
|
||||
DrawModel(model, position, 0.5f, Color.White); // Draw 3d model with texture
|
||||
DrawGrid(10, 1.0f); // Draw a grid
|
||||
EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode
|
||||
|
||||
DrawText("TEXT DRAWN IN RENDER TEXTURE", 200, 10, 30, Color.Red);
|
||||
EndTextureMode(); // End drawing to texture (now we have a texture available for next passes)
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite); // Clear screen background
|
||||
|
||||
// Enable shader using the custom uniform
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0, 0),
|
||||
Color.White
|
||||
);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
// Draw some 2d text over drawn texture
|
||||
DrawText(
|
||||
"(c) Barracks 3D model by Alberto Cano",
|
||||
screenWidth - 220,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadModel(model); // Unload model
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - custom uniform");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new CustomUniform();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
|
||||
swirlCenter[0] = mousePosition.X;
|
||||
swirlCenter[1] = screenHeight - mousePosition.Y;
|
||||
|
||||
// Send new value to the shader to be used on drawing
|
||||
Raylib.SetShaderValue(shader, swirlCenterLoc, swirlCenter, ShaderUniformDataType.Vec2);
|
||||
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Enable drawing to texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(model, position, 0.5f, Color.White);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("TEXT DRAWN IN RENDER TEXTURE", 200, 10, 30, Color.Red);
|
||||
|
||||
// End drawing to texture (now we have a texture available for next passes)
|
||||
EndTextureMode();
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0, 0),
|
||||
Color.White
|
||||
);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
DrawText(
|
||||
"(c) Barracks 3D model by Alberto Cano",
|
||||
screenWidth - 220,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(texture);
|
||||
UnloadModel(model);
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
400
Examples/Shaders/DeferredRendering.cs
Normal file
400
Examples/Shaders/DeferredRendering.cs
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - deferred rendering
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or OpenGL ES 3.0
|
||||
*
|
||||
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||
*
|
||||
* Example contributed by Justin Andreas Lacoste (@27justin) 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-2025 Justin Andreas Lacoste (@27justin)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using Examples.Shared;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
[ExcludeFromBrowser("multiple-render-target G-buffer, unsupported on WebGL1/GLSL100")]
|
||||
public partial class DeferredRendering : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int MaxCubes = 30;
|
||||
private const int MaxLights = 4;
|
||||
private const float CubeScale = 0.25f;
|
||||
|
||||
// GL_READ_FRAMEBUFFER / GL_DRAW_FRAMEBUFFER / GL_DEPTH_BUFFER_BIT
|
||||
private const uint RlReadFramebuffer = 0x8CA8;
|
||||
private const uint RlDrawFramebuffer = 0x8CA9;
|
||||
private const int GlDepthBufferBit = 0x00000100;
|
||||
|
||||
public string Name => "Shaders / Deferred Rendering";
|
||||
|
||||
public string Title => "raylib [shaders] example - deferred rendering";
|
||||
|
||||
// GBuffer data
|
||||
private struct GBuffer
|
||||
{
|
||||
public uint FramebufferId;
|
||||
|
||||
public uint PositionTextureId;
|
||||
public uint NormalTextureId;
|
||||
public uint AlbedoSpecTextureId;
|
||||
|
||||
public uint DepthRenderbufferId;
|
||||
}
|
||||
|
||||
// Deferred mode passes
|
||||
private enum DeferredMode
|
||||
{
|
||||
Position,
|
||||
Normal,
|
||||
Albedo,
|
||||
Shading
|
||||
}
|
||||
|
||||
private Camera3D camera;
|
||||
private Model model;
|
||||
private Model cube;
|
||||
private Shader gbufferShader;
|
||||
private Shader deferredShader;
|
||||
private GBuffer gBuffer;
|
||||
private Light[] lights;
|
||||
private Vector3[] cubePositions;
|
||||
private float[] cubeRotations;
|
||||
private DeferredMode mode;
|
||||
|
||||
// Texture units our g-buffer textures are bound to
|
||||
private const int TexUnitPosition = 0;
|
||||
private const int TexUnitNormal = 1;
|
||||
private const int TexUnitAlbedoSpec = 2;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
camera = new();
|
||||
camera.Position = new Vector3(5.0f, 4.0f, 5.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 1.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 60.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Load plane model from a generated mesh
|
||||
model = LoadModelFromMesh(GenMeshPlane(10.0f, 10.0f, 3, 3));
|
||||
cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f));
|
||||
|
||||
// Load geometry buffer (G-buffer) shader and deferred shader
|
||||
gbufferShader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/gbuffer.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/gbuffer.fs"
|
||||
);
|
||||
|
||||
deferredShader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/deferred_shading.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/deferred_shading.fs"
|
||||
);
|
||||
deferredShader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(deferredShader, "viewPosition");
|
||||
|
||||
// Initialize the G-buffer
|
||||
gBuffer = new();
|
||||
gBuffer.FramebufferId = Rlgl.LoadFramebuffer();
|
||||
if (gBuffer.FramebufferId == 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Warning, "Failed to create framebufferId");
|
||||
}
|
||||
|
||||
Rlgl.EnableFramebuffer(gBuffer.FramebufferId);
|
||||
|
||||
// NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture
|
||||
// (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position,
|
||||
// depth, and the inverse view/projection matrices
|
||||
|
||||
// 16-bit precision ensures OpenGL ES 3 compatibility, though it may lack precision for real scenarios
|
||||
gBuffer.PositionTextureId = Rlgl.LoadTexture(null, screenWidth, screenHeight, PixelFormat.UncompressedR16G16B16, 1);
|
||||
|
||||
// Similarly, 16-bit precision is used for normals ensures OpenGL ES 3 compatibility
|
||||
gBuffer.NormalTextureId = Rlgl.LoadTexture(null, screenWidth, screenHeight, PixelFormat.UncompressedR16G16B16, 1);
|
||||
|
||||
// Albedo (diffuse color) and specular strength can be combined into one texture
|
||||
// The color in RGB, and the specular strength in the alpha channel
|
||||
gBuffer.AlbedoSpecTextureId = Rlgl.LoadTexture(null, screenWidth, screenHeight, PixelFormat.UncompressedR8G8B8A8, 1);
|
||||
|
||||
// Activate the draw buffers for our framebufferId
|
||||
Rlgl.ActiveDrawBuffers(3);
|
||||
|
||||
// Now we attach our textures to the framebufferId
|
||||
Rlgl.FramebufferAttach(gBuffer.FramebufferId, gBuffer.PositionTextureId, FramebufferAttachType.ColorChannel0, FramebufferAttachTextureType.Texture2D, 0);
|
||||
Rlgl.FramebufferAttach(gBuffer.FramebufferId, gBuffer.NormalTextureId, FramebufferAttachType.ColorChannel1, FramebufferAttachTextureType.Texture2D, 0);
|
||||
Rlgl.FramebufferAttach(gBuffer.FramebufferId, gBuffer.AlbedoSpecTextureId, FramebufferAttachType.ColorChannel2, FramebufferAttachTextureType.Texture2D, 0);
|
||||
|
||||
// Finally we attach the depth buffer
|
||||
gBuffer.DepthRenderbufferId = Rlgl.LoadTextureDepth(screenWidth, screenHeight, true);
|
||||
Rlgl.FramebufferAttach(gBuffer.FramebufferId, gBuffer.DepthRenderbufferId, FramebufferAttachType.Depth, FramebufferAttachTextureType.Renderbuffer, 0);
|
||||
|
||||
// Make sure our framebufferId is complete
|
||||
// NOTE: rlFramebufferComplete() automatically unbinds the framebufferId, so we don't have to rlDisableFramebuffer() here
|
||||
if (Rlgl.FramebufferComplete(gBuffer.FramebufferId) == 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Warning, "Framebuffer is not complete");
|
||||
}
|
||||
|
||||
// Now we initialize the sampler2D uniform's in the deferred shader
|
||||
// We do this by setting the uniform's values to the texture units that
|
||||
// we later bind our g-buffer textures to
|
||||
Rlgl.EnableShader(deferredShader.Id);
|
||||
int texUnitPosition = TexUnitPosition;
|
||||
int texUnitNormal = TexUnitNormal;
|
||||
int texUnitAlbedoSpec = TexUnitAlbedoSpec;
|
||||
Raylib.SetShaderValue(deferredShader, GetShaderLocation(deferredShader, "gPosition"), texUnitPosition, ShaderUniformDataType.Sampler2D);
|
||||
Raylib.SetShaderValue(deferredShader, GetShaderLocation(deferredShader, "gNormal"), texUnitNormal, ShaderUniformDataType.Sampler2D);
|
||||
Raylib.SetShaderValue(deferredShader, GetShaderLocation(deferredShader, "gAlbedoSpec"), texUnitAlbedoSpec, ShaderUniformDataType.Sampler2D);
|
||||
Rlgl.DisableShader();
|
||||
|
||||
// Assign out lighting shader to model
|
||||
model.Materials[0].Shader = gbufferShader;
|
||||
cube.Materials[0].Shader = gbufferShader;
|
||||
|
||||
// Create lights
|
||||
lights = new Light[MaxLights];
|
||||
lights[0] = Rlights.CreateLight(0, LightType.Point, new Vector3(-2, 1, -2), Vector3.Zero, Color.Yellow, deferredShader);
|
||||
lights[1] = Rlights.CreateLight(1, LightType.Point, new Vector3(2, 1, 2), Vector3.Zero, Color.Red, deferredShader);
|
||||
lights[2] = Rlights.CreateLight(2, LightType.Point, new Vector3(-2, 1, 2), Vector3.Zero, Color.Green, deferredShader);
|
||||
lights[3] = Rlights.CreateLight(3, LightType.Point, new Vector3(2, 1, -2), Vector3.Zero, Color.Blue, deferredShader);
|
||||
|
||||
var rand = new Random();
|
||||
cubePositions = new Vector3[MaxCubes];
|
||||
cubeRotations = new float[MaxCubes];
|
||||
|
||||
for (var i = 0; i < MaxCubes; i++)
|
||||
{
|
||||
cubePositions[i] = new Vector3(
|
||||
(float)(rand.Next() % 10) - 5,
|
||||
(float)(rand.Next() % 5),
|
||||
(float)(rand.Next() % 10) - 5
|
||||
);
|
||||
|
||||
cubeRotations[i] = (float)(rand.Next() % 360);
|
||||
}
|
||||
|
||||
mode = DeferredMode.Shading;
|
||||
|
||||
Rlgl.EnableDepthTest();
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||
Raylib.SetShaderValue(
|
||||
deferredShader,
|
||||
deferredShader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
// Check key inputs to enable/disable lights
|
||||
if (IsKeyPressed(KeyboardKey.Y)) { lights[0].Enabled = !lights[0].Enabled; }
|
||||
if (IsKeyPressed(KeyboardKey.R)) { lights[1].Enabled = !lights[1].Enabled; }
|
||||
if (IsKeyPressed(KeyboardKey.G)) { lights[2].Enabled = !lights[2].Enabled; }
|
||||
if (IsKeyPressed(KeyboardKey.B)) { lights[3].Enabled = !lights[3].Enabled; }
|
||||
|
||||
// Check key inputs to switch between G-buffer textures
|
||||
if (IsKeyPressed(KeyboardKey.One)) mode = DeferredMode.Position;
|
||||
if (IsKeyPressed(KeyboardKey.Two)) mode = DeferredMode.Normal;
|
||||
if (IsKeyPressed(KeyboardKey.Three)) mode = DeferredMode.Albedo;
|
||||
if (IsKeyPressed(KeyboardKey.Four)) mode = DeferredMode.Shading;
|
||||
|
||||
// Update light values (actually, only enable/disable them)
|
||||
for (var i = 0; i < MaxLights; i++) Rlights.UpdateLightValues(deferredShader, lights[i]);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
// Draw to the geometry buffer by first activating it
|
||||
Rlgl.EnableFramebuffer(gBuffer.FramebufferId);
|
||||
Rlgl.ClearColor(0, 0, 0, 0);
|
||||
Rlgl.ClearScreenBuffers(); // Clear color and depth buffer
|
||||
Rlgl.DisableColorBlend();
|
||||
|
||||
BeginMode3D(camera);
|
||||
// NOTE: We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader`
|
||||
// will not work, as they won't immediately load the shader program
|
||||
Rlgl.EnableShader(gbufferShader.Id);
|
||||
// When drawing a model here, make sure that the material's shaders are set to the gbuffer shader!
|
||||
DrawModel(model, Vector3.Zero, 1.0f, Color.White);
|
||||
DrawModel(cube, new Vector3(0.0f, 1.0f, 0.0f), 1.0f, Color.White);
|
||||
|
||||
for (var i = 0; i < MaxCubes; i++)
|
||||
{
|
||||
var position = cubePositions[i];
|
||||
DrawModelEx(cube, position, new Vector3(1, 1, 1), cubeRotations[i], new Vector3(CubeScale, CubeScale, CubeScale), Color.White);
|
||||
}
|
||||
Rlgl.DisableShader();
|
||||
EndMode3D();
|
||||
|
||||
Rlgl.EnableColorBlend();
|
||||
|
||||
// Go back to the default framebufferId (0) and draw our deferred shading
|
||||
Rlgl.DisableFramebuffer();
|
||||
Rlgl.ClearScreenBuffers(); // Clear color & depth buffer
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case DeferredMode.Shading:
|
||||
{
|
||||
BeginMode3D(camera);
|
||||
Rlgl.DisableColorBlend();
|
||||
Rlgl.EnableShader(deferredShader.Id);
|
||||
// Bind our g-buffer textures
|
||||
// We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`,
|
||||
// and `gAlbedoSpec`
|
||||
Rlgl.ActiveTextureSlot(TexUnitPosition);
|
||||
Rlgl.EnableTexture(gBuffer.PositionTextureId);
|
||||
Rlgl.ActiveTextureSlot(TexUnitNormal);
|
||||
Rlgl.EnableTexture(gBuffer.NormalTextureId);
|
||||
Rlgl.ActiveTextureSlot(TexUnitAlbedoSpec);
|
||||
Rlgl.EnableTexture(gBuffer.AlbedoSpecTextureId);
|
||||
|
||||
// Finally, we draw a fullscreen quad to our default framebufferId
|
||||
// This will now be shaded using our deferred shader
|
||||
Rlgl.LoadDrawQuad();
|
||||
Rlgl.DisableShader();
|
||||
Rlgl.EnableColorBlend();
|
||||
EndMode3D();
|
||||
|
||||
// As a last step, we now copy over the depth buffer from our g-buffer to the default framebufferId
|
||||
Rlgl.BindFramebuffer(RlReadFramebuffer, gBuffer.FramebufferId);
|
||||
Rlgl.BindFramebuffer(RlDrawFramebuffer, 0);
|
||||
Rlgl.BlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, GlDepthBufferBit);
|
||||
Rlgl.DisableFramebuffer();
|
||||
|
||||
// Since our shader is now done and disabled, we can draw spheres
|
||||
// that represent light positions in default forward rendering
|
||||
BeginMode3D(camera);
|
||||
Rlgl.EnableShader(Rlgl.GetShaderIdDefault());
|
||||
for (var i = 0; i < MaxLights; i++)
|
||||
{
|
||||
if (lights[i].Enabled) DrawSphereEx(lights[i].Position, 0.2f, 8, 8, lights[i].Color);
|
||||
else DrawSphereWires(lights[i].Position, 0.2f, 8, 8, ColorAlpha(lights[i].Color, 0.3f));
|
||||
}
|
||||
Rlgl.DisableShader();
|
||||
EndMode3D();
|
||||
|
||||
DrawText("FINAL RESULT", 10, screenHeight - 30, 20, Color.DarkGreen);
|
||||
}
|
||||
break;
|
||||
case DeferredMode.Position:
|
||||
{
|
||||
DrawTextureRec(
|
||||
new Texture2D { Id = gBuffer.PositionTextureId, Width = screenWidth, Height = screenHeight },
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.RayWhite
|
||||
);
|
||||
|
||||
DrawText("POSITION TEXTURE", 10, screenHeight - 30, 20, Color.DarkGreen);
|
||||
}
|
||||
break;
|
||||
case DeferredMode.Normal:
|
||||
{
|
||||
DrawTextureRec(
|
||||
new Texture2D { Id = gBuffer.NormalTextureId, Width = screenWidth, Height = screenHeight },
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.RayWhite
|
||||
);
|
||||
|
||||
DrawText("NORMAL TEXTURE", 10, screenHeight - 30, 20, Color.DarkGreen);
|
||||
}
|
||||
break;
|
||||
case DeferredMode.Albedo:
|
||||
{
|
||||
DrawTextureRec(
|
||||
new Texture2D { Id = gBuffer.AlbedoSpecTextureId, Width = screenWidth, Height = screenHeight },
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.RayWhite
|
||||
);
|
||||
|
||||
DrawText("ALBEDO TEXTURE", 10, screenHeight - 30, 20, Color.DarkGreen);
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
DrawText("Toggle lights keys: [Y][R][G][B]", 10, 40, 20, Color.DarkGray);
|
||||
DrawText("Switch G-buffer textures: [1][2][3][4]", 10, 70, 20, Color.DarkGray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// Unload the models
|
||||
UnloadModel(model);
|
||||
UnloadModel(cube);
|
||||
|
||||
// Unload shaders
|
||||
UnloadShader(deferredShader);
|
||||
UnloadShader(gbufferShader);
|
||||
|
||||
// Unload geometry buffer and all attached textures
|
||||
Rlgl.UnloadFramebuffer(gBuffer.FramebufferId);
|
||||
Rlgl.UnloadTexture(gBuffer.PositionTextureId);
|
||||
Rlgl.UnloadTexture(gBuffer.NormalTextureId);
|
||||
Rlgl.UnloadTexture(gBuffer.AlbedoSpecTextureId);
|
||||
Rlgl.UnloadTexture(gBuffer.DepthRenderbufferId);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - deferred rendering");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new DeferredRendering();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
226
Examples/Shaders/DepthRendering.cs
Normal file
226
Examples/Shaders/DepthRendering.cs
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - depth rendering
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Luís Almeida (@luis605) 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) 2025 Luís Almeida (@luis605)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class DepthRendering : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Depth Rendering";
|
||||
|
||||
public string Title => "raylib [shaders] example - depth rendering";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private RenderTexture2D target;
|
||||
private Shader depthShader;
|
||||
private int depthLoc;
|
||||
private Model cube;
|
||||
private Model floor;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(4.0f, 1.0f, 5.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
// Load render texture with a depth texture attached
|
||||
target = LoadRenderTextureDepthTex(screenWidth, screenHeight);
|
||||
|
||||
// Load depth shader and get depth texture shader location
|
||||
depthShader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/depth_render.fs");
|
||||
depthLoc = GetShaderLocation(depthShader, "depthTexture");
|
||||
var flipTextureLoc = GetShaderLocation(depthShader, "flipY");
|
||||
Raylib.SetShaderValue(depthShader, flipTextureLoc, 1, ShaderUniformDataType.Int); // Flip Y texture
|
||||
|
||||
// Load scene models
|
||||
cube = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
|
||||
floor = LoadModelFromMesh(GenMeshPlane(20.0f, 20.0f, 1, 1));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawModel(cube, new Vector3(0.0f, 0.0f, 0.0f), 3.0f, Color.Yellow);
|
||||
DrawModel(floor, new Vector3(10.0f, 0.0f, 2.0f), 2.0f, Color.Red);
|
||||
EndMode3D();
|
||||
EndTextureMode();
|
||||
|
||||
// Draw into screen (main framebuffer)
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(depthShader);
|
||||
SetShaderValueTexture(depthShader, depthLoc, target.Depth);
|
||||
DrawTexture(target.Depth, 0, 0, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawRectangle(10, 10, 320, 93, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 320, 93, Color.Blue);
|
||||
|
||||
DrawText("Camera Controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- WASD to move", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- Z to zoom to (0, 0, 0)", 40, 80, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadModel(cube); // Unload model
|
||||
UnloadModel(floor); // Unload model
|
||||
UnloadRenderTextureDepthTex(target);
|
||||
UnloadShader(depthShader); // Unload shader
|
||||
}
|
||||
|
||||
// Load custom render texture, create a writable depth texture buffer
|
||||
private static unsafe RenderTexture2D LoadRenderTextureDepthTex(int width, int height)
|
||||
{
|
||||
RenderTexture2D target = new();
|
||||
|
||||
// Load an empty framebuffer
|
||||
target.Id = Rlgl.LoadFramebuffer();
|
||||
|
||||
if (target.Id > 0)
|
||||
{
|
||||
Rlgl.EnableFramebuffer(target.Id);
|
||||
|
||||
// Create color texture (default to RGBA)
|
||||
target.Texture.Id = Rlgl.LoadTexture(
|
||||
null,
|
||||
width,
|
||||
height,
|
||||
PixelFormat.UncompressedR8G8B8A8,
|
||||
1
|
||||
);
|
||||
target.Texture.Width = width;
|
||||
target.Texture.Height = height;
|
||||
target.Texture.Format = PixelFormat.UncompressedR8G8B8A8;
|
||||
target.Texture.Mipmaps = 1;
|
||||
|
||||
// Create depth texture buffer (instead of raylib default renderbuffer)
|
||||
target.Depth.Id = Rlgl.LoadTextureDepth(width, height, false);
|
||||
target.Depth.Width = width;
|
||||
target.Depth.Height = height;
|
||||
target.Depth.Format = PixelFormat.CompressedPvrtRgba; // DEPTH_COMPONENT_24BIT: Not defined in raylib
|
||||
target.Depth.Mipmaps = 1;
|
||||
|
||||
// Attach color texture and depth texture to FBO
|
||||
Rlgl.FramebufferAttach(
|
||||
target.Id,
|
||||
target.Texture.Id,
|
||||
FramebufferAttachType.ColorChannel0,
|
||||
FramebufferAttachTextureType.Texture2D,
|
||||
0
|
||||
);
|
||||
Rlgl.FramebufferAttach(
|
||||
target.Id,
|
||||
target.Depth.Id,
|
||||
FramebufferAttachType.Depth,
|
||||
FramebufferAttachTextureType.Texture2D,
|
||||
0
|
||||
);
|
||||
|
||||
// Check if fbo is complete with attachments (valid)
|
||||
if (Rlgl.FramebufferComplete(target.Id) != 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Info, $"FBO: [ID {target.Id}] Framebuffer object created successfully");
|
||||
}
|
||||
|
||||
Rlgl.DisableFramebuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLog(TraceLogLevel.Warning, "FBO: Framebuffer object can not be created");
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
// Unload render texture from GPU memory (VRAM)
|
||||
private static void UnloadRenderTextureDepthTex(RenderTexture2D target)
|
||||
{
|
||||
if (target.Id > 0)
|
||||
{
|
||||
// Color texture attached to FBO is deleted
|
||||
Rlgl.UnloadTexture(target.Texture.Id);
|
||||
Rlgl.UnloadTexture(target.Depth.Id);
|
||||
|
||||
// NOTE: Depth texture is automatically
|
||||
// queried and deleted before deleting framebuffer
|
||||
Rlgl.UnloadFramebuffer(target.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - depth rendering");
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new DepthRendering();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,29 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Sieve of Eratosthenes
|
||||
* raylib [shaders] example - eratosthenes sieve
|
||||
*
|
||||
* Sieve of Eratosthenes, the earliest known (ancient Greek) prime number sieve.
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* "Sift the twos and sift the threes,
|
||||
* The Sieve of Eratosthenes.
|
||||
* When the multiples sublime,
|
||||
* the numbers that are left are prime."
|
||||
* NOTE: Sieve of Eratosthenes, the earliest known (ancient Greek) prime number sieve
|
||||
*
|
||||
* "Sift the twos and sift the threes,
|
||||
* The Sieve of Eratosthenes.
|
||||
* When the multiples sublime,
|
||||
* the numbers that are left are prime."
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3).
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by ProfJski and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by ProfJski (@ProfJski) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 ProfJski and 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) 2019-2025 ProfJski (@ProfJski) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -28,73 +32,97 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class Eratosthenes
|
||||
public class Eratosthenes : IExample
|
||||
{
|
||||
const int GlslVersion = 330;
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Shaders / Eratosthenes";
|
||||
|
||||
public string Title => "raylib [shaders] example - eratosthenes sieve";
|
||||
|
||||
private RenderTexture2D target;
|
||||
private Shader shader;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// Load Eratosthenes shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/eratosthenes.fs");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Nothing to do here, everything is happening in the shader
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target); // Enable drawing to texture
|
||||
ClearBackground(Color.Black); // Clear the render texture
|
||||
|
||||
// Draw a rectangle in shader mode to be used as shader canvas
|
||||
// NOTE: Rectangle uses font white character texture coordinates,
|
||||
// so shader can not be applied here directly because input vertexTexCoord
|
||||
// do not represent full screen coordinates (space where want to apply shader)
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Black);
|
||||
EndTextureMode(); // End drawing to texture (now we have a blank texture available for the shader)
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite); // Clear screen background
|
||||
|
||||
BeginShaderMode(shader);
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0.0f, 0.0f),
|
||||
Color.White
|
||||
);
|
||||
EndShaderMode();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
UnloadRenderTexture(target);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Sieve of Eratosthenes");
|
||||
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// Load Eratosthenes shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/eratosthenes.fs");
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - eratosthenes sieve");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Eratosthenes();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Nothing to do here, everything is happening in the shader
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Enable drawing to texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw a rectangle in shader mode to be used as shader canvas
|
||||
// NOTE: Rectangle uses font white character texture coordinates,
|
||||
// so shader can not be applied here directly because input vertexTexCoord
|
||||
// do not represent full screen coordinates (space where want to apply shader)
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Black);
|
||||
|
||||
// End drawing to texture (now we have a blank texture available for the shader)
|
||||
EndTextureMode();
|
||||
|
||||
BeginShaderMode(shader);
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0.0f, 0.0f),
|
||||
Color.White
|
||||
);
|
||||
EndShaderMode();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - fog
|
||||
* raylib [shaders] example - fog rendering
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3).
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.7
|
||||
*
|
||||
* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Chris Camacho (@codifies - http://bedroomcoders.co.uk/) notes:
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* This is based on the PBR lighting example, but greatly simplified to aid learning...
|
||||
* actually there is very little of the PBR example left!
|
||||
* When I first looked at the bewildering complexity of the PBR example I feared
|
||||
* I would never understand how I could do simple lighting with raylib however its
|
||||
* a testement to the authors of raylib (including rlights.h) that the example
|
||||
* came together fairly quickly.
|
||||
*
|
||||
* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -32,21 +27,36 @@ using Examples.Shared;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class Fog
|
||||
public class Fog : IExample
|
||||
{
|
||||
public unsafe static int Main()
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Shaders / Fog";
|
||||
|
||||
public string Title => "raylib [shaders] example - fog rendering";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Model modelA;
|
||||
private Model modelB;
|
||||
private Model modelC;
|
||||
private Texture2D texture;
|
||||
private Shader shader;
|
||||
private int fogDensityLoc;
|
||||
private float fogDensity;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - fog");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera = new();
|
||||
camera.Position = new Vector3(2.0f, 2.0f, 6.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
|
|
@ -54,10 +64,10 @@ public class Fog
|
|||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
// Load models and texture
|
||||
Model modelA = LoadModelFromMesh(GenMeshTorus(0.4f, 1.0f, 16, 32));
|
||||
Model modelB = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
|
||||
Model modelC = LoadModelFromMesh(GenMeshSphere(0.5f, 32, 32));
|
||||
Texture2D texture = LoadTexture("resources/texel_checker.png");
|
||||
modelA = LoadModelFromMesh(GenMeshTorus(0.4f, 1.0f, 16, 32));
|
||||
modelB = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
|
||||
modelC = LoadModelFromMesh(GenMeshSphere(0.5f, 32, 32));
|
||||
texture = LoadTexture("resources/texel_checker.png");
|
||||
|
||||
// Assign texture to default model material
|
||||
Raylib.SetMaterialTexture(ref modelA, 0, MaterialMapIndex.Albedo, ref texture);
|
||||
|
|
@ -65,12 +75,15 @@ public class Fog
|
|||
Raylib.SetMaterialTexture(ref modelC, 0, MaterialMapIndex.Albedo, ref texture);
|
||||
|
||||
// Load shader and set up some uniforms
|
||||
Shader shader = LoadShader("resources/shaders/glsl330/lighting.vs", "resources/shaders/glsl330/fog.fs");
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/lighting.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/fog.fs"
|
||||
);
|
||||
shader.Locs[(int)ShaderLocationIndex.MatrixModel] = GetShaderLocation(shader, "matModel");
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(shader, "viewPos");
|
||||
|
||||
// Ambient light level
|
||||
int ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
var ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
ambientLoc,
|
||||
|
|
@ -78,8 +91,12 @@ public class Fog
|
|||
ShaderUniformDataType.Vec4
|
||||
);
|
||||
|
||||
float fogDensity = 0.15f;
|
||||
int fogDensityLoc = GetShaderLocation(shader, "fogDensity");
|
||||
var fogColor = ColorNormalize(Color.Gray);
|
||||
var fogColorLoc = GetShaderLocation(shader, "fogColor");
|
||||
Raylib.SetShaderValue(shader, fogColorLoc, fogColor, ShaderUniformDataType.Vec4);
|
||||
|
||||
fogDensity = 0.15f;
|
||||
fogDensityLoc = GetShaderLocation(shader, "fogDensity");
|
||||
Raylib.SetShaderValue(shader, fogDensityLoc, fogDensity, ShaderUniformDataType.Float);
|
||||
|
||||
// NOTE: All models share the same shader
|
||||
|
|
@ -89,90 +106,112 @@ public class Fog
|
|||
|
||||
// Using just 1 point lights
|
||||
Rlights.CreateLight(0, LightType.Point, new Vector3(0, 2, 6), Vector3.Zero, Color.White, shader);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
fogDensity += 0.001f;
|
||||
if (fogDensity > 1.0f)
|
||||
{
|
||||
fogDensity += 0.001f;
|
||||
if (fogDensity > 1.0f)
|
||||
{
|
||||
fogDensity = 1.0f;
|
||||
}
|
||||
fogDensity = 1.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
fogDensity -= 0.001f;
|
||||
if (fogDensity < 0.0f)
|
||||
{
|
||||
fogDensity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(shader, fogDensityLoc, fogDensity, ShaderUniformDataType.Float);
|
||||
|
||||
// Rotate the torus
|
||||
modelA.Transform = MatrixMultiply(modelA.Transform, MatrixRotateX(-0.025f));
|
||||
modelA.Transform = MatrixMultiply(modelA.Transform, MatrixRotateZ(0.012f));
|
||||
|
||||
// Update the light shader with the camera view position
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Gray);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw the three models
|
||||
DrawModel(modelA, Vector3.Zero, 1.0f, Color.White);
|
||||
DrawModel(modelB, new Vector3(-2.6f, 0, 0), 1.0f, Color.White);
|
||||
DrawModel(modelC, new Vector3(2.6f, 0, 0), 1.0f, Color.White);
|
||||
|
||||
for (int i = -20; i < 20; i += 2)
|
||||
{
|
||||
DrawModel(modelA, new Vector3(i, 0, 2), 1.0f, Color.White);
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText(
|
||||
$"Use up/down to change fog density [{fogDensity:F2}]",
|
||||
10,
|
||||
10,
|
||||
20,
|
||||
Color.RayWhite
|
||||
);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
fogDensity -= 0.001f;
|
||||
if (fogDensity < 0.0f)
|
||||
{
|
||||
fogDensity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(shader, fogDensityLoc, fogDensity, ShaderUniformDataType.Float);
|
||||
|
||||
// Rotate the torus
|
||||
modelA.Transform = MatrixMultiply(modelA.Transform, MatrixRotateX(-0.025f));
|
||||
modelA.Transform = MatrixMultiply(modelA.Transform, MatrixRotateZ(0.012f));
|
||||
|
||||
// Update the light shader with the camera view position
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Gray);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw the three models
|
||||
DrawModel(modelA, Vector3.Zero, 1.0f, Color.White);
|
||||
DrawModel(modelB, new Vector3(-2.6f, 0, 0), 1.0f, Color.White);
|
||||
DrawModel(modelC, new Vector3(2.6f, 0, 0), 1.0f, Color.White);
|
||||
|
||||
for (var i = -20; i < 20; i += 2)
|
||||
{
|
||||
DrawModel(modelA, new Vector3(i, 0, 2), 1.0f, Color.White);
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText(
|
||||
$"Use KEY_UP/KEY_DOWN to change fog density [{fogDensity:F2}]",
|
||||
10,
|
||||
10,
|
||||
20,
|
||||
Color.RayWhite
|
||||
);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadModel(modelA);
|
||||
UnloadModel(modelB);
|
||||
UnloadModel(modelC);
|
||||
|
||||
UnloadTexture(texture);
|
||||
UnloadShader(shader);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - fog rendering");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Fog();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
433
Examples/Shaders/GameOfLife.cs
Normal file
433
Examples/Shaders/GameOfLife.cs
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - game of life
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Jordi Santonja (@JordSant) 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) 2025 Jordi Santonja (@JordSant)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class GameOfLife : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Game of Life";
|
||||
|
||||
public string Title => "raylib [shaders] example - game of life";
|
||||
|
||||
// Interaction mode
|
||||
private enum InteractionMode
|
||||
{
|
||||
Run = 0,
|
||||
Pause,
|
||||
Draw,
|
||||
}
|
||||
|
||||
// Struct to store example preset patterns
|
||||
private struct PresetPattern
|
||||
{
|
||||
public string Name;
|
||||
public Vector2 Position;
|
||||
|
||||
public PresetPattern(string name, Vector2 position)
|
||||
{
|
||||
Name = name;
|
||||
Position = position;
|
||||
}
|
||||
}
|
||||
|
||||
private const int menuWidth = 100;
|
||||
private const int windowWidth = screenWidth - menuWidth;
|
||||
private const int windowHeight = screenHeight;
|
||||
|
||||
private const int worldWidth = 2048;
|
||||
private const int worldHeight = 2048;
|
||||
|
||||
private const int randomTiles = 8; // Random preset: divide the world to compute random points in each tile
|
||||
|
||||
private static readonly PresetPattern[] presetPatterns =
|
||||
{
|
||||
new("Glider", new Vector2(0.5f, 0.5f)), new("R-pentomino", new Vector2(0.5f, 0.5f)), new("Acorn", new Vector2(0.5f, 0.5f)),
|
||||
new("Spaceships", new Vector2(0.1f, 0.5f)), new("Still lifes", new Vector2(0.5f, 0.5f)), new("Oscillators", new Vector2(0.5f, 0.5f)),
|
||||
new("Puffer train", new Vector2(0.1f, 0.5f)), new("Glider Gun", new Vector2(0.2f, 0.2f)), new("Breeder", new Vector2(0.1f, 0.5f)),
|
||||
new("Random", new Vector2(0.5f, 0.5f))
|
||||
};
|
||||
|
||||
private static readonly int numberOfPresets = presetPatterns.Length;
|
||||
|
||||
private Rectangle worldRectSource;
|
||||
private Rectangle worldRectDest;
|
||||
private Rectangle textureOnScreen;
|
||||
|
||||
private int zoom;
|
||||
private float offsetX;
|
||||
private float offsetY;
|
||||
private int framesPerStep;
|
||||
private int frame;
|
||||
|
||||
private int preset;
|
||||
private InteractionMode mode;
|
||||
private bool buttonZoomIn;
|
||||
private bool buttonZomOut;
|
||||
private bool buttonFaster;
|
||||
private bool buttonSlower;
|
||||
|
||||
private Shader shdrGameOfLife;
|
||||
private int resolutionLoc;
|
||||
|
||||
private RenderTexture2D world1;
|
||||
private RenderTexture2D world2;
|
||||
private RenderTexture2D currentWorld;
|
||||
private RenderTexture2D previousWorld;
|
||||
|
||||
// Image to be used in DRAW mode, to be changed with mouse input
|
||||
private Image imageToDraw;
|
||||
private bool imageToDrawValid;
|
||||
|
||||
// Static locals in the original loop, promoted to fields
|
||||
private Vector2 previousMousePosition;
|
||||
private int firstColor;
|
||||
|
||||
private void FreeImageToDraw()
|
||||
{
|
||||
if (imageToDrawValid)
|
||||
{
|
||||
UnloadImage(imageToDraw);
|
||||
imageToDrawValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
worldRectSource = new Rectangle(0, 0, worldWidth, -worldHeight);
|
||||
worldRectDest = new Rectangle(0, 0, worldWidth, worldHeight);
|
||||
textureOnScreen = new Rectangle(0, 0, windowWidth, windowHeight);
|
||||
|
||||
zoom = 1;
|
||||
offsetX = (worldWidth - windowWidth) / 2.0f; // Centered on window
|
||||
offsetY = (worldHeight - windowHeight) / 2.0f; // Centered on window
|
||||
framesPerStep = 1;
|
||||
frame = 0;
|
||||
|
||||
preset = -1; // No button pressed for preset
|
||||
mode = InteractionMode.Run; // Starting mode: running
|
||||
buttonZoomIn = false; // Button states: false not pressed
|
||||
buttonZomOut = false;
|
||||
buttonFaster = false;
|
||||
buttonSlower = false;
|
||||
|
||||
previousMousePosition = new Vector2(0.0f, 0.0f);
|
||||
firstColor = -1;
|
||||
imageToDrawValid = false;
|
||||
|
||||
// Load shader
|
||||
shdrGameOfLife = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/game_of_life.fs");
|
||||
|
||||
// Set shader uniform size of the world
|
||||
resolutionLoc = GetShaderLocation(shdrGameOfLife, "resolution");
|
||||
var resolution = new[] { (float)worldWidth, (float)worldHeight };
|
||||
Raylib.SetShaderValue(shdrGameOfLife, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
|
||||
// Define two textures: the current world and the previous world
|
||||
world1 = LoadRenderTexture(worldWidth, worldHeight);
|
||||
world2 = LoadRenderTexture(worldWidth, worldHeight);
|
||||
BeginTextureMode(world2);
|
||||
ClearBackground(Color.RayWhite);
|
||||
EndTextureMode();
|
||||
|
||||
var startPattern = LoadImage("resources/game_of_life/r_pentomino.png");
|
||||
UpdateTextureRec(
|
||||
world2.Texture,
|
||||
new Rectangle(worldWidth / 2.0f, worldHeight / 2.0f, startPattern.Width, startPattern.Height),
|
||||
startPattern.Data
|
||||
);
|
||||
UnloadImage(startPattern);
|
||||
|
||||
// References to the two textures, to be swapped
|
||||
currentWorld = world2;
|
||||
previousWorld = world1;
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
frame++;
|
||||
|
||||
// Change zoom: both by buttons or by mouse wheel
|
||||
var mouseWheelMove = GetMouseWheelMove();
|
||||
if (buttonZoomIn || (buttonZomOut && (zoom > 1)) || (mouseWheelMove != 0.0f))
|
||||
{
|
||||
FreeImageToDraw(); // Zoom change: free the image to draw to be recreated again
|
||||
|
||||
var centerX = offsetX + (windowWidth / 2.0f) / zoom;
|
||||
var centerY = offsetY + (windowHeight / 2.0f) / zoom;
|
||||
if (buttonZoomIn || (mouseWheelMove > 0.0f)) zoom *= 2;
|
||||
if ((buttonZomOut || (mouseWheelMove < 0.0f)) && (zoom > 1)) zoom /= 2;
|
||||
offsetX = centerX - (windowWidth / 2.0f) / zoom;
|
||||
offsetY = centerY - (windowHeight / 2.0f) / zoom;
|
||||
}
|
||||
|
||||
// Change speed: number of frames per step
|
||||
if (buttonFaster && framesPerStep > 1) framesPerStep--;
|
||||
if (buttonSlower) framesPerStep++;
|
||||
|
||||
// Mouse management
|
||||
if ((mode == InteractionMode.Run) || (mode == InteractionMode.Pause))
|
||||
{
|
||||
FreeImageToDraw(); // Free the image to draw: no longer needed in these modes
|
||||
|
||||
// Pan with mouse left button
|
||||
var mousePosition = GetMousePosition();
|
||||
if (IsMouseButtonDown(MouseButton.Left) && (mousePosition.X < windowWidth))
|
||||
{
|
||||
offsetX -= (mousePosition.X - previousMousePosition.X) / zoom;
|
||||
offsetY -= (mousePosition.Y - previousMousePosition.Y) / zoom;
|
||||
}
|
||||
previousMousePosition = mousePosition;
|
||||
}
|
||||
else // MODE_DRAW
|
||||
{
|
||||
var offsetDecimalX = offsetX - MathF.Floor(offsetX);
|
||||
var offsetDecimalY = offsetY - MathF.Floor(offsetY);
|
||||
var sizeInWorldX = (int)(MathF.Ceiling((windowWidth + offsetDecimalX * zoom) / zoom));
|
||||
var sizeInWorldY = (int)(MathF.Ceiling((windowHeight + offsetDecimalY * zoom) / zoom));
|
||||
if (offsetX + sizeInWorldX >= worldWidth) sizeInWorldX = worldWidth - (int)MathF.Floor(offsetX);
|
||||
if (offsetY + sizeInWorldY >= worldHeight) sizeInWorldY = worldHeight - (int)MathF.Floor(offsetY);
|
||||
|
||||
// Create image to draw if not created yet
|
||||
if (!imageToDrawValid)
|
||||
{
|
||||
var worldOnScreen = LoadRenderTexture(sizeInWorldX, sizeInWorldY);
|
||||
BeginTextureMode(worldOnScreen);
|
||||
DrawTexturePro(
|
||||
currentWorld.Texture,
|
||||
new Rectangle(MathF.Floor(offsetX), MathF.Floor(offsetY), sizeInWorldX, -sizeInWorldY),
|
||||
new Rectangle(0, 0, sizeInWorldX, sizeInWorldY),
|
||||
new Vector2(0, 0), 0.0f, Color.White
|
||||
);
|
||||
EndTextureMode();
|
||||
imageToDraw = LoadImageFromTexture(worldOnScreen.Texture);
|
||||
imageToDrawValid = true;
|
||||
|
||||
UnloadRenderTexture(worldOnScreen);
|
||||
}
|
||||
|
||||
var mousePosition = GetMousePosition();
|
||||
if (IsMouseButtonDown(MouseButton.Left) && (mousePosition.X < windowWidth))
|
||||
{
|
||||
var mouseX = (int)(mousePosition.X + offsetDecimalX * zoom) / zoom;
|
||||
var mouseY = (int)(mousePosition.Y + offsetDecimalY * zoom) / zoom;
|
||||
if (mouseX >= sizeInWorldX) mouseX = sizeInWorldX - 1;
|
||||
if (mouseY >= sizeInWorldY) mouseY = sizeInWorldY - 1;
|
||||
if (firstColor == -1) firstColor = (GetImageColor(imageToDraw, mouseX, mouseY).R < 5) ? 0 : 1;
|
||||
var prevColor = (GetImageColor(imageToDraw, mouseX, mouseY).R < 5) ? 0 : 1;
|
||||
|
||||
ImageDrawPixel(ref imageToDraw, mouseX, mouseY, (firstColor != 0) ? Color.Black : Color.RayWhite);
|
||||
|
||||
if (prevColor != firstColor)
|
||||
{
|
||||
UpdateTextureRec(
|
||||
currentWorld.Texture,
|
||||
new Rectangle(MathF.Floor(offsetX), MathF.Floor(offsetY), sizeInWorldX, sizeInWorldY),
|
||||
imageToDraw.Data
|
||||
);
|
||||
}
|
||||
}
|
||||
else firstColor = -1;
|
||||
}
|
||||
|
||||
// Load selected preset
|
||||
if (preset >= 0)
|
||||
{
|
||||
Image pattern;
|
||||
if (preset < numberOfPresets - 1) // Preset with pattern image to load
|
||||
{
|
||||
pattern = preset switch
|
||||
{
|
||||
0 => LoadImage("resources/game_of_life/glider.png"),
|
||||
1 => LoadImage("resources/game_of_life/r_pentomino.png"),
|
||||
2 => LoadImage("resources/game_of_life/acorn.png"),
|
||||
3 => LoadImage("resources/game_of_life/spaceships.png"),
|
||||
4 => LoadImage("resources/game_of_life/still_lifes.png"),
|
||||
5 => LoadImage("resources/game_of_life/oscillators.png"),
|
||||
6 => LoadImage("resources/game_of_life/puffer_train.png"),
|
||||
7 => LoadImage("resources/game_of_life/glider_gun.png"),
|
||||
8 => LoadImage("resources/game_of_life/breeder.png"),
|
||||
_ => default,
|
||||
};
|
||||
BeginTextureMode(currentWorld);
|
||||
ClearBackground(Color.RayWhite);
|
||||
EndTextureMode();
|
||||
|
||||
UpdateTextureRec(
|
||||
currentWorld.Texture,
|
||||
new Rectangle(
|
||||
worldWidth * presetPatterns[preset].Position.X - pattern.Width / 2.0f,
|
||||
worldHeight * presetPatterns[preset].Position.Y - pattern.Height / 2.0f,
|
||||
pattern.Width, pattern.Height
|
||||
),
|
||||
pattern.Data
|
||||
);
|
||||
}
|
||||
else // Last preset: Random values
|
||||
{
|
||||
pattern = GenImageColor(worldWidth / randomTiles, worldHeight / randomTiles, Color.RayWhite);
|
||||
for (var i = 0; i < randomTiles; i++)
|
||||
{
|
||||
for (var j = 0; j < randomTiles; j++)
|
||||
{
|
||||
ImageClearBackground(ref pattern, Color.RayWhite);
|
||||
for (var x = 0; x < pattern.Width; x++)
|
||||
{
|
||||
for (var y = 0; y < pattern.Height; y++)
|
||||
{
|
||||
if (GetRandomValue(0, 100) < 15) ImageDrawPixel(ref pattern, x, y, Color.Black);
|
||||
}
|
||||
}
|
||||
UpdateTextureRec(
|
||||
currentWorld.Texture,
|
||||
new Rectangle(pattern.Width * i, pattern.Height * j, pattern.Width, pattern.Height),
|
||||
pattern.Data
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnloadImage(pattern);
|
||||
|
||||
mode = InteractionMode.Pause;
|
||||
offsetX = worldWidth * presetPatterns[preset].Position.X - (float)windowWidth / zoom / 2.0f;
|
||||
offsetY = worldHeight * presetPatterns[preset].Position.Y - (float)windowHeight / zoom / 2.0f;
|
||||
}
|
||||
|
||||
// Check window draw inside world limits
|
||||
if (offsetX < 0) offsetX = 0;
|
||||
if (offsetY < 0) offsetY = 0;
|
||||
if (offsetX > worldWidth - (float)windowWidth / zoom) offsetX = worldWidth - (float)windowWidth / zoom;
|
||||
if (offsetY > worldHeight - (float)windowHeight / zoom) offsetY = worldHeight - (float)windowHeight / zoom;
|
||||
|
||||
// Rectangles for drawing texture portion to screen
|
||||
var textureSourceToScreen = new Rectangle(offsetX, offsetY, (float)windowWidth / zoom, (float)windowHeight / zoom);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw to texture
|
||||
//----------------------------------------------------------------------------------
|
||||
if ((mode == InteractionMode.Run) && ((frame % framesPerStep) == 0))
|
||||
{
|
||||
// Swap worlds
|
||||
var tempWorld = currentWorld;
|
||||
currentWorld = previousWorld;
|
||||
previousWorld = tempWorld;
|
||||
|
||||
// Draw to texture
|
||||
BeginTextureMode(currentWorld);
|
||||
BeginShaderMode(shdrGameOfLife);
|
||||
DrawTexturePro(previousWorld.Texture, worldRectSource, worldRectDest, new Vector2(0, 0), 0.0f, Color.RayWhite);
|
||||
EndShaderMode();
|
||||
EndTextureMode();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw to screen
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
DrawTexturePro(currentWorld.Texture, textureSourceToScreen, textureOnScreen, new Vector2(0, 0), 0.0f, Color.White);
|
||||
|
||||
DrawLine(windowWidth, 0, windowWidth, screenHeight, new Color(218, 218, 218, 255));
|
||||
DrawRectangle(windowWidth, 0, screenWidth - windowWidth, screenHeight, new Color(232, 232, 232, 255));
|
||||
|
||||
DrawText("Conway's", 704, 4, 20, Color.DarkBlue);
|
||||
DrawText(" game of", 704, 19, 20, Color.DarkBlue);
|
||||
DrawText(" life", 708, 34, 20, Color.DarkBlue);
|
||||
DrawText("in raylib", 757, 42, 6, Color.Black);
|
||||
|
||||
DrawText("Presets", 710, 58, 8, Color.Gray);
|
||||
preset = -1;
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
// NOTE: raygui is not bound in raylib-cs; controls are kept for reference. The
|
||||
// simulation still runs automatically and mouse wheel zoom / left-drag pan work.
|
||||
/*for (int i = 0; i < numberOfPresets; i++)
|
||||
if (GuiButton(new Rectangle( 710.0f, 70.0f + 18*i, 80.0f, 16.0f ), presetPatterns[i].Name)) preset = i;
|
||||
|
||||
GuiToggleGroup(new Rectangle( 710, 258, 80, 16 ), "Run\nPause\nDraw", ref mode);*/
|
||||
|
||||
DrawText($"Zoom: {zoom}x", 710, 316, 8, Color.Gray);
|
||||
/*buttonZoomIn = GuiButton(new Rectangle( 710, 328, 80, 16 ), "Zoom in");
|
||||
buttonZomOut = GuiButton(new Rectangle( 710, 346, 80, 16 ), "Zoom out");*/
|
||||
|
||||
DrawText($"Speed: {framesPerStep} frame{((framesPerStep > 1) ? "s" : "")}", 710, 370, 8, Color.Gray);
|
||||
/*buttonFaster = GuiButton(new Rectangle( 710, 382, 80, 16 ), "Faster");
|
||||
buttonSlower = GuiButton(new Rectangle( 710, 400, 80, 16 ), "Slower");*/
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DrawFPS(712, 426);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shdrGameOfLife);
|
||||
UnloadRenderTexture(world1);
|
||||
UnloadRenderTexture(world2);
|
||||
|
||||
FreeImageToDraw();
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - game of life");
|
||||
|
||||
SetTargetFPS(60); // Set at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new GameOfLife();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,135 +1,189 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Hot reloading
|
||||
* raylib [shaders] example - hot reloading
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330
|
||||
* is currently supported. OpenGL ES 2.0 platforms are not supported at the moment.
|
||||
* is currently supported. OpenGL ES 2.0 platforms are not supported at the moment
|
||||
*
|
||||
* This example has been created using raylib 3.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 3.0, last time updated with raylib 3.5
|
||||
*
|
||||
* Copyright (c) 2020 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) 2020-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class HotReloading
|
||||
public class HotReloading : IExample
|
||||
{
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Shaders / Hot Reloading";
|
||||
|
||||
public string Title => "raylib [shaders] example - hot reloading";
|
||||
|
||||
private string fragShaderFileName;
|
||||
private Shader shader;
|
||||
private int resolutionLoc;
|
||||
private int mouseLoc;
|
||||
private int timeLoc;
|
||||
private float[] resolution;
|
||||
private float totalTime;
|
||||
#if !BROWSER
|
||||
private long fragShaderFileModTime;
|
||||
private bool shaderAutoReloading;
|
||||
#endif
|
||||
|
||||
public void Init()
|
||||
{
|
||||
fragShaderFileName = $"resources/shaders/glsl{GlslVersion}/reload.fs";
|
||||
#if !BROWSER
|
||||
fragShaderFileModTime = GetFileModTime(fragShaderFileName);
|
||||
#endif
|
||||
|
||||
// Load raymarching shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, fragShaderFileName);
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
mouseLoc = GetShaderLocation(shader, "mouse");
|
||||
timeLoc = GetShaderLocation(shader, "time");
|
||||
|
||||
resolution = new[] { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
|
||||
totalTime = 0.0f;
|
||||
#if !BROWSER
|
||||
shaderAutoReloading = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
totalTime += GetFrameTime();
|
||||
var mouse = GetMousePosition();
|
||||
var mousePos = new[] { mouse.X, mouse.Y };
|
||||
|
||||
// Set shader required uniform values
|
||||
Raylib.SetShaderValue(shader, timeLoc, totalTime, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, mouseLoc, mousePos, ShaderUniformDataType.Vec2);
|
||||
|
||||
#if !BROWSER
|
||||
// Hot shader reloading
|
||||
if (shaderAutoReloading || (IsMouseButtonPressed(MouseButton.Left)))
|
||||
{
|
||||
var currentFragShaderModTime = GetFileModTime(fragShaderFileName);
|
||||
|
||||
// Check if shader file has been modified
|
||||
if (currentFragShaderModTime != fragShaderFileModTime)
|
||||
{
|
||||
// Try reloading updated shader
|
||||
var updatedShader = LoadShader(null, fragShaderFileName);
|
||||
|
||||
// It was correctly loaded
|
||||
if (updatedShader.Id != Rlgl.GetShaderIdDefault())
|
||||
{
|
||||
UnloadShader(shader);
|
||||
shader = updatedShader;
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
mouseLoc = GetShaderLocation(shader, "mouse");
|
||||
timeLoc = GetShaderLocation(shader, "time");
|
||||
|
||||
// Reset required uniforms
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
resolutionLoc,
|
||||
resolution,
|
||||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
}
|
||||
|
||||
fragShaderFileModTime = currentFragShaderModTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.A))
|
||||
{
|
||||
shaderAutoReloading = !shaderAutoReloading;
|
||||
}
|
||||
#endif
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// We only draw a white full-screen rectangle, frame is generated in shader
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
#if BROWSER
|
||||
DrawText("Shader generates the frame in real time", 10, 10, 10, Color.Black);
|
||||
#else
|
||||
var info = $"PRESS [A] to TOGGLE SHADER AUTOLOADING: {(shaderAutoReloading ? "AUTO" : "MANUAL")}";
|
||||
DrawText(info, 10, 10, 10, shaderAutoReloading ? Color.Red : Color.Black);
|
||||
if (!shaderAutoReloading)
|
||||
{
|
||||
DrawText("MOUSE CLICK to SHADER RE-LOADING", 10, 30, 10, Color.Black);
|
||||
}
|
||||
|
||||
var lastModification = DateTimeOffset.FromUnixTimeSeconds(fragShaderFileModTime).LocalDateTime.ToString();
|
||||
DrawText($"Shader last modification: {lastModification}", 10, 430, 10, Color.Black);
|
||||
#endif
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
int screenWidth = 800;
|
||||
int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - hot reloading");
|
||||
|
||||
string fragShaderFileName = "resources/shaders/glsl330/reload.fs";
|
||||
long fragShaderFileModTime = GetFileModTime(fragShaderFileName);
|
||||
|
||||
// Load raymarching shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
Shader shader = LoadShader(null, fragShaderFileName);
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
int resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
int mouseLoc = GetShaderLocation(shader, "mouse");
|
||||
int timeLoc = GetShaderLocation(shader, "time");
|
||||
|
||||
float[] resolution = new[] { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
|
||||
float totalTime = 0.0f;
|
||||
bool shaderAutoReloading = false;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new HotReloading();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
totalTime += GetFrameTime();
|
||||
Vector2 mouse = GetMousePosition();
|
||||
float[] mousePos = new[] { mouse.X, mouse.Y };
|
||||
|
||||
// Set shader required uniform values
|
||||
Raylib.SetShaderValue(shader, timeLoc, totalTime, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, mouseLoc, mousePos, ShaderUniformDataType.Vec2);
|
||||
|
||||
// Hot shader reloading
|
||||
if (shaderAutoReloading || (IsMouseButtonPressed(MouseButton.Left)))
|
||||
{
|
||||
long currentFragShaderModTime = GetFileModTime(fragShaderFileName);
|
||||
|
||||
// Check if shader file has been modified
|
||||
if (currentFragShaderModTime != fragShaderFileModTime)
|
||||
{
|
||||
// Try reloading updated shader
|
||||
Shader updatedShader = LoadShader(null, fragShaderFileName);
|
||||
|
||||
// It was correctly loaded
|
||||
if (updatedShader.Id != 0) //rlGetShaderIdDefault())
|
||||
{
|
||||
UnloadShader(shader);
|
||||
shader = updatedShader;
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
mouseLoc = GetShaderLocation(shader, "mouse");
|
||||
timeLoc = GetShaderLocation(shader, "time");
|
||||
|
||||
// Reset required uniforms
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
resolutionLoc,
|
||||
resolution,
|
||||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
}
|
||||
|
||||
fragShaderFileModTime = currentFragShaderModTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.A))
|
||||
{
|
||||
shaderAutoReloading = !shaderAutoReloading;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// We only draw a white full-screen rectangle, frame is generated in shader
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
string info = $"PRESS [A] to TOGGLE SHADER AUTOLOADING: {(shaderAutoReloading ? "AUTO" : "MANUAL")}";
|
||||
DrawText(info, 10, 10, 10, shaderAutoReloading ? Color.Red : Color.Black);
|
||||
if (!shaderAutoReloading)
|
||||
{
|
||||
DrawText("MOUSE CLICK to SHADER RE-LOADING", 10, 30, 10, Color.Black);
|
||||
}
|
||||
|
||||
// DrawText($"Shader last modification: ", 10, 430, 10, Color.BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Hybrid Rendering
|
||||
* raylib [shaders] example - hybrid rendering
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
|
|
@ -9,7 +11,7 @@
|
|||
* 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) 2022-2023 Buğra Alptekin Sarı (@BugraAlptekinSari)
|
||||
* Copyright (c) 2022-2025 Buğra Alptekin Sarı (@BugraAlptekinSari)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -19,43 +21,54 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class HybridRender
|
||||
public class HybridRender : IExample
|
||||
{
|
||||
struct RayLocs
|
||||
private struct RayLocs
|
||||
{
|
||||
public int CamPos;
|
||||
public int CamDir;
|
||||
public int ScreenCenter;
|
||||
}
|
||||
|
||||
const int GLSL_VERSION = 330;
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Shaders / Hybrid Render";
|
||||
|
||||
public string Title => "raylib [shaders] example - hybrid rendering";
|
||||
|
||||
private Shader shdrRaymarch;
|
||||
private Shader shdrRaster;
|
||||
private RayLocs marchLocs;
|
||||
private RenderTexture2D target;
|
||||
private Camera3D camera;
|
||||
private float camDist;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - hybrid render");
|
||||
|
||||
// This shader calculates pixel depth and color using raymarch
|
||||
Shader shdrRaymarch = LoadShader(null, $"resources/shaders/glsl{GLSL_VERSION}/hybrid_raymarch.fs");
|
||||
// This Shader calculates pixel depth and color using raymarch
|
||||
shdrRaymarch = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/hybrid_raymarch.fs");
|
||||
|
||||
// This Shader is a standard rasterization fragment shader with the addition of depth writing
|
||||
// You are required to write depth for all shaders if one shader does it
|
||||
Shader shdrRaster = LoadShader(null, $"resources/shaders/glsl{GLSL_VERSION}/hybrid_raster.fs");
|
||||
shdrRaster = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/hybrid_raster.fs");
|
||||
|
||||
// Declare struct used to store camera locs
|
||||
RayLocs marchLocs = new();
|
||||
// Declare Struct used to store camera locs
|
||||
marchLocs = new();
|
||||
|
||||
// Fill the struct with shader locs.
|
||||
// Fill the struct with shader locs
|
||||
marchLocs.CamPos = GetShaderLocation(shdrRaymarch, "camPos");
|
||||
marchLocs.CamDir = GetShaderLocation(shdrRaymarch, "camDir");
|
||||
marchLocs.ScreenCenter = GetShaderLocation(shdrRaymarch, "screenCenter");
|
||||
|
||||
// Transfer screenCenter position to shader. Which is used to calculate ray direction.
|
||||
Vector2 screenCenter = new(screenWidth / 2, screenHeight / 2);
|
||||
// Transfer screenCenter position to shader. Which is used to calculate ray direction
|
||||
Vector2 screenCenter = new(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
SetShaderValue(
|
||||
shdrRaymarch,
|
||||
marchLocs.ScreenCenter,
|
||||
|
|
@ -63,91 +76,111 @@ public class HybridRender
|
|||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
|
||||
// Use customized function to create writable depth texture buffer
|
||||
RenderTexture2D target = LoadRenderTextureDepthTex(screenWidth, screenHeight);
|
||||
// Use Customized function to create writable depth texture buffer
|
||||
target = LoadRenderTextureDepthTex(screenWidth, screenHeight);
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera;
|
||||
camera.Position = new Vector3(0.5f, 1.0f, 1.5f);
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(0.5f, 1.0f, 1.5f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Camera FOV is pre-calculated in the camera Distance.
|
||||
float camDist = 1.0f / (MathF.Tan(camera.FovY * 0.5f * Raylib.DEG2RAD));
|
||||
// Camera FOV is pre-calculated in the camera distance
|
||||
camDist = 1.0f / (MathF.Tan(camera.FovY * 0.5f * Raylib.DEG2RAD));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Update Camera Postion in the ray march shader
|
||||
SetShaderValue(
|
||||
shdrRaymarch,
|
||||
marchLocs.CamPos,
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
// Update Camera Looking Vector. Vector length determines FOV
|
||||
var camDir = Vector3.Normalize(camera.Target - camera.Position) * camDist;
|
||||
SetShaderValue(shdrRaymarch, marchLocs.CamDir, camDir, ShaderUniformDataType.Vec3);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw into our custom render texture (framebuffer)
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
// Raymarch Scene
|
||||
// Manually enable Depth Test to handle multiple rendering methods
|
||||
Rlgl.EnableDepthTest();
|
||||
BeginShaderMode(shdrRaymarch);
|
||||
DrawRectangleRec(new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
// Rasterize Scene
|
||||
BeginMode3D(camera);
|
||||
BeginShaderMode(shdrRaster);
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Red);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Purple);
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.DarkGreen);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Yellow);
|
||||
DrawGrid(10, 1.0f);
|
||||
EndShaderMode();
|
||||
EndMode3D();
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw custom render texture
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.White
|
||||
);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTextureDepthTex(target);
|
||||
UnloadShader(shdrRaymarch);
|
||||
UnloadShader(shdrRaster);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - hybrid rendering");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new HybridRender();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Update Camera Postion in the ray march shader.
|
||||
SetShaderValue(
|
||||
shdrRaymarch,
|
||||
marchLocs.CamPos,
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
// Update Camera Looking Vector. Vector length determines FOV.
|
||||
Vector3 camDir = Vector3.Normalize(camera.Target - camera.Position) * camDist;
|
||||
SetShaderValue(shdrRaymarch, marchLocs.CamDir, camDir, ShaderUniformDataType.Vec3);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw into our custom render texture (framebuffer)
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
// Raymarch Scene
|
||||
// Manually enable Depth Test to handle multiple rendering methods.
|
||||
Rlgl.EnableDepthTest();
|
||||
BeginShaderMode(shdrRaymarch);
|
||||
DrawRectangleRec(new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
// Rasterize Scene
|
||||
BeginMode3D(camera);
|
||||
BeginShaderMode(shdrRaster);
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Red);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Purple);
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.DarkGreen);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Yellow);
|
||||
DrawGrid(10, 1.0f);
|
||||
EndShaderMode();
|
||||
EndMode3D();
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw custom render texture
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.White
|
||||
);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTextureDepthTex(target);
|
||||
UnloadShader(shdrRaymarch);
|
||||
UnloadShader(shdrRaster);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -203,7 +236,7 @@ public class HybridRender
|
|||
);
|
||||
|
||||
// Check if fbo is complete with attachments (valid)
|
||||
if (Rlgl.FramebufferComplete(target.Id))
|
||||
if (Rlgl.FramebufferComplete(target.Id) != 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Info, $"FBO: [ID {target.Id}] Framebuffer object created successfully");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - julia sets
|
||||
* raylib [shaders] example - julia set
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3).
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by eggmund (@eggmund) and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Josh Colclough (@joshcol9232) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 eggmund (@eggmund) and 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) 2019-2025 Josh Colclough (@joshcol9232) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -21,12 +25,27 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class JuliaSet
|
||||
public class JuliaSet : IExample
|
||||
{
|
||||
const int GlslVersion = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
private const float zoomSpeed = 1.01f;
|
||||
private const float offsetSpeedMul = 2.0f;
|
||||
|
||||
private const float startingZoom = 0.75f;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Julia Set";
|
||||
|
||||
public string Title => "raylib [shaders] example - julia set";
|
||||
|
||||
// A few good julia sets
|
||||
static float[][] PointsOfInterest = new float[][] {
|
||||
private float[][] PointsOfInterest = new float[][] {
|
||||
new float[] { -0.348827f, 0.607167f },
|
||||
new float[] { -0.786268f, 0.169728f },
|
||||
new float[] { -0.8f, 0.156f },
|
||||
|
|
@ -35,38 +54,38 @@ public class JuliaSet
|
|||
new float[] { -0.70176f, -0.3842f },
|
||||
};
|
||||
|
||||
public static int Main()
|
||||
private Shader shader;
|
||||
private RenderTexture2D target;
|
||||
private float[] c;
|
||||
private float[] offset;
|
||||
private float zoom;
|
||||
private int cLoc;
|
||||
private int zoomLoc;
|
||||
private int offsetLoc;
|
||||
private int incrementSpeed;
|
||||
private bool showControls;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
const float zoomSpeed = 1.01f;
|
||||
const float offsetSpeedMul = 2.0f;
|
||||
|
||||
const float startingZoom = 0.75f;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - julia sets");
|
||||
|
||||
// Load julia set shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/julia_set.fs");
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/julia_set.fs");
|
||||
|
||||
// Create a RenderTexture2D to be used for render to texture
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// c constant to use in z^2 + c
|
||||
float[] c = { PointsOfInterest[0][0], PointsOfInterest[0][1] };
|
||||
c = new float[] { PointsOfInterest[0][0], PointsOfInterest[0][1] };
|
||||
|
||||
// Offset and zoom to draw the julia set at. (centered on screen and default size)
|
||||
float[] offset = { 0, 0 };
|
||||
float zoom = startingZoom;
|
||||
offset = new float[] { 0, 0 };
|
||||
zoom = startingZoom;
|
||||
|
||||
// Get variable (uniform) locations on the shader to connect with the program
|
||||
// NOTE: If uniform variable could not be found in the shader, function returns -1
|
||||
int cLoc = GetShaderLocation(shader, "c");
|
||||
int zoomLoc = GetShaderLocation(shader, "zoom");
|
||||
int offsetLoc = GetShaderLocation(shader, "offset");
|
||||
cLoc = GetShaderLocation(shader, "c");
|
||||
zoomLoc = GetShaderLocation(shader, "zoom");
|
||||
offsetLoc = GetShaderLocation(shader, "offset");
|
||||
|
||||
// Upload the shader uniform values!
|
||||
Raylib.SetShaderValue(shader, cLoc, c, ShaderUniformDataType.Vec2);
|
||||
|
|
@ -74,166 +93,189 @@ public class JuliaSet
|
|||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
|
||||
// Multiplier of speed to change c value
|
||||
int incrementSpeed = 0;
|
||||
incrementSpeed = 0;
|
||||
// Show controls
|
||||
bool showControls = true;
|
||||
showControls = true;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Press [1 - 6] to reset c to a point of interest
|
||||
if (IsKeyPressed(KeyboardKey.One) ||
|
||||
IsKeyPressed(KeyboardKey.Two) ||
|
||||
IsKeyPressed(KeyboardKey.Three) ||
|
||||
IsKeyPressed(KeyboardKey.Four) ||
|
||||
IsKeyPressed(KeyboardKey.Five) ||
|
||||
IsKeyPressed(KeyboardKey.Six))
|
||||
{
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
c[0] = PointsOfInterest[0][0];
|
||||
c[1] = PointsOfInterest[0][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
c[0] = PointsOfInterest[1][0];
|
||||
c[1] = PointsOfInterest[1][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
c[0] = PointsOfInterest[2][0];
|
||||
c[1] = PointsOfInterest[2][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Four))
|
||||
{
|
||||
c[0] = PointsOfInterest[3][0];
|
||||
c[1] = PointsOfInterest[3][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Five))
|
||||
{
|
||||
c[0] = PointsOfInterest[4][0];
|
||||
c[1] = PointsOfInterest[4][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Six))
|
||||
{
|
||||
c[0] = PointsOfInterest[5][0];
|
||||
c[1] = PointsOfInterest[5][1];
|
||||
}
|
||||
Raylib.SetShaderValue(shader, cLoc, c, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
// If "R" is pressed, reset zoom and offset
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
zoom = startingZoom;
|
||||
offset[0] = 0.0f;
|
||||
offset[1] = 0.0f;
|
||||
Raylib.SetShaderValue(shader, zoomLoc, zoom, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
// Pause animation (c change)
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
incrementSpeed = 0;
|
||||
}
|
||||
|
||||
// Toggle whether or not to show controls
|
||||
if (IsKeyPressed(KeyboardKey.F1))
|
||||
{
|
||||
showControls = !showControls;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
incrementSpeed++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
incrementSpeed--;
|
||||
}
|
||||
|
||||
// If either left or right button is pressed, zoom in/out
|
||||
if (IsMouseButtonDown(MouseButton.Left) || IsMouseButtonDown(MouseButton.Right))
|
||||
{
|
||||
if (IsMouseButtonDown(MouseButton.Left))
|
||||
{
|
||||
zoom *= zoomSpeed;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MouseButton.Right))
|
||||
{
|
||||
zoom *= 1.0f / zoomSpeed;
|
||||
}
|
||||
|
||||
var mousePos = GetMousePosition();
|
||||
var offsetVelocity = Vector2.Zero;
|
||||
|
||||
offsetVelocity.X = (mousePos.X / screenWidth - 0.5f) * offsetSpeedMul / zoom;
|
||||
offsetVelocity.Y = (mousePos.Y / screenHeight - 0.5f) * offsetSpeedMul / zoom;
|
||||
|
||||
// Apply move velocity to camera
|
||||
offset[0] += GetFrameTime() * offsetVelocity.X;
|
||||
offset[1] += GetFrameTime() * offsetVelocity.Y;
|
||||
|
||||
Raylib.SetShaderValue(shader, zoomLoc, zoom, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
// Increment c value with time
|
||||
var dc = GetFrameTime() * incrementSpeed * 0.0005f;
|
||||
c[0] += dc;
|
||||
c[1] += dc;
|
||||
|
||||
Raylib.SetShaderValue(shader, cLoc, c, ShaderUniformDataType.Vec2);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Using a render texture to draw Julia set
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw a rectangle in shader mode to be used as shader canvas
|
||||
// NOTE: Rectangle uses font white character texture coordinates,
|
||||
// so shader can not be applied here directly because input vertexTexCoord
|
||||
// do not represent full screen coordinates (space where want to apply shader)
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Black);
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw the saved texture and rendered julia set with shader
|
||||
// NOTE: We do not invert texture on Y, already considered inside shader
|
||||
BeginShaderMode(shader);
|
||||
// WARNING: If FLAG_WINDOW_HIGHDPI is enabled, HighDPI monitor scaling should be considered
|
||||
// when rendering the RenderTexture2D to fit in the HighDPI scaled Window
|
||||
DrawTextureEx(target.Texture, new Vector2(0.0f, 0.0f), 0.0f, 1.0f, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
if (showControls)
|
||||
{
|
||||
DrawText("Press Mouse buttons right/left to zoom in/out and move", 10, 15, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_F1 to toggle these controls", 10, 30, 10, Color.RayWhite);
|
||||
DrawText("Press KEYS [1 - 6] to change point of interest", 10, 45, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_LEFT | KEY_RIGHT to change speed", 10, 60, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_SPACE to stop movement animation", 10, 75, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_R to recenter the camera", 10, 90, 10, Color.RayWhite);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
UnloadRenderTexture(target);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - julia set");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new JuliaSet();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Press [1 - 6] to reset c to a point of interest
|
||||
if (IsKeyPressed(KeyboardKey.One) ||
|
||||
IsKeyPressed(KeyboardKey.Two) ||
|
||||
IsKeyPressed(KeyboardKey.Three) ||
|
||||
IsKeyPressed(KeyboardKey.Four) ||
|
||||
IsKeyPressed(KeyboardKey.Five) ||
|
||||
IsKeyPressed(KeyboardKey.Six))
|
||||
{
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
c[0] = PointsOfInterest[0][0];
|
||||
c[1] = PointsOfInterest[0][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
c[0] = PointsOfInterest[1][0];
|
||||
c[1] = PointsOfInterest[1][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
c[0] = PointsOfInterest[2][0];
|
||||
c[1] = PointsOfInterest[2][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Four))
|
||||
{
|
||||
c[0] = PointsOfInterest[3][0];
|
||||
c[1] = PointsOfInterest[3][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Five))
|
||||
{
|
||||
c[0] = PointsOfInterest[4][0];
|
||||
c[1] = PointsOfInterest[4][1];
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Six))
|
||||
{
|
||||
c[0] = PointsOfInterest[5][0];
|
||||
c[1] = PointsOfInterest[5][1];
|
||||
}
|
||||
Raylib.SetShaderValue(shader, cLoc, c, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
zoom = startingZoom;
|
||||
offset[0] = 1f;
|
||||
offset[1] = 1f;
|
||||
Raylib.SetShaderValue(shader, zoomLoc, zoom, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
// Pause animation (c change)
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
incrementSpeed = 0;
|
||||
}
|
||||
|
||||
// Toggle whether or not to show controls
|
||||
if (IsKeyPressed(KeyboardKey.F1))
|
||||
{
|
||||
showControls = !showControls;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
incrementSpeed++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
incrementSpeed--;
|
||||
}
|
||||
|
||||
// If either left or right button is pressed, zoom in/out
|
||||
if (IsMouseButtonDown(MouseButton.Left) || IsMouseButtonDown(MouseButton.Right))
|
||||
{
|
||||
if (IsMouseButtonDown(MouseButton.Left))
|
||||
{
|
||||
zoom *= zoomSpeed;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MouseButton.Right))
|
||||
{
|
||||
zoom *= 1.0f / zoomSpeed;
|
||||
}
|
||||
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
Vector2 offsetVelocity = Vector2.Zero;
|
||||
|
||||
offsetVelocity.X = (mousePos.X / screenWidth - 0.5f) * offsetSpeedMul / zoom;
|
||||
offsetVelocity.Y = (mousePos.Y / screenHeight - 0.5f) * offsetSpeedMul / zoom;
|
||||
|
||||
// Apply move velocity to camera
|
||||
offset[0] += GetFrameTime() * offsetVelocity.X;
|
||||
offset[1] += GetFrameTime() * offsetVelocity.Y;
|
||||
|
||||
Raylib.SetShaderValue(shader, zoomLoc, zoom, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
// Increment c value with time
|
||||
float amount = GetFrameTime() * incrementSpeed * 0.0005f;
|
||||
c[0] += amount;
|
||||
c[1] += amount;
|
||||
|
||||
Raylib.SetShaderValue(shader, cLoc, c, ShaderUniformDataType.Vec2);
|
||||
|
||||
// Using a render texture to draw Julia set
|
||||
// Enable drawing to texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw a rectangle in shader mode to be used as shader canvas
|
||||
// NOTE: Rectangle uses font Color.white character texture coordinates,
|
||||
// so shader can not be applied here directly because input vertexTexCoord
|
||||
// do not represent full screen coordinates (space where want to apply shader)
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Black);
|
||||
EndTextureMode();
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw the saved texture and rendered julia set with shader
|
||||
// NOTE: We do not invert texture on Y, already considered inside shader
|
||||
BeginShaderMode(shader);
|
||||
DrawTexture(target.Texture, 0, 0, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
if (showControls)
|
||||
{
|
||||
DrawText("Press Mouse buttons right/left to zoom in/out and move", 10, 15, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_F1 to toggle these controls", 10, 30, 10, Color.RayWhite);
|
||||
DrawText("Press KEYS [1 - 6] to change point of interest", 10, 45, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_LEFT | KEY_RIGHT to change speed", 10, 60, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_SPACE to pause movement animation", 10, 75, 10, Color.RayWhite);
|
||||
DrawText("Press KEY_R to recenter the camera", 10, 90, 10, Color.RayWhite);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
213
Examples/Shaders/LightmapRendering.cs
Normal file
213
Examples/Shaders/LightmapRendering.cs
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - lightmap rendering
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||
*
|
||||
* Example contributed by Jussi Viitala (@nullstare) 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) 2019-2025 Jussi Viitala (@nullstare) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Rlgl;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class LightmapRendering : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private const int MapSize = 16;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Lightmap Rendering";
|
||||
|
||||
public string Title => "raylib [shaders] example - lightmap rendering";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Mesh mesh;
|
||||
private Shader shader;
|
||||
private Texture2D texture;
|
||||
private Texture2D light;
|
||||
private RenderTexture2D lightmap;
|
||||
private Material material;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(4.0f, 6.0f, 8.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
mesh = GenMeshPlane((float)MapSize, (float)MapSize, 1, 1);
|
||||
|
||||
// GenMeshPlane doesn't generate texcoords2 so we will upload them separately
|
||||
mesh.AllocTexCoords2();
|
||||
|
||||
// X // Y
|
||||
mesh.TexCoords2[0] = 0.0f; mesh.TexCoords2[1] = 0.0f;
|
||||
mesh.TexCoords2[2] = 1.0f; mesh.TexCoords2[3] = 0.0f;
|
||||
mesh.TexCoords2[4] = 0.0f; mesh.TexCoords2[5] = 1.0f;
|
||||
mesh.TexCoords2[6] = 1.0f; mesh.TexCoords2[7] = 1.0f;
|
||||
|
||||
// Load a new texcoords2 attributes buffer
|
||||
mesh.VboId[(int)ShaderLocationIndex.VertexTexcoord02] =
|
||||
LoadVertexBuffer(mesh.TexCoords2, mesh.VertexCount * 2 * sizeof(float), false);
|
||||
EnableVertexArray(mesh.VaoId);
|
||||
|
||||
// Index 5 is for texcoords2
|
||||
SetVertexAttribute(5, 2, Rlgl.FLOAT, false, 0, 0);
|
||||
EnableVertexAttribute(5);
|
||||
DisableVertexArray();
|
||||
|
||||
// Load lightmap shader
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/lightmap.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/lightmap.fs"
|
||||
);
|
||||
|
||||
texture = LoadTexture("resources/cubicmap_atlas.png");
|
||||
light = LoadTexture("resources/spark_flame.png");
|
||||
|
||||
GenTextureMipmaps(ref texture);
|
||||
SetTextureFilter(texture, TextureFilter.Trilinear);
|
||||
|
||||
lightmap = LoadRenderTexture(MapSize, MapSize);
|
||||
|
||||
material = LoadMaterialDefault();
|
||||
material.Shader = shader;
|
||||
material.Maps[(int)MaterialMapIndex.Albedo].Texture = texture;
|
||||
material.Maps[(int)MaterialMapIndex.Metalness].Texture = lightmap.Texture;
|
||||
|
||||
// Drawing to lightmap
|
||||
BeginTextureMode(lightmap);
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
BeginBlendMode(BlendMode.Additive);
|
||||
DrawTexturePro(
|
||||
light,
|
||||
new Rectangle(0, 0, (float)light.Width, (float)light.Height),
|
||||
new Rectangle(0, 0, 2.0f * MapSize, 2.0f * MapSize),
|
||||
new Vector2((float)MapSize, (float)MapSize),
|
||||
0.0f,
|
||||
Color.Red
|
||||
);
|
||||
DrawTexturePro(
|
||||
light,
|
||||
new Rectangle(0, 0, (float)light.Width, (float)light.Height),
|
||||
new Rectangle((float)MapSize * 0.8f, (float)MapSize / 2.0f, 2.0f * MapSize, 2.0f * MapSize),
|
||||
new Vector2((float)MapSize, (float)MapSize),
|
||||
0.0f,
|
||||
Color.Blue
|
||||
);
|
||||
DrawTexturePro(
|
||||
light,
|
||||
new Rectangle(0, 0, (float)light.Width, (float)light.Height),
|
||||
new Rectangle((float)MapSize * 0.8f, (float)MapSize * 0.8f, (float)MapSize, (float)MapSize),
|
||||
new Vector2((float)MapSize / 2.0f, (float)MapSize / 2.0f),
|
||||
0.0f,
|
||||
Color.Green
|
||||
);
|
||||
BeginBlendMode(BlendMode.Alpha);
|
||||
EndTextureMode();
|
||||
|
||||
// NOTE: To enable trilinear filtering we need mipmaps available for texture
|
||||
GenTextureMipmaps(ref lightmap.Texture);
|
||||
SetTextureFilter(lightmap.Texture, TextureFilter.Trilinear);
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawMesh(mesh, material, Matrix4x4.Identity);
|
||||
EndMode3D();
|
||||
|
||||
DrawTexturePro(
|
||||
lightmap.Texture,
|
||||
new Rectangle(0, 0, -MapSize, -MapSize),
|
||||
new Rectangle((float)GetRenderWidth() - MapSize * 8 - 10, 10, (float)MapSize * 8, (float)MapSize * 8),
|
||||
new Vector2(0.0f, 0.0f),
|
||||
0.0f,
|
||||
Color.White
|
||||
);
|
||||
|
||||
DrawText($"LIGHTMAP: {MapSize}x{MapSize} pixels", GetRenderWidth() - 130, 20 + MapSize * 8, 10, Color.Green);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadMesh(mesh); // Unload the mesh
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadTexture(light); // Unload texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - lightmap rendering");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new LightmapRendering();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
265
Examples/Shaders/MandelbrotSet.cs
Normal file
265
Examples/Shaders/MandelbrotSet.cs
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - mandelbrot set
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Jordi Santonja (@JordSant)
|
||||
* Based on previous work by Josh Colclough (@joshcol9232)
|
||||
*
|
||||
* 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) 2025 Jordi Santonja (@JordSant)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class MandelbrotSet : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Mandelbrot Set";
|
||||
|
||||
public string Title => "raylib [shaders] example - mandelbrot set";
|
||||
|
||||
// A few good interesting places
|
||||
private static readonly float[][] pointsOfInterest = new[]
|
||||
{
|
||||
new[] { -1.76826775f, -0.00422996283f, 28435.9238f },
|
||||
new[] { 0.322004497f, -0.0357099883f, 56499.7266f },
|
||||
new[] { -0.748880744f, -0.0562955774f, 9237.59082f },
|
||||
new[] { -1.78385007f, -0.0156200649f, 14599.5283f },
|
||||
new[] { -0.0985441282f, -0.924688697f, 26259.8535f },
|
||||
new[] { 0.317785531f, -0.0322612226f, 29297.9258f },
|
||||
};
|
||||
|
||||
private const float zoomSpeed = 1.01f;
|
||||
private const float offsetSpeedMul = 2.0f;
|
||||
|
||||
private const float startingZoom = 0.6f;
|
||||
private static readonly float[] startingOffset = { -0.5f, 0.0f };
|
||||
|
||||
private Shader shader;
|
||||
private RenderTexture2D target;
|
||||
private float[] offset;
|
||||
private float zoom;
|
||||
private int maxIterations;
|
||||
private float maxIterationsMultiplier;
|
||||
private int zoomLoc;
|
||||
private int offsetLoc;
|
||||
private int maxIterationsLoc;
|
||||
private bool showControls;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Load mandelbrot set shader
|
||||
// NOTE: Defining null (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/mandelbrot_set.fs");
|
||||
|
||||
// Create a RenderTexture2D to be used for render to texture
|
||||
target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
|
||||
// Offset and zoom to draw the mandelbrot set at. (centered on screen and default size)
|
||||
offset = new[] { startingOffset[0], startingOffset[1] };
|
||||
zoom = startingZoom;
|
||||
|
||||
// Depending on the zoom the maximum number of iterations must be adapted to get more detail as we zoom in
|
||||
// The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys
|
||||
#if BROWSER
|
||||
maxIterations = 43;
|
||||
maxIterationsMultiplier = 22.0f;
|
||||
#else
|
||||
maxIterations = 333;
|
||||
maxIterationsMultiplier = 166.5f;
|
||||
#endif
|
||||
|
||||
// Get variable (uniform) locations on the shader to connect with the program
|
||||
// NOTE: If uniform variable could not be found in the shader, function returns -1
|
||||
zoomLoc = GetShaderLocation(shader, "zoom");
|
||||
offsetLoc = GetShaderLocation(shader, "offset");
|
||||
maxIterationsLoc = GetShaderLocation(shader, "maxIterations");
|
||||
|
||||
// Upload the shader uniform values!
|
||||
Raylib.SetShaderValue(shader, zoomLoc, zoom, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
Raylib.SetShaderValue(shader, maxIterationsLoc, maxIterations, ShaderUniformDataType.Int);
|
||||
|
||||
showControls = true; // Show controls
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
var updateShader = false;
|
||||
|
||||
// Press [1 - 6] to reset c to a point of interest
|
||||
if (IsKeyPressed(KeyboardKey.One) ||
|
||||
IsKeyPressed(KeyboardKey.Two) ||
|
||||
IsKeyPressed(KeyboardKey.Three) ||
|
||||
IsKeyPressed(KeyboardKey.Four) ||
|
||||
IsKeyPressed(KeyboardKey.Five) ||
|
||||
IsKeyPressed(KeyboardKey.Six))
|
||||
{
|
||||
var interestIndex = 0;
|
||||
if (IsKeyPressed(KeyboardKey.One)) interestIndex = 0;
|
||||
else if (IsKeyPressed(KeyboardKey.Two)) interestIndex = 1;
|
||||
else if (IsKeyPressed(KeyboardKey.Three)) interestIndex = 2;
|
||||
else if (IsKeyPressed(KeyboardKey.Four)) interestIndex = 3;
|
||||
else if (IsKeyPressed(KeyboardKey.Five)) interestIndex = 4;
|
||||
else if (IsKeyPressed(KeyboardKey.Six)) interestIndex = 5;
|
||||
|
||||
offset[0] = pointsOfInterest[interestIndex][0];
|
||||
offset[1] = pointsOfInterest[interestIndex][1];
|
||||
zoom = pointsOfInterest[interestIndex][2];
|
||||
updateShader = true;
|
||||
}
|
||||
|
||||
// If "R" is pressed, reset zoom and offset
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
offset[0] = startingOffset[0];
|
||||
offset[1] = startingOffset[1];
|
||||
zoom = startingZoom;
|
||||
updateShader = true;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.F1)) showControls = !showControls; // Toggle whether or not to show controls
|
||||
|
||||
// Change number of max iterations with UP and DOWN keys
|
||||
// WARNING: Increasing the number of max iterations greatly impacts performance
|
||||
if (IsKeyPressed(KeyboardKey.Up))
|
||||
{
|
||||
maxIterationsMultiplier *= 1.4f;
|
||||
updateShader = true;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Down))
|
||||
{
|
||||
maxIterationsMultiplier /= 1.4f;
|
||||
updateShader = true;
|
||||
}
|
||||
|
||||
// If either left or right button is pressed, zoom in/out
|
||||
if (IsMouseButtonDown(MouseButton.Left) || IsMouseButtonDown(MouseButton.Right))
|
||||
{
|
||||
// Change zoom. If Mouse left -> zoom in. Mouse right -> zoom out
|
||||
zoom *= IsMouseButtonDown(MouseButton.Left) ? zoomSpeed : (1.0f / zoomSpeed);
|
||||
|
||||
var mousePos = GetMousePosition();
|
||||
Vector2 offsetVelocity;
|
||||
// Find the velocity at which to change the camera. Take the distance of the mouse
|
||||
// From the center of the screen as the direction, and adjust magnitude based on the current zoom
|
||||
offsetVelocity.X = (mousePos.X / (float)screenWidth - 0.5f) * offsetSpeedMul / zoom;
|
||||
offsetVelocity.Y = (mousePos.Y / (float)screenHeight - 0.5f) * offsetSpeedMul / zoom;
|
||||
|
||||
// Apply move velocity to camera
|
||||
offset[0] += GetFrameTime() * offsetVelocity.X;
|
||||
offset[1] += GetFrameTime() * offsetVelocity.Y;
|
||||
|
||||
updateShader = true;
|
||||
}
|
||||
|
||||
// In case a parameter has been changed, update the shader values
|
||||
if (updateShader)
|
||||
{
|
||||
// As we zoom in, increase the number of max iterations to get more detail
|
||||
// Aproximate formula, but it works-ish
|
||||
maxIterations = (int)(MathF.Sqrt(2.0f * MathF.Sqrt(MathF.Abs(1.0f - MathF.Sqrt(37.5f * zoom)))) * maxIterationsMultiplier);
|
||||
|
||||
// Update the shader uniform values!
|
||||
Raylib.SetShaderValue(shader, zoomLoc, zoom, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, offsetLoc, offset, ShaderUniformDataType.Vec2);
|
||||
Raylib.SetShaderValue(shader, maxIterationsLoc, maxIterations, ShaderUniformDataType.Int);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Using a render texture to draw Mandelbrot set
|
||||
BeginTextureMode(target); // Enable drawing to texture
|
||||
ClearBackground(Color.Black); // Clear the render texture
|
||||
|
||||
// Draw a rectangle in shader mode to be used as shader canvas
|
||||
// NOTE: Rectangle uses font white character texture coordinates,
|
||||
// So shader can not be applied here directly because input vertexTexCoord
|
||||
// Do not represent full screen coordinates (space where want to apply shader)
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Black);
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black); // Clear screen background
|
||||
|
||||
// Draw the saved texture and rendered mandelbrot set with shader
|
||||
// NOTE: We do not invert texture on Y, already considered inside shader
|
||||
BeginShaderMode(shader);
|
||||
// WARNING: If FLAG_WINDOW_HIGHDPI is enabled, HighDPI monitor scaling should be considered
|
||||
// When rendering the RenderTexture2D to fit in the HighDPI scaled Window
|
||||
DrawTextureEx(target.Texture, new Vector2(0.0f, 0.0f), 0.0f, 1.0f, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
if (showControls)
|
||||
{
|
||||
DrawText("Press Mouse buttons right/left to zoom in/out and move", 10, 15, 10, Color.RayWhite);
|
||||
DrawText("Press F1 to toggle these controls", 10, 30, 10, Color.RayWhite);
|
||||
DrawText("Press [1 - 6] to change point of interest", 10, 45, 10, Color.RayWhite);
|
||||
DrawText("Press UP | DOWN to change number of iterations", 10, 60, 10, Color.RayWhite);
|
||||
DrawText("Press R to recenter the camera", 10, 75, 10, Color.RayWhite);
|
||||
}
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mandelbrot set");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new MandelbrotSet();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,112 +1,97 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - rlgl module usage for instanced meshes
|
||||
* raylib [shaders] example - mesh instancing
|
||||
*
|
||||
* This example uses [rlgl] module funtionality (pseudo-OpenGL 1.1 style coding)
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* This example has been created using raylib 3.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 3.7, last time updated with raylib 4.2
|
||||
*
|
||||
* Example contributed by @seanpringle and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by seanpringle (@seanpringle) and reviewed by Max (@moliad) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2020 @seanpringle
|
||||
* 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) 2020-2025 seanpringle (@seanpringle), Max (@moliad) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using Examples.Shared;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class MeshInstancing
|
||||
public class MeshInstancing : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int MaxInstances = 10000;
|
||||
|
||||
public string Name => "Shaders / Mesh Instancing";
|
||||
|
||||
public string Title => "raylib [shaders] example - mesh instancing";
|
||||
|
||||
private Camera3D camera;
|
||||
private Mesh cube;
|
||||
private Matrix4x4[] transforms;
|
||||
private Shader shader;
|
||||
private Material matInstances;
|
||||
private Material matDefault;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
const int fps = 60;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - rlgl mesh instanced");
|
||||
|
||||
// Speed of jump animation
|
||||
int speed = 30;
|
||||
// Count of separate groups jumping around
|
||||
int groups = 2;
|
||||
// Maximum amplitude of jump
|
||||
float amp = 10;
|
||||
// Global variance in jump height
|
||||
float variance = 0.8f;
|
||||
// Individual cube's computed loop timer
|
||||
float loop = 0.0f;
|
||||
|
||||
// Used for various 3D coordinate & vector ops
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(-125.0f, 125.0f, -125.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(-125.0f, 125.0f, -125.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Number of instances to display
|
||||
const int instances = 10000;
|
||||
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
|
||||
// Define mesh to be instanced
|
||||
cube = GenMeshCube(1.0f, 1.0f, 1.0f);
|
||||
|
||||
// Rotation state of instances
|
||||
Matrix4x4[] rotations = new Matrix4x4[instances];
|
||||
// Per-frame rotation animation of instances
|
||||
Matrix4x4[] rotationsInc = new Matrix4x4[instances];
|
||||
// Locations of instances
|
||||
Matrix4x4[] translations = new Matrix4x4[instances];
|
||||
// Define transforms to be uploaded to GPU for instances
|
||||
transforms = new Matrix4x4[MaxInstances]; // Pre-multiplied transformations passed to rlgl
|
||||
|
||||
// Scatter random cubes around
|
||||
for (int i = 0; i < instances; i++)
|
||||
// Translate and rotate cubes randomly
|
||||
for (var i = 0; i < MaxInstances; i++)
|
||||
{
|
||||
x = GetRandomValue(-50, 50);
|
||||
y = GetRandomValue(-50, 50);
|
||||
z = GetRandomValue(-50, 50);
|
||||
translations[i] = Matrix4x4.CreateTranslation(x, y, z);
|
||||
|
||||
x = GetRandomValue(0, 360);
|
||||
y = GetRandomValue(0, 360);
|
||||
z = GetRandomValue(0, 360);
|
||||
Vector3 axis = Vector3.Normalize(new Vector3(x, y, z));
|
||||
float angle = (float)GetRandomValue(0, 10) * DEG2RAD;
|
||||
|
||||
rotationsInc[i] = Matrix4x4.CreateFromAxisAngle(axis, angle);
|
||||
rotations[i] = Matrix4x4.Identity;
|
||||
}
|
||||
|
||||
// Pre-multiplied transformations passed to rlgl
|
||||
Matrix4x4[] transforms = new Matrix4x4[instances];
|
||||
Shader shader = LoadShader(
|
||||
"resources/shaders/glsl330/lighting_instancing.vs",
|
||||
"resources/shaders/glsl330/lighting.fs"
|
||||
);
|
||||
|
||||
// Get some shader loactions
|
||||
unsafe
|
||||
{
|
||||
int* locs = (int*)shader.Locs;
|
||||
locs[(int)ShaderLocationIndex.MatrixMvp] = GetShaderLocation(shader, "mvp");
|
||||
locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(shader, "viewPos");
|
||||
locs[(int)ShaderLocationIndex.MatrixModel] = GetShaderLocationAttrib(
|
||||
shader,
|
||||
"instanceTransform"
|
||||
var translation = Matrix4x4.CreateTranslation(
|
||||
GetRandomValue(-50, 50),
|
||||
GetRandomValue(-50, 50),
|
||||
GetRandomValue(-50, 50)
|
||||
);
|
||||
var axis = Vector3.Normalize(new Vector3(
|
||||
GetRandomValue(0, 360),
|
||||
GetRandomValue(0, 360),
|
||||
GetRandomValue(0, 360)
|
||||
));
|
||||
var angle = GetRandomValue(0, 180) * DEG2RAD;
|
||||
var rotation = Matrix4x4.CreateFromAxisAngle(axis, angle);
|
||||
|
||||
transforms[i] = Matrix4x4.Transpose(Matrix4x4.Multiply(rotation, translation));
|
||||
}
|
||||
|
||||
// Ambient light level
|
||||
int ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
// Load lighting shader
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/lighting_instancing.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/lighting.fs"
|
||||
);
|
||||
// Get shader locations
|
||||
shader.Locs[(int)ShaderLocationIndex.MatrixMvp] = GetShaderLocation(shader, "mvp");
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(shader, "viewPos");
|
||||
|
||||
// Set shader value: ambient light level
|
||||
var ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
ambientLoc,
|
||||
|
|
@ -114,211 +99,105 @@ public class MeshInstancing
|
|||
ShaderUniformDataType.Vec4
|
||||
);
|
||||
|
||||
// Create one light
|
||||
Rlights.CreateLight(
|
||||
0,
|
||||
LightType.Directorional,
|
||||
new Vector3(50, 50, 0),
|
||||
new Vector3(50.0f, 50.0f, 0.0f),
|
||||
Vector3.Zero,
|
||||
Color.White,
|
||||
shader
|
||||
);
|
||||
|
||||
Material material = LoadMaterialDefault();
|
||||
material.Shader = shader;
|
||||
unsafe
|
||||
{
|
||||
material.Maps[(int)MaterialMapIndex.Diffuse].Color = Color.Red;
|
||||
}
|
||||
// NOTE: We are assigning the intancing shader to material.shader
|
||||
// to be used on mesh drawing with DrawMeshInstanced()
|
||||
matInstances = LoadMaterialDefault();
|
||||
matInstances.Shader = shader;
|
||||
matInstances.Maps[(int)MaterialMapIndex.Diffuse].Color = Color.Red;
|
||||
|
||||
int textPositionY = 300;
|
||||
// Load default material (using raylib intenral default shader) for non-instanced mesh drawing
|
||||
// WARNING: Default shader enables vertex color attribute BUT GenMeshCube() does not generate vertex colors, so,
|
||||
// when drawing the color attribute is disabled and a default color value is provided as input for thevertex attribute
|
||||
matDefault = LoadMaterialDefault();
|
||||
matDefault.Maps[(int)MaterialMapIndex.Diffuse].Color = Color.Blue;
|
||||
}
|
||||
|
||||
// Simple frames counter to manage animation
|
||||
int framesCounter = 0;
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
SetTargetFPS(fps);
|
||||
// Update the light shader with the camera view position
|
||||
float[] cameraPos = { camera.Position.X, camera.Position.Y, camera.Position.Z };
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
cameraPos,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw cube mesh with default material (BLUE)
|
||||
DrawMesh(cube, matDefault, Matrix4x4.Transpose(Matrix4x4.CreateTranslation(-10.0f, 0.0f, 0.0f)));
|
||||
|
||||
// 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, MaxInstances);
|
||||
|
||||
// Draw cube mesh with default material (BLUE)
|
||||
DrawMesh(cube, matDefault, Matrix4x4.Transpose(Matrix4x4.CreateTranslation(10.0f, 0.0f, 0.0f)));
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// Detach shader so UnloadMaterial does not also unload it, then free everything.
|
||||
matInstances.Shader = new();
|
||||
UnloadMaterial(matInstances);
|
||||
UnloadMaterial(matDefault);
|
||||
UnloadMesh(cube);
|
||||
UnloadShader(shader);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mesh instancing");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new MeshInstancing();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
textPositionY = 300;
|
||||
framesCounter += 1;
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
amp += 0.5f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
amp = (amp <= 1) ? 1.0f : (amp - 1.0f);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
variance = (variance <= 0.0f) ? 0.0f : (variance - 0.01f);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
variance = (variance >= 1.0f) ? 1.0f : (variance + 0.01f);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.One))
|
||||
{
|
||||
groups = 1;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Two))
|
||||
{
|
||||
groups = 2;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Three))
|
||||
{
|
||||
groups = 3;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Four))
|
||||
{
|
||||
groups = 4;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Five))
|
||||
{
|
||||
groups = 5;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Six))
|
||||
{
|
||||
groups = 6;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Seven))
|
||||
{
|
||||
groups = 7;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Eight))
|
||||
{
|
||||
groups = 8;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Nine))
|
||||
{
|
||||
groups = 9;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.W))
|
||||
{
|
||||
groups = 7;
|
||||
amp = 25;
|
||||
speed = 18;
|
||||
variance = 0.70f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Equal))
|
||||
{
|
||||
speed = (speed <= (int)(fps * 0.25f)) ? (int)(fps * 0.25f) : (int)(speed * 0.95f);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.KpAdd))
|
||||
{
|
||||
speed = (speed <= (int)(fps * 0.25f)) ? (int)(fps * 0.25f) : (int)(speed * 0.95f);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Minus))
|
||||
{
|
||||
speed = (int)MathF.Max(speed * 1.02f, speed + 1);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.KpSubtract))
|
||||
{
|
||||
speed = (int)MathF.Max(speed * 1.02f, speed + 1);
|
||||
}
|
||||
|
||||
// Update the light shader with the camera view position
|
||||
float[] cameraPos = { camera.Position.X, camera.Position.Y, camera.Position.Z };
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
(int)ShaderLocationIndex.VectorView,
|
||||
cameraPos,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
// Apply per-instance transformations
|
||||
for (int i = 0; i < instances; i++)
|
||||
{
|
||||
rotations[i] = Matrix4x4.Multiply(rotations[i], rotationsInc[i]);
|
||||
transforms[i] = Matrix4x4.Multiply(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 = (MathF.Sin(loop * MathF.PI * 2)) * amp * ((1 - variance) + (variance * (float)(i % (groups * 10)) / (groups * 10)));
|
||||
|
||||
// Clamp to floor
|
||||
y = (y < 0) ? 0.0f : y;
|
||||
|
||||
transforms[i] = Matrix4x4.Multiply(transforms[i], Matrix4x4.CreateTranslation(0.0f, y, 0.0f));
|
||||
transforms[i] = Matrix4x4.Transpose(transforms[i]);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawMeshInstanced(cube, material, transforms, instances);
|
||||
EndMode3D();
|
||||
|
||||
DrawText("A CUBE OF DANCING CUBES!", 490, 10, 20, Color.Maroon);
|
||||
DrawText("PRESS KEYS:", 10, textPositionY, 20, Color.Black);
|
||||
|
||||
DrawText("1 - 9", 10, textPositionY += 25, 10, Color.Black);
|
||||
DrawText(": Number of groups", 50, textPositionY, 10, Color.Black);
|
||||
DrawText($": {groups}", 160, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("UP", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": increase amplitude", 50, textPositionY, 10, Color.Black);
|
||||
DrawText($": {amp}%.2f", 160, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("DOWN", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": decrease amplitude", 50, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("LEFT", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": decrease variance", 50, textPositionY, 10, Color.Black);
|
||||
DrawText($": {variance}.2f", 160, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("RIGHT", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": increase variance", 50, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("+/=", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": increase speed", 50, textPositionY, 10, Color.Black);
|
||||
DrawText($": {speed} = {((float)fps / speed)} loops/sec", 160, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("-", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": decrease speed", 50, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawText("W", 10, textPositionY += 15, 10, Color.Black);
|
||||
DrawText(": Wild setup!", 50, textPositionY, 10, Color.Black);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Apply a shader to a 3d model
|
||||
* raylib [shaders] example - model shader
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 3.7
|
||||
*
|
||||
* Copyright (c) 2014 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -21,86 +25,122 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class ModelShader
|
||||
public class ModelShader : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Model Shader";
|
||||
|
||||
public string Title => "raylib [shaders] example - model shader";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private Model model;
|
||||
private Texture2D texture;
|
||||
private Shader shader;
|
||||
private Vector3 position;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(4.0f, 4.0f, 4.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 1.0f, -1.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
model = LoadModel("resources/models/obj/watermill.obj"); // Load OBJ model
|
||||
texture = LoadTexture("resources/models/obj/watermill_diffuse.png"); // Load model texture
|
||||
|
||||
// Load shader for model
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/grayscale.fs");
|
||||
|
||||
Raylib.SetMaterialShader(ref model, 0, ref shader); // Set shader effect to 3d model
|
||||
Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Albedo, ref texture); // Bind texture to model
|
||||
|
||||
position = new(0.0f, 0.0f, 0.0f); // Set model position
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(model, position, 0.2f, Color.White); // Draw 3d model with texture
|
||||
|
||||
DrawGrid(10, 1.0f); // Draw a grid
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText(
|
||||
"(c) Watermill 3D model by Alberto Cano",
|
||||
screenWidth - 210,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadModel(model); // Unload model
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(4.0f, 4.0f, 4.0f);
|
||||
camera.Target = new Vector3(0.0f, 1.0f, -1.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
Model model = LoadModel("resources/models/obj/watermill.obj");
|
||||
Texture2D texture = LoadTexture("resources/models/obj/watermill_diffuse.png");
|
||||
Shader shader = LoadShader("resources/shaders/glsl330/base.vs",
|
||||
"resources/shaders/glsl330/grayscale.fs");
|
||||
|
||||
Raylib.SetMaterialShader(ref model, 0, ref shader);
|
||||
Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Albedo, ref texture);
|
||||
|
||||
Vector3 position = new(0.0f, 0.0f, 0.0f);
|
||||
|
||||
SetTargetFPS(60);
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ModelShader();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(model, position, 0.2f, Color.White);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText(
|
||||
"(c) Watermill 3D model by Alberto Cano",
|
||||
screenWidth - 210,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
DrawText($"Camera3D position: ({camera.Position})", 600, 20, 10, Color.Black);
|
||||
DrawText($"Camera3D target: ({camera.Position})", 600, 40, 10, Color.Gray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(texture);
|
||||
UnloadModel(model);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Multiple sample2D with default batch system
|
||||
* raylib [shaders] example - multi sample2d
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 3.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 3.5, last time updated with raylib 3.5
|
||||
*
|
||||
* Copyright (c) 2020 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) 2020-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -20,94 +24,129 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class MultiSample2d
|
||||
public class MultiSample2d : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Multi Sample 2D";
|
||||
|
||||
public string Title => "raylib [shaders] example - multi sample2d";
|
||||
|
||||
private Texture2D texRed;
|
||||
private Texture2D texBlue;
|
||||
private Shader shader;
|
||||
private int texBlueLoc;
|
||||
private int dividerLoc;
|
||||
private float dividerValue;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var imRed = GenImageColor(800, 450, new Color(255, 0, 0, 255));
|
||||
texRed = LoadTextureFromImage(imRed);
|
||||
UnloadImage(imRed);
|
||||
|
||||
var imBlue = GenImageColor(800, 450, new Color(0, 0, 255, 255));
|
||||
texBlue = LoadTextureFromImage(imBlue);
|
||||
UnloadImage(imBlue);
|
||||
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/color_mix.fs");
|
||||
|
||||
// Get an additional sampler2D location to be enabled on drawing
|
||||
texBlueLoc = GetShaderLocation(shader, "texture1");
|
||||
|
||||
// Get shader uniform for divider
|
||||
dividerLoc = GetShaderLocation(shader, "divider");
|
||||
dividerValue = 0.5f;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
dividerValue += 0.01f;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
dividerValue -= 0.01f;
|
||||
}
|
||||
|
||||
if (dividerValue < 0.0f)
|
||||
{
|
||||
dividerValue = 0.0f;
|
||||
}
|
||||
else if (dividerValue > 1.0f)
|
||||
{
|
||||
dividerValue = 1.0f;
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(shader, dividerLoc, dividerValue, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// WARNING: Additional textures (sampler2D) are enabled for ALL draw calls in the batch,
|
||||
// but EndShaderMode() forces batch drawing and resets active textures, this way
|
||||
// other textures (sampler2D) can be activated on consequent drawings (if required)
|
||||
// The downside of this approach is that SetShaderValue() must be called inside the loop,
|
||||
// to be set again after every EndShaderMode() reset
|
||||
SetShaderValueTexture(shader, texBlueLoc, texBlue);
|
||||
|
||||
// We are drawing texRed using default [sampler2D texture0] but
|
||||
// an additional texture units is enabled for texBlue [sampler2D texture1]
|
||||
DrawTexture(texRed, 0, 0, Color.White);
|
||||
|
||||
EndShaderMode(); // Texture sampler2D is reseted, needs to be set again for next frame
|
||||
|
||||
var y = GetScreenHeight() - 40;
|
||||
DrawText("Use KEY_LEFT/KEY_RIGHT to move texture mixing in shader!", 80, y, 20, Color.RayWhite);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(texRed);
|
||||
UnloadTexture(texBlue);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib - multiple sample2D");
|
||||
|
||||
Image imRed = GenImageColor(800, 450, new Color(255, 0, 0, 255));
|
||||
Texture2D texRed = LoadTextureFromImage(imRed);
|
||||
UnloadImage(imRed);
|
||||
|
||||
Image imBlue = GenImageColor(800, 450, new Color(0, 0, 255, 255));
|
||||
Texture2D texBlue = LoadTextureFromImage(imBlue);
|
||||
UnloadImage(imBlue);
|
||||
|
||||
Shader shader = LoadShader(null, "resources/shaders/glsl330/color_mix.fs");
|
||||
|
||||
// Get an additional sampler2D location to be enabled on drawing
|
||||
int texBlueLoc = GetShaderLocation(shader, "texture1");
|
||||
|
||||
// Get shader uniform for divider
|
||||
int dividerLoc = GetShaderLocation(shader, "divider");
|
||||
float dividerValue = 0.5f;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - multi sample2d");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new MultiSample2d();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
dividerValue += 0.01f;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
dividerValue -= 0.01f;
|
||||
}
|
||||
|
||||
if (dividerValue < 0.0f)
|
||||
{
|
||||
dividerValue = 0.0f;
|
||||
}
|
||||
else if (dividerValue > 1.0f)
|
||||
{
|
||||
dividerValue = 1.0f;
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(shader, dividerLoc, dividerValue, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// WARNING: Additional samplers are enabled for all draw calls in the batch,
|
||||
// EndShaderMode() forces batch drawing and consequently resets active textures
|
||||
// to let other sampler2D to be activated on consequent drawings (if required)
|
||||
SetShaderValueTexture(shader, texBlueLoc, texBlue);
|
||||
|
||||
// We are drawing texRed using default sampler2D texture0 but
|
||||
// an additional texture units is enabled for texBlue (sampler2D texture1)
|
||||
DrawTexture(texRed, 0, 0, Color.White);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
int y = GetScreenHeight() - 40;
|
||||
DrawText("Use KEY_LEFT/KEY_RIGHT to move texture mixing in shader!", 80, y, 20, Color.RayWhite);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(texRed);
|
||||
UnloadTexture(texBlue);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
233
Examples/Shaders/NormalmapRendering.cs
Normal file
233
Examples/Shaders/NormalmapRendering.cs
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - normalmap rendering
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Jeremy Montgomery (@Sir_Irk) 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) 2025 Jeremy Montgomery (@Sir_Irk) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Raymath;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class NormalmapRendering : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Normalmap Rendering";
|
||||
|
||||
public string Title => "raylib [shaders] example - normalmap rendering";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Shader shader;
|
||||
private Model plane;
|
||||
private Vector3 lightPosition;
|
||||
private int lightPosLoc;
|
||||
private float specularExponent;
|
||||
private int specularExponentLoc;
|
||||
private int useNormalMap;
|
||||
private int useNormalMapLoc;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
camera = new();
|
||||
camera.Position = new Vector3(0.0f, 2.0f, -4.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
// Load basic normal map lighting shader
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/normalmap.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/normalmap.fs"
|
||||
);
|
||||
|
||||
// Get some required shader locations
|
||||
shader.Locs[(int)ShaderLocationIndex.MapNormal] = GetShaderLocation(shader, "normalMap");
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(shader, "viewPos");
|
||||
|
||||
// NOTE: "matModel" location name is automatically assigned on shader loading,
|
||||
// no need to get the location again if using that uniform name
|
||||
// shader.Locs[(int)ShaderLocationIndex.MatrixModel] = GetShaderLocation(shader, "matModel");
|
||||
|
||||
// This example uses just 1 point light
|
||||
lightPosition = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
lightPosLoc = GetShaderLocation(shader, "lightPos");
|
||||
|
||||
// Load a plane model that has proper normals and tangents
|
||||
plane = LoadModel("resources/models/plane.glb");
|
||||
|
||||
// Set the plane model's shader and texture maps
|
||||
plane.Materials[0].Shader = shader;
|
||||
plane.Materials[0].Maps[(int)MaterialMapIndex.Diffuse].Texture = LoadTexture("resources/tiles_diffuse.png");
|
||||
plane.Materials[0].Maps[(int)MaterialMapIndex.Normal].Texture = LoadTexture("resources/tiles_normal.png");
|
||||
|
||||
// Generate Mipmaps and use TRILINEAR filtering to help with texture aliasing
|
||||
GenTextureMipmaps(ref plane.Materials[0].Maps[(int)MaterialMapIndex.Diffuse].Texture);
|
||||
GenTextureMipmaps(ref plane.Materials[0].Maps[(int)MaterialMapIndex.Normal].Texture);
|
||||
|
||||
SetTextureFilter(plane.Materials[0].Maps[(int)MaterialMapIndex.Diffuse].Texture, TextureFilter.Trilinear);
|
||||
SetTextureFilter(plane.Materials[0].Maps[(int)MaterialMapIndex.Normal].Texture, TextureFilter.Trilinear);
|
||||
|
||||
// Specular exponent AKA shininess of the material
|
||||
specularExponent = 8.0f;
|
||||
specularExponentLoc = GetShaderLocation(shader, "specularExponent");
|
||||
|
||||
// Allow toggling the normal map on and off for comparison purposes
|
||||
useNormalMap = 1;
|
||||
useNormalMapLoc = GetShaderLocation(shader, "useNormalMap");
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Move the light around on the X and Z axis using WASD keys
|
||||
Vector3 direction = new(0.0f, 0.0f, 0.0f);
|
||||
if (IsKeyDown(KeyboardKey.W))
|
||||
{
|
||||
direction = Vector3Add(direction, new Vector3(0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.S))
|
||||
{
|
||||
direction = Vector3Add(direction, new Vector3(0.0f, 0.0f, -1.0f));
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.D))
|
||||
{
|
||||
direction = Vector3Add(direction, new Vector3(-1.0f, 0.0f, 0.0f));
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.A))
|
||||
{
|
||||
direction = Vector3Add(direction, new Vector3(1.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
direction = Vector3Normalize(direction);
|
||||
lightPosition = Vector3Add(lightPosition, Vector3Scale(direction, GetFrameTime() * 3.0f));
|
||||
|
||||
// Increase/Decrease the specular exponent(shininess)
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
specularExponent = Clamp(specularExponent + 40.0f * GetFrameTime(), 2.0f, 128.0f);
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
specularExponent = Clamp(specularExponent - 40.0f * GetFrameTime(), 2.0f, 128.0f);
|
||||
}
|
||||
|
||||
// Toggle normal map on and off
|
||||
if (IsKeyPressed(KeyboardKey.N))
|
||||
{
|
||||
useNormalMap = (useNormalMap != 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
// Spin plane model at a constant rate
|
||||
plane.Transform = MatrixRotateY((float)GetTime() * 0.5f);
|
||||
|
||||
// Update shader values
|
||||
Raylib.SetShaderValue(shader, lightPosLoc, lightPosition, ShaderUniformDataType.Vec3);
|
||||
|
||||
Raylib.SetShaderValue(
|
||||
shader,
|
||||
shader.Locs[(int)ShaderLocationIndex.VectorView],
|
||||
camera.Position,
|
||||
ShaderUniformDataType.Vec3
|
||||
);
|
||||
|
||||
Raylib.SetShaderValue(shader, specularExponentLoc, specularExponent, ShaderUniformDataType.Float);
|
||||
|
||||
Raylib.SetShaderValue(shader, useNormalMapLoc, useNormalMap, ShaderUniformDataType.Int);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawModel(plane, Vector3.Zero, 2.0f, Color.White);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
// Draw sphere to show light position
|
||||
DrawSphereWires(lightPosition, 0.2f, 8, 8, Color.Orange);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
Color textColor = (useNormalMap != 0) ? Color.DarkGreen : Color.Red;
|
||||
string toggleStr = (useNormalMap != 0) ? "On" : "Off";
|
||||
DrawText($"Use key [N] to toggle normal map: {toggleStr}", 10, 10, 10, textColor);
|
||||
|
||||
int yOffset = 24;
|
||||
DrawText("Use keys [W][A][S][D] to move the light", 10, 10 + yOffset * 1, 10, Color.Black);
|
||||
DrawText("Use keys [Up][Down] to change specular exponent", 10, 10 + yOffset * 2, 10, Color.Black);
|
||||
DrawText($"Specular Exponent: {specularExponent:F2}", 10, 10 + yOffset * 3, 10, Color.Blue);
|
||||
|
||||
DrawFPS(screenWidth - 90, 10);
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
UnloadModel(plane);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - normalmap rendering");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new NormalmapRendering();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,24 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Color palette switch
|
||||
* raylib [shaders] example - palette switch
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 2.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.7
|
||||
*
|
||||
* Example contributed by Marco Lizza (@MarcoLizza) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 Marco Lizza (@MarcoLizza) and 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) 2019-2025 Marco Lizza (@MarcoLizza) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -22,13 +26,24 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class PaletteSwitch
|
||||
public class PaletteSwitch : IExample
|
||||
{
|
||||
const int GlslVersion = 330;
|
||||
const int ColorsPerPalette = 8;
|
||||
const int VALUES_PER_COLOR = 3;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
static int[][] Palettes = new int[][] {
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
private const int ColorsPerPalette = 8;
|
||||
private const int VALUES_PER_COLOR = 3;
|
||||
|
||||
public string Name => "Shaders / Palette Switch";
|
||||
|
||||
public string Title => "raylib [shaders] example - palette switch";
|
||||
|
||||
private int[][] Palettes = new int[][] {
|
||||
// 3-BIT RGB
|
||||
new int[] {
|
||||
0, 0, 0,
|
||||
|
|
@ -64,101 +79,119 @@ public class PaletteSwitch
|
|||
}
|
||||
};
|
||||
|
||||
static string[] PaletteText = new string[] {
|
||||
private string[] PaletteText = new string[] {
|
||||
"3-BIT RGB",
|
||||
"AMMO-8 (GameBoy-like)",
|
||||
"RKBV (2-strip film)"
|
||||
};
|
||||
|
||||
private Shader shader;
|
||||
private int paletteLoc;
|
||||
private int currentPalette;
|
||||
private int lineHeight;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Load shader to be used on some parts drawing
|
||||
// NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
|
||||
// NOTE 2: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/palette_switch.fs");
|
||||
|
||||
// Get variable (uniform) location on the shader to connect with the program
|
||||
// NOTE: If uniform variable could not be found in the shader, function returns -1
|
||||
paletteLoc = GetShaderLocation(shader, "palette");
|
||||
|
||||
currentPalette = 0;
|
||||
lineHeight = screenHeight / ColorsPerPalette;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
currentPalette++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
currentPalette--;
|
||||
}
|
||||
|
||||
if (currentPalette >= Palettes.Length)
|
||||
{
|
||||
currentPalette = 0;
|
||||
}
|
||||
else if (currentPalette < 0)
|
||||
{
|
||||
currentPalette = Palettes.Length - 1;
|
||||
}
|
||||
|
||||
// Send palette data to the shader to be used on drawing
|
||||
// NOTE: We are sending RGB triplets w/o the alpha channel
|
||||
Raylib.SetShaderValueV(
|
||||
shader,
|
||||
paletteLoc,
|
||||
Palettes[currentPalette],
|
||||
ShaderUniformDataType.IVec3,
|
||||
ColorsPerPalette
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
for (var i = 0; i < ColorsPerPalette; i++)
|
||||
{
|
||||
// Draw horizontal screen-wide rectangles with increasing "palette index"
|
||||
// The used palette index is encoded in the RGB components of the pixel
|
||||
DrawRectangle(0, lineHeight * i, GetScreenWidth(), lineHeight, new Color(i, i, i, 255));
|
||||
}
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("< >", 10, 10, 30, Color.DarkBlue);
|
||||
DrawText("CURRENT PALETTE:", 60, 15, 20, Color.RayWhite);
|
||||
DrawText(PaletteText[currentPalette], 300, 15, 20, Color.Red);
|
||||
|
||||
DrawFPS(700, 15);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - palette switch");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - color palette switch");
|
||||
|
||||
// Load shader to be used on some parts drawing
|
||||
// NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
|
||||
// NOTE 2: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/palette_switch.fs");
|
||||
|
||||
// Get variable (uniform) location on the shader to connect with the program
|
||||
// NOTE: If uniform variable could not be found in the shader, function returns -1
|
||||
int paletteLoc = GetShaderLocation(shader, "palette");
|
||||
|
||||
int currentPalette = 0;
|
||||
int lineHeight = screenHeight / ColorsPerPalette;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new PaletteSwitch();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
currentPalette++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
currentPalette--;
|
||||
}
|
||||
|
||||
if (currentPalette >= Palettes.Length)
|
||||
{
|
||||
currentPalette = 0;
|
||||
}
|
||||
else if (currentPalette < 0)
|
||||
{
|
||||
currentPalette = Palettes.Length - 1;
|
||||
}
|
||||
|
||||
// Send new value to the shader to be used on drawing.
|
||||
// NOTE: We are sending RGB triplets w/o the alpha channel
|
||||
Raylib.SetShaderValueV(
|
||||
shader,
|
||||
paletteLoc,
|
||||
Palettes[currentPalette],
|
||||
ShaderUniformDataType.IVec3,
|
||||
ColorsPerPalette
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
for (int i = 0; i < ColorsPerPalette; i++)
|
||||
{
|
||||
// Draw horizontal screen-wide rectangles with increasing "palette index"
|
||||
// The used palette index is encoded in the RGB components of the pixel
|
||||
DrawRectangle(0, lineHeight * i, GetScreenWidth(), lineHeight, new Color(i, i, i, 255));
|
||||
}
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("< >", 10, 10, 30, Color.DarkBlue);
|
||||
DrawText("CURRENT PALETTE:", 60, 15, 20, Color.RayWhite);
|
||||
DrawText(PaletteText[currentPalette], 300, 15, 20, Color.Red);
|
||||
|
||||
DrawFPS(700, 15);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Apply a postprocessing shader to a scene
|
||||
* raylib [shaders] example - postprocessing
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.0
|
||||
*
|
||||
* Copyright (c) 2015 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -21,11 +25,24 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class PostProcessing
|
||||
public class PostProcessing : IExample
|
||||
{
|
||||
public const int GLSL_VERSION = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
enum PostproShader
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Post Processing";
|
||||
|
||||
public string Title => "raylib [shaders] example - postprocessing";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private enum PostproShader
|
||||
{
|
||||
FxGrayScale = 0,
|
||||
FxPosterization,
|
||||
|
|
@ -43,7 +60,7 @@ public class PostProcessing
|
|||
Max
|
||||
}
|
||||
|
||||
static string[] postproShaderText = new string[] {
|
||||
private string[] postproShaderText = new string[] {
|
||||
"GRAYSCALE",
|
||||
"POSTERIZATION",
|
||||
"DREAM_VISION",
|
||||
|
|
@ -59,40 +76,39 @@ public class PostProcessing
|
|||
//"FXAA"
|
||||
};
|
||||
|
||||
public static int Main()
|
||||
private Camera3D camera;
|
||||
private Model model;
|
||||
private Texture2D texture;
|
||||
private Vector3 position;
|
||||
private Shader[] shaders;
|
||||
private int currentShader;
|
||||
private RenderTexture2D target;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing shader");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(2.0f, 3.0f, 2.0f);
|
||||
camera.Target = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(2.0f, 3.0f, 2.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 1.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
Model model = LoadModel("resources/models/obj/church.obj");
|
||||
Texture2D texture = LoadTexture("resources/models/obj/church_diffuse.png");
|
||||
model = LoadModel("resources/models/church.obj"); // Load OBJ model
|
||||
texture = LoadTexture("resources/models/church_diffuse.png"); // Load model texture (diffuse map)
|
||||
|
||||
// Set model diffuse texture
|
||||
Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Albedo, ref texture);
|
||||
|
||||
Vector3 position = new(0.0f, 0.0f, 0.0f);
|
||||
position = new(0.0f, 0.0f, 0.0f); // Set model position
|
||||
|
||||
// Load all postpro shaders
|
||||
// NOTE 1: All postpro shader use the base vertex shader (DEFAULT_VERTEX_SHADER)
|
||||
// NOTE 2: We load the correct shader depending on GLSL version
|
||||
Shader[] shaders = new Shader[(int)PostproShader.Max];
|
||||
shaders = new Shader[(int)PostproShader.Max];
|
||||
|
||||
// NOTE: Defining null (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
string shaderPath = "resources/shaders/glsl330";
|
||||
var shaderPath = $"resources/shaders/glsl{GlslVersion}";
|
||||
shaders[(int)PostproShader.FxGrayScale] = LoadShader(null, $"{shaderPath}/grayscale.fs");
|
||||
shaders[(int)PostproShader.FxPosterization] = LoadShader(null, $"{shaderPath}/posterization.fs");
|
||||
shaders[(int)PostproShader.FxDreamVision] = LoadShader(null, $"{shaderPath}/dream_vision.fs");
|
||||
|
|
@ -106,99 +122,122 @@ public class PostProcessing
|
|||
shaders[(int)PostproShader.FxBloom] = LoadShader(null, $"{shaderPath}/bloom.fs");
|
||||
shaders[(int)PostproShader.FxBlur] = LoadShader(null, $"{shaderPath}/blur.fs");
|
||||
|
||||
int currentShader = (int)PostproShader.FxGrayScale;
|
||||
currentShader = (int)PostproShader.FxGrayScale;
|
||||
|
||||
// Create a RenderTexture2D to be used for render to texture
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
currentShader++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
currentShader--;
|
||||
}
|
||||
|
||||
if (currentShader >= (int)PostproShader.Max)
|
||||
{
|
||||
currentShader = 0;
|
||||
}
|
||||
else if (currentShader < 0)
|
||||
{
|
||||
currentShader = (int)PostproShader.Max - 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Enable drawing to texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(model, position, 0.1f, Color.White);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// End drawing to texture (now we have a texture available for next passes)
|
||||
EndTextureMode();
|
||||
|
||||
// Render previously generated texture using selected postpro shader
|
||||
BeginShaderMode(shaders[currentShader]);
|
||||
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0, 0),
|
||||
Color.White
|
||||
);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
DrawRectangle(0, 9, 580, 30, ColorAlpha(Color.LightGray, 0.7f));
|
||||
|
||||
DrawText("(c) Church 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, Color.Gray);
|
||||
|
||||
DrawText("CURRENT POSTPRO SHADER:", 10, 15, 20, Color.Black);
|
||||
DrawText(postproShaderText[currentShader], 330, 15, 20, Color.Red);
|
||||
DrawText("< >", 540, 10, 30, Color.DarkBlue);
|
||||
|
||||
DrawFPS(700, 15);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
currentShader++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
currentShader--;
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
for (int i = 0; i < (int)PostproShader.Max; i++)
|
||||
if (currentShader >= (int)PostproShader.Max)
|
||||
{
|
||||
currentShader = 0;
|
||||
}
|
||||
else if (currentShader < 0)
|
||||
{
|
||||
currentShader = (int)PostproShader.Max - 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Enable drawing to texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(model, position, 0.1f, Color.White);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// End drawing to texture (now we have a texture available for next passes)
|
||||
EndTextureMode();
|
||||
|
||||
// Render generated texture using selected postprocessing shader
|
||||
BeginShaderMode(shaders[currentShader]);
|
||||
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Vector2(0, 0),
|
||||
Color.White
|
||||
);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
DrawRectangle(0, 9, 580, 30, Fade(Color.LightGray, 0.7f));
|
||||
|
||||
DrawText("(c) Church 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, Color.Gray);
|
||||
|
||||
DrawText("CURRENT POSTPRO SHADER:", 10, 15, 20, Color.Black);
|
||||
DrawText(postproShaderText[currentShader], 330, 15, 20, Color.Red);
|
||||
DrawText("< >", 540, 10, 30, Color.DarkBlue);
|
||||
|
||||
DrawFPS(700, 15);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// Unload all postpro shaders
|
||||
for (var i = 0; i < (int)PostproShader.Max; i++)
|
||||
{
|
||||
UnloadShader(shaders[i]);
|
||||
}
|
||||
|
||||
UnloadTexture(texture);
|
||||
UnloadModel(model);
|
||||
UnloadRenderTexture(target);
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadModel(model); // Unload model
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
}
|
||||
|
||||
CloseWindow();
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new PostProcessing();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Raymarching shapes generation
|
||||
* raylib [shaders] example - raymarching rendering
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
* NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330
|
||||
* is currently supported. OpenGL ES 2.0 platforms are not supported at the moment
|
||||
*
|
||||
* 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)
|
||||
* Example originally created with raylib 2.0, last time updated with raylib 4.2
|
||||
*
|
||||
* Copyright (c) 2018 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) 2018-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -22,98 +22,138 @@ using static Raylib_cs.ConfigFlags;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class Raymarching
|
||||
public class Raymarching : IExample
|
||||
{
|
||||
#if BROWSER
|
||||
public const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
public const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Raymarching";
|
||||
|
||||
public string Title => "raylib [shaders] example - raymarching rendering";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.ResizableWindow;
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private int screenWidth;
|
||||
private int screenHeight;
|
||||
|
||||
private Camera3D camera;
|
||||
private Shader shader;
|
||||
private int viewEyeLoc;
|
||||
private int viewCenterLoc;
|
||||
private int runTimeLoc;
|
||||
private int resolutionLoc;
|
||||
private float runTime;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
screenWidth = GetScreenWidth();
|
||||
screenHeight = GetScreenHeight();
|
||||
|
||||
camera = new();
|
||||
camera.Position = new Vector3(2.5f, 2.5f, 3.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.7f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 65.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Load raymarching shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/raymarching.fs");
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
viewEyeLoc = GetShaderLocation(shader, "viewEye");
|
||||
viewCenterLoc = GetShaderLocation(shader, "viewCenter");
|
||||
runTimeLoc = GetShaderLocation(shader, "runTime");
|
||||
resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
|
||||
float[] resolution = { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
|
||||
runTime = 0.0f;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.FirstPerson);
|
||||
|
||||
var deltaTime = GetFrameTime();
|
||||
runTime += deltaTime;
|
||||
|
||||
// Set shader required uniform values
|
||||
Raylib.SetShaderValue(shader, viewEyeLoc, camera.Position, ShaderUniformDataType.Vec3);
|
||||
Raylib.SetShaderValue(shader, viewCenterLoc, camera.Target, ShaderUniformDataType.Vec3);
|
||||
Raylib.SetShaderValue(shader, runTimeLoc, runTime, ShaderUniformDataType.Float);
|
||||
|
||||
// Check if screen is resized
|
||||
if (IsWindowResized())
|
||||
{
|
||||
screenWidth = GetScreenWidth();
|
||||
screenHeight = GetScreenHeight();
|
||||
var resolution = new float[] { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// We only draw a white full-screen rectangle,
|
||||
// frame is generated in shader using raymarching
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawText(
|
||||
"(c) Raymarching shader by Iñigo Quilez. MIT License.",
|
||||
screenWidth - 280,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
Color.Black
|
||||
);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
int screenWidth = 800;
|
||||
int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(ResizableWindow);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - raymarching shapes");
|
||||
InitWindow(800, 450, "raylib [shaders] example - raymarching rendering");
|
||||
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(2.5f, 2.5f, 3.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.7f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 65.0f;
|
||||
|
||||
// Load raymarching shader
|
||||
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/raymarching.fs");
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
int viewEyeLoc = GetShaderLocation(shader, "viewEye");
|
||||
int viewCenterLoc = GetShaderLocation(shader, "viewCenter");
|
||||
int runTimeLoc = GetShaderLocation(shader, "runTime");
|
||||
int resolutionLoc = GetShaderLocation(shader, "resolution");
|
||||
|
||||
float[] resolution = { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
|
||||
float runTime = 0.0f;
|
||||
|
||||
SetTargetFPS(60);
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Raymarching();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Check if screen is resized
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsWindowResized())
|
||||
{
|
||||
screenWidth = GetScreenWidth();
|
||||
screenHeight = GetScreenHeight();
|
||||
resolution = new float[] { (float)screenWidth, (float)screenHeight };
|
||||
Raylib.SetShaderValue(shader, resolutionLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
}
|
||||
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
float deltaTime = GetFrameTime();
|
||||
runTime += deltaTime;
|
||||
|
||||
// Set shader required uniform values
|
||||
Raylib.SetShaderValue(shader, viewEyeLoc, camera.Position, ShaderUniformDataType.Vec3);
|
||||
Raylib.SetShaderValue(shader, viewCenterLoc, camera.Target, ShaderUniformDataType.Vec3);
|
||||
Raylib.SetShaderValue(shader, runTimeLoc, runTime, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// We only draw a white full-screen rectangle,
|
||||
// frame is generated in shader using raymarching
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawText(
|
||||
"(c) Raymarching shader by Iñigo Quilez. MIT License.",
|
||||
screenWidth - 280,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
Color.Black
|
||||
);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
242
Examples/Shaders/RlglCompute.cs
Normal file
242
Examples/Shaders/RlglCompute.cs
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - rlgl compute
|
||||
*
|
||||
* WARNING: This example requires raylib compiled with OpenGL 4.3 version for
|
||||
* compute shaders support, shaders used in this example are #version 430
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Teddy Astie (@tsnake41) 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) 2021-2025 Teddy Astie (@tsnake41)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
[ExcludeFromBrowser("compute shaders are not available on WebGL")]
|
||||
public partial class RlglCompute : IExample
|
||||
{
|
||||
// IMPORTANT: This must match gol*.glsl GOL_WIDTH constant
|
||||
// This must be a multiple of 16 (check golLogic compute dispatch)
|
||||
private const int GolWidth = 768;
|
||||
|
||||
// Maximum amount of queued draw commands (squares draw from mouse down events)
|
||||
private const int MaxBufferedTransferts = 48;
|
||||
|
||||
private const int screenWidth = GolWidth;
|
||||
private const int screenHeight = GolWidth;
|
||||
|
||||
public string Name => "Shaders / Rlgl Compute";
|
||||
|
||||
public string Title => "raylib [shaders] example - rlgl compute";
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Game Of Life Update Command
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct GolUpdateCmd
|
||||
{
|
||||
public uint X; // x coordinate of the gol command
|
||||
public uint Y; // y coordinate of the gol command
|
||||
public uint W; // width of the filled zone
|
||||
public uint Enabled; // whether to enable or disable zone
|
||||
}
|
||||
|
||||
// Inline fixed-size array of GolUpdateCmd (MAX_BUFFERED_TRANSFERTS entries)
|
||||
[InlineArray(MaxBufferedTransferts)]
|
||||
private struct GolUpdateCmdBuffer
|
||||
{
|
||||
private GolUpdateCmd _element0;
|
||||
}
|
||||
|
||||
// Game Of Life Update Commands SSBO
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct GolUpdateSSBO
|
||||
{
|
||||
public uint Count;
|
||||
public GolUpdateCmdBuffer Commands;
|
||||
}
|
||||
|
||||
private Vector2 resolution;
|
||||
private uint brushSize;
|
||||
private uint golLogicShader;
|
||||
private uint golLogicProgram;
|
||||
private uint golTransfertShader;
|
||||
private uint golTransfertProgram;
|
||||
private Shader golRenderShader;
|
||||
private int resUniformLoc;
|
||||
private uint ssboA;
|
||||
private uint ssboB;
|
||||
private uint ssboTransfert;
|
||||
private GolUpdateSSBO transfertBuffer;
|
||||
private Texture2D whiteTex;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
resolution = new Vector2(screenWidth, screenHeight);
|
||||
brushSize = 8;
|
||||
|
||||
// Game of Life logic compute shader
|
||||
var golLogicCode = LoadFileText("resources/shaders/glsl430/gol.glsl");
|
||||
var golLogicBytes = Encoding.UTF8.GetBytes(golLogicCode + "\0");
|
||||
fixed (byte* p = golLogicBytes)
|
||||
{
|
||||
golLogicShader = Rlgl.LoadShader((sbyte*)p, (int)ShaderType.Compute);
|
||||
}
|
||||
golLogicProgram = Rlgl.LoadShaderProgramCompute(golLogicShader);
|
||||
|
||||
// Game of Life logic render shader
|
||||
golRenderShader = LoadShader(null, "resources/shaders/glsl430/gol_render.glsl");
|
||||
resUniformLoc = GetShaderLocation(golRenderShader, "resolution");
|
||||
|
||||
// Game of Life transfert shader (CPU<->GPU download and upload)
|
||||
var golTransfertCode = LoadFileText("resources/shaders/glsl430/gol_transfert.glsl");
|
||||
var golTransfertBytes = Encoding.UTF8.GetBytes(golTransfertCode + "\0");
|
||||
fixed (byte* p = golTransfertBytes)
|
||||
{
|
||||
golTransfertShader = Rlgl.LoadShader((sbyte*)p, (int)ShaderType.Compute);
|
||||
}
|
||||
golTransfertProgram = Rlgl.LoadShaderProgramCompute(golTransfertShader);
|
||||
|
||||
// Load shader storage buffer object (SSBO), id returned
|
||||
ssboA = Rlgl.LoadShaderBuffer((uint)(GolWidth * GolWidth * sizeof(uint)), null, Rlgl.DYNAMIC_COPY);
|
||||
ssboB = Rlgl.LoadShaderBuffer((uint)(GolWidth * GolWidth * sizeof(uint)), null, Rlgl.DYNAMIC_COPY);
|
||||
ssboTransfert = Rlgl.LoadShaderBuffer((uint)sizeof(GolUpdateSSBO), null, Rlgl.DYNAMIC_COPY);
|
||||
|
||||
transfertBuffer = new();
|
||||
|
||||
// Create a white texture of the size of the window to update
|
||||
// each pixel of the window using the fragment shader: golRenderShader
|
||||
var whiteImage = GenImageColor(GolWidth, GolWidth, Color.White);
|
||||
whiteTex = LoadTextureFromImage(whiteImage);
|
||||
UnloadImage(whiteImage);
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
brushSize += (uint)(int)GetMouseWheelMove();
|
||||
|
||||
if ((IsMouseButtonDown(MouseButton.Left) || IsMouseButtonDown(MouseButton.Right))
|
||||
&& (transfertBuffer.Count < MaxBufferedTransferts))
|
||||
{
|
||||
// Buffer a new command
|
||||
transfertBuffer.Commands[(int)transfertBuffer.Count].X = (uint)GetMouseX() - brushSize / 2;
|
||||
transfertBuffer.Commands[(int)transfertBuffer.Count].Y = (uint)GetMouseY() - brushSize / 2;
|
||||
transfertBuffer.Commands[(int)transfertBuffer.Count].W = brushSize;
|
||||
transfertBuffer.Commands[(int)transfertBuffer.Count].Enabled = IsMouseButtonDown(MouseButton.Left) ? 1u : 0u;
|
||||
transfertBuffer.Count++;
|
||||
}
|
||||
else if (transfertBuffer.Count > 0) // Process transfert buffer
|
||||
{
|
||||
// Send SSBO buffer to GPU
|
||||
fixed (GolUpdateSSBO* ptr = &transfertBuffer)
|
||||
{
|
||||
Rlgl.UpdateShaderBuffer(ssboTransfert, ptr, (uint)sizeof(GolUpdateSSBO), 0);
|
||||
}
|
||||
|
||||
// Process SSBO commands on GPU
|
||||
Rlgl.EnableShader(golTransfertProgram);
|
||||
Rlgl.BindShaderBuffer(ssboA, 1);
|
||||
Rlgl.BindShaderBuffer(ssboTransfert, 3);
|
||||
Rlgl.ComputeShaderDispatch(transfertBuffer.Count, 1, 1); // Each GPU unit will process a command!
|
||||
Rlgl.DisableShader();
|
||||
|
||||
transfertBuffer.Count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Process game of life logic
|
||||
Rlgl.EnableShader(golLogicProgram);
|
||||
Rlgl.BindShaderBuffer(ssboA, 1);
|
||||
Rlgl.BindShaderBuffer(ssboB, 2);
|
||||
Rlgl.ComputeShaderDispatch(GolWidth / 16, GolWidth / 16, 1);
|
||||
Rlgl.DisableShader();
|
||||
|
||||
// ssboA <-> ssboB
|
||||
var temp = ssboA;
|
||||
ssboA = ssboB;
|
||||
ssboB = temp;
|
||||
}
|
||||
|
||||
Rlgl.BindShaderBuffer(ssboA, 1);
|
||||
Raylib.SetShaderValue(golRenderShader, resUniformLoc, resolution, ShaderUniformDataType.Vec2);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.Blank);
|
||||
|
||||
BeginShaderMode(golRenderShader);
|
||||
DrawTexture(whiteTex, 0, 0, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawRectangleLines(GetMouseX() - (int)(brushSize / 2), GetMouseY() - (int)(brushSize / 2), (int)brushSize, (int)brushSize, Color.Red);
|
||||
|
||||
DrawText("Use Mouse wheel to increase/decrease brush size", 10, 10, 20, Color.White);
|
||||
DrawFPS(GetScreenWidth() - 100, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// Unload shader buffers objects
|
||||
Rlgl.UnloadShaderBuffer(ssboA);
|
||||
Rlgl.UnloadShaderBuffer(ssboB);
|
||||
Rlgl.UnloadShaderBuffer(ssboTransfert);
|
||||
|
||||
// Unload compute shader
|
||||
Rlgl.UnloadShader(golLogicShader);
|
||||
Rlgl.UnloadShader(golTransfertShader);
|
||||
Rlgl.UnloadShaderProgram(golTransfertProgram);
|
||||
Rlgl.UnloadShaderProgram(golLogicProgram);
|
||||
|
||||
UnloadTexture(whiteTex); // Unload white texture
|
||||
UnloadShader(golRenderShader); // Unload rendering fragment shader
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - rlgl compute");
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new RlglCompute();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
243
Examples/Shaders/RoundedRectangle.cs
Normal file
243
Examples/Shaders/RoundedRectangle.cs
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - rounded rectangle
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Anstro Pleuton (@anstropleuton) 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) 2025 Anstro Pleuton (@anstropleuton)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class RoundedRectangle : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Rounded Rectangle";
|
||||
|
||||
public string Title => "raylib [shaders] example - rounded rectangle";
|
||||
|
||||
// Rounded rectangle data
|
||||
private struct RoundedRect
|
||||
{
|
||||
public Vector4 CornerRadius; // Individual corner radius (top-left, top-right, bottom-left, bottom-right)
|
||||
|
||||
// Shadow variables
|
||||
public float ShadowRadius;
|
||||
public Vector2 ShadowOffset;
|
||||
public float ShadowScale;
|
||||
|
||||
// Border variables
|
||||
public float BorderThickness; // Inner-border thickness
|
||||
|
||||
// Shader locations
|
||||
public int RectangleLoc;
|
||||
public int RadiusLoc;
|
||||
public int ColorLoc;
|
||||
public int ShadowRadiusLoc;
|
||||
public int ShadowOffsetLoc;
|
||||
public int ShadowScaleLoc;
|
||||
public int ShadowColorLoc;
|
||||
public int BorderThicknessLoc;
|
||||
public int BorderColorLoc;
|
||||
}
|
||||
|
||||
private Shader shader;
|
||||
private RoundedRect roundedRectangle;
|
||||
|
||||
private readonly Color rectangleColor = Color.Blue;
|
||||
private readonly Color shadowColor = Color.DarkBlue;
|
||||
private readonly Color borderColor = Color.SkyBlue;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Load the shader
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/base.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/rounded_rectangle.fs"
|
||||
);
|
||||
|
||||
// Create a rounded rectangle
|
||||
roundedRectangle = CreateRoundedRectangle(
|
||||
new Vector4(5.0f, 10.0f, 15.0f, 20.0f), // Corner radius
|
||||
20.0f, // Shadow radius
|
||||
new Vector2(0.0f, -5.0f), // Shadow offset
|
||||
0.95f, // Shadow scale
|
||||
5.0f, // Border thickness
|
||||
shader // Shader
|
||||
);
|
||||
|
||||
// Update shader uniforms
|
||||
UpdateRoundedRectangle(roundedRectangle, shader);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw rectangle box with rounded corners using shader
|
||||
Rectangle rec = new(50, 70, 110, 60);
|
||||
DrawRectangleLines((int)rec.X - 20, (int)rec.Y - 20, (int)rec.Width + 40, (int)rec.Height + 40, Color.DarkGray);
|
||||
DrawText("Rounded rectangle", (int)rec.X - 20, (int)rec.Y - 35, 10, Color.DarkGray);
|
||||
|
||||
// Flip Y axis to match shader coordinate system
|
||||
rec.Y = screenHeight - rec.Y - rec.Height;
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.RectangleLoc, new[] { rec.X, rec.Y, rec.Width, rec.Height }, ShaderUniformDataType.Vec4);
|
||||
|
||||
// Only rectangle color
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ColorLoc, new[] { rectangleColor.R / 255.0f, rectangleColor.G / 255.0f, rectangleColor.B / 255.0f, rectangleColor.A / 255.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ShadowColorLoc, new[] { 0.0f, 0.0f, 0.0f, 0.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.BorderColorLoc, new[] { 0.0f, 0.0f, 0.0f, 0.0f }, ShaderUniformDataType.Vec4);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
// Draw rectangle shadow using shader
|
||||
rec = new Rectangle(50, 200, 110, 60);
|
||||
DrawRectangleLines((int)rec.X - 20, (int)rec.Y - 20, (int)rec.Width + 40, (int)rec.Height + 40, Color.DarkGray);
|
||||
DrawText("Rounded rectangle shadow", (int)rec.X - 20, (int)rec.Y - 35, 10, Color.DarkGray);
|
||||
|
||||
rec.Y = screenHeight - rec.Y - rec.Height;
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.RectangleLoc, new[] { rec.X, rec.Y, rec.Width, rec.Height }, ShaderUniformDataType.Vec4);
|
||||
|
||||
// Only shadow color
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ColorLoc, new[] { 0.0f, 0.0f, 0.0f, 0.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ShadowColorLoc, new[] { shadowColor.R / 255.0f, shadowColor.G / 255.0f, shadowColor.B / 255.0f, shadowColor.A / 255.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.BorderColorLoc, new[] { 0.0f, 0.0f, 0.0f, 0.0f }, ShaderUniformDataType.Vec4);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
// Draw rectangle's border using shader
|
||||
rec = new Rectangle(50, 330, 110, 60);
|
||||
DrawRectangleLines((int)rec.X - 20, (int)rec.Y - 20, (int)rec.Width + 40, (int)rec.Height + 40, Color.DarkGray);
|
||||
DrawText("Rounded rectangle border", (int)rec.X - 20, (int)rec.Y - 35, 10, Color.DarkGray);
|
||||
|
||||
rec.Y = screenHeight - rec.Y - rec.Height;
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.RectangleLoc, new[] { rec.X, rec.Y, rec.Width, rec.Height }, ShaderUniformDataType.Vec4);
|
||||
|
||||
// Only border color
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ColorLoc, new[] { 0.0f, 0.0f, 0.0f, 0.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ShadowColorLoc, new[] { 0.0f, 0.0f, 0.0f, 0.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.BorderColorLoc, new[] { borderColor.R / 255.0f, borderColor.G / 255.0f, borderColor.B / 255.0f, borderColor.A / 255.0f }, ShaderUniformDataType.Vec4);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
// Draw one more rectangle with all three colors
|
||||
rec = new Rectangle(240, 80, 500, 300);
|
||||
DrawRectangleLines((int)rec.X - 30, (int)rec.Y - 30, (int)rec.Width + 60, (int)rec.Height + 60, Color.DarkGray);
|
||||
DrawText("Rectangle with all three combined", (int)rec.X - 30, (int)rec.Y - 45, 10, Color.DarkGray);
|
||||
|
||||
rec.Y = screenHeight - rec.Y - rec.Height;
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.RectangleLoc, new[] { rec.X, rec.Y, rec.Width, rec.Height }, ShaderUniformDataType.Vec4);
|
||||
|
||||
// All three colors
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ColorLoc, new[] { rectangleColor.R / 255.0f, rectangleColor.G / 255.0f, rectangleColor.B / 255.0f, rectangleColor.A / 255.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.ShadowColorLoc, new[] { shadowColor.R / 255.0f, shadowColor.G / 255.0f, shadowColor.B / 255.0f, shadowColor.A / 255.0f }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, roundedRectangle.BorderColorLoc, new[] { borderColor.R / 255.0f, borderColor.G / 255.0f, borderColor.B / 255.0f, borderColor.A / 255.0f }, ShaderUniformDataType.Vec4);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("(c) Rounded rectangle SDF by Iñigo Quilez. MIT License.", screenWidth - 300, screenHeight - 20, 10, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
}
|
||||
|
||||
// Create a rounded rectangle and set uniform locations
|
||||
private static RoundedRect CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader)
|
||||
{
|
||||
RoundedRect rec;
|
||||
rec.CornerRadius = cornerRadius;
|
||||
rec.ShadowRadius = shadowRadius;
|
||||
rec.ShadowOffset = shadowOffset;
|
||||
rec.ShadowScale = shadowScale;
|
||||
rec.BorderThickness = borderThickness;
|
||||
|
||||
// Get shader uniform locations
|
||||
rec.RectangleLoc = GetShaderLocation(shader, "rectangle");
|
||||
rec.RadiusLoc = GetShaderLocation(shader, "radius");
|
||||
rec.ColorLoc = GetShaderLocation(shader, "color");
|
||||
rec.ShadowRadiusLoc = GetShaderLocation(shader, "shadowRadius");
|
||||
rec.ShadowOffsetLoc = GetShaderLocation(shader, "shadowOffset");
|
||||
rec.ShadowScaleLoc = GetShaderLocation(shader, "shadowScale");
|
||||
rec.ShadowColorLoc = GetShaderLocation(shader, "shadowColor");
|
||||
rec.BorderThicknessLoc = GetShaderLocation(shader, "borderThickness");
|
||||
rec.BorderColorLoc = GetShaderLocation(shader, "borderColor");
|
||||
|
||||
UpdateRoundedRectangle(rec, shader);
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
// Update rounded rectangle uniforms
|
||||
private static void UpdateRoundedRectangle(RoundedRect rec, Shader shader)
|
||||
{
|
||||
Raylib.SetShaderValue(shader, rec.RadiusLoc, new[] { rec.CornerRadius.X, rec.CornerRadius.Y, rec.CornerRadius.Z, rec.CornerRadius.W }, ShaderUniformDataType.Vec4);
|
||||
Raylib.SetShaderValue(shader, rec.ShadowRadiusLoc, rec.ShadowRadius, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, rec.ShadowOffsetLoc, new[] { rec.ShadowOffset.X, rec.ShadowOffset.Y }, ShaderUniformDataType.Vec2);
|
||||
Raylib.SetShaderValue(shader, rec.ShadowScaleLoc, rec.ShadowScale, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, rec.BorderThicknessLoc, rec.BorderThickness, ShaderUniformDataType.Float);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - rounded rectangle");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new RoundedRectangle();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
316
Examples/Shaders/ShadowmapRendering.cs
Normal file
316
Examples/Shaders/ShadowmapRendering.cs
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - shadowmap rendering
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example contributed by TheManTheMythTheGameDev (@TheManTheMythTheGameDev) 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-2025 TheManTheMythTheGameDev (@TheManTheMythTheGameDev)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Raymath;
|
||||
using static Raylib_cs.Rlgl;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class ShadowmapRendering : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
private const int ShadowmapResolution = 1024;
|
||||
|
||||
public string Name => "Shaders / Shadowmap Rendering";
|
||||
|
||||
public string Title => "raylib [shaders] example - shadowmap rendering";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
private Camera3D camera;
|
||||
private Shader shadowShader;
|
||||
private Vector3 lightDir;
|
||||
private int lightDirLoc;
|
||||
private int lightVPLoc;
|
||||
private int shadowMapLoc;
|
||||
private Model cube;
|
||||
private Model robot;
|
||||
private unsafe ModelAnimation* anims;
|
||||
private int animCount;
|
||||
private RenderTexture2D shadowMap;
|
||||
private Camera3D lightCamera;
|
||||
private int frameCounter;
|
||||
private int textureActiveSlot;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Shadows are a HUGE topic, and this example shows an extremely simple implementation of the shadowmapping algorithm,
|
||||
// which is the industry standard for shadows. This algorithm can be extended in a ridiculous number of ways to improve
|
||||
// realism and also adapt it for different scenes. This is pretty much the simplest possible implementation
|
||||
|
||||
camera = new();
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f);
|
||||
camera.Target = Vector3.Zero;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
|
||||
shadowShader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/shadowmap.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/shadowmap.fs"
|
||||
);
|
||||
shadowShader.Locs[(int)ShaderLocationIndex.VectorView] = GetShaderLocation(shadowShader, "viewPos");
|
||||
|
||||
lightDir = Vector3Normalize(new Vector3(0.35f, -1.0f, -0.35f));
|
||||
var lightColor = Color.White;
|
||||
var lightColorNormalized = ColorNormalize(lightColor);
|
||||
lightDirLoc = GetShaderLocation(shadowShader, "lightDir");
|
||||
var lightColLoc = GetShaderLocation(shadowShader, "lightColor");
|
||||
Raylib.SetShaderValue(shadowShader, lightDirLoc, lightDir, ShaderUniformDataType.Vec3);
|
||||
Raylib.SetShaderValue(shadowShader, lightColLoc, lightColorNormalized, ShaderUniformDataType.Vec4);
|
||||
var ambientLoc = GetShaderLocation(shadowShader, "ambient");
|
||||
var ambient = new[] { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
Raylib.SetShaderValue(shadowShader, ambientLoc, ambient, ShaderUniformDataType.Vec4);
|
||||
lightVPLoc = GetShaderLocation(shadowShader, "lightVP");
|
||||
shadowMapLoc = GetShaderLocation(shadowShader, "shadowMap");
|
||||
var shadowMapResolution = ShadowmapResolution;
|
||||
Raylib.SetShaderValue(shadowShader, GetShaderLocation(shadowShader, "shadowMapResolution"), shadowMapResolution, ShaderUniformDataType.Int);
|
||||
|
||||
cube = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
|
||||
cube.Materials[0].Shader = shadowShader;
|
||||
robot = LoadModel("resources/models/robot.glb");
|
||||
for (var i = 0; i < robot.MaterialCount; i++)
|
||||
{
|
||||
robot.Materials[i].Shader = shadowShader;
|
||||
}
|
||||
|
||||
animCount = 0;
|
||||
anims = LoadModelAnimations("resources/models/robot.glb", ref animCount);
|
||||
|
||||
shadowMap = LoadShadowmapRenderTexture(ShadowmapResolution, ShadowmapResolution);
|
||||
|
||||
// For the shadowmapping algorithm, we will be rendering everything from the light's point of view
|
||||
lightCamera = new();
|
||||
lightCamera.Position = Vector3Scale(lightDir, -15.0f);
|
||||
lightCamera.Target = Vector3.Zero;
|
||||
lightCamera.Projection = CameraProjection.Orthographic; // Use an orthographic projection for directional lights
|
||||
lightCamera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
lightCamera.FovY = 20.0f;
|
||||
|
||||
frameCounter = 0;
|
||||
textureActiveSlot = 10; // Can be anything 0 to 15, but 0 will probably be taken up
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
var deltaTime = GetFrameTime();
|
||||
|
||||
var cameraPos = camera.Position;
|
||||
Raylib.SetShaderValue(shadowShader, shadowShader.Locs[(int)ShaderLocationIndex.VectorView], cameraPos, ShaderUniformDataType.Vec3);
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
|
||||
frameCounter++;
|
||||
frameCounter %= anims[0].KeyFrameCount;
|
||||
UpdateModelAnimation(robot, anims[0], (float)frameCounter);
|
||||
|
||||
// Move light with arrow keys
|
||||
const float cameraSpeed = 0.05f;
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
if (lightDir.X < 0.6f)
|
||||
{
|
||||
lightDir.X += cameraSpeed * 60.0f * deltaTime;
|
||||
}
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
if (lightDir.X > -0.6f)
|
||||
{
|
||||
lightDir.X -= cameraSpeed * 60.0f * deltaTime;
|
||||
}
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
if (lightDir.Z < 0.6f)
|
||||
{
|
||||
lightDir.Z += cameraSpeed * 60.0f * deltaTime;
|
||||
}
|
||||
}
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
if (lightDir.Z > -0.6f)
|
||||
{
|
||||
lightDir.Z -= cameraSpeed * 60.0f * deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
lightDir = Vector3Normalize(lightDir);
|
||||
lightCamera.Position = Vector3Scale(lightDir, -15.0f);
|
||||
Raylib.SetShaderValue(shadowShader, lightDirLoc, lightDir, ShaderUniformDataType.Vec3);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// PASS 01: Render all objects into the shadowmap render texture
|
||||
// We record all the objects' depths (as rendered from the light source's point of view) in a buffer
|
||||
// Anything that is "visible" to the light is in light, anything that isn't is in shadow
|
||||
// We can later use the depth buffer when rendering everything from the player's point of view
|
||||
// to determine whether a given point is "visible" to the light
|
||||
Matrix4x4 lightView;
|
||||
Matrix4x4 lightProj;
|
||||
BeginTextureMode(shadowMap);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
BeginMode3D(lightCamera);
|
||||
lightView = GetMatrixModelview();
|
||||
lightProj = GetMatrixProjection();
|
||||
DrawScene(cube, robot);
|
||||
EndMode3D();
|
||||
|
||||
EndTextureMode();
|
||||
var lightViewProj = MatrixMultiply(lightView, lightProj);
|
||||
|
||||
// PASS 02: Draw the scene into main framebuffer, using the generated shadowmap
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
SetShaderValueMatrix(shadowShader, lightVPLoc, lightViewProj);
|
||||
EnableShader(shadowShader.Id);
|
||||
|
||||
ActiveTextureSlot(textureActiveSlot);
|
||||
EnableTexture(shadowMap.Depth.Id);
|
||||
var slot = textureActiveSlot;
|
||||
SetUniform(shadowMapLoc, &slot, (int)ShaderUniformDataType.Int, 1);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawScene(cube, robot); // Draw the same exact things as we drew in the shadowmap!
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Use the arrow keys to rotate the light!", 10, 10, 30, Color.Red);
|
||||
DrawText("Shadows in raylib using the shadowmapping algorithm!", screenWidth - 280, screenHeight - 20, 10, Color.Gray);
|
||||
|
||||
EndDrawing();
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.F))
|
||||
{
|
||||
TakeScreenshot("shaders_shadowmap.png");
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public unsafe void Unload()
|
||||
{
|
||||
UnloadShader(shadowShader);
|
||||
UnloadModel(cube);
|
||||
UnloadModel(robot);
|
||||
UnloadModelAnimations(anims, animCount);
|
||||
UnloadShadowmapRenderTexture(shadowMap);
|
||||
}
|
||||
|
||||
// Load render texture for shadowmap projection
|
||||
// NOTE: Load framebuffer with only a texture depth attachment,
|
||||
// no color attachment required for shadowmap
|
||||
private static unsafe RenderTexture2D LoadShadowmapRenderTexture(int width, int height)
|
||||
{
|
||||
RenderTexture2D target = new();
|
||||
|
||||
target.Id = LoadFramebuffer(); // Load an empty framebuffer
|
||||
target.Texture.Width = width;
|
||||
target.Texture.Height = height;
|
||||
|
||||
if (target.Id > 0)
|
||||
{
|
||||
EnableFramebuffer(target.Id);
|
||||
|
||||
// Create depth texture
|
||||
// NOTE: No need a color texture attachment for the shadowmap
|
||||
target.Depth.Id = LoadTextureDepth(width, height, false);
|
||||
target.Depth.Width = width;
|
||||
target.Depth.Height = height;
|
||||
target.Depth.Format = (PixelFormat)19; // DEPTH_COMPONENT_24BIT?
|
||||
target.Depth.Mipmaps = 1;
|
||||
|
||||
// Attach depth texture to FBO
|
||||
FramebufferAttach(target.Id, target.Depth.Id, FramebufferAttachType.Depth, FramebufferAttachTextureType.Texture2D, 0);
|
||||
|
||||
// Check if fbo is complete with attachments (valid)
|
||||
if (FramebufferComplete(target.Id) != 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Info, $"FBO: [ID {target.Id}] Framebuffer object created successfully");
|
||||
}
|
||||
|
||||
DisableFramebuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLog(TraceLogLevel.Warning, "FBO: Framebuffer object can not be created");
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
// Unload shadowmap render texture from GPU memory (VRAM)
|
||||
private static void UnloadShadowmapRenderTexture(RenderTexture2D target)
|
||||
{
|
||||
if (target.Id > 0)
|
||||
{
|
||||
// NOTE: Depth texture/renderbuffer is automatically
|
||||
// queried and deleted before deleting framebuffer
|
||||
UnloadFramebuffer(target.Id);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw full scene projecting shadows
|
||||
// NOTE: Required to be called several time to generate shadowmap
|
||||
private static void DrawScene(Model cube, Model robot)
|
||||
{
|
||||
DrawModelEx(cube, Vector3.Zero, new Vector3(0.0f, 1.0f, 0.0f), 0.0f, new Vector3(10.0f, 1.0f, 10.0f), Color.Blue);
|
||||
DrawModelEx(cube, new Vector3(1.5f, 1.0f, -1.5f), new Vector3(0.0f, 1.0f, 0.0f), 0.0f, Vector3.One, Color.White);
|
||||
DrawModelEx(robot, new Vector3(0.0f, 0.5f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f), 0.0f, new Vector3(1.0f, 1.0f, 1.0f), Color.Red);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shadowmap rendering");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ShadowmapRendering();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,22 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Apply a shader to some shape or texture
|
||||
* raylib [shaders] example - shapes textures
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 1.7 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.7, last time updated with raylib 3.7
|
||||
*
|
||||
* Copyright (c) 2015 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -21,101 +25,123 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class ShapesTextures
|
||||
public class ShapesTextures : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Shapes Textures";
|
||||
|
||||
public string Title => "raylib [shaders] example - shapes textures";
|
||||
|
||||
private Texture2D fudesumi;
|
||||
private Shader shader;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
fudesumi = LoadTexture("resources/fudesumi.png");
|
||||
|
||||
// Load shader to be used on some parts drawing
|
||||
// NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
|
||||
// NOTE 2: Defining null (NULL) for vertex shader forces usage of internal default vertex shader
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/grayscale.fs");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Start drawing with default shader
|
||||
DrawText("USING DEFAULT SHADER", 20, 40, 10, Color.Red);
|
||||
|
||||
DrawCircle(80, 120, 35, Color.DarkBlue);
|
||||
DrawCircleGradient(new Vector2(80, 220), 60, Color.Green, Color.SkyBlue);
|
||||
DrawCircleLines(80, 340, 80, Color.DarkBlue);
|
||||
|
||||
|
||||
// Activate our custom shader to be applied on next shapes/textures drawings
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawText("USING CUSTOM SHADER", 190, 40, 10, Color.Red);
|
||||
|
||||
DrawRectangle(250 - 60, 90, 120, 60, Color.Red);
|
||||
DrawRectangleGradientH(250 - 90, 170, 180, 130, Color.Maroon, Color.Gold);
|
||||
DrawRectangleLines(250 - 40, 320, 80, 60, Color.Orange);
|
||||
|
||||
// Activate our default shader for next drawings
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("USING DEFAULT SHADER", 370, 40, 10, Color.Red);
|
||||
|
||||
DrawTriangle(
|
||||
new Vector2(430, 80),
|
||||
new Vector2(430 - 60, 150),
|
||||
new Vector2(430 + 60, 150), Color.Violet
|
||||
);
|
||||
|
||||
DrawTriangleLines(
|
||||
new Vector2(430, 160),
|
||||
new Vector2(430 - 20, 230),
|
||||
new Vector2(430 + 20, 230), Color.DarkBlue
|
||||
);
|
||||
|
||||
DrawPoly(new Vector2(430, 320), 6, 80, 0, Color.Brown);
|
||||
|
||||
// Activate our custom shader to be applied on next shapes/textures drawings
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// Using custom shader
|
||||
DrawTexture(fudesumi, 500, -30, Color.White);
|
||||
|
||||
// Activate our default shader for next drawings
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("(c) Fudesumi sprite by Eiden Marsal", 380, screenHeight - 20, 10, Color.Gray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(fudesumi); // Unload texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shapes textures");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shapes and texture shaders");
|
||||
|
||||
Texture2D fudesumi = LoadTexture("resources/fudesumi.png");
|
||||
|
||||
// NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
|
||||
Shader shader = LoadShader(
|
||||
"resources/shaders/glsl330/base.vs",
|
||||
"resources/shaders/glsl330/grayscale.fs"
|
||||
);
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ShapesTextures();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Start drawing with default shader
|
||||
DrawText("USING DEFAULT SHADER", 20, 40, 10, Color.Red);
|
||||
|
||||
DrawCircle(80, 120, 35, Color.DarkBlue);
|
||||
DrawCircleGradient(new Vector2(80, 220), 60, Color.Green, Color.SkyBlue);
|
||||
DrawCircleLines(80, 340, 80, Color.DarkBlue);
|
||||
|
||||
|
||||
// Activate our custom shader to be applied on next shapes/textures drawings
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawText("USING CUSTOM SHADER", 190, 40, 10, Color.Red);
|
||||
|
||||
DrawRectangle(250 - 60, 90, 120, 60, Color.Red);
|
||||
DrawRectangleGradientH(250 - 90, 170, 180, 130, Color.Maroon, Color.Gold);
|
||||
DrawRectangleLines(250 - 40, 320, 80, 60, Color.Orange);
|
||||
|
||||
// Activate our default shader for next drawings
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("USING DEFAULT SHADER", 370, 40, 10, Color.Red);
|
||||
|
||||
DrawTriangle(
|
||||
new Vector2(430, 80),
|
||||
new Vector2(430 - 60, 150),
|
||||
new Vector2(430 + 60, 150), Color.Violet
|
||||
);
|
||||
|
||||
DrawTriangleLines(
|
||||
new Vector2(430, 160),
|
||||
new Vector2(430 - 20, 230),
|
||||
new Vector2(430 + 20, 230), Color.DarkBlue
|
||||
);
|
||||
|
||||
DrawPoly(new Vector2(430, 320), 6, 80, 0, Color.Brown);
|
||||
|
||||
// Activate our custom shader to be applied on next shapes/textures drawings
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// Using custom shader
|
||||
DrawTexture(fudesumi, 500, -30, Color.White);
|
||||
|
||||
// Activate our default shader for next drawings
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("(c) Fudesumi sprite by Eiden Marsal", 380, screenHeight - 20, 10, Color.Gray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(fudesumi);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Simple shader mask
|
||||
* raylib [shaders] example - simple mask
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.7
|
||||
*
|
||||
* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Chris Camacho (@chriscamacho) 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) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************
|
||||
*
|
||||
|
|
@ -24,54 +28,72 @@ using static Raylib_cs.Raymath;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class SimpleMask
|
||||
public class SimpleMask : IExample
|
||||
{
|
||||
public unsafe static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Simple Mask";
|
||||
|
||||
public string Title => "raylib [shaders] example - simple mask";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private Model model1;
|
||||
private Model model2;
|
||||
private Model model3;
|
||||
private Shader shader;
|
||||
private Texture2D texDiffuse;
|
||||
private Texture2D texMask;
|
||||
private int shaderFrame;
|
||||
private int framesCounter;
|
||||
private Vector3 rotation;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib - simple shader mask");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(0.0f, 1.0f, 2.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(0.0f, 1.0f, 2.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Define our three models to show the shader on
|
||||
Mesh torus = GenMeshTorus(.3f, 1, 16, 32);
|
||||
Model model1 = LoadModelFromMesh(torus);
|
||||
var torus = GenMeshTorus(.3f, 1, 16, 32);
|
||||
model1 = LoadModelFromMesh(torus);
|
||||
|
||||
Mesh cube = GenMeshCube(.8f, .8f, .8f);
|
||||
Model model2 = LoadModelFromMesh(cube);
|
||||
var cube = GenMeshCube(.8f, .8f, .8f);
|
||||
model2 = LoadModelFromMesh(cube);
|
||||
|
||||
// Generate model to be shaded just to see the gaps in the other two
|
||||
Mesh sphere = GenMeshSphere(1, 16, 16);
|
||||
Model model3 = LoadModelFromMesh(sphere);
|
||||
var sphere = GenMeshSphere(1, 16, 16);
|
||||
model3 = LoadModelFromMesh(sphere);
|
||||
|
||||
// Load the shader
|
||||
Shader shader = LoadShader("resources/shaders/glsl330/mask.vs", "resources/shaders/glsl330/mask.fs");
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/mask.fs");
|
||||
|
||||
// Load and apply the diffuse texture (colour map)
|
||||
Texture2D texDiffuse = LoadTexture("resources/plasma.png");
|
||||
texDiffuse = LoadTexture("resources/plasma.png");
|
||||
|
||||
Material* materials = model1.Materials;
|
||||
MaterialMap* maps = materials[0].Maps;
|
||||
var materials = model1.Materials;
|
||||
var maps = materials[0].Maps;
|
||||
model1.Materials[0].Maps[(int)MaterialMapIndex.Albedo].Texture = texDiffuse;
|
||||
|
||||
materials = model2.Materials;
|
||||
maps = materials[0].Maps;
|
||||
maps[(int)MaterialMapIndex.Albedo].Texture = texDiffuse;
|
||||
|
||||
// Using MAP_EMISSION as a spare slot to use for 2nd texture
|
||||
// NOTE: Don't use MAP_IRRADIANCE, MAP_PREFILTER or MAP_CUBEMAP
|
||||
// as they are bound as cube maps
|
||||
Texture2D texMask = LoadTexture("resources/mask.png");
|
||||
// Using MATERIAL_MAP_EMISSION as a spare slot to use for 2nd texture
|
||||
// NOTE: Don't use MATERIAL_MAP_IRRADIANCE, MATERIAL_MAP_PREFILTER or MATERIAL_MAP_CUBEMAP as they are bound as cube maps
|
||||
texMask = LoadTexture("resources/mask.png");
|
||||
|
||||
materials = model1.Materials;
|
||||
maps = (MaterialMap*)materials[0].Maps;
|
||||
|
|
@ -81,11 +103,11 @@ public class SimpleMask
|
|||
maps = (MaterialMap*)materials[0].Maps;
|
||||
maps[(int)MaterialMapIndex.Emission].Texture = texMask;
|
||||
|
||||
int* locs = shader.Locs;
|
||||
var locs = shader.Locs;
|
||||
locs[(int)ShaderLocationIndex.MapEmission] = GetShaderLocation(shader, "mask");
|
||||
|
||||
// Frame is incremented each frame to animate the shader
|
||||
int shaderFrame = GetShaderLocation(shader, "framesCounter");
|
||||
shaderFrame = GetShaderLocation(shader, "frame");
|
||||
|
||||
// Apply the shader to the two models
|
||||
materials = model1.Materials;
|
||||
|
|
@ -94,69 +116,88 @@ public class SimpleMask
|
|||
materials = (Material*)model2.Materials;
|
||||
materials[0].Shader = shader;
|
||||
|
||||
int framesCounter = 0;
|
||||
framesCounter = 0;
|
||||
rotation = new(0, 0, 0); // Model rotation angles
|
||||
}
|
||||
|
||||
// Model rotation angles
|
||||
Vector3 rotation = new(0, 0, 0);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.FirstPerson);
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
rotation.X += 0.01f;
|
||||
rotation.Y += 0.005f;
|
||||
rotation.Z -= 0.0025f;
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
rotation.X += 0.01f;
|
||||
rotation.Y += 0.005f;
|
||||
rotation.Z -= 0.0025f;
|
||||
// Send frames counter to shader for animation
|
||||
Raylib.SetShaderValue(shader, shaderFrame, framesCounter, ShaderUniformDataType.Int);
|
||||
|
||||
// Send frames counter to shader for animation
|
||||
Raylib.SetShaderValue(shader, shaderFrame, framesCounter, ShaderUniformDataType.Int);
|
||||
// Rotate one of the models
|
||||
model1.Transform = MatrixRotateXYZ(rotation);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Rotate one of the models
|
||||
model1.Transform = MatrixRotateXYZ(rotation);
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.DarkBlue);
|
||||
|
||||
UpdateCamera(ref camera, CameraMode.Custom);
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.DarkBlue);
|
||||
DrawModel(model1, new Vector3(0.5f, 0, 0), 1, Color.White);
|
||||
DrawModelEx(model2, new Vector3(-.5f, 0, 0), new Vector3(1, 1, 0), 50, new Vector3(1, 1, 1), Color.White);
|
||||
DrawModel(model3, new Vector3(0, 0, -1.5f), 1, Color.White);
|
||||
DrawGrid(10, 1.0f); // Draw a grid
|
||||
|
||||
BeginMode3D(camera);
|
||||
EndMode3D();
|
||||
|
||||
DrawModel(model1, new Vector3(0.5f, 0, 0), 1, Color.White);
|
||||
DrawModelEx(model2, new Vector3(-.5f, 0, 0), new Vector3(1, 1, 0), 50, new Vector3(1, 1, 1), Color.White);
|
||||
DrawModel(model3, new Vector3(0, 0, -1.5f), 1, Color.White);
|
||||
DrawGrid(10, 1.0f);
|
||||
var frameText = $"Frame: {framesCounter}";
|
||||
DrawRectangle(16, 698, MeasureText(frameText, 20) + 8, 42, Color.Blue);
|
||||
DrawText(frameText, 20, 700, 20, Color.White);
|
||||
|
||||
EndMode3D();
|
||||
DrawFPS(10, 10);
|
||||
|
||||
string frameText = $"Frame: {framesCounter}";
|
||||
DrawRectangle(16, 698, MeasureText(frameText, 20) + 8, 42, Color.Blue);
|
||||
DrawText(frameText, 20, 700, 20, Color.White);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
public void Unload()
|
||||
{
|
||||
UnloadModel(model1);
|
||||
UnloadModel(model2);
|
||||
UnloadModel(model3);
|
||||
|
||||
UnloadTexture(texDiffuse);
|
||||
UnloadTexture(texMask);
|
||||
UnloadTexture(texDiffuse); // Unload default diffuse texture
|
||||
UnloadTexture(texMask); // Unload texture mask
|
||||
|
||||
UnloadShader(shader);
|
||||
UnloadShader(shader); // Unload shader
|
||||
}
|
||||
|
||||
CloseWindow();
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - simple mask");
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
SetTargetFPS(60); // Set to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new SimpleMask();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,29 +1,32 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Simple shader mask
|
||||
* raylib [shaders] example - spotlight rendering
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example contributed by Chris Camacho (@chriscamacho - http://bedroomcoders.co.uk/)
|
||||
* and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.7
|
||||
*
|
||||
* Copyright (c) 2019 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Chris Camacho (@chriscamacho) 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) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************
|
||||
*
|
||||
* The shader makes alpha holes in the forground to give the apearance of a top
|
||||
* The shader makes alpha holes in the forground to give the appearance of a top
|
||||
* down look at a spotlight casting a pool of light...
|
||||
*
|
||||
* The right hand side of the screen there is just enough light to see whats
|
||||
* going on without the spot light, great for a stealth type game where you
|
||||
* have to avoid the spotlights.
|
||||
* have to avoid the spotlights
|
||||
*
|
||||
* The left hand side of the screen is in pitch dark except for where the spotlights are.
|
||||
* The left hand side of the screen is in pitch dark except for where the spotlights are
|
||||
*
|
||||
* Although this example doesn't scale like the letterbox example, you could integrate
|
||||
* the two techniques, but by scaling the actual colour of the render texture rather
|
||||
* than using alpha as a mask.
|
||||
* than using alpha as a mask
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -33,14 +36,29 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class Spotlight
|
||||
public class Spotlight : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
// NOTE: It must be the same as define in shader
|
||||
const int MaxSpots = 3;
|
||||
const int MaxStars = 400;
|
||||
private const int MaxSpots = 3;
|
||||
private const int MaxStars = 400;
|
||||
|
||||
public string Name => "Shaders / Spotlight";
|
||||
|
||||
public string Title => "raylib [shaders] example - spotlight rendering";
|
||||
|
||||
public bool CursorHidden => true;
|
||||
|
||||
// Spot data
|
||||
struct Spot
|
||||
private struct Spot
|
||||
{
|
||||
public Vector2 pos;
|
||||
public Vector2 vel;
|
||||
|
|
@ -54,53 +72,51 @@ public class Spotlight
|
|||
}
|
||||
|
||||
// Stars in the star field have a position and velocity
|
||||
struct Star
|
||||
private struct Star
|
||||
{
|
||||
public Vector2 pos;
|
||||
public Vector2 vel;
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
private Texture2D texRay;
|
||||
private Star[] stars;
|
||||
private int frameCounter;
|
||||
private Shader shdrSpot;
|
||||
private Spot[] spots;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
texRay = LoadTexture("resources/raysan.png");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib - shader spotlight");
|
||||
HideCursor();
|
||||
stars = new Star[MaxStars];
|
||||
|
||||
Texture2D texRay = LoadTexture("resources/raysan.png");
|
||||
|
||||
Star[] stars = new Star[MaxStars];
|
||||
|
||||
for (int n = 0; n < MaxStars; n++)
|
||||
for (var n = 0; n < MaxStars; n++)
|
||||
{
|
||||
ResetStar(ref stars[n]);
|
||||
}
|
||||
|
||||
// Progress all the stars on, so they don't all start in the centre
|
||||
for (int m = 0; m < screenWidth / 2.0; m++)
|
||||
for (var m = 0; m < screenWidth / 2.0; m++)
|
||||
{
|
||||
for (int n = 0; n < MaxStars; n++)
|
||||
for (var n = 0; n < MaxStars; n++)
|
||||
{
|
||||
UpdateStar(ref stars[n]);
|
||||
}
|
||||
}
|
||||
|
||||
int frameCounter = 0;
|
||||
frameCounter = 0;
|
||||
|
||||
// Use default vert shader
|
||||
Shader shdrSpot = LoadShader(null, "resources/shaders/glsl330/spotlight.fs");
|
||||
shdrSpot = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/spotlight.fs");
|
||||
|
||||
// Get the locations of spots in the shader
|
||||
Spot[] spots = new Spot[MaxSpots];
|
||||
spots = new Spot[MaxSpots];
|
||||
|
||||
for (int i = 0; i < MaxSpots; i++)
|
||||
for (var i = 0; i < MaxSpots; i++)
|
||||
{
|
||||
string posName = $"spots[{i}].pos";
|
||||
string innerName = $"spots[{i}].inner";
|
||||
string radiusName = $"spots[{i}].radius";
|
||||
var posName = $"spots[{i}].pos";
|
||||
var innerName = $"spots[{i}].inner";
|
||||
var radiusName = $"spots[{i}].radius";
|
||||
|
||||
spots[i].posLoc = GetShaderLocation(shdrSpot, posName);
|
||||
spots[i].innerLoc = GetShaderLocation(shdrSpot, innerName);
|
||||
|
|
@ -108,14 +124,14 @@ public class Spotlight
|
|||
}
|
||||
|
||||
// Tell the shader how wide the screen is so we can have
|
||||
// a pitch Color.black half and a dimly lit half.
|
||||
int wLoc = GetShaderLocation(shdrSpot, "screenWidth");
|
||||
float sw = (float)GetScreenWidth();
|
||||
// a pitch black half and a dimly lit half
|
||||
var wLoc = GetShaderLocation(shdrSpot, "screenWidth");
|
||||
var sw = (float)GetScreenWidth();
|
||||
Raylib.SetShaderValue(shdrSpot, wLoc, sw, ShaderUniformDataType.Float);
|
||||
|
||||
// Randomise the locations and velocities of the spotlights
|
||||
// and initialise the shader locations
|
||||
for (int i = 0; i < MaxSpots; i++)
|
||||
// Randomize the locations and velocities of the spotlights
|
||||
// and initialize the shader locations
|
||||
for (var i = 0; i < MaxSpots; i++)
|
||||
{
|
||||
spots[i].pos.X = GetRandomValue(64, screenWidth - 64);
|
||||
spots[i].pos.Y = GetRandomValue(64, screenHeight - 64);
|
||||
|
|
@ -123,8 +139,8 @@ public class Spotlight
|
|||
|
||||
while ((MathF.Abs(spots[i].vel.X) + MathF.Abs(spots[i].vel.Y)) < 2)
|
||||
{
|
||||
spots[i].vel.X = GetRandomValue(-40, 40) / 10.0f;
|
||||
spots[i].vel.Y = GetRandomValue(-40, 40) / 10.0f;
|
||||
spots[i].vel.X = GetRandomValue(-400, 40) / 25.0f;
|
||||
spots[i].vel.Y = GetRandomValue(-400, 40) / 25.0f;
|
||||
}
|
||||
|
||||
spots[i].inner = 28.0f * (i + 1);
|
||||
|
|
@ -149,118 +165,110 @@ public class Spotlight
|
|||
ShaderUniformDataType.Float
|
||||
);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
frameCounter++;
|
||||
|
||||
// Move the stars, resetting them if the go offscreen
|
||||
for (int n = 0; n < MaxStars; n++)
|
||||
{
|
||||
UpdateStar(ref stars[n]);
|
||||
}
|
||||
|
||||
// Update the spots, send them to the shader
|
||||
for (int i = 0; i < MaxSpots; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
Vector2 mp = GetMousePosition();
|
||||
spots[i].pos.X = mp.X;
|
||||
spots[i].pos.Y = screenHeight - mp.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
spots[i].pos.X += spots[i].vel.X;
|
||||
spots[i].pos.Y += spots[i].vel.Y;
|
||||
|
||||
if (spots[i].pos.X < 64)
|
||||
{
|
||||
spots[i].vel.X = -spots[i].vel.X;
|
||||
}
|
||||
|
||||
if (spots[i].pos.X > (screenWidth - 64))
|
||||
{
|
||||
spots[i].vel.X = -spots[i].vel.X;
|
||||
}
|
||||
|
||||
if (spots[i].pos.Y < 64)
|
||||
{
|
||||
spots[i].vel.Y = -spots[i].vel.Y;
|
||||
}
|
||||
|
||||
if (spots[i].pos.Y > (screenHeight - 64))
|
||||
{
|
||||
spots[i].vel.Y = -spots[i].vel.Y;
|
||||
}
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(
|
||||
shdrSpot,
|
||||
spots[i].posLoc,
|
||||
spots[i].pos,
|
||||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
}
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.DarkBlue);
|
||||
|
||||
// Draw stars and bobs
|
||||
for (int n = 0; n < MaxStars; n++)
|
||||
{
|
||||
// MathF.Single pixel is just too small these days!
|
||||
DrawRectangle((int)stars[n].pos.X, (int)stars[n].pos.Y, 2, 2, Color.White);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
DrawTexture(
|
||||
texRay,
|
||||
(int)((screenWidth / 2.0) + MathF.Cos((frameCounter + i * 8) / 51.45f) * (screenWidth / 2.2) - 32),
|
||||
(int)((screenHeight / 2.0) + MathF.Sin((frameCounter + i * 8) / 17.87f) * (screenHeight / 4.2)),
|
||||
Color.White
|
||||
);
|
||||
}
|
||||
|
||||
// Draw spot lights
|
||||
BeginShaderMode(shdrSpot);
|
||||
|
||||
// Instead of a blank rectangle you could render a render texture of the full screen used to do screen
|
||||
// scaling (slight adjustment to shader would be required to actually pay attention to the colour!)
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText("Move the mouse!", 10, 30, 20, Color.Green);
|
||||
DrawText("Pitch Color.Black", (int)(screenWidth * 0.2f), screenHeight / 2, 20, Color.Green);
|
||||
DrawText("Dark", (int)(screenWidth * 0.66f), screenHeight / 2, 20, Color.Green);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texRay);
|
||||
UnloadShader(shdrSpot);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ResetStar(ref Star s)
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
frameCounter++;
|
||||
|
||||
// Move the stars, resetting them if the go offscreen
|
||||
for (var n = 0; n < MaxStars; n++)
|
||||
{
|
||||
UpdateStar(ref stars[n]);
|
||||
}
|
||||
|
||||
// Update the spots, send them to the shader
|
||||
for (var i = 0; i < MaxSpots; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
var mp = GetMousePosition();
|
||||
spots[i].pos.X = mp.X;
|
||||
spots[i].pos.Y = screenHeight - mp.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
spots[i].pos.X += spots[i].vel.X;
|
||||
spots[i].pos.Y += spots[i].vel.Y;
|
||||
|
||||
if (spots[i].pos.X < 64)
|
||||
{
|
||||
spots[i].vel.X = -spots[i].vel.X;
|
||||
}
|
||||
|
||||
if (spots[i].pos.X > (screenWidth - 64))
|
||||
{
|
||||
spots[i].vel.X = -spots[i].vel.X;
|
||||
}
|
||||
|
||||
if (spots[i].pos.Y < 64)
|
||||
{
|
||||
spots[i].vel.Y = -spots[i].vel.Y;
|
||||
}
|
||||
|
||||
if (spots[i].pos.Y > (screenHeight - 64))
|
||||
{
|
||||
spots[i].vel.Y = -spots[i].vel.Y;
|
||||
}
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(
|
||||
shdrSpot,
|
||||
spots[i].posLoc,
|
||||
spots[i].pos,
|
||||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
}
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.DarkBlue);
|
||||
|
||||
// Draw stars and bobs
|
||||
for (var n = 0; n < MaxStars; n++)
|
||||
{
|
||||
// Single pixel is just too small these days!
|
||||
DrawRectangle((int)stars[n].pos.X, (int)stars[n].pos.Y, 2, 2, Color.White);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 16; i++)
|
||||
{
|
||||
DrawTexture(
|
||||
texRay,
|
||||
(int)((screenWidth / 2.0) + MathF.Cos((frameCounter + i * 8) / 51.45f) * (screenWidth / 2.2) - 32),
|
||||
(int)((screenHeight / 2.0) + MathF.Sin((frameCounter + i * 8) / 17.87f) * (screenHeight / 4.2)),
|
||||
Color.White
|
||||
);
|
||||
}
|
||||
|
||||
// Draw spot lights
|
||||
BeginShaderMode(shdrSpot);
|
||||
|
||||
// Instead of a blank rectangle you could render a render texture of the full screen used to do screen
|
||||
// scaling (slight adjustment to shader would be required to actually pay attention to the colour!)
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText("Move the mouse!", 10, 30, 20, Color.Green);
|
||||
DrawText("Pitch Black", (int)(screenWidth * 0.2f), screenHeight / 2, 20, Color.Green);
|
||||
DrawText("Dark", (int)(screenWidth * 0.66f), screenHeight / 2, 20, Color.Green);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadTexture(texRay);
|
||||
UnloadShader(shdrSpot);
|
||||
}
|
||||
|
||||
private static void ResetStar(ref Star s)
|
||||
{
|
||||
s.pos = new Vector2(GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f);
|
||||
|
||||
|
|
@ -270,10 +278,10 @@ public class Spotlight
|
|||
s.vel.Y = (float)GetRandomValue(-1000, 1000) / 100.0f;
|
||||
} while (!((MathF.Abs(s.vel.X) + (MathF.Abs(s.vel.Y)) > 1)));
|
||||
|
||||
s.pos += s.pos + (s.vel * new Vector2(8.0f, 8.0f));
|
||||
s.pos += s.vel * new Vector2(8.0f, 8.0f);
|
||||
}
|
||||
|
||||
static void UpdateStar(ref Star s)
|
||||
private static void UpdateStar(ref Star s)
|
||||
{
|
||||
s.pos += s.vel;
|
||||
|
||||
|
|
@ -283,4 +291,33 @@ public class Spotlight
|
|||
ResetStar(ref s);
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - spotlight rendering");
|
||||
HideCursor();
|
||||
|
||||
SetTargetFPS(60); // Set to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Spotlight();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [textures] example - Texture drawing
|
||||
* raylib [shaders] example - texture rendering
|
||||
*
|
||||
* This example illustrates how to draw on a blank texture using a shader
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* 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)
|
||||
* Example originally created with raylib 2.0, last time updated with raylib 3.7
|
||||
*
|
||||
* Example contributed by Michał Ciesielski and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Michał Ciesielski (@ciessielski) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 Michał Ciesielski and 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) 2019-2025 Michał Ciesielski (@ciessielski) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -17,68 +19,92 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class TextureDrawing
|
||||
public class TextureDrawing : IExample
|
||||
{
|
||||
const int GlslVersion = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Texture Drawing";
|
||||
|
||||
public string Title => "raylib [shaders] example - texture rendering";
|
||||
|
||||
private Texture2D texture;
|
||||
private Shader shader;
|
||||
private float time;
|
||||
private int timeLoc;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var imBlank = GenImageColor(1024, 1024, Color.Blank);
|
||||
texture = LoadTextureFromImage(imBlank); // Load blank texture to fill on shader
|
||||
UnloadImage(imBlank);
|
||||
|
||||
// NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/cubes_panning.fs");
|
||||
|
||||
time = 0.0f;
|
||||
timeLoc = GetShaderLocation(shader, "uTime");
|
||||
Raylib.SetShaderValue(shader, timeLoc, time, ShaderUniformDataType.Float);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
time = (float)GetTime();
|
||||
Raylib.SetShaderValue(shader, timeLoc, time, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader); // Enable our custom shader for next shapes/textures drawings
|
||||
DrawTexture(texture, 0, 0, Color.White); // Drawing BLANK texture, all rendering magic happens on shader
|
||||
EndShaderMode(); // Disable our custom shader, return to default shader
|
||||
|
||||
DrawText("BACKGROUND is PAINTED and ANIMATED on SHADER!", 10, 10, 20, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(texture);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture rendering");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");
|
||||
|
||||
// Load blank texture to fill on shader
|
||||
Image imBlank = GenImageColor(1024, 1024, Color.Blank);
|
||||
Texture2D texture = LoadTextureFromImage(imBlank);
|
||||
UnloadImage(imBlank);
|
||||
|
||||
// NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/cubes_panning.fs");
|
||||
|
||||
float time = 0.0f;
|
||||
int timeLoc = GetShaderLocation(shader, "uTime");
|
||||
Raylib.SetShaderValue(shader, timeLoc, time, ShaderUniformDataType.Float);
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new TextureDrawing();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
time = (float)GetTime();
|
||||
Raylib.SetShaderValue(shader, timeLoc, time, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Enable our custom shader for next shapes/textures drawings
|
||||
BeginShaderMode(shader);
|
||||
|
||||
// Drawing blank texture, all magic happens on shader
|
||||
DrawTexture(texture, 0, 0, Color.White);
|
||||
|
||||
// Disable our custom shader, return to default shader
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("BACKGROUND is PAINTED and ANIMATED on SHADER!", 10, 10, 20, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [textures] example - Texture drawing
|
||||
* raylib [shaders] example - texture outline
|
||||
*
|
||||
* This example illustrates how to draw on a blank texture using a shader
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* 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)
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* Example contributed by Michał Ciesielski and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||
*
|
||||
* Copyright (c) 2019 Michał Ciesielski and Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Serenity Skiff (@GoldenThumbs) 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) 2021-2025 Serenity Skiff (@GoldenThumbs) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -17,32 +22,41 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class TextureOutline
|
||||
public class TextureOutline : IExample
|
||||
{
|
||||
const int GLSL_VERSION = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public static int Main()
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Texture Outline";
|
||||
|
||||
public string Title => "raylib [shaders] example - texture outline";
|
||||
|
||||
private Texture2D texture;
|
||||
private Shader shdrOutline;
|
||||
private float outlineSize;
|
||||
private int outlineSizeLoc;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
texture = LoadTexture("resources/fudesumi.png");
|
||||
shdrOutline = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/outline.fs");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Apply an outline to a texture");
|
||||
outlineSize = 2.0f;
|
||||
|
||||
Texture2D texture = LoadTexture("resources/fudesumi.png");
|
||||
Shader shdrOutline = LoadShader(null, $"resources/shaders/glsl{GLSL_VERSION}/outline.fs");
|
||||
|
||||
float outlineSize = 2.0f;
|
||||
|
||||
// Normalized red color
|
||||
float[] outlineColor = new[] { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
// Normalized RED color
|
||||
var outlineColor = new[] { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
float[] textureSize = { (float)texture.Width, (float)texture.Height };
|
||||
|
||||
// Get shader locations
|
||||
int outlineSizeLoc = GetShaderLocation(shdrOutline, "outlineSize");
|
||||
int outlineColorLoc = GetShaderLocation(shdrOutline, "outlineColor");
|
||||
int textureSizeLoc = GetShaderLocation(shdrOutline, "textureSize");
|
||||
outlineSizeLoc = GetShaderLocation(shdrOutline, "outlineSize");
|
||||
var outlineColorLoc = GetShaderLocation(shdrOutline, "outlineColor");
|
||||
var textureSizeLoc = GetShaderLocation(shdrOutline, "textureSize");
|
||||
|
||||
// Set shader values (they can be changed later)
|
||||
Raylib.SetShaderValue(
|
||||
|
|
@ -63,55 +77,75 @@ public class TextureOutline
|
|||
textureSize,
|
||||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
outlineSize += GetMouseWheelMove();
|
||||
if (outlineSize < 1.0f)
|
||||
{
|
||||
outlineSize = 1.0f;
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(
|
||||
shdrOutline,
|
||||
outlineSizeLoc,
|
||||
outlineSize,
|
||||
ShaderUniformDataType.Float
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shdrOutline);
|
||||
DrawTexture(texture, GetScreenWidth() / 2 - texture.Width / 2, -30, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("Shader-based\ntexture\noutline", 10, 10, 20, Color.Gray);
|
||||
DrawText("Scroll mouse wheel to\nchange outline size", 10, 72, 20, Color.Gray);
|
||||
DrawText($"Outline size: {(int)outlineSize} px", 10, 120, 20, Color.Maroon);
|
||||
|
||||
DrawFPS(710, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadTexture(texture);
|
||||
UnloadShader(shdrOutline);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture outline");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new TextureOutline();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
outlineSize += GetMouseWheelMove();
|
||||
if (outlineSize < 1.0f)
|
||||
{
|
||||
outlineSize = 1.0f;
|
||||
}
|
||||
|
||||
Raylib.SetShaderValue(
|
||||
shdrOutline,
|
||||
outlineSizeLoc,
|
||||
outlineSize,
|
||||
ShaderUniformDataType.Float
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shdrOutline);
|
||||
DrawTexture(texture, GetScreenWidth() / 2 - texture.Width / 2, -30, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("Shader-based\ntexture\noutline", 10, 10, 20, Color.Gray);
|
||||
|
||||
DrawText($"Outline size: {outlineSize} px", 10, 120, 20, Color.Maroon);
|
||||
|
||||
DrawFPS(710, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texture);
|
||||
UnloadShader(shdrOutline);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
143
Examples/Shaders/TextureTiling.cs
Normal file
143
Examples/Shaders/TextureTiling.cs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - texture tiling
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example demonstrates how to tile a texture on a 3D model using raylib
|
||||
*
|
||||
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||
*
|
||||
* Example contributed by Luis Almeida (@luis605) 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-2025 Luis Almeida (@luis605)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class TextureTiling : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Texture Tiling";
|
||||
|
||||
public string Title => "raylib [shaders] example - texture tiling";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private Model model;
|
||||
private Texture2D texture;
|
||||
private Shader shader;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(4.0f, 4.0f, 4.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Load a cube model
|
||||
var cube = GenMeshCube(1.0f, 1.0f, 1.0f);
|
||||
model = LoadModelFromMesh(cube);
|
||||
|
||||
// Load a texture and assign to cube model
|
||||
texture = LoadTexture("resources/cubicmap_atlas.png");
|
||||
model.Materials[0].Maps[(int)MaterialMapIndex.Diffuse].Texture = texture;
|
||||
|
||||
// Set the texture tiling using a shader
|
||||
var tiling = new[] { 3.0f, 3.0f };
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/tiling.fs");
|
||||
SetTextureWrap(texture, TextureWrap.Repeat);
|
||||
Raylib.SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, ShaderUniformDataType.Vec2);
|
||||
model.Materials[0].Shader = shader;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Z))
|
||||
{
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
DrawModel(model, new Vector3(0.0f, 0.0f, 0.0f), 2.0f, Color.White);
|
||||
EndShaderMode();
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Use mouse to rotate the camera", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadModel(model); // Unload model
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture tiling");
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new TextureTiling();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,24 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Texture Waves
|
||||
* raylib [shaders] example - texture waves
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
|
||||
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
|
||||
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
|
||||
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.7
|
||||
*
|
||||
* Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 Anata (@anatagawa) and 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) 2019-2025 Anata (@anatagawa) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -22,40 +26,49 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class TextureWaves
|
||||
public class TextureWaves : IExample
|
||||
{
|
||||
const int GlslVersion = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public static int Main()
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Texture Waves";
|
||||
|
||||
public string Title => "raylib [shaders] example - texture waves";
|
||||
|
||||
private Texture2D texture;
|
||||
private Shader shader;
|
||||
private int secondsLoc;
|
||||
private float seconds;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture waves");
|
||||
|
||||
// Load texture texture to apply shaders
|
||||
Texture2D texture = LoadTexture("resources/space.png");
|
||||
texture = LoadTexture("resources/space.png");
|
||||
|
||||
// Load shader and setup location points and values
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/wave.fs");
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/wave.fs");
|
||||
|
||||
int secondsLoc = GetShaderLocation(shader, "secondes");
|
||||
int freqXLoc = GetShaderLocation(shader, "freqX");
|
||||
int freqYLoc = GetShaderLocation(shader, "freqY");
|
||||
int ampXLoc = GetShaderLocation(shader, "ampX");
|
||||
int ampYLoc = GetShaderLocation(shader, "ampY");
|
||||
int speedXLoc = GetShaderLocation(shader, "speedX");
|
||||
int speedYLoc = GetShaderLocation(shader, "speedY");
|
||||
secondsLoc = GetShaderLocation(shader, "seconds");
|
||||
var freqXLoc = GetShaderLocation(shader, "freqX");
|
||||
var freqYLoc = GetShaderLocation(shader, "freqY");
|
||||
var ampXLoc = GetShaderLocation(shader, "ampX");
|
||||
var ampYLoc = GetShaderLocation(shader, "ampY");
|
||||
var speedXLoc = GetShaderLocation(shader, "speedX");
|
||||
var speedYLoc = GetShaderLocation(shader, "speedY");
|
||||
|
||||
// Shader uniform values that can be updated at any time
|
||||
float freqX = 25.0f;
|
||||
float freqY = 25.0f;
|
||||
float ampX = 5.0f;
|
||||
float ampY = 5.0f;
|
||||
float speedX = 8.0f;
|
||||
float speedY = 8.0f;
|
||||
var freqX = 25.0f;
|
||||
var freqY = 25.0f;
|
||||
var ampX = 5.0f;
|
||||
var ampY = 5.0f;
|
||||
var speedX = 8.0f;
|
||||
var speedY = 8.0f;
|
||||
|
||||
float[] screenSize = { (float)GetScreenWidth(), (float)GetScreenHeight() };
|
||||
Raylib.SetShaderValue(
|
||||
|
|
@ -71,43 +84,63 @@ public class TextureWaves
|
|||
Raylib.SetShaderValue(shader, speedXLoc, speedX, ShaderUniformDataType.Float);
|
||||
Raylib.SetShaderValue(shader, speedYLoc, speedY, ShaderUniformDataType.Float);
|
||||
|
||||
float seconds = 0.0f;
|
||||
seconds = 0.0f;
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
seconds += GetFrameTime();
|
||||
|
||||
Raylib.SetShaderValue(shader, secondsLoc, seconds, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawTexture(texture, 0, 0, Color.White);
|
||||
DrawTexture(texture, texture.Width, 0, Color.White);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture waves");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new TextureWaves();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
seconds += GetFrameTime();
|
||||
|
||||
Raylib.SetShaderValue(shader, secondsLoc, seconds, ShaderUniformDataType.Float);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawTexture(texture, 0, 0, Color.White);
|
||||
DrawTexture(texture, texture.Width, 0, Color.White);
|
||||
|
||||
EndShaderMode();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadTexture(texture);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
148
Examples/Shaders/VertexDisplacement.cs
Normal file
148
Examples/Shaders/VertexDisplacement.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - vertex displacement
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* 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-2025 Alex ZH (@ZzzhHe)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Rlgl;
|
||||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public partial class VertexDisplacement : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Vertex Displacement";
|
||||
|
||||
public string Title => "raylib [shaders] example - vertex displacement";
|
||||
|
||||
private Camera3D camera;
|
||||
private Shader shader;
|
||||
private Texture2D perlinNoiseMap;
|
||||
private Model planeModel;
|
||||
private float time;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// set up camera
|
||||
camera = new();
|
||||
camera.Position = new Vector3(20.0f, 5.0f, -20.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 60.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
// Load vertex and fragment shaders
|
||||
shader = LoadShader(
|
||||
$"resources/shaders/glsl{GlslVersion}/vertex_displacement.vs",
|
||||
$"resources/shaders/glsl{GlslVersion}/vertex_displacement.fs"
|
||||
);
|
||||
|
||||
// Load perlin noise texture
|
||||
var perlinNoiseImage = GenImagePerlinNoise(512, 512, 0, 0, 1.0f);
|
||||
perlinNoiseMap = LoadTextureFromImage(perlinNoiseImage);
|
||||
UnloadImage(perlinNoiseImage);
|
||||
|
||||
// Set shader uniform location
|
||||
var perlinNoiseMapLoc = GetShaderLocation(shader, "perlinNoiseMap");
|
||||
EnableShader(shader.Id);
|
||||
ActiveTextureSlot(1);
|
||||
EnableTexture(perlinNoiseMap.Id);
|
||||
SetUniformSampler(perlinNoiseMapLoc, 1);
|
||||
|
||||
// Create a plane mesh and model
|
||||
var planeMesh = GenMeshPlane(50, 50, 50, 50);
|
||||
planeModel = LoadModelFromMesh(planeMesh);
|
||||
// Set plane model material
|
||||
var materials = planeModel.Materials;
|
||||
materials[0].Shader = shader;
|
||||
|
||||
time = 0.0f;
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free); // Update camera
|
||||
|
||||
time += GetFrameTime(); // Update time variable
|
||||
Raylib.SetShaderValue(shader, GetShaderLocation(shader, "time"), time, ShaderUniformDataType.Float); // Send time value to shader
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
// Draw plane model
|
||||
DrawModel(planeModel, new Vector3(0.0f, 0.0f, 0.0f), 1.0f, new Color(255, 255, 255, 255));
|
||||
EndShaderMode();
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Vertex displacement", 10, 10, 20, Color.DarkGray);
|
||||
DrawFPS(10, 40);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadShader(shader);
|
||||
UnloadModel(planeModel);
|
||||
UnloadTexture(perlinNoiseMap);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - vertex displacement");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new VertexDisplacement();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - Depth buffer writing
|
||||
* raylib [shaders] example - depth writing
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
|
|
@ -9,7 +11,7 @@
|
|||
* 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) 2022-2023 Buğra Alptekin Sarı (@BugraAlptekinSari)
|
||||
* Copyright (c) 2022-2025 Buğra Alptekin Sarı (@BugraAlptekinSari)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -18,86 +20,115 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Shaders;
|
||||
|
||||
public class WriteDepth
|
||||
public class WriteDepth : IExample
|
||||
{
|
||||
const int GLSL_VERSION = 330;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Shaders / Write Depth";
|
||||
|
||||
public string Title => "raylib [shaders] example - depth writing";
|
||||
|
||||
private Camera3D camera;
|
||||
private RenderTexture2D target;
|
||||
private Shader shader;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(2.0f, 2.0f, 3.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
// Load custom render texture with writable depth texture buffer
|
||||
target = LoadRenderTextureDepthTex(screenWidth, screenHeight);
|
||||
|
||||
// Load depth writing shader
|
||||
// NOTE: The shader inverts the depth buffer by writing into it by `gl_FragDepth = 1 - gl_FragCoord.z;`
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/depth_write.fs");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw into our custom render texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
BeginMode3D(camera);
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Red);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Purple);
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.DarkGreen);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Yellow);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndShaderMode();
|
||||
EndMode3D();
|
||||
EndTextureMode();
|
||||
|
||||
// Draw into screen our custom render texture
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.White
|
||||
);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTextureDepthTex(target);
|
||||
UnloadShader(shader);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - depth writing");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - write depth buffer");
|
||||
|
||||
// The shader inverts the depth buffer by writing into it by `gl_FragDepth = 1 - gl_FragCoord.z;`
|
||||
Shader shader = LoadShader(null, $"resources/shaders/glsl{GLSL_VERSION}/write_depth.fs");
|
||||
|
||||
// Use customized function to create writable depth texture buffer
|
||||
RenderTexture2D target = LoadRenderTextureDepthTex(screenWidth, screenHeight);
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera;
|
||||
camera.Position = new Vector3(2.0f, 2.0f, 3.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.5f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new WriteDepth();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Orbital);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw into our custom render texture (framebuffer)
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
|
||||
BeginMode3D(camera);
|
||||
BeginShaderMode(shader);
|
||||
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Red);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, 1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Purple);
|
||||
DrawCubeWiresV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.DarkGreen);
|
||||
DrawCubeV(new Vector3(0.0f, 0.5f, -1.0f), new Vector3(1.0f, 1.0f, 1.0f), Color.Yellow);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndShaderMode();
|
||||
EndMode3D();
|
||||
EndTextureMode();
|
||||
|
||||
// Draw custom render texture
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, screenWidth, -screenHeight),
|
||||
Vector2.Zero,
|
||||
Color.White
|
||||
);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTextureDepthTex(target);
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
@ -152,7 +183,7 @@ public class WriteDepth
|
|||
);
|
||||
|
||||
// Check if fbo is complete with attachments (valid)
|
||||
if (Rlgl.FramebufferComplete(target.Id))
|
||||
if (Rlgl.FramebufferComplete(target.Id) != 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Info, $"FBO: [ID {target.Id}] Framebuffer object created successfully");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue