Skip to content

Commit 2394acc

Browse files
committed
Add example for vsg::LOD nodes
1 parent e48d973 commit 2394acc

File tree

3 files changed

+322
-0
lines changed

3 files changed

+322
-0
lines changed

examples/nodes/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_subdirectory(vsgannotation)
22
add_subdirectory(vsggroups)
3+
add_subdirectory(vsglod)
34
add_subdirectory(vsgtransform)
45
add_subdirectory(vsgtextureprojection)
56
add_subdirectory(vsglayers)

examples/nodes/vsglod/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
set(SOURCES
2+
vsglod.cpp
3+
)
4+
5+
add_executable(vsglod ${SOURCES})
6+
7+
target_link_libraries(vsglod vsg::vsg)
8+
9+
if (Tracy_FOUND)
10+
target_compile_definitions(vsglod PRIVATE Tracy_FOUND)
11+
target_link_libraries(vsglod Tracy::TracyClient)
12+
endif()
13+
14+
install(TARGETS vsglod RUNTIME DESTINATION bin)

examples/nodes/vsglod/vsglod.cpp

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
#include <vsg/all.h>
2+
3+
#ifdef Tracy_FOUND
4+
# include <vsg/utils/TracyInstrumentation.h>
5+
#endif
6+
7+
#include <iostream>
8+
9+
struct ModelSettings
10+
{
11+
vsg::ref_ptr<vsg::Options> options;
12+
double lodMinScreenRatio = 0.01;
13+
};
14+
15+
vsg::ref_ptr<vsg::Node> createTestScene(const ModelSettings& settings)
16+
{
17+
auto builder = vsg::Builder::create();
18+
builder->options = settings.options;
19+
20+
auto scene = vsg::Group::create();
21+
22+
vsg::GeometryInfo geomInfo;
23+
geomInfo.color.set(1.0f, 1.0f, 0.5f, 1.0f);
24+
vsg::StateInfo stateInfo;
25+
26+
auto node = builder->createCone(geomInfo, stateInfo);
27+
auto node2 = builder->createCylinder(geomInfo, stateInfo);
28+
29+
vsg::ComputeBounds cb;
30+
node->accept(cb);
31+
node2->accept(cb);
32+
auto bb = cb.bounds;
33+
34+
// shows empty/node2/node when approaching
35+
auto lod = vsg::LOD::create();
36+
lod->bound = vsg::dsphere((bb.min + bb.max) * 0.5, vsg::length(bb.max - bb.min));
37+
lod->addChild(vsg::LOD::Child{settings.lodMinScreenRatio+1, node});
38+
lod->addChild(vsg::LOD::Child{settings.lodMinScreenRatio, node2});
39+
scene->addChild(lod);
40+
41+
geomInfo.position += geomInfo.dx * 1.5f;
42+
geomInfo.color.set(1.0f, 0.5f, 1.0f, 1.0f);
43+
auto node3 = builder->createCone(geomInfo, stateInfo);
44+
auto node4 = builder->createSphere(geomInfo, stateInfo);
45+
46+
vsg::ComputeBounds cb2;
47+
node3->accept(cb2);
48+
node4->accept(cb2);
49+
auto bb2 = cb2.bounds;
50+
51+
// should show node4/node3 when approaching - TODO: node4 is not displayed
52+
auto lod2 = vsg::LOD::create();
53+
lod2->bound = vsg::dsphere((bb2.min + bb2.max) * 0.5, vsg::length(bb2.max - bb2.min));
54+
lod2->addChild(vsg::LOD::Child{settings.lodMinScreenRatio, node3});
55+
lod2->addChild(vsg::LOD::Child{0.0, node4});
56+
scene->addChild(lod2);
57+
58+
auto bounds = vsg::visit<vsg::ComputeBounds>(scene).bounds;
59+
vsg::info("createTestScene() extents = ", bounds);
60+
61+
return scene;
62+
}
63+
64+
int main(int argc, char** argv)
65+
{
66+
// set up defaults and read command line arguments to override them
67+
auto options = vsg::Options::create();
68+
options->paths = vsg::getEnvPaths("VSG_FILE_PATH");
69+
options->sharedObjects = vsg::SharedObjects::create();
70+
71+
auto windowTraits = vsg::WindowTraits::create();
72+
windowTraits->windowTitle = "vsglod";
73+
74+
// set up defaults and read command line arguments to override them
75+
vsg::CommandLine arguments(&argc, argv);
76+
windowTraits->debugLayer = arguments.read({"--debug", "-d"});
77+
windowTraits->apiDumpLayer = arguments.read({"--api", "-a"});
78+
windowTraits->synchronizationLayer = arguments.read("--sync");
79+
80+
bool reportAverageFrameRate = arguments.read("--fps");
81+
arguments.read("--screen", windowTraits->screenNum);
82+
arguments.read("--display", windowTraits->display);
83+
auto numFrames = arguments.value(-1, "-f");
84+
if (arguments.read({"--fullscreen", "--fs"})) windowTraits->fullscreen = true;
85+
if (arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height)) { windowTraits->fullscreen = false; }
86+
if (arguments.read("--IMMEDIATE")) windowTraits->swapchainPreferences.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
87+
if (arguments.read("--d32")) windowTraits->depthFormat = VK_FORMAT_D32_SFLOAT;
88+
arguments.read("--samples", windowTraits->samples);
89+
if (arguments.read({"-t", "--test"}))
90+
{
91+
windowTraits->swapchainPreferences.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
92+
windowTraits->fullscreen = true;
93+
reportAverageFrameRate = true;
94+
}
95+
if (arguments.read("--st"))
96+
{
97+
windowTraits->swapchainPreferences.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
98+
windowTraits->width = 192, windowTraits->height = 108;
99+
windowTraits->decoration = false;
100+
reportAverageFrameRate = true;
101+
}
102+
103+
const double invalid_time = std::numeric_limits<double>::max();
104+
auto duration = arguments.value(invalid_time, "--duration");
105+
106+
vsg::ref_ptr<vsg::Instrumentation> instrumentation;
107+
if (arguments.read({"--gpu-annotation", "--ga"}) && vsg::isExtensionSupported(VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
108+
{
109+
windowTraits->debugUtils = true;
110+
111+
auto gpu_instrumentation = vsg::GpuAnnotation::create();
112+
if (arguments.read("--func")) gpu_instrumentation->labelType = vsg::GpuAnnotation::SourceLocation_function;
113+
114+
instrumentation = gpu_instrumentation;
115+
}
116+
else if (arguments.read({"--profiler", "--pr"}))
117+
{
118+
// set Profiler options
119+
auto settings = vsg::Profiler::Settings::create();
120+
arguments.read("--cpu", settings->cpu_instrumentation_level);
121+
arguments.read("--gpu", settings->gpu_instrumentation_level);
122+
arguments.read("--log-size", settings->log_size);
123+
arguments.read("--gpu-size", settings->gpu_timestamp_size);
124+
125+
// create the profiler
126+
instrumentation = vsg::Profiler::create(settings);
127+
}
128+
#ifdef Tracy_FOUND
129+
else if (arguments.read("--tracy"))
130+
{
131+
windowTraits->deviceExtensionNames.push_back(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME);
132+
133+
auto tracy_instrumentation = vsg::TracyInstrumentation::create();
134+
arguments.read("--cpu", tracy_instrumentation->settings->cpu_instrumentation_level);
135+
arguments.read("--gpu", tracy_instrumentation->settings->gpu_instrumentation_level);
136+
instrumentation = tracy_instrumentation;
137+
}
138+
#endif
139+
140+
double nearFarRatio = arguments.value<double>(0.001, "--nf");
141+
ModelSettings settings;
142+
settings.options = options;
143+
144+
vsg::ref_ptr<vsg::ResourceHints> resourceHints;
145+
if (auto resourceHintsFilename = arguments.value<vsg::Path>("", "--rh"))
146+
{
147+
resourceHints = vsg::read_cast<vsg::ResourceHints>(resourceHintsFilename, options);
148+
}
149+
150+
if (!resourceHints) resourceHints = vsg::ResourceHints::create();
151+
152+
if (auto outputResourceHintsFilename = arguments.value<vsg::Path>("", "--orh"))
153+
{
154+
if (!resourceHints) resourceHints = vsg::ResourceHints::create();
155+
vsg::write(resourceHints, outputResourceHintsFilename, options);
156+
return 0;
157+
}
158+
159+
auto shaderHints = vsg::ShaderCompileSettings::create();
160+
vsg::ref_ptr<vsg::ShadowSettings> shadowSettings;
161+
162+
auto pathFilename = arguments.value<vsg::Path>("", "-p");
163+
auto outputFilename = arguments.value<vsg::Path>("", "-o");
164+
165+
auto inherit = arguments.read("--inherit");
166+
auto direction = arguments.value(vsg::dvec3(0.0, 0.0, -1.0), "--direction");
167+
auto angleSubtended = arguments.value<float>(0.0090f, "--angleSubtended");
168+
169+
vsg::ref_ptr<vsg::StateGroup> stateGroup;
170+
if (inherit)
171+
{
172+
auto shaderSet = vsg::createPhongShaderSet(options);
173+
auto layout = shaderSet->createPipelineLayout({}, {0, 1});
174+
175+
stateGroup = vsg::StateGroup::create();
176+
177+
uint32_t vds_set = 0;
178+
stateGroup->add(vsg::BindViewDescriptorSets::create(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, vds_set));
179+
180+
vsg::info("Added state to inherit ");
181+
options->inheritedState = stateGroup->stateCommands;
182+
}
183+
184+
vsg::ref_ptr<vsg::Node> scene;
185+
scene = createTestScene(settings);
186+
187+
if (stateGroup)
188+
{
189+
// if setup place the StateGroup at the root of the scene graph
190+
stateGroup->addChild(scene);
191+
scene = stateGroup;
192+
}
193+
194+
// compute the bounds of the scene graph to help position camera
195+
auto bounds = vsg::visit<vsg::ComputeBounds>(scene).bounds;
196+
auto viewingDistance = vsg::length(bounds.max - bounds.min) * 2.0;
197+
198+
vsg::ref_ptr<vsg::LookAt> lookAt;
199+
200+
{
201+
vsg::dvec3 centre = (bounds.min + bounds.max) * 0.5;
202+
203+
// set up the camera
204+
lookAt = vsg::LookAt::create(centre + vsg::dvec3(0.0, -viewingDistance, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0));
205+
}
206+
207+
//auto span = vsg::length(bounds.max - bounds.min);
208+
auto group = vsg::Group::create();
209+
group->addChild(scene);
210+
211+
vsg::ref_ptr<vsg::DirectionalLight> directionalLight;
212+
directionalLight = vsg::DirectionalLight::create();
213+
directionalLight->name = "directional";
214+
directionalLight->color.set(1.0f, 1.0f, 1.0f);
215+
directionalLight->intensity = 0.95f;
216+
directionalLight->direction = direction;
217+
directionalLight->angleSubtended = angleSubtended;
218+
directionalLight->shadowSettings = shadowSettings;
219+
220+
group->addChild(directionalLight);
221+
222+
scene = group;
223+
224+
// write out scene if required
225+
if (!outputFilename.empty())
226+
{
227+
vsg::write(scene, outputFilename, options);
228+
return 0;
229+
}
230+
231+
// create the viewer and assign window(s) to it
232+
auto viewer = vsg::Viewer::create();
233+
234+
auto window = vsg::Window::create(windowTraits);
235+
if (!window)
236+
{
237+
std::cout << "Could not create windows." << std::endl;
238+
return 1;
239+
}
240+
241+
viewer->addWindow(window);
242+
243+
vsg::ref_ptr<vsg::ProjectionMatrix> perspective;
244+
perspective = vsg::Perspective::create(30, 1.0, 1.0, 1000);
245+
246+
auto camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(window->extent2D()));
247+
248+
// add the camera and scene graph to View
249+
auto view = vsg::View::create();
250+
view->camera = camera;
251+
view->addChild(scene);
252+
253+
// add close handler to respond the close window button and pressing escape
254+
viewer->addEventHandler(vsg::CloseHandler::create(viewer));
255+
256+
auto cameraAnimation = vsg::CameraAnimationHandler::create(camera, pathFilename, options);
257+
viewer->addEventHandler(cameraAnimation);
258+
if (cameraAnimation->animation)
259+
{
260+
cameraAnimation->play();
261+
if (reportAverageFrameRate && duration == invalid_time) duration = cameraAnimation->animation->maxTime();
262+
}
263+
264+
viewer->addEventHandler(vsg::Trackball::create(camera));
265+
266+
auto renderGraph = vsg::RenderGraph::create(window, view);
267+
auto commandGraph = vsg::CommandGraph::create(window, renderGraph);
268+
viewer->assignRecordAndSubmitTaskAndPresentation({commandGraph});
269+
270+
if (instrumentation) viewer->assignInstrumentation(instrumentation);
271+
272+
viewer->compile(resourceHints);
273+
274+
auto startTime = vsg::clock::now();
275+
double numFramesCompleted = 0.0;
276+
277+
// rendering main loop
278+
while (viewer->advanceToNextFrame() && (numFrames < 0 || (numFrames--) > 0) && (viewer->getFrameStamp()->simulationTime < duration))
279+
{
280+
// pass any events into EventHandlers assigned to the Viewer
281+
viewer->handleEvents();
282+
viewer->update();
283+
284+
viewer->recordAndSubmit();
285+
286+
viewer->present();
287+
288+
numFramesCompleted += 1.0;
289+
}
290+
291+
if (reportAverageFrameRate)
292+
{
293+
auto elapesedTime = std::chrono::duration<double, std::chrono::seconds::period>(vsg::clock::now() - startTime).count();
294+
if (numFramesCompleted > 0.0)
295+
{
296+
std::cout << "Average frame rate = " << (numFramesCompleted / elapesedTime) << std::endl;
297+
}
298+
}
299+
300+
if (auto profiler = instrumentation.cast<vsg::Profiler>())
301+
{
302+
instrumentation->finish();
303+
profiler->log->report(std::cout);
304+
}
305+
306+
return 0;
307+
}

0 commit comments

Comments
 (0)