// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #pragma once #include #include #include #include namespace anki { // Forward class Frustum; enum class LightComponentType : U8 { kPoint, kSpot, kDirectional, // Basically the sun. kCount, kFirst = 0 }; inline constexpr Array kLightComponentTypeNames = {"Point", "Spot", "Directional"}; // Light component. Contains all the info of lights. class LightComponent : public SceneComponent { ANKI_SCENE_COMPONENT(LightComponent) public: LightComponent(SceneNode* node); ~LightComponent(); void setLightComponentType(LightComponentType type); LightComponentType getLightComponentType() const { return m_type; } const Vec4& getDiffuseColor() const { return m_diffColor; } void setDiffuseColor(const Vec4& x) { m_diffColor = x; m_otherDirty = true; } F32 getLightPower() const { return m_diffColor.xyz.dot(Vec3(0.30f, 0.59f, 0.11f)); } void setRadius(F32 x) { m_point.m_radius = x; m_shapeDirty = true; } F32 getRadius() const { return m_point.m_radius; } void setDistance(F32 x) { m_spot.m_distance = x; m_shapeDirty = true; } F32 getDistance() const { return m_spot.m_distance; } void setInnerAngle(F32 ang) { m_spot.m_innerAngle = ang; m_shapeDirty = true; } F32 getInnerAngle() const { return m_spot.m_innerAngle; } void setOuterAngle(F32 ang) { m_spot.m_outerAngle = ang; m_shapeDirty = true; } F32 getOuterAngle() const { return m_spot.m_outerAngle; } Bool getShadowEnabled() const { return m_shadow; } void setShadowEnabled(const Bool x) { if(x != m_shadow) { m_shadow = x; m_shapeDirty = m_otherDirty = true; } } Vec3 getDirection() const { return -m_worldTransform.getRotation().getZAxis().xyz; } Vec3 getWorldPosition() const { return m_worldTransform.getOrigin().xyz; } const Mat4& getSpotLightViewProjectionMatrix() const { ANKI_ASSERT(m_type == LightComponentType::kSpot); return m_spot.m_viewProjMat; } const Mat3x4& getSpotLightViewMatrix() const { ANKI_ASSERT(m_type == LightComponentType::kSpot); return m_spot.m_viewMat; } // Set the direction of the directional light by setting the date and hour. void setDirectionFromTimeOfDay(I32 month, I32 day, F32 hour) { ANKI_EXPECT(month >= 0 && month < 12); ANKI_EXPECT(day >= 0 && day < 31); ANKI_EXPECT(hour >= 0.0f && hour <= 24.0f); m_dir.m_month = clamp(month, 0, 11); m_dir.m_day = clamp(day, 0, 30); m_dir.m_hour = clamp(hour, 0.0f, 24.0f); m_shapeDirty = true; } // Get the fields which might or might not have come from the direction of the light void getTimeOfDay(I32& month, I32& day, F32& hour) const { month = m_dir.m_month; day = m_dir.m_day; hour = m_dir.m_hour; } // Calculate some matrices for each cascade. For dir lights. // cameraFrustum Who is looking at the light. // cascadeDistances The distances of the cascades. // cascadeProjMats View projection matrices for each cascade. // cascadeViewMats View matrices for each cascade. Optional. void computeCascadeFrustums(const Frustum& cameraFrustum, ConstWeakArray cascadeDistances, WeakArray cascadeProjMats, WeakArray cascadeViewMats = {}, WeakArray> cascadePlanes = {}) const; ANKI_INTERNAL void setShadowAtlasUvViewports(ConstWeakArray viewports); const GpuSceneArrays::Light::Allocation& getGpuSceneLightAllocation() const { return m_gpuSceneLight; } private: Vec4 m_diffColor = Vec4(0.5f); Transform m_worldTransform = Transform::getIdentity(); class Point { public: F32 m_radius = 1.0f; }; class Spot { public: Mat3x4 m_viewMat = Mat3x4::getIdentity(); Mat4 m_viewProjMat = Mat4::getIdentity(); F32 m_distance = 1.0f; F32 m_outerAngle = toRad(30.0f); F32 m_innerAngle = toRad(15.0f); }; class Dir { public: I32 m_month = -1; I32 m_day = -1; F32 m_hour = -1.0; }; Point m_point; Spot m_spot; Dir m_dir; GpuSceneArrays::Light::Allocation m_gpuSceneLight; GpuSceneArrays::LightVisibleRenderablesHash::Allocation m_hash; Array m_shadowAtlasUvViewports; LightComponentType m_type; U8 m_shadow : 1 = false; U8 m_shapeDirty : 1 = true; U8 m_otherDirty : 1 = true; U8 m_shadowAtlasUvViewportCount : 3 = 0; void update(SceneComponentUpdateInfo& info, Bool& updated) override; Error serialize(SceneSerializer& serializer) override; }; } // end namespace anki