1
+ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O.
2
+ // This file is part of the "Nabla Engine".
3
+ // For conditions of distribution and use, see copyright notice in nabla.h
4
+
5
+ #define _NBL_STATIC_LIB_
6
+ #include < iostream>
7
+ #include < cstdio>
8
+ #include < nabla.h>
9
+
10
+ #include " ../common/QToQuitEventReceiver.h"
11
+ #include " nbl/ext/ScreenShot/ScreenShot.h"
12
+
13
+ using namespace nbl ;
14
+ using namespace core ;
15
+
16
+ // #define NBL_USE_STL_LOADER // Uncomment it to use STL loader, otherwise PLY will be in use
17
+
18
+ int main ()
19
+ {
20
+ nbl::SIrrlichtCreationParameters params;
21
+ params.Bits = 24 ;
22
+ params.ZBufferBits = 24 ;
23
+ params.DriverType = video::EDT_OPENGL;
24
+ params.WindowSize = dimension2d<uint32_t >(1280 , 720 );
25
+ params.Fullscreen = false ;
26
+ params.Vsync = true ;
27
+ params.Doublebuffer = true ;
28
+ params.Stencilbuffer = false ;
29
+ auto device = createDeviceEx (params);
30
+
31
+ if (!device)
32
+ return 1 ;
33
+
34
+ device->getCursorControl ()->setVisible (false );
35
+
36
+ QToQuitEventReceiver receiver;
37
+ device->setEventReceiver (&receiver);
38
+
39
+ auto * driver = device->getVideoDriver ();
40
+ auto * smgr = device->getSceneManager ();
41
+
42
+ auto loadAndGetCpuMesh = [&]() -> std::pair<core::smart_refctd_ptr<asset::ICPUMesh>, const asset::IAssetMetadata*>
43
+ {
44
+ auto * am = device->getAssetManager ();
45
+ auto * fs = am->getFileSystem ();
46
+
47
+ asset::IAssetLoader::SAssetLoadParams lp;
48
+
49
+ #ifdef NBL_USE_STL_LOADER
50
+ auto meshes_bundle = am->getAsset (" ../../media/extrusionLogo_TEST_fixed.stl" , lp);
51
+ #else
52
+ auto meshes_bundle = am->getAsset (" ../../media/ply/Industrial compressor.ply" , lp);
53
+ #endif // NBL_USE_STL_LOADER
54
+
55
+ assert (!meshes_bundle.getContents ().empty ());
56
+
57
+ return std::make_pair (core::smart_refctd_ptr_static_cast<asset::ICPUMesh>(meshes_bundle.getContents ().begin ()[0 ]), meshes_bundle.getMetadata ());
58
+ };
59
+
60
+ auto & cpuBundleData = loadAndGetCpuMesh ();
61
+ core::smart_refctd_ptr<asset::ICPUMesh> cpuMesh = cpuBundleData.first ;
62
+ auto metadata = cpuBundleData.second ->selfCast <const asset::CPLYMetadata>();
63
+
64
+ /*
65
+ For the testing puposes we can safely assume all meshbuffers within mesh loaded from PLY & STL has same DS1 layout (used for camera-specific data)
66
+ */
67
+
68
+ asset::ICPUMeshBuffer* const firstMeshBuffer = cpuMesh->getMeshBuffers ().begin ()[0 ];
69
+ asset::ICPUDescriptorSetLayout* ds1layout = firstMeshBuffer->getPipeline ()->getLayout ()->getDescriptorSetLayout (1u ); // ! DS1
70
+ const asset::IRenderpassIndependentPipelineMetadata* pipelineMetadata = metadata->getAssetSpecificMetadata (firstMeshBuffer->getPipeline ());
71
+
72
+ /*
73
+ So we can create just one DescriptorSet
74
+ */
75
+
76
+ auto getDS1UboBinding = [&]()
77
+ {
78
+ uint32_t ds1UboBinding = 0u ;
79
+ for (const auto & bnd : ds1layout->getBindings ())
80
+ if (bnd.type == asset::EDT_UNIFORM_BUFFER)
81
+ {
82
+ ds1UboBinding = bnd.binding ;
83
+ break ;
84
+ }
85
+ return ds1UboBinding;
86
+ };
87
+
88
+ const uint32_t ds1UboBinding = getDS1UboBinding ();
89
+
90
+ auto getNeededDS1UboByteSize = [&]()
91
+ {
92
+ size_t neededDS1UboSize = 0ull ;
93
+ {
94
+ for (const auto & shaderInputs : pipelineMetadata->getRequiredShaderInputs ())
95
+ if (shaderInputs.descriptorSection .type == asset::IRenderpassIndependentPipelineMetadata::ShaderInput::ET_UNIFORM_BUFFER && shaderInputs.descriptorSection .uniformBufferObject .set == 1u && shaderInputs.descriptorSection .uniformBufferObject .binding == ds1UboBinding)
96
+ neededDS1UboSize = std::max<size_t >(neededDS1UboSize, shaderInputs.descriptorSection .uniformBufferObject .relByteoffset + shaderInputs.descriptorSection .uniformBufferObject .bytesize );
97
+ }
98
+ return neededDS1UboSize;
99
+ };
100
+
101
+ const uint64_t uboDS1ByteSize = getNeededDS1UboByteSize ();
102
+
103
+ auto gpuds1layout = driver->getGPUObjectsFromAssets (&ds1layout, &ds1layout + 1 )->front ();
104
+
105
+ auto gpuubo = driver->createDeviceLocalGPUBufferOnDedMem (uboDS1ByteSize);
106
+ auto gpuds1 = driver->createGPUDescriptorSet (std::move (gpuds1layout));
107
+ {
108
+ video::IGPUDescriptorSet::SWriteDescriptorSet write;
109
+ write.dstSet = gpuds1.get ();
110
+ write.binding = ds1UboBinding;
111
+ write.count = 1u ;
112
+ write.arrayElement = 0u ;
113
+ write.descriptorType = asset::EDT_UNIFORM_BUFFER;
114
+ video::IGPUDescriptorSet::SDescriptorInfo info;
115
+ {
116
+ info.desc = gpuubo;
117
+ info.buffer .offset = 0ull ;
118
+ info.buffer .size = uboDS1ByteSize;
119
+ }
120
+ write.info = &info;
121
+ driver->updateDescriptorSets (1u , &write, 0u , nullptr );
122
+ }
123
+
124
+ auto gpuMesh = driver->getGPUObjectsFromAssets (&cpuMesh.get (), &cpuMesh.get () + 1 )->front ();
125
+
126
+ scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS (0 , 100 .0f , 0 .5f );
127
+
128
+ camera->setPosition (core::vector3df (-4 , 0 , 0 ));
129
+ camera->setTarget (core::vector3df (0 , 0 , 0 ));
130
+ camera->setNearValue (1 .f );
131
+ camera->setFarValue (5000 .0f );
132
+
133
+ smgr->setActiveCamera (camera);
134
+
135
+ uint64_t lastFPSTime = 0 ;
136
+ while (device->run () && receiver.keepOpen ())
137
+ {
138
+ driver->beginScene (true , true , video::SColor (255 , 255 , 255 , 255 ));
139
+
140
+ camera->OnAnimate (std::chrono::duration_cast<std::chrono::milliseconds>(device->getTimer ()->getTime ()).count ());
141
+ camera->render ();
142
+
143
+ core::vector<uint8_t > uboData (gpuubo->getSize ());
144
+ for (const auto & shaderInputs : pipelineMetadata->getRequiredShaderInputs ())
145
+ {
146
+ if (shaderInputs.descriptorSection .type == asset::IRenderpassIndependentPipelineMetadata::ShaderInput::ET_UNIFORM_BUFFER && shaderInputs.descriptorSection .uniformBufferObject .set == 1u && shaderInputs.descriptorSection .uniformBufferObject .binding == ds1UboBinding)
147
+ {
148
+ switch (shaderInputs.type )
149
+ {
150
+ case asset::IRenderpassIndependentPipelineMetadata::ECSI_WORLD_VIEW_PROJ:
151
+ {
152
+ core::matrix4SIMD mvp = camera->getConcatenatedMatrix ();
153
+ memcpy (uboData.data () + shaderInputs.descriptorSection .uniformBufferObject .relByteoffset , mvp.pointer (), shaderInputs.descriptorSection .uniformBufferObject .bytesize );
154
+ } break ;
155
+
156
+ case asset::IRenderpassIndependentPipelineMetadata::ECSI_WORLD_VIEW:
157
+ {
158
+ core::matrix3x4SIMD MV = camera->getViewMatrix ();
159
+ memcpy (uboData.data () + shaderInputs.descriptorSection .uniformBufferObject .relByteoffset , MV.pointer (), shaderInputs.descriptorSection .uniformBufferObject .bytesize );
160
+ } break ;
161
+
162
+ case asset::IRenderpassIndependentPipelineMetadata::ECSI_WORLD_VIEW_INVERSE_TRANSPOSE:
163
+ {
164
+ core::matrix3x4SIMD MV = camera->getViewMatrix ();
165
+ memcpy (uboData.data () + shaderInputs.descriptorSection .uniformBufferObject .relByteoffset , MV.pointer (), shaderInputs.descriptorSection .uniformBufferObject .bytesize );
166
+ } break ;
167
+ }
168
+ }
169
+ }
170
+ driver->updateBufferRangeViaStagingBuffer (gpuubo.get (), 0ull , gpuubo->getSize (), uboData.data ());
171
+
172
+ for (auto gpuMeshBuffer : gpuMesh->getMeshBuffers ())
173
+ {
174
+ const video::IGPURenderpassIndependentPipeline* gpuPipeline = gpuMeshBuffer->getPipeline ();
175
+ const video::IGPUDescriptorSet* gpuds3 = gpuMeshBuffer->getAttachedDescriptorSet ();
176
+
177
+ driver->bindGraphicsPipeline (gpuPipeline);
178
+ const video::IGPUDescriptorSet* gpuds1_ptr = gpuds1.get ();
179
+ driver->bindDescriptorSets (video::EPBP_GRAPHICS, gpuPipeline->getLayout (), 1u , 1u , &gpuds1_ptr, nullptr );
180
+
181
+ if (gpuds3) // ! Execute if we have a texture attached as DS
182
+ driver->bindDescriptorSets (video::EPBP_GRAPHICS, gpuPipeline->getLayout (), 3u , 1u , &gpuds3, nullptr );
183
+ driver->pushConstants (gpuPipeline->getLayout (), video::IGPUSpecializedShader::ESS_FRAGMENT, 0u , gpuMeshBuffer->MAX_PUSH_CONSTANT_BYTESIZE , gpuMeshBuffer->getPushConstantsDataPtr ());
184
+
185
+ driver->drawMeshBuffer (gpuMeshBuffer);
186
+ }
187
+
188
+ driver->endScene ();
189
+
190
+ /*
191
+ display frames per second in window title
192
+ */
193
+
194
+ uint64_t time = device->getTimer ()->getRealTime ();
195
+ if (time - lastFPSTime > 1000 )
196
+ {
197
+ std::wostringstream str;
198
+ str << L" PLY & STL Test Demo - Nabla Engine [" << driver->getName () << " ] FPS:" << driver->getFPS () << " PrimitvesDrawn:" << driver->getPrimitiveCountDrawn ();
199
+
200
+ device->setWindowCaption (str.str ().c_str ());
201
+ lastFPSTime = time;
202
+ }
203
+ }
204
+
205
+ return 0 ;
206
+ }
0 commit comments