forked from DaemonEngine/Daemon
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMaterial.h
More file actions
484 lines (377 loc) · 14.1 KB
/
Copy pathMaterial.h
File metadata and controls
484 lines (377 loc) · 14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2024 Daemon Developers
All rights reserved.
This file is part of the Daemon BSD Source Code (Daemon Source Code).
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Daemon developers nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
// Material.h
#ifndef MATERIAL_H
#define MATERIAL_H
#include <vector>
#include "gl_shader.h"
#include "tr_local.h"
#include "GLMemory.h"
static constexpr uint32_t MAX_DRAWCOMMAND_TEXTURES = 64;
extern Cvar::Cvar<bool> r_materialSeparatePerShader;
struct GLIndirectCommand {
GLuint count;
GLuint instanceCount;
GLuint firstIndex;
GLint baseVertex;
GLuint baseInstance;
};
/* Similar to GLIndirectCommand, but we always set instanceCount to 1 and baseVertex to 0,
so no need to waste memory on those */
struct IndirectCompactCommand {
GLuint count;
GLuint firstIndex;
GLuint baseInstance;
};
struct DrawCommand {
IndirectCompactCommand cmd;
uint32_t materialsSSBOOffset = 0;
uint32_t textureCount = 0;
DrawCommand() {
}
DrawCommand( const DrawCommand& other ) {
cmd = other.cmd;
materialsSSBOOffset = other.materialsSSBOOffset;
textureCount = other.textureCount;
}
};
struct MaterialSurface {
shader_t* shader;
surfaceType_t* surface;
bool bspSurface;
bool skyBrush;
int16_t lightMapNum;
int portalNum = -1;
GLuint firstIndex;
GLuint count;
vec3_t origin;
float radius;
srfVert_t* verts;
srfTriangle_t* tris;
uint32_t materialPackIDs[MAX_SHADER_STAGES];
uint32_t materialIDs[MAX_SHADER_STAGES];
uint32_t texDataIDs[MAX_SHADER_STAGES];
bool texDataDynamic[MAX_SHADER_STAGES];
uint32_t shaderVariant[MAX_SHADER_STAGES];
uint8_t stages = 0;
shaderStage_t* shaderStages[MAX_SHADER_STAGES];
};
struct Material {
uint32_t globalID = 0;
uint32_t surfaceCommandBatchOffset = 0;
uint32_t surfaceCommandBatchCount = 0;
uint32_t surfaceCommandBatchPadding = 0;
uint32_t id = 0;
bool useSync = false;
uint32_t syncMaterial = 0; // Must not be drawn before the material with this id
uint32_t stateBits = 0;
stageShaderBinder_t shaderBinder;
GLuint program = 0;
GLShader* shader;
// Used only for glsl_restart
shaderStage_t* refStage;
MaterialSurface refDrawSurf;
int deformIndex;
bool tcGenEnvironment;
bool tcGen_Lightmap;
bool alphaGenPortal;
bool hasDepthFade;
bool bspSurface;
bool enableDeluxeMapping;
bool enableGridLighting;
bool enableGridDeluxeMapping;
bool hasHeightMapInNormalMap;
bool enableReliefMapping;
bool enableNormalMapping;
bool enableSpecularMapping;
bool enablePhysicalMapping;
cullType_t cullType;
uint32_t sort;
bool usePolygonOffset = false;
uint32_t drawCommandCount = 0;
bool texturesResident = false;
std::vector<Texture*> textures;
bool operator==( const Material& other ) {
return program == other.program && stateBits == other.stateBits
&& cullType == other.cullType && usePolygonOffset == other.usePolygonOffset;
}
void AddTexture( Texture* texture ) {
if ( !texture->hasBindlessHandle ) {
texture->GenBindlessHandle();
}
if ( std::find( textures.begin(), textures.end(), texture ) == textures.end() ) {
textures.emplace_back( texture );
}
}
};
struct TexBundle {
vec_t textureMatrix[6];
GLuint64 textures[MAX_TEXTURE_BUNDLES];
};
struct TextureData {
const textureBundle_t* texBundles[MAX_TEXTURE_BUNDLES] = { nullptr, nullptr, nullptr, nullptr, nullptr };
// For ST_STYLELIGHTMAP stages
image_t* texBundlesOverride[MAX_TEXTURE_BUNDLES] = { nullptr, nullptr, nullptr, nullptr, nullptr };
int textureMatrixBundle = 0;
bool operator==( const TextureData& other ) const {
for ( int i = 0; i < MAX_TEXTURE_BUNDLES; i++ ) {
if ( texBundlesOverride[i] != other.texBundlesOverride[i] ) {
return false;
}
const textureBundle_t* bundle = texBundles[i];
const textureBundle_t* otherBundle = other.texBundles[i];
// Skip texBundles image check for ST_STYLELIGHTMAP
if ( !texBundlesOverride[i] ) {
if ( bundle->numImages != otherBundle->numImages ) {
return false;
}
if ( ( bundle->numImages > 1 ) && ( bundle->imageAnimationSpeed != otherBundle->imageAnimationSpeed ) ) {
return false;
}
const uint8_t numImages = bundle->numImages > 0 ? bundle->numImages : 1;
for ( int j = 0; j < numImages; j++ ) {
if ( bundle->image[j] != otherBundle->image[j] ) {
return false;
}
}
}
if ( bundle->numTexMods != otherBundle->numTexMods ) {
return false;
}
for ( size_t j = 0; j < bundle->numTexMods; j++ ) {
if ( bundle->texMods[j] != otherBundle->texMods[j] ) {
return false;
}
}
}
return true;
}
};
enum class MaterialDebugMode {
NONE,
DEPTH,
OPAQUE,
OPAQUE_TRANSPARENT
};
struct PortalSurface {
vec3_t origin;
float radius;
uint32_t drawSurfID;
float distance;
vec2_t padding;
};
struct PortalView {
uint32_t count;
drawSurf_t drawSurf;
uint32_t views[MAX_VIEWS];
};
extern PortalView portalStack[MAX_VIEWS];
#define MAX_SURFACE_COMMANDS 16
#define MAX_COMMAND_COUNTERS 64
#define SURFACE_COMMANDS_PER_BATCH 64
#define MAX_SURFACE_COMMAND_BATCHES 4096
#define BOUNDING_SPHERE_SIZE 4
#define INDIRECT_COMMAND_SIZE 5
#define SURFACE_COMMAND_SIZE 4
#define SURFACE_COMMAND_BATCH_SIZE 2
#define TEX_BUNDLE_SIZE 16
#define TEX_BUNDLE_BITS 12
#define LIGHTMAP_SIZE 4
#define LIGHTMAP_BITS 24
#define PORTAL_SURFACE_SIZE 8
// 64kb min
#define MIN_MATERIAL_UBO_SIZE BIT( 16 )
/* 64kb UBO : 54kb texBundles, 4kb lightmaps, 2kb map shader stages, 4kb entity shader stages
Current mapss use up to ~38kb at max, without models */
#define MAX_TEX_BUNDLES 54 * 1024 / 64
#define MAX_FRAMES 2
#define MAX_VIEWFRAMES MAX_VIEWS * MAX_FRAMES // Buffer 2 frames for each view
struct ViewFrame {
uint32_t viewID = 0;
uint32_t portalViews[MAX_VIEWS];
uint32_t viewCount;
vec3_t origin;
frustum_t frustum;
uint32_t portalSurfaceID;
};
struct Frame {
uint32_t viewCount = 0;
ViewFrame viewFrames[MAX_VIEWS];
};
struct BoundingSphere {
vec3_t origin;
float radius;
};
struct SurfaceDescriptor {
BoundingSphere boundingSphere;
uint32_t surfaceCommandIDs[MAX_SURFACE_COMMANDS] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
};
struct SurfaceCommand {
uint32_t enabled; // uint because bool in GLSL is always 4 bytes
IndirectCompactCommand drawCommand;
};
struct SurfaceCommandBatch {
uint32_t materialIDs[2] { 0, 0 };
};
class MaterialSystem {
public:
friend class ListMaterialsCmd;
friend class ListMaterialSystemStagesCmd;
vec3_t worldViewBounds[2];
uint8_t maxStages = 0;
uint32_t descriptorSize;
std::vector<DrawCommand> drawCommands;
std::vector<MaterialSurface> portalSurfaces;
std::vector<bspSurface_t*> autospriteSurfaces;
std::vector<PortalSurface> portalBounds;
uint32_t totalPortals;
std::vector<shader_t*> skyShaders;
bool buildOneShader = true;
std::vector<Material*> renderedMaterials;
/* MaterialPack is an abstraction to match a range of materials with the 3 different calls to RB_RenderDrawSurfaces()
with 3 different shaderSort_t ranges in RB_RenderView(). The 4th one that uses a different surface filter (DRAWSURFACES_NEAR_ENTITIES)
is ignored because it's never used for BSP surfaces. */
struct MaterialPack {
const shaderSort_t fromSort;
const shaderSort_t toSort;
std::vector<Material> materials;
MaterialPack( const shaderSort_t newFromSort, const shaderSort_t newToSort ) :
fromSort( newFromSort ),
toSort( newToSort ) {
}
};
MaterialPack materialPacks[3]{
{ shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH },
{ shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE },
{ shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS }
};
bool frameStart = false;
void AddPortalSurfaces();
void AddAutospriteSurfaces();
void RenderMaterials( const shaderSort_t fromSort, const shaderSort_t toSort, const uint32_t viewID );
void UpdateDynamicSurfaces();
void QueueSurfaceCull( const uint32_t viewID, const vec3_t origin, const frustum_t* frustum );
void DepthReduction();
void CullSurfaces();
void StartFrame();
void EndFrame();
void SetConstUniforms();
void SetFrameUniforms();
void GenerateDepthImages( const int width, const int height, imageParams_t imageParms );
void InitGLBuffers();
void FreeGLBuffers();
void BindBuffers();
uint32_t GetTexDataSize() const {
return texData.size();
}
void AddStageTextures( MaterialSurface* surface, shaderStage_t* pStage, const uint32_t stage, Material* material );
void AddStage( MaterialSurface* surface, shaderStage_t* pStage, uint32_t stage,
const bool vertexLit, const bool fullbright );
void ProcessStage( MaterialSurface* surface, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage,
uint32_t& previousMaterialID, bool skipStageSync = false );
void GenerateMaterial( MaterialSurface* surface );
void GenerateWorldMaterialsBuffer();
void GenerateWorldCommandBuffer( std::vector<MaterialSurface>& surfaces );
void GeneratePortalBoundingSpheres();
void SetWorldBounds( vec3_t bounds[2] );
void GenerateMaterialsBuffer( std::vector<shaderStage_t*>& stages, const uint32_t size, uint32_t* materialsData );
void GenerateTexturesBuffer( std::vector<TextureData>& textures, TexBundle* textureBundles );
void GLSLRestart();
void Free();
private:
bool PVSLocked = false;
frustum_t lockedFrustums[MAX_VIEWS];
vec3_t lockedOrigins[MAX_VIEWS];
image_t* lockedDepthImage;
matrix_t lockedViewMatrix;
uint32_t viewCount;
image_t* depthImage;
int depthImageLevels;
uint32_t surfaceCommandsCount = 0;
uint32_t surfaceDescriptorsCount = 0;
uint32_t totalBatchCount = 0;
uint32_t packIDs[3] = { 0, 0, 0 };
std::vector<shaderStage_t*> materialStages;
std::vector<shaderStage_t*> dynamicStages;
GLenum texDataBufferType;
GLuint texDataBindingPoint;
std::vector<TextureData> texData;
std::vector<TextureData> dynamicTexData;
uint32_t totalStageSize;
uint32_t dynamicStagesOffset = 0;
uint32_t dynamicStagesSize = 0;
uint32_t dynamicTexDataOffset = 0;
uint32_t dynamicTexDataSize = 0;
Frame frames[MAX_FRAMES];
uint32_t currentFrame = 0;
uint32_t nextFrame = 1;
bool AddPortalSurface( uint32_t viewID, PortalSurface* portalSurfs );
void RenderIndirect( const Material& material, const uint32_t viewID, const GLenum mode );
void RenderMaterial( Material& material, const uint32_t viewID );
void UpdateFrameData();
};
extern GLUBO materialsUBO; // Global
extern GLBuffer texDataBuffer; // Global
extern GLUBO lightMapDataUBO; // Global
extern GLSSBO surfaceDescriptorsSSBO; // Global
extern GLSSBO surfaceCommandsSSBO; // Per viewframe, GPU updated
extern GLBuffer culledCommandsBuffer; // Per viewframe
extern GLUBO surfaceBatchesUBO; // Global
extern GLBuffer atomicCommandCountersBuffer; // Per viewframe
extern GLSSBO portalSurfacesSSBO; // Per viewframe
extern GLSSBO debugSSBO; // Global
extern MaterialSystem materialSystem;
void UpdateSurfaceDataNONE( uint32_t*, shaderStage_t*, bool, bool );
void UpdateSurfaceDataNOP( uint32_t*, shaderStage_t*, bool, bool );
void UpdateSurfaceDataGeneric3D( uint32_t* materials, shaderStage_t* pStage, bool, bool );
void UpdateSurfaceDataLightMapping( uint32_t* materials, shaderStage_t* pStage, bool vertexLit, bool fullbright );
void UpdateSurfaceDataReflection( uint32_t* materials, shaderStage_t* pStage, bool, bool );
void UpdateSurfaceDataSkybox( uint32_t* materials, shaderStage_t* pStage, bool, bool );
void UpdateSurfaceDataScreen( uint32_t* materials, shaderStage_t* pStage, bool, bool );
void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage, bool, bool );
void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage, bool, bool );
void BindShaderNONE( Material* );
void BindShaderNOP( Material* );
void BindShaderGeneric3D( Material* material );
void BindShaderLightMapping( Material* material );
void BindShaderReflection( Material* material );
void BindShaderSkybox( Material* material );
void BindShaderScreen( Material* material );
void BindShaderHeatHaze( Material* material );
void BindShaderLiquid( Material* material );
void ProcessMaterialNONE( Material*, shaderStage_t*, MaterialSurface* );
void ProcessMaterialNOP( Material*, shaderStage_t*, MaterialSurface* );
void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ );
void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, MaterialSurface* surface );
void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ );
void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ );
void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ );
void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, MaterialSurface* surface );
void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ );
#endif // MATERIAL_H