Package: zengl
ZenGLpip install zenglDocumentationzengl on Githubzengl on PyPIConceptZenGL is a low level graphics library.ZenGL turns OpenGL into Vulkan likeRendering PipelinesZenGL usesOpenGL 3.3 CoreandOpenGL 3.0 ES- runs everywhereZenGL provides a developer friendly experience in protyping complex scenesZenGL emerged from an experimental version ofModernGL.
To keep ModernGL backward compatible, ZenGL was re-designed from the ground-up to support a strict subset of OpenGL.
On the other hand, ModernGL supports a wide variety of OpenGL versions and extensions.ZenGL is "ModernGL hard mode"ZenGL intentionally does not support:Transform FeedbackGeometry ShadersTesselationCompute Shaders3D TexturesStorage BuffersMost of the above can be implemented in a more hardware friendly way using the existing ZenGL API.
Interoperability with other modules is also possible. Using such may reduce the application's portablity.
It is even possible to use direct OpenGL calls together with ZenGL, however this is likely not necessary.It is common to render directly to the screen with OpenGL.
With ZenGL, the right way is to render to a framebuffer and blit the final image to the screen.
This allows fine-grained control of the framebuffer format, guaranteed multisampling settings, correct depth/stencil precison.
It is also possible to render directly to the screen, however this feature is designed to be used for the postprocessing step.This design allows ZenGL to support:Rendering without a windowRendering to multiple windowsRendering to HDR monitorsRefreshing the screen without re-rendering the sceneApply post-processing without changing how the scene is renderedMaking reusable shaders and componentsTaking screenshots or exporting a videoThedefault framebufferin OpenGL is highly dependent on how the Window is created.
It is often necessary to configure the Window to provide the proper depth precision, stencil buffer, multisampling and double buffering.
Often the "best pixel format" lacks all of these features on purpose. ZenGL aims to allow choosing these pixel formats and ensures the user specifies the rendering requirements.
It is even possible to render low-resolution images and upscale them for high-resolution monitors.
Tearing can be easily prevented by decoupling the scene rendering from the screen updates.ZenGL was designed for PrototypingIt is tempting to start a project with Vulkan, however even getting a simple scene rendered requires tremendous work and advanced tooling to compile shaders ahead of time. ZenGL provides self-contained Pipelines which can be easily ported to Vulkan.
ZenGL code is verbose and easy to read.ZenGL support multiple design pattersMany libraries enfore certain design patterns.
ZenGL avoids this by providing cached pipeline creation, pipeline templating and lean resourece and framebuffer definition.
It is supported to create pipelines on the fly or template them for certain use-cases.TODO: examples for such pattersDisambiguationZenGL is a drop-in replacement for pure OpenGL codeUsing ZenGL requires some OpenGL knowledgeZenGL Images are OpenGLTexture Objectsor OpenGLRenderbuffer ObjectsZenGL Buffers are OpenGLBuffer ObjectsZenGL Pipelines contain an OpenGLVertex Array Object, an OpenGLProgram Object, and an OpenGLFramebuffer ObjectZenGL Pielines may also contain OpenGLSampler ObjectsCreating ZenGL Pipelines does not necessarily compile the shader from sourceThe ZenGL Shader Cache exists independently from the Pipeline objectsA Framebuffer is always represented by a Python list of ZenGL ImagesThere is noPipeline.clear()method, individual images must be cleared independentlyGLSL Uniform Blocks and sampler2D objects are bound in the Pipeline layoutTextures and Uniform Buffers are bound in the Pipeline resourcesExamplesSimple Pipeline Definitionpipeline=ctx.pipeline(# program definitionvertex_shader='...',fragment_shader='...',layout=[{'name':'Uniforms','binding':0,},{'name':'Texture','binding':0,},],# descriptor setsresources=[{'type':'uniform_buffer','binding':0,'buffer':uniform_buffer,},{'type':'sampler','binding':0,'image':texture,},],# uniformsuniforms={'color':[0.0,0.5,1.0],'iterations':10,},# program definition global statedepth={'func':'less','write':False,},stencil={'front':{'fail_op':'replace','pass_op':'replace','depth_fail_op':'replace','compare_op':'always','compare_mask':1,'write_mask':1,'reference':1,},'back':...,# or'both':...,},blend={'enable':True,'src_color':'src_alpha','dst_color':'one_minus_src_alpha',},cull_face='back',topology='triangles',# framebufferframebuffer=[color1,color2,...,depth],viewport=(x,y,width,height),# vertex arrayvertex_buffers=[*zengl.bind(vertex_buffer,'3f 3f',0,1),# bound vertex attributes*zengl.bind(None,'2f',2),# unused vertex attribute],index_buffer=index_buffer,# or Noneshort_index=False,# 2 or 4 byte intexvertex_count=...,instance_count=1,first_vertex=0,# override includesincludes={'common':'...',},)# some members are actually mutable and calls no OpenGL functionspipeline.viewport=...pipeline.vertex_count=...pipeline.uniforms['iterations'][:]=struct.pack('i',50)# writable memoryview# renderingpipeline.render()# no parameters for hot code