OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
sceneglobals.cpp
Go to the documentation of this file.
1#include "sceneglobals.h"
2
3#include "graphics/shaders.h"
4#include "gothic.h"
5
6static uint32_t nextPot(uint32_t x) {
7 x--;
8 x |= x >> 1;
9 x |= x >> 2;
10 x |= x >> 4;
11 x |= x >> 8;
12 x |= x >> 16;
13 x++;
14 return x;
15 }
16
18 auto& device = Resources::device();
19
20 Gothic::inst().onSettingsChanged.bind(this,&SceneGlobals::initSettings);
21 initSettings();
22
23 uboGlobalCpu.sunDir=Tempest::Vec3::normalize({1,1,-1});
24 uboGlobalCpu.viewProject.identity();
25 uboGlobalCpu.viewProjectInv.identity();
26 for(auto& s:uboGlobalCpu.viewShadow)
27 s.identity();
28
29 for(auto& i:shadowMap)
31
32 vsmPageData = nullptr;
33 vsmPageTbl = nullptr;
34 vsmPageHiZ = nullptr;
35 vsmDbg = device.image2d(Tempest::TextureFormat::R32U, 64, 64);
36
37 for(uint8_t lay=0; lay<V_Count; ++lay) {
38 uboGlobal[lay] = device.ssbo(nullptr,sizeof(UboGlobal));
39 }
40
41 for(uint8_t fId=0; fId<Resources::MaxFramesInFlight; ++fId)
42 for(uint8_t lay=0; lay<V_Count; ++lay) {
43 uboGlobalPf[fId][lay] = device.ubo(UboGlobal());
44 }
45 }
46
48 Gothic::inst().onSettingsChanged.ubind(this,&SceneGlobals::initSettings);
49 }
50
52 switch (v) {
53 case V_Shadow0:
54 case V_Shadow1:
55 case V_Vsm:
56 return true;
57 case V_Main:
58 case V_HiZ:
59 case V_Count:
60 return false;
61 }
62 return false;
63 }
64
65void SceneGlobals::initSettings() {
66 zWindEnabled = Gothic::inst().settingsGetI("ENGINE","zWindEnabled")!=0;
67
68 float period = Gothic::inst().settingsGetF("ENGINE","zWindCycleTime");
69 float periodV = Gothic::inst().settingsGetF("ENGINE","zWindCycleTimeVar");
70 windPeriod = uint64_t((period+periodV)*1000.f);
71 if(windPeriod<=0) {
72 windPeriod = 1;
73 zWindEnabled = false;
74 }
75 }
76
77void SceneGlobals::setViewProject(const Tempest::Matrix4x4& v, const Tempest::Matrix4x4& p,
78 float zNear, float zFar,
79 const Tempest::Matrix4x4* sh) {
80 view = v;
81 proj = p;
82
83 auto vp = p;
84 vp.mul(v);
85
86 uboGlobalCpu.view = v;
87 uboGlobalCpu.project = p;
88 uboGlobalCpu.projectInv = p;
89 uboGlobalCpu.projectInv.inverse();
90 uboGlobalCpu.viewProject = vp;
91 uboGlobalCpu.viewProjectInv = vp;
92 uboGlobalCpu.viewProjectInv.inverse();
93 for(size_t i=0; i<Resources::ShadowLayers; ++i)
94 uboGlobalCpu.viewShadow[i] = sh[i];
95
96 uboGlobalCpu.clipInfo.x = zNear*zFar;
97 uboGlobalCpu.clipInfo.y = zNear-zFar;
98 uboGlobalCpu.clipInfo.z = zFar;
99 znear = zNear;
100
101 uboGlobalCpu.camPos = Tempest::Vec3(0);
102 auto viewInv = uboGlobalCpu.view;
103 viewInv.inverse();
104 viewInv.project(uboGlobalCpu.camPos);
105
106 Tempest::Vec3 min = {0,0.75,0}, max = {0, 0.75f, 0.9f};
107 auto inv = uboGlobalCpu.viewShadow[0]; inv.inverse();
108 inv.project(min);
109 inv.project(max);
110
111 uboGlobalCpu.viewShadow[1].project(min);
112 uboGlobalCpu.viewShadow[1].project(max);
113 uboGlobalCpu.closeupShadowSlice = Tempest::Vec2(min.z,max.z);
114
115 uboGlobalCpu.pfxLeft = Tempest::Vec3::normalize({vp.at(0,0), vp.at(1,0), vp.at(2,0)});
116 uboGlobalCpu.pfxTop = Tempest::Vec3::normalize({vp.at(0,1), vp.at(1,1), vp.at(2,1)});
117 uboGlobalCpu.pfxDepth = Tempest::Vec3::normalize({vp.at(0,2), vp.at(1,2), vp.at(2,2)});
118 }
119
120void SceneGlobals::setViewLwc(const Tempest::Matrix4x4& view, const Tempest::Matrix4x4& proj, const Tempest::Matrix4x4* sh) {
121 viewLwc = view;
122
123 auto m = proj;
124 m.mul(viewLwc);
125 m.inverse();
126 uboGlobalCpu.viewProjectLwcInv = m;
127 for(size_t i=0; i<Resources::ShadowLayers; ++i)
128 uboGlobalCpu.viewShadowLwc[i] = sh[i];
129 }
130
131void SceneGlobals::setViewVsm(const Tempest::Matrix4x4& view, const Tempest::Matrix4x4& viewLwc) {
132 uboGlobalCpu.viewVirtualShadow = view;
133 uboGlobalCpu.viewVirtualShadowLwc = viewLwc;
134
135 auto vsmMat = uboGlobalCpu.viewVirtualShadowLwc;
136 vsmMat.mul(uboGlobalCpu.viewProjectLwcInv);
137
138 //shPos += scene.viewVirtualShadowLwc * (scene.viewProjectLwcInv * vec4(off,0,0));
139 auto s = uboGlobalCpu.screenResInv*Tempest::Vec2(2);
140 uboGlobalCpu.vsmDdx = Tempest::Vec4(s.x, 0, 0,0);
141 uboGlobalCpu.vsmDdy = Tempest::Vec4( 0, s.y, 0,0);
142 vsmMat.project(uboGlobalCpu.vsmDdx);
143 vsmMat.project(uboGlobalCpu.vsmDdy);
144
145 uboGlobalCpu.viewProject2VirtualShadow = vsmMat;
146 }
147
148void SceneGlobals::setSky(const Sky& s) {
149 uboGlobalCpu.sunDir = s.sunLight().dir();
150 uboGlobalCpu.lightCl = s.sunLight().color();
151 uboGlobalCpu.GSunIntensity = s.sunIntensity();
152 uboGlobalCpu.lightAmb = s.ambientLight();
153 uboGlobalCpu.cloudsDir[0] = s.cloudsOffset(0);
154 uboGlobalCpu.cloudsDir[1] = s.cloudsOffset(1);
155 uboGlobalCpu.isNight = s.isNight();
156 uboGlobalCpu.exposure = 1;
157 }
158
160 float minY = wview.bbox().first.y;
161 Tempest::Vec3 plPos = Tempest::Vec3(0,0,0);
162 uboGlobalCpu.viewProjectInv.project(plPos);
163 uboGlobalCpu.plPosY = plPos.y/100.f; //meters
164 // NOTE: minZ is garbage in KoM
165 uboGlobalCpu.plPosY += (-minY)/100.f;
166 uboGlobalCpu.plPosY = std::clamp(uboGlobalCpu.plPosY, 0.f, 1000.f);
167 }
168
170 uboGlobalCpu.underWater = w ? 1 : 0;
171 }
172
173void SceneGlobals::setTime(uint64_t time) {
174 tickCount = time;
175 uboGlobalCpu.waveAnim = 2.f*float(M_PI)*float(tickCount%3000)/3000.f;
176 uboGlobalCpu.tickCount32 = uint32_t(tickCount);
177
178 if(zWindEnabled)
179 windDir = Tempest::Vec2(0.f,1.f)*1.f; else
180 windDir = Tempest::Vec2(0,0);
181 }
182
183void SceneGlobals::commitUbo(uint8_t fId) {
184 UboGlobal perView[V_Count];
185 uboGlobalPf[fId][V_Main].update(&uboGlobalCpu);
186
187 for(size_t i=V_Shadow0; i<V_Count; ++i) {
188 auto& ubo = perView[i];
189 ubo = uboGlobalCpu;
190 if(V_Shadow0<=i && i<=V_ShadowLast)
191 ubo.viewProject = uboGlobalCpu.viewShadow[i-V_Shadow0];
192 if(i==V_Vsm)
193 ubo.viewProject = uboGlobalCpu.viewVirtualShadow;
194 std::memcpy(ubo.frustrum, frustrum[i].f, sizeof(ubo.frustrum));
195 }
196
197 for(size_t i=0; i<V_Count; ++i) {
198 uboGlobalPf[fId][i].update(&perView[i]);
199 }
200 }
201
202void SceneGlobals::prepareGlobals(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t fId) {
203 static_assert(sizeof(UboGlobal)%sizeof(uint32_t)==0);
204
205 cmd.setDebugMarker("Update globals");
206 auto& pso = Shaders::inst().copyBuf;
207 for(uint8_t lay=0; lay<V_Count; ++lay) {
208 cmd.setBinding(0, uboGlobal[lay]);
209 cmd.setBinding(1, uboGlobalPf[fId][lay]);
210 cmd.setPipeline(pso);
211 cmd.dispatchThreads(sizeof(UboGlobal)/sizeof(uint32_t));
212 }
213 }
214
215void SceneGlobals::setResolution(uint32_t w, uint32_t h) {
216 if(w==0)
217 w = 1;
218 if(h==0)
219 h = 1;
220 uboGlobalCpu.screenResInv = Tempest::Vec2(1.f/float(w), 1.f/float(h));
221 uboGlobalCpu.screenRes = Tempest::Point(int(w),int(h));
222 if(hiZ!=nullptr && !hiZ->isEmpty()) {
223 uint32_t hw = nextPot(w);
224 uint32_t hh = nextPot(h);
225
226 uboGlobalCpu.hiZTileSize = Tempest::Point(int(hw)/hiZ->w(),int(hh)/hiZ->h());
227 }
228
229 uboGlobalCpu.probeGridBias = 4 + std::max(std::log2(float(w*h)/float(1920*1080)), 0.f);
230 }
231
232void SceneGlobals::setHiZ(const Tempest::Texture2d& t) {
233 hiZ = &t;
234 }
235
236void SceneGlobals::setShadowMap(const Tempest::Texture2d* tex[]) {
237 for(size_t i=0; i<Resources::ShadowLayers; ++i)
238 shadowMap[i] = tex[i];
239 }
240
242 const Tempest::ZBuffer& pageData,
243 const Tempest::StorageImage& pageTbl,
244 const Tempest::StorageImage& pageHiZ,
245 const Tempest::StorageBuffer& pageList) {
246 vsmEnabled = enabled;
247 if(enabled) {
248 vsmPageData = &Tempest::textureCast<const Tempest::Texture2d&>(pageData);
249 vsmPageTbl = &pageTbl;
250 vsmPageHiZ = &pageHiZ;
251 vsmPageList = &pageList;
252 } else {
253 vsmPageData = nullptr;
254 vsmPageTbl = nullptr;
255 vsmPageHiZ = nullptr;
256 vsmPageList = nullptr;
257 }
258 }
259
260const Tempest::Matrix4x4& SceneGlobals::viewProject() const {
261 return uboGlobalCpu.viewProject;
262 }
263
264const Tempest::Matrix4x4& SceneGlobals::viewProjectInv() const {
265 return uboGlobalCpu.viewProjectInv;
266 }
267
268const Tempest::Matrix4x4& SceneGlobals::viewShadow(uint8_t view) const {
269 return uboGlobalCpu.viewShadow[view];
270 }
271
272const Tempest::Vec3 SceneGlobals::clipInfo() const {
273 return uboGlobalCpu.clipInfo;
274 }
275
276const Tempest::Matrix4x4 SceneGlobals::viewProjectLwc() const {
277 auto m = proj;
278 m.mul(viewLwc);
279 return m;
280 }
281
282const Tempest::Matrix4x4 SceneGlobals::viewProjectLwcInv() const {
283 auto m = proj;
284 m.mul(viewLwc);
285 m.inverse();
286 return m;
287 }
float f[6][4]
Definition frustrum.h:22
Tempest::Signal< void()> onSettingsChanged
Definition gothic.h:182
static Gothic & inst()
Definition gothic.cpp:249
static int settingsGetI(std::string_view sec, std::string_view name)
Definition gothic.cpp:807
static float settingsGetF(std::string_view sec, std::string_view name)
Definition gothic.cpp:841
Tempest::Vec3 dir() const
Definition lightsource.h:12
const Tempest::Vec3 & color() const
Definition lightsource.h:16
@ MaxFramesInFlight
Definition resources.h:48
@ ShadowLayers
Definition resources.h:49
static Tempest::Device & device()
Definition resources.h:83
static const Tempest::Texture2d & fallbackBlack()
const Tempest::Matrix4x4 viewProjectLwcInv() const
uint64_t windPeriod
const Tempest::Matrix4x4 & viewShadow(uint8_t view) const
const Tempest::StorageBuffer * vsmPageList
const Tempest::Texture2d * shadowMap[2]
Tempest::Matrix4x4 proj
void setUnderWater(bool w)
Tempest::StorageImage vsmDbg
const Tempest::Matrix4x4 & viewProject() const
Tempest::UniformBuffer< UboGlobal > uboGlobalPf[Resources::MaxFramesInFlight][V_Count]
void setVirtualShadowMap(bool enabled, const Tempest::ZBuffer &vsmPageData, const Tempest::StorageImage &pageTbl, const Tempest::StorageImage &pageHiZ, const Tempest::StorageBuffer &vsmPageList)
void setViewProject(const Tempest::Matrix4x4 &view, const Tempest::Matrix4x4 &proj, float zNear, float zFar, const Tempest::Matrix4x4 *sh)
void setResolution(uint32_t w, uint32_t h)
Tempest::StorageBuffer uboGlobal[V_Count]
Frustrum frustrum[V_Count]
void setHiZ(const Tempest::Texture2d &hiZ)
Tempest::Matrix4x4 view
const Tempest::Texture2d * hiZ
void commitUbo(uint8_t fId)
const Tempest::StorageImage * vsmPageTbl
void setShadowMap(const Tempest::Texture2d *tex[])
void setViewLwc(const Tempest::Matrix4x4 &view, const Tempest::Matrix4x4 &proj, const Tempest::Matrix4x4 *sh)
const Tempest::Texture2d * vsmPageData
Tempest::Matrix4x4 viewLwc
static bool isShadowView(VisCamera v)
const Tempest::Matrix4x4 & viewProjectInv() const
uint64_t tickCount
void setSky(const Sky &s)
void prepareGlobals(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t frameId)
void setWorld(const WorldView &wview)
void setViewVsm(const Tempest::Matrix4x4 &view, const Tempest::Matrix4x4 &viewLwc)
const Tempest::StorageImage * vsmPageHiZ
const Tempest::Matrix4x4 viewProjectLwc() const
const Tempest::Vec3 clipInfo() const
void setTime(uint64_t time)
Tempest::Vec2 windDir
static Shaders & inst()
Definition shaders.cpp:39
Tempest::ComputePipeline copyBuf
Definition shaders.h:35
Definition sky.h:12
Tempest::Vec2 cloudsOffset(int layer) const
Definition sky.cpp:153
const Tempest::Vec3 & ambientLight() const
Definition sky.h:24
float sunIntensity() const
Definition sky.h:25
float isNight() const
Definition sky.cpp:80
const LightSource & sunLight() const
Definition sky.h:23
std::pair< Tempest::Vec3, Tempest::Vec3 > bbox() const
Definition worldview.cpp:30
static uint32_t nextPot(uint32_t x)
static uint32_t nextPot(uint32_t x)
Tempest::Matrix4x4 viewVirtualShadow
Tempest::Matrix4x4 viewShadowLwc[Resources::ShadowLayers]
Tempest::Matrix4x4 viewProjectInv
Tempest::Vec2 closeupShadowSlice
Tempest::Matrix4x4 viewShadow[Resources::ShadowLayers]
Tempest::Matrix4x4 viewProject2VirtualShadow
Tempest::Matrix4x4 view
Tempest::Matrix4x4 projectInv
Tempest::Matrix4x4 viewVirtualShadowLwc
Tempest::Vec2 screenResInv
Tempest::Vec2 cloudsDir[2]
Tempest::Matrix4x4 project
Tempest::Matrix4x4 viewProject
Tempest::Point screenRes
Tempest::Matrix4x4 viewProjectLwcInv
Tempest::Point hiZTileSize