| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- /* 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) ---
- }
|