use raylib_ffi::*; use ::std::os::raw::*; const MAX_LIGHTS: usize = 4; // Max dynamic lights supported by shader // Light data struct Light { enabled: i32, kind: i32, position: Vector3, target: Vector3, color: Color, // Shader locations enabled_loc: i32, kind_loc: i32, position_loc: i32, target_loc: i32, color_loc: i32, } // Create a light and get shader locations fn create_light(id: isize, kind: i32, position: Vector3, target : Vector3, color : Color, shader : Shader) -> Light { unsafe { let light = Light { enabled: 1, kind, position, target, color, // NOTE: Lighting shader naming must be the provided ones enabled_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].enabled", id))), kind_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].type", id))), position_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].position", id))), target_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].target", id))), color_loc: GetShaderLocation(shader, rl_str!(format!("lights[{}].color", id))) }; update_light_values(shader, &light); return light; } } // Send light properties to shader // NOTE: Light shader locations should be available fn update_light_values(shader: Shader, light: &Light) { unsafe { // Send to shader light enabled state and type let enabled = [light.enabled].as_ptr(); SetShaderValue(shader, light.enabled_loc, enabled as *const c_void, enums::ShaderUniformDataType::Int as i32); let kind = [light.kind].as_ptr(); SetShaderValue(shader, light.kind_loc, kind as *const c_void, enums::ShaderUniformDataType::Int as i32); // Send to shader light position values let position = [light.position.x, light.position.y, light.position.z].as_ptr(); SetShaderValue(shader, light.position_loc, position as *const c_void, enums::ShaderUniformDataType::Vec3 as i32); // Send to shader light target position values let target = [light.position.x, light.position.y, light.position.z].as_ptr(); SetShaderValue(shader, light.target_loc, target as *const c_void, enums::ShaderUniformDataType::Vec3 as i32); // Send to shader light color values let color = [ light.color.r as f32 / 255.0, light.color.g as f32 / 255.0, light.color.b as f32 / 255.0, light.color.a as f32 / 255.0 ].as_ptr(); SetShaderValue(shader, light.color_loc, color as *const c_void, enums::ShaderUniformDataType::Vec4 as i32); } } //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ pub fn main() { unsafe { // Initialization //-------------------------------------------------------------------------------------- SetConfigFlags(enums::ConfigFlags::Msaa4xHint as u32); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(800, 450, rl_str!("raylib [shaders] example - basic lighting")); // Define the camera to look into our 3d world let mut camera = Camera{ position: Vector3{ x: 2.0, y: 4.0, z: 6.0 }, // Camera position target: Vector3{ x: 0.0, y: 0.5, z: 0.0 }, // Camera looking at point up: Vector3{ x: 0.0, y: 1.0, z: 0.0 }, // Camera up vector (rotation towards target) fovy: 45.0, // Camera field-of-view Y projection: enums::CameraProjection::Perspective as i32 // Camera projection type }; // Load plane model from a generated mesh let model = LoadModelFromMesh(GenMeshPlane(10.0, 10.0, 3, 3)); let cube = LoadModelFromMesh(GenMeshCube(2.0, 4.0, 2.0)); // Load basic lighting shader let shader = LoadShader(rl_str!("examples/shaders/lighting.vs"), rl_str!("examples/shaders/lighting.fs")); // Get some required shader locations let view_loc = shader.locs.offset(enums::ShaderLocationIndex::VectorView as isize) as *mut c_int; *view_loc = GetShaderLocation(shader, rl_str!("viewPos")); // Ambient light level (some basic lighting) let ambient_loc = GetShaderLocation(shader, rl_str!("ambient")); let ambient_value = [0.1 as f32, 0.1 as f32, 0.1 as f32, 1.0 as f32].as_ptr(); SetShaderValue(shader, ambient_loc, ambient_value as *const c_void, enums::ShaderUniformDataType::Ivec4 as i32); // Assign lighting shader to model (*(model.materials.offset(0))).shader = shader; (*(cube.materials.offset(0))).shader = shader; // Create lights let mut lights = [ create_light(0, 1, Vector3{ x: -2.0, y: 1.0, z: -2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::YELLOW, shader), create_light(1, 1, Vector3{ x: 2.0, y: 1.0, z: 2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::RED, shader), create_light(2, 1, Vector3{ x: -2.0, y: 1.0, z: 2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::GREEN, shader), create_light(3, 1, Vector3{ x: 2.0, y: 1.0, z: -2.0 }, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, colors::BLUE, shader) ]; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while !WindowShouldClose() // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&mut camera, enums::CameraMode::Orbital as i32); // Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f }) let camera_pos = [camera.position.x, camera.position.y, camera.position.z].as_ptr(); SetShaderValue(shader, shader.locs.offset(enums::ShaderLocationIndex::VectorView as isize).read(), camera_pos as *mut c_void, enums::ShaderUniformDataType::Ivec3 as c_int); // Check key inputs to enable/disable lights if IsKeyPressed(enums::KeyboardKey::R as i32) { lights[1].enabled = !lights[1].enabled; } if IsKeyPressed(enums::KeyboardKey::G as i32) { lights[2].enabled = !lights[2].enabled; } if IsKeyPressed(enums::KeyboardKey::B as i32) { lights[3].enabled = !lights[3].enabled; } if IsKeyPressed(enums::KeyboardKey::Y as i32) { lights[0].enabled = !lights[0].enabled; } // Update light values (actually, only enable/disable them) for i in 0 .. MAX_LIGHTS { update_light_values(shader, &lights[i]); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(colors::WHITE); BeginMode3D(camera); DrawModel(model, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, 1.0, colors::WHITE); DrawModel(cube, Vector3{ x: 0.0, y: 0.0, z: 0.0 }, 1.0, colors::WHITE); // Draw spheres to show where the lights are for i in 0 .. MAX_LIGHTS { if lights[i].enabled > 0 { DrawSphereEx(lights[i].position, 0.2, 8, 8, lights[i].color); } else { DrawSphereWires(lights[i].position, 0.2, 8, 8, ColorAlpha(lights[i].color, 0.3)); } } DrawGrid(10, 1.0); EndMode3D(); DrawFPS(10, 10); DrawText(rl_str!("Use keys [Y][R][G][B] to toggle lights"), 10, 40, 20, colors::DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(model); // Unload the model UnloadModel(cube); // Unload the model UnloadShader(shader); // Unload shader CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } }