diff --git a/docs/opengl46-renderer.md b/docs/opengl46-renderer.md index 4589e56f..52ed7793 100644 --- a/docs/opengl46-renderer.md +++ b/docs/opengl46-renderer.md @@ -180,6 +180,9 @@ scales can also be changed in the **Light clusters** debug window. shines always). Their colour, power, cone and the optional `Radius:`/`SoftFalloff:`/`CastShadows:` are those of the light point (brightness `gfx.lights.freespot.intensity`, the self-illumination threshold doesn't matter), and they fade in the daylight as the cab lamp does. The dimming of the cab lamp applies only to the lamp under the top. +- **`LightOnly: true`** (an optional entry of any `FreeSpotLight`, after `HotspotAngle:` with the others; in e3d the flag 0x8 + after the radius) makes the light point only a light: it lights its surroundings, but its glowing point and its glare, + seen from afar, aren't drawn. For lights hidden in fittings, the backlight of a desk and the like. The lamps of models and compartments fade in from the light level at which scenery lamps switch on (`ls_Dark`) to full darkness; in daylight they are not gathered at all. The cab lamp and the lamps of scenery models nearest to the camera cast diff --git a/model/Model3d.cpp b/model/Model3d.cpp index 983fc7ae..90875b6c 100644 --- a/model/Model3d.cpp +++ b/model/Model3d.cpp @@ -227,6 +227,7 @@ inline void readMatrix(cParser &parser, float4x4 &matrix) static constexpr std::uint32_t E3D_LIGHT_SHADESELF{0x1}; static constexpr std::uint32_t E3D_LIGHT_NOSHADOWS{0x2}; static constexpr std::uint32_t E3D_LIGHT_SOFTFALLOFF{0x4}; +static constexpr std::uint32_t E3D_LIGHT_LIGHTONLY{0x8}; // a light point whose cone takes the whole sphere (FalloffAngle 360) is a point light: it shines and is seen all around static void point_light_cones(float &Falloff, float &Hotspot) @@ -377,7 +378,7 @@ std::pair TSubModel::Load(cParser &parser, bool dynamic) >> discard >> fCosHotspotAngle; // kąt liczony dla średnicy, a nie promienia // opcjonalne parametry, każdy to nazwa i wartość, w dowolnej kolejności: natężenie światła w procentach (hotspotpower:), // promień kuli świecącej (radius:), cienie od własnego modelu (shadeself:), rzucanie cieni (castshadows:), spadek natężenia - // jak przy soft falloff blendera (softfalloff:). trzeba pobrać do kolejki 2 tokeny; jeśli to nie żaden z nich, zostają w + // jak przy soft falloff blendera (softfalloff:), samo oświetlenie bez punktu i poświaty (lightonly:). trzeba pobrać do kolejki 2 tokeny; jeśli to nie żaden z nich, zostają w // kolejce dla odczytu zasięgu widoczności, który przywraca autoclear while (true) { @@ -421,6 +422,10 @@ std::pair TSubModel::Load(cParser &parser, bool dynamic) { parser >> discard >> bSoftFalloff; } + else if (key == "lightonly:") + { + parser >> discard >> bLightOnly; + } else { parser.autoclear(false); @@ -1976,7 +1981,7 @@ void TSubModel::serialize(std::ostream &s, std::vector &models, std sn_utils::ls_float32(s, fHotspotPower); // the optional parameters of light points. the zeros of the fill of older files are their defaults sn_utils::ls_float32(s, fLightRadius); - sn_utils::ls_uint32(s, (bShadeSelf ? E3D_LIGHT_SHADESELF : 0u) | (bCastShadows ? 0u : E3D_LIGHT_NOSHADOWS) | (bSoftFalloff ? E3D_LIGHT_SOFTFALLOFF : 0u)); + sn_utils::ls_uint32(s, (bShadeSelf ? E3D_LIGHT_SHADESELF : 0u) | (bCastShadows ? 0u : E3D_LIGHT_NOSHADOWS) | (bSoftFalloff ? E3D_LIGHT_SOFTFALLOFF : 0u) | (bLightOnly ? E3D_LIGHT_LIGHTONLY : 0u)); // fill empty space size_t fill = end - s.tellp(); @@ -2164,6 +2169,7 @@ void TSubModel::deserialize(std::istream &s) bShadeSelf = (lightflags & E3D_LIGHT_SHADESELF) != 0; bCastShadows = (lightflags & E3D_LIGHT_NOSHADOWS) == 0; bSoftFalloff = (lightflags & E3D_LIGHT_SOFTFALLOFF) != 0; + bLightOnly = (lightflags & E3D_LIGHT_LIGHTONLY) != 0; // necessary rotations were already done during t3d->e3d conversion m_rotation_init_done = true; diff --git a/model/Model3d.h b/model/Model3d.h index 3ce02236..d35f11e2 100644 --- a/model/Model3d.h +++ b/model/Model3d.h @@ -132,6 +132,7 @@ public: bool bShadeSelf { false }; // cienie światła rzuca także model, do którego ono należy (shadeself:) bool bCastShadows { true }; // światło rzuca cienie (castshadows:) bool bSoftFalloff { false }; // natężenie maleje jak 1 / (d^2 + r^2), jak przy soft falloff blendera, zamiast świecenia z powierzchni kuli (softfalloff:) + bool bLightOnly { false }; // tylko oświetlenie: bez świecącego punktu i poświaty, widocznych z daleka (lightonly:) float fCosViewAngle { 0.0f }; // cos kata pod jakim sie teraz patrzy bool m_rotation_init_done = false; diff --git a/rendering/common/scenewalk.cpp b/rendering/common/scenewalk.cpp index d73341bc..e2266e9f 100644 --- a/rendering/common/scenewalk.cpp +++ b/rendering/common/scenewalk.cpp @@ -3073,8 +3073,9 @@ void scene_walk::Render_Alpha(TSubModel *Submodel) } } } - else if (Submodel->eType == TP_FREESPOTLIGHT) + else if ((Submodel->eType == TP_FREESPOTLIGHT) && (false == Submodel->bLightOnly)) { + // the point of the light and its glare; a light point marked lightonly: only lights its surroundings (gfx::local_lights) // NOTE: we're forced here to redo view angle calculations etc, because this data isn't instanced but stored along with the single mesh // TODO: separate instance data from reusable geometry auto const &modelview = OpenGLMatrices.data(GL_MODELVIEW);