Watch
2
0
Fork
You've already forked raylib-cs
0
raylib-cs/Examples/Shaders/SimpleMask.cs
2026-07-07 23:29:25 +02:00

205 lines
7.3 KiB
C#

/*******************************************************************************************
*
* raylib [shaders] example - simple mask
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 2.5, last time updated with raylib 3.7
*
* 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)
*
********************************************************************************************
*
* After a model is loaded it has a default material, this material can be
* modified in place rather than creating one from scratch...
* While all of the maps have particular names, they can be used for any purpose
* except for three maps that are applied as cubic maps (see below)
*
********************************************************************************************/
using System.Numerics;
using static Raylib_cs.Raylib;
using static Raylib_cs.Raymath;
namespace Examples.Shaders;
public class SimpleMask : 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 / 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()
{
// Define the camera to look into our 3d world
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
var torus = GenMeshTorus(.3f, 1, 16, 32);
model1 = LoadModelFromMesh(torus);
var cube = GenMeshCube(.8f, .8f, .8f);
model2 = LoadModelFromMesh(cube);
// Generate model to be shaded just to see the gaps in the other two
var sphere = GenMeshSphere(1, 16, 16);
model3 = LoadModelFromMesh(sphere);
// Load the shader
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/mask.fs");
// Load and apply the diffuse texture (colour map)
texDiffuse = LoadTexture("resources/plasma.png");
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 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;
maps[(int)MaterialMapIndex.Emission].Texture = texMask;
materials = model2.Materials;
maps = (MaterialMap*)materials[0].Maps;
maps[(int)MaterialMapIndex.Emission].Texture = texMask;
var locs = shader.Locs;
locs[(int)ShaderLocationIndex.MapEmission] = GetShaderLocation(shader, "mask");
// Frame is incremented each frame to animate the shader
shaderFrame = GetShaderLocation(shader, "frame");
// Apply the shader to the two models
materials = model1.Materials;
materials[0].Shader = shader;
materials = (Material*)model2.Materials;
materials[0].Shader = shader;
framesCounter = 0;
rotation = new(0, 0, 0); // Model rotation angles
}
public void Update()
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(ref camera, CameraMode.FirstPerson);
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);
// Rotate one of the models
model1.Transform = MatrixRotateXYZ(rotation);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(Color.DarkBlue);
BeginMode3D(camera);
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
EndMode3D();
var frameText = $"Frame: {framesCounter}";
DrawRectangle(16, 698, MeasureText(frameText, 20) + 8, 42, Color.Blue);
DrawText(frameText, 20, 700, 20, Color.White);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
public void Unload()
{
UnloadModel(model1);
UnloadModel(model2);
UnloadModel(model3);
UnloadTexture(texDiffuse); // Unload default diffuse texture
UnloadTexture(texMask); // Unload texture mask
UnloadShader(shader); // Unload shader
}
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;
}
}