├── .gitignore ├── 3rdParty └── pyenv-2.5.7.tar.gz ├── LICENSE ├── README.rst ├── README_assimpy.rst ├── README_glass.rst ├── README_glass_engine.rst ├── assimpy ├── LICENSE ├── README_PYPI.md ├── __init__.py ├── __pyinstaller │ ├── __init__.py │ ├── assimp │ │ └── LICENSE │ ├── hook-assimpy.py │ └── pybind11 │ │ └── LICENSE ├── assimp-5.4.3.zip ├── assimpy_ext.cpp ├── assimpy_ext.h ├── module.cpp └── pybind11-2.13.6.zip ├── auto_format.py ├── build_assimpy.py ├── build_glass.py ├── build_glass_engine.py ├── glass ├── ACBO.py ├── AttrList.py ├── BO.py ├── Block.py ├── CSRMat.py ├── CodeCompressor │ ├── CodeCompressor.py │ ├── ShaderBuiltins.py │ ├── ShaderSyntaxTokens.py │ ├── __init__.py │ ├── generate_code.py │ ├── minifyc.py │ └── pcpp │ │ ├── LICENSE │ │ ├── __init__.py │ │ ├── evaluator.py │ │ ├── lextab.py │ │ ├── parser.py │ │ ├── parsetab.py │ │ ├── pcmd.py │ │ ├── ply │ │ ├── __init__.py │ │ ├── cpp.py │ │ ├── ctokens.py │ │ ├── lex.py │ │ ├── yacc.py │ │ └── ygen.py │ │ └── preprocessor.py ├── ComputeProgram.py ├── CustomLiteral.py ├── DictList.py ├── EBO.py ├── FBO.py ├── FBOAttachment.py ├── GLConfig.py ├── GLInfo.py ├── GLObject.py ├── GPUProgram.py ├── GlassConfig.py ├── ImageLoader.py ├── ImageUnits.py ├── Increment.py ├── Indices.py ├── Instances.py ├── LICENSE ├── MetaInstancesRecorder.py ├── RBO.py ├── README_PYPI.md ├── RenderHints.py ├── SSBO.py ├── SSUBO.py ├── SameTypeList.py ├── ShaderParser.py ├── ShaderProgram.py ├── ShaderStorageBlock.py ├── Shaders.py ├── TextLoader.py ├── TextureUnits.py ├── UBO.py ├── Uniform.py ├── UniformBlock.py ├── VAO.py ├── VBO.py ├── Vertices.py ├── WeakDict.py ├── WeakList.py ├── WeakRef.py ├── WeakSet.py ├── __init__.py ├── __pyinstaller │ ├── __init__.py │ └── hook-glass.py ├── callback_vec.py ├── download.py ├── glsl │ ├── draw_frame.vert │ └── shadertoy_template.frag ├── helper.py ├── iimage2D.py ├── image2D.py ├── isampler2D.py ├── isampler2DMS.py ├── sampler2D.py ├── sampler2DArray.py ├── sampler2DMS.py ├── samplerCube.py ├── uimage2D.py ├── usampler2D.py ├── usampler2DMS.py └── utils.py ├── glass_engine ├── AffineTransform.py ├── Animations │ ├── Animation.py │ ├── AnimationGroup.py │ ├── Chronoscope.py │ ├── EasingCurve.py │ ├── ParallelAnimation.py │ ├── SequentialAnimation.py │ └── __init__.py ├── Background.py ├── BasicScene.py ├── Camera.py ├── ColorMap.py ├── Fog.py ├── Frame.py ├── Geometries │ ├── Box.py │ ├── Circle.py │ ├── CircleFace.py │ ├── Cone.py │ ├── ConeSide.py │ ├── ConeTrustum.py │ ├── ConeTrustumSide.py │ ├── CoordSys.py │ ├── Cylinder.py │ ├── CylinderSide.py │ ├── CylindricalFSurf.py │ ├── Dodecahedron.py │ ├── EllipseFace.py │ ├── Extruder.py │ ├── FSurf.py │ ├── Floor.py │ ├── Hexahedron.py │ ├── HollowRPolygonFace.py │ ├── Icosahedron.py │ ├── Icosphere.py │ ├── ImageQuad.py │ ├── Octahedron.py │ ├── Point.py │ ├── Points.py │ ├── Polyline.py │ ├── Prism.py │ ├── PrismSide.py │ ├── Pyramid.py │ ├── PyramidSide.py │ ├── PyramidTrustum.py │ ├── PyramidTrustumSide.py │ ├── RPolygonFace.py │ ├── RectFace.py │ ├── Rotator.py │ ├── Sphere.py │ ├── SphericalCap.py │ ├── SphericalCapTop.py │ ├── SphericalFSurf.py │ ├── Surf.py │ ├── Tetrahedron.py │ ├── Torus.py │ ├── TorusFace.py │ ├── TrefoilKnot.py │ └── __init__.py ├── GlassEngineConfig.py ├── LICENSE ├── Lights │ ├── DirLight.py │ ├── Light.py │ ├── PointLight.py │ ├── SpotLight.py │ └── __init__.py ├── Manipulators │ ├── Manipulator.py │ ├── ModelViewManipulator.py │ ├── SceneRoamManipulator.py │ └── __init__.py ├── Material.py ├── Mesh.py ├── Model.py ├── Pivot.py ├── PostProcessEffects │ ├── ACESToneMapper.py │ ├── BloomEffect.py │ ├── DOFEffect.py │ ├── ExposureAdaptor.py │ ├── FXAAEffect.py │ ├── GaussBlur.py │ ├── KernelFilter.py │ ├── LUTEffect.py │ ├── MedianBlur.py │ ├── MulFilter.py │ ├── PostProcessEffect.py │ ├── PostProcessEffects.py │ ├── SSAOEffect.py │ ├── ShaderEffect.py │ └── __init__.py ├── README_PYPI.md ├── Renderers │ ├── CommonRenderer.py │ ├── DeferredRenderer.py │ ├── ForwardRenderer.py │ ├── Renderer.py │ └── __init__.py ├── Scene.py ├── SceneNode.py ├── Screens │ ├── PyQt5Screen.py │ ├── PyQt6Screen.py │ ├── PySide2Screen.py │ ├── PySide6Screen.py │ ├── QtScreen.py │ └── __init__.py ├── SkyBox.py ├── SkyDome.py ├── SlideAverageFilter.py ├── VideoRecorder.py ├── WeightedIntegrator.py ├── __init__.py ├── __pyinstaller │ ├── __init__.py │ └── hook-glass_engine.py ├── algorithm.py ├── glsl │ ├── Lights │ │ ├── DirLight.glsl │ │ ├── DirLight_lighting.glsl │ │ ├── DirLight_shadow_mapping.glsl │ │ ├── Lights.glsl │ │ ├── Lights_lighting.glsl │ │ ├── PointLight.glsl │ │ ├── PointLight_lighting.glsl │ │ ├── PointLight_shadow_mapping.glsl │ │ ├── SpotLight.glsl │ │ ├── SpotLight_lighting.glsl │ │ └── SpotLight_shadow_mapping.glsl │ ├── Pipelines │ │ ├── DirLight_depth │ │ │ ├── DirLight_depth.frag │ │ │ ├── DirLight_depth.geom │ │ │ ├── DirLight_depth.vert │ │ │ ├── DirLight_depth_lines.geom │ │ │ └── DirLight_depth_points.geom │ │ ├── OIT_blend.frag │ │ ├── PointLight_depth │ │ │ ├── PointLight_depth.frag │ │ │ ├── PointLight_depth.geom │ │ │ ├── PointLight_depth.vert │ │ │ ├── PointLight_depth_lines.geom │ │ │ └── PointLight_depth_points.geom │ │ ├── SpotLight_depth │ │ │ ├── SpotLight_depth.frag │ │ │ ├── SpotLight_depth.geom │ │ │ ├── SpotLight_depth_lines.geom │ │ │ └── SpotLight_depth_points.geom │ │ ├── deferred_rendering │ │ │ ├── deferred_rendering.frag │ │ │ ├── draw_points_to_gbuffer.frag │ │ │ ├── draw_to_gbuffer.frag │ │ │ ├── read_from_gbuffer.glsl │ │ │ └── write_to_gbuffer.glsl │ │ ├── draw_frame.frag │ │ ├── draw_geometry │ │ │ ├── draw_geometry.frag │ │ │ ├── draw_geometry.geom │ │ │ ├── draw_geometry.vert │ │ │ ├── draw_geometry_lines.vert │ │ │ ├── draw_geometry_points.frag │ │ │ └── draw_geometry_points.vert │ │ ├── env_mapping │ │ │ ├── env_OIT_blend.frag │ │ │ ├── gen_env_map.frag │ │ │ ├── gen_env_map.geom │ │ │ ├── gen_env_map.vert │ │ │ ├── gen_env_map_lines.geom │ │ │ ├── gen_env_map_points.frag │ │ │ ├── gen_env_map_points.geom │ │ │ └── gen_env_map_points.vert │ │ ├── forward_rendering │ │ │ ├── forward_draw_lines.vert │ │ │ ├── forward_draw_points.frag │ │ │ ├── forward_draw_points.vert │ │ │ ├── forward_rendering.frag │ │ │ ├── forward_rendering.geom │ │ │ └── forward_rendering.vert │ │ ├── skybox │ │ │ ├── skybox.frag │ │ │ └── skybox.vert │ │ └── skydome │ │ │ ├── skydome.frag │ │ │ └── skydome.vert │ ├── PostProcessEffects │ │ ├── ACES_tone_mapper.glsl │ │ ├── FXAA.frag │ │ ├── FXAA_array.frag │ │ ├── FXAA_cube.frag │ │ ├── SSAO_visibility.glsl │ │ ├── bloom_downsampling.frag │ │ ├── bloom_mix.frag │ │ ├── bloom_upsampling.frag │ │ ├── dof.frag │ │ ├── exposure_adaptor.glsl │ │ ├── gauss_blur.frag │ │ ├── gauss_blur_array.frag │ │ ├── gauss_blur_cube.frag │ │ ├── kernel_filter.frag │ │ ├── kernel_filter_array.frag │ │ ├── kernel_filter_cube.frag │ │ ├── lut.glsl │ │ ├── median_gray_blur5.glsl │ │ ├── mul_filter.glsl │ │ ├── shader_effect_template.frag │ │ ├── slit_stretch.glsl │ │ ├── star_field.glsl │ │ └── water_wave.glsl │ ├── ShadingModels │ │ ├── CookTorrance.glsl │ │ ├── Flat.glsl │ │ ├── Fresnel.glsl │ │ ├── Gouraud.glsl │ │ ├── Lambert.glsl │ │ ├── Minnaert.glsl │ │ ├── OrenNayar.glsl │ │ ├── Phong.glsl │ │ ├── PhongBlinn.glsl │ │ ├── Toon.glsl │ │ ├── lighting.glsl │ │ └── rim.glsl │ ├── check.py │ └── include │ │ ├── Camera.glsl │ │ ├── FXAA.glsl │ │ ├── FresnelRefract.glsl │ │ ├── InternalMaterial.glsl │ │ ├── Material.glsl │ │ ├── OIT.glsl │ │ ├── ShadingInfo.glsl │ │ ├── background.glsl │ │ ├── env_mapping.glsl │ │ ├── fog.glsl │ │ ├── image_read_write.glsl │ │ ├── limits.glsl │ │ ├── math.glsl │ │ ├── parallax_mapping.glsl │ │ ├── quat.glsl │ │ ├── random.glsl │ │ ├── sampling.glsl │ │ ├── shading_all.glsl │ │ ├── soft.glsl │ │ ├── tex_coord.glsl │ │ └── transform.glsl ├── images │ ├── glass_engine_logo256.png │ ├── glass_engine_logo411.png │ ├── glass_engine_logo64.png │ └── start.png └── lut.py ├── linux_install_python.sh ├── mac_install_python.sh ├── requirements.txt ├── setup_assimpy.py ├── setup_glass.py ├── setup_glass_engine.py ├── static_check.py ├── to-do-list.txt ├── upload_assimpy.py ├── upload_glass.py ├── upload_glass_engine.py └── windows_install_python.bat /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | __glcache__ 3 | workspace 4 | *.pyd/* 5 | build 6 | dist 7 | *.egg-info 8 | *.avi 9 | *.mp4 10 | .vscode 11 | upload.bat 12 | generate_md5.py 13 | used_shaders 14 | setup.py 15 | MANIFEST.in 16 | .python-version 17 | .DS_Store 18 | assimpy/assimp-*/* 19 | assimpy/pybind11-*/* 20 | assimpy/assimp/* 21 | assimpy/pybind11/* 22 | *.sqlite 23 | glass/CodeCompressor/tree-sitter-glsl/src/* 24 | test_* 25 | .venv* 26 | *.spv 27 | note.txt 28 | glass_engine/glsl/temp -------------------------------------------------------------------------------- /3rdParty/pyenv-2.5.7.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/3rdParty/pyenv-2.5.7.tar.gz -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2025 王炳辉 (binghui.wang@foxmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Glass Engine -- 易用的 Python 3D 渲染引擎 2 | ================================================================ 3 | 4 | .. figure:: glass_engine/images/glass_engine_logo256.png 5 | :align: center 6 | :alt: glass_engine_logo 7 | :width: 256px 8 | 9 | 10 | **Glass Engine** 是一个相当易用的 Python 实时 3D 渲染引擎,完全免费开源。使用 **Glass Engine** 你可以轻松地在你的 Python 界面程序中嵌入可交互的 3D 画面。 11 | 12 | 首先,使用以下命令即可完成对 **Glass Engine** 的安装, 13 | 14 | :: 15 | 16 | pip install glass-engine 17 | 18 | 如果你是中国区用户,使用以下命令则可以加速安装过程: 19 | 20 | :: 21 | 22 | pip install glass-engine -i https://mirrors.aliyun.com/pypi/simple 23 | 24 | 接下来,让我们通过一个简单例子来直观感受一下 **Glass Engine** 的使用过程: 25 | 26 | .. highlight:: python3 27 | 28 | :: 29 | 30 | from glass_engine import * 31 | from glass_engine.Geometries import * # 导入所有的基本几何体 32 | 33 | scene, camera, light, floor = SceneRoam() # 创建基本场景 34 | 35 | sphere = Sphere() # 创建一个球体模型 36 | sphere.position.z = 1 # 设置球体位置 37 | scene.add(sphere) # 将球体添加到场景中 38 | 39 | camera.screen.show() # 相机显示屏显示渲染结果 40 | 41 | 上述代码首先使用 ``SceneRoam`` 创建出一个基本场景,包括了相机、光源、地板,然后往场景中添加了一个球体模型,最后将相机观察到的视口显示出来。 42 | 43 | 可以看出,使用 **Glass Engine** 创建 3D 场景无需自定义任何类和任何函数,仅通过对象创建、方法调用的顺序程序结构就可完成场景的构建和显示,由此体现出 **Glass Engine** 高度的易用性,这也是 **Glass Engine** 相比于其他同类 3D 引擎的优势所在。 44 | 45 | 运行上述程序,你将得到下图所示结果: 46 | 47 | .. figure:: glass_engine/images/start.png 48 | :alt: glass_engine_simple_scene 49 | :align: center 50 | :width: 400px 51 | 52 | 53 | 你可以通过鼠标右键拖动以旋转视角,还可通过键盘按键 :kbd:`W` :kbd:`A` :kbd:`S` :kbd:`D` :kbd:`E` :kbd:`C` 来在场景中漫游: 54 | 55 | - :kbd:`A` 向左移动,:kbd:`D` 向右移动 56 | - :kbd:`W` 向前移动,:kbd:`S` 向后移动 57 | - :kbd:`E` 向上移动,:kbd:`C` 向下移动 58 | 59 | 怎么样,是不是很简单、直观、易用?如果你感兴趣的话,就让我们开始接下来的 3D 渲染之旅吧! 60 | 61 | - `文档 `_ 62 | - `PyPI 索引 `_ 63 | -------------------------------------------------------------------------------- /README_assimpy.rst: -------------------------------------------------------------------------------- 1 | Assimpy -- 为 Glass Engine 提供 3D 模型加载功能 2 | ================================================================ 3 | 4 | **Assimpy** 为 **Glass Engine** 的子项目,是 Assimp 项目的 Python 绑定,为 Glass Engine 提供 3D 模型加载功能。 5 | 仅提供 ``load(file_name:str, flags:int)->Model`` 函数用于加载模型。其优势在于: 6 | 7 | - 使用 assimp 加载模型后,不做任何的中间类型拷贝,直接将原生内存 buffer 暴露给 python 8 | - 支持内置纹理加载 9 | 10 | 你可以在任意需要加载 3D 模型的时候使用 **Assimpy**,并在其源码中找见加载上来的模型结构, 11 | 但不建议你这么做。因为其初衷是为 **Glass Engine** 提供 3D 模型的加载功能, 12 | 因此不过多介绍 **Assimpy** 的用法,欢迎访问 **Glass Engine** 项目: 13 | 14 | - `文档 `_ 15 | - `Github 项目主页 `_ 16 | - `Gitee 项目主页 `_ 17 | - `PyPI 索引 `_ 18 | 19 | **Glass Engine** 中的模型加载功能用法请参考 `Glass Engine 文档的模型加载章节 `_ -------------------------------------------------------------------------------- /README_glass.rst: -------------------------------------------------------------------------------- 1 | Glass -- 为 Glass Engine 提供 OpenGL 易用封装 2 | ================================================================ 3 | 4 | **Glass** 为 **Glass Engine** 的子项目,为 OpenGL Assistant 的缩写。 5 | OpenGL 函数的底层接口的设计为了跨平台,牺牲了易用性。 6 | 为了使 OpenGL 的调用对 Python 用户更友好,封装了 **Glass** 库。 7 | 该库简化了大量 OpenGL 概念以及函数调用方法,几项重点简化包括: 8 | 9 | - 支持从文件编译 Shader,支持在 Shader 中使用 ``include``,并将报错行号指向真实的 include 文件; 10 | - ShaderProgram 自动采用增量编译策略,仅当文件和依赖改变时重新编译; 11 | - 设置 Uniform/Uniform Block/Shader Storage Block 变量时,Python 对象可直接赋值给 Shader 中的对应结构变量; 12 | - 提供 Vertices/Indices 类对顶点和索引进行管理,用户无需接触 VBO/VAO/EBO 等直接操作显存的概念; 13 | - 变化的顶点和索引采用增量拷贝算法同步到显存,提高拷贝效率。 14 | 15 | 下面是一段不完整的代码展示了 glass 操作 OpenGL 的方法: 16 | 17 | .. highlight:: python3 18 | 19 | :: 20 | 21 | from glass import * 22 | 23 | # 在一个合法的 OpenGL 上下文中: 24 | 25 | # 创建 shader 程序 26 | program = ShaderProgram() 27 | program.compile("path/to/vertex_shader.vert") 28 | program.compile("path/to/fragment_shader.frag") 29 | # 上述两个 compile 并不会每次运行都编译,仅首次以及 Shader 文件修改后才编译 30 | # shader 文件中可含有 #include 语法 31 | 32 | # 将 Python 变量 pyvar 直接赋值给 Shader 端的 Uniform 结构体变量 uniform_var 33 | # 只要 Python 变量中含有对应的属性 34 | program["uniform_var"] = pyvar 35 | 36 | # 纹理 uniform 变量可用如下方法赋值 37 | # 对用户隐藏纹理单元概念 38 | program["sampler_var"] = sampler2D("path/to/image.png") 39 | 40 | # 创建顶点数组 41 | vertices = Vertices() # 像 list 一样操作 vertices,只不过元素只能为 Vertex 类型 42 | 43 | # 添加顶点 44 | vertices.append(Vertex(position=glm.vec2(-0.5,-0.5), color=glm.vec3(1,0,0))) 45 | vertices.append(Vertex(position=glm.vec2(0.5,-0.5), color=glm.vec3(0,1,0))) 46 | vertices.append(Vertex(position=glm.vec2(0,0.5), color=glm.vec3(0,0,1))) 47 | # 构建顶点 Vertex 时,属性名可为任意值 48 | # 只要在 vertex shader 中的 layout 指定了该属性名并且类型匹配 49 | 50 | # 创建索引数组 51 | indices = Indices() # 像 list 一样操作 indices,只不过元素只能为 glm.uvec3 类型 52 | indices.append(glm.uvec3(0, 1, 2)) 53 | 54 | # 绘制三角形 55 | program.draw_triangles(vertices=vertices, indices=indices) 56 | 57 | # vertices 和 indices 可在任意时刻动态修改内部元素,以及动态增加删除元素 58 | # 所有修改将在下次绘制时同步到显存 59 | 60 | 你可以在任意需要使用 OpenGL 的地方使用 **Glass**, 61 | 但其初衷是为 **Glass Engine** 提供 OpenGL 的封装,因此不过多介绍 **Glass** 的用法,欢迎访问 **Glass Engine** 项目: 62 | 63 | - `文档 `_ 64 | - `Github 项目主页 `_ 65 | - `Gitee 项目主页 `_ 66 | - `PyPI 索引 `_ 67 | -------------------------------------------------------------------------------- /README_glass_engine.rst: -------------------------------------------------------------------------------- 1 | Glass Engine -- 易用的 Python 3D 渲染引擎 2 | ================================================================ 3 | 4 | .. figure:: glass_engine/images/glass_engine_logo256.png 5 | :align: center 6 | :alt: glass_engine_logo 7 | :width: 256px 8 | 9 | 10 | **Glass Engine** 是一个相当易用的 Python 实时 3D 渲染引擎,完全免费开源。使用 **Glass Engine** 你可以轻松地在你的 Python 界面程序中嵌入可交互的 3D 画面。 11 | 12 | 首先,使用以下命令即可完成对 **Glass Engine** 的安装, 13 | 14 | :: 15 | 16 | pip install glass-engine 17 | 18 | 如果你是中国区用户,使用以下命令则可以加速安装过程: 19 | 20 | :: 21 | 22 | pip install glass-engine -i https://mirrors.aliyun.com/pypi/simple 23 | 24 | 接下来,让我们通过一个简单例子来直观感受一下 **Glass Engine** 的使用过程: 25 | 26 | .. highlight:: python3 27 | 28 | :: 29 | 30 | from glass_engine import * 31 | from glass_engine.Geometries import * # 导入所有的基本几何体 32 | 33 | scene, camera, light, floor = SceneRoam() # 创建基本场景 34 | 35 | sphere = Sphere() # 创建一个球体模型 36 | sphere.position.z = 1 # 设置球体位置 37 | scene.add(sphere) # 将球体添加到场景中 38 | 39 | camera.screen.show() # 相机显示屏显示渲染结果 40 | 41 | 上述代码首先使用 ``SceneRoam`` 创建出一个基本场景,包括了相机、光源、地板,然后往场景中添加了一个球体模型,最后将相机观察到的视口显示出来。 42 | 43 | 可以看出,使用 **Glass Engine** 创建 3D 场景无需自定义任何类和任何函数,仅通过对象创建、方法调用的顺序程序结构就可完成场景的构建和显示,由此体现出 **Glass Engine** 高度的易用性,这也是 **Glass Engine** 相比于其他同类 3D 引擎的优势所在。 44 | 45 | 运行上述程序,你将得到下图所示结果: 46 | 47 | .. figure:: glass_engine/images/start.png 48 | :alt: glass_engine_simple_scene 49 | :align: center 50 | :width: 400px 51 | 52 | 53 | 你可以通过鼠标右键拖动以旋转视角,还可通过键盘按键 :kbd:`W` :kbd:`A` :kbd:`S` :kbd:`D` :kbd:`E` :kbd:`C` 来在场景中漫游: 54 | 55 | - :kbd:`A` 向左移动,:kbd:`D` 向右移动 56 | - :kbd:`W` 向前移动,:kbd:`S` 向后移动 57 | - :kbd:`E` 向上移动,:kbd:`C` 向下移动 58 | 59 | 怎么样,是不是很简单、直观、易用?如果你感兴趣的话,就让我们开始接下来的 3D 渲染之旅吧! 60 | 61 | - `文档 `_ 62 | - `PyPI 索引 `_ 63 | -------------------------------------------------------------------------------- /assimpy/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2025 王炳辉 (binghui.wang@foxmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assimpy/README_PYPI.md: -------------------------------------------------------------------------------- 1 | # Assimpy -- 为 Glass Engine 提供 3D 模型加载功能 2 | 3 | **Assimpy** 为 **Glass Engine** 的子项目,是 Assimp 项目的 Python 绑定,为 Glass Engine 提供 3D 模型加载功能。 4 | 仅提供 ``load(file_name:str, flags:int)->Model`` 函数用于加载模型。其优势在于: 5 | 6 | * 使用 assimp 加载模型后,不做任何的中间类型拷贝,直接将原生内存 buffer 暴露给 python 7 | * 支持内置纹理加载 8 | 9 | 你可以在任意需要加载 3D 模型的时候使用 **Assimpy**,并在其源码中找见加载上来的模型结构, 10 | 但不建议你这么做。因为其初衷是为 **Glass Engine** 提供 3D 模型的加载功能, 11 | 因此不过多介绍 **Assimpy** 的用法,欢迎访问 **Glass Engine** 项目: 12 | 13 | * 文档: 14 | * Github 项目主页: 15 | * Gitee 项目主页: 16 | * PyPI 索引: 17 | 18 | **Glass Engine** 中的模型加载功能用法请参考: 19 | 20 | -------------------------------------------------------------------------------- /assimpy/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "5.4.3.3" 2 | 3 | from assimpy_ext import load -------------------------------------------------------------------------------- /assimpy/__pyinstaller/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def get_hook_dirs(): 4 | return [os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")] -------------------------------------------------------------------------------- /assimpy/__pyinstaller/hook-assimpy.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | self_folder = os.path.dirname(os.path.abspath(__file__)) 4 | datas = [ 5 | (os.path.abspath(self_folder + "/../LICENSE").replace("\\", "/"), "assimpy"), 6 | (os.path.abspath(self_folder + "/assimp/LICENSE").replace("\\", "/"), "assimpy/assimp"), 7 | (os.path.abspath(self_folder + "/pybind11/LICENSE").replace("\\", "/"), "assimpy/pybind11") 8 | ] 9 | -------------------------------------------------------------------------------- /assimpy/__pyinstaller/pybind11/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Wenzel Jakob , All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of 29 | external contributions to this project including patches, pull requests, etc. 30 | -------------------------------------------------------------------------------- /assimpy/assimp-5.4.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/assimpy/assimp-5.4.3.zip -------------------------------------------------------------------------------- /assimpy/pybind11-2.13.6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/assimpy/pybind11-2.13.6.zip -------------------------------------------------------------------------------- /auto_format.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | 5 | def auto_format(folder_name): 6 | subprocess.call([sys.executable, "-m", "black", folder_name]) 7 | 8 | 9 | auto_format("glass") 10 | auto_format("glass_engine") 11 | -------------------------------------------------------------------------------- /build_glass.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | import os 4 | import shutil 5 | 6 | try: 7 | if os.path.isdir("build"): 8 | shutil.rmtree("build") 9 | 10 | if os.path.isdir("python_glass.egg-info"): 11 | shutil.rmtree("python_glass.egg-info") 12 | 13 | with open("README_glass.rst", "r", encoding="utf-8") as in_file: 14 | content = in_file.read() 15 | 16 | with open("README.rst", "w", encoding="utf-8") as out_file: 17 | out_file.write(content) 18 | 19 | with open("setup_glass.py", "r", encoding="utf-8") as in_file: 20 | content = in_file.read() 21 | 22 | with open("setup.py", "w", encoding="utf-8") as out_file: 23 | out_file.write(content) 24 | 25 | with open("MANIFEST.in", "w", encoding="utf-8") as out_file: 26 | out_file.write( 27 | """include glass/README_PYPI.md 28 | include glass/LICENSE 29 | include glass/CodeCompressor/pcpp/LICENSE 30 | """) 31 | 32 | subprocess.call([sys.executable, "setup.py", "sdist", "bdist_wheel"]) 33 | finally: 34 | with open("README_glass_engine.rst", "r", encoding="utf-8") as in_file: 35 | content = in_file.read() 36 | 37 | with open("README.rst", "w", encoding="utf-8") as out_file: 38 | out_file.write(content) -------------------------------------------------------------------------------- /build_glass_engine.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | import os 4 | import shutil 5 | 6 | if os.path.isdir("build"): 7 | shutil.rmtree("build") 8 | 9 | if os.path.isdir("glass_engine.egg-info"): 10 | shutil.rmtree("glass_engine.egg-info") 11 | 12 | with open("README_glass_engine.rst", "r", encoding="utf-8") as in_file: 13 | content = in_file.read() 14 | 15 | with open("README.rst", "w", encoding="utf-8") as out_file: 16 | out_file.write(content) 17 | 18 | with open("setup_glass_engine.py", "r", encoding="utf-8") as in_file: 19 | content = in_file.read() 20 | 21 | with open("setup.py", "w", encoding="utf-8") as out_file: 22 | out_file.write(content) 23 | 24 | with open("MANIFEST.in", "w", encoding="utf-8") as out_file: 25 | out_file.write( 26 | """include glass_engine/images/glass_engine_logo256.png 27 | include glass_engine/images/start.png 28 | include glass_engine/README_PYPI.md 29 | include glass_engine/LICENSE 30 | """) 31 | 32 | subprocess.call([sys.executable, "setup.py", "sdist", "bdist_wheel"]) 33 | -------------------------------------------------------------------------------- /glass/ACBO.py: -------------------------------------------------------------------------------- 1 | from .BO import BO 2 | from .utils import capacity_of 3 | 4 | from OpenGL import GL 5 | import numpy as np 6 | 7 | 8 | class ACBO(BO): 9 | 10 | _basic_info = { 11 | "gen_func": GL.glGenBuffers, 12 | "bind_func": GL.glBindBuffer, 13 | "del_func": GL.glDeleteBuffers, 14 | "target_type": GL.GL_ATOMIC_COUNTER_BUFFER, 15 | "binding_type": GL.GL_ATOMIC_COUNTER_BUFFER_BINDING, 16 | "need_number": True, 17 | } 18 | 19 | _binding_points_pool = None 20 | 21 | _ACBO_map = {} 22 | 23 | def __init__(self) -> None: 24 | BO.__init__(self) 25 | 26 | @staticmethod 27 | def set(binding: int, offset: int, value: int) -> None: 28 | acbo = None 29 | if binding not in ACBO._ACBO_map: 30 | acbo = ACBO() 31 | acbo.malloc(4 * capacity_of(offset / 4), GL.GL_DYNAMIC_COPY) 32 | ACBO._ACBO_map[binding] = acbo 33 | else: 34 | acbo = ACBO._ACBO_map[binding] 35 | if offset + 4 > acbo.nbytes: 36 | temp_bo = ACBO() 37 | temp_bo.malloc(4 * capacity_of(offset / 4), GL.GL_DYNAMIC_COPY) 38 | acbo.copy_to(0, acbo.nbytes, temp_bo, 0) 39 | acbo.delete() 40 | acbo = temp_bo 41 | ACBO._ACBO_map[binding] = acbo 42 | 43 | acbo.bind_to_point(binding) 44 | acbo.bufferSubData(offset, 4, np.array([int(value)], dtype=np.uint32)) 45 | 46 | @staticmethod 47 | def get(binding: int, offset: int) -> int: 48 | if binding not in ACBO._ACBO_map: 49 | return 0 50 | 51 | acbo = ACBO._ACBO_map[binding] 52 | acbo.bind() 53 | data = np.array([0], np.uint32) 54 | GL.glGetBufferSubData(GL.GL_ATOMIC_COUNTER_BUFFER, offset, 4, data) 55 | return int(data[0]) 56 | 57 | def bind_to_point(self, binding_point: int) -> None: 58 | self.bind() 59 | GL.glBindBufferBase(GL.GL_ATOMIC_COUNTER_BUFFER, binding_point, self._id) 60 | -------------------------------------------------------------------------------- /glass/CodeCompressor/__init__.py: -------------------------------------------------------------------------------- 1 | from .CodeCompressor import CodeCompressor 2 | -------------------------------------------------------------------------------- /glass/CodeCompressor/pcpp/LICENSE: -------------------------------------------------------------------------------- 1 | (C) 2018-2019 Niall Douglas http://www.nedproductions.biz/ 2 | and (C) 2007-2019 David Beazley http://www.dabeaz.com/ 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | * Neither the name of the David Beazley or Dabeaz LLC may be used to 16 | endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /glass/CodeCompressor/pcpp/__init__.py: -------------------------------------------------------------------------------- 1 | from .evaluator import Evaluator 2 | from .parser import Action, OutputDirective 3 | from .pcmd import main, version, CmdPreprocessor 4 | from .preprocessor import Preprocessor 5 | 6 | __version__ = version 7 | -------------------------------------------------------------------------------- /glass/CodeCompressor/pcpp/ply/__init__.py: -------------------------------------------------------------------------------- 1 | # PLY package 2 | # Author: David Beazley (dave@dabeaz.com) 3 | 4 | __version__ = "3.11" 5 | __all__ = ["lex", "yacc"] 6 | -------------------------------------------------------------------------------- /glass/CustomLiteral.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Tuple, Type, Union 2 | 3 | 4 | class _CustomLiteralMeta(type): 5 | 6 | def __getitem__(cls, args: Union[Tuple[Any, ...], Any]) -> Type: 7 | if not isinstance(args, tuple): 8 | args = (args,) 9 | name = f"CustomLiteral[{', '.join(map(repr, args))}]" 10 | new_cls = type.__new__(_CustomLiteralMeta, name, (), {"__args__": args}) 11 | return new_cls 12 | 13 | def __instancecheck__(cls, instance: Any) -> bool: 14 | return any(instance == arg for arg in getattr(cls, "__args__", ())) 15 | 16 | def __contains__(cls, item: Any)->bool: 17 | return (item in cls.__args__) 18 | 19 | class CustomLiteral(metaclass=_CustomLiteralMeta): 20 | 21 | def __class_getitem__(cls, args) -> Type: 22 | return _CustomLiteralMeta.__getitem__(cls, args) -------------------------------------------------------------------------------- /glass/EBO.py: -------------------------------------------------------------------------------- 1 | from .BO import BO 2 | 3 | from OpenGL import GL 4 | 5 | 6 | class EBO(BO): 7 | 8 | _basic_info = { 9 | "gen_func": GL.glGenBuffers, 10 | "bind_func": GL.glBindBuffer, 11 | "del_func": GL.glDeleteBuffers, 12 | "target_type": GL.GL_ELEMENT_ARRAY_BUFFER, 13 | "binding_type": GL.GL_ELEMENT_ARRAY_BUFFER_BINDING, 14 | "need_number": True, 15 | } 16 | 17 | def __init__(self): 18 | BO.__init__(self) 19 | -------------------------------------------------------------------------------- /glass/GlassConfig.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import re 4 | 5 | from .GLConfig import GLConfig 6 | 7 | 8 | class GlassConfig: 9 | 10 | def __init__(self): 11 | self_folder = os.path.dirname(os.path.abspath(__file__)).replace("\\", "/") 12 | glass_engine_glsl_folder = os.path.abspath( 13 | self_folder + "/../glass_engine/glsl" 14 | ).replace("\\", "/") 15 | glass_glsl_folder = self_folder + "/glsl" 16 | if os.path.isdir(glass_engine_glsl_folder): 17 | self.__cache_folder = glass_engine_glsl_folder + "/__glcache__" 18 | else: 19 | self.__cache_folder = glass_glsl_folder + "/__glcache__" 20 | 21 | self.debug: bool = False 22 | self.print: bool = True 23 | self.warning: bool = True 24 | self.recompile: bool = False 25 | self.save_used_shaders: bool = False 26 | 27 | @property 28 | def cache_folder(self) -> str: 29 | if not os.path.isdir(self.__cache_folder): 30 | os.makedirs(self.__cache_folder) 31 | 32 | return self.__cache_folder 33 | 34 | @cache_folder.setter 35 | def cache_folder(self, folder_path: str): 36 | self.__cache_folder = folder_path 37 | 38 | @property 39 | def renderer_folder(self) -> str: 40 | santified_renderer = re.sub(r'[\\/:*?"<>|]', " ", GLConfig.renderer) 41 | renderer_folder = f"{self.__cache_folder}/{santified_renderer}" 42 | if not os.path.isdir(renderer_folder): 43 | os.makedirs(renderer_folder) 44 | 45 | return renderer_folder 46 | 47 | def clear_cache(self): 48 | if os.path.isdir(self.__cache_folder): 49 | shutil.rmtree(self.__cache_folder) 50 | 51 | 52 | GlassConfig = GlassConfig() 53 | -------------------------------------------------------------------------------- /glass/ImageUnits.py: -------------------------------------------------------------------------------- 1 | from .GLConfig import GLConfig 2 | 3 | 4 | class ImageUnits: 5 | def __init__(self): 6 | self._unit_image_map = {} 7 | self._image_unit_map = {} 8 | 9 | def __getitem__(self, unit: int) -> tuple: 10 | key = (GLConfig.buffered_current_context, unit) 11 | if key not in self._unit_image_map: 12 | return None 13 | 14 | return self._unit_image_map[key] 15 | 16 | def __setitem__(self, unit: int, image: tuple): 17 | context = GLConfig.buffered_current_context 18 | 19 | unit_key = (context, unit) 20 | if unit_key in self._unit_image_map: 21 | old_image = self._unit_image_map[unit_key] 22 | if old_image != image: 23 | del self._image_unit_map[context, old_image] 24 | 25 | image_key = (context, image) 26 | if image_key in self._image_unit_map: 27 | old_unit = self._image_unit_map[image_key] 28 | if old_unit != unit: 29 | del self._unit_image_map[context, old_unit] 30 | 31 | self._unit_image_map[unit_key] = image 32 | self._image_unit_map[image_key] = unit 33 | 34 | def unit_of_image(self, image: tuple) -> int: 35 | key = (GLConfig.buffered_current_context, image) 36 | if key not in self._image_unit_map: 37 | return None 38 | 39 | return self._image_unit_map[key] 40 | 41 | @property 42 | def available_unit(self): 43 | context = GLConfig.buffered_current_context 44 | 45 | for i in range(GLConfig.max_image_units): 46 | key = (context, i) 47 | if key not in self._unit_image_map: 48 | return i 49 | 50 | if self._unit_image_map[key] == 0: 51 | return i 52 | 53 | return None 54 | 55 | 56 | ImageUnits = ImageUnits() 57 | -------------------------------------------------------------------------------- /glass/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2025 王炳辉 (binghui.wang@foxmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /glass/MetaInstancesRecorder.py: -------------------------------------------------------------------------------- 1 | from .WeakSet import WeakSet 2 | import functools 3 | 4 | 5 | class MetaInstancesRecorder(type): 6 | 7 | _all_instances = {} 8 | 9 | @property 10 | def all_instances(cls): 11 | all_instances = WeakSet() 12 | for key, _set in MetaInstancesRecorder._all_instances.items(): 13 | if issubclass(key, cls): 14 | all_instances.update(_set) 15 | 16 | return all_instances 17 | 18 | def init(func): 19 | 20 | @functools.wraps(func) 21 | def wrapper(*args, **kwargs): 22 | self = args[0] 23 | if self.__class__ not in MetaInstancesRecorder._all_instances: 24 | MetaInstancesRecorder._all_instances[self.__class__] = WeakSet() 25 | 26 | MetaInstancesRecorder._all_instances[self.__class__].add(self) 27 | return func(*args, **kwargs) 28 | 29 | return wrapper 30 | 31 | def delete(func): 32 | 33 | @functools.wraps(func) 34 | def wrapper(*args, **kwargs): 35 | self = args[0] 36 | if self.__class__ in MetaInstancesRecorder._all_instances: 37 | MetaInstancesRecorder._all_instances[self.__class__].remove(self) 38 | 39 | return func(*args, **kwargs) 40 | 41 | return wrapper 42 | -------------------------------------------------------------------------------- /glass/README_PYPI.md: -------------------------------------------------------------------------------- 1 | # Glass -- 为 Glass Engine 提供 OpenGL 易用封装 2 | 3 | **Glass** 为 **Glass Engine** 的子项目,为 OpenGL Assistant 的缩写。 4 | OpenGL 函数的底层接口的设计为了跨平台,牺牲了易用性。 5 | 为了使 OpenGL 的调用对 Python 用户更友好,封装了 **Glass** 库。 6 | 该库简化了大量 OpenGL 概念以及函数调用方法,几项重点简化包括: 7 | 8 | * 支持从文件编译 Shader,支持在 Shader 中使用 ``include``,并将报错行号指向真实的 include 文件; 9 | * ShaderProgram 自动采用增量编译策略,仅当文件和依赖改变时重新编译; 10 | * 设置 Uniform/Uniform Block/Shader Storage Block 变量时,Python 对象可直接赋值给 Shader 中的对应结构变量; 11 | * 提供 Vertices/Indices 类对顶点和索引进行管理,用户无需接触 VBO/VAO/EBO 等直接操作显存的概念; 12 | * 变化的顶点和索引采用增量拷贝算法同步到显存,提高拷贝效率。 13 | 14 | 下面是一段不完整的代码展示了 glass 操作 OpenGL 的方法: 15 | 16 | ```python 17 | from glass import * 18 | 19 | # 在一个合法的 OpenGL 上下文中: 20 | 21 | # 创建 shader 程序 22 | program = ShaderProgram() 23 | program.compile("path/to/vertex_shader.vert") 24 | program.compile("path/to/fragment_shader.frag") 25 | # 上述两个 compile 并不会每次运行都编译,仅首次以及 Shader 文件修改后才编译 26 | # shader 文件中可含有 #include 语法 27 | 28 | # 将 Python 变量 pyvar 直接赋值给 Shader 端的 Uniform 结构体变量 uniform_var 29 | # 只要 Python 变量中含有对应的属性 30 | program["uniform_var"] = pyvar 31 | 32 | # 纹理 uniform 变量可用如下方法赋值 33 | # 对用户隐藏纹理单元概念 34 | program["sampler_var"] = sampler2D("path/to/image.png") 35 | 36 | # 创建顶点数组 37 | vertices = Vertices() # 像 list 一样操作 vertices,只不过元素只能为 Vertex 类型 38 | 39 | # 添加顶点 40 | vertices.append(Vertex(position=glm.vec2(-0.5,-0.5), color=glm.vec3(1,0,0))) 41 | vertices.append(Vertex(position=glm.vec2(0.5,-0.5), color=glm.vec3(0,1,0))) 42 | vertices.append(Vertex(position=glm.vec2(0,0.5), color=glm.vec3(0,0,1))) 43 | # 构建顶点 Vertex 时,属性名可为任意值 44 | # 只要在 vertex shader 中的 layout 指定了该属性名并且类型匹配 45 | 46 | # 创建索引数组 47 | indices = Indices() # 像 list 一样操作 indices,只不过元素只能为 glm.uvec3 类型 48 | indices.append(glm.uvec3(0, 1, 2)) 49 | 50 | # 绘制三角形 51 | program.draw_triangles(vertices=vertices, indices=indices) 52 | 53 | # vertices 和 indices 可在任意时刻动态修改内部元素,以及动态增加删除元素 54 | # 所有修改将在下次绘制时同步到显存 55 | ``` 56 | 57 | 你可以在任意需要使用 OpenGL 的地方使用 **Glass**, 58 | 但其初衷是为 **Glass Engine** 提供 OpenGL 的封装,因此不过多介绍 **Glass** 的用法,欢迎访问 **Glass Engine** 项目: 59 | 60 | * [文档](https://glass-engine-doc.readthedocs.io/zh/latest/) 61 | * [Github 项目主页](https://github.com/Time-Coder/Glass-Engine) 62 | * [Gitee 项目主页](https://gitee.com/time-coder/Glass-Engine) 63 | * [PyPI 索引](https://pypi.org/project/glass-engine/) 64 | -------------------------------------------------------------------------------- /glass/ShaderStorageBlock.py: -------------------------------------------------------------------------------- 1 | from .Block import Block 2 | from .SSBO import SSBO 3 | 4 | 5 | class ShaderStorageBlock(Block): 6 | 7 | BO = SSBO 8 | 9 | def __init__(self, program): 10 | Block.__init__(self, program) 11 | -------------------------------------------------------------------------------- /glass/TextureUnits.py: -------------------------------------------------------------------------------- 1 | from .GLConfig import GLConfig 2 | 3 | 4 | class TextureUnits: 5 | def __init__(self): 6 | self._unit_texture_map = {} 7 | self._texture_unit_map = {} 8 | 9 | def __getitem__(self, unit: int) -> tuple: 10 | key = (GLConfig.buffered_current_context, unit) 11 | if key not in self._unit_texture_map: 12 | return None 13 | 14 | return self._unit_texture_map[key] 15 | 16 | def __setitem__(self, unit: int, texture: tuple): 17 | context = GLConfig.buffered_current_context 18 | 19 | unit_key = (context, unit) 20 | if unit_key in self._unit_texture_map: 21 | old_texture = self._unit_texture_map[unit_key] 22 | if old_texture != texture: 23 | del self._texture_unit_map[context, old_texture] 24 | 25 | texture_key = (context, texture) 26 | if texture_key in self._texture_unit_map: 27 | old_unit = self._texture_unit_map[texture_key] 28 | if old_unit != unit: 29 | del self._unit_texture_map[context, old_unit] 30 | 31 | self._unit_texture_map[unit_key] = texture 32 | self._texture_unit_map[texture_key] = unit 33 | 34 | @property 35 | def current_texture(self): 36 | return self[GLConfig.active_texture_unit] 37 | 38 | @current_texture.setter 39 | def current_texture(self, texture: tuple): 40 | self[GLConfig.active_texture_unit] = texture 41 | 42 | def unit_of_texture(self, texture: tuple) -> int: 43 | key = (GLConfig.buffered_current_context, texture) 44 | if key not in self._texture_unit_map: 45 | return None 46 | 47 | return self._texture_unit_map[key] 48 | 49 | @property 50 | def available_unit(self): 51 | context = GLConfig.buffered_current_context 52 | 53 | for i in range(GLConfig.max_texture_units): 54 | key = (context, i) 55 | if key not in self._unit_texture_map: 56 | return i 57 | 58 | if self._unit_texture_map[key] == 0: 59 | return i 60 | 61 | return None 62 | 63 | 64 | TextureUnits = TextureUnits() 65 | -------------------------------------------------------------------------------- /glass/UBO.py: -------------------------------------------------------------------------------- 1 | from .SSUBO import SSUBO 2 | 3 | from OpenGL import GL 4 | 5 | 6 | class UBO(SSUBO): 7 | 8 | _basic_info = { 9 | "gen_func": GL.glGenBuffers, 10 | "bind_func": GL.glBindBuffer, 11 | "del_func": GL.glDeleteBuffers, 12 | "target_type": GL.GL_UNIFORM_BUFFER, 13 | "binding_type": GL.GL_UNIFORM_BUFFER_BINDING, 14 | "need_number": True, 15 | } 16 | 17 | _binding_points_pool = None 18 | _current_context = 0 19 | 20 | def __init__(self): 21 | SSUBO.__init__(self) 22 | -------------------------------------------------------------------------------- /glass/UniformBlock.py: -------------------------------------------------------------------------------- 1 | from .Block import Block 2 | from .UBO import UBO 3 | 4 | 5 | class UniformBlock(Block): 6 | 7 | BO = UBO 8 | 9 | def __init__(self, shader_program): 10 | Block.__init__(self, shader_program) 11 | -------------------------------------------------------------------------------- /glass/VBO.py: -------------------------------------------------------------------------------- 1 | from .BO import BO 2 | 3 | from OpenGL import GL 4 | 5 | 6 | class VBO(BO): 7 | 8 | _basic_info = { 9 | "gen_func": GL.glGenBuffers, 10 | "bind_func": GL.glBindBuffer, 11 | "del_func": GL.glDeleteBuffers, 12 | "target_type": GL.GL_ARRAY_BUFFER, 13 | "binding_type": GL.GL_ARRAY_BUFFER_BINDING, 14 | "need_number": True, 15 | } 16 | 17 | def __init__(self): 18 | BO.__init__(self) 19 | self._location = -1 20 | -------------------------------------------------------------------------------- /glass/WeakList.py: -------------------------------------------------------------------------------- 1 | from .WeakRef import WeakRef 2 | 3 | from typing import Any, Iterable, Iterator, Union, List 4 | 5 | 6 | class WeakList: 7 | 8 | class iterator: 9 | def __init__(self, iterator: Iterator): 10 | self._iterator: Iterator = iterator 11 | 12 | def __next__(self) -> Any: 13 | return self._iterator.__next__().value 14 | 15 | def __iter__(self) -> Iterator: 16 | return self 17 | 18 | def __init__(self) -> None: 19 | self._list: List[WeakRef] = [] 20 | 21 | def __setitem__(self, index: Union[int, slice], value: Any) -> None: 22 | self._list[index] = WeakRef(value) 23 | 24 | def __getitem__(self, index: Union[int, slice]) -> Any: 25 | value: Any = self._list[index] 26 | if isinstance(index, slice): 27 | return list(map(lambda x: x.value, value)) 28 | else: 29 | return value.value 30 | 31 | def __delitem__(self, index: Union[int, slice]) -> None: 32 | del self._list[index] 33 | 34 | def __contains__(self, value: Any) -> bool: 35 | return WeakRef(value) in self._list 36 | 37 | def __len__(self) -> int: 38 | return self._list.__len__() 39 | 40 | def __bool__(self) -> bool: 41 | return bool(self._list) 42 | 43 | def __iter__(self) -> Iterator: 44 | return WeakList.iterator(self._list.__iter__()) 45 | 46 | def append(self, value: Any) -> None: 47 | self._list.append(WeakRef(value)) 48 | 49 | def insert(self, index: int, value: Any) -> None: 50 | self._list.insert(index, WeakRef(value)) 51 | 52 | def extend(self, value_list: Iterable): 53 | if isinstance(value_list, WeakList): 54 | self._list.extend(value_list._list) 55 | else: 56 | self._list.extend(map(lambda x: WeakRef(x), value_list)) 57 | 58 | def index(self, value: Any) -> int: 59 | return self._list.index(WeakRef(value)) 60 | 61 | def remove(self, value: Any) -> None: 62 | self._list.remove(WeakRef(value)) 63 | 64 | def pop(self, index: int) -> Any: 65 | return self._list.pop(index).value 66 | 67 | def clear(self) -> None: 68 | self._list.clear() 69 | -------------------------------------------------------------------------------- /glass/WeakRef.py: -------------------------------------------------------------------------------- 1 | from .utils import di 2 | 3 | from typing import Any, Union 4 | 5 | 6 | class WeakRef: 7 | 8 | def __init__(self, obj: Any) -> None: 9 | if isinstance(obj, (int, float, complex, bool, str, bytes, type(None))): 10 | self._obj_id: Union[int, float, complex, bool, str, bytes, None] = obj 11 | self._is_real_id: bool = False 12 | else: 13 | self._obj_id: Union[int, float, complex, bool, str, bytes, None] = id(obj) 14 | self._is_real_id: bool = True 15 | 16 | def __hash__(self) -> int: 17 | return hash(self._obj_id) 18 | 19 | def __eq__(self, other: Any) -> bool: 20 | if isinstance(other, WeakRef): 21 | return self._obj_id == other._obj_id 22 | else: 23 | return self.value == other 24 | 25 | def __repr__(self) -> str: 26 | return self.value.__repr__() 27 | 28 | @property 29 | def value(self) -> Any: 30 | if self._is_real_id: 31 | return di(self._obj_id) 32 | else: 33 | return self._obj_id 34 | -------------------------------------------------------------------------------- /glass/WeakSet.py: -------------------------------------------------------------------------------- 1 | from .WeakRef import WeakRef 2 | 3 | 4 | class WeakSet: 5 | 6 | class iterator: 7 | def __init__(self, _iterator): 8 | self._iterator = _iterator 9 | 10 | def __next__(self): 11 | value = self._iterator.__next__() 12 | return value.value 13 | 14 | def __iter__(self): 15 | return self 16 | 17 | def __init__(self): 18 | self._set = set() 19 | 20 | def __iter__(self): 21 | result = WeakSet.iterator(self._set.__iter__()) 22 | return result 23 | 24 | def __len__(self): 25 | return len(self._set) 26 | 27 | def __bool__(self): 28 | return bool(self._set) 29 | 30 | def __contains__(self, value): 31 | return WeakRef(value) in self._set 32 | 33 | def __repr__(self): 34 | return self._set.__repr__() 35 | 36 | def __sub__(self, other): 37 | result = WeakSet() 38 | if isinstance(other, WeakSet): 39 | result._set = self._set - other._set 40 | else: 41 | result._set = self._set - map(lambda x: WeakRef(x), other) 42 | 43 | return result 44 | 45 | def __add__(self, other): 46 | result = WeakSet() 47 | if isinstance(other, WeakSet): 48 | result._set = self._set + other._set 49 | else: 50 | result._set = self._set + map(lambda x: WeakRef(x), other) 51 | 52 | return result 53 | 54 | def __isub__(self, other): 55 | result = WeakSet() 56 | if isinstance(other, WeakSet): 57 | self._set -= other._set 58 | else: 59 | self._set -= map(lambda x: WeakRef(x), other) 60 | 61 | return result 62 | 63 | def __iadd__(self, other): 64 | result = WeakSet() 65 | if isinstance(other, WeakSet): 66 | self._set += other._set 67 | else: 68 | self._set += map(lambda x: WeakRef(x), other) 69 | 70 | return result 71 | 72 | def add(self, value): 73 | self._set.add(WeakRef(value)) 74 | 75 | def remove(self, value): 76 | ref_value = WeakRef(value) 77 | if ref_value in self._set: 78 | self._set.remove(ref_value) 79 | 80 | def pop(self): 81 | return self._set.pop().value 82 | 83 | def clear(self): 84 | self._set.clear() 85 | 86 | def update(self, new_set): 87 | if isinstance(new_set, WeakSet): 88 | self._set.update(new_set._set) 89 | else: 90 | self._set.update(map(lambda x: WeakRef(x), new_set)) 91 | -------------------------------------------------------------------------------- /glass/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.1.64" 2 | 3 | from .VAO import VAO 4 | from .VBO import VBO 5 | from .EBO import EBO 6 | from .FBO import FBO 7 | from .RBO import RBO 8 | from .SSBO import SSBO 9 | from .UBO import UBO 10 | from .ACBO import ACBO 11 | 12 | from .sampler2D import sampler2D 13 | from .usampler2D import usampler2D 14 | from .isampler2D import isampler2D 15 | from .image2D import image2D 16 | from .uimage2D import uimage2D 17 | from .iimage2D import iimage2D 18 | from .sampler2DMS import sampler2DMS 19 | from .isampler2DMS import isampler2DMS 20 | from .usampler2DMS import usampler2DMS 21 | from .samplerCube import samplerCube 22 | from .sampler2DArray import sampler2DArray 23 | 24 | from .Vertices import Vertices, Vertex 25 | from .Indices import Indices 26 | from .Instances import Instance, Instances 27 | from .AttrList import AttrList 28 | 29 | from .ShaderProgram import ShaderProgram 30 | from .ComputeProgram import ComputeProgram 31 | 32 | from .ShaderStorageBlock import ShaderStorageBlock 33 | from .UniformBlock import UniformBlock 34 | from .Block import Block 35 | from .Uniform import Uniform 36 | 37 | from .GLConfig import GLConfig 38 | from .GlassConfig import GlassConfig 39 | from .GLInfo import GLInfo 40 | from .RenderHints import RenderHints 41 | from .download import download 42 | from .ImageLoader import ImageLoader 43 | 44 | # from .TextLoader import TextLoader, Font 45 | from .CustomLiteral import CustomLiteral 46 | from .callback_vec import callback_vec2, callback_vec3, callback_vec4, callback_quat -------------------------------------------------------------------------------- /glass/__pyinstaller/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_hook_dirs(): 5 | return [os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")] 6 | -------------------------------------------------------------------------------- /glass/__pyinstaller/hook-glass.py: -------------------------------------------------------------------------------- 1 | import os 2 | import platform 3 | 4 | 5 | def find_files(directory): 6 | file_list = [] 7 | abs_directory = ( 8 | os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/..").replace( 9 | "\\", "/" 10 | ) 11 | + "/" 12 | + directory 13 | ) 14 | for root, _, files in os.walk(abs_directory): 15 | for file in files: 16 | file_path = os.path.abspath(os.path.join(root, file)).replace("\\", "/") 17 | if not os.path.isfile(file_path): 18 | continue 19 | 20 | target_path = ( 21 | "glass/" 22 | + directory 23 | + file_path[ 24 | len(abs_directory) : (-len(os.path.basename(file_path)) - 1) 25 | ] 26 | ) 27 | if "__glcache__" not in file_path: 28 | file_list.append((file_path.replace("\\", "/"), target_path)) 29 | return file_list 30 | 31 | self_folder = os.path.dirname(os.path.abspath(__file__)) 32 | datas = find_files("glsl") 33 | datas.extend( 34 | [ 35 | ( 36 | os.path.abspath(self_folder + "/../LICENSE").replace("\\", "/"), 37 | "glass", 38 | ), 39 | ( 40 | os.path.abspath(self_folder + "/../CodeCompressor/pcpp/LICENSE").replace("\\", "/"), 41 | "glass/CodeCompressor/pcpp", 42 | ) 43 | ] 44 | ) 45 | if platform.system() == "Linux": 46 | hiddenimports = ["OpenGL.platform.egl"] 47 | -------------------------------------------------------------------------------- /glass/glsl/draw_frame.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | out vec2 tex_coord; 4 | 5 | void main() 6 | { 7 | switch (gl_VertexID) 8 | { 9 | case 0: 10 | case 5: 11 | { 12 | gl_Position = vec4(-1, -1, 0.0, 1.0); 13 | tex_coord = vec2(0, 0); 14 | break; 15 | } 16 | 17 | case 1: 18 | { 19 | gl_Position = vec4(1, -1, 0.0, 1.0); 20 | tex_coord = vec2(1, 0); 21 | break; 22 | } 23 | 24 | case 2: 25 | case 3: 26 | { 27 | gl_Position = vec4(1, 1, 0.0, 1.0); 28 | tex_coord = vec2(1, 1); 29 | break; 30 | } 31 | 32 | case 4: 33 | { 34 | gl_Position = vec4(-1, 1, 0.0, 1.0); 35 | tex_coord = vec2(0, 1); 36 | break; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /glass/glsl/shadertoy_template.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 out_color; 5 | 6 | uniform vec3 iResolution; // viewport resolution (in pixels) 7 | uniform float iTime; // shader playback time (in seconds) 8 | uniform float iTimeDelta; // render time (in seconds) 9 | uniform float iFrameRate; // shader frame rate 10 | uniform int iFrame; // shader playback frame 11 | uniform float iChannelTime[4]; // channel playback time (in seconds) 12 | uniform vec3 iChannelResolution[4]; // channel resolution (in pixels) 13 | uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click 14 | uniform sampler2D iChannel0, iChannel1, iChannel2, iChannel3; // input channel. XX = 2D/Cube 15 | uniform vec4 iDate; // (year, month, day, time in seconds) 16 | uniform float iSampleRate; // sound sample rate (i.e., 44100) 17 | 18 | #include FILE_NAME 19 | 20 | void main() 21 | { 22 | vec2 frag_coord = tex_coord * iResolution.xy; 23 | mainImage(out_color, frag_coord); 24 | } -------------------------------------------------------------------------------- /glass/iimage2D.py: -------------------------------------------------------------------------------- 1 | from .sampler2D import sampler2D 2 | from .GLInfo import GLInfo 3 | from .utils import checktype 4 | from .isampler2D import isampler2D 5 | 6 | from OpenGL import GL 7 | import numpy as np 8 | from typing import Union 9 | 10 | 11 | class iimage2D(isampler2D): 12 | 13 | _default_internal_format = GL.GL_RGBA32I 14 | _default_filter_min = GL.GL_NEAREST 15 | _default_filter_mag = GL.GL_NEAREST 16 | _default_filter_mipmap = None 17 | 18 | @checktype 19 | def __init__( 20 | self, 21 | image: Union[str, np.ndarray, None] = None, 22 | width: int = None, 23 | height: int = None, 24 | internal_format: GLInfo.iimage_internal_formats = None, 25 | ): 26 | isampler2D.__init__(self, image, width, height, internal_format) 27 | 28 | @property 29 | def internal_format(self): 30 | return self._internal_format 31 | 32 | @internal_format.setter 33 | @sampler2D.param_setter 34 | def internal_format(self, internal_format: GLInfo.iimage_internal_formats): 35 | self._set_internal_format(internal_format) 36 | 37 | @property 38 | def filter_min(self): 39 | return GL.GL_NEAREST 40 | 41 | @filter_min.setter 42 | def filter_min(self, filter_type: GLInfo.filter_types): 43 | raise RuntimeError("cannot set filter for iimage2D") 44 | 45 | @property 46 | def filter_mag(self): 47 | return GL.GL_NEAREST 48 | 49 | @filter_mag.setter 50 | def filter_mag(self, filter_type: GLInfo.filter_types): 51 | raise RuntimeError("cannot set filter for iimage2D") 52 | 53 | @property 54 | def filter_mipmap(self): 55 | return GL.GL_NONE 56 | 57 | @filter_mipmap.setter 58 | def filter_mipmap(self, filter_type: GLInfo.filter_types): 59 | raise RuntimeError("cannot set filter for iimage2D") 60 | 61 | @property 62 | def filter(self): 63 | return GL.GL_NEAREST, GL.GL_NEAREST, None 64 | 65 | @filter.setter 66 | def filter(self, filter_type): 67 | raise RuntimeError("cannot set filter for iimage2D") 68 | -------------------------------------------------------------------------------- /glass/image2D.py: -------------------------------------------------------------------------------- 1 | from OpenGL import GL 2 | import numpy as np 3 | from typing import Union 4 | 5 | from .FBOAttachment import FBOAttachment 6 | from .GLInfo import GLInfo 7 | from .utils import checktype 8 | from .sampler2D import sampler2D 9 | 10 | 11 | class image2D(sampler2D): 12 | 13 | _default_internal_format = GL.GL_RGBA32F 14 | _default_filter_min = GL.GL_NEAREST 15 | _default_filter_mag = GL.GL_NEAREST 16 | _default_filter_mipmap = None 17 | 18 | @checktype 19 | def __init__( 20 | self, 21 | image: Union[str, np.ndarray] = None, 22 | width: int = None, 23 | height: int = None, 24 | internal_format: GLInfo.image_internal_formats = None, 25 | ): 26 | sampler2D.__init__(self, image, width, height, internal_format) 27 | 28 | @property 29 | def internal_format(self): 30 | return self._internal_format 31 | 32 | @internal_format.setter 33 | @FBOAttachment.param_setter 34 | def internal_format(self, internal_format: GLInfo.image_internal_formats): 35 | self._set_internal_format(internal_format) 36 | 37 | @property 38 | def filter_min(self): 39 | return GL.GL_NEAREST 40 | 41 | @filter_min.setter 42 | def filter_min(self, filter_type: GLInfo.filter_types): 43 | raise RuntimeError("cannot set filter for image2D") 44 | 45 | @property 46 | def filter_mag(self): 47 | return GL.GL_NEAREST 48 | 49 | @filter_mag.setter 50 | def filter_mag(self, filter_type: GLInfo.filter_types): 51 | raise RuntimeError("cannot set filter for image2D") 52 | 53 | @property 54 | def filter_mipmap(self): 55 | return GL.GL_NONE 56 | 57 | @filter_mipmap.setter 58 | def filter_mipmap(self, filter_type: GLInfo.filter_types): 59 | raise RuntimeError("cannot set filter for image2D") 60 | 61 | @property 62 | def filter(self): 63 | return GL.GL_NEAREST, GL.GL_NEAREST, None 64 | 65 | @filter.setter 66 | def filter(self, filter_type): 67 | raise RuntimeError("cannot set filter for image2D") 68 | -------------------------------------------------------------------------------- /glass/isampler2D.py: -------------------------------------------------------------------------------- 1 | from .sampler2D import sampler2D 2 | from .GLInfo import GLInfo 3 | from .utils import checktype 4 | 5 | from OpenGL import GL 6 | import OpenGL.GL.ARB.bindless_texture as bt 7 | import numpy as np 8 | from typing import Union 9 | 10 | 11 | class isampler2D(sampler2D): 12 | 13 | _default_internal_format = GL.GL_RGBA32I 14 | _default_filter_min = GL.GL_NEAREST 15 | _default_filter_mag = GL.GL_NEAREST 16 | _default_filter_mipmap = None 17 | 18 | @checktype 19 | def __init__( 20 | self, 21 | image: Union[str, np.ndarray] = None, 22 | width: int = None, 23 | height: int = None, 24 | internal_format: GLInfo.isampler_internal_formats = None, 25 | ): 26 | if internal_format is None: 27 | internal_format = GL.GL_RGBA32I 28 | 29 | sampler2D.__init__(self, image, width, height, internal_format) 30 | 31 | @property 32 | def internal_format(self): 33 | return self._internal_format 34 | 35 | @internal_format.setter 36 | @sampler2D.param_setter 37 | def internal_format(self, internal_format: GLInfo.isampler_internal_formats): 38 | self._set_internal_format(internal_format) 39 | 40 | @property 41 | def handle(self): 42 | if not bt.glGetTextureHandleARB: 43 | return 0 44 | 45 | self.bind() 46 | if self._handle == 0: 47 | self._handle = bt.glGetTextureHandleARB(self._id) 48 | if self._handle == 0: 49 | raise RuntimeError(f"failed to create isampler2D {self._id}'s handle") 50 | bt.glMakeTextureHandleResidentARB(self._handle) 51 | 52 | self._dynamic = False 53 | 54 | return self._handle 55 | -------------------------------------------------------------------------------- /glass/isampler2DMS.py: -------------------------------------------------------------------------------- 1 | from .sampler2DMS import sampler2DMS 2 | from .GLInfo import GLInfo 3 | from .utils import checktype 4 | 5 | from OpenGL import GL 6 | import OpenGL.GL.ARB.bindless_texture as bt 7 | 8 | 9 | class isampler2DMS(sampler2DMS): 10 | 11 | @checktype 12 | def __init__( 13 | self, 14 | width: int = 0, 15 | height: int = 0, 16 | samples: int = 4, 17 | internal_format: GLInfo.isampler_internal_formats = None, 18 | ): 19 | if internal_format is None: 20 | internal_format = GL.GL_RGBA32I 21 | 22 | sampler2DMS.__init__(self, width, height, samples, internal_format) 23 | 24 | @property 25 | def internal_format(self): 26 | return self._internal_format 27 | 28 | @internal_format.setter 29 | @checktype 30 | def internal_format(self, format: GLInfo.isampler_internal_formats): 31 | if self._internal_format != format: 32 | self._internal_format = format 33 | self._param_changed = True 34 | 35 | @property 36 | def handle(self): 37 | if not bt.glGetTextureHandleARB: 38 | return 0 39 | 40 | self.bind() 41 | if self._handle == 0: 42 | self._handle = bt.glGetTextureHandleARB(self._id) 43 | if self._handle == 0: 44 | raise RuntimeError(f"failed to create isampler2D {self._id}'s handle") 45 | bt.glMakeTextureHandleResidentARB(self._handle) 46 | self._dynamic = False 47 | 48 | return self._handle 49 | -------------------------------------------------------------------------------- /glass/uimage2D.py: -------------------------------------------------------------------------------- 1 | from .sampler2D import sampler2D 2 | from .GLInfo import GLInfo 3 | from .utils import checktype 4 | from .usampler2D import usampler2D 5 | 6 | from OpenGL import GL 7 | import numpy as np 8 | from typing import Union 9 | 10 | 11 | class uimage2D(usampler2D): 12 | 13 | _default_internal_format = GL.GL_RGBA32UI 14 | _default_filter_min = GL.GL_NEAREST 15 | _default_filter_mag = GL.GL_NEAREST 16 | _default_filter_mipmap = None 17 | 18 | @checktype 19 | def __init__( 20 | self, 21 | image: Union[str, np.ndarray] = None, 22 | width: int = None, 23 | height: int = None, 24 | internal_format: GLInfo.uimage_internal_formats = None, 25 | ): 26 | usampler2D.__init__(self, image, width, height, internal_format) 27 | 28 | @property 29 | def internal_format(self): 30 | return self._internal_format 31 | 32 | @internal_format.setter 33 | @sampler2D.param_setter 34 | def internal_format(self, internal_format: GLInfo.uimage_internal_formats): 35 | self._set_internal_format(internal_format) 36 | 37 | @property 38 | def filter_min(self): 39 | return GL.GL_NEAREST 40 | 41 | @filter_min.setter 42 | def filter_min(self, filter_type: GLInfo.filter_types): 43 | raise RuntimeError("cannot set filter for uimage2D") 44 | 45 | @property 46 | def filter_mag(self): 47 | return GL.GL_NEAREST 48 | 49 | @filter_mag.setter 50 | def filter_mag(self, filter_type: GLInfo.filter_types): 51 | raise RuntimeError("cannot set filter for uimage2D") 52 | 53 | @property 54 | def filter_mipmap(self): 55 | return GL.GL_NONE 56 | 57 | @filter_mipmap.setter 58 | def filter_mipmap(self, filter_type: GLInfo.filter_types): 59 | raise RuntimeError("cannot set filter for uimage2D") 60 | 61 | @property 62 | def filter(self): 63 | return GL.GL_NEAREST, GL.GL_NEAREST, None 64 | 65 | @filter.setter 66 | def filter(self, filter_type): 67 | raise RuntimeError("cannot set filter for uimage2D") 68 | -------------------------------------------------------------------------------- /glass/usampler2D.py: -------------------------------------------------------------------------------- 1 | from .sampler2D import sampler2D 2 | from .GLInfo import GLInfo 3 | from .utils import checktype 4 | 5 | from OpenGL import GL 6 | import OpenGL.GL.ARB.bindless_texture as bt 7 | import numpy as np 8 | from typing import Union 9 | 10 | 11 | class usampler2D(sampler2D): 12 | 13 | _default_internal_format = GL.GL_RGBA32UI 14 | _default_filter_min = GL.GL_NEAREST 15 | _default_filter_mag = GL.GL_NEAREST 16 | _default_filter_mipmap = None 17 | 18 | @checktype 19 | def __init__( 20 | self, 21 | image: Union[str, np.ndarray] = None, 22 | width: int = None, 23 | height: int = None, 24 | internal_format: GLInfo.usampler_internal_formats = None, 25 | ): 26 | if internal_format is None: 27 | internal_format = GL.GL_RGBA32UI 28 | 29 | sampler2D.__init__(self, image, width, height, internal_format) 30 | 31 | @property 32 | def internal_format(self): 33 | return self._internal_format 34 | 35 | @internal_format.setter 36 | @sampler2D.param_setter 37 | def internal_format(self, internal_format: GLInfo.usampler_internal_formats): 38 | self._set_internal_format(internal_format) 39 | 40 | @property 41 | def handle(self): 42 | if not bt.glGetTextureHandleARB: 43 | return 0 44 | 45 | self.bind() 46 | if self._handle == 0: 47 | self._handle = bt.glGetTextureHandleARB(self._id) 48 | if self._handle == 0: 49 | raise RuntimeError(f"failed to create usampler2D {self._id}'s handle") 50 | bt.glMakeTextureHandleResidentARB(self._handle) 51 | self._dynamic = False 52 | 53 | return self._handle 54 | -------------------------------------------------------------------------------- /glass/usampler2DMS.py: -------------------------------------------------------------------------------- 1 | from .sampler2DMS import sampler2DMS 2 | from .GLInfo import GLInfo 3 | from .utils import checktype 4 | 5 | from OpenGL import GL 6 | import OpenGL.GL.ARB.bindless_texture as bt 7 | 8 | 9 | class usampler2DMS(sampler2DMS): 10 | 11 | @checktype 12 | def __init__( 13 | self, 14 | width: int = 0, 15 | height: int = 0, 16 | samples: int = 4, 17 | internal_format: GLInfo.usampler_internal_formats = None, 18 | ): 19 | if internal_format is None: 20 | internal_format = GL.GL_RGBA32UI 21 | 22 | sampler2DMS.__init__(self, width, height, samples, internal_format) 23 | 24 | @property 25 | def internal_format(self): 26 | return self._internal_format 27 | 28 | @internal_format.setter 29 | @checktype 30 | def internal_format(self, format: GLInfo.usampler_internal_formats): 31 | if self._internal_format != format: 32 | self._internal_format = format 33 | self._param_changed = True 34 | 35 | @property 36 | def handle(self): 37 | if not bt.glGetTextureHandleARB: 38 | return 0 39 | 40 | self.bind() 41 | if self._handle == 0: 42 | self._handle = bt.glGetTextureHandleARB(self._id) 43 | if self._handle == 0: 44 | raise RuntimeError(f"failed to create isampler2D {self._id}'s handle") 45 | bt.glMakeTextureHandleResidentARB(self._handle) 46 | self._dynamic = False 47 | 48 | return self._handle 49 | -------------------------------------------------------------------------------- /glass_engine/AffineTransform.py: -------------------------------------------------------------------------------- 1 | import glm 2 | from glass import Instance 3 | 4 | 5 | class AffineTransform(Instance): 6 | def __init__(self): 7 | Instance.__init__(self) 8 | 9 | self["affine_transform_row0"] = glm.vec4(1, 0, 0, 0) 10 | self["affine_transform_row1"] = glm.vec4(0, 1, 0, 0) 11 | self["affine_transform_row2"] = glm.vec4(0, 0, 1, 0) 12 | self["env_map_handle"] = 0 13 | self["visible"] = 1 14 | 15 | def apply(self, pos): 16 | transform_mat = glm.mat4( 17 | self["affine_transform_row0"], 18 | self["affine_transform_row1"], 19 | self["affine_transform_row2"], 20 | glm.vec4(0, 0, 0, 1), 21 | ) 22 | transform_mat = glm.transpose(transform_mat) 23 | result = transform_mat * glm.vec4(*pos, 1) 24 | return result.xyz 25 | -------------------------------------------------------------------------------- /glass_engine/Animations/AnimationGroup.py: -------------------------------------------------------------------------------- 1 | from .Animation import Animation 2 | from glass.DictList import DictList, ExtendableList 3 | 4 | from typing import Any 5 | 6 | 7 | def before_animation_add_callback(self: ExtendableList, animation: Any): 8 | if not isinstance(animation, Animation): 9 | raise TypeError("item add to AnimationGroup must be in type 'Animation'") 10 | 11 | 12 | def after_animation_add_callback(self: ExtendableList, animation: Any): 13 | animation._parents.add(self) 14 | 15 | 16 | def after_animation_remove_callback(self: ExtendableList, animation: Any): 17 | animation._parents.remove(self) 18 | 19 | 20 | class AnimationGroup(Animation, DictList): 21 | 22 | def __init__(self, *animations, **kwargs): 23 | Animation.__init__(self, **kwargs) 24 | DictList.__init__( 25 | self, 26 | values=animations, 27 | before_item_add_callback=before_animation_add_callback, 28 | after_item_add_callback=after_animation_add_callback, 29 | after_item_remove_callback=after_animation_remove_callback, 30 | ) 31 | 32 | def _update_duration(self): 33 | return 34 | 35 | @property 36 | def duration(self): 37 | self._update_duration() 38 | return self._duration 39 | 40 | @property 41 | def total_duration(self): 42 | self._update_duration() 43 | return self._total_duration 44 | -------------------------------------------------------------------------------- /glass_engine/Animations/EasingCurve.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | import pytweening 3 | 4 | 5 | class EasingCurve(Enum): 6 | 7 | Linear = 0 8 | InQuad = 1 9 | OutQuad = 2 10 | InOutQuad = 3 11 | OutInQuad = 4 12 | InCubic = 5 13 | OutCubic = 6 14 | InOutCubic = 7 15 | OutInCubic = 8 16 | InQuart = 9 17 | OutQuart = 10 18 | InOutQuart = 11 19 | OutInQuart = 12 20 | InQuint = 13 21 | OutQuint = 14 22 | InOutQuint = 15 23 | OutInQuint = 16 24 | InSine = 17 25 | OutSine = 18 26 | InOutSine = 19 27 | OutInSine = 20 28 | InExpo = 21 29 | OutExpo = 22 30 | InOutExpo = 23 31 | OutInExpo = 24 32 | InCirc = 25 33 | OutCirc = 26 34 | InOutCirc = 27 35 | OutInCirc = 28 36 | InElastic = 29 37 | OutElastic = 30 38 | InOutElastic = 31 39 | OutInElastic = 32 40 | InBack = 33 41 | OutBack = 34 42 | InOutBack = 35 43 | OutInBack = 36 44 | InBounce = 37 45 | OutBounce = 38 46 | InOutBounce = 39 47 | OutInBounce = 40 48 | 49 | def __call__(self, progress: float) -> float: 50 | if self == EasingCurve.Linear: 51 | return progress 52 | 53 | func_name = "ease" + str(self)[len("EasingCurve.") :] 54 | func = getattr(pytweening, func_name) 55 | return func(progress) 56 | -------------------------------------------------------------------------------- /glass_engine/Animations/ParallelAnimation.py: -------------------------------------------------------------------------------- 1 | from .AnimationGroup import AnimationGroup 2 | 3 | 4 | class ParallelAnimation(AnimationGroup): 5 | 6 | def __init__(self, *animations, **kwargs): 7 | AnimationGroup.__init__(self, *animations, **kwargs) 8 | 9 | def _update_duration(self): 10 | if not self._total_duration_dirty: 11 | return 12 | 13 | self._duration = 0 14 | for animation in self: 15 | if animation.total_duration > self._duration: 16 | self._duration = animation.total_duration 17 | 18 | self._total_duration = self._duration * self.loops 19 | if self._go_back: 20 | self._total_duration *= 2 21 | 22 | self._total_duration_dirty = False 23 | 24 | def _go_to(self, t: float): 25 | if t > self.total_duration: 26 | t = self.total_duration 27 | self._running = False 28 | 29 | progress = t / self.duration 30 | int_progress = int(progress) 31 | if progress != int_progress: 32 | progress -= int_progress 33 | elif progress != 0: 34 | progress = 1 35 | else: 36 | progress = 0 37 | 38 | if self.go_back and int_progress % 2 == 1: 39 | progress = 1 - progress 40 | 41 | reduce_t = progress * self.duration 42 | 43 | has_active_animation = False 44 | for animation in self: 45 | if animation is None: 46 | continue 47 | 48 | if reduce_t < animation.total_duration: 49 | animation._go_to(reduce_t) 50 | has_active_animation = True 51 | 52 | if not has_active_animation: 53 | self._running = False 54 | return 55 | 56 | if self.running_callback is not None: 57 | self.running_callback(t) 58 | -------------------------------------------------------------------------------- /glass_engine/Animations/SequentialAnimation.py: -------------------------------------------------------------------------------- 1 | from .AnimationGroup import AnimationGroup 2 | 3 | 4 | class SequentialAnimation(AnimationGroup): 5 | 6 | def __init__(self, *animations, **kwargs): 7 | AnimationGroup.__init__(self, *animations, **kwargs) 8 | 9 | def _update_duration(self): 10 | if not self._total_duration_dirty: 11 | return 12 | 13 | self._duration = 0 14 | for animation in self: 15 | self._duration += animation.total_duration 16 | 17 | self._total_duration = self._duration * self.loops 18 | if self._go_back: 19 | self._total_duration *= 2 20 | 21 | self._total_duration_dirty = False 22 | 23 | def _go_to(self, t: float): 24 | if t > self.total_duration: 25 | t = self.total_duration 26 | self._running = False 27 | 28 | progress = t / self.duration 29 | int_progress = int(progress) 30 | if progress != int_progress: 31 | progress -= int_progress 32 | elif progress != 0: 33 | progress = 1 34 | else: 35 | progress = 0 36 | 37 | if self.go_back and int_progress % 2 == 1: 38 | progress = 1 - progress 39 | 40 | reduce_t = progress * self.duration 41 | 42 | accum_time = 0 43 | next_accum_time = 0 44 | active_animation = None 45 | for animation in self: 46 | if animation is None: 47 | continue 48 | 49 | next_accum_time += animation.total_duration 50 | if accum_time <= reduce_t < next_accum_time: 51 | active_animation = animation 52 | break 53 | accum_time = next_accum_time 54 | 55 | if active_animation is None: 56 | self._running = False 57 | return 58 | 59 | active_animation._go_to(reduce_t - accum_time) 60 | 61 | if self.running_callback is not None: 62 | self.running_callback(t) 63 | -------------------------------------------------------------------------------- /glass_engine/Animations/__init__.py: -------------------------------------------------------------------------------- 1 | from .Animation import Animation 2 | from .EasingCurve import EasingCurve 3 | from .Chronoscope import Chronoscope 4 | from .SequentialAnimation import SequentialAnimation 5 | from .ParallelAnimation import ParallelAnimation 6 | -------------------------------------------------------------------------------- /glass_engine/Background.py: -------------------------------------------------------------------------------- 1 | from .SkyBox import SkyBox 2 | from .SkyDome import SkyDome 3 | 4 | from glass import samplerCube, sampler2D 5 | 6 | import glm 7 | from typing import Union 8 | 9 | 10 | class Background: 11 | def __init__(self): 12 | self._skybox: SkyBox = SkyBox() 13 | self._skydome: SkyDome = SkyDome() 14 | self._color: glm.vec4 = glm.vec4(0, 0, 0, 1) 15 | self._distance: float = 100.0 16 | 17 | @property 18 | def skybox(self): 19 | return self._skybox 20 | 21 | @skybox.setter 22 | def skybox(self, skybox_map: samplerCube): 23 | self._skybox.skybox_map = skybox_map 24 | 25 | @property 26 | def skydome(self): 27 | return self._skydome 28 | 29 | @skydome.setter 30 | def skydome(self, image: str): 31 | self._skydome.skydome_map = image 32 | 33 | @property 34 | def skybox_map(self) -> samplerCube: 35 | return self._skybox.skybox_map 36 | 37 | @property 38 | def skydome_map(self) -> sampler2D: 39 | return self._skydome.skydome_map 40 | 41 | @property 42 | def distance(self) -> float: 43 | return self._distance 44 | 45 | @distance.setter 46 | def distance(self, distance: float) -> None: 47 | self._distance = distance 48 | 49 | @property 50 | def color(self) -> glm.vec4: 51 | return self._color 52 | 53 | @color.setter 54 | def color(self, color: Union[glm.vec4, glm.vec3]) -> None: 55 | if isinstance(color, glm.vec3): 56 | color = glm.vec4(color, 1) 57 | 58 | self._color = color 59 | -------------------------------------------------------------------------------- /glass_engine/BasicScene.py: -------------------------------------------------------------------------------- 1 | from .Scene import Scene 2 | from .Camera import Camera 3 | from .Geometries.Floor import Floor 4 | from .Lights.DirLight import DirLight 5 | from .Manipulators import ModelViewManipulator 6 | 7 | 8 | def SceneRoam(add_floor=True): 9 | scene = Scene() 10 | 11 | camera = Camera() 12 | camera.position.y = -5 13 | camera.position.z = 1.7 14 | camera.pitch = -10 15 | scene.add(camera) 16 | 17 | floor = None 18 | if add_floor: 19 | floor = Floor() 20 | scene.add(floor) 21 | 22 | dir_light = DirLight() 23 | dir_light.pitch = -45 24 | dir_light.yaw = 45 25 | scene.add(dir_light) 26 | 27 | return scene, camera, dir_light, floor 28 | 29 | 30 | def ModelView(distance: float = 5, azimuth_deg: float = 0, elevation_deg: float = 0): 31 | scene = Scene() 32 | 33 | camera = Camera() 34 | camera.screen.manipulator = ModelViewManipulator( 35 | distance, azimuth_deg, elevation_deg 36 | ) 37 | scene.add(camera) 38 | 39 | dir_light = DirLight() 40 | dir_light.pitch = -45 41 | dir_light.yaw = 45 42 | scene.add(dir_light) 43 | 44 | return scene, camera, dir_light 45 | -------------------------------------------------------------------------------- /glass_engine/Frame.py: -------------------------------------------------------------------------------- 1 | from glass import ShaderProgram, sampler2D, GLConfig, sampler2DArray 2 | 3 | import os 4 | from OpenGL import GL 5 | from typing import Union 6 | 7 | 8 | class Frame: 9 | 10 | def __init__(self): 11 | self._program = None 12 | 13 | @property 14 | def program(self): 15 | if self._program is None: 16 | self._program = ShaderProgram() 17 | self._program.compile(self.draw_frame_vs) 18 | self._program.compile(self.draw_frame_fs) 19 | self._program.uniform_not_set_warning = False 20 | 21 | return self._program 22 | 23 | @property 24 | def draw_frame_vs(self) -> str: 25 | self_folder = os.path.dirname(os.path.abspath(__file__)) 26 | return os.path.abspath(self_folder + "/../glass/glsl/draw_frame.vert").replace( 27 | "\\", "/" 28 | ) 29 | 30 | @property 31 | def draw_frame_fs(self) -> str: 32 | self_folder = os.path.dirname(os.path.abspath(__file__)) 33 | return os.path.abspath(self_folder + "/glsl/Pipelines/draw_frame.frag").replace( 34 | "\\", "/" 35 | ) 36 | 37 | def draw( 38 | self, 39 | screen_image: Union[sampler2D, sampler2DArray], 40 | gray: bool = False, 41 | invert: bool = False, 42 | layer: int = -1, 43 | index: int = 0, 44 | ): 45 | with GLConfig.LocalEnv(): 46 | GLConfig.cull_face = None 47 | GLConfig.polygon_mode = GL.GL_FILL 48 | 49 | if isinstance(screen_image, sampler2D): 50 | self.program["screen_image"] = screen_image 51 | self.program["layer"] = -1 52 | else: 53 | self.program["screen_image_array"] = screen_image 54 | self.program["layer"] = layer 55 | 56 | self.program["gray"] = gray 57 | self.program["invert"] = invert 58 | self.program["index"] = index 59 | self.program.draw_triangles(vertices=self._vertices, indices=self._indices) 60 | 61 | 62 | Frame = Frame() 63 | -------------------------------------------------------------------------------- /glass_engine/Geometries/CoordSys.py: -------------------------------------------------------------------------------- 1 | from .Cylinder import Cylinder 2 | from .Cone import Cone 3 | from ..SceneNode import SceneNode 4 | 5 | from typing import Union 6 | 7 | import glm 8 | 9 | 10 | class CoordSys(SceneNode): 11 | 12 | def __init__( 13 | self, 14 | x_length: float = 1, 15 | y_length: Union[float, None] = None, 16 | z_length: Union[float, None] = None, 17 | alpha: float = 1, 18 | name: str = "", 19 | ): 20 | SceneNode.__init__(self, name=name) 21 | 22 | if y_length is None: 23 | y_length = x_length 24 | 25 | if z_length is None: 26 | z_length = x_length 27 | 28 | x_axis = CoordSys.create_axis(x_length, glm.vec4(1, 0, 0, alpha)) 29 | x_axis.roll = 90 30 | self.add_child(x_axis) 31 | 32 | y_axis = CoordSys.create_axis(y_length, glm.vec4(0, 1, 0, alpha)) 33 | y_axis.pitch = -90 34 | self.add_child(y_axis) 35 | 36 | z_axis = CoordSys.create_axis(z_length, glm.vec4(0, 0, 1, alpha)) 37 | self.add_child(z_axis) 38 | 39 | @staticmethod 40 | def create_axis(length: float, color: glm.vec4): 41 | axis = Cylinder(0.015, length, color=color) 42 | arrow = Cone(0.04, 0.15, color=color) 43 | arrow.position.z = length 44 | axis.add_child(arrow) 45 | 46 | return axis 47 | -------------------------------------------------------------------------------- /glass_engine/Geometries/Point.py: -------------------------------------------------------------------------------- 1 | from ..Mesh import Mesh 2 | 3 | from glass import Vertex 4 | from glass.utils import checktype 5 | 6 | import glm 7 | from OpenGL import GL 8 | from typing import Union 9 | 10 | 11 | class Point(Mesh): 12 | 13 | def __init__( 14 | self, 15 | position: glm.vec3 = glm.vec3(0), 16 | color: Union[glm.vec3, glm.vec4] = glm.vec4(0.396, 0.74151, 0.69102, 1), 17 | point_size: int = 5, 18 | name: str = "", 19 | ): 20 | Mesh.__init__(self, primitive_type=GL.GL_POINTS, color=color, name=name) 21 | self.render_hints.point_size = point_size 22 | self.__position = position 23 | 24 | def build(self): 25 | position = self.__position 26 | vertices = self._vertices 27 | 28 | vertices[0] = Vertex(position=position, tex_coord=glm.vec3(0.5, 0.5, 0)) 29 | del vertices[1:] 30 | 31 | @property 32 | def position(self): 33 | return self.__position 34 | 35 | @position.setter 36 | @Mesh.param_setter 37 | def position(self, position: glm.vec3): 38 | self.__position = position 39 | 40 | @property 41 | def point_size(self): 42 | return self.render_hints.point_size 43 | 44 | @point_size.setter 45 | @checktype 46 | def point_size(self, point_size: int): 47 | self.render_hints.point_size = point_size 48 | -------------------------------------------------------------------------------- /glass_engine/Geometries/Points.py: -------------------------------------------------------------------------------- 1 | from ..Mesh import Mesh 2 | 3 | from glass import Vertex 4 | from glass.utils import checktype 5 | 6 | import glm 7 | from OpenGL import GL 8 | from typing import Union 9 | 10 | 11 | class Points(Mesh): 12 | 13 | def __init__( 14 | self, 15 | points: list = [], 16 | color: Union[glm.vec3, glm.vec4] = glm.vec4(0.396, 0.74151, 0.69102, 1), 17 | point_size: int = 5, 18 | name: str = "", 19 | block: bool = True, 20 | ): 21 | Mesh.__init__( 22 | self, 23 | primitive_type=GL.GL_POINTS, 24 | color=color, 25 | name=name, 26 | block=block 27 | ) 28 | self.render_hints.point_size = point_size 29 | self.__points = points 30 | 31 | def build(self): 32 | points = self.__points 33 | vertices = self._vertices 34 | 35 | length = 0 36 | len_points = len(points) 37 | for i in range(len_points): 38 | if i > 0: 39 | length += glm.length(points[i] - points[i - 1]) 40 | vertices[i] = Vertex(position=points[i], tex_coord=glm.vec3(length, 0, 0)) 41 | 42 | del vertices[len_points:] 43 | 44 | @property 45 | def points(self): 46 | return self.__points 47 | 48 | @points.setter 49 | def points(self, points): 50 | self.__points = points 51 | self._build_state = Mesh.BuildState.NotBuilt 52 | 53 | @property 54 | def point_size(self): 55 | return self.render_hints.point_size 56 | 57 | @point_size.setter 58 | @checktype 59 | def point_size(self, point_size: int): 60 | self.render_hints.point_size = point_size 61 | -------------------------------------------------------------------------------- /glass_engine/Geometries/Polyline.py: -------------------------------------------------------------------------------- 1 | from ..Mesh import Mesh 2 | 3 | from glass import Vertex 4 | from glass.utils import checktype 5 | 6 | import glm 7 | from OpenGL import GL 8 | from typing import Union 9 | 10 | 11 | class Polyline(Mesh): 12 | 13 | def __init__( 14 | self, 15 | points: list = [], 16 | color: Union[glm.vec3, glm.vec4] = glm.vec4(0.396, 0.74151, 0.69102, 1), 17 | line_width: int = 2, 18 | loop: bool = False, 19 | name: str = "", 20 | block: bool = True, 21 | ): 22 | primitive_type = GL.GL_LINE_STRIP if not loop else GL.GL_LINE_LOOP 23 | Mesh.__init__( 24 | self, 25 | primitive_type=primitive_type, 26 | color=color, 27 | name=name, 28 | block=block 29 | ) 30 | self.render_hints.line_width = line_width 31 | self.__points = points 32 | 33 | def build(self): 34 | points = self.__points 35 | vertices = self._vertices 36 | 37 | length = 0 38 | len_points = len(points) 39 | for i in range(len_points): 40 | if i > 0: 41 | length += glm.length(points[i] - points[i - 1]) 42 | bitangent = None 43 | if i < len_points - 1: 44 | bitangent = glm.normalize(points[i + 1] - points[i]) 45 | else: 46 | bitangent = glm.normalize(points[i] - points[i - 1]) 47 | vertices[i] = Vertex( 48 | position=points[i], 49 | bitangent=bitangent, 50 | tex_coord=glm.vec3(length, 0, 0), 51 | ) 52 | 53 | del vertices[len_points:] 54 | 55 | @property 56 | def points(self): 57 | return self.__points 58 | 59 | @points.setter 60 | def points(self, points): 61 | self.__points = points 62 | self._build_state = Mesh.BuildState.NotBuilt 63 | 64 | @property 65 | def line_width(self): 66 | return self.render_hints.line_width 67 | 68 | @line_width.setter 69 | @checktype 70 | def line_width(self, line_width: int): 71 | self.render_hints.line_width = line_width 72 | 73 | @property 74 | def loop(self): 75 | return self.primitive_type == GL.GL_LINE_LOOP 76 | 77 | @loop.setter 78 | @Mesh.param_setter 79 | def loop(self, flag: bool): 80 | self.primitive_type = GL.GL_LINE_STRIP if not flag else GL.GL_LINE_LOOP 81 | -------------------------------------------------------------------------------- /glass_engine/Geometries/__init__.py: -------------------------------------------------------------------------------- 1 | # 点 2 | from .Point import Point 3 | from .Points import Points 4 | 5 | # 线 6 | from .Polyline import Polyline 7 | from .Circle import Circle 8 | 9 | # 面 10 | from .RectFace import RectFace 11 | 12 | from .RPolygonFace import RPolygonFace 13 | from .HollowRPolygonFace import HollowRPolygonFace 14 | 15 | from .CircleFace import CircleFace 16 | from .TorusFace import TorusFace 17 | from .EllipseFace import EllipseFace 18 | 19 | # 体 20 | 21 | # 多面体 22 | from .Box import Box 23 | 24 | from .Prism import Prism 25 | from .PrismSide import PrismSide 26 | 27 | from .Pyramid import Pyramid 28 | from .PyramidSide import PyramidSide 29 | 30 | from .PyramidTrustum import PyramidTrustum 31 | from .PyramidTrustumSide import PyramidTrustumSide 32 | 33 | # 曲面体 34 | from .Cylinder import Cylinder 35 | from .CylinderSide import CylinderSide 36 | 37 | from .Cone import Cone 38 | from .ConeSide import ConeSide 39 | from .ConeTrustum import ConeTrustum 40 | from .ConeTrustumSide import ConeTrustumSide 41 | 42 | from .Sphere import Sphere 43 | from .Icosphere import Icosphere 44 | from .SphericalCap import SphericalCap 45 | from .SphericalCapTop import SphericalCapTop 46 | 47 | # 正多面体 48 | from .Tetrahedron import Tetrahedron # 正四面体 49 | from .Hexahedron import Hexahedron # 正六面体 50 | from .Octahedron import Octahedron # 正八面体 51 | from .Dodecahedron import Dodecahedron # 正十二面体 52 | from .Icosahedron import Icosahedron # 正二十面体 53 | 54 | # 通用函数曲面 55 | from .Surf import Surf 56 | from .FSurf import FSurf 57 | from .CylindricalFSurf import CylindricalFSurf 58 | from .SphericalFSurf import SphericalFSurf 59 | 60 | # 变形体 61 | from .Rotator import Rotator 62 | from .Extruder import Extruder 63 | 64 | # 特殊几何体 65 | from .Floor import Floor 66 | from .Torus import Torus 67 | from .TrefoilKnot import TrefoilKnot 68 | from .CoordSys import CoordSys 69 | from .ImageQuad import ImageQuad 70 | -------------------------------------------------------------------------------- /glass_engine/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2024 王炳辉 (binghui.wang@foxmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /glass_engine/Lights/DirLight.py: -------------------------------------------------------------------------------- 1 | from .Light import Light, FlatLight 2 | from glass.DictList import DictList 3 | from glass import Block 4 | 5 | import glm 6 | from typing import Union 7 | 8 | 9 | class DirLight(Light): 10 | pass 11 | 12 | 13 | class FlatDirLight(FlatLight): 14 | 15 | def __init__(self, dir_light: DirLight): 16 | self.direction = glm.vec3(0, 1, 0) 17 | self.abs_orientation = glm.quat(1, 0, 0, 0) 18 | self.max_back_offset = 0 19 | FlatLight.__init__(self, dir_light) 20 | 21 | 22 | class DirLights(Block.HostClass): 23 | 24 | def __init__(self): 25 | Block.HostClass.__init__(self) 26 | self.dir_lights = DictList() 27 | 28 | def __getitem__(self, key: Union[str, int]): 29 | return self.dir_lights[key] 30 | 31 | @Block.HostClass.not_const 32 | def __setitem__(self, key: Union[str, int], dir_light: FlatDirLight): 33 | self.dir_lights[key] = dir_light 34 | 35 | @Block.HostClass.not_const 36 | def __delitem__(self, key: Union[str, int]): 37 | del self.dir_lights[key] 38 | 39 | def __contains__(self, path_str: str): 40 | return path_str in self.dir_lights 41 | 42 | def __len__(self): 43 | return len(self.dir_lights) 44 | 45 | def __iter__(self): 46 | return iter(self.dir_lights) 47 | 48 | def keys(self): 49 | return self.dir_lights.keys() 50 | 51 | @property 52 | def n_dir_lights(self): 53 | return len(self.dir_lights) 54 | -------------------------------------------------------------------------------- /glass_engine/Lights/__init__.py: -------------------------------------------------------------------------------- 1 | from .DirLight import DirLight 2 | from .PointLight import PointLight 3 | from .SpotLight import SpotLight 4 | -------------------------------------------------------------------------------- /glass_engine/Manipulators/__init__.py: -------------------------------------------------------------------------------- 1 | from .Manipulator import Manipulator 2 | from .ModelViewManipulator import ModelViewManipulator 3 | from .SceneRoamManipulator import SceneRoamManipulator 4 | -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/ACESToneMapper.py: -------------------------------------------------------------------------------- 1 | from .ShaderEffect import ShaderEffect 2 | import os 3 | 4 | 5 | class ACESToneMapper(ShaderEffect): 6 | 7 | def __init__(self): 8 | self_folder = os.path.dirname(os.path.abspath(__file__)) 9 | ShaderEffect.__init__( 10 | self, self_folder + "/../glsl/PostProcessEffects/ACES_tone_mapper.glsl" 11 | ) 12 | -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/ExposureAdaptor.py: -------------------------------------------------------------------------------- 1 | from .ShaderEffect import ShaderEffect 2 | from glass import sampler2D, Block 3 | 4 | import time 5 | import os 6 | 7 | 8 | class ExposureAdaptor(ShaderEffect): 9 | 10 | class CurrentLuma(Block.HostClass): 11 | def __init__(self): 12 | Block.HostClass.__init__(self) 13 | self._current_luma = 0 14 | 15 | @property 16 | def current_luma(self): 17 | return self._current_luma 18 | 19 | @current_luma.setter 20 | @Block.HostClass.not_const 21 | def current_luma(self, luma: float): 22 | self._current_luma = luma 23 | 24 | def __init__(self): 25 | self_folder = os.path.dirname(os.path.abspath(__file__)) 26 | ShaderEffect.__init__( 27 | self, 28 | self_folder + "/../glsl/PostProcessEffects/exposure_adaptor.glsl", 29 | generate_mipmap=True, 30 | ) 31 | 32 | self.current_luma = ExposureAdaptor.CurrentLuma() 33 | self["CurrentLuma"] = self.current_luma 34 | 35 | def apply(self, screen_image: sampler2D) -> sampler2D: 36 | self.program["fps"] = self.camera.screen.smooth_fps 37 | return ShaderEffect.apply(self, screen_image) 38 | 39 | def draw_to_active(self, screen_image: sampler2D) -> None: 40 | self.program["fps"] = self.camera.screen.smooth_fps 41 | ShaderEffect.draw_to_active(self, screen_image) 42 | 43 | @property 44 | def should_update_until(self)->float: 45 | if not self._enabled: 46 | return 0 47 | 48 | if self.camera is None: 49 | return 0 50 | 51 | if (not self.camera.lens.auto_explosure) or self.camera.lens.local_explosure: 52 | return 0 53 | 54 | return self.camera.screen.scene_update_time + self.camera.lens.explosure_adapt_time 55 | -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/LUTEffect.py: -------------------------------------------------------------------------------- 1 | from .ShaderEffect import ShaderEffect 2 | from .PostProcessEffect import PostProcessEffect 3 | from .. import lut 4 | from glass import sampler2D 5 | from glass.utils import extname 6 | 7 | import numpy as np 8 | import os 9 | from OpenGL import GL 10 | from typing import Union 11 | 12 | 13 | class LUTEffect(ShaderEffect): 14 | 15 | def __init__(self, LUT: Union[str, np.ndarray, sampler2D], contribute: float = 1.0): 16 | self_folder = os.path.dirname(os.path.abspath(__file__)) 17 | ShaderEffect.__init__( 18 | self, self_folder + "/../glsl/PostProcessEffects/lut.glsl" 19 | ) 20 | 21 | if isinstance(LUT, str) and extname(LUT) == "cube": 22 | LUT = lut.cube_to_LUT(LUT) 23 | 24 | if not isinstance(LUT, sampler2D): 25 | LUT = sampler2D(LUT) 26 | 27 | LUT.wrap = GL.GL_CLAMP_TO_EDGE 28 | self["LUT"] = LUT 29 | self["contribute"] = contribute 30 | self.__LUT = LUT 31 | self.__contribute = contribute 32 | 33 | @property 34 | def LUT(self): 35 | return self.__LUT 36 | 37 | @LUT.setter 38 | @PostProcessEffect.param_setter 39 | def LUT(self, LUT: Union[str, np.ndarray, sampler2D]): 40 | if isinstance(LUT, str) and extname(LUT) == "cube": 41 | LUT = lut.cube_to_LUT(LUT) 42 | 43 | if not isinstance(LUT, sampler2D): 44 | LUT = sampler2D(LUT) 45 | 46 | LUT.wrap = GL.GL_CLAMP_TO_EDGE 47 | self.__LUT = LUT 48 | self["LUT"] = LUT 49 | 50 | @property 51 | def contribute(self): 52 | return self.__contribute 53 | 54 | @contribute.setter 55 | @PostProcessEffect.param_setter 56 | def contribute(self, contribute: float): 57 | self.__contribute = contribute 58 | self["contribute"] = contribute 59 | -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/MedianBlur.py: -------------------------------------------------------------------------------- 1 | from .ShaderEffect import ShaderEffect 2 | import os 3 | 4 | 5 | class MedianBlur(ShaderEffect): 6 | 7 | def __init__(self): 8 | self_folder = os.path.dirname(os.path.abspath(__file__)) 9 | ShaderEffect.__init__( 10 | self, self_folder + "/../glsl/PostProcessEffects/median_gray_blur5.glsl" 11 | ) 12 | -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/MulFilter.py: -------------------------------------------------------------------------------- 1 | from .ShaderEffect import ShaderEffect 2 | import os 3 | 4 | 5 | class MulFilter(ShaderEffect): 6 | 7 | def __init__(self): 8 | self_folder = os.path.dirname(os.path.abspath(__file__)) 9 | ShaderEffect.__init__( 10 | self, self_folder + "/../glsl/PostProcessEffects/mul_filter.glsl" 11 | ) 12 | -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/PostProcessEffect.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from glass import sampler2D 3 | from glass.utils import checktype 4 | 5 | from functools import wraps 6 | 7 | 8 | class PostProcessEffect(ABC): 9 | 10 | def __init__(self): 11 | self._enabled = True 12 | 13 | self.depth_map = None 14 | self.world_pos_map = None 15 | self.world_normal_map = None 16 | self.camera = None 17 | 18 | def __bool__(self) -> bool: 19 | return self._enabled 20 | 21 | def param_setter(func): 22 | @wraps(func) 23 | def wrapper(*args, **kwargs): 24 | self = args[0] 25 | value = args[1] 26 | 27 | equal = False 28 | try: 29 | lvalue = getattr(self, func.__name__) 30 | if type(lvalue) != type(value): 31 | equal = False 32 | else: 33 | equal = bool(getattr(self, func.__name__) == value) 34 | except: 35 | equal = False 36 | 37 | if equal: 38 | return 39 | 40 | safe_func = checktype(func) 41 | return_value = safe_func(*args, **kwargs) 42 | if self.camera is not None: 43 | self.camera.screen.update_PPEs() 44 | 45 | return return_value 46 | 47 | return wrapper 48 | 49 | @abstractmethod 50 | def apply(self, screen_image: sampler2D) -> sampler2D: 51 | pass 52 | 53 | @abstractmethod 54 | def draw_to_active(self, screen_image: sampler2D) -> None: 55 | pass 56 | 57 | @abstractmethod 58 | def need_pos_info(self) -> bool: 59 | return False 60 | 61 | @property 62 | def enabled(self) -> bool: 63 | return self._enabled 64 | 65 | @enabled.setter 66 | @param_setter 67 | def enabled(self, flag: bool): 68 | self._enabled = flag 69 | 70 | @property 71 | def should_update_until(self)->float: 72 | return 0.0 -------------------------------------------------------------------------------- /glass_engine/PostProcessEffects/__init__.py: -------------------------------------------------------------------------------- 1 | from .PostProcessEffects import PostProcessEffects 2 | from .PostProcessEffect import PostProcessEffect 3 | from .ShaderEffect import ShaderEffect 4 | 5 | from .GaussBlur import GaussBlur 6 | from .KernelFilter import KernelFilter 7 | from .BloomEffect import BloomEffect 8 | from .ACESToneMapper import ACESToneMapper 9 | from .DOFEffect import DOFEffect 10 | from .FXAAEffect import FXAAEffect 11 | from .LUTEffect import LUTEffect 12 | from .SSAOEffect import SSAOEffect 13 | from .MulFilter import MulFilter 14 | from .ExposureAdaptor import ExposureAdaptor 15 | -------------------------------------------------------------------------------- /glass_engine/Renderers/Renderer.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class Renderer(ABC): 5 | 6 | def __init__(self): 7 | self._camera = None 8 | 9 | @property 10 | def camera(self): 11 | return self._camera 12 | 13 | @property 14 | def scene(self): 15 | return self.camera.scene 16 | 17 | @property 18 | def screen(self): 19 | return self.camera.screen 20 | 21 | def startup(self): 22 | pass 23 | 24 | @abstractmethod 25 | def render(self) -> bool: 26 | pass 27 | -------------------------------------------------------------------------------- /glass_engine/Renderers/__init__.py: -------------------------------------------------------------------------------- 1 | from .Renderer import Renderer 2 | from .ForwardRenderer import ForwardRenderer 3 | from .DeferredRenderer import DeferredRenderer 4 | -------------------------------------------------------------------------------- /glass_engine/Screens/PyQt5Screen.py: -------------------------------------------------------------------------------- 1 | from glass.download import pip_install 2 | from .QtScreen import init_QtScreen 3 | from ..Manipulators.Manipulator import Manipulator 4 | 5 | try: 6 | import PyQt5 7 | except ModuleNotFoundError: 8 | pip_install("PyQt5") 9 | import PyQt5 10 | 11 | from PyQt5.QtWidgets import QOpenGLWidget 12 | 13 | import glm 14 | 15 | 16 | @init_QtScreen 17 | class PyQt5Screen(QOpenGLWidget): 18 | mouse_pressed = PyQt5.QtCore.pyqtSignal(Manipulator.MouseButton, glm.vec2, glm.vec2) 19 | mouse_released = PyQt5.QtCore.pyqtSignal( 20 | Manipulator.MouseButton, glm.vec2, glm.vec2 21 | ) 22 | mouse_double_clicked = PyQt5.QtCore.pyqtSignal( 23 | Manipulator.MouseButton, glm.vec2, glm.vec2 24 | ) 25 | mouse_moved = PyQt5.QtCore.pyqtSignal(glm.vec2, glm.vec2) 26 | wheel_scrolled = PyQt5.QtCore.pyqtSignal(glm.vec2, glm.vec2, glm.vec2) 27 | key_pressed = PyQt5.QtCore.pyqtSignal(Manipulator.Key) 28 | key_released = PyQt5.QtCore.pyqtSignal(Manipulator.Key) 29 | key_repeated = PyQt5.QtCore.pyqtSignal(set) 30 | frame_started = PyQt5.QtCore.pyqtSignal() 31 | frame_ended = PyQt5.QtCore.pyqtSignal() 32 | -------------------------------------------------------------------------------- /glass_engine/Screens/PyQt6Screen.py: -------------------------------------------------------------------------------- 1 | from glass.download import pip_install 2 | from .QtScreen import init_QtScreen 3 | from ..Manipulators.Manipulator import Manipulator 4 | 5 | try: 6 | import PyQt6 7 | except ModuleNotFoundError: 8 | pip_install("PyQt6") 9 | import PyQt6 10 | 11 | from PyQt6.QtOpenGLWidgets import QOpenGLWidget 12 | 13 | import glm 14 | 15 | 16 | @init_QtScreen 17 | class PyQt6Screen(QOpenGLWidget): 18 | mouse_pressed = PyQt6.QtCore.pyqtSignal(Manipulator.MouseButton, glm.vec2, glm.vec2) 19 | mouse_released = PyQt6.QtCore.pyqtSignal( 20 | Manipulator.MouseButton, glm.vec2, glm.vec2 21 | ) 22 | mouse_double_clicked = PyQt6.QtCore.pyqtSignal( 23 | Manipulator.MouseButton, glm.vec2, glm.vec2 24 | ) 25 | mouse_moved = PyQt6.QtCore.pyqtSignal(glm.vec2, glm.vec2) 26 | wheel_scrolled = PyQt6.QtCore.pyqtSignal(glm.vec2, glm.vec2, glm.vec2) 27 | key_pressed = PyQt6.QtCore.pyqtSignal(Manipulator.Key) 28 | key_released = PyQt6.QtCore.pyqtSignal(Manipulator.Key) 29 | key_repeated = PyQt6.QtCore.pyqtSignal(set) 30 | frame_started = PyQt6.QtCore.pyqtSignal() 31 | frame_ended = PyQt6.QtCore.pyqtSignal() 32 | -------------------------------------------------------------------------------- /glass_engine/Screens/PySide2Screen.py: -------------------------------------------------------------------------------- 1 | from glass.download import pip_install 2 | from .QtScreen import init_QtScreen 3 | from ..Manipulators.Manipulator import Manipulator 4 | 5 | try: 6 | import PySide2 7 | except ModuleNotFoundError: 8 | pip_install("PySide2") 9 | import PySide2 10 | 11 | from PySide2.QtOpenGLWidgets import QOpenGLWidget 12 | 13 | import glm 14 | 15 | 16 | @init_QtScreen 17 | class PySide2Screen(QOpenGLWidget): 18 | mouse_pressed = PySide2.QtCore.Signal(Manipulator.MouseButton, glm.vec2, glm.vec2) 19 | mouse_released = PySide2.QtCore.Signal(Manipulator.MouseButton, glm.vec2, glm.vec2) 20 | mouse_double_clicked = PySide2.QtCore.Signal( 21 | Manipulator.MouseButton, glm.vec2, glm.vec2 22 | ) 23 | mouse_moved = PySide2.QtCore.Signal(glm.vec2, glm.vec2) 24 | wheel_scrolled = PySide2.QtCore.Signal(glm.vec2, glm.vec2, glm.vec2) 25 | key_pressed = PySide2.QtCore.Signal(Manipulator.Key) 26 | key_released = PySide2.QtCore.Signal(Manipulator.Key) 27 | key_repeated = PySide2.QtCore.Signal(set) 28 | frame_started = PySide2.QtCore.Signal() 29 | frame_ended = PySide2.QtCore.Signal() 30 | -------------------------------------------------------------------------------- /glass_engine/Screens/PySide6Screen.py: -------------------------------------------------------------------------------- 1 | from glass.download import pip_install 2 | from .QtScreen import init_QtScreen 3 | from ..Manipulators.Manipulator import Manipulator 4 | 5 | try: 6 | import PySide6 7 | except ModuleNotFoundError: 8 | pip_install("PySide6") 9 | import PySide6 10 | 11 | from PySide6.QtOpenGLWidgets import QOpenGLWidget 12 | 13 | import glm 14 | 15 | 16 | @init_QtScreen 17 | class PySide6Screen(QOpenGLWidget): 18 | mouse_pressed = PySide6.QtCore.Signal(Manipulator.MouseButton, glm.vec2, glm.vec2) 19 | mouse_released = PySide6.QtCore.Signal(Manipulator.MouseButton, glm.vec2, glm.vec2) 20 | mouse_double_clicked = PySide6.QtCore.Signal( 21 | Manipulator.MouseButton, glm.vec2, glm.vec2 22 | ) 23 | mouse_moved = PySide6.QtCore.Signal(glm.vec2, glm.vec2) 24 | wheel_scrolled = PySide6.QtCore.Signal(glm.vec2, glm.vec2, glm.vec2) 25 | key_pressed = PySide6.QtCore.Signal(Manipulator.Key) 26 | key_released = PySide6.QtCore.Signal(Manipulator.Key) 27 | key_repeated = PySide6.QtCore.Signal(set) 28 | frame_started = PySide6.QtCore.Signal() 29 | frame_ended = PySide6.QtCore.Signal() 30 | -------------------------------------------------------------------------------- /glass_engine/Screens/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/glass_engine/Screens/__init__.py -------------------------------------------------------------------------------- /glass_engine/SlideAverageFilter.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | 4 | class SlideAverageFilter: 5 | 6 | def __init__(self, window_width: int = 10) -> None: 7 | self._current_sum = 0 8 | self._window_width = window_width 9 | self._data_list = [] 10 | 11 | def __call__(self, new_value: Union[float, int]) -> float: 12 | if len(self._data_list) >= self._window_width: 13 | old_value = self._data_list.pop(0) 14 | self._current_sum -= old_value 15 | 16 | self._data_list.append(new_value) 17 | self._current_sum += new_value 18 | 19 | return self._current_sum / len(self._data_list) 20 | 21 | @property 22 | def window_width(self) -> int: 23 | return self._window_width 24 | 25 | @window_width.setter 26 | def window_width(self, window_width: int) -> None: 27 | self._window_width = window_width 28 | -------------------------------------------------------------------------------- /glass_engine/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.1.64" 2 | 3 | from .Scene import Scene 4 | from .SceneNode import SceneNode 5 | from .BasicScene import SceneRoam, ModelView 6 | 7 | from .Camera import Camera 8 | from .Material import Material 9 | from .Mesh import Mesh 10 | from .Model import Model 11 | 12 | from .ColorMap import ColorMap 13 | from .Frame import Frame 14 | from .Fog import Fog 15 | 16 | import glm 17 | 18 | from OpenGL import GL 19 | from glass import GlassConfig 20 | -------------------------------------------------------------------------------- /glass_engine/__pyinstaller/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_hook_dirs(): 5 | return [os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")] 6 | -------------------------------------------------------------------------------- /glass_engine/__pyinstaller/hook-glass_engine.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def find_files(directory): 5 | file_list = [] 6 | abs_directory = ( 7 | os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/..").replace( 8 | "\\", "/" 9 | ) 10 | + "/" 11 | + directory 12 | ) 13 | for root, _, files in os.walk(abs_directory): 14 | for file in files: 15 | file_path = os.path.abspath(os.path.join(root, file)).replace("\\", "/") 16 | if not os.path.isfile(file_path): 17 | continue 18 | 19 | target_path = ( 20 | "glass_engine/" 21 | + directory 22 | + file_path[ 23 | len(abs_directory) : (-len(os.path.basename(file_path)) - 1) 24 | ] 25 | ) 26 | if "__glcache__" not in file_path and "__pycache__" not in file_path: 27 | file_list.append((file_path.replace("\\", "/"), target_path)) 28 | return file_list 29 | 30 | self_folder = os.path.dirname(os.path.abspath(__file__)) 31 | datas = find_files("glsl") 32 | datas.extend( 33 | [ 34 | ( 35 | os.path.abspath(self_folder + "/../images/glass_engine_logo64.png").replace("\\", "/"), 36 | "glass_engine/images", 37 | ), 38 | ( 39 | os.path.abspath(self_folder + "/../LICENSE").replace("\\", "/"), 40 | "glass_engine", 41 | ) 42 | ] 43 | ) 44 | 45 | hiddenimports = [ 46 | "glass_engine.Screens.PyQt5Screen", 47 | "glass_engine.Screens.PyQt6Screen", 48 | "glass_engine.Screens.PySide2Screen", 49 | "glass_engine.Screens.PySide6Screen", 50 | "glass_engine.Screens.QtScreen", 51 | ] 52 | -------------------------------------------------------------------------------- /glass_engine/glsl/Lights/DirLight.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _DIRLIGHT_GLSL_ 2 | #define _DIRLIGHT_GLSL_ 3 | 4 | #include "../include/quat.glsl" 5 | 6 | struct DirLight 7 | { 8 | vec3 color; 9 | bool generate_shadows; 10 | uvec2 depth_map_handle; 11 | float max_back_offset; 12 | float rim_power; 13 | vec3 direction; 14 | quat abs_orientation; 15 | }; 16 | 17 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/Lights/Lights.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _LIGHTS_GLSL_ 2 | #define _LIGHTS_GLSL_ 3 | 4 | #include "DirLight.glsl" 5 | #include "PointLight.glsl" 6 | #include "SpotLight.glsl" 7 | 8 | #if USE_SHADER_STORAGE_BLOCK 9 | 10 | buffer DirLights 11 | { 12 | int n_dir_lights; 13 | DirLight dir_lights[]; 14 | }; 15 | 16 | buffer PointLights 17 | { 18 | int n_point_lights; 19 | PointLight point_lights[]; 20 | }; 21 | 22 | buffer SpotLights 23 | { 24 | int n_spot_lights; 25 | SpotLight spot_lights[]; 26 | }; 27 | 28 | #else 29 | 30 | uniform DirLights 31 | { 32 | int n_dir_lights; 33 | DirLight dir_lights[32]; 34 | }; 35 | 36 | uniform PointLights 37 | { 38 | int n_point_lights; 39 | PointLight point_lights[32]; 40 | }; 41 | 42 | uniform SpotLights 43 | { 44 | int n_spot_lights; 45 | SpotLight spot_lights[32]; 46 | }; 47 | 48 | #endif 49 | 50 | 51 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/Lights/PointLight.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _POINTLIGHT_GLSL_ 2 | #define _POINTLIGHT_GLSL_ 3 | 4 | struct PointLight 5 | { 6 | vec3 color; 7 | float rim_power; 8 | float K1; 9 | float K2; 10 | float coverage; 11 | bool generate_shadows; 12 | uvec2 depth_map_handle; 13 | vec3 abs_position; 14 | }; 15 | 16 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/Lights/PointLight_shadow_mapping.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _POINTLIGHT_SHADOW_MAPPING_GLSL_ 2 | #define _POINTLIGHT_SHADOW_MAPPING_GLSL_ 3 | 4 | #include "PointLight.glsl" 5 | 6 | float PCF(PointLight light, vec3 frag_pos, vec3 frag_normal) 7 | { 8 | vec3 depth_map_tex_coord = frag_pos - light.abs_position; 9 | float self_depth = length(depth_map_tex_coord); 10 | if (self_depth < 0.1) 11 | { 12 | return 1.0; 13 | } 14 | 15 | depth_map_tex_coord /= self_depth; 16 | 17 | float max_angle_shift = atan(0.05/self_depth); 18 | float beta = acos(max(0, dot(frag_normal, -depth_map_tex_coord))); 19 | float bias = 0.05 * clamp(tan(beta), 0.2, 10.0); 20 | self_depth -= bias; 21 | 22 | int n_samples = 10; 23 | int rand_seed = 0; 24 | int not_occ_count = 0; 25 | int total_count = 0; 26 | quat correction_quat = quat(cos45, sin45, 0, 0); 27 | for (int i = 0; i < n_samples; i++) 28 | { 29 | vec3 sample_dir = rand3_near(depth_map_tex_coord, max_angle_shift, rand_seed); 30 | sample_dir = quat_apply(correction_quat, sample_dir); 31 | float sample_depth = max(texture(samplerCube(light.depth_map_handle), sample_dir).r, 0.0); 32 | sample_depth *= light.coverage; 33 | not_occ_count += (sample_depth > self_depth ? 1 : 0); 34 | total_count += 1; 35 | } 36 | 37 | return 1.0*not_occ_count/total_count; 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/Lights/SpotLight.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _SPOTLIGHT_GLSL_ 2 | #define _SPOTLIGHT_GLSL_ 3 | 4 | struct SpotLight 5 | { 6 | vec3 color; 7 | float rim_power; 8 | float half_span_angle_rad; 9 | float half_softness_rad; 10 | float aggregate_coeff; 11 | float K1; 12 | float K2; 13 | float coverage; 14 | bool generate_shadows; 15 | uvec2 depth_map_handle; 16 | vec3 abs_position; 17 | vec3 direction; 18 | }; 19 | 20 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/Lights/SpotLight_shadow_mapping.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _SPOTLIGHT_SHADOW_MAPPING_GLSL_ 2 | #define _SPOTLIGHT_SHADOW_MAPPING_GLSL_ 3 | 4 | #include "SpotLight.glsl" 5 | 6 | float PCF(SpotLight light, vec3 frag_pos, vec3 frag_normal) 7 | { 8 | vec3 depth_map_tex_coord = frag_pos - light.abs_position; 9 | float self_depth = length(depth_map_tex_coord); 10 | if (self_depth < 0.1) 11 | return 1; 12 | depth_map_tex_coord /= self_depth; 13 | float theta = acos(dot(normalize(light.direction), depth_map_tex_coord)); 14 | float cutoff = soft_step(light.half_span_angle_rad+light.half_softness_rad-theta, light.half_softness_rad); 15 | if (cutoff < 1E-6) 16 | return 1; 17 | float max_angle_shift = atan(0.05/self_depth); 18 | float beta = acos(max(0, dot(frag_normal, -depth_map_tex_coord))); 19 | float bias = 0.05 * clamp(tan(beta), 0.2, 10.0); 20 | self_depth -= bias; 21 | 22 | int n_samples = 10; 23 | int rand_seed = 0; 24 | int not_occ_count = 0; 25 | int total_count = 0; 26 | quat correction_quat = quat(cos45, sin45, 0, 0); 27 | for (int i = 0; i < n_samples; i++) 28 | { 29 | vec3 sample_dir = rand3_near(depth_map_tex_coord, max_angle_shift, rand_seed); 30 | sample_dir = quat_apply(correction_quat, sample_dir); 31 | 32 | float sample_depth = max(texture(samplerCube(light.depth_map_handle), sample_dir).r, 0.0); 33 | sample_depth *= light.coverage; 34 | 35 | not_occ_count += (sample_depth > self_depth ? 1 : 0); 36 | total_count += 1; 37 | } 38 | return 1.0*not_occ_count/total_count; 39 | } 40 | 41 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/DirLight_depth/DirLight_depth.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in VertexOut 4 | { 5 | vec4 color; 6 | vec4 back_color; 7 | vec3 tex_coord; 8 | flat int visible; 9 | } fs_in; 10 | 11 | #include "../../include/InternalMaterial.glsl" 12 | 13 | uniform Material material; 14 | uniform Material back_material; 15 | 16 | void main() 17 | { 18 | if (fs_in.visible == 0) 19 | { 20 | discard; 21 | } 22 | 23 | InternalMaterial internal_material; 24 | 25 | if (gl_FrontFacing) 26 | { 27 | internal_material = fetch_internal_material(fs_in.color, material, fs_in.tex_coord.st); 28 | } 29 | else 30 | { 31 | internal_material = fetch_internal_material(fs_in.back_color, back_material, fs_in.tex_coord.st); 32 | } 33 | 34 | if (internal_material.opacity < 1E-6) 35 | { 36 | discard; 37 | } 38 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/DirLight_depth/DirLight_depth.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | layout (triangles, invocations=CSM_LEVELS) in; 9 | layout (triangle_strip, max_vertices=3) out; 10 | 11 | in VertexOut 12 | { 13 | vec4 color; 14 | vec4 back_color; 15 | vec3 tex_coord; 16 | flat int visible; 17 | } gs_in[]; 18 | 19 | out VertexOut 20 | { 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/DirLight.glsl" 29 | #include "../../Lights/DirLight_shadow_mapping.glsl" 30 | 31 | uniform DirLight dir_light; 32 | uniform Camera camera; 33 | 34 | void main() 35 | { 36 | vec3 v1 = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz; 37 | vec3 v2 = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz; 38 | vec3 face_world_normal = normalize(cross(v1, v2)); 39 | 40 | gl_Layer = gl_InvocationID; 41 | for (int i = 0; i < 3; i++) 42 | { 43 | vec3 world_pos = gl_in[i].gl_Position.xyz; 44 | gs_out.visible = gs_in[i].visible; 45 | gs_out.color = gs_in[i].color; 46 | gs_out.back_color = gs_in[i].back_color; 47 | gs_out.tex_coord = gs_in[i].tex_coord; 48 | 49 | gl_Position = world_to_lightNDC(dir_light, camera, gl_InvocationID, world_pos); 50 | EmitVertex(); 51 | } 52 | 53 | EndPrimitive(); 54 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/DirLight_depth/DirLight_depth.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | layout (location = 0) in vec3 position; 9 | layout (location = 1) in vec3 tex_coord; 10 | layout (location = 2) in vec4 color; 11 | layout (location = 3) in vec4 back_color; 12 | layout (location = 4) in vec4 affine_transform_row0; 13 | layout (location = 5) in vec4 affine_transform_row1; 14 | layout (location = 6) in vec4 affine_transform_row2; 15 | layout (location = 7) in int visible; 16 | 17 | out VertexOut 18 | { 19 | vec4 color; 20 | vec4 back_color; 21 | vec3 tex_coord; 22 | flat int visible; 23 | } vs_out; 24 | 25 | #include "../../include/transform.glsl" 26 | 27 | void main() 28 | { 29 | mat4 transform = transpose(mat4( 30 | affine_transform_row0, 31 | affine_transform_row1, 32 | affine_transform_row2, 33 | vec4(0, 0, 0, 1) 34 | )); 35 | 36 | vec3 world_pos = transform_apply(transform, position); 37 | gl_Position = vec4(world_pos, 1); 38 | 39 | vs_out.visible = visible; 40 | vs_out.color = color; 41 | vs_out.back_color = back_color; 42 | vs_out.tex_coord = tex_coord; 43 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/DirLight_depth/DirLight_depth_lines.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | layout (lines, invocations=CSM_LEVELS) in; 9 | layout (line_strip, max_vertices=2) out; 10 | 11 | in VertexOut 12 | { 13 | vec4 color; 14 | vec4 back_color; 15 | vec3 tex_coord; 16 | flat int visible; 17 | } gs_in[]; 18 | 19 | out VertexOut 20 | { 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/DirLight_shadow_mapping.glsl" 29 | 30 | uniform DirLight dir_light; 31 | uniform Camera camera; 32 | 33 | void main() 34 | { 35 | gl_Layer = gl_InvocationID; 36 | for (int i = 0; i < 2; i++) 37 | { 38 | gs_out.visible = gs_in[i].visible; 39 | gs_out.color = gs_in[i].color; 40 | gs_out.back_color = gs_in[i].back_color; 41 | gs_out.tex_coord = gs_in[i].tex_coord; 42 | 43 | gl_Position = world_to_lightNDC(dir_light, camera, gl_InvocationID, gl_in[i].gl_Position.xyz); 44 | EmitVertex(); 45 | } 46 | EndPrimitive(); 47 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/DirLight_depth/DirLight_depth_points.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | layout (points, invocations=CSM_LEVELS) in; 9 | layout (points, max_vertices=1) out; 10 | 11 | in VertexOut 12 | { 13 | vec4 color; 14 | vec4 back_color; 15 | vec3 tex_coord; 16 | flat int visible; 17 | } gs_in[]; 18 | 19 | out VertexOut 20 | { 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/DirLight_shadow_mapping.glsl" 29 | 30 | uniform DirLight dir_light; 31 | uniform Camera camera; 32 | 33 | void main() 34 | { 35 | gl_Layer = gl_InvocationID; 36 | 37 | gs_out.visible = gs_in[0].visible; 38 | gs_out.color = gs_in[0].color; 39 | gs_out.back_color = gs_in[0].back_color; 40 | gs_out.tex_coord = gs_in[0].tex_coord; 41 | 42 | gl_Position = world_to_lightNDC(dir_light, camera, gl_InvocationID, gl_in[0].gl_Position.xyz); 43 | EmitVertex(); 44 | EndPrimitive(); 45 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/OIT_blend.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | #include "../include/OIT.glsl" 7 | 8 | uniform sampler2D accum_map; 9 | uniform sampler2D reveal_map; 10 | 11 | void main() 12 | { 13 | vec4 accum = texture(accum_map, tex_coord); 14 | float reveal = texture(reveal_map, tex_coord).r; 15 | frag_color = blend_composite(accum, reveal); 16 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/PointLight_depth/PointLight_depth.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | in GeometryOut 8 | { 9 | vec3 world_pos; 10 | vec4 color; 11 | vec4 back_color; 12 | vec3 tex_coord; 13 | flat int visible; 14 | } fs_in; 15 | 16 | #include "../../Lights/PointLight.glsl" 17 | #include "../../include/InternalMaterial.glsl" 18 | 19 | uniform PointLight point_light; 20 | uniform Material material; 21 | uniform Material back_material; 22 | 23 | void main() 24 | { 25 | if (fs_in.visible == 0) 26 | { 27 | discard; 28 | } 29 | 30 | InternalMaterial internal_material; 31 | if (gl_FrontFacing) 32 | { 33 | internal_material = fetch_internal_material( 34 | fs_in.color, material, fs_in.tex_coord.st 35 | ); 36 | } 37 | else 38 | { 39 | internal_material = fetch_internal_material( 40 | fs_in.back_color, back_material, fs_in.tex_coord.st 41 | ); 42 | } 43 | 44 | if (internal_material.opacity < 1E-6) 45 | { 46 | discard; 47 | } 48 | 49 | float distance_to_light = length(point_light.abs_position - fs_in.world_pos); 50 | gl_FragDepth = distance_to_light / point_light.coverage; 51 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/PointLight_depth/PointLight_depth.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | layout (triangles, invocations=6) in; 8 | layout (triangle_strip, max_vertices=3) out; 9 | 10 | in VertexOut 11 | { 12 | vec4 color; 13 | vec4 back_color; 14 | vec3 tex_coord; 15 | flat int visible; 16 | } gs_in[]; 17 | 18 | out GeometryOut 19 | { 20 | vec3 world_pos; 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/PointLight.glsl" 29 | 30 | uniform PointLight point_light; 31 | 32 | void main() 33 | { 34 | vec3 v1 = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz; 35 | vec3 v2 = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz; 36 | vec3 face_world_normal = normalize(cross(v1, v2)); 37 | 38 | gl_Layer = gl_InvocationID; 39 | 40 | Camera camera = cube_camera(gl_InvocationID, point_light.abs_position, 0.1, point_light.coverage); 41 | for (int i = 0; i < 3; i++) 42 | { 43 | gs_out.world_pos = gl_in[i].gl_Position.xyz; 44 | gs_out.visible = gs_in[i].visible; 45 | gs_out.color = gs_in[i].color; 46 | gs_out.back_color = gs_in[i].back_color; 47 | gs_out.tex_coord = gs_in[i].tex_coord; 48 | 49 | gl_Position = Camera_project(camera, gs_out.world_pos); 50 | EmitVertex(); 51 | } 52 | 53 | EndPrimitive(); 54 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/PointLight_depth/PointLight_depth.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | layout (location = 0) in vec3 position; 6 | layout (location = 1) in vec3 tex_coord; 7 | layout (location = 2) in vec4 color; 8 | layout (location = 3) in vec4 back_color; 9 | 10 | // instance 11 | layout (location = 4) in vec4 affine_transform_row0; 12 | layout (location = 5) in vec4 affine_transform_row1; 13 | layout (location = 6) in vec4 affine_transform_row2; 14 | layout (location = 7) in int visible; 15 | 16 | out VertexOut 17 | { 18 | vec4 color; 19 | vec4 back_color; 20 | vec3 tex_coord; 21 | flat int visible; 22 | } vs_out; 23 | 24 | #include "../../include/transform.glsl" 25 | 26 | void main() 27 | { 28 | mat4 transform = transpose(mat4( 29 | affine_transform_row0, 30 | affine_transform_row1, 31 | affine_transform_row2, 32 | vec4(0, 0, 0, 1) 33 | )); 34 | 35 | vec3 world_pos = transform_apply(transform, position); 36 | gl_Position = vec4(world_pos, 1); 37 | 38 | vs_out.visible = visible; 39 | vs_out.color = color; 40 | vs_out.back_color = back_color; 41 | vs_out.tex_coord = tex_coord; 42 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/PointLight_depth/PointLight_depth_lines.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | layout (lines, invocations=6) in; 8 | layout (line_strip, max_vertices=2) out; 9 | 10 | in VertexOut 11 | { 12 | vec4 color; 13 | vec4 back_color; 14 | vec3 tex_coord; 15 | flat int visible; 16 | } gs_in[]; 17 | 18 | out GeometryOut 19 | { 20 | vec3 world_pos; 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/PointLight.glsl" 29 | 30 | uniform PointLight point_light; 31 | 32 | void main() 33 | { 34 | gl_Layer = gl_InvocationID; 35 | Camera camera = cube_camera(gl_InvocationID, point_light.abs_position, 0.1, point_light.coverage); 36 | for (int i = 0; i < 2; i++) 37 | { 38 | gs_out.world_pos = gl_in[i].gl_Position.xyz; 39 | gs_out.visible = gs_in[i].visible; 40 | gs_out.color = gs_in[i].color; 41 | gs_out.back_color = gs_in[i].back_color; 42 | gs_out.tex_coord = gs_in[i].tex_coord; 43 | 44 | gl_Position = Camera_project(camera, gs_out.world_pos); 45 | EmitVertex(); 46 | } 47 | EndPrimitive(); 48 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/PointLight_depth/PointLight_depth_points.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | layout (points, invocations=6) in; 8 | layout (points, max_vertices=1) out; 9 | 10 | in VertexOut 11 | { 12 | vec4 color; 13 | vec4 back_color; 14 | vec3 tex_coord; 15 | flat int visible; 16 | } gs_in[]; 17 | 18 | out GeometryOut 19 | { 20 | vec3 world_pos; 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/PointLight.glsl" 29 | 30 | uniform PointLight point_light; 31 | 32 | void main() 33 | { 34 | gl_Layer = gl_InvocationID; 35 | Camera camera = cube_camera(gl_InvocationID, point_light.abs_position, 0.1, point_light.coverage); 36 | gs_out.world_pos = gl_in[0].gl_Position.xyz; 37 | gs_out.visible = gs_in[0].visible; 38 | gs_out.color = gs_in[0].color; 39 | gs_out.back_color = gs_in[0].back_color; 40 | gs_out.tex_coord = gs_in[0].tex_coord; 41 | 42 | gl_Position = Camera_project(camera, gs_out.world_pos); 43 | EmitVertex(); 44 | EndPrimitive(); 45 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/SpotLight_depth/SpotLight_depth.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | in GeometryOut 8 | { 9 | vec3 world_pos; 10 | vec4 color; 11 | vec4 back_color; 12 | vec3 tex_coord; 13 | flat int visible; 14 | } fs_in; 15 | 16 | #include "../../Lights/SpotLight.glsl" 17 | #include "../../include/InternalMaterial.glsl" 18 | 19 | uniform SpotLight spot_light; 20 | uniform Material material; 21 | uniform Material back_material; 22 | 23 | void main() 24 | { 25 | if (fs_in.visible == 0) 26 | { 27 | discard; 28 | } 29 | 30 | InternalMaterial internal_material; 31 | if (gl_FrontFacing) 32 | { 33 | internal_material = fetch_internal_material(fs_in.color, material, fs_in.tex_coord.st); 34 | } 35 | else 36 | { 37 | internal_material = fetch_internal_material(fs_in.back_color, back_material, fs_in.tex_coord.st); 38 | } 39 | 40 | if (internal_material.opacity < 1E-6) 41 | { 42 | discard; 43 | } 44 | 45 | float distance_to_light = length(spot_light.abs_position - fs_in.world_pos); 46 | gl_FragDepth = distance_to_light / spot_light.coverage; 47 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/SpotLight_depth/SpotLight_depth.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | layout (triangles, invocations=6) in; 8 | layout (triangle_strip, max_vertices=3) out; 9 | 10 | in VertexOut 11 | { 12 | vec4 color; 13 | vec4 back_color; 14 | vec3 tex_coord; 15 | flat int visible; 16 | } gs_in[]; 17 | 18 | out GeometryOut 19 | { 20 | vec3 world_pos; 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/SpotLight.glsl" 29 | 30 | uniform SpotLight spot_light; 31 | 32 | void main() 33 | { 34 | vec3 v1 = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz; 35 | vec3 v2 = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz; 36 | vec3 face_world_normal = normalize(cross(v1, v2)); 37 | 38 | gl_Layer = gl_InvocationID; 39 | Camera camera = cube_camera(gl_InvocationID, spot_light.abs_position, 0.1, spot_light.coverage); 40 | for (int i = 0; i < 3; i++) 41 | { 42 | gs_out.world_pos = gl_in[i].gl_Position.xyz; 43 | gs_out.visible = gs_in[i].visible; 44 | gs_out.color = gs_in[i].color; 45 | gs_out.back_color = gs_in[i].back_color; 46 | gs_out.tex_coord = gs_in[i].tex_coord; 47 | 48 | gl_Position = Camera_project(camera, gs_out.world_pos); 49 | EmitVertex(); 50 | } 51 | 52 | EndPrimitive(); 53 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/SpotLight_depth/SpotLight_depth_lines.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | layout (lines, invocations=6) in; 8 | layout (line_strip, max_vertices=2) out; 9 | 10 | in VertexOut 11 | { 12 | vec4 color; 13 | vec4 back_color; 14 | vec3 tex_coord; 15 | flat int visible; 16 | } gs_in[]; 17 | 18 | out GeometryOut 19 | { 20 | vec3 world_pos; 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/SpotLight.glsl" 29 | 30 | uniform SpotLight spot_light; 31 | 32 | void main() 33 | { 34 | gl_Layer = gl_InvocationID; 35 | Camera camera = cube_camera(gl_InvocationID, spot_light.abs_position, 0.1, spot_light.coverage); 36 | for (int i = 0; i < 2; i++) 37 | { 38 | gs_out.world_pos = gl_in[i].gl_Position.xyz; 39 | gs_out.visible = gs_in[i].visible; 40 | gs_out.color = gs_in[i].color; 41 | gs_out.back_color = gs_in[i].back_color; 42 | gs_out.tex_coord = gs_in[i].tex_coord; 43 | 44 | gl_Position = Camera_project(camera, gs_out.world_pos); 45 | EmitVertex(); 46 | } 47 | EndPrimitive(); 48 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/SpotLight_depth/SpotLight_depth_points.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | layout (points, invocations=6) in; 8 | layout (points, max_vertices=1) out; 9 | 10 | in VertexOut 11 | { 12 | vec4 color; 13 | vec4 back_color; 14 | vec3 tex_coord; 15 | flat int visible; 16 | } gs_in[]; 17 | 18 | out GeometryOut 19 | { 20 | vec3 world_pos; 21 | vec4 color; 22 | vec4 back_color; 23 | vec3 tex_coord; 24 | flat int visible; 25 | } gs_out; 26 | 27 | #include "../../include/Camera.glsl" 28 | #include "../../Lights/SpotLight.glsl" 29 | 30 | uniform SpotLight spot_light; 31 | 32 | void main() 33 | { 34 | gl_Layer = gl_InvocationID; 35 | Camera camera = cube_camera(gl_InvocationID, spot_light.abs_position, 0.1, spot_light.coverage); 36 | gs_out.world_pos = gl_in[0].gl_Position.xyz; 37 | gs_out.visible = gs_in[0].visible; 38 | gs_out.color = gs_in[0].color; 39 | gs_out.back_color = gs_in[0].back_color; 40 | gs_out.tex_coord = gs_in[0].tex_coord; 41 | 42 | gl_Position = Camera_project(camera, gs_out.world_pos); 43 | EmitVertex(); 44 | EndPrimitive(); 45 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/deferred_rendering/deferred_rendering.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | in vec2 tex_coord; 9 | out vec4 out_color; 10 | 11 | #include "../../include/shading_all.glsl" 12 | #include "read_from_gbuffer.glsl" 13 | 14 | uniform sampler2D world_pos_and_alpha_map; 15 | uniform sampler2D world_normal_and_emission_r_map; 16 | uniform sampler2D ambient_and_emission_g_map; 17 | uniform sampler2D diffuse_or_base_color_and_emission_b_map; 18 | uniform sampler2D specular_and_shininess_map; 19 | uniform sampler2D reflection_map; 20 | uniform sampler2D env_center_and_mixed_value_map; 21 | uniform usampler2D mixed_uint_map; 22 | uniform Camera camera; 23 | uniform Background background; 24 | 25 | #if USE_FOG 26 | uniform Fog fog; 27 | #endif 28 | 29 | void main() 30 | { 31 | PostShadingInfo shading_info = read_from_gbuffer(camera, 32 | world_pos_and_alpha_map, world_normal_and_emission_r_map, 33 | ambient_and_emission_g_map, diffuse_or_base_color_and_emission_b_map, 34 | specular_and_shininess_map, reflection_map, 35 | env_center_and_mixed_value_map, mixed_uint_map, tex_coord 36 | ); 37 | 38 | out_color = post_shading_all(camera, camera, background 39 | #if USE_FOG 40 | , fog 41 | #endif 42 | , shading_info 43 | ); 44 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/deferred_rendering/draw_points_to_gbuffer.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | 7 | in VertexOut 8 | { 9 | mat4 affine_transform; 10 | vec3 world_pos; 11 | mat3 world_TBN; 12 | vec3 tex_coord; 13 | vec4 color; 14 | flat int visible; 15 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 16 | flat uvec2 env_map_handle; 17 | #endif 18 | } fs_in; 19 | 20 | layout(location=3) out vec4 world_pos_and_alpha; 21 | layout(location=4) out vec4 world_normal_and_emission_r; 22 | layout(location=2) out vec4 ambient_and_emission_g; 23 | layout(location=0) out vec4 base_color_and_emission_b; 24 | layout(location=1) out vec4 specular_and_shininess; 25 | layout(location=5) out vec4 reflection; 26 | layout(location=6) out vec4 env_center_and_mixed_value; 27 | layout(location=7) out uvec4 mixed_uint; 28 | 29 | #include "../../include/InternalMaterial.glsl" 30 | #include "../../include/parallax_mapping.glsl" 31 | #include "../../include/math.glsl" 32 | #include "../../include/transform.glsl" 33 | #include "write_to_gbuffer.glsl" 34 | 35 | uniform Camera camera; 36 | uniform Material material; 37 | uniform vec3 mesh_center; 38 | 39 | void main() 40 | { 41 | if (fs_in.visible == 0) 42 | { 43 | discard; 44 | } 45 | 46 | vec2 tex_coord = fs_in.tex_coord.st; 47 | mat3 world_TBN = fs_in.world_TBN; 48 | vec3 world_pos = fs_in.world_pos; 49 | vec3 env_center = transform_apply(fs_in.affine_transform, mesh_center); 50 | change_geometry(camera, material, tex_coord, world_TBN, world_pos); 51 | InternalMaterial internal_material = fetch_internal_material(fs_in.color, material, tex_coord); 52 | 53 | write_to_gbuffer( 54 | internal_material, world_pos, world_TBN[2], env_center, 55 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 56 | fs_in.env_map_handle, 57 | #endif 58 | false, 59 | world_pos_and_alpha, world_normal_and_emission_r, ambient_and_emission_g, 60 | base_color_and_emission_b, specular_and_shininess, 61 | reflection, env_center_and_mixed_value, mixed_uint 62 | ); 63 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/draw_frame.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | in vec2 tex_coord; 6 | out vec4 frag_color; 7 | 8 | uniform sampler2D screen_image; 9 | uniform sampler2DArray screen_image_array; 10 | uniform int layer; 11 | uniform int index; 12 | uniform bool gray; 13 | uniform bool invert; 14 | 15 | void main() 16 | { 17 | if (layer < 0) 18 | frag_color = max(texture(screen_image, tex_coord), 0.0); 19 | else 20 | frag_color = max(texture(screen_image_array, vec3(tex_coord, layer)), 0.0); 21 | 22 | if (gray) 23 | frag_color = vec4(vec3(frag_color[index]), 1); 24 | if (invert) 25 | frag_color.rgb = 1 - frag_color.rgb; 26 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/draw_geometry/draw_geometry.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | in GeometryOut 9 | { 10 | mat4 affine_transform; 11 | vec3 world_pos; 12 | mat3 world_TBN; 13 | vec3 tex_coord; 14 | vec4 color; 15 | vec4 back_color; 16 | flat int visible; 17 | } fs_in; 18 | 19 | layout(location=3) out vec3 world_pos; 20 | layout(location=4) out vec3 world_normal; 21 | 22 | #include "../../include/InternalMaterial.glsl" 23 | #include "../../include/shading_all.glsl" 24 | 25 | uniform Material material; 26 | uniform Material back_material; 27 | uniform Camera camera; 28 | 29 | void main() 30 | { 31 | if (fs_in.visible == 0) 32 | { 33 | discard; 34 | } 35 | 36 | vec2 tex_coord = fs_in.tex_coord.st; 37 | mat3 world_TBN = fs_in.world_TBN; 38 | world_pos = fs_in.world_pos; 39 | InternalMaterial internal_material; 40 | 41 | if (gl_FrontFacing) 42 | { 43 | change_geometry(camera, material, tex_coord, world_TBN, world_pos); 44 | if (hasnan(world_TBN[2]) || length(world_TBN[2]) < 1E-6) 45 | { 46 | discard; 47 | } 48 | 49 | internal_material = fetch_internal_material(fs_in.color, material, tex_coord); 50 | } 51 | else 52 | { 53 | change_geometry(camera, back_material, tex_coord, world_TBN, world_pos); 54 | if (hasnan(world_TBN[2]) || length(world_TBN[2]) < 1E-6) 55 | { 56 | discard; 57 | } 58 | 59 | internal_material = fetch_internal_material(fs_in.back_color, back_material, tex_coord); 60 | } 61 | 62 | if (internal_material.opacity < 1E-6) 63 | { 64 | discard; 65 | } 66 | 67 | world_normal = world_TBN[2]; 68 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/draw_geometry/draw_geometry.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | // vertex 4 | layout (location = 0) in vec3 position; 5 | layout (location = 1) in vec3 tangent; 6 | layout (location = 2) in vec3 bitangent; 7 | layout (location = 3) in vec3 normal; 8 | layout (location = 4) in vec3 tex_coord; 9 | layout (location = 5) in vec4 color; 10 | layout (location = 6) in vec4 back_color; 11 | 12 | // instance 13 | layout (location = 7) in vec4 affine_transform_row0; 14 | layout (location = 8) in vec4 affine_transform_row1; 15 | layout (location = 9) in vec4 affine_transform_row2; 16 | layout (location = 10) in int visible; 17 | 18 | out VertexOut 19 | { 20 | mat4 affine_transform; 21 | mat3 world_TBN; 22 | vec3 tex_coord; 23 | vec3 back_tex_coord; 24 | vec4 color; 25 | vec4 back_color; 26 | flat int visible; 27 | } vs_out; 28 | 29 | #include "../../include/transform.glsl" 30 | #include "../../include/tex_coord.glsl" 31 | #include "../../include/Camera.glsl" 32 | #include "../../include/Material.glsl" 33 | 34 | uniform Camera camera; 35 | uniform Material material; 36 | uniform Material back_material; 37 | 38 | void main() 39 | { 40 | mat4 transform = transpose(mat4( 41 | affine_transform_row0, 42 | affine_transform_row1, 43 | affine_transform_row2, 44 | vec4(0, 0, 0, 1) 45 | )); 46 | 47 | vs_out.affine_transform = transform; 48 | vs_out.color = color; 49 | vs_out.back_color = back_color; 50 | vs_out.visible = visible; 51 | vs_out.world_TBN = transform_apply_to_TBN(transform, mat3(tangent, bitangent, normal)); 52 | transform_tex_coord(material, back_material, tex_coord, vs_out.tex_coord, vs_out.back_tex_coord); 53 | 54 | gl_Position = vec4(transform_apply(transform, position), 1); 55 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/draw_geometry/draw_geometry_lines.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : enable 7 | 8 | // vertex 9 | layout (location = 0) in vec3 position; 10 | layout (location = 1) in vec3 bitangent; 11 | layout (location = 2) in vec3 tex_coord; 12 | layout (location = 3) in vec4 color; 13 | 14 | // instance 15 | layout (location = 4) in vec4 affine_transform_row0; 16 | layout (location = 5) in vec4 affine_transform_row1; 17 | layout (location = 6) in vec4 affine_transform_row2; 18 | layout (location = 8) in int visible; 19 | 20 | out VertexOut 21 | { 22 | mat4 affine_transform; 23 | vec3 world_pos; 24 | vec3 world_normal; 25 | vec3 tex_coord; 26 | vec4 color; 27 | flat int visible; 28 | } vs_out; 29 | 30 | #include "../../include/transform.glsl" 31 | #include "../../include/Camera.glsl" 32 | 33 | uniform Camera camera; 34 | 35 | void main() 36 | { 37 | mat4 transform = transpose(mat4( 38 | affine_transform_row0, 39 | affine_transform_row1, 40 | affine_transform_row2, 41 | vec4(0, 0, 0, 1) 42 | )); 43 | 44 | vs_out.affine_transform = transform; 45 | vs_out.color = color; 46 | vs_out.tex_coord = tex_coord; 47 | vs_out.world_pos = transform_apply(transform, position); 48 | vec3 world_bitangent = mat3(transform) * bitangent; 49 | vec3 to_camera = normalize(camera.abs_position - vs_out.world_pos); 50 | vec3 world_tangent = normalize(cross(world_bitangent, to_camera)); 51 | vs_out.world_normal = normalize(cross(world_tangent, world_bitangent)); 52 | vs_out.visible = visible; 53 | 54 | gl_Position = Camera_project(camera, vs_out.world_pos); 55 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/draw_geometry/draw_geometry_points.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | in VertexOut 9 | { 10 | mat4 affine_transform; 11 | vec3 world_pos; 12 | vec3 world_normal; 13 | vec3 tex_coord; 14 | vec4 color; 15 | flat int visible; 16 | } fs_in; 17 | 18 | layout(location=3) out vec3 world_pos; 19 | layout(location=4) out vec3 world_normal; 20 | 21 | #include "../../include/InternalMaterial.glsl" 22 | #include "../../include/Material.glsl" 23 | #include "../../include/Camera.glsl" 24 | 25 | uniform Material material; 26 | uniform Camera camera; 27 | 28 | void main() 29 | { 30 | if (fs_in.visible == 0) 31 | { 32 | discard; 33 | } 34 | 35 | InternalMaterial internal_material = 36 | fetch_internal_material(fs_in.color, material, fs_in.tex_coord.st); 37 | 38 | if (internal_material.opacity < 1E-6) 39 | { 40 | discard; 41 | } 42 | 43 | world_pos = fs_in.world_pos; 44 | world_normal = fs_in.world_normal; 45 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/draw_geometry/draw_geometry_points.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : enable 7 | 8 | // vertex 9 | layout (location = 0) in vec3 position; 10 | layout (location = 1) in vec3 tex_coord; 11 | layout (location = 2) in vec4 color; 12 | 13 | // instance 14 | layout (location = 3) in vec4 affine_transform_row0; 15 | layout (location = 4) in vec4 affine_transform_row1; 16 | layout (location = 5) in vec4 affine_transform_row2; 17 | layout (location = 6) in int visible; 18 | 19 | out VertexOut 20 | { 21 | mat4 affine_transform; 22 | vec3 world_pos; 23 | vec3 world_normal; 24 | vec3 tex_coord; 25 | vec4 color; 26 | flat int visible; 27 | } vs_out; 28 | 29 | #include "../../include/transform.glsl" 30 | #include "../../include/Camera.glsl" 31 | 32 | uniform Camera camera; 33 | 34 | void main() 35 | { 36 | mat4 transform = transpose(mat4( 37 | affine_transform_row0, 38 | affine_transform_row1, 39 | affine_transform_row2, 40 | vec4(0, 0, 0, 1) 41 | )); 42 | 43 | vs_out.affine_transform = transform; 44 | vs_out.color = color; 45 | vs_out.tex_coord = tex_coord; 46 | vs_out.world_pos = transform_apply(transform, position); 47 | vs_out.world_normal = normalize(camera.abs_position - vs_out.world_pos); 48 | vs_out.visible = visible; 49 | 50 | gl_Position = Camera_project(camera, vs_out.world_pos); 51 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/env_mapping/env_OIT_blend.frag: -------------------------------------------------------------------------------- 1 | 2 | #version 430 core 3 | 4 | in vec2 tex_coord; 5 | out vec4 frag_color; 6 | 7 | #include "../../include/OIT.glsl" 8 | #include "../../include/math.glsl" 9 | #include "../../include/quat.glsl" 10 | 11 | uniform samplerCube opaque_color_map; 12 | uniform samplerCube accum_map; 13 | uniform samplerCube reveal_map; 14 | 15 | void main() 16 | { 17 | float theta = M_PI*(1.5 - 2*tex_coord.x); 18 | float phi = M_PI*(tex_coord.y-0.5); 19 | 20 | vec3 cube_tex_coord; 21 | cube_tex_coord.x = cos(phi)*cos(theta); 22 | cube_tex_coord.y = cos(phi)*sin(theta); 23 | cube_tex_coord.z = sin(phi); 24 | cube_tex_coord = quat_apply(quat(cos45, sin45, 0, 0), cube_tex_coord); 25 | 26 | vec4 opaque_color = max(texture(opaque_color_map, cube_tex_coord), 0.0); 27 | vec4 accum = texture(accum_map, cube_tex_coord); 28 | float reveal = texture(reveal_map, cube_tex_coord).r; 29 | if (hasinf(accum.rgb)) 30 | { 31 | accum.rgb = vec3(accum.a); 32 | } 33 | 34 | vec3 transparent_color = accum.rgb / max(accum.a, 1E-6); 35 | float alpha = exp(reveal); 36 | frag_color.rgb = mix(transparent_color, opaque_color.rgb, alpha); 37 | frag_color.a = 1-(1-opaque_color.a)*alpha; 38 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/env_mapping/gen_env_map.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | // vertex 4 | layout (location = 0) in vec3 position; 5 | layout (location = 1) in vec3 tangent; 6 | layout (location = 2) in vec3 bitangent; 7 | layout (location = 3) in vec3 normal; 8 | layout (location = 4) in vec3 tex_coord; 9 | layout (location = 5) in vec4 color; 10 | layout (location = 6) in vec4 back_color; 11 | 12 | // instance 13 | layout (location = 7) in vec4 affine_transform_row0; 14 | layout (location = 8) in vec4 affine_transform_row1; 15 | layout (location = 9) in vec4 affine_transform_row2; 16 | 17 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 18 | layout (location = 10) in uvec2 env_map_handle; 19 | #endif 20 | 21 | layout (location = 11) in int visible; 22 | 23 | out VertexOut 24 | { 25 | mat4 affine_transform; 26 | mat3 world_TBN; 27 | vec3 tex_coord; 28 | vec3 back_tex_coord; 29 | vec4 color; 30 | vec4 back_color; 31 | 32 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 33 | flat uvec2 env_map_handle; 34 | #endif 35 | 36 | flat int visible; 37 | } vs_out; 38 | 39 | #include "../../include/transform.glsl" 40 | #include "../../include/tex_coord.glsl" 41 | #include "../../include/Material.glsl" 42 | 43 | uniform Material material; 44 | uniform Material back_material; 45 | 46 | void main() 47 | { 48 | mat4 transform = transpose(mat4( 49 | affine_transform_row0, 50 | affine_transform_row1, 51 | affine_transform_row2, 52 | vec4(0, 0, 0, 1) 53 | )); 54 | 55 | vs_out.affine_transform = transform; 56 | vs_out.color = color; 57 | vs_out.back_color = back_color; 58 | vs_out.world_TBN = transform_apply_to_TBN(transform, mat3(tangent, bitangent, normal)); 59 | 60 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 61 | vs_out.env_map_handle = env_map_handle; 62 | #endif 63 | 64 | transform_tex_coord(material, back_material, tex_coord, vs_out.tex_coord, vs_out.back_tex_coord); 65 | vs_out.visible = visible; 66 | 67 | gl_Position = vec4(transform_apply(transform, position), 1); 68 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/env_mapping/gen_env_map_points.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | in GeometryOut 9 | { 10 | mat4 affine_transform; 11 | vec3 world_pos; 12 | mat3 world_TBN; 13 | vec3 tex_coord; 14 | vec4 color; 15 | flat int visible; 16 | } fs_in; 17 | 18 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 19 | in flat uvec2 env_map_handle; 20 | #endif 21 | 22 | layout(location=0) out vec4 out_color; 23 | layout(location=1) out vec4 accum; 24 | layout(location=2) out float reveal; 25 | 26 | #include "../../include/Camera.glsl" 27 | #include "../../include/Material.glsl" 28 | #include "../../include/OIT.glsl" 29 | #include "../../include/fog.glsl" 30 | #include "../../include/shading_all.glsl" 31 | 32 | uniform vec3 view_center; 33 | uniform vec3 mesh_center; 34 | uniform Material material; 35 | uniform bool is_opaque_pass; 36 | uniform Camera CSM_camera; 37 | uniform Background background; 38 | 39 | #if USE_FOG 40 | uniform Fog fog; 41 | #endif 42 | 43 | void main() 44 | { 45 | if (fs_in.visible == 0) 46 | { 47 | discard; 48 | } 49 | 50 | Camera camera = cube_camera(gl_Layer, view_center); 51 | 52 | ShadingInfo shading_info; 53 | shading_info.color = fs_in.color; 54 | #if USE_DYNAMIC_ENV_MAPPING 55 | shading_info.env_map_handle = env_map_handle; 56 | #endif 57 | shading_info.is_opaque_pass = is_opaque_pass; 58 | shading_info.is_sphere = false; 59 | shading_info.world_TBN = fs_in.world_TBN; 60 | shading_info.world_pos = fs_in.world_pos; 61 | shading_info.tex_coord = fs_in.tex_coord.st; 62 | shading_info.affine_transform = fs_in.affine_transform; 63 | shading_info.mesh_center = mesh_center; 64 | 65 | out_color = shading_all(camera, CSM_camera, background, material 66 | #if USE_FOG 67 | , fog 68 | #endif 69 | , shading_info); 70 | 71 | if (!is_opaque_pass && out_color.a < 1 - 1E-6) 72 | { 73 | vec3 view_pos = world_to_view(camera, fs_in.world_pos); 74 | get_OIT_info(out_color, view_pos.y, accum, reveal); 75 | out_color = vec4(0); 76 | } 77 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/env_mapping/gen_env_map_points.geom: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | layout (points, invocations=6) in; 9 | layout (points, max_vertices=1) out; 10 | 11 | in VertexOut 12 | { 13 | mat4 affine_transform; 14 | vec3 tex_coord; 15 | vec4 color; 16 | 17 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 18 | flat uvec2 env_map_handle; 19 | #endif 20 | 21 | flat int visible; 22 | } gs_in[]; 23 | 24 | out GeometryOut 25 | { 26 | mat4 affine_transform; 27 | vec3 world_pos; 28 | vec3 world_normal; 29 | vec3 tex_coord; 30 | vec4 color; 31 | flat int visible; 32 | } gs_out; 33 | 34 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 35 | out flat uvec2 env_map_handle; 36 | #endif 37 | 38 | #include "../../include/transform.glsl" 39 | #include "../../include/Camera.glsl" 40 | #include "../../include/InternalMaterial.glsl" 41 | #include "../../Lights/Lights_lighting.glsl" 42 | 43 | uniform vec3 view_center; 44 | uniform Material material; 45 | uniform Camera CSM_camera; 46 | 47 | void main() 48 | { 49 | gl_Layer = gl_InvocationID; 50 | Camera camera = cube_camera(gl_InvocationID, view_center); 51 | 52 | gs_out.affine_transform = gs_in[0].affine_transform; 53 | gs_out.world_pos = gl_in[0].gl_Position.xyz; 54 | gs_out.world_normal = normalize(camera.abs_position - gs_out.world_pos); 55 | gs_out.tex_coord = gs_in[0].tex_coord; 56 | gs_out.color = gs_in[0].color; 57 | gs_out.visible = gs_in[0].visible; 58 | 59 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 60 | env_map_handle = gs_in[0].env_map_handle; 61 | #endif 62 | 63 | #if USE_SHADING_MODEL_FLAT || USE_SHADING_MODEL_GOURAUD 64 | if (material.shading_model == SHADING_MODEL_FLAT || 65 | material.shading_model == SHADING_MODEL_GOURAUD) 66 | { 67 | InternalMaterial internal_material = fetch_internal_material(gs_in[0].color, material, gs_in[0].tex_coord.st); 68 | gs_out.color = vec4(lighting(internal_material, CSM_camera, camera.abs_position, gs_out.world_pos, gs_out.world_normal), 1.0); 69 | } 70 | #endif 71 | 72 | gl_Position = Camera_project(camera, gs_out.world_pos); 73 | EmitVertex(); 74 | EndPrimitive(); 75 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/env_mapping/gen_env_map_points.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | // vertex 4 | layout (location = 0) in vec3 position; 5 | layout (location = 1) in vec3 tex_coord; 6 | layout (location = 2) in vec4 color; 7 | 8 | // instance 9 | layout (location = 3) in vec4 affine_transform_row0; 10 | layout (location = 4) in vec4 affine_transform_row1; 11 | layout (location = 5) in vec4 affine_transform_row2; 12 | 13 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 14 | layout (location = 6) in uvec2 env_map_handle; 15 | #endif 16 | 17 | layout (location = 7) in int visible; 18 | 19 | out VertexOut 20 | { 21 | mat4 affine_transform; 22 | vec3 tex_coord; 23 | vec4 color; 24 | 25 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 26 | flat uvec2 env_map_handle; 27 | #endif 28 | 29 | flat int visible; 30 | } vs_out; 31 | 32 | #include "../../include/transform.glsl" 33 | 34 | void main() 35 | { 36 | mat4 transform = transpose(mat4( 37 | affine_transform_row0, 38 | affine_transform_row1, 39 | affine_transform_row2, 40 | vec4(0, 0, 0, 1) 41 | )); 42 | 43 | vec3 world_pos = transform_apply(transform, position); 44 | gl_Position = vec4(world_pos, 1); 45 | 46 | vs_out.affine_transform = transform; 47 | vs_out.color = color; 48 | vs_out.tex_coord = tex_coord; 49 | 50 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 51 | vs_out.env_map_handle = env_map_handle; 52 | #endif 53 | 54 | vs_out.visible = visible; 55 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/forward_rendering/forward_draw_points.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : require 7 | 8 | in VertexOut 9 | { 10 | mat4 affine_transform; 11 | vec3 world_pos; 12 | mat3 world_TBN; 13 | vec3 tex_coord; 14 | vec4 color; 15 | flat int visible; 16 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 17 | flat uvec2 env_map_handle; 18 | #endif 19 | 20 | } fs_in; 21 | 22 | layout(location=0) out vec4 out_color; 23 | layout(location=1) out vec4 accum; 24 | layout(location=2) out float reveal; 25 | layout(location=3) out vec3 world_pos; 26 | layout(location=4) out vec3 world_normal; 27 | 28 | #include "../../include/Material.glsl" 29 | #include "../../include/OIT.glsl" 30 | #include "../../include/fog.glsl" 31 | #include "../../include/shading_all.glsl" 32 | 33 | uniform Material material; 34 | uniform Camera camera; 35 | uniform bool is_opaque_pass; 36 | uniform vec3 mesh_center; 37 | 38 | #if USE_FOG 39 | uniform Fog fog; 40 | #endif 41 | 42 | uniform Background background; 43 | 44 | void main() 45 | { 46 | if (fs_in.visible == 0) 47 | { 48 | discard; 49 | } 50 | 51 | ShadingInfo shading_info; 52 | shading_info.color = fs_in.color; 53 | #if USE_DYNAMIC_ENV_MAPPING 54 | shading_info.env_map_handle = fs_in.env_map_handle; 55 | #endif 56 | shading_info.is_opaque_pass = is_opaque_pass; 57 | shading_info.is_sphere = false; 58 | shading_info.world_TBN = fs_in.world_TBN; 59 | shading_info.world_pos = fs_in.world_pos; 60 | shading_info.tex_coord = fs_in.tex_coord.st; 61 | shading_info.affine_transform = fs_in.affine_transform; 62 | shading_info.mesh_center = mesh_center; 63 | 64 | out_color = shading_all(camera, background, material 65 | #if USE_FOG 66 | , fog 67 | #endif 68 | , shading_info); 69 | 70 | if (is_opaque_pass) 71 | { 72 | world_pos = shading_info.world_pos; 73 | world_normal = shading_info.world_TBN[2]; 74 | } 75 | else if (out_color.a < 1 - 1E-6) 76 | { 77 | vec3 view_pos = world_to_view(camera, fs_in.world_pos); 78 | get_OIT_info(out_color, view_pos.y, accum, reveal); 79 | out_color = vec4(0); 80 | } 81 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/forward_rendering/forward_draw_points.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #if USE_BINDLESS_TEXTURE 4 | #extension GL_ARB_bindless_texture : require 5 | #endif 6 | #extension GL_EXT_texture_array : enable 7 | 8 | // vertex 9 | layout (location = 0) in vec3 position; 10 | layout (location = 1) in vec3 tex_coord; 11 | layout (location = 2) in vec4 color; 12 | 13 | // instance 14 | layout (location = 3) in vec4 affine_transform_row0; 15 | layout (location = 4) in vec4 affine_transform_row1; 16 | layout (location = 5) in vec4 affine_transform_row2; 17 | 18 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 19 | layout (location = 6) in uvec2 env_map_handle; 20 | #endif 21 | 22 | layout (location = 7) in int visible; 23 | 24 | out VertexOut 25 | { 26 | mat4 affine_transform; 27 | vec3 world_pos; 28 | vec3 world_normal; 29 | vec3 tex_coord; 30 | vec4 color; 31 | flat int visible; 32 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 33 | flat uvec2 env_map_handle; 34 | #endif 35 | 36 | } vs_out; 37 | 38 | #include "../../include/transform.glsl" 39 | #include "../../include/Camera.glsl" 40 | #include "../../include/InternalMaterial.glsl" 41 | #include "../../Lights/Lights_lighting.glsl" 42 | 43 | uniform Camera camera; 44 | uniform Material material; 45 | 46 | void main() 47 | { 48 | mat4 transform = transpose(mat4( 49 | affine_transform_row0, 50 | affine_transform_row1, 51 | affine_transform_row2, 52 | vec4(0, 0, 0, 1) 53 | )); 54 | 55 | vs_out.affine_transform = transform; 56 | vs_out.color = color; 57 | vs_out.tex_coord = tex_coord; 58 | vs_out.world_pos = transform_apply(transform, position); 59 | vs_out.world_normal = normalize(camera.abs_position - vs_out.world_pos); 60 | 61 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 62 | vs_out.env_map_handle = env_map_handle; 63 | #endif 64 | 65 | vs_out.visible = visible; 66 | gl_Position = Camera_project(camera, vs_out.world_pos); 67 | 68 | #if USE_SHADING_MODEL_FLAT || USE_SHADING_MODEL_GOURAUD 69 | if (material.shading_model == SHADING_MODEL_FLAT || 70 | material.shading_model == SHADING_MODEL_GOURAUD) 71 | { 72 | InternalMaterial internal_material = fetch_internal_material(color, material, tex_coord.st); 73 | vs_out.color = vec4(lighting(internal_material, camera, camera.abs_position, vs_out.world_pos, vs_out.world_normal), 1.0); 74 | } 75 | #endif 76 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/forward_rendering/forward_rendering.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | // vertex 4 | layout (location = 0) in vec3 position; 5 | layout (location = 1) in vec3 tangent; 6 | layout (location = 2) in vec3 bitangent; 7 | layout (location = 3) in vec3 normal; 8 | layout (location = 4) in vec3 tex_coord; 9 | layout (location = 5) in vec4 color; 10 | layout (location = 6) in vec4 back_color; 11 | 12 | // instance 13 | layout (location = 7) in vec4 affine_transform_row0; 14 | layout (location = 8) in vec4 affine_transform_row1; 15 | layout (location = 9) in vec4 affine_transform_row2; 16 | 17 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 18 | layout (location = 10) in uvec2 env_map_handle; 19 | #endif 20 | 21 | layout (location = 11) in int visible; 22 | 23 | out VertexOut 24 | { 25 | mat4 affine_transform; 26 | mat3 world_TBN; 27 | vec3 tex_coord; 28 | vec3 back_tex_coord; 29 | vec4 color; 30 | vec4 back_color; 31 | 32 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 33 | flat uvec2 env_map_handle; 34 | #endif 35 | 36 | flat int visible; 37 | } vs_out; 38 | 39 | #include "../../include/transform.glsl" 40 | #include "../../include/Camera.glsl" 41 | #include "../../include/tex_coord.glsl" 42 | 43 | uniform Camera camera; 44 | uniform Material material; 45 | uniform Material back_material; 46 | 47 | void main() 48 | { 49 | mat4 transform = transpose(mat4( 50 | affine_transform_row0, 51 | affine_transform_row1, 52 | affine_transform_row2, 53 | vec4(0, 0, 0, 1) 54 | )); 55 | 56 | vs_out.affine_transform = transform; 57 | vs_out.color = color; 58 | vs_out.back_color = back_color; 59 | vs_out.world_TBN = transform_apply_to_TBN(transform, mat3(tangent, bitangent, normal)); 60 | 61 | #if USE_BINDLESS_TEXTURE && USE_DYNAMIC_ENV_MAPPING 62 | vs_out.env_map_handle = env_map_handle; 63 | #endif 64 | 65 | transform_tex_coord(material, back_material, tex_coord, vs_out.tex_coord, vs_out.back_tex_coord); 66 | 67 | vs_out.visible = visible; 68 | gl_Position = vec4(transform_apply(transform, position), 1); 69 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/skybox/skybox.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | layout(location=0) out vec4 frag_color; 4 | layout(location=3) out vec3 world_pos; 5 | layout(location=4) out vec3 world_normal; 6 | 7 | in vec3 tex_coord; 8 | in vec3 view_dir; 9 | 10 | #include "../../include/fog.glsl" 11 | #include "../../include/Camera.glsl" 12 | 13 | uniform samplerCube skybox_map; 14 | uniform float sky_distance; 15 | uniform Camera camera; 16 | 17 | #if USE_FOG 18 | uniform Fog fog; 19 | #endif 20 | 21 | void main() 22 | { 23 | frag_color = max(texture(skybox_map, tex_coord), 0.0); 24 | 25 | #if USE_FOG 26 | frag_color.rgb = fog_apply(fog, frag_color.rgb, sky_distance); 27 | #endif 28 | 29 | world_pos = sky_distance * normalize(view_dir); 30 | world_normal = vec3(0); 31 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/skybox/skybox.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | layout (location = 0) in vec3 position; 3 | 4 | out vec3 tex_coord; 5 | out vec3 view_dir; 6 | 7 | #include "../../include/Camera.glsl" 8 | 9 | uniform Camera camera; 10 | 11 | void main() 12 | { 13 | tex_coord = position; 14 | vec3 world_dir = quat_apply(quat(cos45, -sin45, 0, 0), position); 15 | view_dir = world_dir_to_view(camera, world_dir); 16 | vec4 NDC = view_to_NDC(camera, view_dir, CAMERA_PROJECTION_PERSPECTIVE); 17 | 18 | gl_Position = NDC.xyww; 19 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/skydome/skydome.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 frag_tex_coord; 4 | in vec3 view_dir; 5 | 6 | layout(location=0) out vec4 frag_color; 7 | layout(location=3) out vec3 world_pos; 8 | layout(location=4) out vec3 world_normal; 9 | 10 | #include "../../include/fog.glsl" 11 | #include "../../include/Camera.glsl" 12 | 13 | uniform sampler2D skydome_map; 14 | uniform float sky_distance; 15 | uniform Camera camera; 16 | 17 | #if USE_FOG 18 | uniform Fog fog; 19 | #endif 20 | 21 | void main() 22 | { 23 | frag_color = max(textureLod(skydome_map, frag_tex_coord, 0), 0.0); 24 | 25 | #if USE_FOG 26 | frag_color.rgb = fog_apply(fog, frag_color.rgb, sky_distance); 27 | #endif 28 | 29 | world_pos = sky_distance * normalize(view_dir); 30 | world_normal = vec3(0); 31 | } -------------------------------------------------------------------------------- /glass_engine/glsl/Pipelines/skydome/skydome.vert: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | layout (location = 0) in vec3 position; 4 | layout (location = 1) in vec2 tex_coord; 5 | 6 | out vec2 frag_tex_coord; 7 | out vec3 view_dir; 8 | 9 | #include "../../include/Camera.glsl" 10 | 11 | uniform Camera camera; 12 | 13 | void main() 14 | { 15 | frag_tex_coord = tex_coord; 16 | view_dir = world_dir_to_view(camera, position); 17 | vec4 NDC = view_to_NDC(camera, view_dir, CAMERA_PROJECTION_PERSPECTIVE); 18 | 19 | gl_Position = NDC.xyww; 20 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/ACES_tone_mapper.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _ACES_TONE_MAPPER_GLSL_ 2 | #define _ACES_TONE_MAPPER_GLSL_ 3 | 4 | //================================================================================================= 5 | // 6 | // Baking Lab 7 | // by MJP and David Neubelt 8 | // http://mynameismjp.wordpress.com/ 9 | // https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl 10 | // 11 | // All code licensed under the MIT license 12 | // 13 | //================================================================================================= 14 | 15 | // The code in this file was originally written by Stephen Hill (@self_shadow), who deserves all 16 | // credit for coming up with this fit and implementing it. Buy him a beer next time you see him. :) 17 | 18 | // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT 19 | const mat3 ACESInputMat = mat3( 20 | vec3(0.59719, 0.07600, 0.02840), 21 | vec3(0.35458, 0.90834, 0.13383), 22 | vec3(0.04823, 0.01566, 0.83777) 23 | ); 24 | 25 | // ODT_SAT => XYZ => D60_2_D65 => sRGB 26 | const mat3x3 ACESOutputMat = mat3( 27 | vec3(1.60475, -0.10208, -0.00327), 28 | vec3(-0.53108, 1.10813, -0.07276), 29 | vec3(-0.07367, -0.00605, 1.07602) 30 | ); 31 | 32 | vec3 RRTAndODTFit(vec3 v) 33 | { 34 | vec3 a = v * (v + 0.0245786) - 0.000090537; 35 | vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; 36 | return a / b; 37 | } 38 | 39 | vec3 ACESFitted(vec3 color) 40 | { 41 | color = ACESInputMat * color; 42 | 43 | // Apply RRT and ODT 44 | color = RRTAndODTFit(color); 45 | 46 | color = ACESOutputMat * color; 47 | 48 | // Clamp to [0, 1] 49 | color = clamp(color, 0.0, 1.0); 50 | 51 | return color; 52 | } 53 | 54 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 55 | { 56 | vec4 result = max(textureLod(screen_image, tex_coord, 0), 0.0); 57 | result.rgb = ACESFitted(result.rgb); 58 | // result.rgb = sin(acos(-1)/2.0*result.rgb); 59 | return result; 60 | } 61 | 62 | 63 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/FXAA.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | in vec2 tex_coord; 6 | out vec4 frag_color; 7 | 8 | #include "../include/FXAA.glsl" 9 | 10 | uniform sampler2D screen_image; 11 | 12 | void main() 13 | { 14 | frag_color = textureFXAA(screen_image, tex_coord); 15 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/FXAA_array.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | in vec2 tex_coord; 6 | out vec4 frag_color; 7 | 8 | #include "../include/FXAA.glsl" 9 | 10 | uniform sampler2DArray screen_image; 11 | 12 | void main() 13 | { 14 | frag_color = textureFXAA(screen_image, vec3(tex_coord, gl_Layer)); 15 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/FXAA_cube.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | in vec2 tex_coord; 6 | out vec4 frag_color; 7 | 8 | #include "../include/FXAA.glsl" 9 | 10 | uniform samplerCube screen_image; 11 | 12 | void main() 13 | { 14 | frag_color = textureCubeFaceFXAA(screen_image, tex_coord, gl_Layer); 15 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/bloom_mix.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | uniform sampler2D screen_image; 7 | uniform sampler2D bloom_image; 8 | 9 | void main() 10 | { 11 | vec4 src_color = max(texture(screen_image, tex_coord), 0.0); 12 | vec4 bloom_color = max(texture(bloom_image, tex_coord), 0.0); 13 | frag_color = mix(bloom_color, src_color, 0.9); 14 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/bloom_upsampling.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | uniform float filter_radius; 7 | uniform sampler2D screen_image; 8 | 9 | void main() 10 | { 11 | // The filter kernel is applied with a radius, specified in texture 12 | // coordinates, so that the radius will vary across mip resolutions. 13 | float dx = filter_radius; 14 | float dy = filter_radius; 15 | 16 | // Take 9 samples around current texel: 17 | // a - b - c 18 | // d - e - f 19 | // g - h - i 20 | // === ('e' is the current texel) === 21 | vec4 a = textureLod(screen_image, vec2(tex_coord.x - dx, tex_coord.y + dy), 0); 22 | vec4 b = textureLod(screen_image, vec2(tex_coord.x, tex_coord.y + dy), 0); 23 | vec4 c = textureLod(screen_image, vec2(tex_coord.x + dx, tex_coord.y + dy), 0); 24 | 25 | vec4 d = textureLod(screen_image, vec2(tex_coord.x - dx, tex_coord.y), 0); 26 | vec4 e = textureLod(screen_image, vec2(tex_coord.x, tex_coord.y), 0); 27 | vec4 f = textureLod(screen_image, vec2(tex_coord.x + dx, tex_coord.y), 0); 28 | 29 | vec4 g = textureLod(screen_image, vec2(tex_coord.x - dx, tex_coord.y - dy), 0); 30 | vec4 h = textureLod(screen_image, vec2(tex_coord.x, tex_coord.y - dy), 0); 31 | vec4 i = textureLod(screen_image, vec2(tex_coord.x + dx, tex_coord.y - dy), 0); 32 | 33 | // Apply weighted distribution, by using a 3x3 tent filter: 34 | // 1 | 1 2 1 | 35 | // -- * | 2 4 2 | 36 | // 16 | 1 2 1 | 37 | frag_color = e*4.0; 38 | frag_color += (b+d+f+h)*2.0; 39 | frag_color += (a+c+g+i); 40 | frag_color *= 1.0 / 16.0; 41 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/exposure_adaptor.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _EXPOSURE_ADAPTOR_GLSL_ 2 | #define _EXPOSURE_ADAPTOR_GLSL_ 3 | 4 | #include "../include/math.glsl" 5 | 6 | uniform float fps; 7 | 8 | buffer CurrentLuma 9 | { 10 | float current_luma; 11 | }; 12 | 13 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 14 | { 15 | vec4 color = max(textureLod(screen_image, tex_coord, 0), 0.0); 16 | ivec2 frag_coord = ivec2(gl_FragCoord.xy); 17 | if (!camera.lens.auto_exposure) 18 | { 19 | if (frag_coord.x == 0 && frag_coord.y == 0) 20 | { 21 | current_luma = pow((1.0/camera.lens.exposure) - 0.5, 2.0); 22 | memoryBarrier(); 23 | } 24 | 25 | color.rgb = camera.lens.exposure * color.rgb; 26 | } 27 | else if (!camera.lens.local_exposure) 28 | { 29 | float target_luma = luminance(max(textureLod(screen_image, camera.lens.focus_tex_coord, 6).rgb, 0.0)); 30 | float luma = target_luma; 31 | float _current_luma = current_luma; 32 | if (abs(target_luma-current_luma) > 1E-6) 33 | { 34 | if (_current_luma != 0 && camera.lens.exposure_adapt_time > 1E-6) 35 | { 36 | float sgn = sign(target_luma - _current_luma); 37 | float a = log(10)/camera.lens.exposure_adapt_time; 38 | luma = _current_luma + a * (target_luma - _current_luma) / fps; 39 | if (sgn == sign(luma - target_luma)) 40 | { 41 | luma = target_luma; 42 | } 43 | } 44 | if (frag_coord.x == 0 && frag_coord.y == 0) 45 | { 46 | current_luma = luma; 47 | memoryBarrier(); 48 | } 49 | } 50 | 51 | color.rgb = color.rgb / (0.5 + sqrt(luma)); 52 | return color; 53 | } 54 | else 55 | { 56 | float luma = luminance(max(textureLod(screen_image, tex_coord, 7).rgb, 0.0)); 57 | color.rgb = color.rgb / (0.5 + sqrt(luma)); 58 | } 59 | return color; 60 | } 61 | 62 | 63 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/gauss_blur.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | uniform sampler2D screen_image; 7 | uniform bool horizontal; 8 | 9 | uniform uvec2 kernel_shape; 10 | uniform vec2 sigma; 11 | uniform int channels; 12 | 13 | void main() 14 | { 15 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0); 16 | frag_color = vec4(0); 17 | 18 | if (horizontal) 19 | { 20 | float double_sigma_x2 = 2*sigma.x*sigma.x; 21 | float t = tex_coord.t; 22 | float weight_sum = 0; 23 | for(int j = 0; j < kernel_shape.x; j++) 24 | { 25 | float dj = j - 0.5*(kernel_shape.x-1); 26 | float ds = dj*tex_offset.x; 27 | float s = tex_coord.s + ds; 28 | float weight = exp(-dj*dj/double_sigma_x2); 29 | vec4 current_value = max(textureLod(screen_image, vec2(s, t), 0), 0.0); 30 | if (channels == 1) 31 | { 32 | current_value.gb = current_value.rr; 33 | current_value.a = 1; 34 | } 35 | frag_color += weight * current_value; 36 | weight_sum += weight; 37 | } 38 | frag_color = frag_color / weight_sum; 39 | } 40 | else 41 | { 42 | float double_sigma_y2 = 2*sigma.y*sigma.y; 43 | float s = tex_coord.s; 44 | float weight_sum = 0; 45 | for(int i = 0; i < kernel_shape.y; i++) 46 | { 47 | float di = i - 0.5*(kernel_shape.y-1); 48 | float dt = di*tex_offset.y; 49 | float t = tex_coord.t + dt; 50 | float weight = exp(-di*di/double_sigma_y2); 51 | vec4 current_value = max(textureLod(screen_image, vec2(s, t), 0), 0.0); 52 | if (channels == 1) 53 | { 54 | current_value.gb = current_value.rr; 55 | current_value.a = 1; 56 | } 57 | frag_color += weight * current_value; 58 | weight_sum += weight; 59 | } 60 | frag_color = frag_color / weight_sum; 61 | } 62 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/gauss_blur_array.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | in vec2 tex_coord; 6 | out vec4 frag_color; 7 | 8 | uniform sampler2DArray screen_image; 9 | uniform bool horizontal; 10 | 11 | uniform uvec2 kernel_shape; 12 | uniform vec2 sigma; 13 | uniform int channels; 14 | 15 | void main() 16 | { 17 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0).xy; 18 | frag_color = vec4(0); 19 | 20 | if (horizontal) 21 | { 22 | float double_sigma_x2 = 2*sigma.x*sigma.x; 23 | float t = tex_coord.t; 24 | float weight_sum = 0; 25 | for(int j = 0; j < kernel_shape.x; j++) 26 | { 27 | float d = (j - 0.5*(kernel_shape.x-1))*tex_offset.x; 28 | float s = tex_coord.s + d; 29 | float weight = exp(-d*d/double_sigma_x2); 30 | vec4 current_value = max(texture(screen_image, vec3(s, t, gl_Layer)), 0.0); 31 | if (channels == 1) 32 | { 33 | current_value.gb = current_value.rr; 34 | current_value.a = 1; 35 | } 36 | frag_color += weight * current_value; 37 | weight_sum += weight; 38 | } 39 | frag_color = frag_color / weight_sum; 40 | } 41 | else 42 | { 43 | float double_sigma_y2 = 2*sigma.y*sigma.y; 44 | float s = tex_coord.s; 45 | float weight_sum = 0; 46 | for(int i = 0; i < kernel_shape.y; i++) 47 | { 48 | float d = (i - 0.5*(kernel_shape.y-1))*tex_offset.y; 49 | float t = tex_coord.t + d; 50 | float weight = exp(-d*d/double_sigma_y2); 51 | vec4 current_value = max(texture(screen_image, vec3(s, t, gl_Layer)), 0.0); 52 | if (channels == 1) 53 | { 54 | current_value.gb = current_value.rr; 55 | current_value.a = 1; 56 | } 57 | frag_color += weight * current_value; 58 | weight_sum += weight; 59 | } 60 | frag_color = frag_color / weight_sum; 61 | } 62 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/gauss_blur_cube.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | #include "../include/sampling.glsl" 7 | 8 | uniform samplerCube screen_image; 9 | uniform bool horizontal; 10 | 11 | uniform uvec2 kernel_shape; 12 | uniform vec2 sigma; 13 | uniform int channels; 14 | 15 | void main() 16 | { 17 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0).xy; 18 | frag_color = vec4(0); 19 | 20 | if (horizontal) 21 | { 22 | float double_sigma_x2 = 2*sigma.x*sigma.x; 23 | float t = tex_coord.t; 24 | float weight_sum = 0; 25 | for(int j = 0; j < kernel_shape.x; j++) 26 | { 27 | float d = (j - 0.5*(kernel_shape.x-1))*tex_offset.x; 28 | float s = tex_coord.s + d; 29 | float weight = exp(-d*d/double_sigma_x2); 30 | vec4 current_value = max(textureCubeFace(screen_image, vec2(s, t), gl_Layer), 0.0); 31 | if (channels == 1) 32 | { 33 | current_value.gb = current_value.rr; 34 | current_value.a = 1; 35 | } 36 | frag_color += weight * current_value; 37 | weight_sum += weight; 38 | } 39 | frag_color = frag_color / weight_sum; 40 | } 41 | else 42 | { 43 | float double_sigma_y2 = 2*sigma.y*sigma.y; 44 | float s = tex_coord.s; 45 | float weight_sum = 0; 46 | for(int i = 0; i < kernel_shape.y; i++) 47 | { 48 | float d = (i - 0.5*(kernel_shape.y-1))*tex_offset.y; 49 | float t = tex_coord.t + d; 50 | float weight = exp(-d*d/double_sigma_y2); 51 | vec4 current_value = max(textureCubeFace(screen_image, vec2(s, t), gl_Layer), 0.0); 52 | if (channels == 1) 53 | { 54 | current_value.gb = current_value.rr; 55 | current_value.a = 1; 56 | } 57 | frag_color += weight * current_value; 58 | weight_sum += weight; 59 | } 60 | frag_color = frag_color / weight_sum; 61 | } 62 | } -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/kernel_filter.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | uniform sampler2D screen_image; 7 | uniform int channels; 8 | 9 | buffer Kernel 10 | { 11 | int rows; 12 | int cols; 13 | float data[]; 14 | }; 15 | 16 | void main() 17 | { 18 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0); 19 | float dx = tex_offset.x; 20 | float dy = tex_offset.y; 21 | 22 | frag_color = vec4(0); 23 | for (int i = 0; i < rows; i++) 24 | { 25 | float t = tex_coord.t + (i - 0.5*(rows-1))*dy; 26 | for (int j = 0; j < cols; j++) 27 | { 28 | float s = tex_coord.s + (j - 0.5*(cols-1))*dx; 29 | vec4 current_value = max(textureLod(screen_image, vec2(s, t), 0), 0.0); 30 | if (channels == 1) 31 | { 32 | current_value.gb = current_value.rr; 33 | current_value.a = 1; 34 | } 35 | frag_color += data[i*cols + j] * current_value; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/kernel_filter_array.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | #extension GL_EXT_texture_array : require 4 | 5 | in vec2 tex_coord; 6 | out vec4 frag_color; 7 | 8 | uniform sampler2DArray screen_image; 9 | uniform int channels; 10 | 11 | buffer Kernel 12 | { 13 | int rows; 14 | int cols; 15 | float data[]; 16 | }; 17 | 18 | void main() 19 | { 20 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0).xy; 21 | float dx = tex_offset.x; 22 | float dy = tex_offset.y; 23 | 24 | frag_color = vec4(0); 25 | for (int i = 0; i < rows; i++) 26 | { 27 | float t = tex_coord.t + (i - 0.5*(rows-1))*dy; 28 | for (int j = 0; j < cols; j++) 29 | { 30 | float s = tex_coord.s + (j - 0.5*(cols-1))*dx; 31 | vec4 current_value = max(texture(screen_image, vec3(s, t, gl_Layer)), 0.0); 32 | if (channels == 1) 33 | { 34 | current_value.gb = current_value.rr; 35 | current_value.a = 1; 36 | } 37 | frag_color += data[i*cols + j] * current_value; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/kernel_filter_cube.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | 3 | in vec2 tex_coord; 4 | out vec4 frag_color; 5 | 6 | #include "../include/sampling.glsl" 7 | 8 | uniform samplerCube screen_image; 9 | uniform int channels; 10 | 11 | buffer Kernel 12 | { 13 | int rows; 14 | int cols; 15 | float data[]; 16 | }; 17 | 18 | void main() 19 | { 20 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0).xy; 21 | float dx = tex_offset.x; 22 | float dy = tex_offset.y; 23 | 24 | frag_color = vec4(0); 25 | for (int i = 0; i < rows; i++) 26 | { 27 | float t = tex_coord.t + (i - 0.5*(rows-1))*dy; 28 | for (int j = 0; j < cols; j++) 29 | { 30 | float s = tex_coord.s + (j - 0.5*(cols-1))*dx; 31 | vec4 current_value = max(textureCubeFace(screen_image, vec2(s, t), gl_Layer), 0.0); 32 | if (channels == 1) 33 | { 34 | current_value.gb = current_value.rr; 35 | current_value.a = 1; 36 | } 37 | frag_color += data[i*cols + j] * current_value; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/lut.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _LUT_GLSL_ 2 | #define _LUT_GLSL_ 3 | 4 | uniform sampler2D LUT; 5 | uniform float contribute; 6 | 7 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 8 | { 9 | ivec2 LUT_size = textureSize(LUT, 0); 10 | int block_width = 0; 11 | ivec2 block_shape = ivec2(0); 12 | if (LUT_size.x == LUT_size.y) 13 | { 14 | block_width = int(pow(LUT_size.x, 2.0/3.0)); 15 | } 16 | else 17 | { 18 | block_width = min(LUT_size.x, LUT_size.y); 19 | } 20 | block_shape = ivec2(block_width); 21 | 22 | ivec2 block_size = LUT_size / block_shape; 23 | vec2 block_ratio = vec2(block_shape) / vec2(LUT_size); 24 | int n_blocks = block_size.x * block_size.y; 25 | 26 | vec4 color = clamp(textureLod(screen_image, tex_coord, 0), 0.0, 1.0); 27 | vec2 dxy = color.rg * (block_ratio - 1.0/LUT_size) + 0.5/LUT_size; 28 | 29 | float i_blockf = color.b * (n_blocks - 1); 30 | int i_block = int(i_blockf); 31 | float rear = i_blockf - i_block; 32 | 33 | ivec2 block_index = ivec2(i_block % block_size.x, i_block / block_size.x); 34 | vec2 start_xy = block_index * block_ratio; 35 | vec2 new_tex_coord = start_xy + dxy; 36 | vec4 new_color = textureLod(LUT, vec2(new_tex_coord.x, 1-new_tex_coord.y), 0); 37 | 38 | if (i_block < n_blocks-1) 39 | { 40 | block_index = ivec2((i_block+1) % block_size.x, (i_block+1) / block_size.x); 41 | start_xy = block_index * block_ratio; 42 | new_tex_coord = start_xy + dxy; 43 | new_color = mix(new_color, textureLod(LUT, vec2(new_tex_coord.x, 1-new_tex_coord.y), 0), rear); 44 | } 45 | 46 | return mix(color, new_color, contribute); 47 | } 48 | 49 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/median_gray_blur5.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _MEDIAN_GRAY_BLUR5_GLSL_ 2 | #define _MEDIAN_GRAY_BLUR5_GLSL_ 3 | 4 | #define KERNEL_WIDTH 5 5 | 6 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 7 | { 8 | float values[KERNEL_WIDTH*KERNEL_WIDTH]; 9 | vec2 tex_offset = 1.0 / textureSize(screen_image, 0); 10 | float dx = tex_offset.x; 11 | float dy = tex_offset.y; 12 | 13 | int current_index = 0; 14 | float half_width = (KERNEL_WIDTH - 1.0)/2.0; 15 | for (float i = -half_width; i <= half_width; i += 1) 16 | { 17 | float y = tex_coord.y + dy*i; 18 | for (float j = -half_width; j <= half_width; j += 1) 19 | { 20 | float x = tex_coord.x + dx*j; 21 | values[current_index] = textureLod(screen_image, vec2(x, y), 0).r; 22 | current_index++; 23 | } 24 | } 25 | 26 | int N = KERNEL_WIDTH * KERNEL_WIDTH; 27 | for (int j = N-1; j >= 0; j--) 28 | { 29 | for (int i = 0; i < j; i++) 30 | { 31 | if (values[i] > values[i+1]) 32 | { 33 | float temp = values[i]; 34 | values[i] = values[i+1]; 35 | values[i+1] = temp; 36 | } 37 | } 38 | } 39 | 40 | int half_index = (KERNEL_WIDTH - 1) / 2; 41 | if (KERNEL_WIDTH % 2 == 0) 42 | { 43 | return vec4(vec3(0.5*(values[half_index] + values[half_index+1])), 1); 44 | } 45 | else 46 | { 47 | return vec4(vec3(values[half_index]), 1); 48 | } 49 | } 50 | 51 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/mul_filter.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _MUL_FILTER_GLSL_ 2 | #define _MUL_FILTER_GLSL_ 3 | 4 | uniform sampler2D filter_image; 5 | uniform int filter_channels; 6 | 7 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 8 | { 9 | vec4 color0 = max(textureLod(screen_image, tex_coord, 0), 0.0); 10 | vec4 color1 = max(textureLod(filter_image, tex_coord, 0), 0.0); 11 | if (filter_channels == 1) 12 | { 13 | color1.gb = color1.rr; 14 | color1.a = 1; 15 | } 16 | 17 | return color0 * color1; 18 | } 19 | 20 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/slit_stretch.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _SLIT_STRETCH_GLSL_ 2 | #define _SLIT_STRETCH_GLSL_ 3 | 4 | float triWave(float x) 5 | { 6 | return(abs(mod(x-10.0, 20.0)-10.0)+1.0); 7 | } 8 | 9 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 10 | { 11 | vec2 uv = 2.0*(tex_coord-0.5); 12 | 13 | vec2 uvR = uv*(1.0-length(uv)/(triWave(iTime*5.0))); 14 | vec2 uvG = uv*(1.0-length(uv)/(triWave(iTime*5.0+0.1))); 15 | vec2 uvB = uv*(1.0-length(uv)/(triWave(iTime*5.0+0.2))); 16 | 17 | uvR = uvR/2.0 + 0.5; 18 | uvG = uvG/2.0 + 0.5; 19 | uvB = uvB/2.0 + 0.5; 20 | 21 | float R = max(texture(screen_image, uvR).r, 0.0); 22 | float G = max(texture(screen_image, uvG).g, 0.0); 23 | float B = max(texture(screen_image, uvB).b, 0.0); 24 | 25 | return vec4(R, G, B, 1.0); 26 | } 27 | 28 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/star_field.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _STAR_FIELD_GLSL_ 2 | #define _STAR_FIELD_GLSL_ 3 | 4 | #define M_PI acos(-1) 5 | 6 | #define H(P) fract(sin(dot(P,vec2(127.1,311.7)))*43758.545) 7 | #define pR(a) mat2(cos(a),sin(a),-sin(a),cos(a)) 8 | 9 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 10 | { 11 | float t = iTime * 0.6; 12 | vec4 frag_color = max(texture(screen_image, tex_coord), 0.0); 13 | 14 | vec2 uv = (tex_coord-0.5) * 3.0; 15 | 16 | vec3 vuv = vec3(sin(iTime * 0.3), 1.0, cos(iTime)); 17 | vec3 ro = vec3(0.0, 0.0, 134.0); 18 | vec3 vrp = vec3(5.0, sin(iTime) * 60.0, 20.0); 19 | 20 | vrp.xz * pR(iTime); 21 | vrp.yz * pR(iTime * 0.2); 22 | 23 | vec3 vpn = normalize(vrp - ro); 24 | vec3 u = normalize(cross(vuv, vpn)); 25 | vec3 rd = normalize(vpn + uv.x * u + uv.y * cross(vpn, u)); 26 | 27 | vec3 sceneColor = vec3(0.0, 0.0, 0.3); 28 | vec3 flareCol = vec3(0.0); 29 | float flareIntensivity = 0.0; 30 | 31 | for (float k = 0.0; k < 400.0; k++) { 32 | float r = H(vec2(k)) * 2.0 - 1.0; 33 | vec3 flarePos = vec3(H(vec2(k) * r) * 20.0 - 10.0, r * 8.0, (mod(sin(k / 200.0 * M_PI * 4.0) * 15.0 - t * 13.0 * k * 0.007, 25.0))); 34 | float v = max(abs(dot(normalize(flarePos), rd)), 0.0); 35 | 36 | flareIntensivity += pow(v, 30000.0) * 4.0; 37 | flareIntensivity += pow(v, 1e2) * 0.15; 38 | flareIntensivity *= 1.0 - flarePos.z / 25.0; 39 | flareCol += vec3(flareIntensivity) * (vec3(sin(r * 3.12 - k), r, cos(k) * 2.0)) * 0.3; 40 | } 41 | 42 | sceneColor += abs(flareCol); 43 | sceneColor = mix(sceneColor, sceneColor.rrr * 1.4, length(uv) / 2.0); 44 | 45 | frag_color += vec4(pow(sceneColor, vec3(1.1)), 1.0); 46 | 47 | return frag_color; 48 | } 49 | 50 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/PostProcessEffects/water_wave.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _WATER_WAVE_GLSL_ 2 | #define _WATER_WAVE_GLSL_ 3 | 4 | vec4 post_process(sampler2D screen_image, vec2 tex_coord) 5 | { 6 | vec2 uv = tex_coord * 0.8 + 0.1; 7 | uv += cos(iTime*vec2(6.0, 7.0) + uv*10.0)*0.02; 8 | 9 | return max(texture(screen_image, uv), 0.0); 10 | } 11 | 12 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/CookTorrance.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _COOKTORRANCE_GLSL_ 2 | #define _COOKTORRANCE_GLSL_ 3 | 4 | #include "../include/Material.glsl" 5 | 6 | float NormalDistributionFunction(vec3 halfway_vec, vec3 normal, float roughness) 7 | { 8 | roughness = mix(0.02, 1.0, roughness); 9 | float roughness4 = pow(roughness, 4); 10 | return roughness4 / pow(1 - (1 - roughness4)*pow(dot(normal, halfway_vec), 2), 2); 11 | } 12 | 13 | float GeometryFunction(float cos_to_light, float cos_to_camera, float roughness) 14 | { 15 | float k = pow(roughness + 1, 2) / 8; 16 | float G = cos_to_light/(cos_to_light*(1 - k) + k) * cos_to_camera/(cos_to_camera*(1 - k) + k); 17 | return G; 18 | } 19 | 20 | vec3 FresnelEquation(float cos_to_camera, vec3 base_color, float metallic) 21 | { 22 | vec3 F0 = mix(vec3(0.04), base_color, metallic); 23 | vec3 F = F0 + (1 - F0) * pow(1 - cos_to_camera, 5); 24 | return F; 25 | } 26 | 27 | vec3 CookTorrance_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 28 | { 29 | float cos_to_light = max(dot(normal, to_light), 0); 30 | float cos_to_camera = max(dot(normal, to_camera), 0); 31 | vec3 halfway_vec = normalize(to_light + to_camera); 32 | float D = NormalDistributionFunction(halfway_vec, normal, material.roughness); 33 | float G = GeometryFunction(cos_to_light, cos_to_camera, material.roughness); 34 | vec3 F = FresnelEquation(cos_to_camera, material.base_color, material.metallic); 35 | vec3 kd = (1 - F)*(1 - material.metallic); 36 | vec3 Lo = kd * material.base_color * cos_to_light + D*G*F / (4*cos_to_camera + 0.001); 37 | return material.shadow_visibility * Lo; 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Flat.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _FLAT_GLSL_ 2 | #define _FLAT_GLSL_ 3 | 4 | #include "../include/Material.glsl" 5 | 6 | vec3 Flat_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 7 | { 8 | vec3 diffuse_color = material.base_color * Lambert_diffuse(to_light, normal); 9 | vec3 rim_color = material.base_color * rim(to_light, to_camera, normal, material.light_rim_power, material.rim_power); 10 | return material.shadow_visibility*diffuse_color + rim_color; 11 | } 12 | 13 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Fresnel.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _FRESNEL_GLSL_ 2 | #define _FRESNEL_GLSL_ 3 | 4 | #include "../include/Material.glsl" 5 | 6 | float Fresnel_diffuse(vec3 to_camera, vec3 normal, float rim_power) 7 | { 8 | float cos_to_camera = max(0, dot(to_camera, normal)); 9 | return pow(1 - cos_to_camera, 1/(0.001 + rim_power)); 10 | } 11 | 12 | vec3 Fresnel_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 13 | { 14 | return material.base_color * Fresnel_diffuse(to_camera, normal, material.rim_power); 15 | } 16 | 17 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Gouraud.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _GOURAUD_GLSL_ 2 | #define _GOURAUD_GLSL_ 3 | 4 | #include "Phong.glsl" 5 | 6 | vec3 Gouraud_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 7 | { 8 | return Phong_lighting(to_light, to_camera, normal, material); 9 | } 10 | 11 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Lambert.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _LAMBERT_GLSL_ 2 | #define _LAMBERT_GLSL_ 3 | 4 | #include "rim.glsl" 5 | #include "../include/Material.glsl" 6 | 7 | float Lambert_diffuse(vec3 to_light, vec3 normal) 8 | { 9 | return max(dot(to_light, normal), 0.0); 10 | } 11 | 12 | vec3 Lambert_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 13 | { 14 | vec3 diffuse_color = material.base_color * Lambert_diffuse(to_light, normal); 15 | vec3 rim_color = material.base_color * rim(to_light, to_camera, normal, material.light_rim_power, material.rim_power); 16 | return material.shadow_visibility * diffuse_color + rim_color; 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Minnaert.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _MINNAERT_GLSL_ 2 | #define _MINNAERT_GLSL_ 3 | 4 | #include "rim.glsl" 5 | #include "../include/Material.glsl" 6 | 7 | float Minnaert_diffuse(vec3 to_light, vec3 to_camera, vec3 normal, float roughness) 8 | { 9 | float cos_to_light = dot(to_light, normal); 10 | float cos_to_camera = dot(to_camera, normal); 11 | return max(cos_to_light * pow(cos_to_light*cos_to_camera, roughness), 0.0); 12 | } 13 | 14 | vec3 Minnaert_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 15 | { 16 | vec3 diffuse_color = material.base_color * Minnaert_diffuse(to_light, to_camera, normal, material.roughness); 17 | vec3 rim_color = material.base_color * rim(to_light, to_camera, normal, material.light_rim_power, material.rim_power); 18 | return material.shadow_visibility * diffuse_color + rim_color; 19 | } 20 | 21 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/OrenNayar.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _ORENNAYAR_GLSL_ 2 | #define _ORENNAYAR_GLSL_ 3 | 4 | #include "rim.glsl" 5 | #include "../include/Material.glsl" 6 | 7 | vec3 OrenNayar_diffuse(vec3 to_light, vec3 to_camera, vec3 normal, float roughness, vec3 diffuse_color) 8 | { 9 | float cos_theta_i = dot(normal, to_light); 10 | float cos_theta_r = dot(normal, to_camera); 11 | float theta_i = acos(cos_theta_i); 12 | float theta_r = acos(cos_theta_r); 13 | float cos_phi_r_phi_i = dot(normalize(to_camera - cos_theta_r*normal), normalize(to_light - cos_theta_i*normal)); 14 | float alpha = max(theta_r, theta_i); 15 | float beta = min(theta_r, theta_i); 16 | float sigma = 0.5*acos(-1)*roughness; 17 | float sigma2 = sigma*sigma; 18 | float C1 = 1 - 0.5 * sigma2 / (sigma2 + 0.33); 19 | float C2 = 0.45 * sigma2 / (sigma2 + 0.09); 20 | C2 *= (cos_phi_r_phi_i >= 0 ? sin(alpha) : sin(alpha) - pow(2*beta/M_PI, 3)); 21 | float C3 = 2 * sigma2/(sigma2 + 0.09) * pow((alpha/M_PI)*(beta/M_PI), 2); 22 | float L1 = C1 + cos_phi_r_phi_i*C2*tan(beta) + (1 - abs(cos_phi_r_phi_i))*C3*tan(0.5*(alpha+beta)); 23 | vec3 L2 = 0.17 * diffuse_color * sigma2 / (sigma2 + 0.13) * (1 - cos_phi_r_phi_i*pow(2*beta/M_PI, 2)); 24 | return (L1 + L2) * max(cos_theta_i, 0.0); 25 | } 26 | 27 | vec3 OrenNayar_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 28 | { 29 | vec3 diffuse_color = material.base_color * OrenNayar_diffuse(to_light, to_camera, normal, material.roughness, material.base_color); 30 | vec3 rim_color = material.base_color * rim(to_light, to_camera, normal, material.light_rim_power, material.rim_power); 31 | return material.shadow_visibility * diffuse_color + rim_color; 32 | } 33 | 34 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Phong.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _PHONG_GLSL_ 2 | #define _PHONG_GLSL_ 3 | 4 | float Phong_specular(vec3 to_light, vec3 to_camera, vec3 normal, float shininess) 5 | { 6 | vec3 reflect_dir = reflect(-to_light, normal); 7 | float cos_out = max(dot(reflect_dir, to_camera), 0.0); 8 | return pow(cos_out, shininess); 9 | } 10 | 11 | vec3 Phong_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 12 | { 13 | vec3 diffuse_color = material.base_color * Lambert_diffuse(to_light, normal); 14 | vec3 specular_color = material.specular * Phong_specular(to_light, to_camera, normal, material.shininess); 15 | vec3 rim_color = material.base_color * rim(to_light, to_camera, normal, material.light_rim_power, material.rim_power); 16 | return material.shadow_visibility*(diffuse_color + specular_color) + rim_color; 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/PhongBlinn.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _PHONGBLINN_GLSL_ 2 | #define _PHONGBLINN_GLSL_ 3 | 4 | float PhongBlinn_specular(vec3 to_light, vec3 to_camera, vec3 normal, float shininess) 5 | { 6 | vec3 halfway_vec = normalize(to_light + to_camera); 7 | float cos_out = max(dot(halfway_vec, normal), 0.0); 8 | return pow(cos_out, shininess); 9 | } 10 | 11 | vec3 PhongBlinn_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 12 | { 13 | vec3 diffuse_color = material.base_color * Lambert_diffuse(to_light, normal); 14 | vec3 specular_color = material.specular * PhongBlinn_specular(to_light, to_camera, normal, material.shininess); 15 | vec3 rim_color = material.base_color * rim(to_light, to_camera, normal, material.light_rim_power, material.rim_power); 16 | return material.shadow_visibility*(diffuse_color + specular_color) + rim_color; 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/Toon.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _TOON_GLSL_ 2 | #define _TOON_GLSL_ 3 | 4 | #include "Phong.glsl" 5 | 6 | float Toonify(float value, uint bands, float softness) 7 | { 8 | return (soft_floor(value*(bands - 1) - softness/2, softness/2) + 1) / (bands - 1); 9 | } 10 | 11 | vec3 Toon_lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 12 | { 13 | float diffuse_factor = Lambert_diffuse(to_light, normal); 14 | vec3 diffuse_color = material.base_color * Toonify(diffuse_factor, material.diffuse_bands, material.diffuse_softness); 15 | float specular_factor = Phong_specular(to_light, to_camera, normal, material.shininess); 16 | vec3 specular_color = material.specular * Toonify(specular_factor, material.specular_bands, material.specular_softness); 17 | float rim_factor = pow(1 - dot(normal, to_camera), 1/(0.001+material.rim_power)) * pow(max(0, dot(to_light, normal)), 1/(1+material.light_rim_power)); 18 | vec3 rim_color = material.base_color * soft_step(rim_factor-0.2, 0.05); 19 | return material.shadow_visibility*(diffuse_color + specular_color) + rim_color; 20 | } 21 | 22 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/lighting.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _LIGHTING_GLSL_ 2 | #define _LIGHTING_GLSL_ 3 | 4 | #include "Lambert.glsl" 5 | 6 | #if USE_SHADING_MODEL_FLAT 7 | #include "Flat.glsl" 8 | #endif 9 | 10 | #if USE_SHADING_MODEL_GOURAUD 11 | #include "Gouraud.glsl" 12 | #endif 13 | 14 | #if USE_SHADING_MODEL_PHONG 15 | #include "Phong.glsl" 16 | #endif 17 | 18 | #if USE_SHADING_MODEL_PHONG_BLINN 19 | #include "PhongBlinn.glsl" 20 | #endif 21 | 22 | #if USE_SHADING_MODEL_TOON 23 | #include "Toon.glsl" 24 | #endif 25 | 26 | #if USE_SHADING_MODEL_OREN_NAYAR 27 | #include "OrenNayar.glsl" 28 | #endif 29 | 30 | #if USE_SHADING_MODEL_MINNAERT 31 | #include "Minnaert.glsl" 32 | #endif 33 | 34 | #if USE_SHADING_MODEL_COOK_TORRANCE 35 | #include "CookTorrance.glsl" 36 | #endif 37 | 38 | #if USE_SHADING_MODEL_FRESNEL 39 | #include "Fresnel.glsl" 40 | #endif 41 | 42 | vec3 lighting(vec3 to_light, vec3 to_camera, vec3 normal, InternalMaterial material) 43 | { 44 | switch (material.shading_model) 45 | { 46 | #if USE_SHADING_MODEL_FLAT 47 | case SHADING_MODEL_FLAT: return Flat_lighting(to_light, to_camera, normal, material); 48 | #endif 49 | #if USE_SHADING_MODEL_GOURAUD 50 | case SHADING_MODEL_GOURAUD: return Gouraud_lighting(to_light, to_camera, normal, material); 51 | #endif 52 | #if USE_SHADING_MODEL_PHONG 53 | case SHADING_MODEL_PHONG: return Phong_lighting(to_light, to_camera, normal, material); 54 | #endif 55 | #if USE_SHADING_MODEL_PHONG_BLINN 56 | case SHADING_MODEL_PHONG_BLINN: return PhongBlinn_lighting(to_light, to_camera, normal, material); 57 | #endif 58 | #if USE_SHADING_MODEL_TOON 59 | case SHADING_MODEL_TOON: return Toon_lighting(to_light, to_camera, normal, material); 60 | #endif 61 | #if USE_SHADING_MODEL_OREN_NAYAR 62 | case SHADING_MODEL_OREN_NAYAR: return OrenNayar_lighting(to_light, to_camera, normal, material); 63 | #endif 64 | #if USE_SHADING_MODEL_MINNAERT 65 | case SHADING_MODEL_MINNAERT: return Minnaert_lighting(to_light, to_camera, normal, material); 66 | #endif 67 | #if USE_SHADING_MODEL_COOK_TORRANCE 68 | case SHADING_MODEL_COOK_TORRANCE: 69 | case SHADING_MODEL_PBR: return CookTorrance_lighting(to_light, to_camera, normal, material); 70 | #endif 71 | #if USE_SHADING_MODEL_FRESNEL 72 | case SHADING_MODEL_FRESNEL: return Fresnel_lighting(to_light, to_camera, normal, material); 73 | #endif 74 | default: return vec3(0); 75 | } 76 | } 77 | 78 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/ShadingModels/rim.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _RIM_GLSL_ 2 | #define _RIM_GLSL_ 3 | 4 | float rim(vec3 to_light, vec3 to_camera, vec3 normal, float light_rim_power, float material_rim_power) 5 | { 6 | if (light_rim_power < 1E-6 || material_rim_power < 1E-6) 7 | return 0; 8 | float light_rim = pow(clamp(0.5 - 0.5*dot(to_light, to_camera), 0, 1), 1/(0.001+light_rim_power)); 9 | float material_rim = pow(clamp(1 - dot(normal, to_camera), 0, 1), 1/(0.001+material_rim_power)); 10 | return light_rim * material_rim; 11 | } 12 | 13 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/FresnelRefract.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _FRESNELREFRACT_GLSL_ 2 | #define _FRESNELREFRACT_GLSL_ 3 | 4 | float fresnel_reflect_ratio(float n1, float n2, float cos_theta_i) 5 | { 6 | float sin_theta_i2 = 1 - cos_theta_i*cos_theta_i; 7 | float sin_theta_o2 = (n1*n1/(n2*n2))*sin_theta_i2; 8 | if (sin_theta_o2 >= 1) 9 | { 10 | return 1; 11 | } 12 | 13 | float cos_theta_o = sqrt(1 - sin_theta_o2); 14 | float n1_cos_theta_i = n1 * cos_theta_i; 15 | float n2_cos_theta_o = n2 * cos_theta_o; 16 | float n1_cos_theta_o = n1 * cos_theta_o; 17 | float n2_cos_theta_i = n2 * cos_theta_i; 18 | float Rs = (n1_cos_theta_i - n2_cos_theta_o) / (n1_cos_theta_i + n2_cos_theta_o); 19 | float Rp = (n1_cos_theta_o - n2_cos_theta_i) / (n1_cos_theta_o + n2_cos_theta_i); 20 | 21 | return clamp(0.5*(Rs*Rs + Rp*Rp), 0, 1); 22 | } 23 | 24 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/OIT.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _OIT_GLSL_ 2 | #define _OIT_GLSL_ 3 | 4 | #include "limits.glsl" 5 | 6 | float blend_weight1(float abs_z) 7 | { 8 | return clamp(10/(1E-5 + pow(abs_z/5, 2) + pow(abs_z/200, 6)), 1E-2, 3E3); 9 | } 10 | 11 | float blend_weight2(float abs_z) 12 | { 13 | return clamp(10/(1E-5 + pow(abs_z/5, 3) + pow(abs_z/200, 6)), 1E-2, 3E3); 14 | } 15 | 16 | float blend_weight3(float abs_z) 17 | { 18 | return clamp(10/(1E-5 + pow(abs_z/200, 4)), 1E-2, 3E3); 19 | } 20 | 21 | float blend_weight4(float dz) 22 | { 23 | return max(1E-2, 3E3*pow(1 - dz, 3)); 24 | } 25 | 26 | void get_OIT_info(vec4 out_color, float abs_z, out vec4 accum, out float reveal) 27 | { 28 | float weight = out_color.a * blend_weight2(abs_z); 29 | accum = vec4(out_color.rgb*out_color.a, out_color.a) * weight; 30 | reveal = log(1 - out_color.a); 31 | } 32 | 33 | vec4 blend_composite(vec4 accum, float reveal) 34 | { 35 | if (hasinf(accum.rgb)) 36 | { 37 | accum.rgb = vec3(accum.a); 38 | } 39 | vec3 average_color = accum.rgb / max(accum.a, 1E-6); 40 | return vec4(average_color, exp(reveal)); 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/ShadingInfo.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _SHADINGINFO_GLSL_ 2 | #define _SHADINGINFO_GLSL_ 3 | 4 | #include "Material.glsl" 5 | #include "background.glsl" 6 | 7 | struct ShadingInfo 8 | { 9 | vec4 color; 10 | #if USE_DYNAMIC_ENV_MAPPING 11 | uvec2 env_map_handle; 12 | #endif 13 | bool is_opaque_pass; 14 | bool is_sphere; 15 | mat3 world_TBN; 16 | vec3 world_pos; 17 | vec2 tex_coord; 18 | mat4 affine_transform; 19 | vec3 mesh_center; 20 | }; 21 | 22 | struct PostShadingInfo 23 | { 24 | InternalMaterial material; 25 | #if USE_DYNAMIC_ENV_MAPPING 26 | uvec2 env_map_handle; 27 | #endif 28 | bool is_sphere; 29 | vec3 world_pos; 30 | vec3 world_normal; 31 | vec3 env_center; 32 | }; 33 | 34 | 35 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/background.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _BACKGROUND_GLSL_ 2 | #define _BACKGROUND_GLSL_ 3 | 4 | struct Background 5 | { 6 | samplerCube skybox_map; 7 | sampler2D skydome_map; 8 | vec4 color; 9 | float distance; 10 | }; 11 | 12 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/fog.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _FOG_GLSL_ 2 | #define _FOG_GLSL_ 3 | 4 | #include "math.glsl" 5 | 6 | #if USE_FOG 7 | 8 | #define FOG_MODE_LINEAR 9729 9 | #define FOG_MODE_EXP 2048 10 | #define FOG_MODE_EXP2 2049 11 | 12 | struct Fog 13 | { 14 | uint mode; 15 | vec3 color; 16 | float extinction_density; 17 | float inscattering_density; 18 | }; 19 | 20 | vec3 fog_apply(Fog fog, vec3 color, float distance) 21 | { 22 | if (fog.extinction_density < 1E-6 && fog.inscattering_density < 1E-6) 23 | return color; 24 | 25 | float extinction = 1; 26 | float inscattering = 1; 27 | if (fog.mode == FOG_MODE_LINEAR) 28 | { 29 | extinction = max(0, 1 - fog.extinction_density*distance); 30 | inscattering = max(0, 1 - fog.inscattering_density*distance); 31 | } 32 | else if (fog.mode == FOG_MODE_EXP) 33 | { 34 | extinction = exp(-fog.extinction_density*distance); 35 | inscattering = exp(-fog.inscattering_density*distance); 36 | } 37 | else if (fog.mode == FOG_MODE_EXP2) 38 | { 39 | float d2 = distance*distance; 40 | extinction = exp(-fog.extinction_density*d2); 41 | inscattering = exp(-fog.inscattering_density*d2); 42 | } 43 | return color*extinction + fog.color * (1 - inscattering); 44 | } 45 | 46 | #endif 47 | 48 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/image_read_write.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _IMAGE_READ_WRITE_GLSL_ 2 | #define _IMAGE_READ_WRITE_GLSL_ 3 | 4 | #define imageRead(value_center, image, tex_coord) \ 5 | vec4 value_center;\ 6 | {\ 7 | ivec2 image_size = imageSize(image);\ 8 | float x_max = float(image_size.x - 1);\ 9 | float y_max = float(image_size.y - 1);\ 10 | \ 11 | vec2 texel_coord = tex_coord * (vec2(image_size) - 1.0);\ 12 | float x = floor(texel_coord.x);\ 13 | float y = floor(texel_coord.y);\ 14 | float x_rear = texel_coord.x - x;\ 15 | float y_rear = texel_coord.y - y;\ 16 | vec4 value1 = imageLoad(image, ivec2(x, y));\ 17 | vec4 value2 = imageLoad(image, ivec2(min(x+1, x_max), y));\ 18 | vec4 value3 = imageLoad(image, ivec2(x, min(y+1, y_max)));\ 19 | vec4 value4 = imageLoad(image, ivec2(min(x+1, x_max), min(y+1, y_max)));\ 20 | vec4 value12 = mix(value1, value2, x_rear);\ 21 | vec4 value34 = mix(value3, value4, x_rear);\ 22 | value_center = mix(value12, value34, y_rear);\ 23 | } 24 | 25 | #define imageWrite(image, tex_coord, value) \ 26 | {\ 27 | ivec2 image_size = imageSize(image);\ 28 | float x_max = float(image_size.x - 1);\ 29 | float y_max = float(image_size.y - 1);\ 30 | \ 31 | vec2 texel_coord = tex_coord * (vec2(image_size) - 1.0);\ 32 | float x = floor(texel_coord.x);\ 33 | float y = floor(texel_coord.y);\ 34 | float x_rear = texel_coord.x - x;\ 35 | float y_rear = texel_coord.y - y;\ 36 | \ 37 | vec4 value1 = (1-x_rear)*(1-y_rear)*value;\ 38 | vec4 value2 = x_rear*(1-y_rear)*value;\ 39 | vec4 value3 = (1-x_rear)*y_rear*value;\ 40 | vec4 value4 = x_rear*y_rear*value;\ 41 | \ 42 | ivec2 texel_coord1 = ivec2(x, y);\ 43 | ivec2 texel_coord2 = ivec2(min(x+1, x_max), y);\ 44 | ivec2 texel_coord3 = ivec2(x, min(y+1, y_max));\ 45 | ivec2 texel_coord4 = ivec2(min(x+1, x_max), min(y+1, y_max));\ 46 | \ 47 | vec4 old_value1 = imageLoad(image, texel_coord1);\ 48 | vec4 old_value2 = imageLoad(image, texel_coord2);\ 49 | vec4 old_value3 = imageLoad(image, texel_coord3);\ 50 | vec4 old_value4 = imageLoad(image, texel_coord4);\ 51 | \ 52 | imageStore(image, texel_coord1, old_value1+value1);\ 53 | memoryBarrierImage();\ 54 | \ 55 | imageStore(image, texel_coord2, old_value2+value2);\ 56 | memoryBarrierImage();\ 57 | \ 58 | imageStore(image, texel_coord3, old_value3+value3);\ 59 | memoryBarrierImage();\ 60 | \ 61 | imageStore(image, texel_coord4, old_value4+value4);\ 62 | memoryBarrierImage();\ 63 | } 64 | 65 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/math.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _MATH_GLSL_ 2 | #define _MATH_GLSL_ 3 | 4 | const float M_PI = acos(-1); 5 | const float cos45 = 0.5*sqrt(2); 6 | const float sin45 = cos45; 7 | 8 | uint get_digit(uint value, uint p) 9 | { 10 | value /= p; 11 | return (value - value / 10 * 10); 12 | } 13 | 14 | float luminance(vec3 color) 15 | { 16 | return dot(color, vec3(0.2126, 0.7152, 0.0722)); 17 | } 18 | 19 | float luminance(vec4 color) 20 | { 21 | return dot(color.rgb*color.a, vec3(0.2126, 0.7152, 0.0722)); 22 | } 23 | 24 | bool is_equal(float a, float b) 25 | { 26 | return abs(a - b) <= (abs(a) < abs(b) ? abs(b) : abs(a)) * 1E-6; 27 | } 28 | 29 | float max3(vec3 v) 30 | { 31 | return max(max(v.x, v.y), v.z); 32 | } 33 | 34 | float max4(vec4 v) 35 | { 36 | return max(max(max(v.x, v.y), v.z), v.w); 37 | } 38 | 39 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/quat.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _QUAT_GLSL_ 2 | #define _QUAT_GLSL_ 3 | 4 | struct quat 5 | { 6 | float w; 7 | float x; 8 | float y; 9 | float z; 10 | }; 11 | 12 | quat vec3_to_quat(vec3 v) 13 | { 14 | quat q; 15 | q.w = 0; 16 | q.x = v.x; 17 | q.y = v.y; 18 | q.z = v.z; 19 | return q; 20 | } 21 | 22 | quat vec4_to_quat(vec4 v) 23 | { 24 | quat q; 25 | q.w = v[0]; 26 | q.x = v[1]; 27 | q.y = v[2]; 28 | q.z = v[3]; 29 | return q; 30 | } 31 | 32 | quat quat_conj(quat q) 33 | { 34 | quat p; 35 | p.w = q.w; 36 | p.x = -q.x; 37 | p.y = -q.y; 38 | p.z = -q.z; 39 | return p; 40 | } 41 | 42 | quat quat_mult(quat p, quat q) 43 | { 44 | quat pq; 45 | pq.w = p.w*q.w - p.x*q.x - p.y*q.y - p.z*q.z; 46 | pq.x = p.w*q.x + p.x*q.w + p.y*q.z - p.z*q.y; 47 | pq.y = p.w*q.y - p.x*q.z + p.y*q.w + p.z*q.x; 48 | pq.z = p.w*q.z + p.x*q.y - p.y*q.x + p.z*q.w; 49 | return pq; 50 | } 51 | 52 | float quat_norm(quat q) 53 | { 54 | return sqrt(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z); 55 | } 56 | 57 | quat quat_normalize(quat q) 58 | { 59 | quat result; 60 | float norm = quat_norm(q); 61 | result.w = q.w / norm; 62 | result.x = q.x / norm; 63 | result.y = q.y / norm; 64 | result.z = q.z / norm; 65 | return result; 66 | } 67 | 68 | vec3 quat_apply(quat q, vec3 v) 69 | { 70 | quat result = quat_mult(quat_mult(q, vec3_to_quat(v)), quat_conj(q)); 71 | return vec3(result.x, result.y, result.z); 72 | } 73 | 74 | mat3 quat_to_mat3(quat q) 75 | { 76 | return mat3(1.0-2.0*(q.y*q.y + q.z*q.z), 2.0*(q.x*q.y + q.w*q.z), 2.0*(q.x*q.z - q.w*q.y), 77 | 2.0*(q.x*q.y - q.w*q.z), 1.0-2.0*(q.x*q.x + q.z*q.z), 2.0*(q.y*q.z + q.w*q.x), 78 | 2.0*(q.x*q.z + q.w*q.y), 2.0*(q.y*q.z - q.w*q.x), 1.0-2.0*(q.x*q.x + q.y*q.y)); 79 | } 80 | 81 | mat4 quat_to_mat4(quat q) 82 | { 83 | return mat4(1.0-2.0*(q.y*q.y + q.z*q.z), 2.0*(q.x*q.y + q.w*q.z), 2.0*(q.x*q.z - q.w*q.y), 0.0, 84 | 2.0*(q.x*q.y - q.w*q.z), 1.0-2.0*(q.x*q.x + q.z*q.z), 2.0*(q.y*q.z + q.w*q.x), 0.0, 85 | 2.0*(q.x*q.z + q.w*q.y), 2.0*(q.y*q.z - q.w*q.x), 1.0-2.0*(q.x*q.x + q.y*q.y), 0.0, 86 | 0.0, 0.0, 0.0, 1.0); 87 | } 88 | 89 | #endif -------------------------------------------------------------------------------- /glass_engine/glsl/include/tex_coord.glsl: -------------------------------------------------------------------------------- 1 | #ifndef _TEX_COORD_GLSL_ 2 | #define _TEX_COORD_GLSL_ 3 | 4 | #include "Material.glsl" 5 | #include "math.glsl" 6 | 7 | void transform_tex_coord(Material material, Material back_material, vec3 tex_coord, out vec3 new_tex_coord, out vec3 back_tex_coord) 8 | { 9 | new_tex_coord = tex_coord; 10 | new_tex_coord.st -= material.st_pivot; 11 | new_tex_coord.st *= material.st_scale; 12 | float st_angle_rad = material.st_rotation / 180.0 * M_PI; 13 | new_tex_coord.st = mat2( 14 | cos(st_angle_rad), sin(st_angle_rad), 15 | -sin(st_angle_rad), cos(st_angle_rad) 16 | ) * new_tex_coord.st; 17 | new_tex_coord.st += material.st_pivot; 18 | new_tex_coord.st += material.st_offset; 19 | 20 | back_tex_coord = tex_coord; 21 | back_tex_coord.st -= back_material.st_pivot; 22 | back_tex_coord.st *= back_material.st_scale; 23 | st_angle_rad = back_material.st_rotation / 180.0 * M_PI; 24 | back_tex_coord.st = mat2( 25 | cos(st_angle_rad), sin(st_angle_rad), 26 | -sin(st_angle_rad), cos(st_angle_rad) 27 | ) * back_tex_coord.st; 28 | back_tex_coord.st += back_material.st_pivot; 29 | back_tex_coord.st += back_material.st_offset; 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /glass_engine/images/glass_engine_logo256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/glass_engine/images/glass_engine_logo256.png -------------------------------------------------------------------------------- /glass_engine/images/glass_engine_logo411.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/glass_engine/images/glass_engine_logo411.png -------------------------------------------------------------------------------- /glass_engine/images/glass_engine_logo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/glass_engine/images/glass_engine_logo64.png -------------------------------------------------------------------------------- /glass_engine/images/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Time-Coder/Glass-Engine/6c415fefc770882599a014e394e87fd1b8ea3b98/glass_engine/images/start.png -------------------------------------------------------------------------------- /linux_install_python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # sudo aptitude install libreadline-dev libbz2-dev liblzma-dev libsqlite3-dev tk-dev libffi-dev libgdbm-dev uuid-dev 6 | 7 | python_versions=("3.7.17" "3.8.20" "3.9.22" "3.10.17" "3.11.12" "3.12.10" "3.13.3") 8 | for version in ${python_versions[@]}; 9 | do 10 | # wget --no-check-certificate https://npm.taobao.org/mirrors/python/$version/Python-$version.tar.xz -P ~/.pyenv/cache/ 11 | pyenv install -v $version 12 | # pyenv local $version 13 | # $(pyenv which python) -m pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple 14 | # $(pyenv which python) -m pip install -r requirements.txt --upgrade -i https://mirrors.aliyun.com/pypi/simple 15 | done; 16 | -------------------------------------------------------------------------------- /mac_install_python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # brew install xz 6 | 7 | python_versions=("3.7.9" "3.8.10" "3.9.13" "3.10.11" "3.11.7" "3.12.1") 8 | for version in ${python_versions[@]}; 9 | do 10 | # wget --no-check-certificate https://npm.taobao.org/mirrors/python/$version/Python-$version.tar.xz -P ~/.pyenv/cache/ 11 | # pyenv install $version 12 | pyenv local $version 13 | $(pyenv which python) -m pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple 14 | $(pyenv which python) -m pip install -r requirements.txt --upgrade -i https://mirrors.aliyun.com/pypi/simple 15 | done; 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PyOpenGL 2 | tree-sitter 3 | PyGLM 4 | numpy 5 | opencv-python 6 | wget 7 | requests 8 | chardet 9 | freetype-py 10 | pytweening 11 | setuptools 12 | wheel 13 | auditwheel 14 | twine 15 | pyinstaller 16 | pyflakes 17 | pycodestyle 18 | black 19 | -------------------------------------------------------------------------------- /setup_glass.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | import os 3 | 4 | def find_files(module, directory): 5 | file_list = [] 6 | for root, _, files in os.walk(directory): 7 | for file in files: 8 | file_path = os.path.join(root, file)[(len(module) + 1) :] 9 | abs_file_path = os.path.abspath(os.path.join(root, file)).replace("\\", "/") 10 | if not os.path.isfile(abs_file_path): 11 | continue 12 | 13 | if "__glcache__" not in file_path: 14 | file_list.append(file_path.replace("\\", "/")) 15 | return file_list 16 | 17 | extra_files = ["LICENSE", "pcpp/LICENSE"] 18 | extra_files += find_files("glass", "glass/glsl") 19 | extra_files += find_files("glass", "glass/CodeCompressor/tree-sitter-glsl") 20 | 21 | with open("glass/README_PYPI.md", "r", encoding='utf-8') as in_file: 22 | long_description = in_file.read() 23 | 24 | setuptools.setup( 25 | name="python_glass", 26 | version="0.1.64", 27 | author="王炳辉 (BingHui-WANG)", 28 | author_email="binghui.wang@foxmail.com", 29 | description="OpenGL wrapper for Glass-Engine", 30 | long_description=long_description, 31 | long_description_content_type="text/markdown", 32 | url="https://github.com/Time-Coder/Glass-Engine", 33 | packages=setuptools.find_packages(exclude=['*glass_engine*', '*assimpy*']), 34 | package_data={ 35 | 'glass': extra_files 36 | }, 37 | include_package_data=False, 38 | python_requires=">=3.7", 39 | install_requires=[ 40 | "PyOpenGL", 41 | "PyGLM", 42 | "numpy", 43 | "opencv-python", 44 | "wget", 45 | "requests", 46 | "chardet", 47 | "tree-sitter>=0.20.4", 48 | "tree-sitter-glsl37", 49 | "typeguard", 50 | "typing_extensions" 51 | ], 52 | classifiers=[ 53 | "Programming Language :: Python :: 3", 54 | "License :: OSI Approved :: MIT License", 55 | 'Operating System :: OS Independent', 56 | ], 57 | entry_points={'pyinstaller40': ['hook-dirs = glass.__pyinstaller:get_hook_dirs']} 58 | ) 59 | -------------------------------------------------------------------------------- /setup_glass_engine.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | import os 3 | 4 | def find_files(module, directory): 5 | file_list = [] 6 | for root, _, files in os.walk(directory): 7 | for file in files: 8 | file_path = os.path.join(root, file)[(len(module) + 1) :] 9 | abs_file_path = os.path.abspath(os.path.join(root, file)).replace("\\", "/") 10 | if not os.path.isfile(abs_file_path): 11 | continue 12 | 13 | if "__glcache__" not in file_path: 14 | file_list.append(file_path.replace("\\", "/")) 15 | return file_list 16 | 17 | with open("glass_engine/README_PYPI.md", "r", encoding='utf-8') as fh: 18 | long_description = fh.read() 19 | 20 | extra_files = ["images/glass_engine_logo64.png", "LICENSE"] 21 | extra_files += find_files("glass_engine", "glass_engine/glsl") 22 | 23 | setuptools.setup( 24 | name="glass_engine", 25 | version="0.1.64", 26 | author="王炳辉 (BingHui-WANG)", 27 | author_email="binghui.wang@foxmail.com", 28 | description="An easy-to-use 3D rendering engine for Python", 29 | long_description=long_description, 30 | long_description_content_type="text/markdown", 31 | url="https://github.com/Time-Coder/Glass-Engine", 32 | packages=setuptools.find_packages(include=['glass_engine*']), 33 | package_data={ 34 | 'glass_engine': extra_files, 35 | }, 36 | include_package_data=False, 37 | python_requires=">=3.7", 38 | install_requires=[ 39 | "python-glass==0.1.64", 40 | "assimpy>=5.4.3.3", 41 | "pytweening" 42 | ], 43 | classifiers=[ 44 | "Programming Language :: Python :: 3", 45 | "License :: OSI Approved :: MIT License", 46 | 'Operating System :: OS Independent', 47 | ], 48 | entry_points={'pyinstaller40': ['hook-dirs = glass_engine.__pyinstaller:get_hook_dirs']} 49 | ) 50 | -------------------------------------------------------------------------------- /static_check.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | 5 | def check_syntax(folder_name): 6 | subprocess.call([sys.executable, "-m", "pyflakes", folder_name]) 7 | 8 | 9 | def check_style(folder_name): 10 | subprocess.call([sys.executable, "-m", "pycodestyle", folder_name]) 11 | 12 | 13 | check_syntax("glass") 14 | check_syntax("glass_engine") 15 | 16 | # check_style("glass") 17 | # check_style("glass_engine") 18 | -------------------------------------------------------------------------------- /to-do-list.txt: -------------------------------------------------------------------------------- 1 | * Material 纹理随物体缩放 2 | * 灯的颜色不对 3 | * 不需要 geometry shader 的不使用 geometry shader 4 | * Lights 优先采用 Uniform Buffer Object,超过 32 个再使用 Shader Storage Buffer Object 5 | * uniform, uniform block, buffer 采用 tree-sitter 解析,删除原来的正则解析 6 | * uniform, uniform block, buffer 结构体绑定变量,变量属性改变透传 uniform, uniform block, buffer 结构体属性改变 7 | * 优化增量更新 8 | * 兼容 glfw, tikinter, pygame 9 | 10 | * 完善全部类型注解 -------------------------------------------------------------------------------- /upload_assimpy.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | subprocess.call([sys.executable, "-m", "twine", "upload", "dist/assimpy-*.tar.gz", "dist/assimpy-*.whl", "--verbose"]) -------------------------------------------------------------------------------- /upload_glass.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | subprocess.call([sys.executable, "-m", "twine", "upload", "dist/python_glass-*.tar.gz", "dist/python_glass-*.whl", "--verbose"]) 5 | -------------------------------------------------------------------------------- /upload_glass_engine.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | subprocess.call([sys.executable, "-m", "twine", "upload", "dist/glass_engine-*.tar.gz", "dist/glass_engine-*.whl", "--verbose"]) 5 | -------------------------------------------------------------------------------- /windows_install_python.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set python_versions=3.7.9 3.7.9-win32 3.8.10 3.8.10-win32 3.9.13 3.9.13-win32 3.10.11 3.10.11-win32 3.11.7 3.11.7-win32 3.12.1 3.12.1-win32 4 | 5 | for %%v in (%python_versions%) do ( 6 | pyenv install %%v 7 | pyenv local %%v 8 | python -m pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple 9 | @REM python -m pip install -r requirements.txt --upgrade -i https://mirrors.aliyun.com/pypi/simple 10 | ) 11 | --------------------------------------------------------------------------------