UNPKG

oxygen-core

Version:

Oxygen game engine (Xenon Core for browsers)

1,333 lines (1,175 loc) 80.3 kB
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <base data-ice="baseUrl" href="../../../"> <title data-ice="title">src/systems/RenderSystem.js | oxygen-core</title> <link type="text/css" rel="stylesheet" href="css/style.css"> <link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css"> <script src="script/prettify/prettify.js"></script> <script src="script/manual.js"></script> <meta name="description" content="Oxygen game engine (Xenon Core for browsers)"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="oxygen-core"><meta property="twitter:description" content="Oxygen game engine (Xenon Core for browsers)"></head> <body class="layout-container" data-ice="rootContainer"> <header> <a href="./">Home</a> <a href="identifiers.html">Reference</a> <a href="source.html">Source</a> <div class="search-box"> <span> <img src="./image/search.png"> <span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span> </span> <ul class="search-result"></ul> </div> <a style="position:relative; top:3px;" href="https://github.com/PsichiX/Oxygen"><img width="20px" src="./image/github.png"></a></header> <nav class="navigation" data-ice="nav"><div> <ul> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/index.js~EventsController.html">EventsController</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-lazyInitialization">lazyInitialization</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#asset-loaders">asset-loaders</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/AssemblyAsset.js~AssemblyAsset.html">AssemblyAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/AtlasAsset.js~AtlasAsset.html">AtlasAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/BinaryAsset.js~BinaryAsset.html">BinaryAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/FontAsset.js~FontAsset.html">FontAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/ImageAsset.js~ImageAsset.html">ImageAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/JSONAsset.js~JSONAsset.html">JSONAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/MusicAsset.js~MusicAsset.html">MusicAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/PackAsset.js~PackAsset.html">PackAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/ParticleSystemAsset.js~ParticleSystemAsset.html">ParticleSystemAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/PostprocessRackEffectAsset.js~PostprocessRackEffectAsset.html">PostprocessRackEffectAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/SVGAsset.js~SVGAsset.html">SVGAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/SceneAsset.js~SceneAsset.html">SceneAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/SetAsset.js~SetAsset.html">SetAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/ShaderAsset.js~ShaderAsset.html">ShaderAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/SkeletonAsset.js~SkeletonAsset.html">SkeletonAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/SoundAsset.js~SoundAsset.html">SoundAsset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asset-loaders/TextAsset.js~TextAsset.html">TextAsset</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#components">components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/AtlasSprite.js~AtlasSprite.html">AtlasSprite</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Camera.js~Camera.html">Camera</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Camera.js~PostprocessPass.html">PostprocessPass</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Camera2D.js~Camera2D.html">Camera2D</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/CameraDirector2D.js~CameraDirector2D.html">CameraDirector2D</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/CircleShape.js~CircleShape.html">CircleShape</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Container.js~Container.html">Container</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/DeferredRenderer.js~DeferredPipeline.html">DeferredPipeline</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/DeferredRenderer.js~DeferredRenderer.html">DeferredRenderer</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/GestureListener.js~GestureListener.html">GestureListener</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/InputHandler.js~InputHandler.html">InputHandler</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/MultipassRenderer.js~MultipassPipeline.html">MultipassPipeline</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/MultipassRenderer.js~MultipassRenderer.html">MultipassRenderer</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Particles.js~Particles.html">Particles</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PhysicsBody.js~PhysicsBody.html">PhysicsBody</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PhysicsWorld.js~PhysicsWorld.html">PhysicsWorld</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PolygonShape.js~PolygonShape.html">PolygonShape</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PostprocessRack.js~PostprocessRack.html">PostprocessRack</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PostprocessRack.js~PostprocessRackPass.html">PostprocessRackPass</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PostprocessRack.js~PostprocessRackRawEffectPass.html">PostprocessRackRawEffectPass</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/PrefabInstance.js~PrefabInstance.html">PrefabInstance</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/RectangleRenderer.js~RectangleRenderer.html">RectangleRenderer</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/RectangleShape.js~RectangleShape.html">RectangleShape</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Script.js~Script.html">Script</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Shape.js~Shape.html">Shape</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Skeleton.js~Skeleton.html">Skeleton</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/SortedActions.js~SortedActions.html">SortedActions</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/Sprite.js~Sprite.html">Sprite</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/TextRenderer.js~TextRenderer.html">TextRenderer</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/UiLayout.js~UiLayout.html">UiLayout</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/UiSprite.js~UiSprite.html">UiSprite</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/components/VerticesRenderer.js~VerticesRenderer.html">VerticesRenderer</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#systems">systems</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/AssemblySystem.js~AssemblySystem.html">AssemblySystem</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/AudioSystem.js~AudioSystem.html">AudioSystem</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/InputSystem.js~InputSystem.html">InputSystem</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/RenderSystem.js~Command.html">Command</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/RenderSystem.js~Pipeline.html">Pipeline</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/RenderSystem.js~RenderFullscreenCommand.html">RenderFullscreenCommand</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/RenderSystem.js~RenderSystem.html">RenderSystem</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/RenderSystem.js~RenderTargetWrapper.html">RenderTargetWrapper</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/StorageSystem.js~StorageSystem.html">StorageSystem</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/System.js~System.html">System</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#systems-assetsystem">systems/AssetSystem</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/AssetSystem/Asset.js~Asset.html">Asset</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/AssetSystem/index.js~AssetSystem.html">AssetSystem</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#systems-entitysystem">systems/EntitySystem</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/EntitySystem/Component.js~Component.html">Component</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/EntitySystem/Entity.js~Entity.html">Entity</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/systems/EntitySystem/index.js~EntitySystem.html">EntitySystem</a></span></span></li> <li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#utils">utils</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/utils/Events.js~Events.html">Events</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-angleDifference">angleDifference</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-bezierCubic">bezierCubic</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-convertGlobalPointToLocalPoint">convertGlobalPointToLocalPoint</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-convertLocalPointToGlobalPoint">convertLocalPointToGlobalPoint</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-findMapKeyOfValue">findMapKeyOfValue</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getMipmapScale">getMipmapScale</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getPOT">getPOT</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-isGlobalPointInGlobalBoundingBox">isGlobalPointInGlobalBoundingBox</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-isLocalPointInLocalBoundingBox">isLocalPointInLocalBoundingBox</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-isPOT">isPOT</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-propsEnumStringify">propsEnumStringify</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-stringToRGBA">stringToRGBA</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-waitForSeconds">waitForSeconds</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-Box2D">Box2D</a></span></span></li> </ul> </div> </nav> <div class="content" data-ice="content"><h1 data-ice="title">src/systems/RenderSystem.js</h1> <pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">import System from &apos;./System&apos;; import Events from &apos;../utils/Events&apos;; import { vec2, vec3, vec4, mat2, mat3, mat4 } from &apos;../utils/gl-matrix&apos;; import { isPOT, getPOT, getMipmapScale } from &apos;../utils&apos;; import funcParser from &apos;../utils/funcParser&apos;; let rtwUidGenerator = 0; const versions = [ // TODO: change order to provide fallback to previous versions if requested is not supported. [1, &apos;webgl&apos;], [2, &apos;webgl2&apos;], ]; const vertices = new Float32Array([ -1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1 ]); const indices = new Uint16Array([ 0, 1, 2, 2, 3, 0 ]); const extensions = { instanced_arrays: [ 1, &apos;ANGLE_instanced_arrays&apos;, null, 2, null, null ], blend_minmax: [ 1, &apos;EXT_blend_minmax&apos;, null, 2, null, null ], color_buffer_float: [ 1, &apos;WEBGL_color_buffer_float&apos;, null, 2, &apos;EXT_color_buffer_float&apos;, null ], color_buffer_half_float: [ 1, &apos;WEBGL_color_buffer_half_float&apos;, null, 2, &apos;EXT_color_buffer_half_float&apos;, null ], disjoint_timer_query: [ 1, &apos;EXT_disjoint_timer_query&apos;, null, 2, &apos;EXT_disjoint_timer_query_webgl2&apos;, null ], frag_depth: [ 1, &apos;EXT_frag_depth&apos;, null, 2, null, null ], sRGB: [ 1, &apos;EXT_sRGB&apos;, null, 2, null, null ], shader_texture_lod: [ 1, &apos;EXT_shader_texture_lod&apos;, null, 2, null, null ], texture_filter_anisotropic: [ 1, &apos;EXT_texture_filter_anisotropic&apos;, null, 2, &apos;EXT_texture_filter_anisotropic&apos;, null ], element_index_uint: [ 1, &apos;OES_element_index_uint&apos;, null, 2, null, null ], standard_derivatives: [ 1, &apos;OES_standard_derivatives&apos;, null, 2, null, null ], texture_float: [ 1, &apos;OES_texture_float&apos;, null, 2, null, null ], texture_float_linear: [ 1, &apos;OES_texture_float_linear&apos;, null, 2, &apos;OES_texture_float_linear&apos;, null ], texture_half_float: [ 1, &apos;OES_texture_half_float&apos;, null, 2, null, null ], texture_half_float_linear: [ 1, &apos;OES_texture_half_float_linear&apos;, null, 2, &apos;OES_texture_half_float_linear&apos;, null ], vertex_array_object: [ 1, &apos;OES_vertex_array_object&apos;, null, 2, null, null ], compressed_texture_astc: [ 1, &apos;WEBGL_compressed_texture_astc&apos;, null, 2, &apos;WEBGL_compressed_texture_astc&apos;, null ], compressed_texture_atc: [ 1, &apos;WEBGL_compressed_texture_atc&apos;, null, 2, &apos;WEBGL_compressed_texture_atc&apos;, null ], compressed_texture_etc: [ 1, &apos;WEBGL_compressed_texture_etc&apos;, null, 2, &apos;WEBGL_compressed_texture_etc&apos;, null ], compressed_texture_etc1: [ 1, &apos;WEBGL_compressed_texture_etc1&apos;, null, 2, &apos;WEBGL_compressed_texture_etc1&apos;, null ], compressed_texture_pvrtc: [ 1, &apos;WEBGL_compressed_texture_pvrtc&apos;, null, 2, &apos;WEBGL_compressed_texture_pvrtc&apos;, null ], compressed_texture_s3tc: [ 1, &apos;WEBGL_compressed_texture_s3tc&apos;, null, 2, &apos;WEBGL_compressed_texture_s3tc&apos;, null ], compressed_texture_s3tc_srgb: [ 1, &apos;WEBGL_compressed_texture_s3tc_srgb&apos;, null, 2, &apos;WEBGL_compressed_texture_s3tc_srgb&apos;, null ], debug_renderer_info: [ 1, &apos;WEBGL_debug_renderer_info&apos;, null, 2, &apos;WEBGL_debug_renderer_info&apos;, null ], debug_shaders: [ 1, &apos;WEBGL_debug_shaders&apos;, null, 2, &apos;WEBGL_debug_shaders&apos;, null ], depth_texture: [ 1, &apos;WEBGL_depth_texture&apos;, null, 2, null, null ], draw_buffers: [ 1, &apos;WEBGL_draw_buffers&apos;, [ &apos;drawBuffersWEBGL&apos;, &apos;drawBuffers&apos; ], 2, null, null ], lose_context: [ 1, &apos;WEBGL_lose_context&apos;, null, 2, &apos;WEBGL_lose_context&apos;, null ] }; const functions = new Map(); function getExtensionByVersion(meta, context, version) { for (var i = 0, c = meta.length; i &lt; c; i += 3) { if (meta[i] === version) { const name = meta[i + 1]; if (!name) { return context; } else { const ext = context.getExtension(name); if (!ext) { return null; } const mappings = meta[i + 2]; if (!!mappings) { for (var j = 0, n = mappings.length; j &lt; n; j += 2) { context[mappings[j + 1]] = ext[mappings[j]].bind(ext); } } return ext; } } } return null; } function makeApplierFunction(code) { code = funcParser.parse(code); return new Function(&apos;location&apos;, &apos;gl&apos;, &apos;out&apos;, &apos;getValue&apos;, &apos;mat4&apos;, code); } export class RenderTargetWrapper { get id() { return this._id; } set id(value) { if (!value) { this._id = `#RenderTargetWrapper-rt-${++rtwUidGenerator}`; this._dirty = true; return; } if (typeof value !== &apos;string&apos;) { throw new Error(&apos;`value` is not type of String!&apos;); } this._id = value; this._dirty = true; } get width() { return this._width; } set width(value) { if (typeof value !== &apos;number&apos;) { throw new Error(&apos;`value` is not type of Number!&apos;); } this._width = value; this._dirty = true; } get height() { return this._height; } set height(value) { if (typeof value !== &apos;number&apos;) { throw new Error(&apos;`value` is not type of Number!&apos;); } this._height = value; this._dirty = true; } get level() { return this._level; } set level(value) { if (typeof value !== &apos;number&apos;) { throw new Error(&apos;`value` is not type of Number!&apos;); } this._level = Math.max(0, value | 0); this._dirty = true; } get potMode() { return this._potMode; } set potMode(value) { if (!value) { this._potMode = null; return; } if (typeof value !== &apos;string&apos;) { throw new Error(&apos;`value` is not type of String!&apos;); } this._potMode = value; this._dirty = true; } get floatPointData() { return this._floatPointData; } set floatPointData(value) { if (typeof value !== &apos;boolean&apos;) { throw new Error(&apos;`value` is not type of Boolean!&apos;); } this._floatPointData = value; this._dirty = true; } get pushPopMode() { return this._pushPopMode; } set pushPopMode(value) { if (typeof value !== &apos;boolean&apos;) { throw new Error(&apos;`value` is not type of Boolean!&apos;); } this._pushPopMode = value; } get targets() { return this._targets; } set targets(value) { if (!value) { this._targets = null; return; } if (!Array.isArray(value)) { throw new Error(&apos;`value` is not type of Array!&apos;); } this._targets = value; this._dirty = true; } constructor() { this._renderer = null; this._id = `#RenderTargetWrapper-rt-${++rtwUidGenerator}`; this._idUsed = null; this._width = -1; this._height = -1; this._level = 0; this._potMode = null; this._floatPointData = false; this._pushPopMode = false; this._targets = null; this._dirty = true; } dispose() { const { _renderer, _idUsed } = this; if (!!_renderer) { if (!!_idUsed) { _renderer.unregisterRenderTarget(_idUsed); } } this._renderer = null; this._id = null; this._idUsed = null; this._potMode = null; this._targets = null; } enable(renderer) { this._ensureState(renderer); const { _idUsed } = this; if (!!_idUsed) { if (this._pushPopMode) { renderer.pushRenderTarget(_idUsed); } else { renderer.enableRenderTarget(_idUsed); } } } disable() { const { _renderer } = this; if (!!_renderer) { if (this._pushPopMode) { _renderer.popRenderTarget(); } else { _renderer.disableRenderTarget(); } } } rebuild() { this._dirty = true; } _ensureState(renderer) { if (!this._dirty) { return; } const { _id } = this; if (!_id) { throw new Error(&apos;`id` cannot be null!&apos;); } if (!!this._idUsed) { renderer.unregisterRenderTarget(this._idUsed); } const { _potMode, _level, _width, _height } = this; const width = _width &lt; 0 ? renderer.canvas.width : _width; const height = _height &lt; 0 ? renderer.canvas.height : _height; const w = !_potMode ? width : getPOT(width, _potMode === &apos;upper&apos;); const h = !_potMode ? height : getPOT(height, _potMode === &apos;upper&apos;); const s = getMipmapScale(_level); this._idUsed = this._id; if (targets === undefined || targets === null) { renderer.registerRenderTarget( this._idUsed, (w * s) | 0, (h * s) | 0, this._floatPointData ); } else { renderer.registerRenderTargetMulti( this._idUsed, (w * s) | 0, (h * s) | 0, this._targets ); } this._renderer = renderer; this._dirty = false; } } /** * Rendering command base class. */ export class Command { /** * Dispose (release all internal resources). * * @example * command.dispose(); * command = null; */ dispose() {} /** * Called when command is executed. * * @abstract * @param {WebGLRenderingContext} gl - WebGL context. * @param {RenderSystem} renderer - Render system that is used to render. * @param {number} deltaTime - Delta time. * @param {string} layer - Layer id. */ onRender(gl, renderer, deltaTime, layer) { throw new Error(&apos;Not implemented!&apos;); } /** * Called on view resize. * * @param {number} width - Width. * @param {number} height - Height. */ onResize(width, height) {} } /** * Rendering pipeline base class. * Pipeline is a set of commands to render at once. */ export class Pipeline extends Command { get commands() { return this._commands; } set commands(value) { if (!value) { this._commands = null; return; } if (!Array.isArray(value)) { throw new Error(&apos;`value` is not type of Array!&apos;); } for (const item of value) { if (!(item instanceof Command)) { throw new Error(&apos;One of `value` items is not type of Command!&apos;); } } this._commands = value; } /** * Constructor. */ constructor(commands = null) { super(); this.commands = commands; } /** * @override */ dispose() { const { _commands } = this; if (!!_commands) { for (const command of _commands) { command.dispose(); } this._commands = null; } } /** * @override */ onRender(gl, renderer, deltaTime, layer) { const { _commands } = this; if (!!_commands) { for (const command of _commands) { command.onRender(gl, renderer, deltaTime, layer); } } } /** * @override */ onResize(width, height) { const { _commands } = this; if (!!_commands) { for (const command of _commands) { command.onResize(width, height); } } } } /** * Command to render fullscreen image with given shader. */ export class RenderFullscreenCommand extends Command { /** @type {string|null} */ get shader() { return this._shader; } /** @type {string|null} */ set shader(value) { if (!value) { this._shader = null; return; } if (typeof value !== &apos;string&apos;) { throw new Error(&apos;`value` is not type of String!&apos;); } this._shader = value; } /** @type {*} */ get overrideUniforms() { return this._overrideUniforms; } /** @type {*} */ get overrideSamplers() { return this._overrideSamplers; } /** * Constructor. */ constructor() { super(); this._context = null; this._vertexBuffer = null; this._indexBuffer = null; this._shader = null; this._overrideUniforms = new Map(); this._overrideSamplers = new Map(); this._dirty = true; } /** * Destructor (dispose internal resources). * * @example * command.dispose(); * pass = null; */ dispose() { const { _context, _vertexBuffer, _indexBuffer } = this; if (!!_context) { if (!!_vertexBuffer) { _context.deleteBuffer(_vertexBuffer); } if (!!_indexBuffer) { _context.deleteBuffer(_indexBuffer); } } this._overrideUniforms.clear(); this._overrideSamplers.clear(); this._context = null; this._vertexBuffer = null; this._indexBuffer = null; this._shader = null; this._overrideUniforms = null; this._overrideSamplers = null; } /** * Called when camera need to postprocess it&apos;s rendered image. * * @param {WebGLRenderingContext} gl - WebGL context. * @param {RenderSystem} renderer - Render system that is used to render. * @param {number} deltaTime - Delta time. * @param {string|null} layer - Layer ID. */ onRender(gl, renderer, deltaTime, layer) { const { _shader, _overrideUniforms, _overrideSamplers } = this; if (!_shader) { console.warn(&apos;Trying to render PostprocessPass without shader!&apos;); return; } this._ensureState(gl, renderer); gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer); if (this._dirty) { this._dirty = false; gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); } renderer.enableShader(_shader); if (_overrideUniforms.size &gt; 0) { for (const [ name, value ] of _overrideUniforms) { renderer.overrideShaderUniform(name, value); } } if (_overrideSamplers.size &gt; 0) { for (const [ name, { texture, filtering } ] of _overrideSamplers) { if (texture !== &apos;&apos;) { renderer.overrideShaderSampler(name, texture, filtering); } } } gl.drawElements( gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0 ); renderer.disableShader(); } _ensureState(gl, renderer) { this._context = gl; if (!this._vertexBuffer) { this._vertexBuffer = gl.createBuffer(); this._dirty = true; } if (!this._indexBuffer) { this._indexBuffer = gl.createBuffer(); this._dirty = true; } } } /** * Rendering graphics onto screen canvas. * * @example * const system = new RenderSystem(&apos;screen-0&apos;); */ export default class RenderSystem extends System { /** @type {*} */ static get propsTypes() { return { useDevicePixelRatio: &apos;boolean&apos;, timeScale: &apos;number&apos;, collectStats: &apos;boolean&apos; }; } /** @type {number} */ get contextVersion() { return this._contextVersion; } /** @type {boolean} */ get useDevicePixelRatio() { return this._useDevicePixelRatio; } /** @type {boolean} */ set useDevicePixelRatio(value) { this._useDevicePixelRatio = !!value; } /** @type {number} */ get timeScale() { return this._timeScale; } /** @type {number} */ set timeScale(value) { if (typeof value !== &apos;number&apos;) { throw new Error(&apos;`value` is not type of Number!&apos;); } this._timeScale = value; } /** @type {boolean} */ get collectStats() { return this._collectStats; } /** @type {boolean} */ set collectStats(value) { if (typeof value !== &apos;boolean&apos;) { throw new Error(&apos;`value` is not type of Boolean!&apos;); } this._collectStats = value; } /** @type {number} */ get passedTime() { return this._passedTime; } /** @type {HTMLCanvasElement} */ get canvas() { return this._canvas; } /** @type {Events} */ get events() { return this._events; } /** @type {string} */ get activeShader() { return this._activeShader; } /** @type {string} */ get activeRenderTarget() { return this._activeRenderTarget; } /** @type {string} */ get clearColor() { return this._clearColor; } /** @type {mat4} */ get projectionMatrix() { return this._projectionMatrix; } /** @type {mat4} */ get viewMatrix() { return this._viewMatrix; } /** @type {mat4} */ get modelMatrix() { return this._modelMatrix; } /** @type {Map} */ get stats() { return this._stats; } /** @type {string} */ get statsText() { if (!this._collectStats) { return &apos;&apos;; } const { _stats } = this; const deltaTime = _stats.get(&apos;delta-time&apos;); const passedTime = _stats.get(&apos;passed-time&apos;); const fps = `FPS: ${(1000 / deltaTime) | 0} (${1000 / deltaTime})`; const dt = `Delta time: ${deltaTime | 0} ms (${deltaTime})`; const pt = `Passed time: ${passedTime | 0} ms (${passedTime})`; const sc = `Shader changes: ${_stats.get(&apos;shader-changes&apos;)}`; const f = `Frames: ${_stats.get(&apos;frames&apos;)}`; const s = `Shaders: ${_stats.get(&apos;shaders&apos;)}`; const t = `Textures: ${_stats.get(&apos;textures&apos;)}`; const rt = `Render targets: ${_stats.get(&apos;renderTargets&apos;)}`; const e = `Extensions:${_stats.get(&apos;extensions&apos;).map(e =&gt; `\n - ${e}`).join()}`; return `${fps}\n${dt}\n${pt}\n${sc}\n${f}\n${s}\n${t}\n${rt}\n${e}`; } /** * Constructor. * Automaticaly binds into specified canvas. * * @param {string} canvas - HTML canvas element id. * @param {boolean} optimize - Optimize rendering pipeline. * @param {Array.&lt;string&gt;} extensions - array with WebGL extensions list. * @param {number} contextVersion - WebGL context version number. * @param {boolean} manualMode - Manually trigger rendering next frames. */ constructor(canvas, optimize = true, extensions = null, contextVersion = 1, manualMode = false) { super(); this._manualMode = !!manualMode; this._extensions = new Map(); this._contextVersion = contextVersion | 0; this._useDevicePixelRatio = false; this._timeScale = 1; this._collectStats = false; this._animationFrame = 0; this._lastTimestamp = null; this._canvas = null; this._context = null; this._shaders = new Map(); this._textures = new Map(); this._renderTargets = new Map(); this._renderTargetsStack = []; this._events = new Events(); this._activeShader = null; this._activeRenderTarget = null; this._activeViewportSize = vec2.create(); this._clearColor = vec4.create(); this._projectionMatrix = mat4.create(); this._viewMatrix = mat4.create(); this._modelMatrix = mat4.create(); this._blendingConstants = {}; this._stats = new Map(); this._counterShaderChanges = 0; this._counterFrames = 0; this._optimize = !!optimize; this._passedTime = 0; this._shaderApplierOut = mat4.create(); this._shaderApplierGetValue = name =&gt; { if (name === &apos;model-matrix&apos;) { return this._modelMatrix; } else if (name === &apos;view-matrix&apos;) { return this._viewMatrix; } else if (name === &apos;projection-matrix&apos;) { return this._projectionMatrix; } else { throw new Error(`Unknown matrix: ${name}`); } }; this.__onFrame = this._onFrame.bind(this); if (!!extensions) { for (const name of extensions) { this._extensions.set(name, null); } } this._setup(canvas); } /** * Destructor (disposes internal resources). * * @example * system.dispose(); * sustem = null; */ dispose() { const { _context, _shaders, _textures, _renderTargets, _events } = this; this._stopAnimation(); _context.clear(_context.COLOR_BUFFER_BIT); for (const shader of _shaders.keys()) { this.unregisterShader(shader); } for (const texture of _textures.keys()) { this.unregisterTexture(texture); } for (const renderTarget of _renderTargets.keys()) { this.unregisterRenderTarget(renderTarget); } _events.dispose(); this._extensions = null; this._lastTimestamp = null; this._canvas = null; this._context = null; this._shaders = null; this._textures = null; this._renderTargets = null; this._renderTargetsStack = null; this._events = null; this._activeShader = null; this._activeRenderTarget = null; this._activeViewportSize = null; this._clearColor = null; this._projectionMatrix = null; this._viewMatrix = null; this._modelMatrix = null; this._blendingConstants = null; this._stats = null; this._shaderApplierOut = null; this._shaderApplierGetValue = null; this.__onFrame = null; } /** * Get loaded WebGL extension by it&apos;s name. * * @param {string} name - Extension name. * * @return {*|null} WebGL extension or null if not found. * * @example * const extension = system.extension(&apos;vertex_array_object&apos;); * if (!!extension) { * const vao = extension.createVertexArrayOES(); * extension.bindVertexArrayOES(vao); * } */ extension(name) { return this._extensions.get(name) || null; } /** * Load WebGL extension by it&apos;s name. * * @param {string} name - Extension name. * * @return {*|null} WebGL extension or null if not supported. * * @example * const extension = system.requestExtension(&apos;vertex_array_object&apos;); * if (!!extension) { * const vao = extension.createVertexArrayOES(); * extension.bindVertexArrayOES(vao); * } */ requestExtension(name) { const { _context, _contextVersion, _extensions } = this; if (!_context) { throw new Error(&apos;WebGL context is not yet ready!&apos;); } let ext = _extensions.get(name); if (!!ext) { return ext; } const meta = extensions[name]; if (!meta) { throw new Error(`Unsupported extension: ${name}`); } ext = getExtensionByVersion(meta, _context, _contextVersion); if (!!ext) { _extensions.set(name, ext); } else { console.warn(`Could not get WebGL extension: ${name}`); } return ext || null; } /** * Load WebGL extensions by their names. * * @param {string[]} args - Extension names. * * @return {boolean} True if all are supported and loaded, false otherwise. * * @example * const supported = system.requestExtensions(&apos;texture_float&apos;, &apos;texture_float_linear&apos;); * if (!supported) { * throw new Error(&apos;One of requested WebGL extensions is not supported!&apos;); * } */ requestExtensions(...args) { for (const arg of args) { if (!this.requestExtension(arg)) { return false; } } return true; } /** * Execute rendering command. * * @param {Command} command - command to execute. * @param {number} deltaTime - Delta time. * @param {string|null} layer - Layer ID. */ executeCommand(command, deltaTime, layer) { if (!(command instanceof Command)) { throw new Error(&apos;`command` is not type of Command!&apos;); } if (typeof deltaTime !== &apos;number&apos;) { throw new Error(&apos;`deltaTime` is not type of Number!&apos;); } command.onRender(this._context, this, deltaTime, layer); } /** * Register new shader. * * @param {string} id - Shader id. * @param {string} vertex - Vertex shader code. * @param {string} fragment - Fragment shader code. * @param {*} layoutInfo - Vertex layout description. * @param {*} uniformsInfo - Uniforms description. * @param {*} samplersInfo - Samplers description. * @param {*} blendingInfo - Blending mode description. * @param {string[]|null} extensionsInfo - Required extensions list. * * @example * system.registerShader( * &apos;red&apos;, * &apos;attribute vec2 aPosition;\nvoid main() { gl_Position = vec4(aPosition, 0.0, 1.0); }&apos;, * &apos;void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }&apos;, * { aPosition: { size: 2, stride: 2, offset: 0 } }, * {}, * { source: &apos;src-alpha&apos;, destination: &apos;one-minus-src-alpha&apos; } * ); */ registerShader( id, vertex, fragment, layoutInfo, uniformsInfo, samplersInfo, blendingInfo, extensionsInfo ) { if (typeof id !== &apos;string&apos;) { throw new Error(&apos;`id` is not type of String!&apos;); } if (typeof vertex !== &apos;string&apos;) { throw new Error(&apos;`vertex` is not type of String!&apos;); } if (typeof fragment !== &apos;string&apos;) { throw new Error(&apos;`fragment` is not type of String!&apos;); } if (!layoutInfo) { throw new Error(&apos;`layoutInfo` cannot be null!&apos;); } this.unregisterShader(id); if (Array.isArray(extensionsInfo) &amp;&amp; extensionsInfo.length &gt; 0) { if (!this.requestExtensions(...extensionsInfo)) { throw new Error(`One of shader extensions is not supported (${id})!`); } } const gl = this._context; const shader = gl.createProgram(); const vshader = gl.createShader(gl.VERTEX_SHADER); const fshader = gl.createShader(gl.FRAGMENT_SHADER); const deleteAll = () =&gt; { gl.deleteShader(vshader); gl.deleteShader(fshader); gl.deleteProgram(shader); }; // TODO: fix problem with forced GLSL 3 in WebGL 2. // const { _contextVersion } = this; // if (_contextVersion &gt; 1) { // vertex = `#version 300 es\n#define OXY_ctx_ver ${_contextVersion}\n${vertex}`; // fragment = `#version 300 es\n#define OXY_ctx_ver ${_contextVersion}\n${fragment}`; // } else { // vertex = `#define OXY_ctx_ver ${_contextVersion}\n${vertex}`; // fragment = `#define OXY_ctx_ver ${_contextVersion}\n${fragment}`; // } gl.shaderSource(vshader, vertex); gl.shaderSource(fshader, fragment); gl.compileShader(vshader); gl.compileShader(fshader); if (!gl.getShaderParameter(vshader, gl.COMPILE_STATUS)) { const log = gl.getShaderInfoLog(vshader); deleteAll(); throw new Error(`Cannot compile vertex shader: ${id}\nLog: ${log}`); } if (!gl.getShaderParameter(fshader, gl.COMPILE_STATUS)) { const log = gl.getShaderInfoLog(fshader); deleteAll(); throw new Error(`Cannot compile fragment shader: ${id}\nLog: ${log}`); } gl.attachShader(shader, vshader); gl.attachShader(shader, fshader); gl.linkProgram(shader); if (!gl.getProgramParameter(shader, gl.LINK_STATUS)) { const log = gl.getProgramInfoLog(shader); deleteAll(); throw new Error(`Cannot link shader program: ${id}\nLog: ${log}`); } const layout = new Map(); const uniforms = new Map(); const samplers = new Map(); let blending = null; for (const name in layoutInfo) { const { size, stride, offset } = layoutInfo[name]; if (typeof size !== &apos;number&apos; || typeof stride !== &apos;number&apos; || typeof offset !== &apos;number&apos; ) { deleteAll(); throw new Error( `Shader layout does not have proper settings: ${id} (${name})` ); } const location = gl.getAttribLocation(shader, name); if (location &lt; 0) { deleteAll(); throw new Error( `Shader does not have attribute: ${id} (${name})` ); } layout.set(name, { location, size, stride, offset }); } if (layout.size === 0) { deleteAll(); throw new Error(`Shader layout cannot be empty: ${id}`); } if (!!uniformsInfo) { for (const name in uniformsInfo) { const mapping = uniformsInfo[name]; if (typeof mapping !== &apos;string&apos; &amp;&amp; typeof mapping !== &apos;number&apos; &amp;&amp; !(mapping instanceof Array) ) { deleteAll(); throw new Error( `Shader uniform does not have proper settings: ${id} (${name})` ); } let func = null; if (typeof mapping === &apos;string&apos; &amp;&amp; mapping.startsWith(&apos;@&apos;)) { func = functions[mapping]; if (!func) { func = functions[mapping] = makeApplierFunction(mapping); } } const location = gl.getUniformLocation(shader, name); if (!location) { deleteAll(); throw new Error( `Shader does not have uniform: ${id} (${name})` ); } const forcedUpdate = !!func || mapping === &apos;projection-matrix&apos; || mapping === &apos;view-matrix&apos; || mapping === &apos;model-matrix&apos; || mapping === &apos;time&apos; || mapping === &apos;viewport-size&apos; || mapping === &apos;inverse-viewport-size&apos;; uniforms.set(name, { location, mapping: !func ? mapping : func, forcedUpdate }); } } if (!!samplersInfo) { for (const name in samplersInfo) { const { channel, texture, filtering } = samplersInfo[name]; if (typeof channel !== &apos;number&apos; || (!!texture &amp;&amp; typeof texture !== &apos;string&apos;) || (!!filtering &amp;&amp; typeof filtering !== &apos;string&apos;) ) { deleteAll(); throw new Error( `Shader sampler does not have proper settings: ${id} (${name})` ); } const location = gl.getUniformLocation(shader, name); if (!location) { deleteAll(); throw new Error( `Shader does not have sampler: ${id} (${name})` ); } samplers.set(name, { location, channel, texture, filtering }); } } if (!!blendingInfo) { const { source, destinat