├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── bili.config.js ├── docs ├── 1-white-clouds-png-image_400x400.2471b47f.png ├── 3d.2d1ce79b.css ├── 3d.b302f3ed.js ├── api │ ├── .nojekyll │ ├── assets │ │ ├── highlight.css │ │ ├── icons.css │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── main.js │ │ ├── search.js │ │ ├── style.css │ │ ├── widgets.png │ │ └── widgets@2x.png │ ├── classes │ │ ├── Bloom.html │ │ ├── Blur.html │ │ ├── Godray.html │ │ ├── GodrayLight.html │ │ ├── KglAuto.html │ │ ├── KglEffect.html │ │ ├── ObjectGl.html │ │ ├── Program.html │ │ ├── Specular.html │ │ ├── Vec2.html │ │ ├── Vec3.html │ │ ├── Vec4.html │ │ ├── Zoomblur.html │ │ └── default.html │ ├── index.html │ ├── interfaces │ │ ├── _internal_.ANGLE_instanced_arrays.html │ │ ├── _internal_.ARIAMixin.html │ │ ├── _internal_.AbstractRange.html │ │ ├── _internal_.AddEventListenerOptions.html │ │ ├── _internal_.Animatable.html │ │ ├── _internal_.Animation.html │ │ ├── _internal_.AnimationEffect.html │ │ ├── _internal_.AnimationEvent.html │ │ ├── _internal_.AnimationEventMap.html │ │ ├── _internal_.AnimationFrameProvider.html │ │ ├── _internal_.AnimationPlaybackEvent.html │ │ ├── _internal_.AnimationTimeline.html │ │ ├── _internal_.ArrayBufferView.html │ │ ├── _internal_.ArrayLike.html │ │ ├── _internal_.AssignedNodesOptions.html │ │ ├── _internal_.AsyncIterableIterator.html │ │ ├── _internal_.AsyncIterator.html │ │ ├── _internal_.Attr.html │ │ ├── _internal_.AudioBuffer.html │ │ ├── _internal_.AudioProcessingEvent.html │ │ ├── _internal_.BarProp.html │ │ ├── _internal_.BeforeUnloadEvent.html │ │ ├── _internal_.BlobCallback.html │ │ ├── _internal_.BlobEvent.html │ │ ├── _internal_.Body.html │ │ ├── _internal_.Buffer.html │ │ ├── _internal_.BufferConstructor.html │ │ ├── _internal_.CDATASection.html │ │ ├── _internal_.CSSRule.html │ │ ├── _internal_.CSSStyleSheet.html │ │ ├── _internal_.CacheQueryOptions.html │ │ ├── _internal_.CacheStorage.html │ │ ├── _internal_.CanvasCompositing.html │ │ ├── _internal_.CanvasDrawImage.html │ │ ├── _internal_.CanvasDrawPath.html │ │ ├── _internal_.CanvasFillStrokeStyles.html │ │ ├── _internal_.CanvasFilters.html │ │ ├── _internal_.CanvasGradient.html │ │ ├── _internal_.CanvasImageData.html │ │ ├── _internal_.CanvasImageSmoothing.html │ │ ├── _internal_.CanvasPath.html │ │ ├── _internal_.CanvasPattern.html │ │ ├── _internal_.CanvasRect.html │ │ ├── _internal_.CanvasRenderingContext2D.html │ │ ├── _internal_.CanvasRenderingContext2DSettings.html │ │ ├── _internal_.CanvasShadowStyles.html │ │ ├── _internal_.CanvasState.html │ │ ├── _internal_.CanvasText.html │ │ ├── _internal_.CanvasTextDrawingStyles.html │ │ ├── _internal_.CanvasTransform.html │ │ ├── _internal_.CanvasUserInterface.html │ │ ├── _internal_.CharacterData.html │ │ ├── _internal_.ChildNode.html │ │ ├── _internal_.ClipboardEvent.html │ │ ├── _internal_.CloseEvent.html │ │ ├── _internal_.Comment.html │ │ ├── _internal_.CompositionEvent.html │ │ ├── _internal_.ComputedEffectTiming.html │ │ ├── _internal_.ConcatArray.html │ │ ├── _internal_.ConstrainBooleanParameters.html │ │ ├── _internal_.ConstrainDOMStringParameters.html │ │ ├── _internal_.ConstrainDoubleRange.html │ │ ├── _internal_.ConstrainULongRange.html │ │ ├── _internal_.Crypto.html │ │ ├── _internal_.CustomElementConstructor.html │ │ ├── _internal_.CustomElementRegistry.html │ │ ├── _internal_.CustomEvent.html │ │ ├── _internal_.DOMException.html │ │ ├── _internal_.DOMImplementation.html │ │ ├── _internal_.DOMMatrix.html │ │ ├── _internal_.DOMMatrix2DInit.html │ │ ├── _internal_.DOMMatrixInit.html │ │ ├── _internal_.DOMMatrixReadOnly.html │ │ ├── _internal_.DOMPoint.html │ │ ├── _internal_.DOMPointInit.html │ │ ├── _internal_.DOMPointReadOnly.html │ │ ├── _internal_.DOMRect.html │ │ ├── _internal_.DOMRectInit.html │ │ ├── _internal_.DOMRectReadOnly.html │ │ ├── _internal_.DOMStringMap.html │ │ ├── _internal_.DataTransfer.html │ │ ├── _internal_.DeviceMotionEvent.html │ │ ├── _internal_.DeviceMotionEventAcceleration.html │ │ ├── _internal_.DeviceMotionEventRotationRate.html │ │ ├── _internal_.DeviceOrientationEvent.html │ │ ├── _internal_.Document.html │ │ ├── _internal_.DocumentAndElementEventHandlers.html │ │ ├── _internal_.DocumentAndElementEventHandlersEventMap.html │ │ ├── _internal_.DocumentEventMap.html │ │ ├── _internal_.DocumentFragment.html │ │ ├── _internal_.DocumentOrShadowRoot.html │ │ ├── _internal_.DocumentTimeline.html │ │ ├── _internal_.DocumentType.html │ │ ├── _internal_.DoubleRange.html │ │ ├── _internal_.DragEvent.html │ │ ├── _internal_.EXT_blend_minmax.html │ │ ├── _internal_.EXT_color_buffer_float.html │ │ ├── _internal_.EXT_color_buffer_half_float.html │ │ ├── _internal_.EXT_float_blend.html │ │ ├── _internal_.EXT_frag_depth.html │ │ ├── _internal_.EXT_sRGB.html │ │ ├── _internal_.EXT_shader_texture_lod.html │ │ ├── _internal_.EXT_texture_filter_anisotropic.html │ │ ├── _internal_.EffectTiming.html │ │ ├── _internal_.Element.html │ │ ├── _internal_.ElementCSSInlineStyle.html │ │ ├── _internal_.ElementContentEditable.html │ │ ├── _internal_.ElementCreationOptions.html │ │ ├── _internal_.ElementDefinitionOptions.html │ │ ├── _internal_.ElementEventMap.html │ │ ├── _internal_.ElementInternals.html │ │ ├── _internal_.Error.html │ │ ├── _internal_.ErrorCallback.html │ │ ├── _internal_.ErrorEvent.html │ │ ├── _internal_.Event.html │ │ ├── _internal_.EventEmitter.html │ │ ├── _internal_.EventListener.html │ │ ├── _internal_.EventListenerObject.html │ │ ├── _internal_.EventListenerOptions.html │ │ ├── _internal_.EventTarget.html │ │ ├── _internal_.External.html │ │ ├── _internal_.File.html │ │ ├── _internal_.FileSystem.html │ │ ├── _internal_.FileSystemDirectoryEntry.html │ │ ├── _internal_.FileSystemDirectoryReader.html │ │ ├── _internal_.FileSystemEntriesCallback.html │ │ ├── _internal_.FileSystemEntry.html │ │ ├── _internal_.FileSystemEntryCallback.html │ │ ├── _internal_.FileSystemFlags.html │ │ ├── _internal_.FocusEvent.html │ │ ├── _internal_.FocusOptions.html │ │ ├── _internal_.FontFace.html │ │ ├── _internal_.FontFaceSetLoadEvent.html │ │ ├── _internal_.FontFaceSource.html │ │ ├── _internal_.FormDataEvent.html │ │ ├── _internal_.FrameRequestCallback.html │ │ ├── _internal_.FullscreenOptions.html │ │ ├── _internal_.Gamepad.html │ │ ├── _internal_.GamepadButton.html │ │ ├── _internal_.GamepadEvent.html │ │ ├── _internal_.GamepadHapticActuator.html │ │ ├── _internal_.GetAnimationsOptions.html │ │ ├── _internal_.GetRootNodeOptions.html │ │ ├── _internal_.GlobalEventHandlers.html │ │ ├── _internal_.GlobalEventHandlersEventMap.html │ │ ├── _internal_.HTMLAnchorElement.html │ │ ├── _internal_.HTMLAreaElement.html │ │ ├── _internal_.HTMLAudioElement.html │ │ ├── _internal_.HTMLBRElement.html │ │ ├── _internal_.HTMLBaseElement.html │ │ ├── _internal_.HTMLBodyElement.html │ │ ├── _internal_.HTMLBodyElementEventMap.html │ │ ├── _internal_.HTMLButtonElement.html │ │ ├── _internal_.HTMLCanvasElement.html │ │ ├── _internal_.HTMLCollection.html │ │ ├── _internal_.HTMLDListElement.html │ │ ├── _internal_.HTMLDataElement.html │ │ ├── _internal_.HTMLDataListElement.html │ │ ├── _internal_.HTMLDetailsElement.html │ │ ├── _internal_.HTMLDialogElement.html │ │ ├── _internal_.HTMLDirectoryElement.html │ │ ├── _internal_.HTMLDivElement.html │ │ ├── _internal_.HTMLElement.html │ │ ├── _internal_.HTMLElementDeprecatedTagNameMap.html │ │ ├── _internal_.HTMLElementEventMap.html │ │ ├── _internal_.HTMLElementTagNameMap.html │ │ ├── _internal_.HTMLEmbedElement.html │ │ ├── _internal_.HTMLFieldSetElement.html │ │ ├── _internal_.HTMLFontElement.html │ │ ├── _internal_.HTMLFrameElement.html │ │ ├── _internal_.HTMLFrameSetElement.html │ │ ├── _internal_.HTMLFrameSetElementEventMap.html │ │ ├── _internal_.HTMLHRElement.html │ │ ├── _internal_.HTMLHeadElement.html │ │ ├── _internal_.HTMLHeadingElement.html │ │ ├── _internal_.HTMLHtmlElement.html │ │ ├── _internal_.HTMLHyperlinkElementUtils.html │ │ ├── _internal_.HTMLIFrameElement.html │ │ ├── _internal_.HTMLImageElement.html │ │ ├── _internal_.HTMLInputElement.html │ │ ├── _internal_.HTMLLIElement.html │ │ ├── _internal_.HTMLLabelElement.html │ │ ├── _internal_.HTMLLegendElement.html │ │ ├── _internal_.HTMLLinkElement.html │ │ ├── _internal_.HTMLMapElement.html │ │ ├── _internal_.HTMLMarqueeElement.html │ │ ├── _internal_.HTMLMediaElement.html │ │ ├── _internal_.HTMLMediaElementEventMap.html │ │ ├── _internal_.HTMLMenuElement.html │ │ ├── _internal_.HTMLMetaElement.html │ │ ├── _internal_.HTMLMeterElement.html │ │ ├── _internal_.HTMLModElement.html │ │ ├── _internal_.HTMLOListElement.html │ │ ├── _internal_.HTMLObjectElement.html │ │ ├── _internal_.HTMLOptGroupElement.html │ │ ├── _internal_.HTMLOptionElement.html │ │ ├── _internal_.HTMLOrSVGElement.html │ │ ├── _internal_.HTMLOutputElement.html │ │ ├── _internal_.HTMLParagraphElement.html │ │ ├── _internal_.HTMLParamElement.html │ │ ├── _internal_.HTMLPictureElement.html │ │ ├── _internal_.HTMLPreElement.html │ │ ├── _internal_.HTMLProgressElement.html │ │ ├── _internal_.HTMLQuoteElement.html │ │ ├── _internal_.HTMLScriptElement.html │ │ ├── _internal_.HTMLSlotElement.html │ │ ├── _internal_.HTMLSourceElement.html │ │ ├── _internal_.HTMLSpanElement.html │ │ ├── _internal_.HTMLStyleElement.html │ │ ├── _internal_.HTMLTableCaptionElement.html │ │ ├── _internal_.HTMLTableCellElement.html │ │ ├── _internal_.HTMLTableColElement.html │ │ ├── _internal_.HTMLTableElement.html │ │ ├── _internal_.HTMLTableRowElement.html │ │ ├── _internal_.HTMLTableSectionElement.html │ │ ├── _internal_.HTMLTemplateElement.html │ │ ├── _internal_.HTMLTextAreaElement.html │ │ ├── _internal_.HTMLTimeElement.html │ │ ├── _internal_.HTMLTitleElement.html │ │ ├── _internal_.HTMLTrackElement.html │ │ ├── _internal_.HTMLUListElement.html │ │ ├── _internal_.HTMLVideoElement.html │ │ ├── _internal_.HTMLVideoElementEventMap.html │ │ ├── _internal_.HashChangeEvent.html │ │ ├── _internal_.History.html │ │ ├── _internal_.IDBCursor.html │ │ ├── _internal_.IDBCursorWithValue.html │ │ ├── _internal_.IDBDatabaseInfo.html │ │ ├── _internal_.IDBFactory.html │ │ ├── _internal_.IDBIndex.html │ │ ├── _internal_.IDBKeyRange.html │ │ ├── _internal_.IDBOpenDBRequest.html │ │ ├── _internal_.IDBOpenDBRequestEventMap.html │ │ ├── _internal_.IDBRequest.html │ │ ├── _internal_.IDBRequestEventMap.html │ │ ├── _internal_.IDBTransaction.html │ │ ├── _internal_.IDBTransactionEventMap.html │ │ ├── _internal_.IDBVersionChangeEvent.html │ │ ├── _internal_.IdleDeadline.html │ │ ├── _internal_.IdleRequestCallback.html │ │ ├── _internal_.IdleRequestOptions.html │ │ ├── _internal_.ImageBitmap.html │ │ ├── _internal_.ImageBitmapOptions.html │ │ ├── _internal_.ImageBitmapRenderingContext.html │ │ ├── _internal_.ImageBitmapRenderingContextSettings.html │ │ ├── _internal_.ImageData.html │ │ ├── _internal_.ImageDataSettings.html │ │ ├── _internal_.InnerHTML.html │ │ ├── _internal_.InputEvent.html │ │ ├── _internal_.Iterable.html │ │ ├── _internal_.IterableIterator.html │ │ ├── _internal_.Iterator.html │ │ ├── _internal_.IteratorReturnResult.html │ │ ├── _internal_.IteratorYieldResult.html │ │ ├── _internal_.KHR_parallel_shader_compile.html │ │ ├── _internal_.KeyboardEvent.html │ │ ├── _internal_.Keyframe.html │ │ ├── _internal_.KeyframeAnimationOptions.html │ │ ├── _internal_.KeyframeEffectOptions.html │ │ ├── _internal_.LinkStyle.html │ │ ├── _internal_.Location.html │ │ ├── _internal_.MIDIConnectionEvent.html │ │ ├── _internal_.MIDIMessageEvent.html │ │ ├── _internal_.MIDIPort.html │ │ ├── _internal_.MIDIPortEventMap.html │ │ ├── _internal_.MediaEncryptedEvent.html │ │ ├── _internal_.MediaError.html │ │ ├── _internal_.MediaKeyMessageEvent.html │ │ ├── _internal_.MediaKeySession.html │ │ ├── _internal_.MediaKeySessionEventMap.html │ │ ├── _internal_.MediaKeys.html │ │ ├── _internal_.MediaQueryList.html │ │ ├── _internal_.MediaQueryListEvent.html │ │ ├── _internal_.MediaQueryListEventMap.html │ │ ├── _internal_.MediaRecorderErrorEvent.html │ │ ├── _internal_.MediaSource.html │ │ ├── _internal_.MediaSourceEventMap.html │ │ ├── _internal_.MediaStream.html │ │ ├── _internal_.MediaStreamEventMap.html │ │ ├── _internal_.MediaStreamTrack.html │ │ ├── _internal_.MediaStreamTrackEvent.html │ │ ├── _internal_.MediaStreamTrackEventMap.html │ │ ├── _internal_.MediaTrackCapabilities.html │ │ ├── _internal_.MediaTrackConstraintSet.html │ │ ├── _internal_.MediaTrackConstraints.html │ │ ├── _internal_.MediaTrackSettings.html │ │ ├── _internal_.MessagePort.html │ │ ├── _internal_.MessagePortEventMap.html │ │ ├── _internal_.MouseEvent.html │ │ ├── _internal_.MultiCacheQueryOptions.html │ │ ├── _internal_.MutationEvent.html │ │ ├── _internal_.Node.html │ │ ├── _internal_.NodeIterator.html │ │ ├── _internal_.NonDocumentTypeChildNode.html │ │ ├── _internal_.NonElementParentNode.html │ │ ├── _internal_.OES_element_index_uint.html │ │ ├── _internal_.OES_standard_derivatives.html │ │ ├── _internal_.OES_texture_float.html │ │ ├── _internal_.OES_texture_float_linear.html │ │ ├── _internal_.OES_texture_half_float.html │ │ ├── _internal_.OES_texture_half_float_linear.html │ │ ├── _internal_.OES_vertex_array_object.html │ │ ├── _internal_.OVR_multiview2.html │ │ ├── _internal_.OfflineAudioCompletionEvent.html │ │ ├── _internal_.OnErrorEventHandlerNonNull.html │ │ ├── _internal_.OptionalEffectTiming.html │ │ ├── _internal_.PageTransitionEvent.html │ │ ├── _internal_.ParentNode.html │ │ ├── _internal_.Path2D.html │ │ ├── _internal_.PaymentCurrencyAmount.html │ │ ├── _internal_.PaymentDetailsBase.html │ │ ├── _internal_.PaymentDetailsModifier.html │ │ ├── _internal_.PaymentDetailsUpdate.html │ │ ├── _internal_.PaymentItem.html │ │ ├── _internal_.PaymentMethodChangeEvent.html │ │ ├── _internal_.PaymentRequestUpdateEvent.html │ │ ├── _internal_.Performance.html │ │ ├── _internal_.PerformanceEntry.html │ │ ├── _internal_.PerformanceEventMap.html │ │ ├── _internal_.PerformanceMark.html │ │ ├── _internal_.PerformanceMarkOptions.html │ │ ├── _internal_.PerformanceMeasure.html │ │ ├── _internal_.PerformanceMeasureOptions.html │ │ ├── _internal_.PerformanceNavigation.html │ │ ├── _internal_.PerformanceTiming.html │ │ ├── _internal_.PictureInPictureWindow.html │ │ ├── _internal_.PictureInPictureWindowEventMap.html │ │ ├── _internal_.PointerEvent.html │ │ ├── _internal_.PopStateEvent.html │ │ ├── _internal_.ProcessingInstruction.html │ │ ├── _internal_.ProgressEvent.html │ │ ├── _internal_.PromiseLike.html │ │ ├── _internal_.PromiseRejectionEvent.html │ │ ├── _internal_.PropertyIndexedKeyframes.html │ │ ├── _internal_.RTCDTMFToneChangeEvent.html │ │ ├── _internal_.RTCDataChannel.html │ │ ├── _internal_.RTCDataChannelEvent.html │ │ ├── _internal_.RTCDataChannelEventMap.html │ │ ├── _internal_.RTCDtlsTransport.html │ │ ├── _internal_.RTCDtlsTransportEventMap.html │ │ ├── _internal_.RTCError.html │ │ ├── _internal_.RTCErrorEvent.html │ │ ├── _internal_.RTCIceCandidate.html │ │ ├── _internal_.RTCIceCandidateInit.html │ │ ├── _internal_.RTCIceTransport.html │ │ ├── _internal_.RTCIceTransportEventMap.html │ │ ├── _internal_.RTCPeerConnectionIceErrorEvent.html │ │ ├── _internal_.RTCPeerConnectionIceEvent.html │ │ ├── _internal_.RTCRtcpParameters.html │ │ ├── _internal_.RTCRtpCapabilities.html │ │ ├── _internal_.RTCRtpCodecCapability.html │ │ ├── _internal_.RTCRtpCodecParameters.html │ │ ├── _internal_.RTCRtpContributingSource.html │ │ ├── _internal_.RTCRtpHeaderExtensionCapability.html │ │ ├── _internal_.RTCRtpHeaderExtensionParameters.html │ │ ├── _internal_.RTCRtpParameters.html │ │ ├── _internal_.RTCRtpReceiveParameters.html │ │ ├── _internal_.RTCRtpReceiver.html │ │ ├── _internal_.RTCRtpSynchronizationSource.html │ │ ├── _internal_.RTCTrackEvent.html │ │ ├── _internal_.Range.html │ │ ├── _internal_.ReadableStream-1.html │ │ ├── _internal_.ReadableStream.html │ │ ├── _internal_.ReadableStreamDefaultReadDoneResult.html │ │ ├── _internal_.ReadableStreamDefaultReadValueResult.html │ │ ├── _internal_.ReadableStreamDefaultReader.html │ │ ├── _internal_.ReadableStreamGenericReader.html │ │ ├── _internal_.ReadableWritablePair.html │ │ ├── _internal_.RemotePlayback.html │ │ ├── _internal_.RemotePlaybackAvailabilityCallback.html │ │ ├── _internal_.RemotePlaybackEventMap.html │ │ ├── _internal_.Request.html │ │ ├── _internal_.RequestInit.html │ │ ├── _internal_.Response.html │ │ ├── _internal_.SVGAElement.html │ │ ├── _internal_.SVGAngle.html │ │ ├── _internal_.SVGAnimateElement.html │ │ ├── _internal_.SVGAnimateMotionElement.html │ │ ├── _internal_.SVGAnimateTransformElement.html │ │ ├── _internal_.SVGAnimatedAngle.html │ │ ├── _internal_.SVGAnimatedBoolean.html │ │ ├── _internal_.SVGAnimatedEnumeration.html │ │ ├── _internal_.SVGAnimatedInteger.html │ │ ├── _internal_.SVGAnimatedLength.html │ │ ├── _internal_.SVGAnimatedLengthList.html │ │ ├── _internal_.SVGAnimatedNumber.html │ │ ├── _internal_.SVGAnimatedNumberList.html │ │ ├── _internal_.SVGAnimatedPoints.html │ │ ├── _internal_.SVGAnimatedPreserveAspectRatio.html │ │ ├── _internal_.SVGAnimatedRect.html │ │ ├── _internal_.SVGAnimatedString.html │ │ ├── _internal_.SVGAnimatedTransformList.html │ │ ├── _internal_.SVGAnimationElement.html │ │ ├── _internal_.SVGBoundingBoxOptions.html │ │ ├── _internal_.SVGCircleElement.html │ │ ├── _internal_.SVGClipPathElement.html │ │ ├── _internal_.SVGComponentTransferFunctionElement.html │ │ ├── _internal_.SVGDefsElement.html │ │ ├── _internal_.SVGDescElement.html │ │ ├── _internal_.SVGElement.html │ │ ├── _internal_.SVGElementEventMap.html │ │ ├── _internal_.SVGElementTagNameMap.html │ │ ├── _internal_.SVGEllipseElement.html │ │ ├── _internal_.SVGFEBlendElement.html │ │ ├── _internal_.SVGFEColorMatrixElement.html │ │ ├── _internal_.SVGFEComponentTransferElement.html │ │ ├── _internal_.SVGFECompositeElement.html │ │ ├── _internal_.SVGFEConvolveMatrixElement.html │ │ ├── _internal_.SVGFEDiffuseLightingElement.html │ │ ├── _internal_.SVGFEDisplacementMapElement.html │ │ ├── _internal_.SVGFEDistantLightElement.html │ │ ├── _internal_.SVGFEDropShadowElement.html │ │ ├── _internal_.SVGFEFloodElement.html │ │ ├── _internal_.SVGFEFuncAElement.html │ │ ├── _internal_.SVGFEFuncBElement.html │ │ ├── _internal_.SVGFEFuncGElement.html │ │ ├── _internal_.SVGFEFuncRElement.html │ │ ├── _internal_.SVGFEGaussianBlurElement.html │ │ ├── _internal_.SVGFEImageElement.html │ │ ├── _internal_.SVGFEMergeElement.html │ │ ├── _internal_.SVGFEMergeNodeElement.html │ │ ├── _internal_.SVGFEMorphologyElement.html │ │ ├── _internal_.SVGFEOffsetElement.html │ │ ├── _internal_.SVGFEPointLightElement.html │ │ ├── _internal_.SVGFESpecularLightingElement.html │ │ ├── _internal_.SVGFESpotLightElement.html │ │ ├── _internal_.SVGFETileElement.html │ │ ├── _internal_.SVGFETurbulenceElement.html │ │ ├── _internal_.SVGFilterElement.html │ │ ├── _internal_.SVGFilterPrimitiveStandardAttributes.html │ │ ├── _internal_.SVGFitToViewBox.html │ │ ├── _internal_.SVGForeignObjectElement.html │ │ ├── _internal_.SVGGElement.html │ │ ├── _internal_.SVGGeometryElement.html │ │ ├── _internal_.SVGGradientElement.html │ │ ├── _internal_.SVGGraphicsElement.html │ │ ├── _internal_.SVGImageElement.html │ │ ├── _internal_.SVGLength.html │ │ ├── _internal_.SVGLineElement.html │ │ ├── _internal_.SVGLinearGradientElement.html │ │ ├── _internal_.SVGMPathElement.html │ │ ├── _internal_.SVGMarkerElement.html │ │ ├── _internal_.SVGMaskElement.html │ │ ├── _internal_.SVGMetadataElement.html │ │ ├── _internal_.SVGNumber.html │ │ ├── _internal_.SVGPathElement.html │ │ ├── _internal_.SVGPatternElement.html │ │ ├── _internal_.SVGPolygonElement.html │ │ ├── _internal_.SVGPolylineElement.html │ │ ├── _internal_.SVGPreserveAspectRatio.html │ │ ├── _internal_.SVGRadialGradientElement.html │ │ ├── _internal_.SVGRectElement.html │ │ ├── _internal_.SVGSVGElement.html │ │ ├── _internal_.SVGSVGElementEventMap.html │ │ ├── _internal_.SVGScriptElement.html │ │ ├── _internal_.SVGSetElement.html │ │ ├── _internal_.SVGStopElement.html │ │ ├── _internal_.SVGStyleElement.html │ │ ├── _internal_.SVGSwitchElement.html │ │ ├── _internal_.SVGSymbolElement.html │ │ ├── _internal_.SVGTSpanElement.html │ │ ├── _internal_.SVGTests.html │ │ ├── _internal_.SVGTextContentElement.html │ │ ├── _internal_.SVGTextElement.html │ │ ├── _internal_.SVGTextPathElement.html │ │ ├── _internal_.SVGTextPositioningElement.html │ │ ├── _internal_.SVGTitleElement.html │ │ ├── _internal_.SVGTransform.html │ │ ├── _internal_.SVGURIReference.html │ │ ├── _internal_.SVGUseElement.html │ │ ├── _internal_.SVGViewElement.html │ │ ├── _internal_.Screen.html │ │ ├── _internal_.ScreenOrientation.html │ │ ├── _internal_.ScreenOrientationEventMap.html │ │ ├── _internal_.ScrollIntoViewOptions.html │ │ ├── _internal_.ScrollOptions.html │ │ ├── _internal_.ScrollToOptions.html │ │ ├── _internal_.SecurityPolicyViolationEvent.html │ │ ├── _internal_.Selection.html │ │ ├── _internal_.ShadowRoot.html │ │ ├── _internal_.ShadowRootEventMap.html │ │ ├── _internal_.ShadowRootInit.html │ │ ├── _internal_.SharedArrayBuffer.html │ │ ├── _internal_.SharedArrayBufferConstructor.html │ │ ├── _internal_.Slottable.html │ │ ├── _internal_.SourceBuffer.html │ │ ├── _internal_.SourceBufferEventMap.html │ │ ├── _internal_.SpeechSynthesis.html │ │ ├── _internal_.SpeechSynthesisErrorEvent.html │ │ ├── _internal_.SpeechSynthesisEvent.html │ │ ├── _internal_.SpeechSynthesisEventMap.html │ │ ├── _internal_.SpeechSynthesisUtterance.html │ │ ├── _internal_.SpeechSynthesisUtteranceEventMap.html │ │ ├── _internal_.SpeechSynthesisVoice.html │ │ ├── _internal_.StaticRange.html │ │ ├── _internal_.Storage.html │ │ ├── _internal_.StorageEvent.html │ │ ├── _internal_.StreamPipeOptions.html │ │ ├── _internal_.StructuredSerializeOptions.html │ │ ├── _internal_.StyleSheet.html │ │ ├── _internal_.SubmitEvent.html │ │ ├── _internal_.Text.html │ │ ├── _internal_.TextMetrics.html │ │ ├── _internal_.TextTrack.html │ │ ├── _internal_.TextTrackCue.html │ │ ├── _internal_.TextTrackCueEventMap.html │ │ ├── _internal_.TextTrackEventMap.html │ │ ├── _internal_.TimeRanges.html │ │ ├── _internal_.TouchEvent.html │ │ ├── _internal_.TrackEvent.html │ │ ├── _internal_.TransitionEvent.html │ │ ├── _internal_.TreeWalker.html │ │ ├── _internal_.UIEvent.html │ │ ├── _internal_.ULongRange.html │ │ ├── _internal_.ValidityState.html │ │ ├── _internal_.VideoFrameMetadata.html │ │ ├── _internal_.VideoFrameRequestCallback.html │ │ ├── _internal_.VideoPlaybackQuality.html │ │ ├── _internal_.VisualViewport.html │ │ ├── _internal_.VisualViewportEventMap.html │ │ ├── _internal_.VoidFunction.html │ │ ├── _internal_.WEBGL_color_buffer_float.html │ │ ├── _internal_.WEBGL_compressed_texture_astc.html │ │ ├── _internal_.WEBGL_compressed_texture_etc.html │ │ ├── _internal_.WEBGL_compressed_texture_etc1.html │ │ ├── _internal_.WEBGL_compressed_texture_s3tc.html │ │ ├── _internal_.WEBGL_compressed_texture_s3tc_srgb.html │ │ ├── _internal_.WEBGL_debug_renderer_info.html │ │ ├── _internal_.WEBGL_debug_shaders.html │ │ ├── _internal_.WEBGL_depth_texture.html │ │ ├── _internal_.WEBGL_lose_context.html │ │ ├── _internal_.WebGL2RenderingContext.html │ │ ├── _internal_.WebGLActiveInfo.html │ │ ├── _internal_.WebGLBuffer.html │ │ ├── _internal_.WebGLContextAttributes.html │ │ ├── _internal_.WebGLContextEvent.html │ │ ├── _internal_.WebGLFramebuffer.html │ │ ├── _internal_.WebGLProgram.html │ │ ├── _internal_.WebGLQuery.html │ │ ├── _internal_.WebGLRenderbuffer.html │ │ ├── _internal_.WebGLRenderingContext.html │ │ ├── _internal_.WebGLSampler.html │ │ ├── _internal_.WebGLShader.html │ │ ├── _internal_.WebGLShaderPrecisionFormat.html │ │ ├── _internal_.WebGLSync.html │ │ ├── _internal_.WebGLTexture.html │ │ ├── _internal_.WebGLTransformFeedback.html │ │ ├── _internal_.WebGLUniformLocation.html │ │ ├── _internal_.WebGLVertexArrayObject.html │ │ ├── _internal_.WebGLVertexArrayObjectOES.html │ │ ├── _internal_.WheelEvent.html │ │ ├── _internal_.Window.html │ │ ├── _internal_.WindowEventHandlers.html │ │ ├── _internal_.WindowEventHandlersEventMap.html │ │ ├── _internal_.WindowEventMap.html │ │ ├── _internal_.WindowLocalStorage.html │ │ ├── _internal_.WindowOrWorkerGlobalScope.html │ │ ├── _internal_.WindowPostMessageOptions.html │ │ ├── _internal_.WindowSessionStorage.html │ │ ├── _internal_.WritableStream-1.html │ │ ├── _internal_.WritableStream.html │ │ ├── _internal_.WritableStreamDefaultWriter.html │ │ ├── _internal_.XMLDocument.html │ │ ├── _internal_.XPathEvaluatorBase.html │ │ ├── _internal_.XPathExpression.html │ │ └── _internal_.XPathResult.html │ ├── modules.html │ └── modules │ │ └── _internal_.html ├── common.97dc6094.css ├── dom-multiple.364abb33.css ├── dom-multiple.f1f90186.js ├── dom.c2350d4c.js ├── dom.f83825bb.css ├── examples.b3b81731.js ├── examples.fa10a2f1.css ├── godray.58904440.js ├── godray.a8d3693c.css ├── godray.c294baa0.js ├── group.2d1ce79b.css ├── group.9da781f2.js ├── image.2d1ce79b.css ├── image.3a2bf2f6.js ├── index.html ├── instancing.00f8c81f.js ├── instancing.167e377c.js ├── instancing.a8d3693c.css ├── kgl-auto │ ├── godray │ │ └── index.html │ ├── instancing │ │ └── index.html │ └── simple │ │ └── index.html ├── kgl │ ├── 3d │ │ └── index.html │ ├── dom-multiple │ │ └── index.html │ ├── dom │ │ └── index.html │ ├── godray │ │ └── index.html │ ├── group │ │ └── index.html │ ├── image │ │ └── index.html │ ├── instancing │ │ └── index.html │ ├── point │ │ └── index.html │ ├── simple │ │ └── index.html │ └── transparent-images │ │ └── index.html ├── point.2d1ce79b.css ├── point.c0a8c1fa.js ├── simple.24c3f6a9.js ├── simple.26db8ec6.js ├── simple.2d1ce79b.css ├── transparent-images.2d1ce79b.css └── transparent-images.7d1a2fcd.js ├── examples ├── .babelrc ├── .gitignore ├── common.styl ├── index.html ├── index.js ├── index.styl ├── kgl-auto │ ├── godray │ │ ├── index.css │ │ ├── index.html │ │ └── index.js │ ├── instancing │ │ ├── index.css │ │ ├── index.html │ │ └── index.js │ └── simple │ │ ├── index.css │ │ ├── index.html │ │ └── index.js ├── kgl │ ├── 3d │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js │ ├── dom-multiple │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js │ ├── dom │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js │ ├── godray │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── mask.frag │ ├── group │ │ ├── cross.frag │ │ ├── full.frag │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js │ ├── image │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js │ ├── instancing │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── shaders │ │ │ ├── main.frag │ │ │ ├── main.vert │ │ │ ├── position.frag │ │ │ ├── reset-position.frag │ │ │ ├── reset-velocity.frag │ │ │ └── velocity.frag │ ├── point │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ ├── index.js │ │ └── index.vert │ ├── simple │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js │ └── transparent-images │ │ ├── 1-white-clouds-png-image_400x400.png │ │ ├── index.css │ │ ├── index.frag │ │ ├── index.html │ │ └── index.js ├── package-lock.json ├── package.json ├── shaders │ ├── PI.glsl │ ├── discardOutOfRangeUv.glsl │ ├── fitContain.glsl │ ├── fitCover.glsl │ ├── getZoomedUv.glsl │ └── hsv.glsl ├── utils.js └── variables.styl ├── package-lock.json ├── package.json ├── src ├── effects │ ├── bloom.ts │ ├── blur.ts │ ├── godray.ts │ ├── godrayLight.ts │ ├── index.ts │ ├── specular.ts │ └── zoomblur.ts ├── index.ts ├── kgl.ts ├── kglAuto.ts ├── kglEffect.ts ├── minMatrix.ts ├── object.ts ├── program.ts ├── shaders │ ├── glsl.d.ts │ ├── postprocessing │ │ ├── bloom.frag │ │ ├── blur.frag │ │ ├── godray.frag │ │ ├── specular.frag │ │ └── zoomblur.frag │ └── template │ │ └── texture.frag ├── shape.ts ├── type.ts └── vector.ts ├── tsconfig.json └── tsconfig.types.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | docs/ 4 | .cache 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: ['standard', 'prettier', 'plugin:prettier/recommended'], 7 | plugins: ['prettier'], 8 | parserOptions: { 9 | ecmaVersion: 12, 10 | sourceType: 'module', 11 | }, 12 | rules: { 13 | 'no-new': 'off', 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | /dist 4 | /lib 5 | /types 6 | # /docs 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ko.Yelie 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.md: -------------------------------------------------------------------------------- 1 | # KGL 2 | 3 | Minimal WebGL library 4 | 5 | ## Pros and Cons 6 | 7 | ### Pros 8 | 9 | - Lightweight 10 | - Can write with less code. 11 | - Automates calculations to fit WebGL and DOM sizes. 12 | - Support TypeScript. 13 | 14 | ### Cons 15 | 16 | - Fragment shaders must always be written by you. 17 | - Cannot use complex 3D models. 18 | - Cannot use lighting. 19 | - Not support WebGL2 yet. 20 | 21 | ## Documentation 22 | 23 | - [API](https://ko-yelie.github.io/kgl/api/) 24 | 25 | ## Usage 26 | 27 | ### Installation 28 | 29 | #### ES Modules 30 | 31 | [npm](https://www.npmjs.com/package/@ko-yelie/kgl) 32 | 33 | ```sh 34 | npm i @ko-yelie/kgl 35 | ``` 36 | 37 | ```js 38 | // Kgl 39 | import Kgl from '@ko-yelie/kgl' 40 | 41 | // KglAuto 42 | import { KglAuto } from '@ko-yelie/kgl' 43 | 44 | // Import only KGL (ignore KglAuto and effects) 45 | import Kgl from '@ko-yelie/kgl/dist/kgl.es.js' 46 | ``` 47 | 48 | #### CDN 49 | 50 | [unpkg](https://unpkg.com/@ko-yelie/kgl) 51 | 52 | ```html 53 | 54 | ``` 55 | 56 | ```js 57 | // Kgl 58 | Kgl.default 59 | 60 | // KglAuto 61 | const { KglAuto } = Kgl 62 | ``` 63 | 64 | ### `Kgl` 65 | 66 | #### HTML 67 | 68 | ```html 69 | 80 | ``` 81 | 82 | #### JS 83 | 84 | ```js 85 | import Kgl from '@ko-yelie/kgl' 86 | 87 | const kgl = new Kgl() 88 | 89 | /** 90 | * program 91 | */ 92 | const program = kgl.createProgram({ 93 | fragmentShaderId: 'fs', 94 | uniforms: { 95 | uTime: 0, 96 | }, 97 | isAutoAdd: true, 98 | }) 99 | 100 | /** 101 | * resize 102 | */ 103 | function resize() { 104 | kgl.resize() 105 | } 106 | resize() 107 | window.addEventListener('resize', resize) 108 | 109 | /** 110 | * tick 111 | */ 112 | function tick(time) { 113 | program.uniforms.uTime = time * 0.001 114 | 115 | kgl.draw() 116 | 117 | requestAnimationFrame(tick) 118 | } 119 | requestAnimationFrame(tick) 120 | ``` 121 | 122 | ### `KglAuto` 123 | 124 | #### JS 125 | 126 | ```js 127 | import { KglAuto } from '@ko-yelie/kgl' 128 | 129 | new KglAuto({ 130 | programs: { 131 | main: { 132 | fragmentShaderId: 'fs', 133 | uniforms: { 134 | uTime: 0, 135 | }, 136 | }, 137 | }, 138 | tick: (kgl, time) => { 139 | kgl.programs.main.uniforms.uTime = time 140 | kgl.draw() 141 | }, 142 | }) 143 | ``` 144 | 145 | ## Examples 146 | 147 | https://ko-yelie.github.io/kgl/ 148 | -------------------------------------------------------------------------------- /bili.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const pkg = require(path.resolve(process.cwd(), 'package.json')) 3 | 4 | const NAME = 'KGL' 5 | const banner = `/*! 6 | * ${NAME || pkg.name} v${pkg.version} 7 | * ${pkg.homepage} 8 | * @license ${pkg.license} 9 | * Copyright ${pkg.author} 10 | */` 11 | 12 | module.exports = { 13 | babel: { 14 | minimal: true, 15 | }, 16 | banner, 17 | input: ['src/index.ts', 'src/kgl.ts'], 18 | output: { 19 | moduleName: 'Kgl', 20 | format: ['es', 'iife', 'iife-min'], 21 | sourceMap: false, 22 | target: 'browser', 23 | }, 24 | plugins: { 25 | replace: { preventAssignment: true }, 26 | glslify: true, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /docs/1-white-clouds-png-image_400x400.2471b47f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ko-yelie/kgl/746f039b018192e5e78574ff933ce0ded15805cc/docs/1-white-clouds-png-image_400x400.2471b47f.png -------------------------------------------------------------------------------- /docs/3d.2d1ce79b.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57} -------------------------------------------------------------------------------- /docs/api/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /docs/api/assets/highlight.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --light-hl-0: #000000; 3 | --dark-hl-0: #D4D4D4; 4 | --light-hl-1: #008000; 5 | --dark-hl-1: #6A9955; 6 | --light-hl-2: #AF00DB; 7 | --dark-hl-2: #C586C0; 8 | --light-hl-3: #001080; 9 | --dark-hl-3: #9CDCFE; 10 | --light-hl-4: #A31515; 11 | --dark-hl-4: #CE9178; 12 | --light-hl-5: #800000; 13 | --dark-hl-5: #808080; 14 | --light-hl-6: #800000; 15 | --dark-hl-6: #569CD6; 16 | --light-hl-7: #000000FF; 17 | --dark-hl-7: #D4D4D4; 18 | --light-hl-8: #FF0000; 19 | --dark-hl-8: #9CDCFE; 20 | --light-hl-9: #0000FF; 21 | --dark-hl-9: #CE9178; 22 | --light-hl-10: #0000FF; 23 | --dark-hl-10: #569CD6; 24 | --light-hl-11: #0070C1; 25 | --dark-hl-11: #4FC1FF; 26 | --light-hl-12: #795E26; 27 | --dark-hl-12: #DCDCAA; 28 | --light-hl-13: #098658; 29 | --dark-hl-13: #B5CEA8; 30 | --light-hl-14: #EE0000; 31 | --dark-hl-14: #D7BA7D; 32 | --light-hl-15: #267F99; 33 | --dark-hl-15: #4EC9B0; 34 | --light-code-background: #F5F5F5; 35 | --dark-code-background: #1E1E1E; 36 | } 37 | 38 | @media (prefers-color-scheme: light) { :root { 39 | --hl-0: var(--light-hl-0); 40 | --hl-1: var(--light-hl-1); 41 | --hl-2: var(--light-hl-2); 42 | --hl-3: var(--light-hl-3); 43 | --hl-4: var(--light-hl-4); 44 | --hl-5: var(--light-hl-5); 45 | --hl-6: var(--light-hl-6); 46 | --hl-7: var(--light-hl-7); 47 | --hl-8: var(--light-hl-8); 48 | --hl-9: var(--light-hl-9); 49 | --hl-10: var(--light-hl-10); 50 | --hl-11: var(--light-hl-11); 51 | --hl-12: var(--light-hl-12); 52 | --hl-13: var(--light-hl-13); 53 | --hl-14: var(--light-hl-14); 54 | --hl-15: var(--light-hl-15); 55 | --code-background: var(--light-code-background); 56 | } } 57 | 58 | @media (prefers-color-scheme: dark) { :root { 59 | --hl-0: var(--dark-hl-0); 60 | --hl-1: var(--dark-hl-1); 61 | --hl-2: var(--dark-hl-2); 62 | --hl-3: var(--dark-hl-3); 63 | --hl-4: var(--dark-hl-4); 64 | --hl-5: var(--dark-hl-5); 65 | --hl-6: var(--dark-hl-6); 66 | --hl-7: var(--dark-hl-7); 67 | --hl-8: var(--dark-hl-8); 68 | --hl-9: var(--dark-hl-9); 69 | --hl-10: var(--dark-hl-10); 70 | --hl-11: var(--dark-hl-11); 71 | --hl-12: var(--dark-hl-12); 72 | --hl-13: var(--dark-hl-13); 73 | --hl-14: var(--dark-hl-14); 74 | --hl-15: var(--dark-hl-15); 75 | --code-background: var(--dark-code-background); 76 | } } 77 | 78 | body.light { 79 | --hl-0: var(--light-hl-0); 80 | --hl-1: var(--light-hl-1); 81 | --hl-2: var(--light-hl-2); 82 | --hl-3: var(--light-hl-3); 83 | --hl-4: var(--light-hl-4); 84 | --hl-5: var(--light-hl-5); 85 | --hl-6: var(--light-hl-6); 86 | --hl-7: var(--light-hl-7); 87 | --hl-8: var(--light-hl-8); 88 | --hl-9: var(--light-hl-9); 89 | --hl-10: var(--light-hl-10); 90 | --hl-11: var(--light-hl-11); 91 | --hl-12: var(--light-hl-12); 92 | --hl-13: var(--light-hl-13); 93 | --hl-14: var(--light-hl-14); 94 | --hl-15: var(--light-hl-15); 95 | --code-background: var(--light-code-background); 96 | } 97 | 98 | body.dark { 99 | --hl-0: var(--dark-hl-0); 100 | --hl-1: var(--dark-hl-1); 101 | --hl-2: var(--dark-hl-2); 102 | --hl-3: var(--dark-hl-3); 103 | --hl-4: var(--dark-hl-4); 104 | --hl-5: var(--dark-hl-5); 105 | --hl-6: var(--dark-hl-6); 106 | --hl-7: var(--dark-hl-7); 107 | --hl-8: var(--dark-hl-8); 108 | --hl-9: var(--dark-hl-9); 109 | --hl-10: var(--dark-hl-10); 110 | --hl-11: var(--dark-hl-11); 111 | --hl-12: var(--dark-hl-12); 112 | --hl-13: var(--dark-hl-13); 113 | --hl-14: var(--dark-hl-14); 114 | --hl-15: var(--dark-hl-15); 115 | --code-background: var(--dark-code-background); 116 | } 117 | 118 | .hl-0 { color: var(--hl-0); } 119 | .hl-1 { color: var(--hl-1); } 120 | .hl-2 { color: var(--hl-2); } 121 | .hl-3 { color: var(--hl-3); } 122 | .hl-4 { color: var(--hl-4); } 123 | .hl-5 { color: var(--hl-5); } 124 | .hl-6 { color: var(--hl-6); } 125 | .hl-7 { color: var(--hl-7); } 126 | .hl-8 { color: var(--hl-8); } 127 | .hl-9 { color: var(--hl-9); } 128 | .hl-10 { color: var(--hl-10); } 129 | .hl-11 { color: var(--hl-11); } 130 | .hl-12 { color: var(--hl-12); } 131 | .hl-13 { color: var(--hl-13); } 132 | .hl-14 { color: var(--hl-14); } 133 | .hl-15 { color: var(--hl-15); } 134 | pre, code { background: var(--code-background); } 135 | -------------------------------------------------------------------------------- /docs/api/assets/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ko-yelie/kgl/746f039b018192e5e78574ff933ce0ded15805cc/docs/api/assets/icons.png -------------------------------------------------------------------------------- /docs/api/assets/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ko-yelie/kgl/746f039b018192e5e78574ff933ce0ded15805cc/docs/api/assets/icons@2x.png -------------------------------------------------------------------------------- /docs/api/assets/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ko-yelie/kgl/746f039b018192e5e78574ff933ce0ded15805cc/docs/api/assets/widgets.png -------------------------------------------------------------------------------- /docs/api/assets/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ko-yelie/kgl/746f039b018192e5e78574ff933ce0ded15805cc/docs/api/assets/widgets@2x.png -------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.DOMStringMap.html: -------------------------------------------------------------------------------- 1 | DOMStringMap | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu
2 |

Used by the dataset HTML attribute to represent data for custom attributes added to elements.

3 |

Hierarchy

  • DOMStringMap

Indexable

[name: string]: string | undefined

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.EXT_color_buffer_float.html: -------------------------------------------------------------------------------- 1 | EXT_color_buffer_float | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface EXT_color_buffer_float

Hierarchy

  • EXT_color_buffer_float

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.EXT_float_blend.html: -------------------------------------------------------------------------------- 1 | EXT_float_blend | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface EXT_float_blend

Hierarchy

  • EXT_float_blend

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.EXT_frag_depth.html: -------------------------------------------------------------------------------- 1 | EXT_frag_depth | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface EXT_frag_depth

2 |

The EXT_frag_depth extension is part of the WebGL API and enables to set a depth value of a fragment from within the fragment shader.

3 |

Hierarchy

  • EXT_frag_depth

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.EXT_shader_texture_lod.html: -------------------------------------------------------------------------------- 1 | EXT_shader_texture_lod | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface EXT_shader_texture_lod

Hierarchy

  • EXT_shader_texture_lod

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.OES_element_index_uint.html: -------------------------------------------------------------------------------- 1 | OES_element_index_uint | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface OES_element_index_uint

2 |

The OES_element_index_uint extension is part of the WebGL API and adds support for gl.UNSIGNED_INT types to WebGLRenderingContext.drawElements().

3 |

Hierarchy

  • OES_element_index_uint

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.OES_texture_float.html: -------------------------------------------------------------------------------- 1 | OES_texture_float | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface OES_texture_float

2 |

The OES_texture_float extension is part of the WebGL API and exposes floating-point pixel types for textures.

3 |

Hierarchy

  • OES_texture_float

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.OES_texture_float_linear.html: -------------------------------------------------------------------------------- 1 | OES_texture_float_linear | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface OES_texture_float_linear

2 |

The OES_texture_float_linear extension is part of the WebGL API and allows linear filtering with floating-point pixel types for textures.

3 |

Hierarchy

  • OES_texture_float_linear

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.OES_texture_half_float_linear.html: -------------------------------------------------------------------------------- 1 | OES_texture_half_float_linear | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface OES_texture_half_float_linear

2 |

The OES_texture_half_float_linear extension is part of the WebGL API and allows linear filtering with half floating-point pixel types for textures.

3 |

Hierarchy

  • OES_texture_half_float_linear

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.VoidFunction.html: -------------------------------------------------------------------------------- 1 | VoidFunction | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • VoidFunction

Callable

  • VoidFunction(): void
  • Returns void

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLBuffer.html: -------------------------------------------------------------------------------- 1 | WebGLBuffer | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu
2 |

Part of the WebGL API and represents an opaque buffer object storing data such as vertices or colors.

3 |

Hierarchy

  • WebGLBuffer

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLFramebuffer.html: -------------------------------------------------------------------------------- 1 | WebGLFramebuffer | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WebGLFramebuffer

2 |

Part of the WebGL API and represents a collection of buffers that serve as a rendering destination.

3 |

Hierarchy

  • WebGLFramebuffer

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLProgram.html: -------------------------------------------------------------------------------- 1 | WebGLProgram | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu
2 |

The WebGLProgram is part of the WebGL API and is a combination of two compiled WebGLShaders consisting of a vertex shader and a fragment shader (both written in GLSL).

3 |

Hierarchy

  • WebGLProgram

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLQuery.html: -------------------------------------------------------------------------------- 1 | WebGLQuery | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • WebGLQuery

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLRenderbuffer.html: -------------------------------------------------------------------------------- 1 | WebGLRenderbuffer | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WebGLRenderbuffer

2 |

Part of the WebGL API and represents a buffer that can contain an image, or can be source or target of an rendering operation.

3 |

Hierarchy

  • WebGLRenderbuffer

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLSampler.html: -------------------------------------------------------------------------------- 1 | WebGLSampler | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • WebGLSampler

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLShader.html: -------------------------------------------------------------------------------- 1 | WebGLShader | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu
2 |

The WebGLShader is part of the WebGL API and can either be a vertex or a fragment shader. A WebGLProgram requires both types of shaders.

3 |

Hierarchy

  • WebGLShader

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLSync.html: -------------------------------------------------------------------------------- 1 | WebGLSync | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • WebGLSync

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLTexture.html: -------------------------------------------------------------------------------- 1 | WebGLTexture | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu
2 |

Part of the WebGL API and represents an opaque texture object providing storage and state for texturing operations.

3 |

Hierarchy

  • WebGLTexture

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLTransformFeedback.html: -------------------------------------------------------------------------------- 1 | WebGLTransformFeedback | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WebGLTransformFeedback

Hierarchy

  • WebGLTransformFeedback

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLUniformLocation.html: -------------------------------------------------------------------------------- 1 | WebGLUniformLocation | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WebGLUniformLocation

2 |

Part of the WebGL API and represents the location of a uniform variable in a shader program.

3 |

Hierarchy

  • WebGLUniformLocation

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLVertexArrayObject.html: -------------------------------------------------------------------------------- 1 | WebGLVertexArrayObject | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WebGLVertexArrayObject

Hierarchy

  • WebGLVertexArrayObject

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/api/interfaces/_internal_.WebGLVertexArrayObjectOES.html: -------------------------------------------------------------------------------- 1 | WebGLVertexArrayObjectOES | @ko-yelie/kgl
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WebGLVertexArrayObjectOES

Hierarchy

  • WebGLVertexArrayObjectOES

Generated using TypeDoc

-------------------------------------------------------------------------------- /docs/common.97dc6094.css: -------------------------------------------------------------------------------- 1 | body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.attribution{position:absolute;top:.5rem;right:.5rem;background-color:rgba(0,0,0,.3);color:hsla(0,0%,100%,.5);font-size:.8rem;padding:0 .3em;text-decoration:none}.attribution:hover{color:hsla(0,0%,100%,.7);text-decoration:underline} -------------------------------------------------------------------------------- /docs/dom-multiple.364abb33.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57}.wapper{position:relative;z-index:2;padding:20% 0}.scroll{position:absolute;top:2%;left:0;right:0;margin:auto;text-align:center;color:hsla(0,0%,100%,.7)}.list{display:flex;flex-direction:column;justify-content:space-between;width:50%;min-height:150vh;margin:0 auto;list-style:none}.item{align-self:flex-start}.item:nth-child(2n){align-self:flex-end}.item:nth-child(n+2){margin-top:20%}.link{display:block;color:hsla(0,0%,100%,.5);text-decoration:none;text-align:center}.image{width:30vw;height:auto;opacity:0}.title{background-color:rgba(0,0,0,.3);font-size:.8rem;padding:0 .3em}.link:hover{color:hsla(0,0%,100%,.7);text-decoration:underline}canvas{position:fixed;top:0;left:0;z-index:1;width:100%;height:100%} -------------------------------------------------------------------------------- /docs/dom.f83825bb.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57}.wapper{position:relative;z-index:2;height:100%;display:flex;justify-content:center;align-items:center}.link{display:block;color:hsla(0,0%,100%,.5);text-decoration:none;text-align:center}.image{width:50vw;height:auto;opacity:0}.title{background-color:rgba(0,0,0,.3);font-size:.8rem;padding:0 .3em}.link:hover{color:hsla(0,0%,100%,.7);text-decoration:underline}canvas{position:fixed;top:0;left:0;z-index:1;width:100%;height:100%} -------------------------------------------------------------------------------- /docs/examples.fa10a2f1.css: -------------------------------------------------------------------------------- 1 | body{display:flex;align-items:flex-start;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}a{text-decoration:none;color:hsla(0,0%,100%,.5)}a:hover{text-decoration:underline}a:hover,header{color:hsla(0,0%,100%,.7)}header{overflow:auto;box-sizing:border-box;position:fixed;top:.5rem;left:.5rem;z-index:1;max-height:calc(100% - 1rem);margin:auto;padding:.5rem;background-color:rgba(0,0,0,.3)}nav ul{margin:0}nav a{padding:.1em .2em;line-height:1.5}nav a.-current{pointer-events:none;text-decoration:none;outline:1px solid hsla(0,0%,100%,.7);background-color:hsla(0,0%,100%,.7);color:#000}h1,h2{margin:0;font-size:1rem;font-weight:400}h1{margin-bottom:.5em}h2{margin-top:.5em}#example{top:0;left:0;width:100%;height:100%}#code,#example{position:absolute}#code{bottom:.5rem;right:.5rem;z-index:2;padding:0 .3em;background-color:rgba(0,0,0,.3)} -------------------------------------------------------------------------------- /docs/godray.a8d3693c.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0} -------------------------------------------------------------------------------- /docs/group.2d1ce79b.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57} -------------------------------------------------------------------------------- /docs/image.2d1ce79b.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57} -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples

KGL Library Examples

Document

<code> -------------------------------------------------------------------------------- /docs/instancing.a8d3693c.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0} -------------------------------------------------------------------------------- /docs/kgl-auto/godray/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - God Ray (KglAuto) Photo by Sasha Freemind on Unsplash -------------------------------------------------------------------------------- /docs/kgl-auto/instancing/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Instancing (KglAuto) -------------------------------------------------------------------------------- /docs/kgl-auto/simple/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Simple (KglAuto) -------------------------------------------------------------------------------- /docs/kgl/3d/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - 3D -------------------------------------------------------------------------------- /docs/kgl/dom-multiple/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Fit Multiple DOM

Scroll Down

-------------------------------------------------------------------------------- /docs/kgl/dom/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Fit DOM

Photo by Anton Maksimov 5642.su
on Unsplash

-------------------------------------------------------------------------------- /docs/kgl/godray/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - God Ray Photo by Sasha Freemind on Unsplash -------------------------------------------------------------------------------- /docs/kgl/group/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Group -------------------------------------------------------------------------------- /docs/kgl/image/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Image Photo by FLY:D on Unsplash -------------------------------------------------------------------------------- /docs/kgl/instancing/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Instancing -------------------------------------------------------------------------------- /docs/kgl/point/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Point -------------------------------------------------------------------------------- /docs/kgl/simple/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Simple -------------------------------------------------------------------------------- /docs/kgl/transparent-images/index.html: -------------------------------------------------------------------------------- 1 | KGL Library Examples - Transparent Images White Clouds Png Image FreePNGImg.com -------------------------------------------------------------------------------- /docs/point.2d1ce79b.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57} -------------------------------------------------------------------------------- /docs/simple.2d1ce79b.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57} -------------------------------------------------------------------------------- /docs/transparent-images.2d1ce79b.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%}body{margin:0;background-color:#494e57} -------------------------------------------------------------------------------- /examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-runtime" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | /dist 3 | /node_modules 4 | -------------------------------------------------------------------------------- /examples/common.styl: -------------------------------------------------------------------------------- 1 | @import 'variables' 2 | 3 | body 4 | font-family font-family 5 | 6 | .attribution 7 | position absolute 8 | top margin-window 9 | right margin-window 10 | background-color background-color 11 | color color-link 12 | font-size 0.8rem 13 | padding 0 0.3em 14 | text-decoration none 15 | 16 | .attribution:hover 17 | color color-text 18 | text-decoration underline 19 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples 7 | 8 | 9 | 10 | 11 | 12 |
13 |

KGL Library Examples 14 |

15 | 16 |

Document

17 | 18 | 40 |
41 | 42 | 43 | 44 | <code> 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | const CLASS_NAME_INITIAL = 'kgl' 2 | const PAGE_INITIAL = 'simple' 3 | const CLASS_NAME_CURRENT = '-current' 4 | 5 | const elExample = document.getElementById('example') 6 | const elCode = document.getElementById('code') 7 | let urlIndex 8 | let classNameCurrent 9 | let pageCurrent 10 | let elLinkCurrent 11 | 12 | const mapLink = [...document.querySelectorAll('nav a')].map((el) => { 13 | const { pathname } = new URL(el.href) 14 | const [, className, page] = pathname.match( 15 | /^\/?(?:kgl\/)?(.+?)\/(.+?)\/index\.html/ 16 | ) 17 | 18 | el.addEventListener('click', (e) => { 19 | e.preventDefault() 20 | 21 | urlIndex.searchParams.set('class', className) 22 | urlIndex.searchParams.set('page', page) 23 | history.pushState(null, '', urlIndex) 24 | 25 | detectExample() 26 | }) 27 | 28 | return { 29 | el, 30 | className, 31 | page, 32 | } 33 | }) 34 | 35 | detectExample() 36 | 37 | window.addEventListener('popstate', detectExample) 38 | 39 | function detectExample() { 40 | urlIndex = new URL(location.href) 41 | const className = urlIndex.searchParams.get('class') || CLASS_NAME_INITIAL 42 | const page = urlIndex.searchParams.get('page') || PAGE_INITIAL 43 | 44 | if (className === classNameCurrent && page === pageCurrent) return 45 | 46 | const directory = `${className}/${page}` 47 | const pathname = `${directory}/index.html` 48 | elExample.contentWindow.location.replace(pathname) 49 | elCode.href = `https://github.com/ko-yelie/kgl/blob/main/examples/${directory}` 50 | 51 | classNameCurrent = className 52 | pageCurrent = page 53 | 54 | detectLink() 55 | } 56 | 57 | function detectLink() { 58 | mapLink.some(({ el, className, page }) => { 59 | if (!(className === classNameCurrent && page === pageCurrent)) return false 60 | 61 | if (elLinkCurrent) { 62 | elLinkCurrent.classList.remove(CLASS_NAME_CURRENT) 63 | } 64 | 65 | el.classList.add(CLASS_NAME_CURRENT) 66 | elLinkCurrent = el 67 | 68 | return true 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /examples/index.styl: -------------------------------------------------------------------------------- 1 | @import 'variables' 2 | 3 | body 4 | display flex 5 | align-items flex-start 6 | margin 0 7 | font-family font-family 8 | 9 | a 10 | text-decoration none 11 | color color-link 12 | 13 | &:hover 14 | text-decoration underline 15 | color color-text 16 | 17 | header 18 | overflow auto 19 | box-sizing border-box 20 | position fixed 21 | top margin-window 22 | left margin-window 23 | z-index 1 24 | max-height 'calc(100% - %s)' % (margin-window * 2) 25 | margin auto 26 | padding 0.5rem 27 | background-color background-color 28 | color color-text 29 | 30 | nav 31 | ul 32 | margin 0 33 | 34 | a 35 | padding 0.1em 0.2em 36 | line-height 1.5 37 | 38 | &.-current 39 | pointer-events none 40 | text-decoration none 41 | outline solid 1px color-text 42 | background-color color-text 43 | color #000 44 | 45 | h1, 46 | h2 47 | margin 0 48 | font-size 1rem 49 | font-weight normal 50 | 51 | h1 52 | margin-bottom 0.5em 53 | 54 | h2 55 | margin-top 0.5em 56 | 57 | #example 58 | position absolute 59 | top 0 60 | left 0 61 | width 100% 62 | height 100% 63 | 64 | #code 65 | position absolute 66 | bottom margin-window 67 | right margin-window 68 | z-index 2 69 | padding 0 0.3em 70 | background-color background-color 71 | -------------------------------------------------------------------------------- /examples/kgl-auto/godray/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | } 9 | -------------------------------------------------------------------------------- /examples/kgl-auto/godray/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - God Ray (KglAuto) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 36 | 37 | Photo 38 | by Sasha Freemind on Unsplash 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/kgl-auto/godray/index.js: -------------------------------------------------------------------------------- 1 | import { KglAuto } from '../../../src/index' 2 | import { loadImage, mix } from '../../utils.js' 3 | 4 | const image = 5 | 'https://images.unsplash.com/photo-1534330207526-8e81f10ec6fc?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ' // https://unsplash.com/photos/Pv5WeEyxMWU 6 | const speed = 0.5 7 | const strength = 12 8 | const maxRadius = window.innerWidth < 768 ? 0.4 : 0.8 9 | const minRadius = 0.1 10 | 11 | async function main() { 12 | const img = await loadImage(image, true) 13 | 14 | new KglAuto({ 15 | programs: { 16 | mask: { 17 | fragmentShaderId: 'mask', 18 | uniforms: { 19 | uImage: img, 20 | uImageResolution: [img.width, img.height], 21 | }, 22 | }, 23 | }, 24 | effects: ['godray'], 25 | framebuffers: ['mask', 'cache', 'output'], 26 | tick: (kgl, time) => { 27 | const cTime = Math.sin(time * speed) * 0.5 + 0.5 28 | const halfTime = -Math.abs(cTime * 2 - 1) + 1 29 | 30 | kgl.bindFramebuffer('mask') 31 | kgl.programs.mask.draw() 32 | 33 | kgl.effects.godray.drawEffect( 34 | 'mask', 35 | 'cache', 36 | 'output', 37 | strength, 38 | [mix(kgl.canvas.width, 0, cTime), kgl.canvas.height * 0.5], 39 | mix(maxRadius, minRadius, halfTime), 40 | true 41 | ) 42 | }, 43 | }) 44 | } 45 | main() 46 | -------------------------------------------------------------------------------- /examples/kgl-auto/instancing/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | } 9 | -------------------------------------------------------------------------------- /examples/kgl-auto/instancing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Instancing (KglAuto) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/kgl-auto/instancing/index.js: -------------------------------------------------------------------------------- 1 | import { KglAuto } from '../../../src/index' 2 | import resetVelocityFrag from '../../kgl/instancing/shaders/reset-velocity.frag' 3 | import resetPositionFrag from '../../kgl/instancing/shaders/reset-position.frag' 4 | import velocityFrag from '../../kgl/instancing/shaders/velocity.frag' 5 | import positionFrag from '../../kgl/instancing/shaders/position.frag' 6 | import mainVert from '../../kgl/instancing/shaders/main.vert' 7 | import mainFrag from '../../kgl/instancing/shaders/main.frag' 8 | 9 | const width = 100 10 | const height = 100 11 | 12 | const sizeUniform = [width, height] 13 | const particleUv = [] 14 | 15 | for (let i = 0; i < width; i++) { 16 | for (let j = 0; j < height; j++) { 17 | particleUv.push(i / (width - 1), 1 - j / (height - 1)) 18 | } 19 | } 20 | 21 | let loopCount = 0 22 | let targetBufferIndex = loopCount++ % 2 23 | let prevBufferIndex 24 | 25 | new KglAuto({ 26 | clearedColor: [0, 0, 0, 1], 27 | hasCamera: true, 28 | hasLight: true, 29 | cameraPosition: [0, 0, 480], 30 | fov: 50, 31 | programs: { 32 | resetVelocity: { 33 | fragmentShader: resetVelocityFrag, 34 | isFloats: true, 35 | }, 36 | resetPosition: { 37 | fragmentShader: resetPositionFrag, 38 | uniforms: { 39 | uSize: sizeUniform, 40 | }, 41 | isFloats: true, 42 | }, 43 | velocity: { 44 | fragmentShader: velocityFrag, 45 | uniforms: { 46 | uSize: sizeUniform, 47 | uPrevVelocityTexture: 'framebuffer', 48 | uPrevPositionTexture: 'framebuffer', 49 | }, 50 | isFloats: true, 51 | }, 52 | position: { 53 | fragmentShader: positionFrag, 54 | uniforms: { 55 | uSize: sizeUniform, 56 | uPrevPositionTexture: 'framebuffer', 57 | uVelocityTexture: 'framebuffer', 58 | }, 59 | isFloats: true, 60 | }, 61 | main: { 62 | shape: 'cube', 63 | vertexShader: mainVert, 64 | fragmentShader: mainFrag, 65 | instancedAttributes: { 66 | aInstancedUv: { 67 | value: particleUv, 68 | size: 2, 69 | }, 70 | }, 71 | uniforms: { 72 | uPositionTexture: 'framebuffer', 73 | uVelocityTexture: 'framebuffer', 74 | uTime: 0, 75 | }, 76 | isDepth: true, 77 | isTransparent: true, 78 | }, 79 | }, 80 | framebufferFloats: { 81 | velocity0: { 82 | width, 83 | height, 84 | }, 85 | velocity1: { 86 | width, 87 | height, 88 | }, 89 | position0: { 90 | width, 91 | height, 92 | }, 93 | position1: { 94 | width, 95 | height, 96 | }, 97 | }, 98 | onBefore: (kgl) => { 99 | kgl.bindFramebuffer('velocity' + targetBufferIndex) 100 | kgl.programs.resetVelocity.draw() 101 | 102 | kgl.bindFramebuffer('position' + targetBufferIndex) 103 | kgl.programs.resetPosition.draw() 104 | }, 105 | tick: (kgl, time) => { 106 | prevBufferIndex = targetBufferIndex 107 | targetBufferIndex = loopCount++ % 2 108 | 109 | const prevVelocityTexture = `velocity${prevBufferIndex}` 110 | const prevPositionTexture = `position${prevBufferIndex}` 111 | const velocityTexture = `velocity${targetBufferIndex}` 112 | const positionTexture = `position${targetBufferIndex}` 113 | 114 | kgl.bindFramebuffer(velocityTexture) 115 | 116 | kgl.programs.velocity.updateUniforms({ 117 | uPrevVelocityTexture: prevVelocityTexture, 118 | uPrevPositionTexture: prevPositionTexture, 119 | }) 120 | kgl.programs.velocity.draw() 121 | 122 | kgl.bindFramebuffer(positionTexture) 123 | 124 | kgl.programs.position.updateUniforms({ 125 | uPrevPositionTexture: prevPositionTexture, 126 | uVelocityTexture: velocityTexture, 127 | }) 128 | kgl.programs.position.draw() 129 | 130 | kgl.unbindFramebuffer() 131 | kgl.clear() 132 | 133 | kgl.programs.main.updateUniforms({ 134 | uPositionTexture: positionTexture, 135 | uVelocityTexture: velocityTexture, 136 | uTime: time, 137 | }) 138 | kgl.programs.main.draw() 139 | }, 140 | }) 141 | -------------------------------------------------------------------------------- /examples/kgl-auto/simple/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl-auto/simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Simple (KglAuto) 7 | 8 | 9 | 10 | 11 | 12 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/kgl-auto/simple/index.js: -------------------------------------------------------------------------------- 1 | import { KglAuto } from '../../../src/index' 2 | 3 | new KglAuto({ 4 | programs: { 5 | main: { 6 | fragmentShaderId: 'fs', 7 | uniforms: { 8 | uTime: 0, 9 | }, 10 | }, 11 | }, 12 | tick: (kgl, time) => { 13 | kgl.programs.main.uniforms.uTime = time 14 | kgl.draw() 15 | }, 16 | }) 17 | -------------------------------------------------------------------------------- /examples/kgl/3d/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/3d/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform float uTime; 4 | 5 | varying vec2 vUv; 6 | 7 | void main() { 8 | gl_FragColor = vec4(vec3(1. / length(vUv * 2. - 1.) * (sin(uTime) * 0.5 + 0.5)), 1.); 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/3d/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - 3D 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/kgl/3d/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | 4 | const kgl = new Kgl({ 5 | hasCamera: true, 6 | }) 7 | 8 | /** 9 | * program 10 | */ 11 | const plane = kgl.createProgram({ 12 | shape: 'plane', 13 | fragmentShader, 14 | uniforms: { 15 | uTime: 0, 16 | }, 17 | isAutoAdd: true, 18 | }) 19 | 20 | /** 21 | * resize 22 | */ 23 | function resize() { 24 | const size = window.innerHeight 25 | 26 | kgl.extraFar = size / 2 27 | kgl.resize() 28 | 29 | plane.scale = size 30 | } 31 | resize() 32 | window.addEventListener('resize', resize) 33 | 34 | /** 35 | * tick 36 | */ 37 | function tick(time) { 38 | time *= 0.001 39 | 40 | plane.x = Math.sin(time * 1) * 300 41 | plane.rotateY = Math.sin(time * 1) * 1 42 | plane.uniforms.uTime = time 43 | 44 | kgl.draw() 45 | 46 | requestAnimationFrame(tick) 47 | } 48 | requestAnimationFrame(tick) 49 | -------------------------------------------------------------------------------- /examples/kgl/dom-multiple/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | 11 | .wapper { 12 | position: relative; 13 | z-index: 2; 14 | padding: 20% 0; 15 | } 16 | 17 | .scroll { 18 | position: absolute; 19 | top: 2%; 20 | left: 0; 21 | right: 0; 22 | margin: auto; 23 | text-align: center; 24 | color: rgba(255, 255, 255, 0.7); 25 | } 26 | 27 | .list { 28 | display: flex; 29 | flex-direction: column; 30 | justify-content: space-between; 31 | width: 50%; 32 | min-height: 150vh; 33 | margin: 0 auto; 34 | list-style: none; 35 | } 36 | 37 | .item { 38 | align-self: flex-start; 39 | } 40 | 41 | .item:nth-child(even) { 42 | align-self: flex-end; 43 | } 44 | 45 | .item:nth-child(n + 2) { 46 | margin-top: 20%; 47 | } 48 | 49 | .link { 50 | display: block; 51 | color: rgba(255, 255, 255, 0.5); 52 | text-decoration: none; 53 | text-align: center; 54 | } 55 | 56 | .image { 57 | width: 30vw; 58 | height: auto; 59 | opacity: 0; 60 | } 61 | 62 | .title { 63 | background-color: rgba(0, 0, 0, 0.3); 64 | font-size: 0.8rem; 65 | padding: 0 0.3em; 66 | } 67 | 68 | .link:hover { 69 | color: rgba(255, 255, 255, 0.7); 70 | text-decoration: underline; 71 | } 72 | 73 | canvas { 74 | position: fixed; 75 | top: 0; 76 | left: 0; 77 | z-index: 1; 78 | width: 100%; 79 | height: 100%; 80 | } 81 | -------------------------------------------------------------------------------- /examples/kgl/dom-multiple/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolutionShape; 4 | uniform sampler2D uImage; 5 | uniform vec2 uImageResolution; 6 | uniform float uScrollDiff; 7 | 8 | varying vec2 vUv; 9 | 10 | #pragma glslify: PI = require(../../shaders/PI.glsl) 11 | #pragma glslify: fitContain = require(../../shaders/fitContain.glsl) 12 | #pragma glslify: discardOutOfRangeUv = require(../../shaders/discardOutOfRangeUv.glsl) 13 | 14 | void main() { 15 | vec2 uv = vUv; 16 | uv.y = 1. - uv.y; 17 | uv = fitContain(uv, uImageResolution, uResolutionShape); 18 | uv.y += sin(uv.x * PI) * uScrollDiff; 19 | discardOutOfRangeUv(uv); 20 | 21 | gl_FragColor = texture2D(uImage, uv); 22 | } 23 | -------------------------------------------------------------------------------- /examples/kgl/dom-multiple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Fit Multiple DOM 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

Scroll Down

15 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /examples/kgl/dom-multiple/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | import { onLoadImage } from '../../utils.js' 4 | 5 | const kgl = new Kgl({ 6 | canvas: '.canvas', 7 | hasCamera: true, 8 | isFullSize: true, 9 | }) 10 | 11 | function createImage(img) { 12 | const { width, height } = img.getBoundingClientRect() 13 | 14 | const program = kgl.createProgram({ 15 | shape: 'plane', 16 | fragmentShader, 17 | uniforms: { 18 | uImage: img, 19 | uImageResolution: [width, height], 20 | uScrollDiff: 0, 21 | }, 22 | isTransparent: true, 23 | isAutoAdd: true, 24 | data: { 25 | img, 26 | }, 27 | }) 28 | 29 | return program 30 | } 31 | 32 | /** 33 | * program 34 | */ 35 | const groupCloud = kgl.createGroup({ 36 | isAutoAdd: true, 37 | }) 38 | 39 | document.querySelectorAll('.image').forEach(async (img) => { 40 | await onLoadImage(img) 41 | const program = createImage(img) 42 | groupCloud.add(program) 43 | resizeProgram(program) 44 | }) 45 | 46 | /** 47 | * scroll 48 | */ 49 | let scrollPrev = 0 50 | let scrollDiff = 0 51 | let scrollDiffSmooth = 0 52 | let timerId 53 | function scroll() { 54 | groupCloud.y = window.scrollY 55 | 56 | scrollDiff = window.scrollY - scrollPrev 57 | scrollPrev = window.scrollY 58 | 59 | if (timerId) { 60 | clearTimeout(timerId) 61 | } 62 | timerId = setTimeout(() => { 63 | scrollDiff = 0 64 | }, 300) 65 | } 66 | scroll() 67 | window.addEventListener('scroll', scroll) 68 | 69 | /** 70 | * resize 71 | */ 72 | function resizeProgram(program) { 73 | const { width, height, top, left } = program.data.img.getBoundingClientRect() 74 | 75 | program.scale = width 76 | program.x = left - (window.innerWidth * 0.5 - width * 0.5) 77 | program.y = -( 78 | top + 79 | window.scrollY - 80 | (window.innerHeight * 0.5 - height * 0.5) 81 | ) 82 | } 83 | function resize() { 84 | kgl.resize() 85 | 86 | groupCloud.forEachProgram((program) => { 87 | resizeProgram(program) 88 | }) 89 | } 90 | resize() 91 | window.addEventListener('resize', resize) 92 | 93 | /** 94 | * tick 95 | */ 96 | function tick(time) { 97 | scrollDiffSmooth += (scrollDiff - scrollDiffSmooth) * 0.05 98 | if (Math.abs(scrollDiff - scrollDiffSmooth) < 0.01) { 99 | scrollDiffSmooth = scrollDiff 100 | } 101 | 102 | groupCloud.forEachProgram((program) => { 103 | program.uniforms.uScrollDiff = scrollDiffSmooth * 0.003 104 | }) 105 | 106 | kgl.draw() 107 | 108 | requestAnimationFrame(tick) 109 | } 110 | requestAnimationFrame(tick) 111 | -------------------------------------------------------------------------------- /examples/kgl/dom/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | 11 | .wapper { 12 | position: relative; 13 | z-index: 2; 14 | height: 100%; 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | } 19 | 20 | .link { 21 | display: block; 22 | color: rgba(255, 255, 255, 0.5); 23 | text-decoration: none; 24 | text-align: center; 25 | } 26 | 27 | .image { 28 | width: 50vw; 29 | height: auto; 30 | opacity: 0; 31 | } 32 | 33 | .title { 34 | background-color: rgba(0, 0, 0, 0.3); 35 | font-size: 0.8rem; 36 | padding: 0 0.3em; 37 | } 38 | 39 | .link:hover { 40 | color: rgba(255, 255, 255, 0.7); 41 | text-decoration: underline; 42 | } 43 | 44 | canvas { 45 | position: fixed; 46 | top: 0; 47 | left: 0; 48 | z-index: 1; 49 | width: 100%; 50 | height: 100%; 51 | } 52 | -------------------------------------------------------------------------------- /examples/kgl/dom/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform sampler2D uImage; 4 | uniform float uTime; 5 | 6 | varying vec2 vUv; 7 | 8 | void main() { 9 | vec2 uv = vUv; 10 | uv.y = 1. - uv.y; 11 | vec4 color = texture2D(uImage, uv); 12 | color.rgb *= mix(0.2, 2.5, sin(uTime) * 0.5 + 0.5); 13 | gl_FragColor = color; 14 | } 15 | -------------------------------------------------------------------------------- /examples/kgl/dom/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Fit DOM 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 18 |

Photo by Anton Maksimov 5642.su
on Unsplash

19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/kgl/dom/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | import { onLoadImage } from '../../utils.js' 4 | 5 | const kgl = new Kgl({ 6 | canvas: '.canvas', 7 | hasCamera: true, 8 | isFullSize: true, 9 | }) 10 | 11 | async function main() { 12 | /** 13 | * program 14 | */ 15 | const img = await onLoadImage(document.querySelector('.image')) 16 | 17 | const program = kgl.createProgram({ 18 | shape: 'plane', 19 | fragmentShader, 20 | uniforms: { 21 | uImage: img, 22 | uTime: 0, 23 | }, 24 | isTransparent: true, 25 | isAutoAdd: true, 26 | }) 27 | 28 | /** 29 | * resize 30 | */ 31 | function resize() { 32 | kgl.resize() 33 | 34 | const { width, height, top, left } = img.getBoundingClientRect() 35 | 36 | program.scale2d = [width, height] 37 | program.x = left - (window.innerWidth * 0.5 - width * 0.5) 38 | program.y = -( 39 | top + 40 | window.scrollY - 41 | (window.innerHeight * 0.5 - height * 0.5) 42 | ) 43 | } 44 | resize() 45 | window.addEventListener('resize', resize) 46 | 47 | /** 48 | * tick 49 | */ 50 | function tick(time) { 51 | time *= 0.001 52 | 53 | program.uniforms.uTime = time 54 | 55 | kgl.draw() 56 | 57 | requestAnimationFrame(tick) 58 | } 59 | requestAnimationFrame(tick) 60 | } 61 | main() 62 | -------------------------------------------------------------------------------- /examples/kgl/godray/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | } 9 | -------------------------------------------------------------------------------- /examples/kgl/godray/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - God Ray 7 | 8 | 9 | 10 | 11 | 12 | 13 | Photo 14 | by Sasha Freemind on Unsplash 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/kgl/godray/index.js: -------------------------------------------------------------------------------- 1 | import { KglEffect, Godray } from '../../../src/index' 2 | import fragmentShader from './mask.frag' 3 | import { loadImage, mix } from '../../utils.js' 4 | 5 | const image = 6 | 'https://images.unsplash.com/photo-1534330207526-8e81f10ec6fc?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ' // https://unsplash.com/photos/Pv5WeEyxMWU 7 | const speed = 0.5 8 | const strength = 12 9 | const maxRadius = window.innerWidth < 768 ? 0.4 : 0.8 10 | const minRadius = 0.1 11 | 12 | const kgl = new KglEffect() 13 | 14 | async function main() { 15 | const img = await loadImage(image, true) 16 | 17 | const mask = kgl.createProgram({ 18 | fragmentShader, 19 | uniforms: { 20 | uImage: img, 21 | uImageResolution: [img.width, img.height], 22 | }, 23 | isAutoAdd: true, 24 | }) 25 | 26 | ;['mask', 'cache', 'output'].forEach((name) => { 27 | kgl.createFramebuffer(name) 28 | }) 29 | 30 | const godray = kgl.createEffect(Godray) 31 | 32 | /** 33 | * resize 34 | */ 35 | function resize() { 36 | kgl.resize() 37 | } 38 | resize() 39 | window.addEventListener('resize', resize) 40 | 41 | /** 42 | * tick 43 | */ 44 | function tick(time) { 45 | const cTime = Math.sin(time * 0.001 * speed) * 0.5 + 0.5 46 | const halfTime = -Math.abs(cTime * 2 - 1) + 1 47 | 48 | kgl.bindFramebuffer('mask') 49 | mask.draw() 50 | 51 | godray.drawEffect( 52 | 'mask', 53 | 'cache', 54 | 'output', 55 | strength, 56 | [mix(kgl.canvas.width, 0, cTime), kgl.canvas.height * 0.5], 57 | mix(maxRadius, minRadius, halfTime), 58 | true 59 | ) 60 | 61 | requestAnimationFrame(tick) 62 | } 63 | requestAnimationFrame(tick) 64 | } 65 | main() 66 | -------------------------------------------------------------------------------- /examples/kgl/godray/mask.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; 4 | uniform sampler2D uImage; 5 | uniform vec2 uImageResolution; 6 | 7 | #pragma glslify: fitCover = require(../../shaders/fitCover.glsl) 8 | 9 | void main() { 10 | vec2 uv = gl_FragCoord.st / uResolution; 11 | uv.y = 1. - uv.y; 12 | uv = fitCover(uv, uImageResolution, uResolution); 13 | 14 | gl_FragColor = texture2D(uImage, uv); 15 | } 16 | -------------------------------------------------------------------------------- /examples/kgl/group/cross.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | const vec3 color = vec3(181. / 255., 174. / 255., 161. / 255.); 4 | 5 | void main() { 6 | gl_FragColor = vec4(color, 1.); 7 | } 8 | -------------------------------------------------------------------------------- /examples/kgl/group/full.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform float uTime; 4 | 5 | const vec3 color = vec3(181. / 255., 174. / 255., 161. / 255.); 6 | 7 | void main() { 8 | gl_FragColor = vec4(color * mix(1.1, 1.5, sin(uTime) * 0.5 + 0.5), 1.); 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/group/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/group/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform float uTime; 4 | 5 | varying vec2 vUv; 6 | 7 | void main() { 8 | float alpha = 1. - min(max(1. / length(vUv * 2. - 1.) * (sin(uTime) * 0.5 + 0.5), 0.), 1.); 9 | gl_FragColor = vec4(vec3(0.), alpha); 10 | } 11 | -------------------------------------------------------------------------------- /examples/kgl/group/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Group 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/kgl/group/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | import fragmentShaderCross from './cross.frag' 4 | import fragmentShaderFull from './full.frag' 5 | 6 | const kgl = new Kgl({ 7 | hasCamera: true, 8 | isFullSize: true, 9 | }) 10 | const { root } = kgl // root group 11 | 12 | /** 13 | * program 14 | */ 15 | 16 | const full = kgl.createProgram({ 17 | fragmentShader: fragmentShaderFull, 18 | uniforms: { 19 | uTime: 0, 20 | }, 21 | isAutoAdd: true, 22 | }) 23 | 24 | /* group cross */ 25 | const groupCross = kgl.createGroup({ 26 | isAutoAdd: true, // add to kgl.root 27 | }) 28 | 29 | /* cross1 */ 30 | const cross1 = kgl.createProgram({ 31 | shape: 'plane', 32 | width: 200, 33 | height: 50, 34 | fragmentShader: fragmentShaderCross, 35 | }) 36 | groupCross.add(cross1) 37 | 38 | /* cross2 */ 39 | const cross2 = kgl.createProgram({ 40 | shape: 'plane', 41 | width: 50, 42 | height: 200, 43 | fragmentShader: fragmentShaderCross, 44 | }) 45 | groupCross.add(cross2) 46 | 47 | /* plane1 */ 48 | const size = 500 49 | const plane1 = kgl.createProgram({ 50 | shape: 'plane', 51 | width: size, 52 | height: size, 53 | fragmentShader, 54 | uniforms: { 55 | uTime: 0, 56 | }, 57 | isTransparent: true, 58 | }) 59 | kgl.add(plane1) // add to kgl.root 60 | 61 | /* plane2 */ 62 | const size2 = 100 63 | const plane2 = kgl.createProgram({ 64 | shape: 'plane', 65 | width: size2, 66 | height: size2, 67 | fragmentShader, 68 | uniforms: { 69 | uTime: 0, 70 | }, 71 | isTransparent: true, 72 | }) 73 | kgl.add(plane2) // add to kgl.root 74 | 75 | kgl.extraFar = size / 2 76 | 77 | /** 78 | * resize 79 | */ 80 | function resize() { 81 | kgl.resize() 82 | } 83 | resize() 84 | window.addEventListener('resize', resize) 85 | 86 | /** 87 | * tick 88 | */ 89 | function tick(time) { 90 | time *= 0.001 91 | 92 | // kgl.cameraPosition[1] = Math.sin(time * 0.5) * 300 93 | // kgl.cameraRotation[1] = Math.sin(time * 0.1) 94 | // kgl.updateCamera() 95 | 96 | full.uniforms.uTime = time 97 | 98 | root.x = -Math.sin(time * 0.5) * 500 99 | 100 | plane1.x = Math.sin(time * 1) * 300 101 | plane1.scale = 1 - ((Math.sin(time * 2) + 1) / 2) * 0.5 102 | plane1.rotateY = Math.sin(time * 1) * 1 103 | plane1.uniforms.uTime = time 104 | 105 | plane2.y = Math.sin(time * 1) * 300 106 | plane2.rotateX = Math.sin(time * 1) * 1 107 | plane2.uniforms.uTime = time 108 | 109 | groupCross.rotate = time * 3 110 | cross2.x = -Math.sin(time * 5) * 100 111 | 112 | kgl.draw() 113 | 114 | requestAnimationFrame(tick) 115 | } 116 | requestAnimationFrame(tick) 117 | 118 | /** 119 | * add, remove 120 | */ 121 | // let isExistPlane1 = true 122 | // setInterval(() => { 123 | // if (isExistPlane1) { 124 | // kgl.remove(plane1) 125 | // isExistPlane1 = false 126 | // } else { 127 | // kgl.add(plane1) 128 | // isExistPlane1 = true 129 | // } 130 | // }, 1000) 131 | -------------------------------------------------------------------------------- /examples/kgl/image/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/image/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; 4 | uniform sampler2D uImage; 5 | uniform vec2 uImageResolution; 6 | uniform float uTime; 7 | 8 | const float pSpeed = 1.5; 9 | 10 | #pragma glslify: PI = require(../../shaders/PI.glsl) 11 | #pragma glslify: fitCover = require(../../shaders/fitCover.glsl) 12 | #pragma glslify: getZoomedUv = require(../../shaders/getZoomedUv.glsl) 13 | 14 | void main() { 15 | vec2 uv = gl_FragCoord.st / uResolution; 16 | uv.y = 1. - uv.y; 17 | uv = fitCover(uv, uImageResolution, uResolution); 18 | 19 | vec2 uvCenter = uv * 2. - 1.; 20 | float distortion = min(max(1. / length(uvCenter) * (sin(uTime * pSpeed - PI * 0.5) * 0.5 + 0.5), 0.), 1.); 21 | distortion = smoothstep(0.6, 0.8, distortion) * smoothstep(1., 0.8, distortion); 22 | 23 | vec2 zoomedUv = getZoomedUv(uv, 0.8, vec2(0.)); 24 | 25 | gl_FragColor = texture2D(uImage, mix(uv, zoomedUv, distortion)); 26 | // gl_FragColor = vec4(vec3(distortion), 1.); 27 | } 28 | -------------------------------------------------------------------------------- /examples/kgl/image/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Image 7 | 8 | 9 | 10 | 11 | 12 | 13 | Photo 14 | by FLY:D on Unsplash 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/kgl/image/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | import { loadImage } from '../../utils.js' 4 | 5 | const image = 6 | 'https://images.unsplash.com/photo-1631372126726-edb028823784?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ' // https://unsplash.com/photos/TfntmeQaK6Q 7 | 8 | const kgl = new Kgl() 9 | 10 | async function main() { 11 | /** 12 | * program 13 | */ 14 | const img = await loadImage(image, true) 15 | 16 | const program = kgl.createProgram({ 17 | fragmentShader, 18 | uniforms: { 19 | uImage: img, 20 | uImageResolution: [img.width, img.height], 21 | uTime: 0, 22 | }, 23 | isAutoAdd: true, 24 | }) 25 | 26 | /** 27 | * resize 28 | */ 29 | function resize() { 30 | kgl.resize() 31 | } 32 | resize() 33 | window.addEventListener('resize', resize) 34 | 35 | /** 36 | * tick 37 | */ 38 | function tick(time) { 39 | time *= 0.001 40 | 41 | program.uniforms.uTime = time 42 | 43 | kgl.draw() 44 | 45 | requestAnimationFrame(tick) 46 | } 47 | requestAnimationFrame(tick) 48 | } 49 | main() 50 | -------------------------------------------------------------------------------- /examples/kgl/instancing/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | } 9 | -------------------------------------------------------------------------------- /examples/kgl/instancing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Instancing 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/kgl/instancing/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import resetVelocityFrag from './shaders/reset-velocity.frag' 3 | import resetPositionFrag from './shaders/reset-position.frag' 4 | import velocityFrag from './shaders/velocity.frag' 5 | import positionFrag from './shaders/position.frag' 6 | import mainVert from './shaders/main.vert' 7 | import mainFrag from './shaders/main.frag' 8 | 9 | const width = 100 10 | const height = 100 11 | 12 | const sizeUniform = [width, height] 13 | const particleUv = [] 14 | 15 | for (let i = 0; i < width; i++) { 16 | for (let j = 0; j < height; j++) { 17 | particleUv.push(i / (width - 1), 1 - j / (height - 1)) 18 | } 19 | } 20 | 21 | /** 22 | * generate KGL 23 | */ 24 | const kgl = new Kgl({ 25 | clearedColor: [0, 0, 0, 1], 26 | hasCamera: true, 27 | hasLight: true, 28 | cameraPosition: [0, 0, 480], 29 | fov: 50, 30 | }) 31 | 32 | /** 33 | * program 34 | */ 35 | const programResetVelocity = kgl.createProgram({ 36 | fragmentShader: resetVelocityFrag, 37 | isFloats: true, 38 | }) 39 | 40 | const programResetPosition = kgl.createProgram({ 41 | fragmentShader: resetPositionFrag, 42 | uniforms: { 43 | uSize: sizeUniform, 44 | }, 45 | isFloats: true, 46 | }) 47 | 48 | const programVelocity = kgl.createProgram({ 49 | fragmentShader: velocityFrag, 50 | uniforms: { 51 | uSize: sizeUniform, 52 | uPrevVelocityTexture: 'framebuffer', 53 | uPrevPositionTexture: 'framebuffer', 54 | }, 55 | isFloats: true, 56 | }) 57 | 58 | const programPosition = kgl.createProgram({ 59 | fragmentShader: positionFrag, 60 | uniforms: { 61 | uSize: sizeUniform, 62 | uPrevPositionTexture: 'framebuffer', 63 | uVelocityTexture: 'framebuffer', 64 | }, 65 | isFloats: true, 66 | }) 67 | 68 | const programMain = kgl.createProgram({ 69 | shape: 'cube', 70 | // shape: 'plane', 71 | vertexShader: mainVert, 72 | fragmentShader: mainFrag, 73 | instancedAttributes: { 74 | aInstancedUv: { 75 | value: particleUv, 76 | size: 2, 77 | }, 78 | }, 79 | uniforms: { 80 | uPositionTexture: 'framebuffer', 81 | uVelocityTexture: 'framebuffer', 82 | uTime: 0, 83 | }, 84 | isDepth: true, 85 | isTransparent: true, 86 | isAutoAdd: true, 87 | }) 88 | 89 | /** 90 | * framebuffer (float) 91 | */ 92 | ;['velocity0', 'velocity1', 'position0', 'position1'].forEach((key) => { 93 | kgl.createFramebufferFloat(key, width, height) 94 | }) 95 | 96 | /** 97 | * resize 98 | */ 99 | function resize() { 100 | kgl.resize() 101 | } 102 | resize() 103 | window.addEventListener('resize', resize) 104 | 105 | /** 106 | * reset framebuffer 107 | */ 108 | let loopCount = 0 109 | let targetBufferIndex = loopCount++ % 2 110 | let prevBufferIndex 111 | 112 | kgl.bindFramebuffer(`velocity${targetBufferIndex}`) 113 | programResetVelocity.draw() 114 | 115 | kgl.bindFramebuffer(`position${targetBufferIndex}`) 116 | programResetPosition.draw() 117 | 118 | /** 119 | * tick 120 | */ 121 | function tick(time) { 122 | time *= 0.001 123 | 124 | prevBufferIndex = targetBufferIndex 125 | targetBufferIndex = loopCount++ % 2 126 | 127 | const prevVelocityTexture = `velocity${prevBufferIndex}` 128 | const prevPositionTexture = `position${prevBufferIndex}` 129 | const velocityTexture = `velocity${targetBufferIndex}` 130 | const positionTexture = `position${targetBufferIndex}` 131 | 132 | kgl.bindFramebuffer(velocityTexture) 133 | 134 | programVelocity.updateUniforms({ 135 | uPrevVelocityTexture: prevVelocityTexture, 136 | uPrevPositionTexture: prevPositionTexture, 137 | }) 138 | programVelocity.draw() 139 | 140 | kgl.bindFramebuffer(positionTexture) 141 | 142 | programPosition.updateUniforms({ 143 | uPrevPositionTexture: prevPositionTexture, 144 | uVelocityTexture: velocityTexture, 145 | }) 146 | programPosition.draw() 147 | 148 | kgl.unbindFramebuffer() 149 | kgl.clear() 150 | 151 | programMain.updateUniforms({ 152 | uPositionTexture: positionTexture, 153 | uVelocityTexture: velocityTexture, 154 | uTime: time, 155 | }) 156 | programMain.draw() 157 | 158 | requestAnimationFrame(tick) 159 | } 160 | requestAnimationFrame(tick) 161 | -------------------------------------------------------------------------------- /examples/kgl/instancing/shaders/main.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | varying vec2 vUv; 4 | varying vec4 vColor; 5 | 6 | void main () { 7 | gl_FragColor = vColor; 8 | } 9 | -------------------------------------------------------------------------------- /examples/kgl/instancing/shaders/main.vert: -------------------------------------------------------------------------------- 1 | attribute vec3 aPosition; 2 | attribute vec2 aUv; 3 | attribute vec3 aNormal; 4 | attribute vec2 aInstancedUv; 5 | 6 | uniform sampler2D uPositionTexture; 7 | uniform sampler2D uVelocityTexture; 8 | uniform mat4 uMvpMatrix; 9 | uniform mat4 uInvMatrix; 10 | uniform vec3 uLightDirection; 11 | uniform vec3 uAmbientColor; 12 | uniform vec3 uEyeDirection; 13 | uniform float uTime; 14 | 15 | varying vec2 vUv; 16 | varying vec4 vColor; 17 | 18 | #pragma glslify: rotateQ = require(glsl-y-rotate/rotateQ) 19 | #pragma glslify: random = require(glsl-random) 20 | #pragma glslify: hsv = require(../../../shaders/hsv.glsl) 21 | #pragma glslify: PI = require(../../../shaders/PI.glsl) 22 | 23 | const float PI2 = PI * 2.; 24 | const float colorInterval = PI2 * 10.; 25 | const float scale = 2.; 26 | const float maxScaleRate = 1.4; 27 | const float rotationSpeed = 100.; 28 | const float minRotationSpeed = 0.1; 29 | 30 | void main () { 31 | vec3 modelPosition = aPosition; 32 | vec4 instancedPosition = texture2D(uPositionTexture, aInstancedUv); 33 | float randomValue = instancedPosition.w; 34 | 35 | float velocity = texture2D(uVelocityTexture, aInstancedUv).w; 36 | float life = smoothstep(0.01, 0.04, velocity); 37 | 38 | float cScale = scale; 39 | cScale *= life; 40 | cScale *= mix(1., maxScaleRate, (instancedPosition.z - 1.) * 0.01); 41 | modelPosition *= cScale; 42 | 43 | vec3 axis = normalize(vec3( 44 | random(vec2(randomValue, 0.)), 45 | random(vec2(0., randomValue)), 46 | random(vec2(randomValue, 1.)) 47 | )); 48 | float radian = PI2 * random(vec2(randomValue)); 49 | radian += velocity * mix(minRotationSpeed, rotationSpeed, randomValue); 50 | mat3 rotate = rotateQ(axis, radian); 51 | modelPosition *= rotate; 52 | 53 | vec3 cNormal = normalize(aNormal); 54 | cNormal *= rotate; 55 | vec3 invLight = normalize(uInvMatrix * vec4(uLightDirection, 0.)).rgb; 56 | vec3 invEye = normalize(uInvMatrix * vec4(uEyeDirection, 0.)).rgb; 57 | vec3 halfLE = normalize(invLight + invEye); 58 | float diffuse = clamp(dot(cNormal, invLight), 0.1, 1.); 59 | float specular = pow(clamp(dot(cNormal, halfLE), 0., 1.), 50.); 60 | 61 | vUv = aUv; 62 | 63 | float colorNTime = mod(uTime, colorInterval) / colorInterval; 64 | float alpha = 1.; 65 | vColor = vec4(hsv(colorNTime * PI2, 0.25 + 0.7 * colorNTime, 0.85 + 0.1 * colorNTime), alpha); 66 | vColor.rgb *= vec3(diffuse + specular); 67 | vColor.rgb += uAmbientColor; 68 | vColor.rgb *= mix(0.2, 1., clamp(((instancedPosition + 100.) / 200.).z, 0., 1.)); 69 | vColor.rgb *= life; 70 | 71 | gl_Position = uMvpMatrix * (vec4(modelPosition + instancedPosition.xyz, 1.)); 72 | } 73 | -------------------------------------------------------------------------------- /examples/kgl/instancing/shaders/position.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uSize; 4 | uniform sampler2D uPrevPositionTexture; 5 | uniform sampler2D uVelocityTexture; 6 | 7 | void main () { 8 | vec2 uv = gl_FragCoord.st / uSize; 9 | vec4 prevPosition = texture2D(uPrevPositionTexture, uv); 10 | vec4 velocity = texture2D(uVelocityTexture, uv); 11 | 12 | vec3 position; 13 | if (velocity.w == 1.) { 14 | vec2 nPosition = uv * 2. - 1.; 15 | position = vec3(nPosition * uSize, 0.); 16 | } else { 17 | position = prevPosition.xyz + velocity.xyz; 18 | } 19 | 20 | gl_FragColor = vec4(position, prevPosition.w); 21 | } 22 | -------------------------------------------------------------------------------- /examples/kgl/instancing/shaders/reset-position.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uSize; 4 | 5 | #pragma glslify: random = require(glsl-random) 6 | 7 | void main () { 8 | vec2 nPosition = gl_FragCoord.st / uSize * 2. - 1.; 9 | vec4 position = vec4( 10 | nPosition * uSize, 11 | 0., 12 | random(nPosition) 13 | ); 14 | gl_FragColor = position; 15 | } 16 | -------------------------------------------------------------------------------- /examples/kgl/instancing/shaders/reset-velocity.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | void main () { 4 | gl_FragColor = vec4(vec3(0.), 1.); 5 | } 6 | -------------------------------------------------------------------------------- /examples/kgl/instancing/shaders/velocity.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uSize; 4 | uniform sampler2D uPrevVelocityTexture; 5 | uniform sampler2D uPrevPositionTexture; 6 | 7 | #pragma glslify: curlNoise = require(glsl-curl-noise) 8 | 9 | const float speed = 2.; 10 | const float density = 0.007; 11 | const float ease = 0.02; 12 | 13 | void main () { 14 | vec2 uv = gl_FragCoord.st / uSize; 15 | vec4 velocity = texture2D(uPrevVelocityTexture, uv); 16 | vec3 prevPosition = texture2D(uPrevPositionTexture, uv).xyz; 17 | velocity.xyz += curlNoise(prevPosition * density) * speed; 18 | velocity.xyz *= velocity.w; 19 | if (velocity.w > 0.01) { 20 | velocity.w -= velocity.w * ease; 21 | } else { 22 | velocity.w = 1.; 23 | } 24 | gl_FragColor = velocity; 25 | } 26 | -------------------------------------------------------------------------------- /examples/kgl/point/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/point/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform float uTime; 4 | 5 | varying float vRandom; 6 | 7 | void main() { 8 | vec2 uv = gl_PointCoord; 9 | gl_FragColor = vec4( 10 | smoothstep(0.97, 1., 1. / length(uv * 2. - 1.) * mix(0.1, 1., sin(uTime * vRandom) * 0.5 + 0.5)) 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/kgl/point/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Point 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/kgl/point/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import vertexShader from './index.vert' 3 | import fragmentShader from './index.frag' 4 | 5 | const kgl = new Kgl({ 6 | hasCamera: true, 7 | }) 8 | 9 | /** 10 | * program 11 | */ 12 | const halfSize = 100 13 | const points = kgl.createProgram({ 14 | shape: 'point', 15 | attributes: { 16 | aPosition: { 17 | value: [ 18 | -halfSize, 19 | halfSize, 20 | 0, 21 | -halfSize, 22 | -halfSize, 23 | 0, 24 | halfSize, 25 | halfSize, 26 | 0, 27 | halfSize, 28 | -halfSize, 29 | 0, 30 | ], 31 | size: 3, 32 | }, 33 | aRandom: { 34 | value: [Math.random(), Math.random(), Math.random(), Math.random()], 35 | size: 1, 36 | }, 37 | }, 38 | vertexShader, 39 | fragmentShader, 40 | uniforms: { 41 | uTime: 0, 42 | }, 43 | isAutoAdd: true, 44 | }) 45 | 46 | /** 47 | * resize 48 | */ 49 | function resize() { 50 | kgl.resize() 51 | } 52 | resize() 53 | window.addEventListener('resize', resize) 54 | 55 | /** 56 | * tick 57 | */ 58 | function tick(time) { 59 | time *= 0.001 60 | 61 | // points.x = Math.sin(time * 1) * 100 62 | points.uniforms.uTime = time * 2 63 | 64 | kgl.draw() 65 | 66 | requestAnimationFrame(tick) 67 | } 68 | requestAnimationFrame(tick) 69 | -------------------------------------------------------------------------------- /examples/kgl/point/index.vert: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | attribute vec3 aPosition; 4 | attribute float aRandom; 5 | 6 | uniform mat4 uMvpMatrix; 7 | uniform float uPixelRatio; 8 | uniform float uTime; 9 | 10 | varying float vRandom; 11 | 12 | void main () { 13 | vRandom = aRandom; 14 | 15 | vec3 position = aPosition; 16 | float time = uTime * aRandom; 17 | position.xy += vec2(cos(time), sin(time)) * 30.; 18 | 19 | gl_Position = uMvpMatrix * vec4(position, 1.); 20 | gl_PointSize = uPixelRatio * mix(16., 32., aRandom); 21 | } 22 | -------------------------------------------------------------------------------- /examples/kgl/simple/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/simple/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; // window size (auto added) 4 | uniform float uTime; 5 | 6 | void main() { 7 | float color = max(1. - length(gl_FragCoord.xy / uResolution) * (sin(uTime) * 0.5 + 0.5), 0.); 8 | gl_FragColor = vec4(vec3(color), 1.); 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Simple 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/kgl/simple/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | 4 | const kgl = new Kgl() 5 | 6 | /** 7 | * program 8 | */ 9 | const program = kgl.createProgram({ 10 | fragmentShader, 11 | uniforms: { 12 | uTime: 0, 13 | }, 14 | isAutoAdd: true, 15 | }) 16 | 17 | /** 18 | * resize 19 | */ 20 | function resize() { 21 | kgl.resize() 22 | } 23 | resize() 24 | window.addEventListener('resize', resize) 25 | 26 | /** 27 | * tick 28 | */ 29 | function tick(time) { 30 | program.uniforms.uTime = time * 0.001 31 | 32 | kgl.draw() 33 | 34 | requestAnimationFrame(tick) 35 | } 36 | requestAnimationFrame(tick) 37 | -------------------------------------------------------------------------------- /examples/kgl/transparent-images/1-white-clouds-png-image_400x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ko-yelie/kgl/746f039b018192e5e78574ff933ce0ded15805cc/examples/kgl/transparent-images/1-white-clouds-png-image_400x400.png -------------------------------------------------------------------------------- /examples/kgl/transparent-images/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | background-color: #494e57; 9 | } 10 | -------------------------------------------------------------------------------- /examples/kgl/transparent-images/index.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform sampler2D uImage; 4 | 5 | varying vec2 vUv; 6 | 7 | void main() { 8 | vec2 uv = vUv; 9 | uv.y = 1. - uv.y; 10 | 11 | gl_FragColor = texture2D(uImage, uv); 12 | } 13 | -------------------------------------------------------------------------------- /examples/kgl/transparent-images/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | KGL Library Examples - Transparent Images 7 | 8 | 9 | 10 | 11 | 12 | 13 | White Clouds Png Image FreePNGImg.com 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/kgl/transparent-images/index.js: -------------------------------------------------------------------------------- 1 | import Kgl from '../../../src/index' 2 | import fragmentShader from './index.frag' 3 | import { loadImage } from '../../utils.js' 4 | import image from './1-white-clouds-png-image_400x400.png' 5 | 6 | const kgl = new Kgl({ 7 | hasCamera: true, 8 | isFullSize: true, 9 | }) 10 | 11 | function createCloud(img) { 12 | const randomScale = Math.random() * 2 13 | 14 | const program = kgl.createProgram({ 15 | shape: 'plane', 16 | fragmentShader, 17 | uniforms: { 18 | uImage: img, 19 | }, 20 | isTransparent: true, 21 | isAutoAdd: true, 22 | width: img.width, 23 | height: img.height, 24 | x: (Math.random() * 2 - 1) * window.innerWidth * 0.5, 25 | y: (Math.random() * 2 - 1) * window.innerHeight * 0.5, 26 | // z: randomScale * kgl.cameraPosition[2] * 0.3, 27 | scale: 1 + randomScale, 28 | }) 29 | 30 | return program 31 | } 32 | 33 | async function main() { 34 | /** 35 | * program 36 | */ 37 | const groupCloud = kgl.createGroup({ 38 | isAutoAdd: true, 39 | }) 40 | 41 | const img = await loadImage(image) 42 | 43 | for (let i = 0; i < 10; i++) { 44 | const program = createCloud(img) 45 | groupCloud.add(program) 46 | } 47 | 48 | /** 49 | * resize 50 | */ 51 | function resize() { 52 | kgl.resize() 53 | } 54 | resize() 55 | window.addEventListener('resize', resize) 56 | 57 | /** 58 | * tick 59 | */ 60 | function tick(time) { 61 | groupCloud.forEachProgram((program) => { 62 | program.x += 1 * program.scale 63 | 64 | const xMax = window.innerWidth * 0.5 + program.width * program.scale * 0.5 65 | if (program.x > xMax) { 66 | program.x = -xMax 67 | } 68 | }) 69 | 70 | kgl.draw() 71 | 72 | requestAnimationFrame(tick) 73 | } 74 | requestAnimationFrame(tick) 75 | } 76 | main() 77 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ko-yelie/kgl-example", 3 | "private": true, 4 | "scripts": { 5 | "dev": "parcel index.html", 6 | "build": "parcel build index.html --no-source-maps --out-dir ../docs --public-url /kgl/", 7 | "pages": "rm -rf ../docs && npm run build" 8 | }, 9 | "devDependencies": { 10 | "@babel/core": "^7.17.10", 11 | "@babel/plugin-transform-runtime": "^7.17.10", 12 | "parcel-bundler": "^1.12.5", 13 | "stylus": "^0.57.0" 14 | }, 15 | "dependencies": { 16 | "glsl-curl-noise": "0.0.4", 17 | "glsl-random": "0.0.5", 18 | "glsl-y-rotate": "^3.0.0" 19 | }, 20 | "volta": { 21 | "node": "14.21.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/shaders/PI.glsl: -------------------------------------------------------------------------------- 1 | const float PI = 3.1415926; 2 | 3 | #pragma glslify: export(PI) 4 | -------------------------------------------------------------------------------- /examples/shaders/discardOutOfRangeUv.glsl: -------------------------------------------------------------------------------- 1 | void discardOutOfRangeUv(vec2 uv) { 2 | if (uv.x < 0. || uv.x > 1. || uv.y < 0. || uv.y > 1.) discard; 3 | } 4 | 5 | #pragma glslify: export(discardOutOfRangeUv) 6 | -------------------------------------------------------------------------------- /examples/shaders/fitContain.glsl: -------------------------------------------------------------------------------- 1 | vec2 fitContain(vec2 coord, vec2 inputResolution, vec2 outputResolution) { 2 | vec2 ratio = vec2( 3 | max((outputResolution.x / outputResolution.y) / (inputResolution.x / inputResolution.y), 1.0), 4 | max((outputResolution.y / outputResolution.x) / (inputResolution.y / inputResolution.x), 1.0) 5 | ); 6 | return coord * ratio + (1. - ratio) * 0.5; 7 | } 8 | 9 | #pragma glslify: export(fitContain) 10 | -------------------------------------------------------------------------------- /examples/shaders/fitCover.glsl: -------------------------------------------------------------------------------- 1 | vec2 fitCover(vec2 uv, vec2 inputResolution, vec2 outputResolution) { 2 | vec2 ratio = vec2( 3 | min((outputResolution.x / outputResolution.y) / (inputResolution.x / inputResolution.y), 1.), 4 | min((outputResolution.y / outputResolution.x) / (inputResolution.y / inputResolution.x), 1.) 5 | ); 6 | return uv * ratio + (1. - ratio) * 0.5; 7 | } 8 | 9 | #pragma glslify: export(fitCover) 10 | -------------------------------------------------------------------------------- /examples/shaders/getZoomedUv.glsl: -------------------------------------------------------------------------------- 1 | vec2 getZoomedUv(vec2 uv, float zoom, vec2 origin) { 2 | origin.x = -origin.x; 3 | uv += origin; 4 | float scale = 1. / zoom; 5 | return uv * scale - 0.5 * (scale - 1.); 6 | } 7 | 8 | #pragma glslify: export(getZoomedUv) 9 | -------------------------------------------------------------------------------- /examples/shaders/hsv.glsl: -------------------------------------------------------------------------------- 1 | vec3 hsv(float h, float s, float v) { 2 | vec4 t = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 3 | vec3 p = abs(fract(vec3(h) + t.xyz) * 6.0 - vec3(t.w)); 4 | return v * mix(vec3(t.x), clamp(p - vec3(t.x), 0.0, 1.0), s); 5 | } 6 | 7 | #pragma glslify: export(hsv) 8 | -------------------------------------------------------------------------------- /examples/utils.js: -------------------------------------------------------------------------------- 1 | export function onLoadImage(el) { 2 | return new Promise((resolve) => { 3 | if (el.complete) { 4 | resolve(el) 5 | } else { 6 | el.addEventListener('load', () => { 7 | resolve(el) 8 | }) 9 | } 10 | }) 11 | } 12 | 13 | const cacheLoadImage = {} 14 | 15 | export function loadImage(src, isCrossOrigin) { 16 | const isArray = typeof src === 'object' && src.constructor.name === 'Array' 17 | const promises = [] 18 | ;(isArray ? src : [src]).forEach((srcString) => { 19 | const cache = cacheLoadImage[srcString] 20 | if (cache) { 21 | promises.push(Promise.resolve(cache)) 22 | return 23 | } 24 | const img = document.createElement('img') 25 | if (isCrossOrigin) img.crossOrigin = 'anonymous' 26 | img.src = srcString 27 | const promiseLoad = onLoadImage(img) 28 | promiseLoad.then(() => { 29 | cacheLoadImage[srcString] = img 30 | }) 31 | promises.push(promiseLoad) 32 | }) 33 | return isArray ? Promise.all(promises) : promises[0] 34 | } 35 | 36 | export function mix(x, y, a) { 37 | return x * (1 - a) + y * a 38 | } 39 | -------------------------------------------------------------------------------- /examples/variables.styl: -------------------------------------------------------------------------------- 1 | margin-window = 0.5rem 2 | font-family = -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif 3 | color-text = rgba(#fff, 0.7) 4 | color-link = rgba(#fff, 0.5) 5 | background-color = rgba(#000, 0.3) 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ko-yelie/kgl", 3 | "moduleName": "kgl", 4 | "version": "0.6.2", 5 | "description": "Minimal WebGL library", 6 | "main": "dist/index.es.js", 7 | "types": "types/index.d.ts", 8 | "unpkg": "dist/index.iife.min.js", 9 | "files": [ 10 | "dist", 11 | "types" 12 | ], 13 | "scripts": { 14 | "build": "rm -rf dist && bili", 15 | "types": "tsc --build tsconfig.types.json", 16 | "publish": "npm run build && npm run types && npm publish", 17 | "docs": "typedoc ./src/index.ts --out docs/api", 18 | "dev": "npm run dev --prefix examples", 19 | "pages": "npm run pages --prefix examples && npm run docs" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/ko-yelie/kgl.git" 24 | }, 25 | "keywords": [], 26 | "author": "Ko.Yelie", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/ko-yelie/kgl/issues" 30 | }, 31 | "homepage": "https://ko-yelie.github.io/kgl/", 32 | "devDependencies": { 33 | "bili": "^5.0.5", 34 | "eslint": "^8.15.0", 35 | "eslint-config-prettier": "^8.5.0", 36 | "eslint-config-standard": "^17.0.0", 37 | "eslint-plugin-import": "^2.26.0", 38 | "eslint-plugin-node": "^11.1.0", 39 | "eslint-plugin-prettier": "^4.0.0", 40 | "eslint-plugin-promise": "^6.0.0", 41 | "prettier": "^2.6.2", 42 | "rollup-plugin-glslify": "^1.2.1", 43 | "rollup-plugin-typescript2": "^0.31.1", 44 | "typedoc": "^0.22.17", 45 | "typedoc-plugin-missing-exports": "^0.22.6", 46 | "typescript": "^4.5.3" 47 | }, 48 | "dependencies": { 49 | "glsl-fast-gaussian-blur": "^1.0.2", 50 | "glsl-random": "^0.0.5" 51 | }, 52 | "volta": { 53 | "node": "14.21.3" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/effects/bloom.ts: -------------------------------------------------------------------------------- 1 | import KglEffect from '../kglEffect' 2 | import Program from '../program' 3 | import Specular from './specular' 4 | import Blur from './blur' 5 | import bloomFrag from '../shaders/postprocessing/bloom.frag' 6 | 7 | export default class Bloom extends Program { 8 | bloomSpecular: Specular 9 | bloomBlur: Blur 10 | radius = 0.4 11 | 12 | constructor(kgl: KglEffect) { 13 | const option = { 14 | fragmentShader: bloomFrag, 15 | uniforms: { 16 | uSpecular: 'framebuffer', 17 | uTextureRead: 'framebuffer', 18 | }, 19 | isAdditive: true, 20 | hasCamera: false, 21 | hasLight: false, 22 | } 23 | super(kgl, option) 24 | 25 | this.bloomSpecular = kgl.createEffect(Specular, { 26 | threshold: 0.3, 27 | }) 28 | 29 | this.bloomBlur = kgl.createEffect(Blur) 30 | } 31 | 32 | drawEffect( 33 | readFramebufferKey: string, 34 | cacheFramebufferKey: string, 35 | outFramebufferKey: string, 36 | radius?: number, 37 | isOnscreen?: boolean 38 | ) { 39 | this.bloomSpecular.drawEffect(readFramebufferKey, cacheFramebufferKey) 40 | 41 | this.bloomBlur.drawEffect( 42 | cacheFramebufferKey, 43 | outFramebufferKey, 44 | typeof radius !== 'undefined' ? radius : this.radius 45 | ) 46 | 47 | this.kgl.bindFramebuffer(isOnscreen ? null : outFramebufferKey) 48 | 49 | this.uniforms.uTextureRead = readFramebufferKey 50 | this.uniforms.uSpecular = cacheFramebufferKey 51 | super.draw() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/effects/blur.ts: -------------------------------------------------------------------------------- 1 | import KglEffect from '../kglEffect' 2 | import Program from '../program' 3 | import blurFrag from '../shaders/postprocessing/blur.frag' 4 | 5 | export default class Blur extends Program { 6 | radius = 0.5 7 | 8 | constructor(kgl: KglEffect) { 9 | const option = { 10 | fragmentShader: blurFrag, 11 | uniforms: { 12 | uTexture: 'framebuffer', 13 | uRadius: 0, 14 | uIsHorizontal: false, 15 | }, 16 | hasCamera: false, 17 | hasLight: false, 18 | } 19 | 20 | super(kgl, option) 21 | } 22 | 23 | drawEffect( 24 | readFramebufferKey: string, 25 | cacheFramebufferKey: string, 26 | radius?: number, 27 | isOnscreen?: boolean 28 | ) { 29 | const iterations = 8 30 | for (let i = 0; i < iterations; i++) { 31 | this.kgl.bindFramebuffer( 32 | isOnscreen && i >= iterations - 1 ? null : cacheFramebufferKey 33 | ) 34 | this.uniforms.uTexture = readFramebufferKey 35 | this.uniforms.uRadius = 36 | (iterations - 1 - i) * 37 | (typeof radius !== 'undefined' ? radius : this.radius) 38 | this.uniforms.uIsHorizontal = i % 2 === 0 39 | this.kgl.clear() 40 | super.draw() 41 | 42 | const t = cacheFramebufferKey 43 | cacheFramebufferKey = readFramebufferKey 44 | readFramebufferKey = t 45 | } 46 | // output: readFramebufferKey 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/effects/godray.ts: -------------------------------------------------------------------------------- 1 | import KglEffect from '../kglEffect' 2 | import Program from '../program' 3 | import Blur from './blur' 4 | import Specular from './specular' 5 | import Zoomblur from './zoomblur' 6 | import textureFrag from '../shaders/postprocessing/godray.frag' 7 | import { Array2 } from '../type' 8 | 9 | export default class Godray extends Program { 10 | godraySpecular: Specular 11 | godrayZoomblur: Zoomblur 12 | godrayBlur: Blur 13 | radius = 0.02 14 | 15 | constructor(kgl: KglEffect) { 16 | const option = { 17 | fragmentShader: textureFrag, 18 | uniforms: { 19 | uTexture: 'framebuffer', 20 | uTextureCache: 'framebuffer', 21 | }, 22 | isAdditive: true, 23 | } 24 | super(kgl, option) 25 | 26 | this.godraySpecular = kgl.createEffect(Specular, { 27 | threshold: 0.75, 28 | }) 29 | 30 | this.godrayZoomblur = kgl.createEffect(Zoomblur) 31 | 32 | this.godrayBlur = kgl.createEffect(Blur) 33 | } 34 | 35 | drawEffect( 36 | readFramebufferKey: string, 37 | cacheFramebufferKey: string, 38 | outFramebufferKey: string, 39 | strength?: number, 40 | center?: Array2, 41 | radius?: number, 42 | isOnscreen?: boolean 43 | ) { 44 | this.godraySpecular.drawEffect(readFramebufferKey, outFramebufferKey) 45 | 46 | this.godrayZoomblur.drawEffect( 47 | outFramebufferKey, 48 | cacheFramebufferKey, 49 | strength, 50 | center 51 | ) 52 | 53 | this.godrayBlur.drawEffect( 54 | cacheFramebufferKey, 55 | outFramebufferKey, 56 | typeof radius !== 'undefined' ? radius : this.radius 57 | ) 58 | 59 | this.kgl.bindFramebuffer(isOnscreen ? null : outFramebufferKey) 60 | 61 | this.uniforms.uTexture = readFramebufferKey 62 | this.uniforms.uTextureCache = cacheFramebufferKey 63 | super.draw() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/effects/godrayLight.ts: -------------------------------------------------------------------------------- 1 | import KglEffect from '../kglEffect' 2 | import Program from '../program' 3 | import Blur from './blur' 4 | import Specular from './specular' 5 | import Zoomblur from './zoomblur' 6 | import textureFrag from '../shaders/template/texture.frag' 7 | import { Array2 } from '../type' 8 | 9 | export default class GodrayLight extends Program { 10 | godraySpecular: Specular 11 | godrayZoomblur: Zoomblur 12 | godrayBlur: Blur 13 | radius = 0.02 14 | 15 | constructor(kgl: KglEffect) { 16 | const option = { 17 | fragmentShader: textureFrag, 18 | uniforms: { 19 | uTexture: 'framebuffer', 20 | }, 21 | isAdditive: true, 22 | } 23 | super(kgl, option) 24 | 25 | this.godraySpecular = kgl.createEffect(Specular, { 26 | threshold: 0.75, 27 | }) 28 | 29 | this.godrayZoomblur = kgl.createEffect(Zoomblur) 30 | 31 | this.godrayBlur = kgl.createEffect(Blur) 32 | } 33 | 34 | drawEffect( 35 | readFramebufferKey: string, 36 | cacheFramebufferKey: string, 37 | outFramebufferKey: string, 38 | strength?: number, 39 | center?: Array2, 40 | radius?: number, 41 | isOnscreen?: boolean 42 | ) { 43 | this.godraySpecular.drawEffect(readFramebufferKey, outFramebufferKey) 44 | 45 | this.godrayZoomblur.drawEffect( 46 | outFramebufferKey, 47 | cacheFramebufferKey, 48 | strength, 49 | center 50 | ) 51 | 52 | this.godrayBlur.drawEffect( 53 | cacheFramebufferKey, 54 | outFramebufferKey, 55 | typeof radius !== 'undefined' ? radius : this.radius 56 | ) 57 | 58 | this.kgl.bindFramebuffer(isOnscreen ? null : outFramebufferKey) 59 | 60 | this.uniforms.uTexture = cacheFramebufferKey 61 | super.draw() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/effects/index.ts: -------------------------------------------------------------------------------- 1 | import { default as Blur } from './blur' 2 | import { default as Specular } from './specular' 3 | import { default as Bloom } from './bloom' 4 | import { default as Zoomblur } from './zoomblur' 5 | import { default as Godray } from './godray' 6 | import { default as GodrayLight } from './godrayLight' 7 | 8 | export type EffectInstance = 9 | | Blur 10 | | Specular 11 | | Bloom 12 | | Zoomblur 13 | | Godray 14 | | GodrayLight 15 | 16 | export type KeyofEffect = 17 | | 'blur' 18 | | 'specular' 19 | | 'bloom' 20 | | 'zoomblur' 21 | | 'godray' 22 | | 'godrayLight' 23 | 24 | export { default as Blur } from './blur' 25 | export { default as Specular } from './specular' 26 | export { default as Bloom } from './bloom' 27 | export { default as Zoomblur } from './zoomblur' 28 | export { default as Godray } from './godray' 29 | export { default as GodrayLight } from './godrayLight' 30 | -------------------------------------------------------------------------------- /src/effects/specular.ts: -------------------------------------------------------------------------------- 1 | import KglEffect from '../kglEffect' 2 | import Program from '../program' 3 | import specularFrag from '../shaders/postprocessing/specular.frag' 4 | 5 | export type Option = { 6 | threshold?: number 7 | } 8 | 9 | export default class Specular extends Program { 10 | constructor(kgl: KglEffect, option: Option = {}) { 11 | const { threshold = 0.5 } = option 12 | 13 | const programOption = { 14 | fragmentShader: specularFrag, 15 | uniforms: { 16 | uTexture: 'framebuffer', 17 | uThreshold: threshold, 18 | }, 19 | hasCamera: false, 20 | hasLight: false, 21 | } 22 | 23 | super(kgl, programOption) 24 | } 25 | 26 | drawEffect( 27 | readFramebufferKey: string, 28 | outFramebufferKey: string, 29 | threshold?: number 30 | ) { 31 | this.kgl.bindFramebuffer(outFramebufferKey) 32 | this.uniforms.uTexture = readFramebufferKey 33 | if (typeof threshold !== 'undefined') this.uniforms.uThreshold = threshold 34 | this.kgl.clear() 35 | super.draw() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/effects/zoomblur.ts: -------------------------------------------------------------------------------- 1 | import KglEffect from '../kglEffect' 2 | import Program from '../program' 3 | import zoomblurFrag from '../shaders/postprocessing/zoomblur.frag' 4 | import { Array2 } from '../type' 5 | 6 | export default class Zoomblur extends Program { 7 | constructor(kgl: KglEffect) { 8 | const option = { 9 | fragmentShader: zoomblurFrag, 10 | uniforms: { 11 | uTexture: 'framebuffer', 12 | uStrength: 5, 13 | uCenter: [kgl.canvas.width / 2, kgl.canvas.height / 2], 14 | }, 15 | } 16 | super(kgl, option) 17 | } 18 | 19 | drawEffect( 20 | readFramebufferKey: string, 21 | outFramebufferKey: string, 22 | strength?: number, 23 | center?: Array2, 24 | isOnscreen?: boolean 25 | ) { 26 | this.kgl.bindFramebuffer(isOnscreen ? null : outFramebufferKey) 27 | this.uniforms.uTexture = readFramebufferKey 28 | if (typeof strength !== 'undefined') this.uniforms.uStrength = strength 29 | if (typeof center !== 'undefined') this.uniforms.uCenter = center 30 | this.kgl.clear() 31 | super.draw() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kgl' 2 | export { default } from './kgl' 3 | 4 | export { default as KglEffect } from './kglEffect' 5 | export { default as KglAuto } from './kglAuto' 6 | 7 | export * from './effects/index' 8 | -------------------------------------------------------------------------------- /src/kglAuto.ts: -------------------------------------------------------------------------------- 1 | import { Option as OptionKgl, Framebuffer, OptionCreateProgram } from './kgl' 2 | import KglEffect from './kglEffect' 3 | import Program from './program' 4 | import { EffectInstance, KeyofEffect } from './effects/index' 5 | import * as Effects from './effects/index' 6 | 7 | type framebufferOptions = { [K: string]: { width: number; height: number } } 8 | 9 | type Option = { 10 | programs?: { [K: string]: OptionCreateProgram } 11 | effects?: KeyofEffect[] 12 | framebuffers?: string[] | framebufferOptions 13 | framebufferFloats?: framebufferOptions 14 | tick?: Function 15 | onBefore?: Function 16 | onResize?: Function 17 | isAutoResize?: boolean 18 | isAutoStart?: boolean 19 | } & OptionKgl 20 | 21 | export default class KglAuto extends KglEffect { 22 | programs: { [K: string]: Program } = {} 23 | effects: { 24 | [K: string]: EffectInstance 25 | } = {} 26 | framebuffers: { [K: string]: Framebuffer } = {} 27 | ticks: Function[] = [] 28 | 29 | onResize?: Function 30 | 31 | _resize?: EventListener | Function 32 | requestID: number = 0 33 | 34 | constructor(option: Option = {}) { 35 | super(option) 36 | 37 | const { 38 | programs = {}, 39 | effects = [], 40 | framebuffers = [], 41 | framebufferFloats = {}, 42 | tick, 43 | onBefore, 44 | onResize, 45 | isAutoResize = true, 46 | isAutoStart = true, 47 | } = option 48 | 49 | if (typeof tick === 'function') { 50 | this.addTick(tick) 51 | } 52 | if (typeof onResize === 'function') { 53 | this.onResize = onResize 54 | } 55 | 56 | Object.keys(programs).forEach((key) => { 57 | const data = programs[key] 58 | const program = (this.programs[key] = this.createProgram(data)) 59 | if (!data.isFloats) { 60 | this.add(program) 61 | } 62 | }) 63 | 64 | effects.forEach((key) => { 65 | const classKey = (key.charAt(0).toUpperCase() + 66 | key.slice(1)) as keyof typeof Effects 67 | this.effects[key] = this.createEffect(Effects[classKey]) 68 | }) 69 | 70 | if (isAutoResize) { 71 | this._initResize() 72 | } 73 | 74 | switch (framebuffers.constructor.name) { 75 | case 'Array': 76 | ;(framebuffers as string[]).forEach((key) => { 77 | this.createFramebuffer(key) 78 | }) 79 | break 80 | case 'Object': 81 | Object.keys(framebuffers).forEach((key) => { 82 | const { width, height } = (framebuffers as framebufferOptions)[key] 83 | this.createFramebuffer(key, width, height) 84 | }) 85 | break 86 | } 87 | 88 | Object.keys(framebufferFloats).forEach((key) => { 89 | const { width, height } = framebufferFloats[key] 90 | this.createFramebufferFloat(key, width, height) 91 | }) 92 | 93 | if (typeof onBefore === 'function') onBefore(this) 94 | 95 | if (isAutoStart) this.start() 96 | } 97 | 98 | _initResize() { 99 | this._resize = () => { 100 | this.resize() 101 | if (this.onResize) { 102 | this.onResize() 103 | } 104 | } 105 | ;(this._resize as Function)() 106 | window.addEventListener('resize', this._resize as EventListener) 107 | } 108 | 109 | addTick(tick: Function) { 110 | this.ticks.push(tick) 111 | } 112 | 113 | start() { 114 | let initialTimestamp: number 115 | 116 | requestAnimationFrame((timestamp) => { 117 | initialTimestamp = timestamp 118 | }) 119 | 120 | const render: FrameRequestCallback = (timestamp) => { 121 | const time = (timestamp - initialTimestamp) * 0.001 122 | 123 | for (let i = 0; i < this.ticks.length; i++) { 124 | this.ticks[i](this, time) 125 | } 126 | 127 | this.requestID = requestAnimationFrame(render) 128 | } 129 | this.requestID = requestAnimationFrame(render) 130 | } 131 | 132 | stop() { 133 | if (!this.requestID) return 134 | 135 | cancelAnimationFrame(this.requestID) 136 | this.requestID = 0 137 | } 138 | 139 | destroy() { 140 | this.stop() 141 | 142 | if (this._resize) { 143 | window.removeEventListener('resize', this._resize as EventListener) 144 | } 145 | 146 | super.destroy() 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/kglEffect.ts: -------------------------------------------------------------------------------- 1 | import Kgl from './kgl' 2 | import { EffectInstance } from './effects/index' 3 | import { Option as OptionSpecular } from './effects/specular' 4 | 5 | export default class KglEffect extends Kgl { 6 | effectList: EffectInstance[] = [] 7 | 8 | createEffect( 9 | EffectClass: { new (kgl: KglEffect, option?: OptionSpecular): T }, 10 | option?: OptionSpecular 11 | ) { 12 | const effect = new EffectClass(this, option) 13 | this.effectList.push(effect) 14 | return effect 15 | } 16 | 17 | resize() { 18 | super.resize() 19 | 20 | this.effectList.forEach((program) => { 21 | if (program.isAutoResolution) { 22 | program.uniforms.uResolution = [this.canvas.width, this.canvas.height] 23 | } 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/shaders/glsl.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vert' { 2 | const src: string 3 | export default src 4 | } 5 | 6 | declare module '*.frag' { 7 | const src: string 8 | export default src 9 | } 10 | 11 | declare module '*.glsl' { 12 | const src: string 13 | export default src 14 | } 15 | -------------------------------------------------------------------------------- /src/shaders/postprocessing/bloom.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; 4 | uniform sampler2D uSpecular; 5 | uniform sampler2D uTextureRead; 6 | 7 | const float brightness = 0.7; 8 | const float spread = 0.3; 9 | 10 | void main() { 11 | vec2 uv = gl_FragCoord.st / uResolution; 12 | vec4 specularColor = texture2D(uSpecular, uv); 13 | specularColor.rgb = pow(specularColor.rgb, vec3(1. - brightness)); 14 | specularColor.a = pow(specularColor.a, 1. - spread); 15 | gl_FragColor = texture2D(uTextureRead, uv) + specularColor; 16 | // gl_FragColor = vec4(vec3(specularColor.a), 1.); // * debug 17 | // gl_FragColor = vec4(texture2D(uSpecular, uv).rgb, 1.); // * debug 18 | } 19 | -------------------------------------------------------------------------------- /src/shaders/postprocessing/blur.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform sampler2D uTexture; 4 | uniform vec2 uResolution; 5 | uniform float uRadius; 6 | uniform bool uIsHorizontal; 7 | 8 | #pragma glslify: blur = require(glsl-fast-gaussian-blur) 9 | 10 | void main () { 11 | vec2 uv = gl_FragCoord.xy / uResolution; 12 | vec2 direction = uIsHorizontal ? vec2(1., 0.) : vec2(0., 1.); 13 | direction *= uRadius; 14 | gl_FragColor = blur(uTexture, uv, uResolution, direction); 15 | } 16 | -------------------------------------------------------------------------------- /src/shaders/postprocessing/godray.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; 4 | uniform sampler2D uTexture; 5 | uniform sampler2D uTextureCache; 6 | 7 | void main() { 8 | vec2 uv = gl_FragCoord.st / uResolution; 9 | gl_FragColor = texture2D(uTexture, uv) + texture2D(uTextureCache, uv); 10 | } 11 | -------------------------------------------------------------------------------- /src/shaders/postprocessing/specular.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; 4 | uniform sampler2D uTexture; 5 | uniform float uThreshold; 6 | 7 | void main() { 8 | vec2 uv = gl_FragCoord.st / uResolution; 9 | vec4 color = texture2D(uTexture, uv); 10 | if (color.a == 0. || length(color.rgb) < uThreshold * 1.732) discard; 11 | gl_FragColor = color; 12 | } 13 | -------------------------------------------------------------------------------- /src/shaders/postprocessing/zoomblur.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform sampler2D uTexture; 4 | uniform vec2 uResolution; 5 | uniform float uStrength; 6 | uniform vec2 uCenter; 7 | 8 | #pragma glslify: random = require(glsl-random) 9 | 10 | const float nFrag = 1. / 30.; 11 | 12 | void main () { 13 | vec2 tFrag = 1. / uResolution; 14 | vec3 destColor = vec3(0.); 15 | float randomValue = random(vec2(12.9898, 78.233)); 16 | vec2 fc = gl_FragCoord.st; 17 | vec2 fcc = fc - uCenter; 18 | float totalWeight = 0.; 19 | 20 | for (float i = 0.; i <= 30.; i++) { 21 | float percent = (i + randomValue) * nFrag; 22 | float weight = percent - percent * percent; 23 | vec2 t = fc - fcc * percent * uStrength * nFrag; 24 | destColor += texture2D(uTexture, t * tFrag).rgb * weight; 25 | totalWeight += weight; 26 | } 27 | gl_FragColor = vec4(destColor / totalWeight, 1.); 28 | } 29 | -------------------------------------------------------------------------------- /src/shaders/template/texture.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec2 uResolution; 4 | uniform sampler2D uTexture; 5 | 6 | void main() { 7 | gl_FragColor = texture2D(uTexture, gl_FragCoord.st / uResolution); 8 | } 9 | -------------------------------------------------------------------------------- /src/type.ts: -------------------------------------------------------------------------------- 1 | export type Array2 = [number, number] 2 | export type Array3 = [number, number, number] 3 | export type Array4 = [number, number, number, number] 4 | -------------------------------------------------------------------------------- /src/vector.ts: -------------------------------------------------------------------------------- 1 | export class Vec2 extends Array { 2 | constructor(initialValues?: [number, number]) { 3 | if (initialValues) { 4 | return initialValues 5 | } else { 6 | super(2) 7 | } 8 | } 9 | } 10 | 11 | export class Vec3 extends Array { 12 | constructor(initialValues?: [number, number, number]) { 13 | if (initialValues) { 14 | return initialValues 15 | } else { 16 | super(3) 17 | } 18 | } 19 | } 20 | 21 | export class Vec4 extends Array { 22 | constructor(initialValues?: [number, number, number, number]) { 23 | if (initialValues) { 24 | return initialValues 25 | } else { 26 | super(4) 27 | } 28 | } 29 | } 30 | 31 | export type Matrix = Float32Array 32 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "sourceMap": true, 5 | "target": "ES2015", 6 | "module": "ESNext", 7 | "moduleResolution": "node", 8 | }, 9 | "exclude": [ 10 | "node_modules" 11 | ] 12 | } 13 | --------------------------------------------------------------------------------