Watch
2
0
Fork
You've already forked raylib-cs
0

chore: rebase to main with translation ports

This commit is contained in:
tiger tiger tiger 2026-07-17 07:49:07 +02:00
commit 8024c6ac40
134 changed files with 15456 additions and 10650 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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();
//--------------------------------------------------------------------------------------

View file

@ -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();
//--------------------------------------------------------------------------------------

View file

@ -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();
//--------------------------------------------------------------------------------------

View file

@ -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");
}

View file

@ -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();
//--------------------------------------------------------------------------------------

View file

@ -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;

View file

@ -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;

View file

@ -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();
//--------------------------------------------------------------------------------------

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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");
}