/* r3d_lighting.odin -- R3D Lighting Module. * * Copyright (c) 2025-2026 Le Juez Victor * * This software is provided 'as-is', without any express or implied warranty. * For conditions of distribution and use, see accompanying LICENSE file. */ package r3d import rl "vendor:raylib" when ODIN_OS == .Windows { foreign import lib { "windows/libr3d.a", "system:raylib", "system:assimp", } } else when ODIN_OS == .Linux { foreign import lib { "linux/libr3d.a", "system:raylib", "system:assimp", } } else when ODIN_OS == .Darwin { foreign import lib { "darwin/libr3d.a", "system:raylib", "system:assimp", } } /** * @brief Types of lights supported by the rendering engine. * * Each light type has different behaviors and use cases. */ LightType :: enum u32 { DIR = 0, ///< Directional light, affects the entire scene with parallel rays. SPOT = 1, ///< Spot light, emits light in a cone shape. OMNI = 2, ///< Omni light, emits light in all directions from a single point. TYPE_COUNT = 3, } /** * @brief Modes for updating shadow maps. * * Determines how often the shadow maps are refreshed. */ ShadowUpdateMode :: enum u32 { MANUAL = 0, ///< Shadow maps update only when explicitly requested. INTERVAL = 1, ///< Shadow maps update at defined time intervals. CONTINUOUS = 2, ///< Shadow maps update every frame for real-time accuracy. } /** * @brief Unique identifier for an R3D light. * * ID type used to reference a light. * A negative value indicates an invalid light. */ Light :: i32 @(default_calling_convention="c", link_prefix="R3D_") foreign lib { /** * @brief Creates a new light of the specified type. * * This function creates a light of the given type. The light must be destroyed * manually when no longer needed by calling `R3D_DestroyLight`. * * @param type The type of light to create (directional, spot or omni-directional). * @return The ID of the created light. */ CreateLight :: proc(type: LightType) -> Light --- /** * @brief Destroys the specified light. * * This function deallocates the resources associated with the light and makes * the light ID invalid. It must be called after the light is no longer needed. * * @param id The ID of the light to destroy. */ DestroyLight :: proc(id: Light) --- /** * @brief Checks if a light exists. * * This function checks if the specified light ID is valid and if the light exists. * * @param id The ID of the light to check. * @return True if the light exists, false otherwise. */ IsLightExist :: proc(id: Light) -> bool --- /** * @brief Gets the type of a light. * * This function returns the type of the specified light (directional, spot or omni-directional). * * @param id The ID of the light. * @return The type of the light. */ GetLightType :: proc(id: Light) -> LightType --- /** * @brief Checks if a light is active. * * This function checks whether the specified light is currently active (enabled or disabled). * * @param id The ID of the light to check. * @return True if the light is active, false otherwise. */ IsLightActive :: proc(id: Light) -> bool --- /** * @brief Toggles the state of a light (active or inactive). * * This function toggles the state of the specified light, turning it on if it is off, * or off if it is on. * * @param id The ID of the light to toggle. */ ToggleLight :: proc(id: Light) --- /** * @brief Sets the active state of a light. * * This function allows manually turning a light on or off by specifying its active state. * * @param id The ID of the light to set the active state for. * @param active True to activate the light, false to deactivate it. */ SetLightActive :: proc(id: Light, active: bool) --- /** * @brief Gets the color of a light. * * This function retrieves the color of the specified light as a `rl.Color` structure. * * @param id The ID of the light. * @return The color of the light as a `rl.Color` structure. */ GetLightColor :: proc(id: Light) -> rl.Color --- /** * @brief Gets the color of a light as a `rl.Vector3`. * * This function retrieves the color of the specified light as a `rl.Vector3`, where each * component (x, y, z) represents the RGB values of the light. * * @param id The ID of the light. * @return The color of the light as a `rl.Vector3`. */ GetLightColorV :: proc(id: Light) -> rl.Vector3 --- /** * @brief Sets the color of a light. * * This function sets the color of the specified light using a `rl.Color` structure. * * @param id The ID of the light. * @param color The new color to set for the light. */ SetLightColor :: proc(id: Light, color: rl.Color) --- /** * @brief Sets the color of a light using a `rl.Vector3`. * * This function sets the color of the specified light using a `rl.Vector3`, where each * component (x, y, z) represents the RGB values of the light. * * @param id The ID of the light. * @param color The new color to set for the light as a `rl.Vector3`. */ SetLightColorV :: proc(id: Light, color: rl.Vector3) --- /** * @brief Gets the position of a light. * * This function retrieves the position of the specified light. * Only applicable to spot lights or omni-lights. * * @param id The ID of the light. * @return The position of the light as a `rl.Vector3`. */ GetLightPosition :: proc(id: Light) -> rl.Vector3 --- /** * @brief Sets the position of a light. * * This function sets the position of the specified light. * Only applicable to spot lights or omni-lights. * * @note Has no effect for directional lights. * If called on a directional light, * a warning will be logged. * * @param id The ID of the light. * @param position The new position to set for the light. */ SetLightPosition :: proc(id: Light, position: rl.Vector3) --- /** * @brief Gets the direction of a light. * * This function retrieves the direction of the specified light. * Only applicable to directional lights or spot lights. * * @param id The ID of the light. * @return The direction of the light as a `rl.Vector3`. */ GetLightDirection :: proc(id: Light) -> rl.Vector3 --- /** * @brief Sets the direction of a light. * * This function sets the direction of the specified light. * Only applicable to directional lights or spot lights. * * @note Has no effect for omni-directional lights. * If called on an omni-directional light, * a warning will be logged. * * @param id The ID of the light. * @param direction The new direction to set for the light. * The vector is automatically normalized. */ SetLightDirection :: proc(id: Light, direction: rl.Vector3) --- /** * @brief Sets the position and direction of a light to look at a target point. * * This function sets both the position and the direction of the specified light, * causing it to "look at" a given target point. * * @note - For directional lights, only the direction is updated (position is ignored). * - For omni-directional lights, only the position is updated (direction is not calculated). * - For spot lights, both position and direction are set accordingly. * - This function does **not** emit any warning or log message. * * @param id The ID of the light. * @param position The position to set for the light. * @param target The point the light should look at. */ LightLookAt :: proc(id: Light, position: rl.Vector3, target: rl.Vector3) --- /** * @brief Gets the energy level of a light. * * This function retrieves the energy level (intensity) of the specified light. * Energy typically affects the brightness of the light. * * @param id The ID of the light. * @return The energy level of the light. */ GetLightEnergy :: proc(id: Light) -> f32 --- /** * @brief Sets the energy level of a light. * * This function sets the energy (intensity) of the specified light. * A higher energy value will result in a brighter light. * * @param id The ID of the light. * @param energy The new energy value to set for the light. */ SetLightEnergy :: proc(id: Light, energy: f32) --- /** * @brief Gets the specular intensity of a light. * * This function retrieves the current specular intensity of the specified light. * Specular intensity affects how shiny surfaces appear when reflecting the light. * * @param id The ID of the light. * @return The current specular intensity of the light. */ GetLightSpecular :: proc(id: Light) -> f32 --- /** * @brief Sets the specular intensity of a light. * * This function sets the specular intensity of the specified light. * Higher specular values result in stronger and sharper highlights on reflective surfaces. * * @param id The ID of the light. * @param specular The new specular intensity value to set for the light. */ SetLightSpecular :: proc(id: Light, specular: f32) --- /** * @brief Gets the range of a light. * * This function retrieves the range of the specified light, which determines how far the light can affect. * Only applicable to spot lights or omni-lights. * * @param id The ID of the light. * @return The range of the light. */ GetLightRange :: proc(id: Light) -> f32 --- /** * @brief Sets the range parameter of a light. * * For spot and omni lights, this defines the maximum illumination distance. * For directional lights, this defines the shadow rendering radius around the camera. * * @param id The ID of the light. * @param range The range value to apply. */ SetLightRange :: proc(id: Light, range: f32) --- /** * @brief Gets the attenuation factor of a light. * * This function retrieves the attenuation factor of the specified light. * Attenuation controls how the intensity of a light decreases with distance. * Only applicable to spot lights or omni-lights. * * @param id The ID of the light. * @return The attenuation factor of the light. */ GetLightAttenuation :: proc(id: Light) -> f32 --- /** * @brief Sets the attenuation factor of a light. * * This function sets the attenuation factor of the specified light. * A higher attenuation value causes the light to lose intensity more quickly as the distance increases. * For a realistic effect, an attenuation factor of 2.0f is typically used. * Only applicable to spot lights or omni-lights. * * @param id The ID of the light. * @param attenuation The new attenuation factor to set for the light. */ SetLightAttenuation :: proc(id: Light, attenuation: f32) --- /** * @brief Gets the inner cutoff angle of a spotlight. * * This function retrieves the inner cutoff angle of a spotlight. * The inner cutoff defines the cone of light where the light is at full intensity. * * @param id The ID of the light. * @return The inner cutoff angle in degrees of the spotlight. */ GetLightInnerCutOff :: proc(id: Light) -> f32 --- /** * @brief Sets the inner cutoff angle of a spotlight. * * This function sets the inner cutoff angle of a spotlight. * The inner cutoff angle defines the cone where the light is at full intensity. * Anything outside this cone starts to fade. * * @param id The ID of the light. * @param degrees The new inner cutoff angle in degrees. */ SetLightInnerCutOff :: proc(id: Light, degrees: f32) --- /** * @brief Gets the outer cutoff angle of a spotlight. * * This function retrieves the outer cutoff angle of a spotlight. * The outer cutoff defines the outer boundary of the light's cone, where the light starts to fade. * * @param id The ID of the light. * @return The outer cutoff angle in degrees of the spotlight. */ GetLightOuterCutOff :: proc(id: Light) -> f32 --- /** * @brief Sets the outer cutoff angle of a spotlight. * * This function sets the outer cutoff angle of a spotlight. * The outer cutoff defines the boundary of the light's cone where the light intensity starts to gradually decrease. * * @param id The ID of the light. * @param degrees The new outer cutoff angle in degrees. */ SetLightOuterCutOff :: proc(id: Light, degrees: f32) --- /** * @brief Enables shadow rendering for a light. * * Turns on shadow rendering for the light. The engine will allocate a shadow * map if needed, or reuse one previously allocated for another light. * * Shadow map resolutions are fixed: 2048x2048 for spot and point lights, * and 4096x4096 for directional lights. * * @param id The ID of the light. * * @note Creating too many shadow-casting lights can exhaust GPU memory and * potentially crash the graphics driver. Disabling shadows on one light and * enabling them on another is free, since existing shadow maps are reused. */ EnableShadow :: proc(id: Light) --- /** * @brief Disables shadow rendering for a light. * * Turns off shadow rendering for the light. The associated shadow map is * kept in memory and may later be reused by another light. * * @param id The ID of the light. */ DisableShadow :: proc(id: Light) --- /** * @brief Checks if shadow casting is enabled for a light. * * This function checks if shadow casting is currently enabled for the specified light. * * @param id The ID of the light. * @return True if shadow casting is enabled, false otherwise. */ IsShadowEnabled :: proc(id: Light) -> bool --- /** * @brief Gets the shadow map update mode of a light. * * This function retrieves the current mode for updating the shadow map of a light. The mode can be: * - Interval: Updates the shadow map at a fixed interval. * - Continuous: Updates the shadow map continuously. * - Manual: Updates the shadow map manually (via explicit function calls). * * @param id The ID of the light. * @return The shadow map update mode. */ GetShadowUpdateMode :: proc(id: Light) -> ShadowUpdateMode --- /** * @brief Sets the shadow map update mode of a light. * * This function sets the mode for updating the shadow map of the specified light. * The update mode controls when and how often the shadow map is refreshed. * * @param id The ID of the light. * @param mode The update mode to set for the shadow map (Interval, Continuous, or Manual). */ SetShadowUpdateMode :: proc(id: Light, mode: ShadowUpdateMode) --- /** * @brief Gets the frequency of shadow map updates for the interval update mode. * * This function retrieves the frequency (in milliseconds) at which the shadow map should be updated when * the interval update mode is enabled. This function is only relevant if the shadow map update mode is set * to "Interval". * * @param id The ID of the light. * @return The frequency in milliseconds at which the shadow map is updated. */ GetShadowUpdateFrequency :: proc(id: Light) -> i32 --- /** * @brief Sets the frequency of shadow map updates for the interval update mode. * * This function sets the frequency (in milliseconds) at which the shadow map should be updated when * the interval update mode is enabled. This function is only relevant if the shadow map update mode is set * to "Interval". * * @param id The ID of the light. * @param msec The frequency in milliseconds at which to update the shadow map. */ SetShadowUpdateFrequency :: proc(id: Light, msec: i32) --- /** * @brief Forces an immediate update of the shadow map during the next rendering pass. * * This function forces the shadow map of the specified light to be updated during the next call to `R3D_End`. * This is primarily used for the manual update mode, but may also work for the interval mode. * * @param id The ID of the light. */ UpdateShadowMap :: proc(id: Light) --- /** * @brief Retrieves the softness radius used to simulate penumbra in shadows. * * The softness is expressed as a sampling radius in texels within the shadow map. * * @param id The ID of the light. * @return The softness radius in texels currently set for the shadow. */ GetShadowSoftness :: proc(id: Light) -> f32 --- /** * @brief Sets the softness radius used to simulate penumbra in shadows. * * This function adjusts the softness of the shadow edges for the specified light. * The softness value corresponds to a number of texels in the shadow map, independent * of its resolution. Larger values increase the blur radius, resulting in softer, * more diffuse shadows, while smaller values yield sharper shadows. * * @param id The ID of the light. * @param softness The softness radius in texels to apply (must be >= 0). * * @note The softness must be set only after shadows have been enabled for the light, * since the shadow map resolution must be known before the softness can be applied. */ SetShadowSoftness :: proc(id: Light, softness: f32) --- /** * @brief Gets the shadow depth bias value. */ GetShadowDepthBias :: proc(id: Light) -> f32 --- /** * @brief Sets the shadow depth bias value. * * A higher bias helps reduce "shadow acne" artifacts * (shadows flickering or appearing misaligned on surfaces). * Be careful: too large values may cause shadows to look detached * or floating away from objects. */ SetShadowDepthBias :: proc(id: Light, value: f32) --- /** * @brief Gets the shadow slope bias value. */ GetShadowSlopeBias :: proc(id: Light) -> f32 --- /** * @brief Sets the shadow slope bias value. * * This bias mainly compensates artifacts on surfaces angled * relative to the light. It helps prevent shadows from * incorrectly appearing or disappearing along object edges. */ SetShadowSlopeBias :: proc(id: Light, value: f32) --- /** * @brief Returns the bounding box encompassing the light's area of influence. * * This function computes the axis-aligned bounding box (AABB) that encloses the * volume affected by the specified light, based on its type: * * - For spotlights, the bounding box encloses the light cone. * - For omni-directional lights, it encloses a sphere representing the light's range. * - For directional lights, it returns an infinite bounding box to represent global influence. * * This bounding box is primarily useful for spatial partitioning, culling, or visual debugging. * * @param light The light for which to compute the bounding box. * * @return A rl.BoundingBox struct that encloses the light's influence volume. */ GetLightBoundingBox :: proc(light: Light) -> rl.BoundingBox --- /** * @brief Draws the area of influence of the light in 3D space. * * This function visualizes the area affected by a light in 3D space. * It draws the light's influence, such as the cone for spotlights or the volume for omni-lights. * This function is only relevant for spotlights and omni-lights. * * @note This function should be called while using the default 3D rendering mode of raylib, * not with R3D's rendering mode. It uses raylib's 3D drawing functions to render the light's shape. * * @param id The ID of the light. */ DrawLightShape :: proc(id: Light) --- }