OpenSceneGraph 0.1.2__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. OpenSceneGraph/OpenThreads.lib +0 -0
  2. OpenSceneGraph/_OpenSceneGraph.cp313-win_amd64.pyd +0 -0
  3. OpenSceneGraph/__init__.py +52 -0
  4. OpenSceneGraph/aipython/00-index.md +44 -0
  5. OpenSceneGraph/aipython/01-core.md +255 -0
  6. OpenSceneGraph/aipython/02-inspect.md +81 -0
  7. OpenSceneGraph/aipython/03-headless-frames.md +149 -0
  8. OpenSceneGraph/aipython/05-camera-manipulator.md +68 -0
  9. OpenSceneGraph/aipython/06-camera-effects.md +132 -0
  10. OpenSceneGraph/aipython/07-camera-manual.md +88 -0
  11. OpenSceneGraph/aipython/08-lighting.md +121 -0
  12. OpenSceneGraph/aipython/09-picking.md +90 -0
  13. OpenSceneGraph/aipython/10-rtt.md +199 -0
  14. OpenSceneGraph/aipython/11-mrt.md +104 -0
  15. OpenSceneGraph/aipython/12-gbuffer.md +48 -0
  16. OpenSceneGraph/aipython/15-shader-hotswap.md +72 -0
  17. OpenSceneGraph/aipython/17-particles.md +189 -0
  18. OpenSceneGraph/aipython/18-deterministic-captures.md +157 -0
  19. OpenSceneGraph/aipython/20-object-lifetime.md +77 -0
  20. OpenSceneGraph/aipython/25-async-osgpy.md +228 -0
  21. OpenSceneGraph/aipython/29-material.md +109 -0
  22. OpenSceneGraph/aipython/30-pbribl.md +162 -0
  23. OpenSceneGraph/aipython/40-typed-lights-gizmos.md +218 -0
  24. OpenSceneGraph/examples/__init__.py +24 -0
  25. OpenSceneGraph/examples/__main__.py +143 -0
  26. OpenSceneGraph/examples/blur.py +370 -0
  27. OpenSceneGraph/examples/info.py +126 -0
  28. OpenSceneGraph/examples/mrt.py +493 -0
  29. OpenSceneGraph/examples/pyosg_async.py +467 -0
  30. OpenSceneGraph/examples/pyosg_example.py +120 -0
  31. OpenSceneGraph/examples/pyosg_repl.py +842 -0
  32. OpenSceneGraph/examples/pyosg_visitor.py +138 -0
  33. OpenSceneGraph/ktx.dll +0 -0
  34. OpenSceneGraph/ktx.lib +0 -0
  35. OpenSceneGraph/osg.lib +0 -0
  36. OpenSceneGraph/osg161-osg.dll +0 -0
  37. OpenSceneGraph/osg161-osgAnimation.dll +0 -0
  38. OpenSceneGraph/osg161-osgDB.dll +0 -0
  39. OpenSceneGraph/osg161-osgFX.dll +0 -0
  40. OpenSceneGraph/osg161-osgGA.dll +0 -0
  41. OpenSceneGraph/osg161-osgText.dll +0 -0
  42. OpenSceneGraph/osg161-osgUtil.dll +0 -0
  43. OpenSceneGraph/osg161-osgViewer.dll +0 -0
  44. OpenSceneGraph/osg161-osgWidget.dll +0 -0
  45. OpenSceneGraph/osgAnimation.lib +0 -0
  46. OpenSceneGraph/osgDB.lib +0 -0
  47. OpenSceneGraph/osgFX.lib +0 -0
  48. OpenSceneGraph/osgGA.lib +0 -0
  49. OpenSceneGraph/osgPlugins-3.6.5/jpeg62-ebb2f26be87097e77bafd1e9095b4820.dll +0 -0
  50. OpenSceneGraph/osgPlugins-3.6.5/ktx.dll +0 -0
  51. OpenSceneGraph/osgPlugins-3.6.5/liblzma-b9cff3753c4848b9ff1350ba5a053c6e.dll +0 -0
  52. OpenSceneGraph/osgPlugins-3.6.5/libpng16-36b7e1e8d185cb21280e5688f99660c0.dll +0 -0
  53. OpenSceneGraph/osgPlugins-3.6.5/msvcp140.dll +0 -0
  54. OpenSceneGraph/osgPlugins-3.6.5/osgdb_bmp.dll +0 -0
  55. OpenSceneGraph/osgPlugins-3.6.5/osgdb_dds.dll +0 -0
  56. OpenSceneGraph/osgPlugins-3.6.5/osgdb_gltf.dll +0 -0
  57. OpenSceneGraph/osgPlugins-3.6.5/osgdb_hdr.dll +0 -0
  58. OpenSceneGraph/osgPlugins-3.6.5/osgdb_jpeg.dll +0 -0
  59. OpenSceneGraph/osgPlugins-3.6.5/osgdb_ktx2.dll +0 -0
  60. OpenSceneGraph/osgPlugins-3.6.5/osgdb_obj.dll +0 -0
  61. OpenSceneGraph/osgPlugins-3.6.5/osgdb_osg.dll +0 -0
  62. OpenSceneGraph/osgPlugins-3.6.5/osgdb_png.dll +0 -0
  63. OpenSceneGraph/osgPlugins-3.6.5/osgdb_pnm.dll +0 -0
  64. OpenSceneGraph/osgPlugins-3.6.5/osgdb_rgb.dll +0 -0
  65. OpenSceneGraph/osgPlugins-3.6.5/osgdb_serializers_osg.dll +0 -0
  66. OpenSceneGraph/osgPlugins-3.6.5/osgdb_stl.dll +0 -0
  67. OpenSceneGraph/osgPlugins-3.6.5/osgdb_tga.dll +0 -0
  68. OpenSceneGraph/osgPlugins-3.6.5/osgdb_tiff.dll +0 -0
  69. OpenSceneGraph/osgPlugins-3.6.5/tiff-1defa8059e5ba115a3ab4b120de6f4bb.dll +0 -0
  70. OpenSceneGraph/osgPlugins-3.6.5/z.dll +0 -0
  71. OpenSceneGraph/osgText.lib +0 -0
  72. OpenSceneGraph/osgUtil.lib +0 -0
  73. OpenSceneGraph/osgViewer.lib +0 -0
  74. OpenSceneGraph/osgWidget.lib +0 -0
  75. OpenSceneGraph/osgx.cp313-win_amd64.pyd +0 -0
  76. OpenSceneGraph/osgx_static.lib +0 -0
  77. OpenSceneGraph/ot21-OpenThreads.dll +0 -0
  78. openscenegraph-0.1.2.dist-info/DELVEWHEEL +2 -0
  79. openscenegraph-0.1.2.dist-info/METADATA +563 -0
  80. openscenegraph-0.1.2.dist-info/RECORD +90 -0
  81. openscenegraph-0.1.2.dist-info/WHEEL +5 -0
  82. openscenegraph-0.1.2.dist-info/entry_points.txt +6 -0
  83. openscenegraph-0.1.2.dist-info/licenses/LICENSE +21 -0
  84. openscenegraph.libs/jpeg62-ebb2f26be87097e77bafd1e9095b4820.dll +0 -0
  85. openscenegraph.libs/liblzma-b9cff3753c4848b9ff1350ba5a053c6e.dll +0 -0
  86. openscenegraph.libs/libpng16-36b7e1e8d185cb21280e5688f99660c0.dll +0 -0
  87. openscenegraph.libs/msvcp140.dll +0 -0
  88. openscenegraph.libs/tiff-1defa8059e5ba115a3ab4b120de6f4bb.dll +0 -0
  89. openscenegraph.libs/z.dll +0 -0
  90. osgx.py +7 -0
@@ -0,0 +1,370 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from OpenSceneGraph import *
4
+ from OpenSceneGraph.GL import *
5
+
6
+ import os
7
+ import sys
8
+
9
+ W, H = 800, 600
10
+
11
+ os.environ.update({
12
+ "OSG_WINDOW": f"50 50 {W} {H}",
13
+ "OSG_THREADING": "SingleThreaded",
14
+ "OSG_GL_CONTEXT_PROFILE_MASK": "1",
15
+ "OSG_GL_VERSION": "4.6",
16
+ "OSG_GL_CONTEXT_VERSION": "4.6",
17
+ })
18
+
19
+ FULLSCREEN_VERT = """
20
+ #version 330 core
21
+
22
+ in vec4 osg_Vertex;
23
+ in vec2 osg_MultiTexCoord0;
24
+
25
+ out vec2 uv;
26
+
27
+ void main() {
28
+ uv = osg_MultiTexCoord0;
29
+ gl_Position = osg_Vertex;
30
+ }
31
+ """
32
+
33
+ BLUR_FRAG_OLD = """
34
+ #version 330 core
35
+
36
+ uniform sampler2D inputTex;
37
+ uniform vec2 texelStep;
38
+
39
+ in vec2 uv;
40
+
41
+ out vec4 fragColor;
42
+
43
+ void main() {
44
+ // 9-tap-ish Gaussian weights.
45
+ // Offsets are in units of texelStep, so:
46
+ // horizontal: texelStep = vec2(1.0 / width, 0.0)
47
+ // vertical: texelStep = vec2(0.0, 1.0 / height)
48
+
49
+ vec4 sum = vec4(0.0);
50
+
51
+ sum += texture(inputTex, uv - 4.0 * texelStep) * 0.0162162162;
52
+ sum += texture(inputTex, uv - 3.0 * texelStep) * 0.0540540541;
53
+ sum += texture(inputTex, uv - 2.0 * texelStep) * 0.1216216216;
54
+ sum += texture(inputTex, uv - 1.0 * texelStep) * 0.1945945946;
55
+ sum += texture(inputTex, uv ) * 0.2270270270;
56
+ sum += texture(inputTex, uv + 1.0 * texelStep) * 0.1945945946;
57
+ sum += texture(inputTex, uv + 2.0 * texelStep) * 0.1216216216;
58
+ sum += texture(inputTex, uv + 3.0 * texelStep) * 0.0540540541;
59
+ sum += texture(inputTex, uv + 4.0 * texelStep) * 0.0162162162;
60
+
61
+ fragColor = sum;
62
+ }
63
+ """
64
+
65
+ BLUR_FRAG = """
66
+ #version 330 core
67
+
68
+ uniform sampler2D inputTex;
69
+ uniform vec2 texelStep;
70
+ // uniform float blurRadius;
71
+
72
+ in vec2 uv;
73
+
74
+ out vec4 fragColor;
75
+
76
+ void main() {
77
+ // vec2 step = texelStep * blurRadius;
78
+ vec2 step = texelStep * 8;
79
+
80
+ vec4 sum = vec4(0.0);
81
+
82
+ sum += texture(inputTex, uv - 4.0 * step) * 0.0162162162;
83
+ sum += texture(inputTex, uv - 3.0 * step) * 0.0540540541;
84
+ sum += texture(inputTex, uv - 2.0 * step) * 0.1216216216;
85
+ sum += texture(inputTex, uv - 1.0 * step) * 0.1945945946;
86
+ sum += texture(inputTex, uv ) * 0.2270270270;
87
+ sum += texture(inputTex, uv + 1.0 * step) * 0.1945945946;
88
+ sum += texture(inputTex, uv + 2.0 * step) * 0.1216216216;
89
+ sum += texture(inputTex, uv + 3.0 * step) * 0.0540540541;
90
+ sum += texture(inputTex, uv + 4.0 * step) * 0.0162162162;
91
+
92
+ fragColor = sum;
93
+ }
94
+ """
95
+
96
+ COMPOSITE_FRAG = """
97
+ #version 330 core
98
+
99
+ uniform sampler2D sceneTex;
100
+ uniform sampler2D blurTex;
101
+
102
+ uniform float glowStrength;
103
+
104
+ in vec2 uv;
105
+
106
+ out vec4 fragColor;
107
+
108
+ void main() {
109
+ vec4 scene = texture(sceneTex, uv);
110
+ vec4 blur = texture(blurTex, uv);
111
+
112
+ // Red sensor/display-style tint applied to the original.
113
+ vec3 redScene = scene.rgb * vec3(1.0, 0.28, 0.28);
114
+
115
+ // Red glow from blurred image.
116
+ vec3 redGlow = blur.rgb * vec3(1.0, 0.12, 0.08) * glowStrength;
117
+
118
+ // Screen-space scanlines.
119
+ float scan = step(0.35, fract(gl_FragCoord.y * 0.25));
120
+ scan = mix(0.72, 1.0, scan);
121
+
122
+ // Vignette.
123
+ float d = distance(uv, vec2(0.5));
124
+ float vignette = smoothstep(0.42, 0.12, d);
125
+
126
+ vec3 color = (redScene + redGlow) * scan * vignette;
127
+
128
+ fragColor = vec4(color, 1.0);
129
+ }
130
+ """
131
+
132
+ def make_color_texture(w, h):
133
+ tex = osg.Texture2D()
134
+
135
+ tex.size = (w, h)
136
+ tex.internalFormat = GL_RGBA
137
+ tex.filter = (osg.Texture.LINEAR, osg.Texture.LINEAR)
138
+ tex.wrap = (osg.Texture.CLAMP_TO_EDGE, osg.Texture.CLAMP_TO_EDGE)
139
+
140
+ return tex
141
+
142
+ def make_fullscreen_quad():
143
+ geode = osg.Geode(name="fullscreen-quad")
144
+
145
+ geode.drawables.append(osg.createTexturedQuadGeometry(
146
+ osg.Vec3(-1.0, -1.0, -1.0),
147
+ osg.Vec3(2.0, 0.0, 0.0),
148
+ osg.Vec3(0.0, 2.0, 0.0),
149
+ ))
150
+
151
+ return geode
152
+
153
+ def make_program(name, vert, frag):
154
+ return osg.Program(name=name, shaders=(
155
+ osg.Shader(osg.Shader.VERTEX, vert),
156
+ osg.Shader(osg.Shader.FRAGMENT, frag),
157
+ ))
158
+
159
+ def make_scene_rtt_pass(output_tex, scene, w, h, name="Scene RTT"):
160
+ cam = osg.Camera()
161
+
162
+ cam.name = name
163
+ cam.renderOrder = (osg.Camera.PRE_RENDER, 0)
164
+ cam.renderTargetImplementation = osg.Camera.FRAME_BUFFER_OBJECT
165
+ cam.clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
166
+ # Important for blur/glow: clear to transparent black-ish, not visible blue.
167
+ # Since the final composite currently ignores alpha, RGB is what matters most.
168
+ cam.clearColor = osg.Vec4(0.0, 0.0, 0.0, 1.0)
169
+ cam.viewport = osg.Viewport(0, 0, w, h)
170
+ cam.attach(osg.Camera.COLOR_BUFFER, output_tex)
171
+
172
+ cam.children.append(scene)
173
+
174
+ return cam
175
+
176
+ def make_fullscreen_rtt_pass(
177
+ input_tex,
178
+ output_tex,
179
+ frag_shader,
180
+ w,
181
+ h,
182
+ name="Post RTT",
183
+ order=1,
184
+ extra_uniforms=None
185
+ ):
186
+ cam = osg.Camera()
187
+
188
+ cam.name = name
189
+ cam.renderOrder = (osg.Camera.PRE_RENDER, order)
190
+ cam.dataVariance = osg.Object.DYNAMIC
191
+ cam.renderTargetImplementation = osg.Camera.FRAME_BUFFER_OBJECT
192
+ cam.clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
193
+ cam.clearColor = osg.Vec4(0.0, 0.0, 0.0, 1.0)
194
+ cam.viewport = osg.Viewport(0, 0, w, h)
195
+ cam.projectionMatrix = osg.Matrix.identity()
196
+ cam.viewMatrix = osg.Matrix.identity()
197
+ cam.referenceFrame = osg.Transform.ABSOLUTE_RF
198
+ cam.allowEventFocus = False
199
+
200
+ cam.attach(osg.Camera.COLOR_BUFFER, output_tex)
201
+
202
+ prog = make_program(f"{name}_program", FULLSCREEN_VERT, frag_shader)
203
+
204
+ cam.stateSet.attributes[osg.StateAttribute.PROGRAM] = (
205
+ prog,
206
+ osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE
207
+ )
208
+
209
+ cam.stateSet.textureAttributes[0] = (
210
+ input_tex,
211
+ osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE
212
+ )
213
+
214
+ cam.stateSet.uniforms["inputTex"] = 0
215
+
216
+ if extra_uniforms:
217
+ for k, v in extra_uniforms.items():
218
+ cam.stateSet.uniforms[k] = v
219
+
220
+ cam.children.append(make_fullscreen_quad())
221
+
222
+ return cam
223
+
224
+ def make_blur_pass(input_tex, output_tex, w, h, direction, name, order):
225
+ if direction == "horizontal":
226
+ texel_step = osg.Vec2(1.0 / float(w), 0.0)
227
+
228
+ elif direction == "vertical":
229
+ texel_step = osg.Vec2(0.0, 1.0 / float(h))
230
+
231
+ else:
232
+ raise ValueError(f"invalid blur direction: {direction!r}")
233
+
234
+ return make_fullscreen_rtt_pass(
235
+ input_tex=input_tex,
236
+ output_tex=output_tex,
237
+ frag_shader=BLUR_FRAG,
238
+ w=w,
239
+ h=h,
240
+ name=name,
241
+ order=order,
242
+ extra_uniforms={
243
+ "texelStep": texel_step
244
+ }
245
+ )
246
+
247
+ def make_composite_hud(scene_tex, blur_tex, w, h):
248
+ cam = osg.Camera()
249
+
250
+ cam.name = "Composite HUD"
251
+ cam.renderOrder = osg.Camera.POST_RENDER
252
+ cam.clearMask = GL_DEPTH_BUFFER_BIT
253
+ cam.viewport = osg.Viewport(0, 0, w, h)
254
+ cam.projectionMatrix = osg.Matrix.identity()
255
+ cam.viewMatrix = osg.Matrix.identity()
256
+ cam.referenceFrame = osg.Transform.ABSOLUTE_RF
257
+ cam.allowEventFocus = False
258
+
259
+ prog = make_program("composite_hud_program", FULLSCREEN_VERT, COMPOSITE_FRAG)
260
+
261
+ cam.stateSet.attributes[osg.StateAttribute.PROGRAM] = (
262
+ prog,
263
+ osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE,
264
+ )
265
+
266
+ cam.stateSet.textureAttributes[0] = (
267
+ scene_tex,
268
+ osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE,
269
+ )
270
+ cam.stateSet.textureAttributes[1] = (
271
+ blur_tex,
272
+ osg.StateAttribute.ON | osg.StateAttribute.OVERRIDE,
273
+ )
274
+
275
+ cam.stateSet.uniforms["sceneTex"] = 0
276
+ cam.stateSet.uniforms["blurTex"] = 1
277
+ cam.stateSet.uniforms["glowStrength"] = 2.0
278
+
279
+ cam.children.append(make_fullscreen_quad())
280
+
281
+ return cam
282
+
283
+ # Make this do WHATEVER YOU WANT. :) It'll work just fine...
284
+ def create_scene():
285
+ return osgDB.readNodeFile(len(sys.argv) >= 2 and sys.argv[1] or "glsl_simple.osgt")
286
+
287
+ # The real pipeline-assembly entrypoint -- returns the root Node, no viewer/window side
288
+ # effects. This is what external tooling (e.g. etc/pyside6-glsl.py's shader-editor scaffold)
289
+ # imports and calls directly, so it MUST stay side-effect-free w.r.t. any global viewer state.
290
+ # Takes (w, h) explicitly -- e.g. the real widget size at the caller's GL-context-current
291
+ # point -- rather than reading the module-level W/H globals, which only __main__ below uses.
292
+ def build_scene(w, h):
293
+ # Pass outputs:
294
+ #
295
+ # sceneColor: original osgSlug scene
296
+ # blurA: horizontal blur of sceneColor
297
+ # blurB: vertical blur of blurA
298
+ sceneColor = make_color_texture(w, h)
299
+ blurA = make_color_texture(w, h)
300
+ blurB = make_color_texture(w, h)
301
+
302
+ sceneColor.dataVariance = osg.Object.DYNAMIC
303
+ blurA.dataVariance = osg.Object.DYNAMIC
304
+ blurB.dataVariance = osg.Object.DYNAMIC
305
+
306
+ # Pass 1:
307
+ # Render actual scene to sceneColor.
308
+ scene_pass = make_scene_rtt_pass(
309
+ output_tex=sceneColor,
310
+ scene=create_scene(),
311
+ w=w,
312
+ h=h,
313
+ name="Scene RTT"
314
+ )
315
+
316
+ # Pass 2:
317
+ # Horizontal blur: sceneColor -> blurA.
318
+ blur_h_pass = make_blur_pass(
319
+ input_tex=sceneColor,
320
+ output_tex=blurA,
321
+ w=w,
322
+ h=h,
323
+ direction="horizontal",
324
+ name="Blur Horizontal RTT",
325
+ order=1
326
+ )
327
+
328
+ # Pass 3:
329
+ # Vertical blur: blurA -> blurB.
330
+ blur_v_pass = make_blur_pass(
331
+ input_tex=blurA,
332
+ output_tex=blurB,
333
+ w=w,
334
+ h=h,
335
+ direction="vertical",
336
+ name="Blur Vertical RTT",
337
+ order=2
338
+ )
339
+
340
+ # Pass 4:
341
+ # Composite original scene + blurred glow to default framebuffer.
342
+ hud = make_composite_hud(
343
+ scene_tex=sceneColor,
344
+ blur_tex=blurB,
345
+ w=w,
346
+ h=h
347
+ )
348
+
349
+ root = osg.Group()
350
+ root.children.extend((
351
+ scene_pass,
352
+ blur_h_pass,
353
+ blur_v_pass,
354
+ hud
355
+ ))
356
+
357
+ return root
358
+
359
+ if __name__ == "__main__":
360
+ viewer = osgViewer.Viewer()
361
+ viewer.sceneData = build_scene(W, H)
362
+ viewer.cameraManipulator = osgGA.TrackballManipulator()
363
+
364
+ # Should not be visible if HUD composite is covering the whole screen.
365
+ viewer.camera.clearColor = osg.Vec4(1.0, 0.0, 1.0, 1.0)
366
+
367
+ viewer.TODO()
368
+
369
+ while not viewer.done:
370
+ viewer.frame()
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Quick diagnostic dump, not an interactive viewer: build_info() from OpenSceneGraph (and osgx,
4
+ # if installed), the REQUESTED GL context (DisplaySettings, sourced from the OSG_GL_VERSION/
5
+ # OSG_GL_CONTEXT_VERSION/OSG_GL_CONTEXT_PROFILE_MASK env vars set below), what a realized
6
+ # GraphicsContext's own Traits resolved that request to, and what the driver ACTUALLY granted
7
+ # (State.glExtensions). Realizes just long enough to populate that last part, then exits.
8
+ # Edit the env vars below (or unset them) to see how the three stages diverge -- e.g. request a
9
+ # GL version the driver doesn't support and watch Traits echo the request back while
10
+ # GLExtensions reports what was actually negotiated instead.
11
+
12
+ import os
13
+ import sys
14
+
15
+ os.environ.update({
16
+ "OSG_WINDOW": "50 50 100 100",
17
+ "OSG_THREADING": "SingleThreaded",
18
+ "OSG_GL_CONTEXT_PROFILE_MASK": "1",
19
+ "OSG_GL_VERSION": "4.6",
20
+ "OSG_GL_CONTEXT_VERSION": "4.6",
21
+ })
22
+
23
+ from OpenSceneGraph import *
24
+
25
+ GL_EXTENSION_FIELDS = (
26
+ "contextID",
27
+ "glVersion",
28
+ "glslLanguageVersion",
29
+ "isGlslSupported",
30
+ "isShaderObjectsSupported",
31
+ "isVertexShaderSupported",
32
+ "isFragmentShaderSupported",
33
+ "isLanguage100Supported",
34
+ "isGeometryShader4Supported",
35
+ "areTessellationShadersSupported",
36
+ "isGpuShader4Supported",
37
+ "isUniformBufferObjectSupported",
38
+ "isGetProgramBinarySupported",
39
+ "isGpuShaderFp64Supported",
40
+ "isShaderAtomicCountersSupported",
41
+ "isRectangleSupported",
42
+ "isCubeMapSupported",
43
+ "isClipControlSupported",
44
+ )
45
+
46
+ def section(title):
47
+ print(f"\n== {title} ==")
48
+
49
+ def dump(label, value):
50
+ # Display-only rounding: glVersion/glslLanguageVersion are C++ `float` (32-bit), so e.g.
51
+ # 4.6's nearest float32 widens to 4.599999904632568 once pybind11 hands it back as a
52
+ # Python (64-bit) float -- a real, if slightly lossy, binary representation, not corrupted
53
+ # data. Round here for a readable dump only; anything doing a real comparison against
54
+ # these values should still read the unrounded field directly.
55
+ if isinstance(value, float):
56
+ value = round(value, 4)
57
+
58
+ print(f" {label:<32} {value}")
59
+
60
+ def main(viewer):
61
+ section("build_info()")
62
+
63
+ for key, value in build_info().items():
64
+ dump(key, value)
65
+
66
+ try:
67
+ import osgx
68
+
69
+ section("build_info() [osgx]")
70
+
71
+ for key, value in osgx.build_info().items():
72
+ dump(key, value)
73
+
74
+ except ImportError:
75
+ section("osgx")
76
+ dump("status", "not installed")
77
+
78
+ section("DisplaySettings (requested)")
79
+
80
+ ds = osg.DisplaySettings.instance
81
+
82
+ dump("glContextVersion", repr(ds.glContextVersion))
83
+ dump("glContextProfileMask", ds.glContextProfileMask)
84
+ dump("glContextFlags", ds.glContextFlags)
85
+ dump("numMultiSamples", ds.numMultiSamples)
86
+
87
+ # viewer = osgViewer.Viewer()
88
+ #
89
+ # viewer.cameraManipulator = osgGA.TrackballManipulator()
90
+ viewer.realize()
91
+ viewer.frame()
92
+
93
+ gc = viewer.camera.graphicsContext
94
+
95
+ if not gc or not gc.valid():
96
+ sys.exit("error: failed to realize a GraphicsContext")
97
+
98
+ traits = gc.traits
99
+
100
+ section("GraphicsContext.Traits (resolved)")
101
+
102
+ dump("x, y", f"{traits.x}, {traits.y}")
103
+ dump("width, height", f"{traits.width}, {traits.height}")
104
+ dump("glContextVersion", repr(traits.glContextVersion))
105
+ dump("glContextProfileMask", traits.glContextProfileMask)
106
+ dump("glContextFlags", traits.glContextFlags)
107
+
108
+ section("GLExtensions (actual, from the driver)")
109
+
110
+ ext = gc.state.glExtensions
111
+
112
+ for field in GL_EXTENSION_FIELDS:
113
+ dump(field, getattr(ext, field))
114
+
115
+ print()
116
+
117
+ viewer.close()
118
+
119
+ def build_scene(*args):
120
+ return None
121
+
122
+ def configure_viewer(viewer, root):
123
+ main(viewer)
124
+
125
+ if __name__ == "__main__":
126
+ main(osgViewer.Viewer())