pax_global_header 0000666 0000000 0000000 00000000064 14704200620 0014505 g ustar 00root root 0000000 0000000 52 comment=773b7332292ce9f8c32130d0404b391c2df04428
moderngl-moderngl-773b733/ 0000775 0000000 0000000 00000000000 14704200620 0015402 5 ustar 00root root 0000000 0000000 moderngl-moderngl-773b733/.containerignore 0000664 0000000 0000000 00000000117 14704200620 0020570 0 ustar 00root root 0000000 0000000 .git
.github
.gitignore
.pytest_cache
.vscode
build
dist
*.egg-info
*.pyd
*.so
moderngl-moderngl-773b733/.gitattributes 0000664 0000000 0000000 00000000372 14704200620 0020277 0 ustar 00root root 0000000 0000000 .github/** linguist-detectable=false
examples/** linguist-documentation=false
**/Containerfile linguist-detectable=false
src/glcorearb.h linguist-detectable=false
src/khrplatform.h linguist-detectable=false
examples/data/** linguist-detectable=false
moderngl-moderngl-773b733/.github/ 0000775 0000000 0000000 00000000000 14704200620 0016742 5 ustar 00root root 0000000 0000000 moderngl-moderngl-773b733/.github/workflows/ 0000775 0000000 0000000 00000000000 14704200620 0020777 5 ustar 00root root 0000000 0000000 moderngl-moderngl-773b733/.github/workflows/build.yml 0000664 0000000 0000000 00000000740 14704200620 0022622 0 ustar 00root root 0000000 0000000 name: build
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
build:
name: build
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: setup
uses: actions/setup-python@v5
with:
python-version: '3.12'
architecture: x64
- name: deps
run: python -m pip install -U pip wheel setuptools
- name: wheel
run: python -m pip wheel .
moderngl-moderngl-773b733/.github/workflows/release.yml 0000664 0000000 0000000 00000002111 14704200620 0023135 0 ustar 00root root 0000000 0000000 name: release
on:
workflow_dispatch:
jobs:
release:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: deps
run: python -m pip install -U cibuildwheel build pip wheel setuptools
- name: sdist
run: python -m build --sdist --outdir package
if: matrix.os == 'ubuntu-latest'
- name: wheels
run: python -m cibuildwheel --output-dir package
env:
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.8"
CIBW_SKIP: pp*
- uses: actions/upload-artifact@v4
with:
name: package-${{ matrix.os }}
path: package/*
merge:
name: Merge Artifacts
runs-on: ubuntu-latest
needs:
- release
steps:
- uses: actions/upload-artifact/merge@v4
with:
name: moderngl-5.12.0
delete-merged: true
moderngl-moderngl-773b733/.github/workflows/tests.yml 0000664 0000000 0000000 00000000535 14704200620 0022667 0 ustar 00root root 0000000 0000000 name: tests
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
tests:
name: tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: build
run: docker build . -f tests/Containerfile -t tests
- name: test
run: docker run --rm -t tests
moderngl-moderngl-773b733/.gitignore 0000664 0000000 0000000 00000000120 14704200620 0017363 0 ustar 00root root 0000000 0000000 .vscode
.venv*
venv
build
dist
__pycache__
*.egg-info
*.pyc
*.pyd
*.so
/*.png
moderngl-moderngl-773b733/.readthedocs.yml 0000664 0000000 0000000 00000000450 14704200620 0020467 0 ustar 00root root 0000000 0000000 version: 2
build:
os: ubuntu-20.04
tools:
python: "3.10"
jobs:
post_checkout:
- mv moderngl moderngl-package
- cp moderngl-stubs/__init__.pyi moderngl.py
python:
install:
- requirements: docs/requirements.txt
sphinx:
configuration: docs/conf.py
formats: all
moderngl-moderngl-773b733/CHANGELOG.md 0000664 0000000 0000000 00000054473 14704200620 0017230 0 ustar 00root root 0000000 0000000 # Change Log
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [main](https://github.com/moderngl/moderngl/compare/5.10.0...main)
- Add `Context.debug_scope`.
## [5.10.0](https://github.com/moderngl/moderngl/compare/5.9.0...5.10.0)
- Adding pre-built wheels for MacOS ARM
- Adding size verify when writing to Uniforms
- Adding a new methods: [get_context()](https://moderngl.readthedocs.io/en/latest/reference/moderngl.html#moderngl.moderngl.get_context) and `init_context()` (documentation is not ready yet)
- Complementing old and adding new items to ["The Guide"](https://moderngl.readthedocs.io/en/latest/the_guide/index.html)
- Redesign of ["The Guide"](https://moderngl.readthedocs.io/en/latest/the_guide/index.html) in the documentation
- Adding shadow mapping example (see `examples/*`)
- Improving code reliability (robustness)
## [5.9.0](https://github.com/moderngl/moderngl/compare/5.8.0...5.9.0)
- Removing Python 3.7 support, adding Python 3.12 support
- Fixing memory leaks
- Transferring constants from `moderngl` to `moderngl.Context` (safely)
- Dividing documentation into annotations (`moderngl-stubs/__init__.pyi`) and full documentation (`docs/*`)
- Implemented new property: [Context.depth_clamp_range](https://moderngl.readthedocs.io/en/latest/reference/context.html#Context.depth_clamp_range)
- Adding shader includes
- Adding an example of creating a separate window object
- Adding access to input attributes in SPIR-V programs (via SPIR-V parsing) (example: `vao = ctx.vertex_array(spv_program, buffer, 0, 1)` (if your SPIR-V compiler did not erase attribute names, they can also be used))
- Adding access to program attributes by their location numbers (example: `vao = ctx.vertex_array(program, buffer, 0, 1)`)
- Adding descriptions for [Context.memory_barrier()](https://moderngl.readthedocs.io/en/latest/reference/context.html#Context.memory_barrier) and [Context.depth_clamp_range](https://moderngl.readthedocs.io/en/latest/reference/context.html#Context.depth_clamp_range) in the documentation
- Fixed inaccuracies in documentation
- Implemented depth cube maps: [Context.depth_texture_cube()](https://moderngl.readthedocs.io/en/latest/reference/context.html#Context.depth_texture_cube)
- Update build documentation command (sphinx) (see in `README.md`)
- Minor changes to `README.md`
## [5.8.0](https://github.com/moderngl/moderngl/compare/5.7.4...5.8.0)
This version includes the following structural changes in moderngl:
- The typehints and inline documentation was moved to moderngl-stubs.
- The Python layer was concatenated but moderngl itself stays a package.
- Most of the protected class members were removed.
- Most of the property aliases became ordinary class members.
- Slots were removed.
## [5.7.4](https://github.com/moderngl/moderngl/compare/5.7.3...5.7.4)
...
## [5.7.3](https://github.com/moderngl/moderngl/compare/5.7.2...5.7.3)
...
## [5.7.2](https://github.com/moderngl/moderngl/compare/5.7.1...5.7.2)
...
## [5.7.1](https://github.com/moderngl/moderngl/compare/5.7.0...5.7.1)
...
## [5.7.0](https://github.com/moderngl/moderngl/compare/5.6.4...5.7.0)
* Python 3.11 support
* Added support for configurable garbage collection mode. ``Context.gc_mode`` controls this.
* ``None``: (default) No garbage collection is performed. Objects needs to to be
manually released like in previous versions of moderngl.
* ``"context_gc"``: Dead objects are collected in ``Context.objects``.
These can periodically be released using ``Context.gc()``.
* ``"auto"``: Dead objects are destroyed automatically like we would expect in python.
* Added support for `glPolygonOffset`. The factors and units can be set using `Context.polygon_offset`
* Added support for normalized signed and unsigned integer textures. `ni1`, `nu1`, `ni2` and `nu2`
are the new dtypes for these.
* Added ``Context.external_texture`` for creating textures from existing OpenGL textures.
* Added `TextureCube.bind_to_image` so we can easily access cube textures in compute shaders
* Added `Texture3D.bind_to_image` so we can easily access 3D textures in compute shaders
* Added `TextureArray.bind_to_image` so we can easily access texture arrays in compute shaders
* Added support for specifying a custom internalformat for cube maps. This can be used
for sRGB and texture compression formats.
* Integer textures now use `NEAREST` interpolation by default. This was causing
issues with some drivers.
* Added support for writing to multiple buffers in transforms.
* ``Context.program`` now accepts a dictionary for mapping sampler names to specific texture units.
* Added `Program.is_transform` exposing if the program has a fragment shader or not
* Added `VertexArray.mode` and a `mode` argument in `Context.vertex_array`.
This is now the default rendering mode when no mode parameter is passed
in `render()` or `transform()`
* Added support for 1D sampler in `Uniform`
* Added direct access to `glEnable` / `glDisable` in `Context.enable_direct` / `Context.disable_direct`.
This can be used to enabled capabilities not supported by ModernGL.
* `Framebuffer.read()` now has a `clamp` (bool) parameter. If enabled, floating point data
will clamp to `[0.0, 1.0]`. Clamping is disabled by default.
* Fixed a bug causing ``copy_framebuffer`` to not work with multisampled framebuffers
with multiple color attachments.
* Fixed a bug in ``copy_framebuffer`` that caused the draw buffers to be permanently
changed.
* VertexArray: Removed "the first vertex attribute must not be a per instance attribute" limitation
* Fixed a crash when reading `ctx.provoking_vertex`
* Added workaround for MacOS requiring a framebuffer to be bound in headless mode even for
transform shaders. We simply create and bind a framebuffer internally.
* Added ``GL_MAX_GEOMETRY_OUTPUT_VERTICES`` to ``Context.info``
* Docstring improvements
* Documentation improvements
## [5.6.4](https://github.com/moderngl/moderngl/compare/5.6.3...5.6.4)
* Transform feedback now supports all primitive modes both for
vertex and geometry shaders
* `VertexArray.transform()` now raises sane errors when using the wrong primitive mode with geometry shaders
* `VertexArray.transform()` now automatically detects output primitive based on
the input mode.
* `GL_TRIANGLES_ADJACENCY` enum incorrectly mapped (`D0` instead of `0D`)
* Primitive modes are now accessible in the `Context` instance.
For example: `ctx.POINTS` and `ctx.TRIANGLES`
* Texture filers are now also available in the `Context` instance.
For example: `ctx.NEAREST` and `ctx.LINEAR`
* Docstring and documentation improvements
## [5.6.3](https://github.com/moderngl/moderngl/compare/5.6.2...5.6.3)
* Added `Context.extensions`. This is a `set` containing the
OpenGL extensions supported by the context.
* Added support for overridable internal_format for `Texture`.
This opens up for sRGB and compressed formats if needed.
* Docstring and documentation improvements
## [5.6.2](https://github.com/moderngl/moderngl/compare/5.6.1...5.6.2)
### Bugs
* `TextureArray.build_mimpmaps()` used the wrong target when building mipmaps.
This caused the texture to corrupt with some drivers. Thanks to [Nir Aides](https://github.com/nir)
for discovering this bug.
* Docstring improvements
## [5.6.1](https://github.com/moderngl/moderngl/compare/5.6.0...5.6.1)
### Improvements
* Added `Context.cull_face`. (`glCullFace`). An alternative to `Context.front_face` (`glFrontFace`)
* Added support for signed and unsigned integer sampler uniforms (`isampler*`, `usampler*`)
* Added support for multisampled texture array samplers
* Doc improvements
### Bugs
* Transform feedback with geo shader should now property set the out primitive type.
It incorrectly assumed `POINTS` in some cases causing a gl error.
* Moderngl will now propagate the default error messages when objects cannot
be read using the buffer protocol.
## [5.6.0](https://github.com/moderngl/moderngl/compare/5.5.4...5.6.0) - 2020-02-01
From ModernGL 5.6 context creation is done by the [glcontext](https://github.com/moderngl/glcontext)
package. This means we can keep improving context creation without releasing new
moderngl versions. The bar for contributing to context creation is also lower.
Backends can be written in C++ or by simply using ctypes.
This version also has a lot of improvements to docsstrings, api docs and documentation in general.
Still we have a lot more work to do in this area.
### Added
- Standalone `Context` can now be destroyed on all platforms
- Compute shaders can now write to textures using `Texture*.bind_to_image`
- `VertexBuffer.transform` now as a `buffer_offset` parameter
for setting the start byte offset of the output buffer.
This can be used in many creative ways in for example particle
emitting.
- `Framebuffer` supports having only depth buffer. This makes things like shadow
mapping easier to work with.
- Support for `PROGRAM_POINT_SIZE` context flag so point sizes can be set in
the vertex shader
- Scissor test support. `Framebuffer.scissor` and `Context.scissor` can now be used
to set and enable scissor testing per framebuffer.
- The `Framebuffer.clear` have an optional `color` parameter to replace the
old `red, green, blue, alpha` parameters.
- Samplers and Buffers have an `assign` method to simplify the scope creation.
- Samplers have an optional `texture` parameter that will be used together with
the sampler when given.
- The Scope's `enable_only` keyword argument is deprecated in favor of the
`enable` keyword argument.
- Buffers have a `bind` method that replaces the tuples in the VertexArray creation.
- VertexArrays have an optional `scope` property that will be used when rendering.
- The VertexArray's `vertices` property is now writeable.
- VertexArrays have an `instances` property to control the default number of
instances when rendering.
- The Context object contains the constants provided by the moderngl module.
The constants are: (TRIANGLE, LINES, DEPTH_TEST, ...)
### Changed
- The `framebuffer` parameter is optional in Scopes.
- The `ctx.simple_vertex_array` is deprecated in favor of using `ctx.vertex_array` with the same parameters.
- The `prog[uniform].value = value` is deprecated in favor of using `prog[uniform] = value`.
- The `prog[uniform].write(bytes_value)` is deprecated in favor of using the `prog[uniform] = bytes_value`.
### Bugs
- Fixed an issue with attribute format detection causing integer and double types to fail
- Several minor bug fixes
## [5.5.4](https://github.com/moderngl/moderngl/compare/5.5.3...5.5.4) - 2019-11-10
This version was originally meant to only add python 3.8 support,
but a few additions and fixes where cherry-picked from the 5.6 branch.
- Python 3.8 support
- `Vertexarray`s can now be crated without any content.
- `Context.blend_func` now supports separate blend functions for rgb and alpha.
- Added `Context.blend_equation` supporting separate blend equations for rgb and alpha.
## [5.5.3](https://github.com/moderngl/moderngl/compare/5.5.2...5.5.3) - 2019-08-16
### Fixed
- Scope object uniform buffer bindings.
## [5.5.2](https://github.com/moderngl/moderngl/compare/5.5.1...5.5.2) - 2019-06-13
### Fixed
- missing package in setup.py
## [5.5.1](https://github.com/moderngl/moderngl/compare/5.5.0...5.5.1) - 2019-06-12
### Fixed
- offset fix for vao render
## [5.5.0](https://github.com/moderngl/moderngl/compare/5.4.2...5.5.0) - 2019-01-22
### Fixed
- depth texture filter and compare func
- scope restores old enable flags properly
- clear gl errors as the final step of initialization
- fix default framebuffer's number of attachments
### Added
- documentation for `extra` properties
- improved documentation
- improved build on Mac
## [5.4.2](https://github.com/moderngl/moderngl/compare/5.4.1...5.4.2) - 2018-08-01
### Fixed
- included `moderngl.program_members` in the package list
## [5.4.1](https://github.com/moderngl/moderngl/compare/5.4.0...5.4.1) - 2018-07-30
### Fixed
- broken description on PyPI
## [5.4.0](https://github.com/moderngl/moderngl/compare/5.3.0...5.4.0) - 2018-07-30
### Added
- Sampler object support
- `Context.sampler` method
- `Context.max_anisotropy` property
- `Context.clear_samplers` method
- `Framebuffer.read` and `Framebuffer.read_into` now accepts `attachment=-1` to read the depth attachment
- `Texture.compare_func` property
- `Texture.anisotropy` property
- docs and tests
### Fixed
- missing `ComputeShader` uniforms and uniform blocks
- wrong `DrawBuffer` call when clearing the screen
- reading depth values from textures
- broken compare functions
## [5.3.0](https://github.com/moderngl/moderngl/compare/5.2.1...5.3.0) - 2018-06-27
### Added
- `index_element_size` parameter for `Context.vertex_array` and `Context.simple_vertex_array`
### Fixed
- comapre fuctions
## [5.2.1](https://github.com/moderngl/moderngl/compare/5.2.0...5.2.1) - 2018-05-10
### Fixed
- markdown readme issues
## [5.2.0](https://github.com/moderngl/moderngl/compare/5.1.0...5.2.0) - 2018-05-10
### Added
- `Context.core_profile_check` method
- `GL_CONTEXT_PROFILE_MASK` to `Context.info`
- `GL_PATCHES` constant for drawing patches
- getter and setter for `GL_PATCH_VERTICES`
- markdown readme
### Fixed
- tesselation control and tesselation evaluation shader being swapped when creating a program
## [5.1.0](https://github.com/moderngl/moderngl/compare/5.0.7...5.1.0) - 2018-04-28
### Added
- offset and size parameter to `Buffer.bind_to_uniform_block`
- offset and size parameter to `Buffer.bind_to_storage_buffer`
- `GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT` to `Context.info`
## [5.0.7](https://github.com/moderngl/moderngl/compare/5.0.6...5.0.7) - 2018-04-08
### Fixed
- minor bugs in Buffer Format
## [5.0.6](https://github.com/moderngl/moderngl/compare/5.0.5...5.0.6) - 2018-03-22
### Fixed
- `standalone_context` on linux [issue #173](https://github.com/moderngl/moderngl/issues/173)
## [5.0.5](https://github.com/moderngl/moderngl/compare/5.0.4...5.0.5) - 2018-03-21
### Fixed
- Standalone context on linux fails when the default display is nonzero.
## [5.0.4](https://github.com/moderngl/moderngl/compare/5.0.3...5.0.4) - 2018-03-07
### Fixed
- Standalone context on windows fails when old GPU driver is installed.
## [5.0.3](https://github.com/moderngl/moderngl/compare/5.0.2...5.0.3) - 2018-02-28
### Added
- TextureArray objects
- Indirect drawing
### Changed
- Restored Error class from ModernGL4
### Fixed
- Properly set subroutines in VertexArray render
## [5.0.2](https://github.com/moderngl/moderngl/compare/5.0.1...5.0.2) - 2018-02-20
### Fixed
- Wrong module name in some windows based wheel files
## [5.0.1](https://github.com/moderngl/moderngl/compare/5.0.0...5.0.1) - 2018-02-19
### Fixed
- Build errors and warnings for older python versions
## [5.0.0](https://github.com/moderngl/moderngl/tree/5.0.0) - 2018-02-18
For more information please see: [Differences between ModernGL5 and ModernGL4](https://moderngl.readthedocs.io/en/stable/misc/mgl5_vs_mgl4.html)
### Added
- Query objects
- Scope objects
- Conditional Rendering
- New `RASTERIZER_DISCARD` enable flag
- Context fbo attribute
- Context depth_func and blend_func
- Depth Texture compare_func
### Changed
- Most of the constants became integers
- Renamed `default_framebuffer` to `screen` and always points to framebuffer 0
- VertexArray's buffer formats
- Program creation
- Program members
- Replace floats parameter with dtype
### Removed
- Classes and methods that are no longer needed
## [4.2.2](https://github.com/moderngl/moderngl/compare/4.2.1...4.2.2) - 2018-01-06
### Added
- Program.\_\_getitem\_\_ returns Uniforms, UniformBuffers, Attributes and Varyings
## [4.2.1](https://github.com/moderngl/moderngl/compare/4.2.0...4.2.1) - 2017-11-25
### Added
- UniformMap.get, AttributeMap.get, ... methods
### Fixed
- Context.info `GL_MAX_COMPUTE_WORK_GROUP_COUNT` value
- Missing TextureCube class
- Buffer.clear return type hint
## [4.2.0](https://github.com/moderngl/moderngl/compare/4.1.12...4.2.0) - 2017-10-17
### Added
- Default framebuffer bits attribute
- Context.detect_framebuffer
- Support reserving buffers with human readable sizes
### Fixed
- Standalone context on linux requires 24 bits for the depth buffer at least
- Bound framebuffer reference count
## [4.1.12](https://github.com/moderngl/moderngl/compare/4.1.11...4.1.12) - 2017-08-22
### Added
- TextureCube class and Context `texture_cube` method
- Context `enable_only` method
### Changed
- Enable flags support bitwise `__or__`, `__and__` and `__inv__`
- Framebuffer does not create a Renderbuffer when the depth_attachment is None
### Removed
- `ModernGL.MULTISAMPLE` constant
- Version class and Version constants
### Fixed
- Texture3D created with wrong type
## [4.1.11](https://github.com/moderngl/moderngl/compare/4.1.10...4.1.11) - 2017-07-02
### Added
- Context `front_face` attribute
### Fixed
- VertexArray `program` member type
- Context `viewport` attribute missing `tuple` cast
- Misplaced `GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS`
- Compile warnings (strict-prototypes)
- Initial value of `wireframe`
## [4.1.10](https://github.com/moderngl/moderngl/compare/4.1.9...4.1.10) - 2017-06-23
### Added
- Documentation improvements
- Context `max_samples` attribute
### Fixed
- Validate the number of samples using wrong values
## [4.1.9](https://github.com/moderngl/moderngl/compare/4.1.8...4.1.9) - 2017-06-23
### Added
- Context `info` attribute
- Support Textures in `copy_framebuffer`
- Texture `floats` attribute
### Fixed
- 3D texture `depth` attribute type
## [4.1.8](https://github.com/moderngl/moderngl/compare/4.1.7...4.1.8) - 2017-06-19
### Added
- 3D texture support (`Texture3D` class and Context `texture3d` method)
- Context `max_integer_samples` attribute
- Fallback display for linux
### Removed
- Unused texture's `read` method's `viewport` parameter
### Fixed
- Broken framebuffer `color_attachments` attribute
- Segmentation fault when creating a texture using string data by mistake
- Validate Renderbuffer and Texture samples
## [4.1.7](https://github.com/moderngl/moderngl/compare/4.1.6...4.1.7) - 2017-06-13
### Added
- Uniform `read` and `write` methods
- `write_offset` parameter for the `read_into` methods
- Read framebuffer's pixels to a buffer
- Read texture's pixels to a buffer
- Write texture's from a buffer
- Pixel Buffer Object
### Fixed
- Default framebuffer wrong drawbuffers
- Framebuffer non zero viewport settings
- Uniform setter error messages
## [4.1.6](https://github.com/moderngl/moderngl/compare/4.1.5...4.1.6) - 2017-06-12
### Fixed
- Broken uniform setter in 4.1.5
## [4.1.5](https://github.com/moderngl/moderngl/compare/4.1.4...4.1.5) - 2017-06-09
### Fixed
- Modifying framebuffer properties has no effect unless the framebuffer is explicitly bound
## [4.1.4](https://github.com/moderngl/moderngl/compare/4.1.3...4.1.4) - 2017-06-07
### Added
- Framebuffer `color_mask` attribute
- Framebuffer `depth_mask` attribute
- Framebuffer `viewport` attribute
### Fixed
- `copy_framebuffer` using `default_framebuffer`
- Failing `__repr__` in VertexArrays
### Changed
- Framebuffer methods do not affect the bound framebuffer
### Removed
- Invalid texture sampling parameters for multisample textures
- Invalid texture sampling parameters for depth textures
## [4.1.3](https://github.com/moderngl/moderngl/compare/4.1.2...4.1.3) - 2017-06-04
### Added
- TextureFilter and TextureWrap classes and constants
- Texture `build_mipmaps` method
- Texture `repeat_x`, `repeat_y` and `filter` attributes
- Texture `swizzle` getter
## [4.1.2](https://github.com/moderngl/moderngl/compare/4.1.1...4.1.2) - 2017-05-31
### Added
- Read any color attachments of the Framebuffer
- Framebuffer, Buffer, BufferAccess and Texture `read_into` method
- `__slots__` for ModernGL classes
- Framebuffer read different color attachments
- Tkinter connector for windows using ctypes
### Fixed
- Multiple render targets
- Non-float renderbuffers are not readable
- Buffer `read` keyword only `offset` argument
### Changed
- `Context.renderbuffer` will use `floats=False` by default
- `bind_to_uniform_block` `location` parameter was renamed to `binding`
- `bind_to_storage_buffer` `location` parameter was renamed to `binding`
## [4.1.1](https://github.com/moderngl/moderngl/compare/4.1.0...4.1.1) - 2017-05-27
### Added
- UniformBlock `binding` and `size` attribute
- Framebuffer `width`, `height` and `samples` attribute
- Texture `swizzle` attribute
- Context `error` attribute
- OpenGL objects as `glo` attributes
- Buffer `clear()` method
- Missing `release()` methods
- Iterable program member maps
- Human readable program members
- Pixel pack and unpack alignments
- Subroutines
### Removed
- UniformBlock `array_size` and `location` attribute
- VertexArrayAttribute `default` attribute
### Fixed
- BufferAccess unused `offset` parameter
- Binding buffer to a UniformBlock
- Broken RTD docs
## [4.1.0](https://github.com/moderngl/moderngl/compare/4.0.0...4.1.0) - 2017-05-24
### Added
- Exception handling when importing the implementation
- Standalone context on **linux** and **mac** with fallback mechanism
- Require version at context creation
- Context `version_code` property
- Framebuffer `clear()` method
### Changed
- Context `clear()` method accepts floats
### Removed
- Required `-std=c++11` for **linux** and **mac**
- ModernGL `VERSION` constant
## Fixed
- `Framebuffer` and `Texture` can have uninitialized x, y values
- Uniform setters
## [4.0.0](https://github.com/moderngl/moderngl/tree/4.0.0) - 2017-05-20
### Added
- Full linting support
- Restructure docs
- Examples in docs
- pep8 style
- VSCode snippets
- Changelog
### Changed
- Wrap the C/C++ module with a pure python module
- Rename internal module to avoid ambiguosity
- Rename class like members from the Context class
## [3.1.5](https://github.com/moderngl/moderngl/compare/3.1.0...3.1.5) - 2017-05-07
### Added
- Standalone ModernGL context
- Sphinx generated docs
- Linting with pylint mock file
- Mac OSX support
## [3.1.0](https://github.com/moderngl/moderngl/tree/3.1.0) - 2017-03-01
### Added
- Wrapping OpenGL objects with python types
### Changed
- Improved Linux support
### Removed
- Direct access to OpenGL objects
## [2.4.1](https://github.com/moderngl/moderngl/tree/2.4.1) - 2016-08-30
### Added
- setup.py and PyPI compatible packaging
- Direct access to OpenGL objects
- Linux support
## 1.0.0 - 2016-03-03
- It was a tool for me to develop games in python
moderngl-moderngl-773b733/LICENSE 0000664 0000000 0000000 00000002103 14704200620 0016403 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2017-2024 Szabolcs Dombi, Einar Forselv
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
moderngl-moderngl-773b733/MANIFEST.in 0000664 0000000 0000000 00000000110 14704200620 0017130 0 ustar 00root root 0000000 0000000 recursive-include src *.cpp *.hpp *.h
include README.md
include LICENSE
moderngl-moderngl-773b733/README.md 0000664 0000000 0000000 00000015176 14704200620 0016673 0 ustar 00root root 0000000 0000000
[](#readme)
# ModernGL
ModernGL is a Python wrapper over OpenGL Core. ModernGL simplifies the creation of graphics applications like scientific simulations, games or user interfaces.
Usually, acquiring in-depth knowledge of OpenGL requires a steep learning curve. In contrast, ModernGL is easy to learn and use.
ModernGL is capable of rendering with high performance and quality, with less code written.
```
pip install moderngl
```
- [Documentation](https://moderngl.readthedocs.io/)
- [Examples](https://github.com/moderngl/moderngl/tree/master/examples/#readme)
- [ModernGL on Github](https://github.com/moderngl/moderngl/)
- [ModernGL on PyPI](https://pypi.org/project/ModernGL/)
- [ModernGL Discord Server](https://discord.gg/UEMtW8D)
## Extras
### [glcontext](https://github.com/moderngl/glcontext) - Headless Context Creation
```
pip install moderngl[headless]
```
### [moderngl-window](https://github.com/moderngl/moderngl-window) - Window Creation and Resource Loading
```
pip install moderngl-window
```
## Features
- GPU accelerated high quality graphics
- Rendering modern OpenGL scenes with less headache
- Simpler and faster than PyOpenGL
- Can render without a window
- 100% Pythonic
## Sample usage
```py
>>> import moderngl
>>> ctx = moderngl.get_context()
>>> buf = ctx.buffer(b"Hello World!") # allocated on the GPU
>>> buf.read()
b'Hello World!'
```
For complete examples please visit the [Examples](https://github.com/moderngl/moderngl/tree/master/examples/#readme).
## Easy to use with Pillow
```py
>>> img = Image.open("texture.jpg").convert("RGB")
>>> ctx.texture(img.size, 3, img.tobytes())
```
## Easy to use with Numpy
```py
>>> ctx.buffer(np.array([0.0, 0.0, 1.0, 1.0], dtype="f4"))
```
## Compared to PyOpenGL
With PyOpenGL, using the original OpenGL API, you have to write three lines to
achieve a simple task like binding a VBO:
```py
vbo1 = GL.glGenBuffers(1)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo1)
GL.glBufferData(GL.GL_ARRAY_BUFFER, b"Hello World!", GL.GL_STATIC_DRAW)
vbo2 = GL.glGenBuffers(1)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo2)
GL.glBufferData(GL.GL_ARRAY_BUFFER, None, GL.GL_DYNAMIC_DRAW)
```
With ModernGL you need just one simple line per VBO to achieve the same results:
```py
vbo1 = ctx.buffer(b"Hello World!")
vbo2 = ctx.buffer(reserve=1024, dynamic=True)
```
## Development
```
git clone git@github.com:moderngl/moderngl.git
cd moderngl
python -m pip install -e .
```
## Using GLSL in ModernGL
GLSL (OpenGL Shading Language) is integral for shader programming using the ModernGL library. It allows developers to execute code on the GPU, enhancing graphics rendering performance. This concise introduction covers the core concepts necessary for starting with GLSL in ModernGL.
Data Types
GLSL offers standard data types similar to C, including int, float, double, and bool, as well as graphics-specific types like vectors (vec2, vec3, vec4) and matrices (mat2, mat3, mat4) for efficient graphics computations.
Inputs and Outputs
```
Attributes: Per-vertex data passed to the vertex shader. Commonly used for positions, normals, and texture coordinates.
Varyings: Interpolated data passed from the vertex to the fragment shader, such as colors or texture coordinates.
Output: Fragment shader's output, typically the color of the pixel (fragColor).
```
Uniforms
Uniforms are global variables declared in shaders, constant for all vertices or fragments for a single draw call. They're ideal for passing data from your application, like transformation matrices or material properties, to the shader.
Shader Types
```
Vertex Shader: Processes each vertex's attributes. It's the first stage in the shader pipeline, used for transformations and passing data to the fragment shader.
Fragment Shader: Calculates the color of each pixel. It uses data interpolated from the vertex shader to apply textures, lighting, and color.
Geometry Shader: Processes primitives (points, lines, triangles) formed by vertices from the vertex shader. It can add or remove vertices from the primitive.
Tessellation Shaders: Control the tessellation of patches, allowing for smoother geometries at varying distances.
Compute Shader: Handles general-purpose computing tasks not directly related to rendering images, like physics simulations or post-processing effects.
```
Example
```
glsl
// Vertex Shader
#version 330 core
in vec3 position;
uniform mat4 modelViewProjection;
void main() {
gl_Position = modelViewProjection * vec4(position, 1.0);
}
// Fragment Shader
#version 330 core
out vec4 fragColor;
void main() {
fragColor = vec4(1.0); // Set pixel color to white
}
```
This basic example demonstrates a vertex shader transforming vertex positions with a matrix and a fragment shader setting the color of each pixel to white.
## Notes
ModernGL may be faster than other libraries providing direct OpenGL access.
ModernGL is implemented in C++ and a single render call involving multiple OpenGL functions count as a single Python function call.
ModernGL require **OpenGL 3.3**. Compute Shaders require **OpenGL 4.3**.
Some functionality relies on specific extensions.
ModernGL can be used **anywhere where OpenGL is supported.** ModernGL is also working in a [headless](examples/headless) environment.
ModernGL is responsible for calling the OpenGL API and providing a Pythonic user-friendly API instead.
It is possible to integrate moderngl into any window libraries that support OpenGL.
Consider [moderngl-window](https://github.com/moderngl/moderngl-window) which implements many of them, plus it also helps with resource loading.
ModernGL does not implement the full OpenGL feature set or extensions. You can interact with the ModernGL objects from OpenGL.
## Citation
If you need to cite this repository in academic research:
```txt
@Online{Dombi2020,
author = {Szabolcs Dombi},
title = {ModernGL, high performance python bindings for OpenGL 3.3+},
date = {2020-05-01},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/moderngl/moderngl}},
commit = {}
}
```
The commit hash can be found in the [Releases](https://github.com/moderngl/moderngl/releases).
## Community
- [ModernGL Discord Server](https://discord.gg/UEMtW8D)
- [Contributors](https://github.com/moderngl/moderngl/graphs/contributors)
moderngl-moderngl-773b733/_moderngl.py 0000664 0000000 0000000 00000052605 14704200620 0017732 0 ustar 00root root 0000000 0000000 import struct
from typing import Any, Dict, List, Tuple
class Attribute:
def __init__(self):
self.gl_type = None
self.program_obj = None
self.scalar_type = None
self.rows_length = None
self.row_length = None
self.normalizable = None
self.location = None
self.array_length = None
self.dimension = None
self.shape = None
self.name = None
self.extra = None
def __repr__(self):
return f""
@property
def mglo(self):
return self
class Uniform:
def __init__(self):
self.program_obj = None
self.gl_type = None
self.fmt = None
self.location = None
self.array_length = None
self.element_size = None
self.dimension = None
self.name = None
self.matrix = None
self.ctx = None
self.extra = None
def __repr__(self):
return f""
@property
def mglo(self):
return self
@property
def value(self):
data = self.read()
if self.array_length > 1:
if self.dimension > 1:
return [
struct.unpack(self.fmt, data[i * self.element_size : i * self.element_size + self.element_size])
for i in range(self.array_length)
]
else:
return [
struct.unpack(self.fmt, data[i * self.element_size : i * self.element_size + self.element_size])[0]
for i in range(self.array_length)
]
elif self.dimension > 1:
return struct.unpack(self.fmt, data)
else:
return struct.unpack(self.fmt, data)[0]
@value.setter
def value(self, value):
if self.array_length > 1:
if self.dimension > 1:
data = b"".join(struct.pack(self.fmt, *row) for row in value)
else:
data = b"".join(struct.pack(self.fmt, item) for item in value)
elif self.dimension > 1:
data = struct.pack(self.fmt, *value)
else:
data = struct.pack(self.fmt, value)
self.write(data)
@property
def handle(self):
raise NotImplementedError
@handle.setter
def handle(self, value):
return self.ctx._set_uniform_handle(self.program_obj, self.location, value)
def read(self):
return self.ctx._read_uniform(
self.program_obj, self.location, self.gl_type, self.array_length, self.element_size
)
def write(self, data: Any):
self.ctx._write_uniform(
self.program_obj, self.location, self.gl_type, self.array_length, self.element_size, data,
)
class UniformBlock:
def __init__(self):
self.program_obj = None
self.index = None
self.size = None
self.name = None
self.ctx = None
self.extra = None
def __repr__(self):
return f""
@property
def mglo(self):
return self
@property
def binding(self):
return self.ctx._get_ubo_binding(self.program_obj, self.index)
@binding.setter
def binding(self, binding):
self.ctx._set_ubo_binding(self.program_obj, self.index, binding)
@property
def value(self):
return self.ctx._get_ubo_binding(self.program_obj, self.index)
@value.setter
def value(self, value):
self.ctx._set_ubo_binding(self.program_obj, self.index, value)
class StorageBlock:
def __init__(self):
self.program_obj = None
self.index = None
self.name = None
self.ctx = None
self.extra = None
def __repr__(self):
return f""
@property
def mglo(self):
return self
@property
def binding(self):
return self.ctx._get_storage_block_binding(self.program_obj, self.index)
@binding.setter
def binding(self, binding):
self.ctx._set_storage_block_binding(self.program_obj, self.index, binding)
@property
def value(self):
return self.ctx._get_storage_block_binding(self.program_obj, self.index)
@value.setter
def value(self, value):
self.ctx._set_storage_block_binding(self.program_obj, self.index, value)
class Subroutine:
def __init__(self):
self.index = None
self.name = None
self.extra = None
def __repr__(self):
return f""
@property
def mglo(self):
return self
class Varying:
def __init__(self):
self.number = None
self.array_length = None
self.dimension = None
self.name = None
self.extra = None
def __repr__(self):
return f""
@property
def mglo(self):
return self
class DefaultLoader:
def __init__(self):
import ctypes
import sys
def funcptr(lib, name):
return ctypes.cast(getattr(lib, name, 0), ctypes.c_void_p).value or 0
if sys.platform.startswith("win"):
lib = ctypes.WinDLL("opengl32.dll")
proc = ctypes.cast(lib.wglGetProcAddress, ctypes.WINFUNCTYPE(ctypes.c_ulonglong, ctypes.c_char_p))
if not lib.wglGetCurrentContext():
raise RuntimeError("Cannot detect window with OpenGL support")
def loader(name):
return proc(name.encode()) or funcptr(lib, name)
elif sys.platform.startswith("linux"):
try:
lib = ctypes.CDLL("libEGL.so")
proc = ctypes.cast(lib.eglGetProcAddress, ctypes.CFUNCTYPE(ctypes.c_ulonglong, ctypes.c_char_p))
if not lib.eglGetCurrentContext():
raise RuntimeError("Cannot detect window with OpenGL support")
def loader(name):
return proc(name.encode())
except:
lib = ctypes.CDLL("libGL.so")
proc = ctypes.cast(lib.glXGetProcAddress, ctypes.CFUNCTYPE(ctypes.c_ulonglong, ctypes.c_char_p))
if not lib.glXGetCurrentContext():
raise RuntimeError("Cannot detect window with OpenGL support")
def loader(name):
return proc(name.encode()) or funcptr(lib, name)
elif sys.platform.startswith("darwin"):
lib = ctypes.CDLL("/System/Library/Frameworks/OpenGL.framework/OpenGL")
def loader(name):
return funcptr(lib, name)
elif sys.platform.startswith("emscripten"):
lib = ctypes.CDLL(None)
def loader(name):
return funcptr(lib, name)
elif sys.platform.startswith("wasi"):
lib = ctypes.CDLL(None)
def loader(name):
return funcptr(lib, name)
self.load_opengl_function = loader
def __enter__(self):
pass
def __exit__(self, *args):
pass
def release(self):
pass
class Error(Exception):
pass
ATTRIBUTE_LOOKUP_TABLE = {
0x1404: (1, 0x1404, 1, 1, False, "i"),
0x8B53: (2, 0x1404, 1, 2, False, "i"),
0x8B54: (3, 0x1404, 1, 3, False, "i"),
0x8B55: (4, 0x1404, 1, 4, False, "i"),
0x1405: (1, 0x1405, 1, 1, False, "i"),
0x8DC6: (2, 0x1405, 1, 2, False, "i"),
0x8DC7: (3, 0x1405, 1, 3, False, "i"),
0x8DC8: (4, 0x1405, 1, 4, False, "i"),
0x1406: (1, 0x1406, 1, 1, True, "f"),
0x8B50: (2, 0x1406, 1, 2, True, "f"),
0x8B51: (3, 0x1406, 1, 3, True, "f"),
0x8B52: (4, 0x1406, 1, 4, True, "f"),
0x140A: (1, 0x140A, 1, 1, False, "d"),
0x8FFC: (2, 0x140A, 1, 2, False, "d"),
0x8FFD: (3, 0x140A, 1, 3, False, "d"),
0x8FFE: (4, 0x140A, 1, 4, False, "d"),
0x8B5A: (4, 0x1406, 2, 2, True, "f"),
0x8B65: (6, 0x1406, 2, 3, True, "f"),
0x8B66: (8, 0x1406, 2, 4, True, "f"),
0x8B67: (6, 0x1406, 3, 2, True, "f"),
0x8B5B: (9, 0x1406, 3, 3, True, "f"),
0x8B68: (12, 0x1406, 3, 4, True, "f"),
0x8B69: (8, 0x1406, 4, 2, True, "f"),
0x8B6A: (12, 0x1406, 4, 3, True, "f"),
0x8B5C: (16, 0x1406, 4, 4, True, "f"),
0x8F46: (4, 0x140A, 2, 2, False, "d"),
0x8F49: (6, 0x140A, 2, 3, False, "d"),
0x8F4A: (8, 0x140A, 2, 4, False, "d"),
0x8F4B: (6, 0x140A, 3, 2, False, "d"),
0x8F47: (9, 0x140A, 3, 3, False, "d"),
0x8F4C: (12, 0x140A, 3, 4, False, "d"),
0x8F4D: (8, 0x140A, 4, 2, False, "d"),
0x8F4E: (12, 0x140A, 4, 3, False, "d"),
0x8F48: (16, 0x140A, 4, 4, False, "d"),
}
UNIFORM_LOOKUP_TABLE = {
0x8B56: (False, 1, 4, "1i"),
0x8B57: (False, 2, 8, "2i"),
0x8B58: (False, 3, 12, "3i"),
0x8B59: (False, 4, 16, "4i"),
0x1404: (False, 1, 4, "1i"),
0x8B53: (False, 2, 8, "2i"),
0x8B54: (False, 3, 12, "3i"),
0x8B55: (False, 4, 16, "4i"),
0x1405: (False, 1, 4, "1I"),
0x8DC6: (False, 2, 8, "2I"),
0x8DC7: (False, 3, 12, "3I"),
0x8DC8: (False, 4, 16, "4I"),
0x1406: (False, 1, 4, "1f"),
0x8B50: (False, 2, 8, "2f"),
0x8B51: (False, 3, 12, "3f"),
0x8B52: (False, 4, 16, "4f"),
0x140A: (False, 1, 8, "1d"),
0x8FFC: (False, 2, 16, "2d"),
0x8FFD: (False, 3, 24, "3d"),
0x8FFE: (False, 4, 32, "4d"),
0x8B5D: (False, 1, 4, "1i"),
0x8DC0: (False, 1, 4, "1i"),
0x8DC9: (False, 1, 4, "1i"),
0x8DCE: (False, 1, 4, "1i"),
0x8B5E: (False, 1, 4, "1i"),
0x8DCA: (False, 1, 4, "1i"),
0x8DD2: (False, 1, 4, "1i"),
0x8DC1: (False, 1, 4, "1i"),
0x8DCF: (False, 1, 4, "1i"),
0x8DD7: (False, 1, 4, "1i"),
0x8B5F: (False, 1, 4, "1i"),
0x8DCB: (False, 1, 4, "1i"),
0x8DD3: (False, 1, 4, "1i"),
0x8B62: (False, 1, 4, "1i"),
0x9108: (False, 1, 4, "1i"),
0x9109: (False, 1, 4, "1i"),
0x910A: (False, 1, 4, "1i"),
0x910B: (False, 1, 4, "1i"),
0x910C: (False, 1, 4, "1i"),
0x910D: (False, 1, 4, "1i"),
0x8B60: (False, 1, 4, "1i"),
0x8DCC: (False, 1, 4, "1i"),
0x8DD4: (False, 1, 4, "1i"),
0x904D: (False, 1, 4, "1i"),
0x8B5A: (True, 4, 16, "4f"),
0x8B65: (True, 6, 24, "6f"),
0x8B66: (True, 8, 32, "8f"),
0x8B67: (True, 6, 24, "6f"),
0x8B5B: (True, 9, 36, "9f"),
0x8B68: (True, 12, 48, "12f"),
0x8B69: (True, 8, 32, "8f"),
0x8B6A: (True, 12, 48, "12f"),
0x8B5C: (True, 16, 64, "16f"),
0x8F46: (True, 4, 32, "4d"),
0x8F49: (True, 6, 48, "6d"),
0x8F4A: (True, 8, 64, "8d"),
0x8F4B: (True, 6, 48, "6d"),
0x8F47: (True, 9, 72, "9d"),
0x8F4C: (True, 12, 96, "12d"),
0x8F4D: (True, 8, 64, "8d"),
0x8F4E: (True, 12, 96, "12d"),
0x8F48: (True, 16, 128, "16d"),
}
def make_attribute(name, gl_type, program_obj, location, array_length):
tmp = ATTRIBUTE_LOOKUP_TABLE.get(gl_type, (1, 0, 1, 1, False, "?"))
dimension, scalar_type, rows_length, row_length, normalizable, shape = tmp
rows_length *= array_length
res = Attribute()
res.gl_type = gl_type
res.program_obj = program_obj
res.scalar_type = scalar_type
res.rows_length = rows_length
res.row_length = row_length
res.normalizable = normalizable
res.location = location
res.array_length = array_length
res.dimension = dimension
res.shape = shape
res.name = name
return res
def make_uniform(name, gl_type, program_obj, location, array_length, ctx):
tmp = UNIFORM_LOOKUP_TABLE.get(gl_type, (False, 1, 4, "1i"))
matrix, dimension, element_size, fmt = tmp
res = Uniform()
res.name = name
res.gl_type = gl_type
res.fmt = fmt
res.program_obj = program_obj
res.location = location
res.array_length = array_length
res.matrix = matrix
res.dimension = dimension
res.element_size = element_size
res.ctx = ctx
return res
def make_uniform_block(name, program_obj, index, size, ctx):
res = UniformBlock()
res.name = name
res.program_obj = program_obj
res.index = index
res.size = size
res.ctx = ctx
return res
def make_storage_block(name, program_obj, index, ctx):
res = StorageBlock()
res.name = name
res.program_obj = program_obj
res.index = index
res.ctx = ctx
return res
def make_subroutine(name, index):
res = Subroutine()
res.name = name
res.index = index
return res
def make_varying(name, number, array_length, dimension):
res = Varying()
res.number = number
res.name = name
res.array_length = array_length
res.dimension = dimension
return res
class Spv:
INT32 = 1 << 0
INT64 = 1 << 1
UINT32 = 1 << 2
UINT64 = 1 << 3
FLOAT32 = 1 << 4
FLOAT64 = 1 << 5
VEC2 = 1 << 10
VEC3 = 1 << 11
VEC4 = 1 << 12
MAT2 = 1 << 20
MAT3 = 1 << 21
MAT4 = 1 << 22
NONE = 0
UNKNOWN = 1 << 30
TRANSLATION_TABLE_SPIRV_GLSL = {
Spv.INT32: 0x1404,
Spv.INT32 | Spv.VEC2: 0x8B53,
Spv.INT32 | Spv.VEC3: 0x8B54,
Spv.INT32 | Spv.VEC4: 0x8B55,
Spv.UINT32: 0x1405,
Spv.UINT32 | Spv.VEC2: 0x8DC6,
Spv.UINT32 | Spv.VEC3: 0x8DC7,
Spv.UINT32 | Spv.VEC4: 0x8DC8,
Spv.FLOAT32: 0x1406,
Spv.FLOAT32 | Spv.VEC2: 0x8B50,
Spv.FLOAT32 | Spv.VEC3: 0x8B51,
Spv.FLOAT32 | Spv.VEC4: 0x8B52,
Spv.FLOAT64: 0x140A,
Spv.FLOAT64 | Spv.VEC2: 0x8FFC,
Spv.FLOAT64 | Spv.VEC3: 0x8FFD,
Spv.FLOAT64 | Spv.VEC4: 0x8FFE,
Spv.FLOAT32 | Spv.VEC2 | Spv.MAT2: 0x8B5A,
Spv.FLOAT32 | Spv.VEC3 | Spv.MAT2: 0x8B65,
Spv.FLOAT32 | Spv.VEC4 | Spv.MAT2: 0x8B66,
Spv.FLOAT32 | Spv.VEC2 | Spv.MAT3: 0x8B67,
Spv.FLOAT32 | Spv.VEC3 | Spv.MAT3: 0x8B5B,
Spv.FLOAT32 | Spv.VEC4 | Spv.MAT3: 0x8B68,
Spv.FLOAT32 | Spv.VEC2 | Spv.MAT4: 0x8B69,
Spv.FLOAT32 | Spv.VEC3 | Spv.MAT4: 0x8B6A,
Spv.FLOAT32 | Spv.VEC4 | Spv.MAT4: 0x8B5C,
Spv.FLOAT64 | Spv.VEC2 | Spv.MAT2: 0x8F46,
Spv.FLOAT64 | Spv.VEC3 | Spv.MAT2: 0x8F49,
Spv.FLOAT64 | Spv.VEC4 | Spv.MAT2: 0x8F4A,
Spv.FLOAT64 | Spv.VEC3 | Spv.MAT2: 0x8F4B,
Spv.FLOAT64 | Spv.VEC3 | Spv.MAT3: 0x8F47,
Spv.FLOAT64 | Spv.VEC4 | Spv.MAT3: 0x8F4C,
Spv.FLOAT64 | Spv.VEC2 | Spv.MAT4: 0x8F4D,
Spv.FLOAT64 | Spv.VEC3 | Spv.MAT4: 0x8F4E,
Spv.FLOAT64 | Spv.VEC4 | Spv.MAT4: 0x8F48,
}
def parse_spv_inputs(program: int, spv: bytes) -> Dict[int, Attribute]:
ui32 = struct.Struct("I")
token = lambda i: ui32.unpack(spv[i * 4 : i * 4 + 4])[0]
num_tokens = len(spv) // 4
if token(0) != 0x07230203 or len(spv) % 4 != 0:
raise ValueError("invalid spv")
idx = 5
extracted_names: Dict[int, str] = {} # id : name
extracted_storage_class_id: Dict[int, int] = {} # id : storage_class_id
extracted_constants: Dict[int, Tuple[int, bytes]] = {} # const_id : (type_id, content)
pointer_variable: Dict[int, int] = {} # id : pointer_type_id
pointer_allowed_types: Dict[int, int] = {} # pointer_type_id : type_id
allowed_types: Dict[int, Tuple[int, int, int, int]] = {} # type_id : (spv_type, type_id, arr_const_id, arr_length)
extracted_types: Dict[int, Tuple[int, int]] = {} # id : (spv_type, arr_length)
extracted_location: Dict[int, int] = {} # id : location
while idx < num_tokens:
args, opcode = token(idx) >> 16, token(idx) & 0xFFFF
if opcode == 5: # OpName
# We can extract the name of some ids
name_start, name_end = (idx + 2) * 4, (idx + args) * 4
extracted_names[token(idx + 1)] = spv[name_start:name_end].rstrip(b"\x00").decode()
if opcode == 59: # OpVariable
# We can extract if it is a vertex shader input or not
extracted_storage_class_id[token(idx + 2)] = token(idx + 3)
# Mapping pointer_type_id to id of user variables
pointer_variable[token(idx + 2)] = token(idx + 1)
if opcode == 71: # OpDecorate
# We can extract the location here
extracted_location[token(idx + 1)] = token(idx + 3)
if opcode == 32: # OpTypePointer
# Retrieving used (allowed) type_ids for pointer_type_ids
pointer_allowed_types[token(idx + 1)] = token(idx + 3)
if opcode == 21: # OpTypeInt
unsg, bsz = token(idx + 3), token(idx + 2) // 8
to_write = Spv.UNKNOWN
if unsg == 1:
if bsz == 4:
to_write = Spv.UINT32
elif bsz == 8:
to_write = Spv.UINT64
else:
if bsz == 4:
to_write = Spv.INT32
elif bsz == 8:
to_write = Spv.INT64
allowed_types[token(idx + 1)] = (to_write, -1, -1, -1)
if opcode == 22: # OpTypeFloat
to_write = Spv.UNKNOWN
bsz = token(idx + 2) // 8
if bsz == 4:
to_write = Spv.FLOAT32
elif bsz == 8:
to_write = Spv.FLOAT64
allowed_types[token(idx + 1)] = (to_write, -1, -1, -1)
if opcode == 23: # OpTypeVector
to_write = Spv.UNKNOWN
vsz = token(idx + 3)
if vsz == 2:
to_write = Spv.VEC2
elif vsz == 3:
to_write = Spv.VEC3
elif vsz == 4:
to_write = Spv.VEC4
allowed_types[token(idx + 1)] = (to_write, token(idx + 2), -1, -1)
if opcode == 24: # OpTypeMatrix
to_write = Spv.UNKNOWN
msz = token(idx + 3)
if msz == 2:
to_write = Spv.MAT2
elif msz == 3:
to_write = Spv.MAT3
elif msz == 4:
to_write = Spv.MAT4
allowed_types[token(idx + 1)] = (to_write, token(idx + 2), -1, -1)
if opcode == 28: # OpTypeArray
allowed_types[token(idx + 1)] = (Spv.NONE, token(idx + 2), token(idx + 3), -1)
if opcode == 43: # OpConstant
# OpConstant is needed to extract the length of arrays
# However, it can be used for other purposes
content_start, content_end = (idx + 3) * 4, (idx + args) * 4
extracted_constants[token(idx + 2)] = (token(idx + 1), spv[content_start:content_end])
idx += args
# Assembly types
# Some types of variables have pointers to other types of variables used in them.
# So we use endless research to identify complete types of variables.
def decode_constant(const_id):
type_id, content = extracted_constants[const_id]
typ, _ = assembly(type_id)
if typ == Spv.INT32:
return struct.unpack("i", content[:4])[0]
elif typ == Spv.INT64:
return struct.unpack("q", content[:8])[0]
elif typ == Spv.UINT32:
return struct.unpack("I", content[:4])[0]
elif typ == Spv.UINT64:
return struct.unpack("Q", content[:8])[0]
elif typ == Spv.FLOAT32:
return struct.unpack("f", content[:4])[0]
elif typ == Spv.FLOAT64:
return struct.unpack("d", content[:8])[0]
else:
return 0
def assembly(type_id):
typ, thrw_typ, arr_const_id, arr_length = allowed_types[type_id]
if arr_const_id != -1 and arr_length == -1:
arr_length = decode_constant(arr_const_id)
if thrw_typ != -1:
add_typ, multi_arr_length = assembly(thrw_typ)
typ = add_typ | typ
arr_length = arr_length * multi_arr_length
allowed_types[type_id] = (typ, -1, -1, arr_length if arr_length > 0 else 1)
return typ, arr_length
for type_id in allowed_types.keys():
assembly(type_id)
for ids, pointer_type_id in pointer_variable.items():
type_id = pointer_allowed_types[pointer_type_id]
if type_id in allowed_types:
extracted_types[ids] = (allowed_types[type_id][0], allowed_types[type_id][3])
# Making a whole list
exrtacted_general_ids: List[int] = sorted(
set(
[
*extracted_location.keys(),
*extracted_types.keys(),
*extracted_storage_class_id.keys(),
*extracted_names.keys(),
]
)
)
extracted_collected: Dict[int, Tuple[str, int, int, int, int]] = {} # id : variable_info
for ids in exrtacted_general_ids:
# to_add: Tuple[str, int, int, int] = () # name, class, type, location, arr_length
name, cls, typ, location, arr_length = "", -1, -1, -1, -1
if ids in extracted_names:
name = extracted_names[ids]
if ids in extracted_storage_class_id:
cls = extracted_storage_class_id[ids]
if ids in extracted_types:
typ, arr_length = extracted_types[ids]
if ids in extracted_location:
location = extracted_location[ids]
extracted_collected[ids] = (name, cls, typ, location, arr_length)
# Conversion to the GLSL type
for ids, item in extracted_collected.items():
if item[2] == -1 or item[2] not in TRANSLATION_TABLE_SPIRV_GLSL:
continue
extracted_collected[ids] = (item[0], item[1], TRANSLATION_TABLE_SPIRV_GLSL[item[2]], item[3], item[4])
# Cropping the data to the required output
return {
location: make_attribute(name, gltype, program, location, arr_length)
for name, cls, gltype, location, arr_length in extracted_collected.values()
if cls == 1 and location != -1 and gltype != -1
}
class InvalidObject:
pass
def resolve_includes(ctx, source):
def include(match):
name = match.group(1)
content = ctx.includes.get(name)
if content is None:
raise KeyError(f'cannot include "{name}"')
return content
import re
source = re.sub(r'#include\s+"([^"]+)"', include, source)
return source
moderngl-moderngl-773b733/docs/ 0000775 0000000 0000000 00000000000 14704200620 0016332 5 ustar 00root root 0000000 0000000 moderngl-moderngl-773b733/docs/_static/ 0000775 0000000 0000000 00000000000 14704200620 0017760 5 ustar 00root root 0000000 0000000 moderngl-moderngl-773b733/docs/_static/css/ 0000775 0000000 0000000 00000000000 14704200620 0020550 5 ustar 00root root 0000000 0000000 moderngl-moderngl-773b733/docs/_static/css/custom.css 0000664 0000000 0000000 00000001131 14704200620 0022570 0 ustar 00root root 0000000 0000000 /*
.wy-nav-content {
max-width: 800px;
}
*/
.hll {
background-color: #f2f8fb;
}
/*
.wy-nav-content {
max-width: 100%;
}
*/
.wy-breadcrumbs-aside {
display: none !important;
}
.wy-menu-vertical li.current a {
color: #545454;
}
.toctree-l1 a, .toctree-l2 a, .toctree-l3 a {
min-height: 32px;
}
/* Temporary fix for https://github.com/rtfd/sphinx_rtd_theme/issues/417 */
.rst-content .highlight>pre {
line-height: 18px;
}
.rubric {
/* font-size: 125%; */
font-weight: 700;
font-family: "Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;
}
em {
font-style: normal;
}
moderngl-moderngl-773b733/docs/_static/favicon.ico 0000664 0000000 0000000 00000004636 14704200620 0022112 0 ustar 00root root 0000000 0000000 ˆ ( 0 à à ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿôÿóÿóÿøÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿôÿÿÿÿÿû›ÿŽùÿ„ö…ÿ¡øÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛþÛÿ¸û·ÿoôoÿ_îaÿGèKÿ<äAÿwêmÿßúÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌþÍÿ“÷“ÿ[î]ÿ=ãCÿ.Ú7ÿ!Ó2ÿ2Ó3ÿSÖBÿŒãvÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓþÓÿŒ÷ŒÿRëUÿ1Ý9ÿ!Ñ0ÿÇ2ÿÀ1ÿ*À)ÿ?À(ÿ`È<ÿºê§ÿÿÿÿÿöß×ÿò¾´ÿñ˜ÿõnnÿÿëëÿÿûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÿíÿžùœÿSìUÿ.Ü8ÿÍ0ÿÀ4ÿ
´?ÿ°6ÿ)*ÿ8ªÿG©ÿ^¢ÿ·>ÿÑlIÿÖaFÿÞSDÿèHEÿ÷z{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂýÀÿbðcÿ:à@ÿÏ0ÿ¿4ÿ
Fÿ¢Lÿ >ÿ.3ÿ<š'ÿJ—ÿV•ÿh ÿ±QÿÀFÿÎ:!ÿÝ9/ÿî`^ÿû’”ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöÿöÿ–ø—ÿJèMÿ$Õ2ÿÄ3ÿ
±Cÿ˜_ÿ”Uÿ$‘Iÿ3Ž=ÿB‹1ÿPˆ&ÿ_…ÿk„
ÿ€yÿ°H
ÿÁ6ÿÒ0 ÿåC>ÿ÷‰ˆÿþÛÜÿÿÿÿÿÿÿÿÿÿÿÿÿíÿíÿxô{ÿOåYÿ,ÑCÿ½@ÿ Yÿ
…nÿ…^ÿ)‚Sÿ8GÿG|;ÿUy0ÿdv$ÿssÿsÿ˜aÿ¶<ÿÊ1ÿÞ<3ÿðbaÿþÎÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòþôÿuéƒÿ;ÑYÿ¹Jÿ…tÿwvÿ viÿ.s]ÿ=pQÿLmFÿZj:ÿif.ÿxd#ÿ†aÿ“a
ÿG
ÿÄ2ÿÙ5)ÿìVSÿüÉÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëüïÿbÚÿ ¶\ÿgŽÿiÿ%gsÿ3dgÿBa[ÿQ^Pÿ_ZDÿnW9ÿ}T-ÿŒQ!ÿšNÿ©J
ÿÁ4ÿÖ2%ÿëWSÿúœžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿêÿ,š‹ÿW•ÿZ‰ÿ*W}ÿ8TqÿGQfÿVNZÿdKNÿsHCÿ‚E7ÿ‘B+ÿŸ? ÿ®=ÿÀ5ÿÕ2%ÿëYVÿúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿDyÁÿ
Jœÿ K“ÿ/H‡ÿ=E|ÿLBpÿ[?dÿi¥ÿMšÿ\Žÿl‚ÿ|
uÿfÿ–[ÿ¥fÿÓ[}ÿÝdÿév…ÿó‡ŽÿúŒŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòóÿÿonöÿLGéÿ5*Ùÿ0Êÿ7½ÿA
±ÿO ¥ÿ[›ÿe”ÿg“ÿaÿg&´ÿ͸èÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéêþÿrrõÿMJèÿ8.Ûÿ1Îÿ3Äÿ6¼ÿ:·ÿ>·ÿBºÿM&ÄÿvX×ÿñïýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüÿÿÚÛþÿwwõÿXUëÿ=6àÿ6+Øÿ1 Ðÿ0Ìÿ/Ëÿ:#ÎÿR<×ÿŽ}çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿÿãäþÿ˜—ùÿmmòÿTQêÿC?äÿA;áÿ=6àÿ:4àÿ_Vèÿ¶¯öÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÐýÿŒùÿŽ÷ÿpoóÿsqóÿuuôÿuvõÿÛÙýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿââþÿþþÿÿÛÛþÿÎÏþÿøøÿÿûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ moderngl-moderngl-773b733/docs/_static/logo.png 0000664 0000000 0000000 00000246015 14704200620 0021436 0 ustar 00root root 0000000 0000000 ‰PNG
IHDR €¿6Ì sRGB ®Îé gAMA ±üa pHYs Ä Ä•+ ÿ¥IDATx^ìýk´e×uˆsϹ÷Ö@ P" P2IH²D¦Kˆ-›¶#£GwGc¤ÝÍŒöè(ý#Ã?óÓ¿•¤G¢NFºÙNšý°MÛq‡~È-ÛMYn‹mÊ(QHHxT¡Þuï=ï|ß|¬9×>ûP…G½ö¬šgÍõÍoεÎ=û¬uÖ~ŽÖ2È ƒ2È ×([V2È ƒ2È5É02È ƒr]2L ƒ2È ƒ\—È ƒ2È ×%Ã2È ƒ2ÈuÉ02È ƒr]2L ƒ2È ƒ\—È ƒ2È ×%Ã2È ƒ2ÈuÉ02È ƒr]2L ƒ2È ƒ\—È ƒ2È ×%Ã2È ƒ2ÈuÉ02È ƒr]2L ƒ2È ƒ\—È ƒ2È ×%Ã2È ƒ2ÈuÉ02È ƒr]2L ƒÜþòÔSf|@rp`Æ ƒÜY2L ƒÜÞòâ‹eýøã¥<û¬ï³pòøÚ׬2È w–È ·µ¬¿ñ
-9‰| ÂükLRø*gAnB&An¼ðü°hýܳeýV ´¦eýõ¯«ãýä/O>!æúë¿.å ƒÜI2L ƒÜX9uª¬ŸÅ@ÿÕ¯ðþÉú‰'Õi!õSojå½
&¼V529QQ_?õ´¸Þwޱr“Ê0rC…«N$ïã$"y_¶Õf/—_û;⯲þ‡§]g¨õ“6a½ŸÂ]cï÷ÊiAÞ'&An¨¬Ÿ~º¬1þÊ ÿâKeý›zÌâ½
sNUlRΟÇJä[V¹>Y?ùDYq÷˜÷[J(V7Ô÷Mx &5'‘a2ÈM(Ã2È
Y%`@±~ýÿ©¬Ÿ}N+×)rì«‘‘Ï1Ð/Ù†·{‚¸Õ¿ôIÎsSÔöƒöïY°"[ýtlè=þMäƒaäÆÉKXqØ žuõµ¿óž~ɯþ§oX.Ûuem¨ ‚Ayõø?²ú5â–ÿèq=ÞjhLN«g¿“âõÊ›˜<þÆW¥½šßwõ
2ÈM$Ã2È;~
—¯|åýÝÂAÜE_%ÔÕV _ý›×µJX}ç©²Æ ,RÓE^7W/¾¬ƒý5Èê[OÈY]"µÏZ¨h…+œë¼ç%Vë©ýîÞd›M† dwî‹çAnN"œLÞ‘øÂyû…ã%qËóµ¿ä„1ßz²æèËëuÊòV!ìïò·ûr»
þSÖÏþ “ß\‹°ÿ÷kuÓ´ÃÓ‡Id›L† dw”õK:pqP\}õo¼/“Èê;OËÀXÅ_³W§Þ*‹¯þ-¼Y}·gõ‘V5åå㿦öÕûò7¾.e#UHP8\ë)½l“Ç
ý׿Kê·Ù<á`An&&AÞQ8(ó—·Gî^z/¿†‘#ä®/ÚPêƒ2ÚY~ýŸiåjÂø]®>Ã*ä©ï¼ãñ–å¿üFØ7úiX3WOþŽïFØw[ñÝcM_S{׸ËmA>h&A®.Üò™R2É$ò7®ûl)9NÁI65¿ÝýË'~¿è¿£Ø!²üí'ÊúBç˜IÎåR±ð-¾ö÷ÍÚ”Õ÷Ÿ-ËßÑ«ÍÛ|mžIŠ£w賈MlGcuÂé´'³÷z€~AÞG&A®*¾ú𱎛£¸æ]5Õ÷mâIdó«^lŒ½ÁÅã¿vøJëâwÒê£/WÊÙõÎ_Iª+œæÿ8]m^5µR¥õ}-¾þÏ¥¼š,~ãë2yˆä¿GÓׄ«An"&A®.~¼#uð„òtØÕ5\˜ÇAyU¯÷\–<µQíÚ֨̾ú·{N/¸BÀ$ÒHóëݤæL>39Øwssp¼FlòªÝ}/µÎÕÅSß…Õ/<®"«±N\mKÄÚ0Îêéw±ªdI† d«Êúe;€ÎN1“4ÆñÅò7ßÝ©«0E6ÇÈÔFþõ
q.ä9&‘,¤<;ŠvÏÚŸ³›?þñª²øí'Êò=W›W€ÿ"uRñ’¢öòÿRÊ®p—ÛPiãrlWE
¹ÚýzÎðd@† äv’`ÿøŠ§ï6ã[à€»o…òÝœ1µúÁsÍà˜smˆ
̵-”ÜÝÄ•ˆ‹Ÿà5M¼U®’³ÃV/¾R–Ïþ ¬Þ:U¿uøÕæ^Ô÷Qm(|ù½Î_”kN²ÈäÁÕ
¤GåÎýìr®õú•Aù d˜@n'áýŸxÆû4‘È)±v`:ö2ÈÕ.
–(çW™D˜g3ÕA’’òð¿´á¥Ù5 ôh‡»œ0qðØ%ÚïXòUVÊìï?^fÿªä®>Ñ̇!â%$
ø!Š-¾ñM))\uÌ¿©WÊ÷Å×¶Ìn8fûiÕƒr£e˜@n#áî³Xù?/å}¸µ8Wø )’Æ2àŸ
nÜg_ù«›Ç$ Ü%äÒ7xk.kÄ
‘
î¨,žø2û›KúÌí‹wéä+¦åò‡Ï—Å¿ø-±«¯ ÓJí³”1àÇDW6Üí´üîSeÉÃWLÝx U,oO¾A¹d˜@n'±A[>«âñ(õë^}.bcZÌÚ1N¤èN½Ù{À{ùݸó®HÎã"~Ëãùωcú«ÿ°¬Ï]D-œq‘'k›Ûuuñ|Y¾ñZYžAy:_%ßæR‰6«ôMP;ûÕÇËüŸ½¬gº²é‹oûsX[Àñ9_íàü ƒ|X2L ·‘Èui¬á)¶Ë_ù¿]ÿÝmßz³ÌÚq,»NáUäS¬DXR䀴_§aÏ¥ªûEª8(—¯¿VÖ‹E™?ýƒ²º´Wó¨XéU‘>Ì„?r-_x^JÊò™JÙ·
‘þJi6|Jú®\.Ó¿÷÷Êê‚O¨›\–ü/’&¢n^—õKíq•A¹2L ·“äã>Ö`R‘ë5®ã‘«K^-Î