6#include <zenkit/Archive.hh>
15using namespace Tempest;
18 return std::min(r, 2000.f);
27 std::swap(owner,other.owner);
28 std::swap(
id,other.id);
38 setPosition(Vec3(x,y,z));
44 auto& data = owner->lightSourceDesc[id];
47 auto& ssbo = owner->lightSourceData[id];
49 owner->markAsDurty(
id);
55 auto& data = owner->lightSourceDesc[id];
58 auto& ssbo = owner->lightSourceData[id];
60 owner->markAsDurty(
id);
66 auto& data = owner->lightSourceDesc[id];
69 auto& ssbo = owner->lightSourceData[id];
70 ssbo.range = data.isEnabled() ?
clampRange(r) : 0;
71 owner->markAsDurty(
id);
77 auto& data = owner->lightSourceDesc[id];
80 auto& ssbo = owner->lightSourceData[id];
82 owner->markAsDurty(
id);
88 auto& data = owner->lightSourceDesc[id];
89 data.setColor(c,fps,smooth);
91 auto& ssbo = owner->lightSourceData[id];
92 ssbo.color = data.currentColor();
93 owner->markAsDurty(
id);
99 auto& data = owner->lightSourceDesc[id];
100 data.setTimeOffset(t);
106 auto& data = owner->lightSourceDesc[id];
107 return data.effectPrefferedTime();
112 std::unique_ptr<zenkit::Read> read;
115 zenkit::ArchiveObject obj {};
116 auto count = zen->read_int();
117 for(
int i = 0; i < count; ++i) {
118 zen->read_object_begin(obj);
120 zenkit::LightPreset preset {};
121 preset.load(*zen,
Gothic::inst().version().game == 1 ? zenkit::GameVersion::GOTHIC_1
122 : zenkit::GameVersion::GOTHIC_2);
123 presets.emplace_back(std::move(preset));
125 if(!zen->read_object_end()) {
126 zen->skip_object(
true);
131 Log::e(
"unable to load Zen-file: \"LIGHTPRESETS.ZEN\"");
140 if(!vob.range_animation_scale.empty()) {
141 l.
setRange(vob.range_animation_scale,vob.range,vob.range_animation_fps,vob.range_animation_smooth);
146 if(!vob.color_animation_list.empty()) {
147 l.
setColor(vob.color_animation_list,vob.color_animation_fps,vob.color_animation_smooth);
149 l.
setColor(Vec3(vob.color.r / 255.f, vob.color.g / 255.f, vob.color.b / 255.f));
152 std::lock_guard<std::mutex> guard(sync);
154 auto lx =
Light(*
this,
id);
156 auto& ssbo = lightSourceData[lx.id];
159 ssbo.color = l.
color();
161 auto& data = lightSourceDesc[lx.id];
164 markAsDurtyNoSync(lx.id);
169 auto l =
add(
static_cast<const zenkit::LightPreset&
>(vob));
170 l.setPosition(Vec3(vob.position.x,vob.position.y,vob.position.z));
175 return add(findPreset(preset));
179 static bool ddraw=
false;
184 p.
setPen(Color(1,0,0,1.f));
186 for(
auto& i:lightSourceDesc) {
187 auto pt = i.position();
191 p.
drawLine(pt-Vec3(l,0,0),pt+Vec3(l,0,0));
192 p.
drawLine(pt-Vec3(0,l,0),pt+Vec3(0,l,0));
193 p.
drawLine(pt-Vec3(0,0,l),pt+Vec3(0,0,l));
245 string_frm name(
"light count = ", lightSourceDesc.size());
249size_t LightGroup::alloc(
bool dynamic) {
250 if(freeList.size()>0) {
251 auto ret = freeList.back();
254 animatedLights.insert(ret);
255 markAsDurtyNoSync(ret);
258 lightSourceData.emplace_back();
259 lightSourceDesc.emplace_back();
260 duryBit.resize((lightSourceData.size()+32u-1u)/32u);
262 auto ret = lightSourceData.size()-1;
264 animatedLights.insert(ret);
265 markAsDurtyNoSync(ret);
269void LightGroup::free(
size_t id) {
270 std::lock_guard<std::mutex> guard(sync);
271 markAsDurtyNoSync(
id);
272 animatedLights.erase(
id);
273 if(
id+1==lightSourceData.size()) {
274 lightSourceData.pop_back();
275 lightSourceDesc.pop_back();
276 duryBit.resize((lightSourceData.size()+32u-1u)/32u);
278 lightSourceDesc[id].setRange(0);
279 lightSourceData[id] = LightSsbo();
280 freeList.push_back(
id);
284void LightGroup::markAsDurty(
size_t id) {
285 std::lock_guard<std::mutex> guard(sync);
286 markAsDurtyNoSync(
id);
289void LightGroup::markAsDurtyNoSync(
size_t id) {
290 duryBit[
id/32] |= (1u << (
id%32));
293void LightGroup::resetDurty() {
294 std::memset(duryBit.data(), 0, duryBit.size()*
sizeof(duryBit[0]));
297const zenkit::LightPreset& LightGroup::findPreset(std::string_view preset)
const {
298 for(
auto& i:presets) {
303 Log::e(
"unknown light preset: \"",preset,
"\"");
304 static zenkit::LightPreset zero {};
309 for(
size_t i : animatedLights) {
310 auto& light = lightSourceDesc[i];
314 ssbo.pos = light.position();
315 ssbo.color = light.currentColor();
316 ssbo.range = light.isEnabled() ?
clampRange(light.currentRange()) : 0;
318 auto& dst = lightSourceData[i];
319 if(std::memcmp(&dst, &ssbo,
sizeof(ssbo))==0)
322 markAsDurtyNoSync(i);
329 if(lightSourceSsbo.byteSize()<lightSourceData.size()*
sizeof(LightSsbo)) {
331 lightSourceSsbo = device.ssbo(lightSourceData);
339 std::vector<Path> patchBlock;
340 std::vector<LightSsbo> patchData;
342 for(
size_t i=0; i<lightSourceDesc.size(); ++i) {
343 if(i%32==0 && duryBit[i/32]==0) {
347 if((duryBit[i/32] & (1u<<i%32))==0)
350 patchData.push_back(lightSourceData[i]);
354 p.src = uint32_t(patchData.size()-1);
356 if(patchBlock.size()>0) {
357 auto& b = patchBlock.back();
358 const uint32_t maxBlockSize = 16;
359 if(b.dst+b.size==p.dst && b.size<maxBlockSize) {
364 patchBlock.push_back(p);
367 if(patchBlock.empty())
371 const size_t headerSize = patchBlock.size()*
sizeof(Path);
372 const size_t dataSize = patchData .size()*
sizeof(LightSsbo);
373 for(
auto& i:patchBlock) {
374 i.dst *= uint32_t(
sizeof(LightSsbo));
375 i.src *= uint32_t(
sizeof(LightSsbo));
376 i.size *= uint32_t(
sizeof(LightSsbo));
378 i.src += uint32_t(headerSize);
381 i.dst /=
sizeof(uint32_t);
382 i.src /=
sizeof(uint32_t);
383 i.size /=
sizeof(uint32_t);
387 auto& patch = patchSsbo[fId];
388 if(patch.byteSize()<headerSize+dataSize) {
390 patch = device.ssbo(Tempest::BufferHeap::Upload, Tempest::Uninitialized, headerSize+dataSize);
392 patch.update(patchBlock.data(), 0, headerSize);
393 patch.update(patchData.data(), headerSize, dataSize);
395 cmd.setFramebuffer({});
396 cmd.setBinding(0, lightSourceSsbo);
397 cmd.setBinding(1, patch);
399 cmd.dispatch(patchBlock.size());
void drawText(int x, int y, std::string_view txt)
void drawLine(const Tempest::Vec3 &a, const Tempest::Vec3 &b)
void setPen(const Tempest::Pen &pen)
uint64_t effectPrefferedTime() const
Light & operator=(Light &&other)
void setColor(const Tempest::Vec3 &c)
void setTimeOffset(uint64_t t)
void setPosition(float x, float y, float z)
Light add(const zenkit::LightPreset &vob)
void prepareGlobals(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
LightGroup(const SceneGlobals &scene)
void dbgLights(DbgPainter &p) const
void setDebugName(std::string_view hint)
const Tempest::Vec3 & position() const
const Tempest::Vec3 & color() const
void setColor(const Tempest::Vec3 &cl)
void setPosition(const Tempest::Vec3 &p)
static auto openReader(std::string_view name, std::unique_ptr< zenkit::Read > &read) -> std::unique_ptr< zenkit::ReadArchive >
static Tempest::Device & device()
static void recycle(Tempest::DescriptorArray &&arr)
static float clampRange(float r)