├── .gitignore ├── .prettierignore ├── src ├── geographic │ ├── index.ts │ ├── Ellipsoid.ts │ └── RayCastedGlobe.ts ├── core │ ├── render │ │ ├── RenderPipeline.ts │ │ └── RenderState.ts │ ├── base │ │ ├── index.ts │ │ ├── Time.ts │ │ ├── Util.ts │ │ └── Constant.ts │ ├── material │ │ ├── index.ts │ │ ├── Material.ts │ │ ├── ImageMaterial.ts │ │ └── SkyBoxMaterial.ts │ ├── mesh │ │ └── index.ts │ ├── shaderlib │ │ ├── global.d.ts │ │ ├── extra │ │ │ ├── skybox.vs.glsl │ │ │ ├── earth.vs.glsl │ │ │ ├── rayCastedGlobe.vs.glsl │ │ │ ├── skybox.fs.glsl │ │ │ ├── earth.fs.glsl │ │ │ └── rayCastedGlobe.fs.glsl │ │ ├── common.vs.glsl │ │ └── common.fs.glsl │ ├── lighting │ │ ├── index.ts │ │ ├── AmbientLight.ts │ │ ├── Light.ts │ │ └── PointLight.ts │ ├── shader │ │ ├── ShaderProgramPool.ts │ │ ├── ShaderUniformBlock.ts │ │ ├── enums │ │ │ └── ShaderDataGroup.ts │ │ ├── index.ts │ │ ├── ShaderProperty.ts │ │ ├── ShaderPool.ts │ │ ├── Shader.ts │ │ └── ShaderUniform.ts │ ├── enums │ │ ├── ColorSpace.ts │ │ └── BackgroundMode.ts │ ├── graphic │ │ ├── enums │ │ │ ├── IndexFormat.ts │ │ │ ├── BufferBindFlag.ts │ │ │ ├── BufferUsage.ts │ │ │ ├── MeshTopology.ts │ │ │ └── VertexElementFormat.ts │ │ ├── index.ts │ │ ├── SubMesh.ts │ │ ├── VertexBufferBinding.ts │ │ ├── IndexBufferBinding.ts │ │ ├── VertexElement.ts │ │ ├── BufferUtil.ts │ │ ├── Mesh.ts │ │ └── Buffer.ts │ ├── texture │ │ ├── index.ts │ │ ├── enums │ │ │ ├── TextureFilterMode.ts │ │ │ ├── TextureWrapMode.ts │ │ │ ├── TextureCubeFace.ts │ │ │ └── TextureFormat.ts │ │ ├── TextureCube.ts │ │ ├── Texture2D.ts │ │ └── Texture.ts │ ├── BoolUpdateFlag.ts │ ├── index.ts │ ├── UpdateFlagManager.ts │ ├── UpdateFlag.ts │ ├── Entity.ts │ ├── Canvas.ts │ ├── Background.ts │ ├── Scene.ts │ ├── Engine.ts │ └── Renderer.ts ├── config │ ├── index.ts │ ├── earth.ts │ └── skybox.ts ├── controls │ ├── index.ts │ └── Spherical.ts ├── index.ts └── math │ ├── index.ts │ ├── MathUtil.ts │ └── Color.ts ├── dist ├── geographic │ ├── index.d.ts │ ├── Ellipsoid.d.ts │ └── RayCastedGlobe.d.ts ├── config │ ├── index.d.ts │ ├── earth.d.ts │ └── skybox.d.ts ├── core │ ├── render │ │ ├── RenderState.d.ts │ │ └── RenderPipeline.d.ts │ ├── shader │ │ ├── ShaderProgramPool.d.ts │ │ ├── ShaderPool.d.ts │ │ ├── ShaderUniformBlock.d.ts │ │ ├── enums │ │ │ └── ShaderDataGroup.d.ts │ │ ├── index.d.ts │ │ ├── ShaderProperty.d.ts │ │ ├── Shader.d.ts │ │ ├── ShaderUniform.d.ts │ │ └── ShaderProgram.d.ts │ ├── base │ │ ├── index.d.ts │ │ ├── Util.d.ts │ │ ├── Time.d.ts │ │ └── Constant.d.ts │ ├── material │ │ ├── index.d.ts │ │ ├── Material.d.ts │ │ ├── ImageMaterial.d.ts │ │ └── SkyBoxMaterial.d.ts │ ├── mesh │ │ ├── index.d.ts │ │ ├── PrimitiveMesh.d.ts │ │ └── ModelMesh.d.ts │ ├── lighting │ │ ├── index.d.ts │ │ ├── AmbientLight.d.ts │ │ ├── Light.d.ts │ │ └── PointLight.d.ts │ ├── enums │ │ ├── ColorSpace.d.ts │ │ └── BackgroundMode.d.ts │ ├── graphic │ │ ├── enums │ │ │ ├── IndexFormat.d.ts │ │ │ ├── BufferBindFlag.d.ts │ │ │ ├── BufferUsage.d.ts │ │ │ ├── MeshTopology.d.ts │ │ │ └── VertexElementFormat.d.ts │ │ ├── SubMesh.d.ts │ │ ├── index.d.ts │ │ ├── VertexBufferBinding.d.ts │ │ ├── IndexBufferBinding.d.ts │ │ ├── VertexElement.d.ts │ │ ├── BufferUtil.d.ts │ │ ├── Buffer.d.ts │ │ └── Mesh.d.ts │ ├── texture │ │ ├── index.d.ts │ │ ├── enums │ │ │ ├── TextureFilterMode.d.ts │ │ │ ├── TextureWrapMode.d.ts │ │ │ ├── TextureCubeFace.d.ts │ │ │ └── TextureFormat.d.ts │ │ ├── TextureCube.d.ts │ │ ├── Texture2D.d.ts │ │ └── Texture.d.ts │ ├── BoolUpdateFlag.d.ts │ ├── index.d.ts │ ├── UpdateFlag.d.ts │ ├── UpdateFlagManager.d.ts │ ├── Canvas.d.ts │ ├── Background.d.ts │ ├── Entity.d.ts │ ├── Scene.d.ts │ ├── Renderer.d.ts │ ├── Engine.d.ts │ └── Camera.d.ts ├── controls │ ├── index.d.ts │ └── Spherical.d.ts ├── index.d.ts └── math │ ├── index.d.ts │ ├── MathUtil.d.ts │ └── Color.d.ts ├── .eslintignore ├── .husky ├── pre-commit └── commit-msg ├── typedoc.json ├── jest.config.js ├── commitlint.config.js ├── tsconfig.json ├── release.config.js ├── .eslintrc.js ├── .github └── workflows │ ├── release.yml │ └── docs.yml ├── .vscode └── settings.json ├── .prettierrc.js ├── public └── index.html ├── rollup.config.js ├── test └── geographic │ └── Ellipsoid.test.ts ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | dist 3 | docs 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | *.md 4 | -------------------------------------------------------------------------------- /src/geographic/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Ellipsoid'; 2 | -------------------------------------------------------------------------------- /dist/geographic/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './Ellipsoid'; 2 | -------------------------------------------------------------------------------- /src/core/render/RenderPipeline.ts: -------------------------------------------------------------------------------- 1 | export class RenderPipeline {} 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /es 2 | /lib 3 | /node_modules 4 | rollup.config.js 5 | /dist -------------------------------------------------------------------------------- /src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './earth'; 2 | export * from './skybox'; 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run lint -------------------------------------------------------------------------------- /dist/config/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './earth'; 2 | export * from './skybox'; 3 | -------------------------------------------------------------------------------- /dist/core/render/RenderState.d.ts: -------------------------------------------------------------------------------- 1 | export declare class RenderState { 2 | } 3 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["src/index.ts"], 3 | "out": "docs" 4 | } 5 | -------------------------------------------------------------------------------- /dist/core/render/RenderPipeline.d.ts: -------------------------------------------------------------------------------- 1 | export declare class RenderPipeline { 2 | } 3 | -------------------------------------------------------------------------------- /dist/core/shader/ShaderProgramPool.d.ts: -------------------------------------------------------------------------------- 1 | export declare class ShaderProgramPool { 2 | } 3 | -------------------------------------------------------------------------------- /src/config/earth.ts: -------------------------------------------------------------------------------- 1 | export const earthUrl = `http://121.199.160.202/images/earth.jpg`; 2 | -------------------------------------------------------------------------------- /dist/config/earth.d.ts: -------------------------------------------------------------------------------- 1 | export declare const earthUrl = "http://121.199.160.202/images/earth.jpg"; 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit $1 5 | -------------------------------------------------------------------------------- /src/core/base/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Constant'; 2 | export * from './Time'; 3 | export * from './Util'; 4 | -------------------------------------------------------------------------------- /src/core/render/RenderState.ts: -------------------------------------------------------------------------------- 1 | export class RenderState { 2 | // 环境光颜色 3 | // 深度缓冲函数 4 | // 等等 5 | } 6 | -------------------------------------------------------------------------------- /dist/core/base/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './Constant'; 2 | export * from './Time'; 3 | export * from './Util'; 4 | -------------------------------------------------------------------------------- /src/controls/index.ts: -------------------------------------------------------------------------------- 1 | export { OrbitControl } from './OrbitControl'; 2 | export { Spherical } from './Spherical'; 3 | -------------------------------------------------------------------------------- /dist/controls/index.d.ts: -------------------------------------------------------------------------------- 1 | export { OrbitControl } from './OrbitControl'; 2 | export { Spherical } from './Spherical'; 3 | -------------------------------------------------------------------------------- /src/core/material/index.ts: -------------------------------------------------------------------------------- 1 | export { Material } from './Material'; 2 | export { ImageMaterial } from './ImageMaterial'; 3 | -------------------------------------------------------------------------------- /src/core/mesh/index.ts: -------------------------------------------------------------------------------- 1 | export { ModelMesh } from './ModelMesh'; 2 | export { PrimitiveMesh } from './PrimitiveMesh'; 3 | -------------------------------------------------------------------------------- /src/core/shaderlib/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.glsl' { 2 | const value: string; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /dist/core/material/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Material } from './Material'; 2 | export { ImageMaterial } from './ImageMaterial'; 3 | -------------------------------------------------------------------------------- /dist/core/mesh/index.d.ts: -------------------------------------------------------------------------------- 1 | export { ModelMesh } from './ModelMesh'; 2 | export { PrimitiveMesh } from './PrimitiveMesh'; 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core'; 2 | export * from './math'; 3 | export * from './controls'; 4 | export * from './config'; 5 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './core'; 2 | export * from './math'; 3 | export * from './controls'; 4 | export * from './config'; 5 | -------------------------------------------------------------------------------- /src/core/lighting/index.ts: -------------------------------------------------------------------------------- 1 | export { Light } from './Light'; 2 | export { PointLight } from './PointLight'; 3 | export { AmbientLight } from './AmbientLight'; 4 | -------------------------------------------------------------------------------- /dist/config/skybox.d.ts: -------------------------------------------------------------------------------- 1 | import { DataType } from '../core'; 2 | export declare const skyStarConfig: { 3 | target: DataType; 4 | url: string; 5 | }[]; 6 | -------------------------------------------------------------------------------- /dist/core/lighting/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Light } from './Light'; 2 | export { PointLight } from './PointLight'; 3 | export { AmbientLight } from './AmbientLight'; 4 | -------------------------------------------------------------------------------- /src/core/shader/ShaderProgramPool.ts: -------------------------------------------------------------------------------- 1 | import { ShaderProgram } from './ShaderProgram'; 2 | export class ShaderProgramPool { 3 | // TODO: ShaderProgramPool 4 | } 5 | -------------------------------------------------------------------------------- /src/core/enums/ColorSpace.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Color Space. 3 | */ 4 | export enum ColorSpace { 5 | /** Linear color space. */ 6 | Linear, 7 | /** Gamma color space. */ 8 | Gamma, 9 | } 10 | -------------------------------------------------------------------------------- /src/core/shaderlib/extra/skybox.vs.glsl: -------------------------------------------------------------------------------- 1 | attribute vec3 POSITION; 2 | varying vec4 v_position; 3 | void main() { 4 | gl_Position = vec4(POSITION, 1.0); 5 | v_position = gl_Position; 6 | gl_Position.z = 1.0; 7 | } -------------------------------------------------------------------------------- /src/core/graphic/enums/IndexFormat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Index format. 3 | */ 4 | export enum IndexFormat { 5 | /** 8 bit */ 6 | UInt8, 7 | /** 16 bit */ 8 | UInt16, 9 | /** 32 bit */ 10 | UInt32, 11 | } 12 | -------------------------------------------------------------------------------- /dist/core/enums/ColorSpace.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Color Space. 3 | */ 4 | export declare enum ColorSpace { 5 | /** Linear color space. */ 6 | Linear = 0, 7 | /** Gamma color space. */ 8 | Gamma = 1 9 | } 10 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | testMatch: ['/test/**/*(*.)@(spec|test).[tj]s?(x)'], 6 | }; 7 | -------------------------------------------------------------------------------- /dist/core/enums/BackgroundMode.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enum type for background mode. 3 | */ 4 | export declare enum BackgroundMode { 5 | SolidColor = 0, 6 | Sky = 1, 7 | /** Texture */ 8 | Texture = 2 9 | } 10 | -------------------------------------------------------------------------------- /src/core/shaderlib/extra/earth.vs.glsl: -------------------------------------------------------------------------------- 1 | attribute vec3 POSITION; 2 | attribute vec2 TEXCOORD_0; 3 | varying vec2 v_TexCoord; 4 | varying vec3 v_worldPostion; 5 | void main() { 6 | v_worldPostion = POSITION; 7 | v_TexCoord = TEXCOORD_0; 8 | } -------------------------------------------------------------------------------- /src/core/enums/BackgroundMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enum type for background mode. 3 | */ 4 | export enum BackgroundMode { 5 | /* Solid color. */ 6 | SolidColor, 7 | /* Sky. */ 8 | Sky, 9 | /** Texture */ 10 | Texture, 11 | } 12 | -------------------------------------------------------------------------------- /src/core/shaderlib/extra/rayCastedGlobe.vs.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 POSITION; 2 | uniform mat4 u_vpMat; 3 | varying vec3 v_worldPosition; 4 | 5 | void main() 6 | { 7 | gl_Position = u_vpMat * POSITION; 8 | v_worldPosition = POSITION.xyz; 9 | } -------------------------------------------------------------------------------- /src/core/graphic/enums/BufferBindFlag.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Buffer binding flag. 3 | */ 4 | export enum BufferBindFlag { 5 | /** Vertex buffer binding flag */ 6 | VertexBuffer, 7 | /** Index buffer binding flag */ 8 | IndexBuffer, 9 | } 10 | -------------------------------------------------------------------------------- /dist/core/graphic/enums/IndexFormat.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Index format. 3 | */ 4 | export declare enum IndexFormat { 5 | /** 8 bit */ 6 | UInt8 = 0, 7 | /** 16 bit */ 8 | UInt16 = 1, 9 | /** 32 bit */ 10 | UInt32 = 2 11 | } 12 | -------------------------------------------------------------------------------- /dist/core/shader/ShaderPool.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Engine built-in shader pool. 3 | */ 4 | export declare class ShaderPool { 5 | /** 6 | * Created by Shader based on fragment and vertex shader code. 7 | */ 8 | static init(): void; 9 | } 10 | -------------------------------------------------------------------------------- /dist/core/graphic/enums/BufferBindFlag.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Buffer binding flag. 3 | */ 4 | export declare enum BufferBindFlag { 5 | /** Vertex buffer binding flag */ 6 | VertexBuffer = 0, 7 | /** Index buffer binding flag */ 8 | IndexBuffer = 1 9 | } 10 | -------------------------------------------------------------------------------- /src/core/texture/index.ts: -------------------------------------------------------------------------------- 1 | export { Texture } from './Texture'; 2 | export { Texture2D } from './Texture2D'; 3 | export * from './enums/TextureFilterMode'; 4 | export * from './enums/TextureWrapMode'; 5 | export * from './enums/TextureFormat'; 6 | export * from './enums/TextureCubeFace'; 7 | -------------------------------------------------------------------------------- /dist/core/texture/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Texture } from './Texture'; 2 | export { Texture2D } from './Texture2D'; 3 | export * from './enums/TextureFilterMode'; 4 | export * from './enums/TextureWrapMode'; 5 | export * from './enums/TextureFormat'; 6 | export * from './enums/TextureCubeFace'; 7 | -------------------------------------------------------------------------------- /src/core/texture/enums/TextureFilterMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The filter mode of the texture. 3 | */ 4 | export enum TextureFilterMode { 5 | /** Point filtering. */ 6 | Point = 0, 7 | /** Bilinear filtering. */ 8 | Bilinear = 1, 9 | /** Trilinear filtering. */ 10 | Trilinear = 2, 11 | } 12 | -------------------------------------------------------------------------------- /src/core/shader/ShaderUniformBlock.ts: -------------------------------------------------------------------------------- 1 | import { ShaderUniform } from './ShaderUniform'; 2 | 3 | /** 4 | * Shader uniform block. 5 | * @internal 6 | */ 7 | export class ShaderUniformBlock { 8 | readonly constUniforms: ShaderUniform[] = []; 9 | readonly textureUniforms: ShaderUniform[] = []; 10 | } 11 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | // 提交的类别 5 | 'type-enum': [ 6 | 2, 7 | 'always', 8 | ['build', 'ci', 'chore', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'], 9 | ], 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /dist/core/shader/ShaderUniformBlock.d.ts: -------------------------------------------------------------------------------- 1 | import { ShaderUniform } from './ShaderUniform'; 2 | /** 3 | * Shader uniform block. 4 | * @internal 5 | */ 6 | export declare class ShaderUniformBlock { 7 | readonly constUniforms: ShaderUniform[]; 8 | readonly textureUniforms: ShaderUniform[]; 9 | } 10 | -------------------------------------------------------------------------------- /dist/core/BoolUpdateFlag.d.ts: -------------------------------------------------------------------------------- 1 | import { UpdateFlag } from './UpdateFlag'; 2 | /** 3 | * Used to update tags. 4 | */ 5 | export declare class BoolUpdateFlag extends UpdateFlag { 6 | /** Flag. */ 7 | flag: boolean; 8 | /** 9 | * @inheritdoc 10 | */ 11 | dispatch(): void; 12 | } 13 | -------------------------------------------------------------------------------- /src/core/shader/enums/ShaderDataGroup.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shader data grouping. 3 | */ 4 | export enum ShaderDataGroup { 5 | /** Scene group. */ 6 | Scene, 7 | /** Camera group. */ 8 | Camera, 9 | /** Renderer group. */ 10 | Renderer, 11 | /** material group. */ 12 | Material, 13 | // TODO: Geographic 14 | } 15 | -------------------------------------------------------------------------------- /src/core/shaderlib/extra/skybox.fs.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | uniform samplerCube u_Skybox; 3 | uniform mat4 u_invVPMat; 4 | varying vec4 v_position; 5 | void main() { 6 | // 使用视图投影矩阵的逆来获取相机看向矩形每一个像素的方向。这会是看向立方体贴图的方向 7 | vec4 t = u_invVPMat * v_position; 8 | gl_FragColor = textureCube(u_Skybox, normalize(t.xyz / t.w)); 9 | } -------------------------------------------------------------------------------- /dist/core/texture/enums/TextureFilterMode.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The filter mode of the texture. 3 | */ 4 | export declare enum TextureFilterMode { 5 | /** Point filtering. */ 6 | Point = 0, 7 | /** Bilinear filtering. */ 8 | Bilinear = 1, 9 | /** Trilinear filtering. */ 10 | Trilinear = 2 11 | } 12 | -------------------------------------------------------------------------------- /src/core/BoolUpdateFlag.ts: -------------------------------------------------------------------------------- 1 | import { UpdateFlag } from './UpdateFlag'; 2 | 3 | /** 4 | * Used to update tags. 5 | */ 6 | export class BoolUpdateFlag extends UpdateFlag { 7 | /** Flag. */ 8 | flag = true; 9 | 10 | /** 11 | * @inheritdoc 12 | */ 13 | dispatch(): void { 14 | this.flag = true; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/math/index.ts: -------------------------------------------------------------------------------- 1 | export { Vector2 } from './Vector2'; 2 | export { Vector3 } from './Vector3'; 3 | export { Vector4 } from './Vector4'; 4 | export { Matrix3 } from './Matrix3'; 5 | export { Matrix4 } from './Matrix4'; 6 | export { Quaternion } from './Quaternion'; 7 | export { MathUtil } from './MathUtil'; 8 | export { Color } from './Color'; 9 | -------------------------------------------------------------------------------- /dist/math/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Vector2 } from './Vector2'; 2 | export { Vector3 } from './Vector3'; 3 | export { Vector4 } from './Vector4'; 4 | export { Matrix3 } from './Matrix3'; 5 | export { Matrix4 } from './Matrix4'; 6 | export { Quaternion } from './Quaternion'; 7 | export { MathUtil } from './MathUtil'; 8 | export { Color } from './Color'; 9 | -------------------------------------------------------------------------------- /dist/core/shader/enums/ShaderDataGroup.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shader data grouping. 3 | */ 4 | export declare enum ShaderDataGroup { 5 | /** Scene group. */ 6 | Scene = 0, 7 | /** Camera group. */ 8 | Camera = 1, 9 | /** Renderer group. */ 10 | Renderer = 2, 11 | /** material group. */ 12 | Material = 3 13 | } 14 | -------------------------------------------------------------------------------- /src/core/shader/index.ts: -------------------------------------------------------------------------------- 1 | export { Shader } from './Shader'; 2 | export { ShaderData } from './ShaderData'; 3 | export { ShaderProgram } from './ShaderProgram'; 4 | export { ShaderProperty } from './ShaderProperty'; 5 | export { ShaderUniform } from './ShaderUniform'; 6 | export { ShaderUniformBlock } from './ShaderUniformBlock'; 7 | export { ShaderDataGroup } from './enums/ShaderDataGroup'; 8 | -------------------------------------------------------------------------------- /dist/core/shader/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Shader } from './Shader'; 2 | export { ShaderData } from './ShaderData'; 3 | export { ShaderProgram } from './ShaderProgram'; 4 | export { ShaderProperty } from './ShaderProperty'; 5 | export { ShaderUniform } from './ShaderUniform'; 6 | export { ShaderUniformBlock } from './ShaderUniformBlock'; 7 | export { ShaderDataGroup } from './enums/ShaderDataGroup'; 8 | -------------------------------------------------------------------------------- /src/core/shaderlib/common.vs.glsl: -------------------------------------------------------------------------------- 1 | attribute vec3 POSITION; 2 | attribute vec3 NORMAL; 3 | attribute vec2 TEXCOORD_0; 4 | uniform mat4 u_viewMat; 5 | uniform mat4 u_projMat; 6 | varying vec3 v_worldPostion; 7 | varying vec2 v_TexCoord; 8 | void main() { 9 | gl_Position = u_projMat * u_viewMat * vec4(POSITION, 1.0); 10 | v_worldPostion = POSITION; 11 | v_TexCoord = TEXCOORD_0; 12 | } 13 | -------------------------------------------------------------------------------- /src/core/graphic/enums/BufferUsage.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Buffer usage. 3 | */ 4 | export enum BufferUsage { 5 | /** The buffer content are intended to be specified once, and used many times */ 6 | Static, 7 | /** The buffer contents are intended to be respecified repeatedly, and used many times */ 8 | Dynamic, 9 | /** The buffer contents are intended to be specified once, and used at most a few times */ 10 | Stream, 11 | } 12 | -------------------------------------------------------------------------------- /src/core/index.ts: -------------------------------------------------------------------------------- 1 | export { Scene } from './Scene'; 2 | export { Entity } from './Entity'; 3 | export { Renderer } from './Renderer'; 4 | export { Canvas } from './Canvas'; 5 | export { Transform } from './Transform'; 6 | export { Camera } from './Camera'; 7 | export { Engine } from './Engine'; 8 | export * from './shader'; 9 | export * from './mesh'; 10 | export * from './material'; 11 | export * from './graphic'; 12 | export * from './base'; 13 | -------------------------------------------------------------------------------- /dist/core/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Scene } from './Scene'; 2 | export { Entity } from './Entity'; 3 | export { Renderer } from './Renderer'; 4 | export { Canvas } from './Canvas'; 5 | export { Transform } from './Transform'; 6 | export { Camera } from './Camera'; 7 | export { Engine } from './Engine'; 8 | export * from './shader'; 9 | export * from './mesh'; 10 | export * from './material'; 11 | export * from './graphic'; 12 | export * from './base'; 13 | -------------------------------------------------------------------------------- /src/core/texture/enums/TextureWrapMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapping mode of the texture. 3 | */ 4 | export enum TextureWrapMode { 5 | /** Clamping mode. use the color of edge pixels beyond the texture boundary. */ 6 | Clamp = 0, 7 | /** Repeating mode. tiling will be repeated if it exceeds the texture boundary. */ 8 | Repeat = 1, 9 | /** Mirror repeat mode. tiling will be mirrored and repeated if it exceeds the texture boundary. */ 10 | Mirror = 2, 11 | } 12 | -------------------------------------------------------------------------------- /dist/core/graphic/enums/BufferUsage.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Buffer usage. 3 | */ 4 | export declare enum BufferUsage { 5 | /** The buffer content are intended to be specified once, and used many times */ 6 | Static = 0, 7 | /** The buffer contents are intended to be respecified repeatedly, and used many times */ 8 | Dynamic = 1, 9 | /** The buffer contents are intended to be specified once, and used at most a few times */ 10 | Stream = 2 11 | } 12 | -------------------------------------------------------------------------------- /dist/core/material/Material.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { Shader, ShaderData } from '../shader'; 3 | /** 4 | * Material base class. 5 | */ 6 | export declare class Material { 7 | /** Name. */ 8 | name: string; 9 | /** Shader used by the material. */ 10 | shader: Shader; 11 | engine: Engine; 12 | /** Shader data. */ 13 | readonly shaderData: ShaderData; 14 | constructor(engine: Engine, shader: Shader); 15 | } 16 | -------------------------------------------------------------------------------- /dist/core/texture/enums/TextureWrapMode.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapping mode of the texture. 3 | */ 4 | export declare enum TextureWrapMode { 5 | /** Clamping mode. use the color of edge pixels beyond the texture boundary. */ 6 | Clamp = 0, 7 | /** Repeating mode. tiling will be repeated if it exceeds the texture boundary. */ 8 | Repeat = 1, 9 | /** Mirror repeat mode. tiling will be mirrored and repeated if it exceeds the texture boundary. */ 10 | Mirror = 2 11 | } 12 | -------------------------------------------------------------------------------- /dist/core/shader/ShaderProperty.d.ts: -------------------------------------------------------------------------------- 1 | import { ShaderDataGroup } from './enums/ShaderDataGroup'; 2 | /** 3 | * Shader property. 4 | */ 5 | export declare class ShaderProperty { 6 | private static _propertyNameCounter; 7 | /** @internal */ 8 | _uniqueId: number; 9 | /** @internal */ 10 | _group: ShaderDataGroup; 11 | /** Shader property name. */ 12 | readonly name: string; 13 | /** 14 | * @internal 15 | */ 16 | constructor(name: string); 17 | } 18 | -------------------------------------------------------------------------------- /dist/core/UpdateFlag.d.ts: -------------------------------------------------------------------------------- 1 | import { UpdateFlagManager } from './UpdateFlagManager'; 2 | /** 3 | * Used to update tags. 4 | */ 5 | export declare abstract class UpdateFlag { 6 | /** @internal */ 7 | _flagManagers: UpdateFlagManager[]; 8 | /** 9 | * Dispatch. 10 | * @param param - Parameter 11 | */ 12 | abstract dispatch(param?: Object): void; 13 | /** 14 | * Clear. 15 | */ 16 | clearFromManagers(): void; 17 | /** 18 | * Destroy. 19 | */ 20 | destroy(): void; 21 | private _removeFromManagers; 22 | } 23 | -------------------------------------------------------------------------------- /src/core/shader/ShaderProperty.ts: -------------------------------------------------------------------------------- 1 | import { ShaderDataGroup } from './enums/ShaderDataGroup'; 2 | 3 | /** 4 | * Shader property. 5 | */ 6 | export class ShaderProperty { 7 | private static _propertyNameCounter: number = 0; 8 | 9 | /** @internal */ 10 | _uniqueId: number; 11 | /** @internal */ 12 | _group: ShaderDataGroup; 13 | 14 | /** Shader property name. */ 15 | readonly name: string; 16 | 17 | /** 18 | * @internal 19 | */ 20 | constructor(name: string) { 21 | this.name = name; 22 | this._uniqueId = ShaderProperty._propertyNameCounter++; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/core/texture/enums/TextureCubeFace.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Define the face of the cube texture. 3 | */ 4 | export enum TextureCubeFace { 5 | /** Positive X face for a cube-mapped texture. */ 6 | PositiveX = 0, 7 | /** Negative X face for a cube-mapped texture. */ 8 | NegativeX = 1, 9 | /** Positive Y face for a cube-mapped texture. */ 10 | PositiveY = 2, 11 | /** Negative Y face for a cube-mapped texture. */ 12 | NegativeY = 3, 13 | /** Positive Z face for a cube-mapped texture. */ 14 | PositiveZ = 4, 15 | /** Negative Z face for a cube-mapped texture. */ 16 | NegativeZ = 5, 17 | } 18 | -------------------------------------------------------------------------------- /dist/core/lighting/AmbientLight.d.ts: -------------------------------------------------------------------------------- 1 | import { ShaderData } from '../shader'; 2 | import { Color } from '../../math'; 3 | /** 4 | * Ambient light. 5 | */ 6 | export declare class AmbientLight { 7 | /** Get the address of the point ambient color uniform variable in the shader. */ 8 | private static _colorProperty; 9 | /** The color of the light. */ 10 | color: Color; 11 | constructor(color: Color); 12 | /** 13 | * Set variable value in shader. 14 | * @param shaderData Shader data. 15 | */ 16 | _updateShaderData(shaderData: ShaderData): void; 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/"], 3 | "compilerOptions": { 4 | "module": "esnext", 5 | "target": "esnext", 6 | "skipDefaultLibCheck": true, 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "allowSyntheticDefaultImports": true, 10 | "experimentalDecorators": true, 11 | "declarationDir": "./dist", 12 | "sourceMap": true, 13 | "baseUrl": "./", 14 | "emitDeclarationOnly": false, 15 | "skipLibCheck": true, 16 | "paths": { 17 | "@/*": ["src/*"] 18 | } 19 | }, 20 | "exclude": ["node_modules", "types", "packages/*/tests"] 21 | } 22 | -------------------------------------------------------------------------------- /src/core/material/Material.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { Shader, ShaderData, ShaderDataGroup } from '../shader'; 3 | 4 | /** 5 | * Material base class. 6 | */ 7 | export class Material { 8 | /** Name. */ 9 | name: string; 10 | /** Shader used by the material. */ 11 | shader: Shader; 12 | // TODO: 提升一个RefObject! 13 | engine: Engine; 14 | 15 | /** Shader data. */ 16 | readonly shaderData: ShaderData = new ShaderData(ShaderDataGroup.Material); 17 | 18 | constructor(engine: Engine, shader: Shader) { 19 | this.shader = shader; 20 | this.engine = engine; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dist/core/UpdateFlagManager.d.ts: -------------------------------------------------------------------------------- 1 | import { UpdateFlag } from './UpdateFlag'; 2 | /** 3 | * @internal 4 | */ 5 | export declare class UpdateFlagManager { 6 | /** @internal */ 7 | _updateFlags: UpdateFlag[]; 8 | /** 9 | * Create a UpdateFlag. 10 | * @returns - The UpdateFlag. 11 | */ 12 | createFlag(type: new () => T): T; 13 | /** 14 | * Add a UpdateFlag. 15 | * @param flag - The UpdateFlag. 16 | */ 17 | addFlag(flag: UpdateFlag): void; 18 | /** 19 | * Dispatch. 20 | */ 21 | dispatch(param?: Object): void; 22 | } 23 | -------------------------------------------------------------------------------- /src/core/graphic/enums/MeshTopology.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Mesh topology. 3 | */ 4 | export enum MeshTopology { 5 | /** Draws a single dot */ 6 | Points = 0, 7 | /** Draws a line between a pair of vertices */ 8 | Lines = 1, 9 | /** Draws a straight line to the next vertex, and connects the last vertex back to the first */ 10 | LineLoop = 2, 11 | /** Draws a straight line to the next vertex. */ 12 | LineStrip = 3, 13 | /** Draws a triangle for a group of three vertices */ 14 | Triangles = 4, 15 | /** Draws a triangle strip */ 16 | TriangleStrip = 5, 17 | /** Draws a triangle fan */ 18 | TriangleFan = 6, 19 | } 20 | -------------------------------------------------------------------------------- /release.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | branch: ['master'], 3 | plugins: [ 4 | '@semantic-release/commit-analyzer', 5 | '@semantic-release/release-notes-generator', 6 | [ 7 | '@semantic-release/changelog', 8 | { 9 | changelogFile: 'CHANGELOG.md', 10 | }, 11 | ], 12 | '@semantic-release/npm', 13 | '@semantic-release/github', 14 | [ 15 | '@semantic-release/git', 16 | { 17 | assets: ['CHANGELOG.md', 'dist/**'], 18 | message: 'chore(release): set `package.json` to ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}', 19 | }, 20 | ], 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /dist/core/lighting/Light.d.ts: -------------------------------------------------------------------------------- 1 | import { Matrix4 } from '../../math'; 2 | import { Transform } from '../Transform'; 3 | /** 4 | * Lighting model base class. 5 | */ 6 | export declare class Light { 7 | /** Light source position. */ 8 | protected transform: Transform; 9 | private _viewMat; 10 | private _inverseViewMat; 11 | /** 12 | * Get the view matrix of the light source position. 13 | */ 14 | get viewMatrix(): Matrix4; 15 | /** 16 | * Get the inverse of the view matrix for the light source position. 17 | */ 18 | get inverseViewMatrix(): Matrix4; 19 | constructor(); 20 | } 21 | -------------------------------------------------------------------------------- /dist/core/texture/enums/TextureCubeFace.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Define the face of the cube texture. 3 | */ 4 | export declare enum TextureCubeFace { 5 | /** Positive X face for a cube-mapped texture. */ 6 | PositiveX = 0, 7 | /** Negative X face for a cube-mapped texture. */ 8 | NegativeX = 1, 9 | /** Positive Y face for a cube-mapped texture. */ 10 | PositiveY = 2, 11 | /** Negative Y face for a cube-mapped texture. */ 12 | NegativeY = 3, 13 | /** Positive Z face for a cube-mapped texture. */ 14 | PositiveZ = 4, 15 | /** Negative Z face for a cube-mapped texture. */ 16 | NegativeZ = 5 17 | } 18 | -------------------------------------------------------------------------------- /dist/core/graphic/SubMesh.d.ts: -------------------------------------------------------------------------------- 1 | import { MeshTopology } from './enums/MeshTopology'; 2 | /** 3 | * Sub-mesh, mainly contains drawing information. 4 | */ 5 | export declare class SubMesh { 6 | /** Start drawing offset. */ 7 | start: number; 8 | /** Drawing count. */ 9 | count: number; 10 | /** Drawing topology. */ 11 | topology: MeshTopology; 12 | /** 13 | * Create a sub-mesh. 14 | * @param start - Start drawing offset 15 | * @param count - Drawing count 16 | * @param topology - Drawing topology 17 | */ 18 | constructor(start?: number, count?: number, topology?: MeshTopology); 19 | } 20 | -------------------------------------------------------------------------------- /src/core/graphic/index.ts: -------------------------------------------------------------------------------- 1 | export { Buffer } from './Buffer'; 2 | export { BufferUtil } from './BufferUtil'; 3 | export { BufferBindFlag } from './enums/BufferBindFlag'; 4 | export { BufferUsage } from './enums/BufferUsage'; 5 | export { IndexFormat } from './enums/IndexFormat'; 6 | export { MeshTopology } from './enums/MeshTopology'; 7 | export { VertexElementFormat } from './enums/VertexElementFormat'; 8 | export { IndexBufferBinding } from './IndexBufferBinding'; 9 | export { Mesh } from './Mesh'; 10 | export { SubMesh } from './SubMesh'; 11 | export { VertexBufferBinding } from './VertexBufferBinding'; 12 | export { VertexElement } from './VertexElement'; 13 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 规则继承 3 | extends: ['plugin:@typescript-eslint/recommended'], 4 | // 解析器 5 | parser: '@typescript-eslint/parser', 6 | // ts插件 7 | plugins: ['@typescript-eslint'], 8 | // 规则定制 9 | rules: { 10 | 'no-unused-vars': 'off', 11 | '@typescript-eslint/no-unused-expressions': 'off', 12 | '@typescript-eslint/no-unused-vars': [ 13 | 'error', 14 | { 15 | vars: 'all', //全部声明包括全局 16 | args: 'all', //一次声明全位置 17 | ignoreRestSiblings: true, //忽略rest 18 | argsIgnorePattern: '^_', //通过lint正则 19 | varsIgnorePattern: '^_', //通过lint正则 20 | }, 21 | ], 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /dist/core/graphic/index.d.ts: -------------------------------------------------------------------------------- 1 | export { Buffer } from './Buffer'; 2 | export { BufferUtil } from './BufferUtil'; 3 | export { BufferBindFlag } from './enums/BufferBindFlag'; 4 | export { BufferUsage } from './enums/BufferUsage'; 5 | export { IndexFormat } from './enums/IndexFormat'; 6 | export { MeshTopology } from './enums/MeshTopology'; 7 | export { VertexElementFormat } from './enums/VertexElementFormat'; 8 | export { IndexBufferBinding } from './IndexBufferBinding'; 9 | export { Mesh } from './Mesh'; 10 | export { SubMesh } from './SubMesh'; 11 | export { VertexBufferBinding } from './VertexBufferBinding'; 12 | export { VertexElement } from './VertexElement'; 13 | -------------------------------------------------------------------------------- /dist/core/graphic/enums/MeshTopology.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Mesh topology. 3 | */ 4 | export declare enum MeshTopology { 5 | /** Draws a single dot */ 6 | Points = 0, 7 | /** Draws a line between a pair of vertices */ 8 | Lines = 1, 9 | /** Draws a straight line to the next vertex, and connects the last vertex back to the first */ 10 | LineLoop = 2, 11 | /** Draws a straight line to the next vertex. */ 12 | LineStrip = 3, 13 | /** Draws a triangle for a group of three vertices */ 14 | Triangles = 4, 15 | /** Draws a triangle strip */ 16 | TriangleStrip = 5, 17 | /** Draws a triangle fan */ 18 | TriangleFan = 6 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | release: 8 | name: Release 9 | runs-on: ubuntu-18.04 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | - name: Setup Node 14 | uses: actions/setup-node@v1 15 | with: 16 | node-version: 16 17 | - name: Install Dependencies 18 | run: npm install 19 | - name: Build 20 | run: npm run build 21 | - name: Release 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 24 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 25 | run: npx semantic-release 26 | -------------------------------------------------------------------------------- /dist/core/base/Util.d.ts: -------------------------------------------------------------------------------- 1 | export declare const Util: { 2 | isArray: (value: any) => boolean; 3 | isArrayLike(x: any): boolean; 4 | clone(obj: T): T; 5 | downloadBlob(blob: Blob, fileName?: string): void; 6 | }; 7 | export declare const isArrayLike: (x: any) => x is ArrayLike; 8 | /** 9 | * Fastly remove an element from array. 10 | * @param array - Array 11 | * @param item - Element 12 | */ 13 | export declare function removeFromArray(array: any[], item: any): boolean; 14 | /** 15 | * Get the value of an object or array. 16 | * @param obj Object or Array. 17 | * @returns Object value array. 18 | */ 19 | export declare function ObjectValues(obj: any): any[]; 20 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "[javascript]": { 4 | "editor.defaultFormatter": "esbenp.prettier-vscode", 5 | "editor.formatOnSave": true 6 | }, 7 | "[typescript]": { 8 | "editor.defaultFormatter": "esbenp.prettier-vscode", 9 | "editor.formatOnSave": true 10 | }, 11 | "[typescriptreact]": { 12 | "editor.defaultFormatter": "esbenp.prettier-vscode", 13 | "editor.formatOnSave": true 14 | }, 15 | "[vue]": { 16 | "editor.defaultFormatter": "esbenp.prettier-vscode", 17 | "editor.formatOnSave": true 18 | }, 19 | "compile-hero.disable-compile-files-on-did-save-code": true, 20 | "liveServer.settings.port": 5502 21 | } 22 | -------------------------------------------------------------------------------- /src/core/shaderlib/common.fs.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec3 v_worldPostion; 3 | varying vec2 v_TexCoord; 4 | uniform sampler2D u_Sampler; 5 | uniform vec3 u_pointLightPosition; 6 | uniform vec3 u_pointLightColor; 7 | uniform vec3 u_ambientightColor; 8 | void main() { 9 | vec3 normal = normalize(v_worldPostion); 10 | vec3 lightDirection = normalize(u_pointLightPosition - v_worldPostion); 11 | float nDotL = max(dot(lightDirection, normal), 0.0); 12 | vec4 textureColor = texture2D(u_Sampler, v_TexCoord); 13 | vec3 diffuse = u_pointLightColor * textureColor.rgb * nDotL; 14 | vec3 ambient = u_ambientightColor * textureColor.rgb; 15 | gl_FragColor = vec4(diffuse + ambient, textureColor.a); 16 | } 17 | -------------------------------------------------------------------------------- /src/core/shaderlib/extra/earth.fs.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 v_TexCoord; 3 | varying vec3 v_worldPostion; 4 | uniform sampler2D u_Sampler; 5 | uniform vec3 u_pointLightPosition; 6 | uniform vec3 u_pointLightColor; 7 | uniform vec3 u_ambientightColor; 8 | void main() { 9 | vec3 normal = normalize(v_worldPostion); 10 | vec3 lightDirection = normalize(u_pointLightPosition - v_worldPostion); 11 | float nDotL = max(dot(lightDirection, normal), 0.0); 12 | vec4 textureColor = texture2D(u_Sampler, v_TexCoord); 13 | vec3 diffuse = u_pointLightColor * textureColor.rgb * nDotL; 14 | vec3 ambient = u_ambientightColor * textureColor.rgb; 15 | gl_FragColor = vec4(diffuse + ambient, textureColor.a); 16 | } -------------------------------------------------------------------------------- /dist/core/graphic/VertexBufferBinding.d.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from './Buffer'; 2 | /** 3 | * Vertex buffer binding. 4 | */ 5 | export declare class VertexBufferBinding { 6 | /** Buffer to which vertex elements are bound. */ 7 | _buffer: Buffer; 8 | /** Span between each vertex. */ 9 | _stride: number; 10 | /** 11 | * Vertex buffer. 12 | */ 13 | get buffer(): Buffer; 14 | /** 15 | * Vertex buffer stride. 16 | */ 17 | get stride(): number; 18 | /** 19 | * Create vertex buffer. 20 | * @param buffer - Vertex buffer 21 | * @param stride - Vertex buffer stride 22 | */ 23 | constructor(buffer: Buffer, stride: number); 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | release: 8 | name: Docs 9 | runs-on: ubuntu-18.04 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | with: 14 | fetch-depth: 0 15 | - name: Setup Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: 16 19 | - name: Install 20 | run: | 21 | npm install 22 | npm run docs 23 | - name: Docs 24 | uses: JamesIves/github-pages-deploy-action@3.7.1 25 | with: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | BRANCH: gh-pages 28 | FOLDER: docs 29 | -------------------------------------------------------------------------------- /src/core/graphic/SubMesh.ts: -------------------------------------------------------------------------------- 1 | import { MeshTopology } from './enums/MeshTopology'; 2 | 3 | /** 4 | * Sub-mesh, mainly contains drawing information. 5 | */ 6 | export class SubMesh { 7 | /** Start drawing offset. */ 8 | start: number; 9 | /** Drawing count. */ 10 | count: number; 11 | /** Drawing topology. */ 12 | topology: MeshTopology; 13 | 14 | /** 15 | * Create a sub-mesh. 16 | * @param start - Start drawing offset 17 | * @param count - Drawing count 18 | * @param topology - Drawing topology 19 | */ 20 | constructor(start: number = 0, count: number = 0, topology: MeshTopology = MeshTopology.Triangles) { 21 | this.start = start; 22 | this.count = count; 23 | this.topology = topology; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dist/core/graphic/IndexBufferBinding.d.ts: -------------------------------------------------------------------------------- 1 | import { IndexFormat } from './enums/IndexFormat'; 2 | import { Buffer } from './Buffer'; 3 | /** 4 | * Index buffer binding. 5 | */ 6 | export declare class IndexBufferBinding { 7 | /** Index buffer bound buffer. */ 8 | _buffer: Buffer; 9 | /** Index format. */ 10 | _format: IndexFormat; 11 | /** 12 | * Index buffer. 13 | */ 14 | get buffer(): Buffer; 15 | /** 16 | * Index buffer format. 17 | */ 18 | get format(): IndexFormat; 19 | /** 20 | * Create index buffer binding. 21 | * @param buffer - Index buffer 22 | * @param format - Index buffer format 23 | */ 24 | constructor(buffer: Buffer, format: IndexFormat); 25 | } 26 | -------------------------------------------------------------------------------- /dist/geographic/Ellipsoid.d.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from '../math'; 2 | export declare class Ellipsoid { 3 | static readonly Wgs84: Ellipsoid; 4 | static readonly ScaledWgs84: Ellipsoid; 5 | static readonly UnitSphere: Ellipsoid; 6 | private readonly _radii; 7 | private readonly _radiiSquared; 8 | private readonly _oneOverRadiiSquared; 9 | /** The tree radii of the ellipsoid. */ 10 | get radii(): Vector3; 11 | /** The squares corresponding to the three radii of the ellipsoid. */ 12 | get radiiSquared(): Vector3; 13 | /** The inverse of the square corresponding to the three radii of the ellipsoid. */ 14 | get oneOverRadiiSquared(): Vector3; 15 | constructor(a: number, b: number, c: number); 16 | } 17 | -------------------------------------------------------------------------------- /dist/core/Canvas.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Encapsulate canvas tag. 3 | */ 4 | export declare class Canvas { 5 | /** HTML canvas element. */ 6 | _canvas: HTMLCanvasElement; 7 | private _width; 8 | private _height; 9 | /** Canvas element width. */ 10 | get width(): number; 11 | set width(value: number); 12 | /** Canvas element height. */ 13 | get height(): number; 14 | set height(value: number); 15 | /** 16 | * Resize by client size. 17 | * @param pixelRatio Device pixel ratio. 18 | */ 19 | resizeByClientSize(pixelRatio?: number): void; 20 | /** 21 | * Wrap the canvas element. 22 | * @param canvas HTML canvas element. 23 | */ 24 | constructor(canvas: HTMLCanvasElement); 25 | } 26 | -------------------------------------------------------------------------------- /src/core/graphic/VertexBufferBinding.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from './Buffer'; 2 | 3 | /** 4 | * Vertex buffer binding. 5 | */ 6 | export class VertexBufferBinding { 7 | /** Buffer to which vertex elements are bound. */ 8 | _buffer: Buffer; 9 | /** Span between each vertex. */ 10 | _stride: number; 11 | 12 | /** 13 | * Vertex buffer. 14 | */ 15 | get buffer(): Buffer { 16 | return this._buffer; 17 | } 18 | 19 | /** 20 | * Vertex buffer stride. 21 | */ 22 | get stride(): number { 23 | return this._stride; 24 | } 25 | 26 | /** 27 | * Create vertex buffer. 28 | * @param buffer - Vertex buffer 29 | * @param stride - Vertex buffer stride 30 | */ 31 | constructor(buffer: Buffer, stride: number) { 32 | this._buffer = buffer; 33 | this._stride = stride; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /dist/core/material/ImageMaterial.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { Shader } from '../shader'; 3 | import { Texture2D } from '../texture'; 4 | import { Material } from './Material'; 5 | /** 6 | * Image materials using 2D textures to display the earth, raster tiles, etc. 7 | */ 8 | export declare class ImageMaterial extends Material { 9 | /** The texture used by the image material. */ 10 | texture2d: Texture2D; 11 | /** The address of the texture sampler in the shader. */ 12 | static _sampleprop: import("../shader").ShaderProperty; 13 | constructor(engine: Engine, shader: Shader, url: string); 14 | /** 15 | * Load texture image according to url. 16 | * @param url Texture image url. 17 | * @returns Promise 18 | */ 19 | private loadTexture; 20 | } 21 | -------------------------------------------------------------------------------- /src/core/lighting/AmbientLight.ts: -------------------------------------------------------------------------------- 1 | import { Shader, ShaderData, ShaderProperty } from '../shader'; 2 | import { Color } from '../../math'; 3 | 4 | // 这个不用继承Light,因为只需要颜色 5 | /** 6 | * Ambient light. 7 | */ 8 | export class AmbientLight { 9 | /** Get the address of the point ambient color uniform variable in the shader. */ 10 | private static _colorProperty: ShaderProperty = Shader.getPropertyByName('u_diffuseSpecularAmbientShininess'); 11 | /** The color of the light. */ 12 | color: Color; 13 | 14 | constructor(color: Color) { 15 | this.color = color; 16 | } 17 | 18 | /** 19 | * Set variable value in shader. 20 | * @param shaderData Shader data. 21 | */ 22 | _updateShaderData(shaderData: ShaderData): void { 23 | const color = this.color; 24 | shaderData.setColor(AmbientLight._colorProperty, color); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/core/shader/ShaderPool.ts: -------------------------------------------------------------------------------- 1 | import skyboxFs from '../shaderlib/extra/skybox.fs.glsl'; 2 | import skyboxVs from '../shaderlib/extra/skybox.vs.glsl'; 3 | import rayCastedGlobeFs from '../shaderlib/extra/rayCastedGlobe.fs.glsl'; 4 | import rayCastedGlobeVs from '../shaderlib/extra/rayCastedGlobe.vs.glsl'; 5 | import commonFs from '../shaderlib/common.fs.glsl'; 6 | import commonVs from '../shaderlib/common.vs.glsl'; 7 | import { Shader } from './Shader'; 8 | 9 | /** 10 | * Engine built-in shader pool. 11 | */ 12 | export class ShaderPool { 13 | /** 14 | * Created by Shader based on fragment and vertex shader code. 15 | */ 16 | static init(): void { 17 | Shader.create('skybox', skyboxVs, skyboxFs); 18 | Shader.create('common', commonVs, commonFs); 19 | Shader.create('rayCastedGlobe', rayCastedGlobeVs, rayCastedGlobeFs); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/core/graphic/IndexBufferBinding.ts: -------------------------------------------------------------------------------- 1 | import { IndexFormat } from './enums/IndexFormat'; 2 | import { Buffer } from './Buffer'; 3 | 4 | /** 5 | * Index buffer binding. 6 | */ 7 | export class IndexBufferBinding { 8 | /** Index buffer bound buffer. */ 9 | _buffer: Buffer; 10 | /** Index format. */ 11 | _format: IndexFormat; 12 | 13 | /** 14 | * Index buffer. 15 | */ 16 | get buffer(): Buffer { 17 | return this._buffer; 18 | } 19 | 20 | /** 21 | * Index buffer format. 22 | */ 23 | get format(): IndexFormat { 24 | return this._format; 25 | } 26 | 27 | /** 28 | * Create index buffer binding. 29 | * @param buffer - Index buffer 30 | * @param format - Index buffer format 31 | */ 32 | constructor(buffer: Buffer, format: IndexFormat) { 33 | this._buffer = buffer; 34 | this._format = format; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/core/UpdateFlagManager.ts: -------------------------------------------------------------------------------- 1 | import { UpdateFlag } from './UpdateFlag'; 2 | 3 | /** 4 | * @internal 5 | */ 6 | export class UpdateFlagManager { 7 | /** @internal */ 8 | _updateFlags: UpdateFlag[] = []; 9 | 10 | /** 11 | * Create a UpdateFlag. 12 | * @returns - The UpdateFlag. 13 | */ 14 | createFlag(type: new () => T): T { 15 | const flag = new type(); 16 | this.addFlag(flag); 17 | return flag; 18 | } 19 | 20 | /** 21 | * Add a UpdateFlag. 22 | * @param flag - The UpdateFlag. 23 | */ 24 | addFlag(flag: UpdateFlag): void { 25 | this._updateFlags.push(flag); 26 | flag._flagManagers.push(this); 27 | } 28 | 29 | /** 30 | * Dispatch. 31 | */ 32 | dispatch(param?: Object): void { 33 | const updateFlags = this._updateFlags; 34 | for (let i = updateFlags.length - 1; i >= 0; i--) { 35 | updateFlags[i].dispatch(param); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/config/skybox.ts: -------------------------------------------------------------------------------- 1 | import { DataType } from '../core'; 2 | 3 | export const skyStarConfig = [ 4 | { 5 | target: DataType.TEXTURE_CUBE_MAP_POSITIVE_X, 6 | url: 'http://121.199.160.202/images/skybox/tycho2t3_80_mx.jpg', 7 | }, 8 | { 9 | target: DataType.TEXTURE_CUBE_MAP_NEGATIVE_X, 10 | url: 'http://121.199.160.202/images/skybox/tycho2t3_80_px.jpg', 11 | }, 12 | { 13 | target: DataType.TEXTURE_CUBE_MAP_POSITIVE_Y, 14 | url: 'http://121.199.160.202/images/skybox/tycho2t3_80_py.jpg', 15 | }, 16 | { 17 | target: DataType.TEXTURE_CUBE_MAP_NEGATIVE_Y, 18 | url: 'http://121.199.160.202/images/skybox/tycho2t3_80_my.jpg', 19 | }, 20 | { 21 | target: DataType.TEXTURE_CUBE_MAP_POSITIVE_Z, 22 | url: 'http://121.199.160.202/images/skybox/tycho2t3_80_mz.jpg', 23 | }, 24 | { 25 | target: DataType.TEXTURE_CUBE_MAP_NEGATIVE_Z, 26 | url: 'http://121.199.160.202/images/skybox/tycho2t3_80_pz.jpg', 27 | }, 28 | ]; 29 | -------------------------------------------------------------------------------- /dist/core/Background.d.ts: -------------------------------------------------------------------------------- 1 | import { Color } from '../math'; 2 | import { Engine } from './Engine'; 3 | import { BackgroundMode } from './enums/BackgroundMode'; 4 | import { Mesh } from './graphic'; 5 | import { Material } from './material'; 6 | /** 7 | * Background of the scene. 8 | */ 9 | export declare class Background { 10 | private _engine; 11 | /** 12 | * The pattern of the background, which may be a single color, a skybox or a picture texture. 13 | */ 14 | mode: BackgroundMode; 15 | /** Grid for background. */ 16 | _mesh: Mesh; 17 | /** The material used for the background. */ 18 | _material: Material; 19 | /** Fixed color before skybox or texture is loaded successfully. */ 20 | solidColor: Color; 21 | constructor(_engine: Engine); 22 | /** 23 | * Background with flat grid. 24 | * @param engine Engine instance. 25 | * @returns Mesh 26 | */ 27 | private _createPlane; 28 | } 29 | -------------------------------------------------------------------------------- /src/core/UpdateFlag.ts: -------------------------------------------------------------------------------- 1 | import { removeFromArray } from './base/Util'; 2 | import { UpdateFlagManager } from './UpdateFlagManager'; 3 | 4 | /** 5 | * Used to update tags. 6 | */ 7 | export abstract class UpdateFlag { 8 | /** @internal */ 9 | _flagManagers: UpdateFlagManager[] = []; 10 | 11 | /** 12 | * Dispatch. 13 | * @param param - Parameter 14 | */ 15 | abstract dispatch(param?: Object): void; 16 | 17 | /** 18 | * Clear. 19 | */ 20 | clearFromManagers(): void { 21 | this._removeFromManagers(); 22 | this._flagManagers.length = 0; 23 | } 24 | 25 | /** 26 | * Destroy. 27 | */ 28 | destroy(): void { 29 | this._removeFromManagers(); 30 | this._flagManagers = null; 31 | } 32 | 33 | private _removeFromManagers(): void { 34 | const flagManagers = this._flagManagers; 35 | for (let i = 0, n = flagManagers.length; i < n; i++) { 36 | removeFromArray(flagManagers[i]._updateFlags, this); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 一行最多 120 字符 3 | printWidth: 120, 4 | // 使用 2 个空格缩进 5 | tabWidth: 2, 6 | // 不使用缩进符,而使用空格 7 | useTabs: false, 8 | // 行尾需要有分号 9 | semi: true, 10 | // 使用单引号 11 | singleQuote: true, 12 | // 对象的 key 仅在必要时用引号 13 | quoteProps: 'as-needed', 14 | // jsx 不使用单引号,而使用双引号 15 | jsxSingleQuote: false, 16 | // 末尾需要有逗号 17 | trailingComma: 'all', 18 | // 大括号内的首尾需要空格 19 | bracketSpacing: true, 20 | // jsx 标签的反尖括号需要换行 21 | bracketSameLine: false, 22 | // 箭头函数,只有一个参数的时候,也需要括号 23 | arrowParens: 'always', 24 | // 每个文件格式化的范围是文件的全部内容 25 | rangeStart: 0, 26 | rangeEnd: Infinity, 27 | // 不需要写文件开头的 @prettier 28 | requirePragma: false, 29 | // 不需要自动在文件开头插入 @prettier 30 | insertPragma: false, 31 | // 使用默认的折行标准 32 | proseWrap: 'preserve', 33 | // 根据显示样式决定 html 要不要折行 34 | htmlWhitespaceSensitivity: 'css', 35 | // 换行符使用 lf 36 | endOfLine: 'lf', 37 | // 格式化内嵌代码 38 | embeddedLanguageFormatting: 'auto', 39 | }; 40 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 25 | 26 | 27 | your browser not support canvas 28 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/core/lighting/Light.ts: -------------------------------------------------------------------------------- 1 | import { Matrix4 } from '../../math'; 2 | import { Transform } from '../Transform'; 3 | 4 | /** 5 | * Lighting model base class. 6 | */ 7 | export class Light { 8 | // TODO: 这个抽的不好,只有点光源需要位 9 | /** Light source position. */ 10 | protected transform: Transform; 11 | 12 | private _viewMat: Matrix4; 13 | private _inverseViewMat: Matrix4; 14 | 15 | // 这个暂时没什么用 16 | // 因为我们的点光源采用的是世界坐标系 17 | /** 18 | * Get the view matrix of the light source position. 19 | */ 20 | get viewMatrix() { 21 | if (!this._viewMat) this._viewMat = new Matrix4(); 22 | Matrix4.invert(this.transform.worldMatrix, this._viewMat); 23 | return this._viewMat; 24 | } 25 | 26 | /** 27 | * Get the inverse of the view matrix for the light source position. 28 | */ 29 | get inverseViewMatrix() { 30 | if (!this._inverseViewMat) this._inverseViewMat = new Matrix4(); 31 | Matrix4.invert(this.viewMatrix, this._inverseViewMat); 32 | return this._inverseViewMat; 33 | } 34 | 35 | constructor() { 36 | this.transform = new Transform(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dist/core/material/SkyBoxMaterial.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { Material } from '../material'; 3 | import { TextureCube } from '../texture/TextureCube'; 4 | declare type IFaceInfo = { 5 | target: number; 6 | url: string; 7 | }; 8 | /** 9 | * A skybox material built with a cube texture, used to display the starry sky, etc. 10 | */ 11 | export declare class SkyBoxMaterial extends Material { 12 | /** Cube texture. */ 13 | textureCube: TextureCube; 14 | /** Six sided information array. */ 15 | faceInfos: IFaceInfo[]; 16 | /** Get the sampler for the cube texture in the shader. */ 17 | static _skyboxprop: import("../shader").ShaderProperty; 18 | constructor(engine: Engine, faceInfos: IFaceInfo[]); 19 | /** 20 | * According image url load image. 21 | * @param url Image url. 22 | * @returns Success return html image element, otherwise return error message. 23 | */ 24 | private loadImage; 25 | /** 26 | * Set cube image source when image success load. 27 | */ 28 | private initCubeMap; 29 | } 30 | export {}; 31 | -------------------------------------------------------------------------------- /dist/core/base/Time.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tools for calculating the time per frame. 3 | */ 4 | export declare class Time { 5 | private _clock; 6 | private _timeScale; 7 | private _deltaTime; 8 | private _startTime; 9 | private _lastTickTime; 10 | /** 11 | * Constructor of the Time. 12 | */ 13 | constructor(); 14 | /** 15 | * Set the current time as the end of rendering marker. 16 | */ 17 | reset(): void; 18 | /** 19 | * Current Time 20 | */ 21 | get nowTime(): number; 22 | /** 23 | * Time between two ticks 24 | */ 25 | get deltaTime(): number; 26 | /** 27 | * Scaled delta time. 28 | */ 29 | get timeScale(): number; 30 | set timeScale(s: number); 31 | /** 32 | * Unscaled delta time. 33 | */ 34 | get unscaledDeltaTime(): number; 35 | /** 36 | * The elapsed time, after the clock is initialized. 37 | */ 38 | get timeSinceStartup(): number; 39 | /** 40 | * Call every frame, update delta time and other data. 41 | */ 42 | tick(): void; 43 | } 44 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import typescript from 'rollup-plugin-typescript2'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import glslify from 'rollup-plugin-glslify'; 5 | import serve from 'rollup-plugin-serve'; 6 | 7 | const path = require('path'); 8 | 9 | const { NODE_ENV } = process.env; 10 | 11 | export default [ 12 | { 13 | input: './src/index.ts', 14 | output: [ 15 | { 16 | dir: 'dist', 17 | format: 'cjs', 18 | entryFileNames: '[name].cjs.js', 19 | }, 20 | { 21 | dir: 'dist', 22 | format: 'esm', 23 | entryFileNames: '[name].esm.js', 24 | }, 25 | ], 26 | plugins: [ 27 | resolve(), 28 | glslify({ 29 | include: [/\.glsl$/], 30 | }), 31 | commonjs(), 32 | typescript({ tsconfig: path.resolve(__dirname, 'tsconfig.json') }), 33 | NODE_ENV === 'development' 34 | ? serve({ 35 | open: true, 36 | contentBase: ['public', 'dist'], 37 | port: 9999, 38 | }) 39 | : null, 40 | ], 41 | }, 42 | ]; 43 | -------------------------------------------------------------------------------- /test/geographic/Ellipsoid.test.ts: -------------------------------------------------------------------------------- 1 | import { Ellipsoid } from '../../src/geographic'; 2 | 3 | describe('Ellipsoid', function () { 4 | it('Customize ellipsoid', () => { 5 | let ellipsoid = new Ellipsoid(9, 9, 9); 6 | expect(ellipsoid.radii.x).toBe(9); 7 | expect(ellipsoid.radii.y).toBe(9); 8 | expect(ellipsoid.radii.z).toBe(9); 9 | expect(ellipsoid.radiiSquared.x).toBe(81); 10 | expect(ellipsoid.oneOverRadiiSquared.x).toBe(1 / 81); 11 | }); 12 | 13 | it('Wgs84 ellipsoid', () => { 14 | expect(Ellipsoid.Wgs84.radii.x).toBe(6378137.0); 15 | expect(Ellipsoid.Wgs84.radii.y).toBe(6378137.0); 16 | expect(Ellipsoid.Wgs84.radii.z).toBe(6356752.314245); 17 | }); 18 | 19 | it('ScaledWgs84 ellipsoid', () => { 20 | expect(Ellipsoid.ScaledWgs84.radii.x).toBe(1.0); 21 | expect(Ellipsoid.ScaledWgs84.radii.y).toBe(1.0); 22 | expect(Ellipsoid.ScaledWgs84.radii.z).toBe(6356752.314245 / 6378137.0); 23 | }); 24 | 25 | it('UnitSphere ellipsoid', () => { 26 | expect(Ellipsoid.UnitSphere.radii.x).toBe(1.0); 27 | expect(Ellipsoid.UnitSphere.radii.y).toBe(1.0); 28 | expect(Ellipsoid.UnitSphere.radii.z).toBe(1.0); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /dist/core/Entity.d.ts: -------------------------------------------------------------------------------- 1 | import { Mesh } from './graphic'; 2 | import { Material } from './material'; 3 | import { Transform } from './Transform'; 4 | /** 5 | * Entity classes in the scene. 6 | */ 7 | export declare class Entity { 8 | /** Entity count. */ 9 | static _count: number; 10 | /** Entity count. */ 11 | id: number; 12 | /** Entity name. */ 13 | name: string; 14 | /** Entity mesh. */ 15 | mesh: Mesh; 16 | /** Entity material. */ 17 | material: Material; 18 | /** Parent entity id. */ 19 | parent: Entity; 20 | /** Entity childrens. */ 21 | _children: Entity[]; 22 | /** Entity ransform. */ 23 | readonly transform: Transform; 24 | /** 25 | * An entity consists of meshes and materials. 26 | * @param name Entity name. 27 | * @param mesh Entity mesh. 28 | * @param material Entity material. 29 | */ 30 | constructor(name: string, mesh: Mesh, material: Material); 31 | /** 32 | * Add child entities. 33 | * @param entity Child entities to be loaded. 34 | * @returns The number of child entities. 35 | */ 36 | addEntity(entity: Entity): number; 37 | } 38 | -------------------------------------------------------------------------------- /dist/core/Scene.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from './Engine'; 2 | import { Background } from './Background'; 3 | import { Camera } from './Camera'; 4 | import { ShaderData } from './shader'; 5 | import { AmbientLight, PointLight } from './lighting'; 6 | import { RayCastedGlobe } from '../geographic/RayCastedGlobe'; 7 | export declare class Scene { 8 | readonly shaderData: ShaderData; 9 | /** The engine the scene belongs to. */ 10 | engine: Engine; 11 | /** Cameras in the scene, we only consider the case where there is only one camera in the scene. */ 12 | camera: Camera; 13 | /** The background of the scene, the default is the skybox. */ 14 | background: Background; 15 | /** Point lights in the scene. */ 16 | pointLight: PointLight; 17 | /** Ambient light in the scene. */ 18 | ambientLight: AmbientLight; 19 | /** Earth is the root entity in the scene. */ 20 | private readonly _globe; 21 | get globe(): RayCastedGlobe; 22 | /** 23 | * The camera and the earth are loaded by default inside the constructor. 24 | * @param engine The engine the scene belongs to. 25 | */ 26 | constructor(engine: Engine); 27 | } 28 | -------------------------------------------------------------------------------- /dist/core/Renderer.d.ts: -------------------------------------------------------------------------------- 1 | import { ShaderProgram } from './shader/ShaderProgram'; 2 | import { Mesh, SubMesh } from './graphic'; 3 | /** 4 | * Renderer, each Mesh will have a renderer instance. 5 | */ 6 | export declare class Renderer { 7 | /** Current bind program. */ 8 | static glProgram: ShaderProgram; 9 | private gl; 10 | /** Array of addresses of attribute variables in shader programs. */ 11 | protected attribLocArray: number[]; 12 | /** Mesh to be rendered. */ 13 | protected readonly _primitive: Mesh; 14 | /** 15 | * Render based on rendering context and grid. 16 | * @param gl WebGL rendering context. 17 | * @param primitive Mesh to be rendered. 18 | */ 19 | constructor(gl: WebGLRenderingContext, primitive: Mesh); 20 | /** 21 | * Bind buffer and attribute. 22 | */ 23 | protected bindBufferAndAttrib(shaderProgram: ShaderProgram): void; 24 | /** 25 | * Clear depth, color buffer, etc. 26 | */ 27 | initRenderState(): void; 28 | /** 29 | * Draw the primitive. 30 | */ 31 | draw(shaderProgram: ShaderProgram, subMesh: SubMesh): void; 32 | testDraw(shaderProgram: ShaderProgram): void; 33 | } 34 | -------------------------------------------------------------------------------- /dist/geographic/RayCastedGlobe.d.ts: -------------------------------------------------------------------------------- 1 | import { ModelMesh } from '../core/mesh'; 2 | import { Ellipsoid } from './Ellipsoid'; 3 | import { Material } from '../core/material'; 4 | import { Shader, ShaderData } from '../core/shader'; 5 | import { Engine } from '../core/Engine'; 6 | import { Entity } from '../core/Entity'; 7 | export declare class RayCastedGlobe { 8 | private static _shapeProperty; 9 | private _shape; 10 | private _shader; 11 | private _mesh; 12 | private _material; 13 | /** The collection of entities under the earth. */ 14 | entities: Entity[]; 15 | /** The ellipsoid parameters corresponding to the sphere. */ 16 | get shape(): Ellipsoid; 17 | /** Cube mesh for GPU ray tracing. */ 18 | get mesh(): ModelMesh; 19 | /** The material of the sphere selection. */ 20 | get material(): Material; 21 | /** The shader of the sphere. */ 22 | get shader(): Shader; 23 | /** 24 | * Create a cube grid and build a picture material based on the engine. 25 | * @param engine Engine instance. 26 | */ 27 | constructor(engine: Engine); 28 | /** 29 | * Upload the parameters of the ellipsoid to the GPU. 30 | * @param shaderData Scene shaderdata. 31 | */ 32 | uploadShaderData(shaderData: ShaderData): void; 33 | } 34 | -------------------------------------------------------------------------------- /dist/core/texture/TextureCube.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { TextureFormat } from './enums/TextureFormat'; 3 | import { Texture } from './Texture'; 4 | /** 5 | * Cube texture. 6 | */ 7 | export declare class TextureCube extends Texture { 8 | /** 9 | * Create TextureCube. 10 | * @param engine Define the engine to use to render this texture. 11 | * @param size Texture size. texture width must be equal to height in cube texture. 12 | * @param format Texture format,default TextureFormat.R8G8B8A8. 13 | * @param mipmap Whether to use multi-level texture. 14 | */ 15 | constructor(engine: Engine, size: number, format?: TextureFormat, mipmap?: boolean); 16 | /** 17 | * Set texture based on pixel buffer. 18 | * @param face Which side of the cube. 19 | * @param colorBuffer Color buffer. 20 | * @param mipLevel Mip level. 21 | */ 22 | setPixelBuffer(face: number, colorBuffer: ArrayBufferView, mipLevel?: number): void; 23 | /** 24 | * Set the texture according to the picture. 25 | * @param face Which side of the cube. 26 | * @param imageSource Image source. 27 | * @param mipLevel Mip level. 28 | */ 29 | setImageSource(face: number, imageSource: TexImageSource | null, mipLevel: number): void; 30 | } 31 | -------------------------------------------------------------------------------- /dist/controls/Spherical.d.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from '../math'; 2 | /** 3 | * Spherical. 4 | */ 5 | export declare class Spherical { 6 | /** Spherical radius. */ 7 | radius: number; 8 | /** In the xoy plane, the angle with the x-axis. */ 9 | phi: number; 10 | /** Angle with z-axis. */ 11 | theta: number; 12 | /** 13 | * Build the initial state of the sphere. 14 | * @param radius Spherical radius, default is 1.0. 15 | * @param phi Angle with the x-axis, default is 0. 16 | * @param theta Angle with the z-axis, default is 0. 17 | */ 18 | constructor(radius?: number, phi?: number, theta?: number); 19 | /** 20 | * Set spherical state 21 | * @param radius Spherical radius. 22 | * @param phi Angle with the x-axis. 23 | * @param theta Angle with the z-axis. 24 | * @returns Spherical. 25 | */ 26 | set(radius: number, phi: number, theta: number): this; 27 | makeSafe(): this; 28 | /** 29 | * Calculate sphere state from vector. 30 | * @param v3 Vector3. 31 | * @returns Spherical. 32 | */ 33 | setFromVec3(v3: Vector3): this; 34 | /** 35 | * Get Vector3 from sphere state. 36 | * @param v3 Vector3. 37 | * @returns Spherical. 38 | */ 39 | setToVec3(v3: Vector3): this; 40 | } 41 | -------------------------------------------------------------------------------- /dist/core/lighting/PointLight.d.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from '../../math'; 2 | import { Color } from '../../math/Color'; 3 | import { ShaderData } from '../shader'; 4 | import { Light } from './Light'; 5 | /** 6 | * Point light. 7 | */ 8 | export declare class PointLight extends Light { 9 | /** Get the address of the point light color uniform variable in the shader. */ 10 | private static _colorProperty; 11 | /** Get the address of the uniform variable of the point light position in the shader. */ 12 | private static _positionProperty; 13 | /** Blend object of color and position. */ 14 | private static _combinedData; 15 | /** The color of the light, the default is white light. */ 16 | color: Color; 17 | /** Intensity of light. */ 18 | intensity: number; 19 | /** Final light color. */ 20 | private _lightColor; 21 | /** Get the position of a point light. */ 22 | get position(): Vector3; 23 | /** 24 | * Get the final light color. 25 | */ 26 | get lightColor(): Color; 27 | constructor(position: Vector3); 28 | /** 29 | * Set variable value in shader. 30 | * @param shaderData Shader data. 31 | */ 32 | _updateShaderData(shaderData: ShaderData): void; 33 | /** 34 | * Populate federated data. 35 | */ 36 | _appendData(): void; 37 | } 38 | -------------------------------------------------------------------------------- /src/core/graphic/enums/VertexElementFormat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Vertex element format. 3 | */ 4 | export enum VertexElementFormat { 5 | /** 32-bit float */ 6 | Float, 7 | /** Two-dimensional 32-bit float */ 8 | Vector2, 9 | /** Three-dimensional 32-bit float */ 10 | Vector3, 11 | /** Four-dimensional 32-bit float */ 12 | Vector4, 13 | /** Four-dimensional 8-bit integer,range is [-128,127] */ 14 | Byte4, 15 | /** Four-dimensional 8-bit Unsigned integer, range is [0,255] */ 16 | UByte4, 17 | /** Four-dimensional 8-bit Normalized integer, range is [-1,1] */ 18 | NormalizedByte4, 19 | /** Four-dimensional 8-bit Normalized unsigned integer, range is [0,1] */ 20 | NormalizedUByte4, 21 | /** Two-dimensional 16-bit integer, range is[-32768, 32767] */ 22 | Short2, 23 | /** Two-dimensional 16-bit Unsigned integer, range is [0, 65535] */ 24 | UShort2, 25 | /** Two-dimensional 16-bit Unsigned integer, range is [-1, 1] */ 26 | NormalizedShort2, 27 | /** Two-dimensional 16-bit Normalized unsigned integer, range is [0, 1] */ 28 | NormalizedUShort2, 29 | /** Four-dimensional 16-bit integer, range is [-32768, 32767] */ 30 | Short4, 31 | /** Four-dimensional 16-bit Unsigned integer, range is [0, 65535] */ 32 | UShort4, 33 | /** Four-dimensional 16-bit Normalized integer, range is[-1, 1] */ 34 | NormalizedShort4, 35 | /** Four-dimensional 16-bit Normalized unsigned integer, range is [0, 1] */ 36 | NormalizedUShort4, 37 | } 38 | -------------------------------------------------------------------------------- /dist/core/texture/Texture2D.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { TextureFormat } from './enums/TextureFormat'; 3 | import { Texture } from './Texture'; 4 | /** 5 | * Two-dimensional texture. 6 | */ 7 | export declare class Texture2D extends Texture { 8 | /** 9 | * Create Texture2D. 10 | * @param engine Define the engine to use to render this texture. 11 | * @param width Texture width. 12 | * @param height Texture height. 13 | * @param format Texture format. default `TextureFormat.R8G8B8A8`. 14 | * @param mipmap Whether to use multi-level texture. 15 | */ 16 | constructor(engine: Engine, width: number, height: number, format?: TextureFormat, mipmap?: boolean); 17 | /** 18 | * Set texture based on pixel buffer. 19 | * @param colorBuffer Color buffer array. 20 | * @param mipLevel Mip level. 21 | * @param x Starting point x position. 22 | * @param y Starting point y position. 23 | * @param width Set width. 24 | * @param height Set height. 25 | */ 26 | setPixelBuffer(colorBuffer: ArrayBufferView, mipLevel?: number, x?: number, y?: number, width?: number, height?: number): void; 27 | /** 28 | * Set the texture according to the picture. 29 | * @param imageSource Image source. 30 | * @param mipLevel Mip level. 31 | * @param flipY Y axis reversed. 32 | */ 33 | setImageSource(imageSource: TexImageSource, mipLevel: number, flipY: boolean): void; 34 | } 35 | -------------------------------------------------------------------------------- /src/core/Entity.ts: -------------------------------------------------------------------------------- 1 | import { Mesh } from './graphic'; 2 | import { Material } from './material'; 3 | import { Transform } from './Transform'; 4 | 5 | /** 6 | * Entity classes in the scene. 7 | */ 8 | export class Entity { 9 | /** Entity count. */ 10 | static _count: number = 1; 11 | /** Entity count. */ 12 | id: number; 13 | /** Entity name. */ 14 | name: string; 15 | /** Entity mesh. */ 16 | mesh: Mesh; 17 | /** Entity material. */ 18 | material: Material; 19 | /** Parent entity id. */ 20 | parent: Entity; 21 | /** Entity childrens. */ 22 | _children: Entity[]; 23 | 24 | /** Entity ransform. */ 25 | readonly transform: Transform; 26 | 27 | /** 28 | * An entity consists of meshes and materials. 29 | * @param name Entity name. 30 | * @param mesh Entity mesh. 31 | * @param material Entity material. 32 | */ 33 | constructor(name: string, mesh: Mesh, material: Material) { 34 | this.name = name; 35 | this.id = Entity._count++; 36 | this.mesh = mesh; 37 | this.material = material; 38 | this.transform = new Transform(this); 39 | } 40 | 41 | /** 42 | * Add child entities. 43 | * @param entity Child entities to be loaded. 44 | * @returns The number of child entities. 45 | */ 46 | addEntity(entity: Entity): number { 47 | if (entity instanceof Entity) { 48 | if (this._children == null) { 49 | this._children = []; 50 | } 51 | this._children.push(entity); 52 | } 53 | return this._children.length; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/geographic/Ellipsoid.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from '../math'; 2 | 3 | export class Ellipsoid { 4 | public static readonly Wgs84: Ellipsoid = new Ellipsoid(6378137.0, 6378137.0, 6356752.314245); 5 | public static readonly ScaledWgs84: Ellipsoid = new Ellipsoid(1.0, 1.0, 6356752.314245 / 6378137.0); 6 | public static readonly UnitSphere: Ellipsoid = new Ellipsoid(1.0, 1.0, 1.0); 7 | 8 | private readonly _radii: Vector3; 9 | private readonly _radiiSquared: Vector3; 10 | private readonly _oneOverRadiiSquared: Vector3; 11 | 12 | /** The tree radii of the ellipsoid. */ 13 | get radii(): Vector3 { 14 | return this._radii; 15 | } 16 | 17 | /** The squares corresponding to the three radii of the ellipsoid. */ 18 | get radiiSquared(): Vector3 { 19 | return this._radiiSquared; 20 | } 21 | 22 | /** The inverse of the square corresponding to the three radii of the ellipsoid. */ 23 | get oneOverRadiiSquared(): Vector3 { 24 | return this._oneOverRadiiSquared; 25 | } 26 | 27 | constructor(a: number, b: number, c: number) { 28 | if (a <= 0 || b <= 0 || c <= 0) { 29 | throw new Error('Ellipsoid parameters are not allowed to be set to less than or equal to 0.'); 30 | } 31 | this._radii = new Vector3(a, b, c); 32 | this._radiiSquared = new Vector3(a * a, b * b, c * c); 33 | this._oneOverRadiiSquared = new Vector3( 34 | 1 / (this._radii.x * this._radii.x), 35 | 1 / (this._radii.y * this._radii.y), 36 | 1 / (this._radii.z * this._radii.z), 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dist/core/Engine.d.ts: -------------------------------------------------------------------------------- 1 | import { Canvas } from './Canvas'; 2 | import { Time } from './base'; 3 | import { Texture2D } from './texture'; 4 | import { TextureCube } from './texture/TextureCube'; 5 | /** 6 | * The engine is the big steward of all content. 7 | */ 8 | export declare class Engine { 9 | /** The canvas corresponding to the engine. */ 10 | protected _canvas: Canvas; 11 | /** WebGL rendering context. */ 12 | protected _gl: WebGLRenderingContext; 13 | /** Current active scene. */ 14 | private activeScene; 15 | /** Used to calculate the interval between each frame rendering. */ 16 | private _time; 17 | /** Easy to destroy RAF. */ 18 | private _requestId; 19 | /** Rendered 2D texture when the image has not been loaded yet. */ 20 | _whiteTexture2D: Texture2D; 21 | /** Rendered cube texture when the image has not been loaded yet. */ 22 | _whiteTextureCube: TextureCube; 23 | get canvas(): Canvas; 24 | get gl(): WebGLRenderingContext; 25 | get time(): Time; 26 | /** 27 | * Animation rendering. 28 | */ 29 | private _animate; 30 | /** 31 | * Engine instance. 32 | * @param canvasId HTML canvas id. 33 | */ 34 | constructor(canvasId: string); 35 | /** 36 | * Update all data. 37 | */ 38 | update(): void; 39 | /** 40 | * Render based on updated data. 41 | */ 42 | _render(): void; 43 | /** 44 | * Timing and rendering. 45 | */ 46 | resume(): void; 47 | /** 48 | * Engine run. 49 | */ 50 | run(): void; 51 | } 52 | -------------------------------------------------------------------------------- /dist/core/graphic/enums/VertexElementFormat.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Vertex element format. 3 | */ 4 | export declare enum VertexElementFormat { 5 | /** 32-bit float */ 6 | Float = 0, 7 | /** Two-dimensional 32-bit float */ 8 | Vector2 = 1, 9 | /** Three-dimensional 32-bit float */ 10 | Vector3 = 2, 11 | /** Four-dimensional 32-bit float */ 12 | Vector4 = 3, 13 | /** Four-dimensional 8-bit integer,range is [-128,127] */ 14 | Byte4 = 4, 15 | /** Four-dimensional 8-bit Unsigned integer, range is [0,255] */ 16 | UByte4 = 5, 17 | /** Four-dimensional 8-bit Normalized integer, range is [-1,1] */ 18 | NormalizedByte4 = 6, 19 | /** Four-dimensional 8-bit Normalized unsigned integer, range is [0,1] */ 20 | NormalizedUByte4 = 7, 21 | /** Two-dimensional 16-bit integer, range is[-32768, 32767] */ 22 | Short2 = 8, 23 | /** Two-dimensional 16-bit Unsigned integer, range is [0, 65535] */ 24 | UShort2 = 9, 25 | /** Two-dimensional 16-bit Unsigned integer, range is [-1, 1] */ 26 | NormalizedShort2 = 10, 27 | /** Two-dimensional 16-bit Normalized unsigned integer, range is [0, 1] */ 28 | NormalizedUShort2 = 11, 29 | /** Four-dimensional 16-bit integer, range is [-32768, 32767] */ 30 | Short4 = 12, 31 | /** Four-dimensional 16-bit Unsigned integer, range is [0, 65535] */ 32 | UShort4 = 13, 33 | /** Four-dimensional 16-bit Normalized integer, range is[-1, 1] */ 34 | NormalizedShort4 = 14, 35 | /** Four-dimensional 16-bit Normalized unsigned integer, range is [0, 1] */ 36 | NormalizedUShort4 = 15 37 | } 38 | -------------------------------------------------------------------------------- /dist/core/graphic/VertexElement.d.ts: -------------------------------------------------------------------------------- 1 | import { VertexElementFormat } from './enums/VertexElementFormat'; 2 | import { ElementInfo } from './BufferUtil'; 3 | /** 4 | * Vertex elements contain coordinate information, texture information, normal vector information. 5 | */ 6 | export declare class VertexElement { 7 | _glElementInfo: ElementInfo; 8 | private _semantic; 9 | private _offset; 10 | private _format; 11 | private _bindingIndex; 12 | private _instanceStepRate; 13 | /** 14 | * Vertex semantic. 15 | */ 16 | get semantic(): string; 17 | /** 18 | * Vertex data byte offset. 19 | */ 20 | get offset(): number; 21 | /** 22 | * Vertex data format. 23 | */ 24 | get format(): VertexElementFormat; 25 | /** 26 | * Vertex buffer binding index. 27 | */ 28 | get bindingIndex(): number; 29 | /** 30 | * Instance cadence, the number of instances drawn for each vertex in the buffer, non-instance elements must be 0. 31 | */ 32 | get instanceStepRate(): number; 33 | /** 34 | * Create vertex element. 35 | * @param semantic - Input vertex semantic 36 | * @param offset - Vertex data byte offset 37 | * @param format - Vertex data format 38 | * @param bindingIndex - Vertex buffer binding index 39 | * @param instanceStepRate - Instance cadence, the number of instances drawn for each vertex in the buffer, non-instance elements must be 0. 40 | */ 41 | constructor(semantic: string, offset: number, format: VertexElementFormat, bindingIndex: number, instanceStepRate?: number); 42 | } 43 | -------------------------------------------------------------------------------- /src/core/Canvas.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Encapsulate canvas tag. 3 | */ 4 | export class Canvas { 5 | /** HTML canvas element. */ 6 | _canvas: HTMLCanvasElement; 7 | 8 | private _width: number; 9 | private _height: number; 10 | 11 | /** Canvas element width. */ 12 | get width(): number { 13 | return this._width; 14 | } 15 | 16 | set width(value: number) { 17 | if (this._width !== value) { 18 | this._canvas.width = value; 19 | this._width = value; 20 | } 21 | } 22 | 23 | /** Canvas element height. */ 24 | get height(): number { 25 | return this._height; 26 | } 27 | 28 | set height(value: number) { 29 | if (this._height !== value) { 30 | this._canvas.height = value; 31 | this._height = value; 32 | } 33 | } 34 | 35 | /** 36 | * Resize by client size. 37 | * @param pixelRatio Device pixel ratio. 38 | */ 39 | resizeByClientSize(pixelRatio: number = window.devicePixelRatio): void { 40 | const webCanvas = this._canvas; 41 | if (webCanvas instanceof HTMLCanvasElement) { 42 | this.width = webCanvas.clientWidth * pixelRatio; 43 | this.height = webCanvas.clientHeight * pixelRatio; 44 | } 45 | } 46 | 47 | /** 48 | * Wrap the canvas element. 49 | * @param canvas HTML canvas element. 50 | */ 51 | constructor(canvas: HTMLCanvasElement) { 52 | const width = canvas.width; 53 | const height = canvas.height; 54 | this._canvas = canvas; 55 | this._width = width; 56 | this._height = height; 57 | // TODO: 做的不好,应该想个优雅的方法 58 | window.addEventListener('resize', () => { 59 | this.resizeByClientSize(); 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /dist/core/graphic/BufferUtil.d.ts: -------------------------------------------------------------------------------- 1 | import { BufferUsage } from './enums/BufferUsage'; 2 | import { VertexElementFormat } from './enums/VertexElementFormat'; 3 | import { DataType } from '../base/Constant'; 4 | import { IndexFormat } from './enums/IndexFormat'; 5 | /** 6 | * Information about a single vertex element. 7 | */ 8 | export interface ElementInfo { 9 | /** Number of components per vertex. */ 10 | size: number; 11 | /** Type of data. */ 12 | type: DataType; 13 | /** Whether normalization is required. */ 14 | normalized: boolean; 15 | } 16 | /** 17 | * Utility functions for processing Buffers. 18 | */ 19 | export declare class BufferUtil { 20 | /** 21 | * Obtain the usage of Buffer according to the incoming enumeration. 22 | * @param gl WebGL rendering context. 23 | * @param bufferUsage Buffer usage. 24 | * @returns The number code used by the internal buffer of gl. 25 | */ 26 | static _getGLBufferUsage(gl: WebGLRenderingContext, bufferUsage: BufferUsage): number; 27 | /** 28 | * Get index type code. 29 | * @param indexFormat Index type enumeration. 30 | * @returns The number code used by the internal type of gl. 31 | */ 32 | static _getGLIndexType(indexFormat: IndexFormat): DataType; 33 | /** 34 | * Get gl index byte count. 35 | * @param indexFormat Index type enumeration. 36 | * @returns Index byte count. 37 | */ 38 | static _getGLIndexByteCount(indexFormat: IndexFormat): DataType; 39 | /** 40 | * Returns vertex information based on the element's vertex format. 41 | */ 42 | static _getElementInfo(format: VertexElementFormat): ElementInfo; 43 | } 44 | -------------------------------------------------------------------------------- /src/core/material/ImageMaterial.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { Shader } from '../shader'; 3 | import { Texture2D, TextureFormat } from '../texture'; 4 | import { Material } from './Material'; 5 | 6 | /** 7 | * Image materials using 2D textures to display the earth, raster tiles, etc. 8 | */ 9 | export class ImageMaterial extends Material { 10 | /** The texture used by the image material. */ 11 | texture2d: Texture2D; 12 | /** The address of the texture sampler in the shader. */ 13 | static _sampleprop = Shader.getPropertyByName('u_sampler'); 14 | 15 | // TODO: 应该建立一个shader池,这样就不用再传入shader了 16 | constructor(engine: Engine, shader: Shader, url: string) { 17 | super(engine, shader); 18 | const shaderData = this.shaderData; 19 | this.loadTexture(url) 20 | .then((image) => { 21 | this.texture2d = new Texture2D(engine, image.width, image.height, TextureFormat.R8G8B8, false); 22 | this.texture2d.setImageSource(image, 0, true); 23 | shaderData.setTexture(ImageMaterial._sampleprop, this.texture2d); 24 | }) 25 | .catch((error) => { 26 | throw error; 27 | }); 28 | } 29 | 30 | /** 31 | * Load texture image according to url. 32 | * @param url Texture image url. 33 | * @returns Promise 34 | */ 35 | private loadTexture(url: string): Promise { 36 | return new Promise((resolve, reject) => { 37 | let image: HTMLImageElement = new Image(); 38 | image.onload = () => { 39 | resolve(image); 40 | }; 41 | image.onerror = (error) => { 42 | reject(error); 43 | }; 44 | image.src = url; 45 | image.crossOrigin = 'anonymous'; 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/core/Background.ts: -------------------------------------------------------------------------------- 1 | import { Color, Vector3 } from '../math'; 2 | import { Engine } from './Engine'; 3 | import { BackgroundMode } from './enums/BackgroundMode'; 4 | import { Mesh } from './graphic'; 5 | import { Material } from './material'; 6 | import { SkyBoxMaterial } from './material/SkyBoxMaterial'; 7 | import { ModelMesh } from './mesh'; 8 | import { skyStarConfig } from '../config'; 9 | 10 | /** 11 | * Background of the scene. 12 | */ 13 | export class Background { 14 | /** 15 | * The pattern of the background, which may be a single color, a skybox or a picture texture. 16 | */ 17 | mode: BackgroundMode = BackgroundMode.SolidColor; 18 | 19 | /** Grid for background. */ 20 | _mesh: Mesh; 21 | /** The material used for the background. */ 22 | _material: Material; 23 | 24 | /** Fixed color before skybox or texture is loaded successfully. */ 25 | solidColor: Color = new Color(0.25, 0.25, 0.25, 1.0); 26 | 27 | constructor(private _engine: Engine) { 28 | this._mesh = this._createPlane(this._engine); 29 | this._material = new SkyBoxMaterial(this._engine, skyStarConfig); 30 | } 31 | 32 | /** 33 | * Background with flat grid. 34 | * @param engine Engine instance. 35 | * @returns Mesh 36 | */ 37 | private _createPlane(engine: Engine): ModelMesh { 38 | const mesh = new ModelMesh(engine.gl); 39 | // const indices = new Uint8Array([0, 3, 1, 1, 3, 2]); 40 | 41 | const positions: Vector3[] = [ 42 | new Vector3(-1, -1, 0), 43 | new Vector3(1, -1, 0), 44 | new Vector3(-1, 1, 0), 45 | new Vector3(-1, 1, 0), 46 | new Vector3(1, -1, 0), 47 | new Vector3(1, 1, 0), 48 | ]; 49 | 50 | mesh.setPositions(positions); 51 | // mesh.setIndices(indices); 52 | 53 | mesh.uploadData(false); 54 | mesh.addSubMesh(0, 6); 55 | return mesh; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/core/base/Time.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tools for calculating the time per frame. 3 | */ 4 | export class Time { 5 | private _clock: { now: () => number }; 6 | 7 | private _timeScale: number; 8 | 9 | private _deltaTime: number; 10 | 11 | private _startTime: number; 12 | 13 | private _lastTickTime: number; 14 | /** 15 | * Constructor of the Time. 16 | */ 17 | constructor() { 18 | this._clock = performance ? performance : Date; 19 | 20 | this._timeScale = 1.0; 21 | this._deltaTime = 0.0001; 22 | 23 | const now = this._clock.now(); 24 | this._startTime = now; 25 | this._lastTickTime = now; 26 | } 27 | 28 | /** 29 | * Set the current time as the end of rendering marker. 30 | */ 31 | reset() { 32 | this._lastTickTime = this._clock.now(); 33 | } 34 | 35 | /** 36 | * Current Time 37 | */ 38 | get nowTime(): number { 39 | return this._clock.now(); 40 | } 41 | 42 | /** 43 | * Time between two ticks 44 | */ 45 | get deltaTime(): number { 46 | return this._deltaTime; 47 | } 48 | 49 | /** 50 | * Scaled delta time. 51 | */ 52 | get timeScale(): number { 53 | return this._timeScale; 54 | } 55 | set timeScale(s) { 56 | this._timeScale = s; 57 | } 58 | 59 | /** 60 | * Unscaled delta time. 61 | */ 62 | get unscaledDeltaTime(): number { 63 | return this._deltaTime / this._timeScale; 64 | } 65 | 66 | /** 67 | * The elapsed time, after the clock is initialized. 68 | */ 69 | get timeSinceStartup(): number { 70 | return this.nowTime - this._startTime; 71 | } 72 | 73 | /** 74 | * Call every frame, update delta time and other data. 75 | */ 76 | public tick(): void { 77 | const now = this.nowTime; 78 | this._deltaTime = (now - this._lastTickTime) * this._timeScale; 79 | this._lastTickTime = now; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /dist/core/shader/Shader.d.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { ShaderDataGroup } from './enums/ShaderDataGroup'; 3 | import { ShaderProgram } from './ShaderProgram'; 4 | import { ShaderProperty } from './ShaderProperty'; 5 | /** 6 | * Shader containing vertex and fragment source. 7 | */ 8 | export declare class Shader { 9 | /** Shader counter. */ 10 | private static _shaderCounter; 11 | /** Shader map. */ 12 | private static _shaderMap; 13 | /** Shader counter. */ 14 | private static _propertyNameMap; 15 | /** The name of shader. */ 16 | readonly name: string; 17 | /** @internal */ 18 | _shaderId: number; 19 | /** Vertex shader source. */ 20 | private _vertexSource; 21 | /** Fragment shader source. */ 22 | private _fragmentSource; 23 | private constructor(); 24 | /** 25 | * @internal 26 | */ 27 | static _getShaderPropertyGroup(propertyName: string): ShaderDataGroup | null; 28 | /** 29 | * Get shader property by name. 30 | * @param name - Name of the shader property 31 | * @returns Shader property 32 | */ 33 | static getPropertyByName(name: string): ShaderProperty; 34 | /** 35 | * Create a shader. 36 | * @param name - Name of the shader. 37 | * @param vertexSource - Vertex source code. 38 | * @param fragmentSource - Fragment source code. 39 | */ 40 | static create(name: string, vertexSource: string, fragmentSource: string): Shader; 41 | /** 42 | * Find a shader by name. 43 | * @param name - Name of the shader 44 | */ 45 | static find(name: string): Shader; 46 | /** 47 | * Create program based on shader. 48 | * @param engine 49 | * @returns Shader program. 50 | */ 51 | _getShaderProgram(engine: Engine): ShaderProgram; 52 | } 53 | -------------------------------------------------------------------------------- /dist/math/MathUtil.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Common utility methods for math operations. 3 | */ 4 | export declare class MathUtil { 5 | /** The value for which all absolute numbers smaller than are considered equal to zero. */ 6 | static readonly zeroTolerance: number; 7 | /** The conversion factor that radian to degree. */ 8 | static readonly radToDegreeFactor: number; 9 | /** The conversion factor that degree to radian. */ 10 | static readonly degreeToRadFactor: number; 11 | /** 12 | * Clamps the specified value. 13 | * @param v - The specified value 14 | * @param min - The min value 15 | * @param max - The max value 16 | * @returns The result of clamping a value between min and max 17 | */ 18 | static clamp(v: number, min: number, max: number): number; 19 | /** 20 | * Checks if a and b are almost equals. 21 | * The absolute value of the difference between a and b is close to zero. 22 | * @param a - The left value to compare 23 | * @param b - The right value to compare 24 | * @returns True if a almost equal to b, false otherwise 25 | */ 26 | static equals(a: number, b: number): boolean; 27 | /** 28 | * Determines whether the specified v is pow2. 29 | * @param v - The specified v 30 | * @returns True if the specified v is pow2, false otherwise 31 | */ 32 | static isPowerOf2(v: number): boolean; 33 | /** 34 | * Modify the specified r from radian to degree. 35 | * @param r - The specified r 36 | * @returns The degree value 37 | */ 38 | static radianToDegree(r: number): number; 39 | /** 40 | * Modify the specified d from degree to radian. 41 | * @param d - The specified d 42 | * @returns The radian value 43 | */ 44 | static degreeToRadian(d: number): number; 45 | } 46 | -------------------------------------------------------------------------------- /src/geographic/RayCastedGlobe.ts: -------------------------------------------------------------------------------- 1 | import { ModelMesh, PrimitiveMesh } from '../core/mesh'; 2 | import { Ellipsoid } from './Ellipsoid'; 3 | import { ImageMaterial, Material } from '../core/material'; 4 | import { Shader, ShaderData, ShaderProperty } from '../core/shader'; 5 | import { Engine } from '../core/Engine'; 6 | import { earthUrl } from '../config'; 7 | import { Entity } from '../core/Entity'; 8 | 9 | export class RayCastedGlobe { 10 | private static _shapeProperty: ShaderProperty = Shader.getPropertyByName('u_globeOneOverRadiiSquared'); 11 | 12 | private _shape: Ellipsoid = Ellipsoid.ScaledWgs84; 13 | private _shader: Shader = Shader.find('rayCastedGlobe'); 14 | private _mesh: ModelMesh; 15 | private _material: Material; 16 | 17 | /** The collection of entities under the earth. */ 18 | entities: Entity[] = []; 19 | 20 | /** The ellipsoid parameters corresponding to the sphere. */ 21 | get shape() { 22 | return this._shape; 23 | } 24 | 25 | /** Cube mesh for GPU ray tracing. */ 26 | get mesh() { 27 | return this._mesh; 28 | } 29 | 30 | /** The material of the sphere selection. */ 31 | get material() { 32 | return this._material; 33 | } 34 | 35 | /** The shader of the sphere. */ 36 | get shader() { 37 | return this._shader; 38 | } 39 | 40 | /** 41 | * Create a cube grid and build a picture material based on the engine. 42 | * @param engine Engine instance. 43 | */ 44 | constructor(engine: Engine) { 45 | this._mesh = PrimitiveMesh.createCuboid(engine, 2, 2, 2); 46 | this._material = new ImageMaterial(engine, this.shader, earthUrl); 47 | } 48 | 49 | /** 50 | * Upload the parameters of the ellipsoid to the GPU. 51 | * @param shaderData Scene shaderdata. 52 | */ 53 | uploadShaderData(shaderData: ShaderData): void { 54 | shaderData.setVector3(RayCastedGlobe._shapeProperty, this.shape.oneOverRadiiSquared); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /dist/core/shader/ShaderUniform.d.ts: -------------------------------------------------------------------------------- 1 | import { Matrix4, Vector2, Vector3, Vector4, Color } from '../../math'; 2 | import { Texture } from '../texture'; 3 | import { ShaderPropertyValueType } from './ShaderData'; 4 | /** 5 | * The encapsulation of each uniform variable, including its cache value, data upload method, and data storage address. 6 | */ 7 | export declare class ShaderUniform { 8 | name: string; 9 | propertyId: number; 10 | location: WebGLUniformLocation; 11 | applyFunc: (shaderUniform: ShaderUniform, value: ShaderPropertyValueType) => void; 12 | cacheValue: number | Vector2 | Vector3 | Vector4; 13 | textureIndex: GLenum | GLenum[]; 14 | textureDefault: Texture | Texture[]; 15 | private _gl; 16 | private _colorSpace; 17 | constructor(gl: WebGLRenderingContext); 18 | upload1f(shaderUniform: ShaderUniform, value: number): void; 19 | upload1fv(shaderUniform: ShaderUniform, value: Float32Array): void; 20 | upload2fv(shaderUniform: ShaderUniform, value: Float32Array): void; 21 | upload3f(shaderUniform: ShaderUniform, value: Vector3 | Vector4 | Color): void; 22 | upload3fv(shaderUniform: ShaderUniform, value: Float32Array): void; 23 | upload4f(shaderUniform: ShaderUniform, value: Vector4 | Color): void; 24 | upload4fv(shaderUniform: ShaderUniform, value: Float32Array): void; 25 | upload1i(shaderUniform: ShaderUniform, value: number): void; 26 | upload1iv(shaderUniform: ShaderUniform, value: Int32Array): void; 27 | upload2iv(shaderUniform: ShaderUniform, value: Int32Array): void; 28 | upload3iv(shaderUniform: ShaderUniform, value: Int32Array): void; 29 | upload4iv(shaderUniform: ShaderUniform, value: Int32Array): void; 30 | uploadMat4(shaderUniform: ShaderUniform, value: Matrix4): void; 31 | uploadMat4v(shaderUniform: ShaderUniform, value: Float32Array): void; 32 | uploadTexture(shaderUniform: ShaderUniform, value: Texture): void; 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lamb3d", 3 | "version": "1.1.0", 4 | "description": "A 3d gis engine written in TypeScript and WebAssembly.", 5 | "author": "lamb", 6 | "license": "MIT", 7 | "keywords": [ 8 | "gis", 9 | "webgl", 10 | "wasm" 11 | ], 12 | "homepage": "https://github.com/gy1016/lamb3d", 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/gy1016/lamb3d" 16 | }, 17 | "files": [ 18 | "dist" 19 | ], 20 | "main": "dist/index.js", 21 | "module": "dist/index.esm.js", 22 | "types": "dist/index.d.ts", 23 | "scripts": { 24 | "dev": "cross-env NODE_ENV=development rollup -cw -m inline", 25 | "build": "rm -rf dist && rollup -c", 26 | "lint": "prettier --write .", 27 | "test": "jest", 28 | "docs": "typedoc" 29 | }, 30 | "devDependencies": { 31 | "@commitlint/cli": "^16.2.3", 32 | "@commitlint/config-conventional": "^16.2.1", 33 | "@rollup/plugin-commonjs": "^21.0.3", 34 | "@rollup/plugin-node-resolve": "^13.1.3", 35 | "@semantic-release/changelog": "^6.0.1", 36 | "@semantic-release/git": "^10.0.1", 37 | "@semantic-release/npm": "^9.0.1", 38 | "@types/jest": "^29.0.1", 39 | "@typescript-eslint/eslint-plugin": "^5.17.0", 40 | "@typescript-eslint/parser": "^5.17.0", 41 | "cross-env": "^7.0.3", 42 | "eslint": "^8.12.0", 43 | "eslint-config-prettier": "^8.5.0", 44 | "eslint-plugin-prettier": "^4.0.0", 45 | "husky": "^7.0.4", 46 | "jest": "^29.0.3", 47 | "lint-staged": "^12.3.7", 48 | "prettier": "^2.6.2", 49 | "rollup": "^2.70.1", 50 | "rollup-plugin-glslify": "^1.2.1", 51 | "rollup-plugin-serve": "^2.0.1", 52 | "rollup-plugin-typescript2": "^0.32.1", 53 | "semantic-release": "^19.0.3", 54 | "ts-jest": "^29.0.0", 55 | "tslib": "*", 56 | "typedoc": "^0.23.10", 57 | "typescript": "^4.6.3" 58 | }, 59 | "lint-staged": { 60 | "*.{ts}": [ 61 | "eslint --fix", 62 | "git add" 63 | ] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/math/MathUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Common utility methods for math operations. 3 | */ 4 | export class MathUtil { 5 | /** The value for which all absolute numbers smaller than are considered equal to zero. */ 6 | static readonly zeroTolerance: number = 1e-6; 7 | /** The conversion factor that radian to degree. */ 8 | static readonly radToDegreeFactor: number = 180 / Math.PI; 9 | /** The conversion factor that degree to radian. */ 10 | static readonly degreeToRadFactor: number = Math.PI / 180; 11 | 12 | /** 13 | * Clamps the specified value. 14 | * @param v - The specified value 15 | * @param min - The min value 16 | * @param max - The max value 17 | * @returns The result of clamping a value between min and max 18 | */ 19 | static clamp(v: number, min: number, max: number): number { 20 | return Math.max(min, Math.min(max, v)); 21 | } 22 | 23 | /** 24 | * Checks if a and b are almost equals. 25 | * The absolute value of the difference between a and b is close to zero. 26 | * @param a - The left value to compare 27 | * @param b - The right value to compare 28 | * @returns True if a almost equal to b, false otherwise 29 | */ 30 | static equals(a: number, b: number): boolean { 31 | return Math.abs(a - b) <= MathUtil.zeroTolerance; 32 | } 33 | 34 | /** 35 | * Determines whether the specified v is pow2. 36 | * @param v - The specified v 37 | * @returns True if the specified v is pow2, false otherwise 38 | */ 39 | static isPowerOf2(v: number): boolean { 40 | return (v & (v - 1)) === 0; 41 | } 42 | 43 | /** 44 | * Modify the specified r from radian to degree. 45 | * @param r - The specified r 46 | * @returns The degree value 47 | */ 48 | static radianToDegree(r: number): number { 49 | return r * MathUtil.radToDegreeFactor; 50 | } 51 | 52 | /** 53 | * Modify the specified d from degree to radian. 54 | * @param d - The specified d 55 | * @returns The radian value 56 | */ 57 | static degreeToRadian(d: number): number { 58 | return d * MathUtil.degreeToRadFactor; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/core/Scene.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from './Engine'; 2 | import { Background } from './Background'; 3 | import { Camera } from './Camera'; 4 | import { Color, Vector3 } from '../math'; 5 | import { ShaderData, ShaderDataGroup } from './shader'; 6 | import { AmbientLight, PointLight } from './lighting'; 7 | import { RayCastedGlobe } from '../geographic/RayCastedGlobe'; 8 | 9 | // TODO: 抽象出来一个EngineObject!!!! 10 | export class Scene { 11 | readonly shaderData: ShaderData = new ShaderData(ShaderDataGroup.Scene); 12 | /** The engine the scene belongs to. */ 13 | engine: Engine; 14 | /** Cameras in the scene, we only consider the case where there is only one camera in the scene. */ 15 | camera: Camera; 16 | // TODO: 要想在这里使用你就的先抽象出来 17 | /** The background of the scene, the default is the skybox. */ 18 | background: Background; 19 | // TODO: 可能有多个点光源 20 | /** Point lights in the scene. */ 21 | pointLight: PointLight; 22 | /** Ambient light in the scene. */ 23 | ambientLight: AmbientLight; 24 | /** Earth is the root entity in the scene. */ 25 | private readonly _globe: RayCastedGlobe; 26 | 27 | get globe() { 28 | return this._globe; 29 | } 30 | 31 | /** 32 | * The camera and the earth are loaded by default inside the constructor. 33 | * @param engine The engine the scene belongs to. 34 | */ 35 | constructor(engine: Engine) { 36 | this.engine = engine; 37 | 38 | // 初始化场景相机 39 | this.camera = new Camera(engine); 40 | this.camera.transform.position = new Vector3(10, 10, 10); 41 | this.camera.transform.lookAt(new Vector3(0, 0, 0)); 42 | 43 | // 初始化场景地球 44 | this._globe = new RayCastedGlobe(engine); 45 | this.globe.uploadShaderData(this.shaderData); 46 | 47 | // 初始化背景,即天空盒 48 | this.background = new Background(this.engine); 49 | 50 | // 初始化场景点光源 51 | this.pointLight = new PointLight(new Vector3(10, 10, 10)); 52 | this.pointLight._updateShaderData(this.shaderData); 53 | 54 | // 初始化场景环境光 55 | this.ambientLight = new AmbientLight(new Color(0.3, 0.3, 0.3, 1)); 56 | this.ambientLight._updateShaderData(this.shaderData); 57 | } 58 | 59 | // ! 同级不支持添加其他实体,后续可修改 60 | } 61 | -------------------------------------------------------------------------------- /src/core/graphic/VertexElement.ts: -------------------------------------------------------------------------------- 1 | import { VertexElementFormat } from './enums/VertexElementFormat'; 2 | import { ElementInfo, BufferUtil } from './BufferUtil'; 3 | 4 | /** 5 | * Vertex elements contain coordinate information, texture information, normal vector information. 6 | */ 7 | export class VertexElement { 8 | _glElementInfo: ElementInfo; 9 | 10 | private _semantic: string; 11 | private _offset: number; 12 | private _format: VertexElementFormat; 13 | private _bindingIndex: number; 14 | private _instanceStepRate: number; 15 | 16 | /** 17 | * Vertex semantic. 18 | */ 19 | get semantic(): string { 20 | return this._semantic; 21 | } 22 | 23 | /** 24 | * Vertex data byte offset. 25 | */ 26 | get offset(): number { 27 | return this._offset; 28 | } 29 | 30 | /** 31 | * Vertex data format. 32 | */ 33 | get format(): VertexElementFormat { 34 | return this._format; 35 | } 36 | 37 | /** 38 | * Vertex buffer binding index. 39 | */ 40 | get bindingIndex(): number { 41 | return this._bindingIndex; 42 | } 43 | 44 | /** 45 | * Instance cadence, the number of instances drawn for each vertex in the buffer, non-instance elements must be 0. 46 | */ 47 | get instanceStepRate(): number { 48 | return this._instanceStepRate; 49 | } 50 | 51 | /** 52 | * Create vertex element. 53 | * @param semantic - Input vertex semantic 54 | * @param offset - Vertex data byte offset 55 | * @param format - Vertex data format 56 | * @param bindingIndex - Vertex buffer binding index 57 | * @param instanceStepRate - Instance cadence, the number of instances drawn for each vertex in the buffer, non-instance elements must be 0. 58 | */ 59 | constructor( 60 | semantic: string, 61 | offset: number, 62 | format: VertexElementFormat, 63 | bindingIndex: number, 64 | instanceStepRate: number = 0, 65 | ) { 66 | this._semantic = semantic; 67 | this._offset = offset; 68 | this._format = format; 69 | this._bindingIndex = bindingIndex; 70 | this._glElementInfo = BufferUtil._getElementInfo(this.format); 71 | this._instanceStepRate = Math.floor(instanceStepRate); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /dist/core/mesh/PrimitiveMesh.d.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from '../../math'; 2 | import { ModelMesh } from './ModelMesh'; 3 | import { Engine } from '../Engine'; 4 | /** 5 | * Create a Mesh of Simple Geometry. 6 | */ 7 | export declare class PrimitiveMesh { 8 | /** 9 | * Create a cuboid mesh. 10 | * @param width - Cuboid width 11 | * @param height - Cuboid height 12 | * @param depth - Cuboid depth 13 | * @returns Cuboid model mesh 14 | */ 15 | static createCuboid(engine: Engine, width?: number, height?: number, depth?: number): ModelMesh; 16 | /** 17 | * 18 | * @param engine 引擎实例 19 | * @param level 正四面体递归切分等级 20 | * @returns 球网格实例 21 | */ 22 | static createSphereBySliceTetrahedron(engine: Engine, level?: number): ModelMesh; 23 | /** 24 | * Create a sphere mesh. 25 | * @param engine - Engine 26 | * @param radius - Sphere radius 27 | * @param segments - Number of segments 28 | * @returns Sphere model mesh 29 | */ 30 | static createSphereByParamEquation(engine: Engine, radius?: number, segments?: number): ModelMesh; 31 | /** 32 | * 33 | * @param engine - Engine 34 | * @param width - Plane width 35 | * @param height - Plane height 36 | * @param horizontalSegments - Plane horizontal segments 37 | * @param verticalSegments - Plane vertical segments 38 | * @param noLongerAccessible - Accessible 39 | * @returns Plane mesh 40 | */ 41 | static createPlane(engine: Engine, width?: number, height?: number, horizontalSegments?: number, verticalSegments?: number, noLongerAccessible?: boolean): ModelMesh; 42 | static subdivide(positions: Vector3[], indices: number[], triangle: [number, number, number], level?: number): void; 43 | /** 44 | * According a series of data ti initialize mesh 45 | * @param mesh object's mesh 46 | * @param positions object's position array 47 | * @param normals object's normals array 48 | * @param uv object's uv array 49 | * @param indices object's indices array 50 | */ 51 | private static _initialize; 52 | private static _generateIndices; 53 | } 54 | -------------------------------------------------------------------------------- /src/core/base/Util.ts: -------------------------------------------------------------------------------- 1 | export const Util = { 2 | isArray: 3 | 'isArray' in Array 4 | ? Array.isArray 5 | : (value: any): boolean => { 6 | return toString.call(value) === '[object Array]'; 7 | }, 8 | isArrayLike(x: any): boolean { 9 | return !!x && typeof x.length === 'number' && typeof x !== 'function'; 10 | }, 11 | clone(obj: T): T { 12 | if (typeof obj !== 'object' || obj === null) { 13 | return obj; 14 | } 15 | let rst; 16 | if (Util.isArrayLike(obj)) { 17 | rst = (obj as any).slice(); 18 | for (let i = 0, l = (obj as any).length; i < l; i++) { 19 | rst[i] = Util.clone(obj[i]); 20 | } 21 | } else { 22 | rst = {}; 23 | for (const k in obj) { 24 | if (obj.hasOwnProperty(k)) { 25 | rst[k] = Util.clone(obj[k]); 26 | } 27 | } 28 | } 29 | 30 | return rst; 31 | }, 32 | 33 | downloadBlob(blob: Blob, fileName: string = '') { 34 | let url = window.URL.createObjectURL(blob); 35 | let a = document.createElement('a'); 36 | document.body.appendChild(a); 37 | a.style.display = 'none'; 38 | a.href = url; 39 | a.download = fileName; 40 | a.addEventListener('click', () => { 41 | if (a.parentElement) { 42 | a.parentElement.removeChild(a); 43 | } 44 | }); 45 | a.click(); 46 | window.URL.revokeObjectURL(url); 47 | }, 48 | }; 49 | 50 | export const isArrayLike = (x: any): x is ArrayLike => 51 | x && typeof x.length === 'number' && typeof x !== 'function'; 52 | 53 | /** 54 | * Fastly remove an element from array. 55 | * @param array - Array 56 | * @param item - Element 57 | */ 58 | export function removeFromArray(array: any[], item: any): boolean { 59 | const index = array.indexOf(item); 60 | if (index < 0) { 61 | return false; 62 | } 63 | const last = array.length - 1; 64 | if (index !== last) { 65 | const end = array[last]; 66 | array[index] = end; 67 | } 68 | array.length--; 69 | return true; 70 | } 71 | 72 | /** 73 | * Get the value of an object or array. 74 | * @param obj Object or Array. 75 | * @returns Object value array. 76 | */ 77 | export function ObjectValues(obj: any) { 78 | return Object.keys(obj).map((key: any) => obj[key]); 79 | } 80 | -------------------------------------------------------------------------------- /src/controls/Spherical.ts: -------------------------------------------------------------------------------- 1 | import { Vector3, MathUtil } from '../math'; 2 | 3 | /** Prevent gimbal lock. */ 4 | const ESP = MathUtil.zeroTolerance; 5 | 6 | /** 7 | * Spherical. 8 | */ 9 | export class Spherical { 10 | /** Spherical radius. */ 11 | public radius: number; 12 | /** In the xoy plane, the angle with the x-axis. */ 13 | public phi: number; 14 | /** Angle with z-axis. */ 15 | public theta: number; 16 | 17 | /** 18 | * Build the initial state of the sphere. 19 | * @param radius Spherical radius, default is 1.0. 20 | * @param phi Angle with the x-axis, default is 0. 21 | * @param theta Angle with the z-axis, default is 0. 22 | */ 23 | constructor(radius?: number, phi?: number, theta?: number) { 24 | this.radius = radius !== undefined ? radius : 1.0; 25 | this.phi = phi !== undefined ? phi : 0; 26 | this.theta = theta !== undefined ? theta : 0; 27 | } 28 | 29 | /** 30 | * Set spherical state 31 | * @param radius Spherical radius. 32 | * @param phi Angle with the x-axis. 33 | * @param theta Angle with the z-axis. 34 | * @returns Spherical. 35 | */ 36 | set(radius: number, phi: number, theta: number) { 37 | this.radius = radius; 38 | this.phi = phi; 39 | this.theta = theta; 40 | 41 | return this; 42 | } 43 | 44 | makeSafe() { 45 | this.phi = MathUtil.clamp(this.phi, ESP, Math.PI - ESP); 46 | return this; 47 | } 48 | 49 | /** 50 | * Calculate sphere state from vector. 51 | * @param v3 Vector3. 52 | * @returns Spherical. 53 | */ 54 | setFromVec3(v3: Vector3) { 55 | this.radius = v3.length(); 56 | if (this.radius === 0) { 57 | this.theta = 0; 58 | this.phi = 0; 59 | } else { 60 | this.theta = Math.atan2(v3.x, v3.z); 61 | this.phi = Math.acos(MathUtil.clamp(v3.y / this.radius, -1, 1)); 62 | } 63 | 64 | return this; 65 | } 66 | 67 | /** 68 | * Get Vector3 from sphere state. 69 | * @param v3 Vector3. 70 | * @returns Spherical. 71 | */ 72 | setToVec3(v3: Vector3) { 73 | const sinPhiRadius = Math.sin(this.phi) * this.radius; 74 | v3.setValue( 75 | sinPhiRadius * Math.sin(this.theta), 76 | Math.cos(this.phi) * this.radius, 77 | sinPhiRadius * Math.cos(this.theta), 78 | ); 79 | 80 | return this; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /dist/core/texture/Texture.d.ts: -------------------------------------------------------------------------------- 1 | import { TextureFilterMode } from './enums/TextureFilterMode'; 2 | import { TextureFormat } from './enums/TextureFormat'; 3 | import { TextureWrapMode } from './enums/TextureWrapMode'; 4 | /** 5 | * Texture specific format information. 6 | */ 7 | export interface TextureFormatDetail { 8 | /** Texture color internal format: RGB, RGBA. */ 9 | internalFormat: GLint; 10 | /** Texture color base format: RGB, RGBA. */ 11 | baseFormat?: GLenum; 12 | /** Texel data type. */ 13 | dataType?: GLenum; 14 | /** Whether texture compression. */ 15 | isCompressed: boolean; 16 | } 17 | /** 18 | * The base class of texture, contains some common functions of texture-related classes. 19 | */ 20 | export declare abstract class Texture { 21 | name: string; 22 | /** Whether to enable mipmap. */ 23 | _mipmap: boolean; 24 | /** Texture object storage address. */ 25 | _glTexture: WebGLTexture; 26 | /** Texture sampler. */ 27 | _glTarget: number; 28 | /** Texture format detail. */ 29 | _formatDetail: TextureFormatDetail; 30 | /** Texture format. */ 31 | protected _format: TextureFormat; 32 | /** Texture width. */ 33 | protected _width: number; 34 | /** Texture height. */ 35 | protected _height: number; 36 | protected _mipmapCount: number; 37 | protected _gl: WebGLRenderingContext; 38 | private _wrapModeU; 39 | private _wrapModeV; 40 | private _filterMode; 41 | get format(): TextureFormat; 42 | get width(): number; 43 | get height(): number; 44 | get wrapModeU(): TextureWrapMode; 45 | set wrapModeU(value: TextureWrapMode); 46 | get wrapModeV(): TextureWrapMode; 47 | set wrapModeV(value: TextureWrapMode); 48 | get mipmapCount(): number; 49 | get filterMode(): TextureFilterMode; 50 | set filterMode(value: TextureFilterMode); 51 | protected _getMaxMiplevel(size: number): number; 52 | protected _getMipmapCount(): number; 53 | /** 54 | * Get detailed texture detail information based on texture format. 55 | * @param format Texture format. 56 | * @param gl WebGLRenderingContext. 57 | * @returns Texture format detail. 58 | */ 59 | static _getFormatDetail(format: TextureFormat, gl: WebGLRenderingContext): TextureFormatDetail; 60 | } 61 | -------------------------------------------------------------------------------- /src/core/texture/enums/TextureFormat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Texture format enumeration. 3 | */ 4 | export enum TextureFormat { 5 | /** RGB format,8 bits per channel. */ 6 | R8G8B8, 7 | /** RGBA format,8 bits per channel. */ 8 | R8G8B8A8, 9 | /** RGBA format,4 bits per channel. */ 10 | R4G4B4A4, 11 | /** RGBA format,5 bits in R channel,5 bits in G channel,5 bits in B channel, 1 bit in A channel. */ 12 | R5G5B5A1, 13 | /** RGB format,5 bits in R channel,6 bits in G channel,5 bits in B channel. */ 14 | R5G6B5, 15 | /** Transparent format,8 bits. */ 16 | Alpha8, 17 | /** Luminance/alpha in RGB channel, alpha in A channel. */ 18 | LuminanceAlpha, 19 | /** RGBA format,16 bits per channel. */ 20 | R16G16B16A16, 21 | /** RGBA format,32 bits per channel. */ 22 | R32G32B32A32, 23 | 24 | /** RGB compressed format。*/ 25 | DXT1, 26 | /** RGBA compressed format。*/ 27 | DXT5, 28 | /** RGB compressed format,4 bits per pixel。*/ 29 | ETC1_RGB, 30 | /** RGB compressed format,4 bits per pixel。*/ 31 | ETC2_RGB, 32 | /** RGBA compressed format,5 bits per pixel,4 bit in RGB, 1 bit in A. */ 33 | ETC2_RGBA5, 34 | /** RGB compressed format,8 bits per pixel. */ 35 | ETC2_RGBA8, 36 | /** RGB compressed format,2 bits per pixel. */ 37 | PVRTC_RGB2, 38 | /** RGBA compressed format,2 bits per pixel. */ 39 | PVRTC_RGBA2, 40 | /** RGB compressed format,4 bits per pixel. */ 41 | PVRTC_RGB4, 42 | /** RGBA compressed format,4 bits per pixel. */ 43 | PVRTC_RGBA4, 44 | /** RGB(A) compressed format,128 bits per 4x4 pixel block. */ 45 | ASTC_4x4, 46 | /** RGB(A) compressed format,128 bits per 5x5 pixel block. */ 47 | ASTC_5x5, 48 | /** RGB(A) compressed format,128 bits per 6x6 pixel block. */ 49 | ASTC_6x6, 50 | /** RGB(A) compressed format,128 bits per 8x8 pixel block. */ 51 | ASTC_8x8, 52 | /** RGB(A) compressed format,128 bits per 10x10 pixel block. */ 53 | ASTC_10x10, 54 | /** RGB(A) compressed format,128 bits per 12x12 pixel block. */ 55 | ASTC_12x12, 56 | 57 | /** Render to depth buffer,engine will automatically select the supported precision. */ 58 | Depth, 59 | /** Render to depth stencil buffer, engine will automatically select the supported precision. */ 60 | DepthStencil, 61 | /** Render to stencil buffer. */ 62 | Stencil, 63 | /** Force 16-bit depth buffer. */ 64 | Depth16, 65 | /** Force 24-bit depth buffer. */ 66 | Depth24, 67 | /** Force 32-bit depth buffer. */ 68 | Depth32, 69 | /** Force 16-bit depth + 8-bit stencil buffer. */ 70 | Depth24Stencil8, 71 | /** Force 32-bit depth + 8-bit stencil buffer. */ 72 | Depth32Stencil8, 73 | } 74 | -------------------------------------------------------------------------------- /src/core/lighting/PointLight.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from '../../math'; 2 | import { Color } from '../../math/Color'; 3 | import { Shader, ShaderData, ShaderProperty } from '../shader'; 4 | import { Light } from './Light'; 5 | 6 | /** 7 | * Point light. 8 | */ 9 | export class PointLight extends Light { 10 | // 因为可能有多个点光源 11 | /** Get the address of the point light color uniform variable in the shader. */ 12 | private static _colorProperty: ShaderProperty = Shader.getPropertyByName('u_pointLightColor'); 13 | /** Get the address of the uniform variable of the point light position in the shader. */ 14 | private static _positionProperty: ShaderProperty = Shader.getPropertyByName('u_pointLightPosition'); 15 | /** Blend object of color and position. */ 16 | private static _combinedData = { 17 | color: new Float32Array(3), 18 | position: new Float32Array(3), 19 | }; 20 | 21 | // 白光不管和什么光相乘,都保留颜色 22 | /** The color of the light, the default is white light. */ 23 | color: Color = new Color(1, 1, 1, 1); 24 | /** Intensity of light. */ 25 | intensity: number = 1.0; 26 | 27 | /** Final light color. */ 28 | private _lightColor: Color = new Color(1, 1, 1, 1); 29 | 30 | /** Get the position of a point light. */ 31 | get position(): Vector3 { 32 | return this.transform.worldPosition; 33 | } 34 | 35 | /** 36 | * Get the final light color. 37 | */ 38 | get lightColor(): Color { 39 | this._lightColor.r = this.color.r * this.intensity; 40 | this._lightColor.g = this.color.g * this.intensity; 41 | this._lightColor.b = this.color.b * this.intensity; 42 | this._lightColor.a = this.color.a * this.intensity; 43 | return this._lightColor; 44 | } 45 | 46 | constructor(position: Vector3) { 47 | super(); 48 | this.transform.worldPosition = position; 49 | } 50 | 51 | /** 52 | * Set variable value in shader. 53 | * @param shaderData Shader data. 54 | */ 55 | _updateShaderData(shaderData: ShaderData): void { 56 | this._appendData(); 57 | const data = PointLight._combinedData; 58 | 59 | shaderData.setFloatArray(PointLight._colorProperty, data.color); 60 | shaderData.setFloatArray(PointLight._positionProperty, data.position); 61 | } 62 | 63 | /** 64 | * Populate federated data. 65 | */ 66 | _appendData(): void { 67 | const data = PointLight._combinedData; 68 | const lightColor = this.lightColor; 69 | const lightPosition = this.position; 70 | 71 | data.color[0] = lightColor.r; 72 | data.color[1] = lightColor.g; 73 | data.color[2] = lightColor.b; 74 | data.position[0] = lightPosition.x; 75 | data.position[1] = lightPosition.y; 76 | data.position[2] = lightPosition.z; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/core/material/SkyBoxMaterial.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { Material } from '../material'; 3 | import { Shader } from '../shader'; 4 | import { TextureCube } from '../texture/TextureCube'; 5 | 6 | type IFaceInfo = { 7 | target: number; 8 | url: string; 9 | }; 10 | 11 | /** 12 | * A skybox material built with a cube texture, used to display the starry sky, etc. 13 | */ 14 | export class SkyBoxMaterial extends Material { 15 | /** Cube texture. */ 16 | textureCube: TextureCube; 17 | /** Six sided information array. */ 18 | faceInfos: IFaceInfo[]; 19 | /** Get the sampler for the cube texture in the shader. */ 20 | static _skyboxprop = Shader.getPropertyByName('u_Skybox'); 21 | 22 | // TODO: 抽RefObject 23 | constructor(engine: Engine, faceInfos: IFaceInfo[]) { 24 | super(engine, Shader.find('skybox')); 25 | 26 | this.faceInfos = faceInfos; 27 | 28 | this.initCubeMap(engine); 29 | } 30 | 31 | /** 32 | * According image url load image. 33 | * @param url Image url. 34 | * @returns Success return html image element, otherwise return error message. 35 | */ 36 | private loadImage(url: string): Promise { 37 | return new Promise((resolve, reject) => { 38 | const image = new Image(); 39 | image.src = url; 40 | image.crossOrigin = 'anonymous'; 41 | image.onload = () => { 42 | resolve(image); 43 | }; 44 | image.onerror = (err) => { 45 | reject(err); 46 | }; 47 | }); 48 | } 49 | 50 | /** 51 | * Set cube image source when image success load. 52 | */ 53 | private initCubeMap(engine: Engine) { 54 | const faceInfos = this.faceInfos; 55 | const n = faceInfos.length; 56 | let promises: Promise[] = []; 57 | 58 | for (let i = 0; i < n; ++i) { 59 | const { url } = this.faceInfos[i]; 60 | promises.push(this.loadImage(url)); 61 | } 62 | 63 | Promise.all(promises).then((images) => { 64 | this.textureCube = new TextureCube(this.engine, images[0].width); 65 | this.shaderData.setTexture(SkyBoxMaterial._skyboxprop, this.textureCube); 66 | 67 | this.textureCube.setImageSource(faceInfos[0].target, images[0], 0); 68 | this.textureCube.setImageSource(faceInfos[1].target, images[1], 0); 69 | this.textureCube.setImageSource(faceInfos[2].target, images[2], 0); 70 | this.textureCube.setImageSource(faceInfos[3].target, images[3], 0); 71 | this.textureCube.setImageSource(faceInfos[4].target, images[4], 0); 72 | this.textureCube.setImageSource(faceInfos[5].target, images[5], 0); 73 | 74 | const gl = engine.gl; 75 | gl.generateMipmap(gl.TEXTURE_CUBE_MAP); 76 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); 77 | }); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | # lamb3d 5 | 6 | _✨ Author: lamb ✨_ 7 |
8 | 9 |

10 | 11 | repo_lamb3d 12 | 13 | 14 | npm_lamb3d 15 | 16 | 17 | star_lamb3d 18 | 19 | 20 | release_lamb3d 21 | 22 |

23 | 24 | 25 | 26 | # Introduction 27 | 28 | A 3d gis engine written in TypeScript and WebAssembly. 29 | 30 | # Document 31 | 32 | Here you can see the mind map of the design engine, system architecture and my [brainstorming](https://www.yuque.com/shengaoyang-rl1fl/apm3zh). 33 | 34 | Documentation generated with Typedoc is [here](http://www.sgyat.cn/lamb3d/)! 35 | 36 | 37 | # Architecture 38 | 39 | The modules currently included in lamb3d are shown in the following figure: 40 | 41 | ![Engine Xmind](http://121.199.160.202/images/project/lamb3d/xmind.png) 42 | 43 | The system architecture diagram of lamb3d is as follows: 44 | 45 | ![Engine Architecture](http://121.199.160.202/images/project/lamb3d/systemstruct.png) 46 | 47 | The most important and basic module of the engine is how the program organizes and manages data and how to communicate with the GPU. The graphic module is used to create buffer objects and store vertex and index data. The architecture is as follows: 48 | 49 | ![Graphic Module](http://121.199.160.202/images/project/lamb3d/graphic.png) 50 | 51 | The shader module is used to manage the WebGL program context and data upload. The architecture is as follows: 52 | 53 | ![Shader Module](http://121.199.160.202/images/project/lamb3d/shader.png) 54 | 55 | # Usage 56 | 57 | First we use pnpm to install. 58 | 59 | ```bash 60 | pnpm install lamb3d 61 | ``` 62 | 63 | Then we create a canvas tag and specify the id. 64 | 65 | ```html 66 | Your browser does not support canvas~ 67 | ``` 68 | 69 | Finally, we write a piece of js code. 70 | 71 | ```js 72 | import { Engine } from 'lamb3d'; 73 | 74 | const lamb3d = new Engine('lamb'); 75 | lamb3d.run(); 76 | ``` 77 | 78 | Let's see the effect: 79 | 80 | ![Engine Architecture](http://121.199.160.202/images/project/lamb3d/earth.png) 81 | 82 | # Reference 83 | 84 | - oasis : https://github.com/oasis-engine/engine 85 | 86 | - cesium: https://github.com/CesiumGS/cesium 87 | 88 | - MadDream3D: https://github.com/bajieSummer/MadDream3D 89 | -------------------------------------------------------------------------------- /dist/core/texture/enums/TextureFormat.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Texture format enumeration. 3 | */ 4 | export declare enum TextureFormat { 5 | /** RGB format,8 bits per channel. */ 6 | R8G8B8 = 0, 7 | /** RGBA format,8 bits per channel. */ 8 | R8G8B8A8 = 1, 9 | /** RGBA format,4 bits per channel. */ 10 | R4G4B4A4 = 2, 11 | /** RGBA format,5 bits in R channel,5 bits in G channel,5 bits in B channel, 1 bit in A channel. */ 12 | R5G5B5A1 = 3, 13 | /** RGB format,5 bits in R channel,6 bits in G channel,5 bits in B channel. */ 14 | R5G6B5 = 4, 15 | /** Transparent format,8 bits. */ 16 | Alpha8 = 5, 17 | /** Luminance/alpha in RGB channel, alpha in A channel. */ 18 | LuminanceAlpha = 6, 19 | /** RGBA format,16 bits per channel. */ 20 | R16G16B16A16 = 7, 21 | /** RGBA format,32 bits per channel. */ 22 | R32G32B32A32 = 8, 23 | /** RGB compressed format。*/ 24 | DXT1 = 9, 25 | /** RGBA compressed format。*/ 26 | DXT5 = 10, 27 | /** RGB compressed format,4 bits per pixel。*/ 28 | ETC1_RGB = 11, 29 | /** RGB compressed format,4 bits per pixel。*/ 30 | ETC2_RGB = 12, 31 | /** RGBA compressed format,5 bits per pixel,4 bit in RGB, 1 bit in A. */ 32 | ETC2_RGBA5 = 13, 33 | /** RGB compressed format,8 bits per pixel. */ 34 | ETC2_RGBA8 = 14, 35 | /** RGB compressed format,2 bits per pixel. */ 36 | PVRTC_RGB2 = 15, 37 | /** RGBA compressed format,2 bits per pixel. */ 38 | PVRTC_RGBA2 = 16, 39 | /** RGB compressed format,4 bits per pixel. */ 40 | PVRTC_RGB4 = 17, 41 | /** RGBA compressed format,4 bits per pixel. */ 42 | PVRTC_RGBA4 = 18, 43 | /** RGB(A) compressed format,128 bits per 4x4 pixel block. */ 44 | ASTC_4x4 = 19, 45 | /** RGB(A) compressed format,128 bits per 5x5 pixel block. */ 46 | ASTC_5x5 = 20, 47 | /** RGB(A) compressed format,128 bits per 6x6 pixel block. */ 48 | ASTC_6x6 = 21, 49 | /** RGB(A) compressed format,128 bits per 8x8 pixel block. */ 50 | ASTC_8x8 = 22, 51 | /** RGB(A) compressed format,128 bits per 10x10 pixel block. */ 52 | ASTC_10x10 = 23, 53 | /** RGB(A) compressed format,128 bits per 12x12 pixel block. */ 54 | ASTC_12x12 = 24, 55 | /** Render to depth buffer,engine will automatically select the supported precision. */ 56 | Depth = 25, 57 | /** Render to depth stencil buffer, engine will automatically select the supported precision. */ 58 | DepthStencil = 26, 59 | /** Render to stencil buffer. */ 60 | Stencil = 27, 61 | /** Force 16-bit depth buffer. */ 62 | Depth16 = 28, 63 | /** Force 24-bit depth buffer. */ 64 | Depth24 = 29, 65 | /** Force 32-bit depth buffer. */ 66 | Depth32 = 30, 67 | /** Force 16-bit depth + 8-bit stencil buffer. */ 68 | Depth24Stencil8 = 31, 69 | /** Force 32-bit depth + 8-bit stencil buffer. */ 70 | Depth32Stencil8 = 32 71 | } 72 | -------------------------------------------------------------------------------- /dist/core/mesh/ModelMesh.d.ts: -------------------------------------------------------------------------------- 1 | import { Vector3, Vector2 } from '@/math'; 2 | import { Mesh } from '../graphic'; 3 | /** 4 | * Create a model from an array of information such as vertices, indices, normal vectors, etc. 5 | */ 6 | export declare class ModelMesh extends Mesh { 7 | /** The number of vertices in the model. */ 8 | private _vertexCount; 9 | /** Availability of the model. */ 10 | private _accessible; 11 | private _verticesFloat32; 12 | private _verticesUint8; 13 | /** A vertex has several elements, xyz is 3. */ 14 | private _elementCount; 15 | private _lastUploadVertexCount; 16 | /** Index format. */ 17 | private _indicesFormat; 18 | /** Index type array. */ 19 | private _indices; 20 | /** Array of vertex positions. */ 21 | private _positions; 22 | /** Array of normal vectors. */ 23 | private _normals; 24 | /** Array of texture coordinates */ 25 | private _uv; 26 | /** 27 | * Whether to access data of the mesh. 28 | */ 29 | get accessible(): boolean; 30 | /** 31 | * Vertex count of current mesh. 32 | */ 33 | get vertexCount(): number; 34 | constructor(gl: WebGLRenderingContext, name?: string); 35 | /** 36 | * Set the vertex position information of the model. 37 | * @param positions Array of model vertex coordinates. 38 | */ 39 | setPositions(positions: Vector3[]): void; 40 | /** 41 | * Get the vertex position information of the model. 42 | * @returns Array of model vertex coordinates. 43 | */ 44 | getPostions(): Vector3[]; 45 | /** 46 | * Set model normal vector. 47 | * @param normals Array of normal vectors. 48 | */ 49 | setNormals(normals: Vector3[]): void; 50 | /** 51 | * Get model normal vector. 52 | * @returns Array of normal vectors. 53 | */ 54 | getNormals(): Vector3[]; 55 | /** 56 | * Set texture coordinates. 57 | * @param uv Texture coordinates. 58 | */ 59 | setUVs(uv: Vector2[]): void; 60 | /** 61 | * Get texture coordinates. 62 | * @returns Texture coordinates. 63 | */ 64 | getUVs(): Vector2[]; 65 | /** 66 | * Set indices for the mesh. 67 | * @param indices - The indices for the mesh. 68 | */ 69 | setIndices(indices: Uint8Array | Uint16Array | Uint32Array): void; 70 | /** 71 | * Get indices for the mesh. 72 | */ 73 | getIndices(): Uint8Array | Uint16Array | Uint32Array; 74 | /** 75 | * Upload Mesh Data to the graphics API. 76 | */ 77 | uploadData(noLongerAccessible?: boolean): void; 78 | /** 79 | * Vertex elements are composed of vertex coordinates, texture coordinates, normal vectors and other information. 80 | */ 81 | private _updateVertexElements; 82 | /** 83 | * Fill the void Float32Array with postion, normal and uvs. 84 | * @param vertices void Float32Array 85 | */ 86 | private _updateVertices; 87 | } 88 | -------------------------------------------------------------------------------- /src/core/shader/Shader.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { ShaderDataGroup } from './enums/ShaderDataGroup'; 3 | import { ShaderProgram } from './ShaderProgram'; 4 | import { ShaderProperty } from './ShaderProperty'; 5 | 6 | /** 7 | * Shader containing vertex and fragment source. 8 | */ 9 | export class Shader { 10 | /** Shader counter. */ 11 | private static _shaderCounter = 0; 12 | /** Shader map. */ 13 | private static _shaderMap: Record = Object.create(null); 14 | /** Shader counter. */ 15 | private static _propertyNameMap: Record = Object.create(null); 16 | 17 | /** The name of shader. */ 18 | readonly name: string; 19 | 20 | /** @internal */ 21 | _shaderId = 0; 22 | 23 | /** Vertex shader source. */ 24 | private _vertexSource: string; 25 | /** Fragment shader source. */ 26 | private _fragmentSource: string; 27 | 28 | private constructor(name: string, vertexSource: string, fragmentSource: string) { 29 | this._shaderId = Shader._shaderCounter++; 30 | this.name = name; 31 | this._vertexSource = vertexSource; 32 | this._fragmentSource = fragmentSource; 33 | } 34 | 35 | /** 36 | * @internal 37 | */ 38 | static _getShaderPropertyGroup(propertyName: string): ShaderDataGroup | null { 39 | const shaderProperty = Shader._propertyNameMap[propertyName]; 40 | return shaderProperty?._group; 41 | } 42 | 43 | // 不存在就创建一个 44 | /** 45 | * Get shader property by name. 46 | * @param name - Name of the shader property 47 | * @returns Shader property 48 | */ 49 | static getPropertyByName(name: string): ShaderProperty { 50 | const propertyNameMap = Shader._propertyNameMap; 51 | if (propertyNameMap[name] != null) { 52 | return propertyNameMap[name]; 53 | } else { 54 | // 实例化的时候并不分配分组,即此时property还没有group属性 55 | const property = new ShaderProperty(name); 56 | propertyNameMap[name] = property; 57 | return property; 58 | } 59 | } 60 | 61 | /** 62 | * Create a shader. 63 | * @param name - Name of the shader. 64 | * @param vertexSource - Vertex source code. 65 | * @param fragmentSource - Fragment source code. 66 | */ 67 | static create(name: string, vertexSource: string, fragmentSource: string): Shader { 68 | const shaderMap = Shader._shaderMap; 69 | if (shaderMap[name]) { 70 | throw `Shader named "${name}" already exists.`; 71 | } 72 | return (shaderMap[name] = new Shader(name, vertexSource, fragmentSource)); 73 | } 74 | 75 | /** 76 | * Find a shader by name. 77 | * @param name - Name of the shader 78 | */ 79 | static find(name: string): Shader { 80 | return Shader._shaderMap[name]; 81 | } 82 | 83 | /** 84 | * Create program based on shader. 85 | * @param engine 86 | * @returns Shader program. 87 | */ 88 | _getShaderProgram(engine: Engine): ShaderProgram { 89 | // TODO: 将常量shader拼接到这里 90 | const vertexSource = this._vertexSource; 91 | const fragmentSource = this._fragmentSource; 92 | 93 | return new ShaderProgram(engine, vertexSource, fragmentSource); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/core/texture/TextureCube.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { TextureFilterMode } from './enums/TextureFilterMode'; 3 | import { TextureFormat } from './enums/TextureFormat'; 4 | import { TextureWrapMode } from './enums/TextureWrapMode'; 5 | import { Texture } from './Texture'; 6 | 7 | /** 8 | * Cube texture. 9 | */ 10 | export class TextureCube extends Texture { 11 | /** 12 | * Create TextureCube. 13 | * @param engine Define the engine to use to render this texture. 14 | * @param size Texture size. texture width must be equal to height in cube texture. 15 | * @param format Texture format,default TextureFormat.R8G8B8A8. 16 | * @param mipmap Whether to use multi-level texture. 17 | */ 18 | constructor(engine: Engine, size: number, format: TextureFormat = TextureFormat.R8G8B8A8, mipmap: boolean = true) { 19 | super(); 20 | 21 | this._mipmap = mipmap; 22 | this._width = size; 23 | this._height = size; 24 | this._format = format; 25 | this._mipmapCount = this._getMipmapCount(); 26 | 27 | this.filterMode = TextureFilterMode.Bilinear; 28 | this.wrapModeU = this.wrapModeV = TextureWrapMode.Clamp; 29 | 30 | this._gl = engine.gl; 31 | this._glTexture = this._gl.createTexture(); 32 | this._glTarget = this._gl.TEXTURE_CUBE_MAP; 33 | this._formatDetail = Texture._getFormatDetail(format, this._gl); 34 | } 35 | 36 | /** 37 | * Set texture based on pixel buffer. 38 | * @param face Which side of the cube. 39 | * @param colorBuffer Color buffer. 40 | * @param mipLevel Mip level. 41 | */ 42 | setPixelBuffer( 43 | face: number, 44 | colorBuffer: ArrayBufferView, 45 | mipLevel: number = 0, 46 | // x: number = 0, 47 | // y: number = 0, 48 | // width?: number, 49 | // height?: number, 50 | ): void { 51 | const gl = this._gl; 52 | const { internalFormat, baseFormat, dataType } = this._formatDetail; 53 | 54 | gl.bindTexture(this._glTarget, this._glTexture); 55 | 56 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0); 57 | gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0); 58 | 59 | gl.texImage2D( 60 | gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, 61 | mipLevel, 62 | internalFormat, 63 | this._width, 64 | this._height, 65 | 0, 66 | baseFormat, 67 | dataType, 68 | colorBuffer, 69 | ); 70 | } 71 | 72 | /** 73 | * Set the texture according to the picture. 74 | * @param face Which side of the cube. 75 | * @param imageSource Image source. 76 | * @param mipLevel Mip level. 77 | */ 78 | setImageSource( 79 | face: number, 80 | imageSource: TexImageSource | null, 81 | mipLevel: number, 82 | // flipY: boolean, 83 | // premultiplyAlpha: boolean, 84 | // x: number, 85 | // y: number, 86 | ): void { 87 | const gl = this._gl; 88 | const { baseFormat, dataType, internalFormat } = this._formatDetail; 89 | gl.bindTexture(this._glTarget, this._glTexture); 90 | gl.texImage2D(face, mipLevel, internalFormat, baseFormat, dataType, imageSource); 91 | gl.generateMipmap(gl.TEXTURE_CUBE_MAP); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/core/shaderlib/extra/rayCastedGlobe.fs.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | const float oneOverTwoPi = 0.15915494309189535; 4 | const float oneOverPi = 0.3183098861837907; 5 | 6 | varying vec3 v_worldPosition; 7 | uniform vec3 u_cameraPos; 8 | uniform vec3 u_cameraPosSquared; 9 | uniform vec3 u_globeOneOverRadiiSquared; 10 | uniform vec3 u_pointLightPosition; 11 | uniform vec4 u_diffuseSpecularAmbientShininess; 12 | uniform sampler2D u_sampler; 13 | 14 | 15 | struct Intersection 16 | { 17 | bool Intersects; 18 | float NearTime; 19 | float FarTime; 20 | }; 21 | 22 | Intersection RayIntersectEllipsoid(vec3 rayOrigin, vec3 rayOriginSquared, vec3 rayDirection, vec3 oneOverEllipsoidRadiiSquared) 23 | { 24 | float a = dot(rayDirection * rayDirection, oneOverEllipsoidRadiiSquared); 25 | float b = 2.0 * dot(rayOrigin * rayDirection, oneOverEllipsoidRadiiSquared); 26 | float c = dot(rayOriginSquared, oneOverEllipsoidRadiiSquared) - 1.0; 27 | float discriminant = b * b - 4.0 * a * c; 28 | 29 | if (discriminant < 0.0) 30 | { 31 | return Intersection(false, 0.0, 0.0); 32 | } 33 | else if (discriminant == 0.0) 34 | { 35 | float time = -0.5 * b / a; 36 | return Intersection(true, time, time); 37 | } 38 | 39 | float t = -0.5 * (b + (b > 0.0 ? 1.0 : -1.0) * sqrt(discriminant)); 40 | float root1 = t / a; 41 | float root2 = c / t; 42 | 43 | return Intersection(true, min(root1, root2), max(root1, root2)); 44 | } 45 | 46 | vec3 GeodeticSurfaceNormal(vec3 positionOnEllipsoid, vec3 oneOverEllipsoidRadiiSquared) 47 | { 48 | return normalize(positionOnEllipsoid * oneOverEllipsoidRadiiSquared); 49 | } 50 | 51 | float LightIntensity(vec3 normal, vec3 toLight, vec3 toEye, vec4 diffuseSpecularAmbientShininess) 52 | { 53 | vec3 toReflectedLight = reflect(-toLight, normal); 54 | 55 | float diffuse = max(dot(toLight, normal), 0.0); 56 | float specular = max(dot(toReflectedLight, toEye), 0.0); 57 | specular = pow(specular, diffuseSpecularAmbientShininess.w); 58 | 59 | return (diffuseSpecularAmbientShininess.x * diffuse) + 60 | (diffuseSpecularAmbientShininess.y * specular) + 61 | diffuseSpecularAmbientShininess.z; 62 | } 63 | 64 | vec2 ComputeTextureCoordinates(vec3 normal) 65 | { 66 | return vec2(atan(normal.x, normal.z) * oneOverTwoPi + 0.5, asin(normal.y) * oneOverPi + 0.5); 67 | } 68 | 69 | void main() 70 | { 71 | vec3 rayDirection = normalize(v_worldPosition - u_cameraPos); 72 | Intersection i = RayIntersectEllipsoid(u_cameraPos, u_cameraPosSquared, rayDirection, u_globeOneOverRadiiSquared); 73 | 74 | if (i.Intersects) 75 | { 76 | vec3 position = u_cameraPos + (i.NearTime * rayDirection); 77 | vec3 normal = GeodeticSurfaceNormal(position, u_globeOneOverRadiiSquared); 78 | 79 | vec3 toLight = normalize(u_cameraPos - position); 80 | vec3 toEye = normalize(u_cameraPos - position); 81 | 82 | float intensity = LightIntensity(normal, toLight, toEye, u_diffuseSpecularAmbientShininess); 83 | 84 | gl_FragColor = vec4(intensity * texture2D(u_sampler, ComputeTextureCoordinates(normal)).rgb, 1.0); 85 | } 86 | else 87 | { 88 | discard; 89 | } 90 | } -------------------------------------------------------------------------------- /dist/core/Camera.d.ts: -------------------------------------------------------------------------------- 1 | import { OrbitControl } from '../controls/OrbitControl'; 2 | import { Matrix4, Vector4 } from '../math'; 3 | import { Engine } from './Engine'; 4 | import { ShaderData } from './shader'; 5 | import { Transform } from './Transform'; 6 | /** 7 | * Camera. 8 | */ 9 | export declare class Camera { 10 | private static _tempViewMatrix; 11 | private _engine; 12 | get engine(): Engine; 13 | transform: Transform; 14 | private static _viewMatrixProperty; 15 | private static _projectionMatrixProperty; 16 | private static _inverseVPMatrixProperty; 17 | private static _vpMatrixProperty; 18 | private static _cameraPositionProperty; 19 | private static _cameraPosSquaredProperty; 20 | /** 21 | * Compute the inverse of the rotation translation matrix. 22 | * @param rotation - The rotation used to calculate matrix 23 | * @param translation - The translation used to calculate matrix 24 | * @param out - The calculated matrix 25 | */ 26 | private static _rotationTranslationInv; 27 | /** Shader data. */ 28 | readonly shaderData: ShaderData; 29 | /** Rendering priority - A Camera with higher priority will be rendered on top of a camera with lower priority. */ 30 | priority: number; 31 | orbitControl: OrbitControl; 32 | private _isOrthographic; 33 | private _nearClipPlane; 34 | private _farClipPlane; 35 | private _fieldOfView; 36 | private _orthographicSize; 37 | private _customAspectRatio; 38 | private _projectionMatrix; 39 | private _viewMatrix; 40 | private _viewport; 41 | private _lastAspectSize; 42 | get viewMatrix(): Readonly; 43 | set projectionMatrix(value: Matrix4); 44 | get projectionMatrix(): Matrix4; 45 | /** 46 | * Near clip plane - the closest point to the camera when rendering occurs. 47 | */ 48 | get nearClipPlane(): number; 49 | set nearClipPlane(value: number); 50 | /** 51 | * Far clip plane - the furthest point to the camera when rendering occurs. 52 | */ 53 | get farClipPlane(): number; 54 | set farClipPlane(value: number); 55 | /** 56 | * The camera's view angle. activating when camera use perspective projection. 57 | */ 58 | get fieldOfView(): number; 59 | set fieldOfView(value: number); 60 | get aspectRatio(): number; 61 | set aspectRatio(value: number); 62 | /** 63 | * Viewport, normalized expression, the upper left corner is (0, 0), and the lower right corner is (1, 1). 64 | * @remarks Re-assignment is required after modification to ensure that the modification takes effect. 65 | */ 66 | get viewport(): Vector4; 67 | set viewport(value: Vector4); 68 | /** 69 | * Whether it is orthogonal, the default is false. True will use orthographic projection, false will use perspective projection. 70 | */ 71 | get isOrthographic(): boolean; 72 | set isOrthographic(value: boolean); 73 | get orthographicSize(): number; 74 | set orthographicSize(value: number); 75 | constructor(engine: Engine); 76 | /** 77 | * Upload camera-related shader data. 78 | */ 79 | private _updateShaderData; 80 | /** 81 | * The upload method is triggered by render. 82 | */ 83 | render(): void; 84 | } 85 | -------------------------------------------------------------------------------- /dist/core/graphic/Buffer.d.ts: -------------------------------------------------------------------------------- 1 | import { BufferBindFlag } from './enums/BufferBindFlag'; 2 | import { BufferUsage } from './enums/BufferUsage'; 3 | /** 4 | * Buffer base class, 5 | * which can be an array of vertex buffers or an array of index buffers. 6 | */ 7 | export declare class Buffer { 8 | _gl: WebGLRenderingContext; 9 | _glBindTarget: number; 10 | _glBufferUsage: number; 11 | _nativeBuffer: WebGLBuffer; 12 | private _type; 13 | private _byteLength; 14 | private _bufferUsage; 15 | /** 16 | * Buffer binding flag. 17 | */ 18 | get type(): BufferBindFlag; 19 | /** 20 | * Byte length. 21 | */ 22 | get byteLength(): number; 23 | /** 24 | * Buffer usage. 25 | */ 26 | get bufferUsage(): BufferUsage; 27 | /** 28 | * Create Buffer. 29 | * @param gl - WebGLRenderingContext 30 | * @param type - Buffer binding flag 31 | * @param byteLength - Byte length 32 | * @param bufferUsage - Buffer usage 33 | */ 34 | constructor(gl: WebGLRenderingContext, type: BufferBindFlag, byteLength: number, bufferUsage?: BufferUsage); 35 | /** 36 | * Create Buffer. 37 | * @param gl - WebGLRenderingContext 38 | * @param type - Buffer binding flag 39 | * @param data - Byte 40 | * @param bufferUsage - Buffer usage 41 | */ 42 | constructor(gl: WebGLRenderingContext, type: BufferBindFlag, data: ArrayBuffer | ArrayBufferView, bufferUsage?: BufferUsage); 43 | /** 44 | * Bind buffer. 45 | */ 46 | bind(): void; 47 | /** 48 | * Set buffer data. 49 | * @param data - Input buffer data 50 | */ 51 | setData(data: ArrayBuffer | ArrayBufferView): void; 52 | /** 53 | * Set buffer data. 54 | * @param data - Input buffer data 55 | * @param bufferByteOffset - buffer byte offset 56 | */ 57 | setData(data: ArrayBuffer | ArrayBufferView, bufferByteOffset: number): void; 58 | /** 59 | * Set buffer data. 60 | * @param data - Input buffer data 61 | * @param bufferByteOffset - Buffer byte offset 62 | * @param dataOffset - Buffer byte offset 63 | * @param dataLength - Data length 64 | */ 65 | setData(data: ArrayBuffer | ArrayBufferView, bufferByteOffset: number, dataOffset: number, dataLength?: number): void; 66 | /** 67 | * Set buffer data. 68 | * @param data - Input buffer data 69 | * @param bufferByteOffset - Buffer byte offset 70 | * @param dataOffset - Buffer byte offset 71 | * @param dataLength - Data length 72 | * @param options - Update strategy: None/Discard/NoOverwrite 73 | */ 74 | setData(data: ArrayBuffer | ArrayBufferView, bufferByteOffset: number, dataOffset: number, dataLength: number): void; 75 | /** 76 | * Get buffer data. 77 | * @param data - Output buffer data 78 | */ 79 | getData(data: ArrayBufferView): void; 80 | /** 81 | * Get buffer data. 82 | * @param data - Output buffer data 83 | * @param bufferByteOffset - Buffer byte offset 84 | */ 85 | getData(data: ArrayBufferView, bufferByteOffset: number): void; 86 | /** 87 | * Get buffer data. 88 | * @param data - Output buffer data 89 | * @param bufferByteOffset - Buffer byte offset 90 | * @param dataOffset - Output data offset 91 | * @param dataLength - Output data length 92 | */ 93 | getData(data: ArrayBufferView, bufferByteOffset: number, dataOffset: number, dataLength: number): void; 94 | } 95 | -------------------------------------------------------------------------------- /dist/core/graphic/Mesh.d.ts: -------------------------------------------------------------------------------- 1 | import { IndexBufferBinding } from '../graphic/IndexBufferBinding'; 2 | import { VertexBufferBinding } from '../graphic/VertexBufferBinding'; 3 | import { VertexElement } from '../graphic/VertexElement'; 4 | import { SubMesh } from '../graphic/SubMesh'; 5 | import { ShaderProgram } from '../shader/ShaderProgram'; 6 | import { Renderer } from '../Renderer'; 7 | import { MeshTopology } from './enums/MeshTopology'; 8 | /** 9 | * Grid abstract class. 10 | */ 11 | export declare abstract class Mesh { 12 | /** Name. */ 13 | name: string; 14 | /** Vertex entity record table, used for caching. */ 15 | _vertexElementMap: Record; 16 | /** The storage type of the index, for example: UInt8. */ 17 | _glIndexType: number; 18 | /** Each index occupies several bytes, 8 bits per byte. */ 19 | _glIndexByteCount: number; 20 | /** A platform that provides rendering capabilities. */ 21 | _platformPrimitive: Renderer; 22 | /** A Mesh may consist of multiple vertex instances. */ 23 | _instanceCount: number; 24 | /** The vertex buffer corresponding to the mesh. */ 25 | _vertexBufferBindings: VertexBufferBinding[]; 26 | /** The index buffer corresponding to the mesh */ 27 | _indexBufferBinding: IndexBufferBinding; 28 | /** Array of vertex elements. */ 29 | _vertexElements: VertexElement[]; 30 | protected gl: WebGLRenderingContext; 31 | /** Drawing information for each element. */ 32 | private _subMeshes; 33 | /** 34 | * First sub-mesh. Rendered using the first material. 35 | */ 36 | get subMesh(): SubMesh | null; 37 | /** 38 | * A collection of sub-mesh, each sub-mesh can be rendered with an independent material. 39 | */ 40 | get subMeshes(): Readonly; 41 | /** 42 | * Add sub-mesh, each sub-mesh can correspond to an independent material. 43 | * @param subMesh - Start drawing offset, if the index buffer is set, it means the offset in the index buffer, if not set, it means the offset in the vertex buffer 44 | * @returns Sub-mesh 45 | */ 46 | addSubMesh(subMesh: SubMesh): SubMesh; 47 | /** 48 | * Add sub-mesh, each sub-mesh can correspond to an independent material. 49 | * @param start - Start drawing offset, if the index buffer is set, it means the offset in the index buffer, if not set, it means the offset in the vertex buffer 50 | * @param count - Drawing count, if the index buffer is set, it means the count in the index buffer, if not set, it means the count in the vertex buffer 51 | * @param topology - Drawing topology, default is MeshTopology.Triangles 52 | * @returns Sub-mesh 53 | */ 54 | addSubMesh(start: number, count: number, topology?: MeshTopology): SubMesh; 55 | /** 56 | * Remove sub-mesh. 57 | * @param subMesh - Sub-mesh needs to be removed 58 | */ 59 | removeSubMesh(subMesh: SubMesh): void; 60 | /** 61 | * Clear all sub-mesh. 62 | */ 63 | clearSubMesh(): void; 64 | constructor(gl: WebGLRenderingContext, name?: string); 65 | _clearVertexElements(): void; 66 | _addVertexElement(element: VertexElement): void; 67 | _draw(shaderProgram: ShaderProgram, subMesh: SubMesh): void; 68 | _onDestroy(): void; 69 | protected _setVertexElements(elements: VertexElement[]): void; 70 | protected _setVertexBufferBinding(index: number, binding: VertexBufferBinding): void; 71 | protected _setIndexBufferBinding(binding: IndexBufferBinding | null): void; 72 | } 73 | -------------------------------------------------------------------------------- /dist/core/shader/ShaderProgram.d.ts: -------------------------------------------------------------------------------- 1 | import { ShaderUniformBlock } from './ShaderUniformBlock'; 2 | import { ShaderData } from './ShaderData'; 3 | import { Engine } from '../Engine'; 4 | /** 5 | * Shader program, corresponding to the GPU shader program. 6 | */ 7 | export declare class ShaderProgram { 8 | /** Shader program counter. */ 9 | private static _counter; 10 | /** Shader program id. */ 11 | id: number; 12 | readonly sceneUniformBlock: ShaderUniformBlock; 13 | readonly cameraUniformBlock: ShaderUniformBlock; 14 | readonly rendererUniformBlock: ShaderUniformBlock; 15 | readonly materialUniformBlock: ShaderUniformBlock; 16 | readonly otherUniformBlock: ShaderUniformBlock; 17 | /** Attribute variable location in webgl. */ 18 | attributeLocation: Record; 19 | private _isValid; 20 | private _engine; 21 | private _gl; 22 | private _vertexShader; 23 | private _fragmentShader; 24 | private _glProgram; 25 | /** Currently active texture unit. */ 26 | private _activeTextureUint; 27 | /** WebGL program. */ 28 | get glProgram(): WebGLProgram; 29 | /** 30 | * Whether this shader program is valid. 31 | */ 32 | get isValid(): boolean; 33 | constructor(engine: Engine, vertexSource: string, fragmentSource: string); 34 | /** 35 | * Create a webgl program instance. 36 | * @param vertexSource Vertex source code. 37 | * @param fragmentSource Fragment source code. 38 | * @returns WebGL program. 39 | */ 40 | private _createProgram; 41 | /** 42 | * Create and compile shader. 43 | * @param shaderType Fragment shader code or vertex shader code. 44 | * @param shaderSource Fragment shader source code or vertex shader source code. 45 | * @returns WebGLShader | null 46 | */ 47 | private _createShader; 48 | /** 49 | * Push texture data or uniform data into the block of the corresponding group. 50 | * @param uniform Shader uniform. 51 | * @param group Shader data group: Scene, Camera, Renderer and Material. 52 | * @param isTexture Is it a texture or a uniform variable. 53 | */ 54 | private _groupingUniform; 55 | /** 56 | * Record the location of uniform/attribute. 57 | */ 58 | private _recordLocation; 59 | /** 60 | * Get the address of the active uniform variable in the current webgl program. 61 | * @returns Array of uniform variable addresses. 62 | */ 63 | private _getUniformInfos; 64 | /** 65 | * Get the address of the active attribute variable in the current webgl program. 66 | * @returns Array of attribute variable addresses. 67 | */ 68 | private _getAttributeInfos; 69 | /** 70 | * Upload all shader data in shader uniform block. 71 | * @param uniformBlock - shader Uniform block 72 | * @param shaderData - shader data 73 | */ 74 | uploadAll(uniformBlock: ShaderUniformBlock, shaderData: ShaderData): void; 75 | /** 76 | * Upload constant shader data in shader uniform block. 77 | * @param uniformBlock - shader Uniform block 78 | * @param shaderData - shader data 79 | */ 80 | uploadUniforms(uniformBlock: ShaderUniformBlock, shaderData: ShaderData): void; 81 | /** 82 | * Upload texture shader data in shader uniform block. 83 | * @param uniformBlock - shader Uniform block 84 | * @param shaderData - shader data 85 | */ 86 | uploadTextures(uniformBlock: ShaderUniformBlock, shaderData: ShaderData): void; 87 | /** 88 | * Bind this shader program. 89 | * @returns Whether the shader program is switched. 90 | */ 91 | bind(): boolean; 92 | destroy(): void; 93 | } 94 | -------------------------------------------------------------------------------- /dist/math/Color.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Describes a color in the from of RGBA (in order: R, G, B, A). 3 | */ 4 | export declare class Color { 5 | /** 6 | * Modify a value from the gamma space to the linear space. 7 | * @param value - The value in gamma space 8 | * @returns The value in linear space 9 | */ 10 | static gammaToLinearSpace(value: number): number; 11 | /** 12 | * Modify a value from the linear space to the gamma space. 13 | * @param value - The value in linear space 14 | * @returns The value in gamma space 15 | */ 16 | static linearToGammaSpace(value: number): number; 17 | /** 18 | * Determines whether the specified colors are equals. 19 | * @param left - The first color to compare 20 | * @param right - The second color to compare 21 | * @returns True if the specified colors are equals, false otherwise 22 | */ 23 | static equals(left: Color, right: Color): boolean; 24 | /** 25 | * Determines the sum of two colors. 26 | * @param left - The first color to add 27 | * @param right - The second color to add 28 | * @param out - The sum of two colors 29 | * @returns The added color 30 | */ 31 | static add(left: Color, right: Color, out: Color): Color; 32 | /** 33 | * Scale a color by the given value. 34 | * @param left - The color to scale 35 | * @param s - The amount by which to scale the color 36 | * @param out - The scaled color 37 | * @returns The scaled color 38 | */ 39 | static scale(left: Color, s: number, out: Color): Color; 40 | /** The red component of the color, 0~1. */ 41 | r: number; 42 | /** The green component of the color, 0~1. */ 43 | g: number; 44 | /** The blue component of the color, 0~1. */ 45 | b: number; 46 | /** The alpha component of the color, 0~1. */ 47 | a: number; 48 | /** 49 | * Constructor of Color. 50 | * @param r - The red component of the color 51 | * @param g - The green component of the color 52 | * @param b - The blue component of the color 53 | * @param a - The alpha component of the color 54 | */ 55 | constructor(r?: number, g?: number, b?: number, a?: number); 56 | /** 57 | * Set the value of this color. 58 | * @param r - The red component of the color 59 | * @param g - The green component of the color 60 | * @param b - The blue component of the color 61 | * @param a - The alpha component of the color 62 | * @returns This color. 63 | */ 64 | setValue(r: number, g: number, b: number, a: number): Color; 65 | /** 66 | * Determines the sum of this color and the specified color. 67 | * @param color - The specified color 68 | * @returns The added color 69 | */ 70 | add(color: Color): Color; 71 | /** 72 | * Scale this color by the given value. 73 | * @param s - The amount by which to scale the color 74 | * @returns The scaled color 75 | */ 76 | scale(s: number): Color; 77 | /** 78 | * Creates a clone of this color. 79 | * @returns A clone of this color 80 | */ 81 | clone(): Color; 82 | /** 83 | * Clones this color to the specified color. 84 | * @param out - The specified color 85 | * @returns The specified color 86 | */ 87 | cloneTo(out: Color): Color; 88 | /** 89 | * Modify components (r, g, b) of this color from gamma space to linear space. 90 | * @param out - The color in linear space 91 | * @returns The color in linear space 92 | */ 93 | toLinear(out: Color): Color; 94 | /** 95 | * Modify components (r, g, b) of this color from linear space to gamma space. 96 | * @param out - The color in gamma space 97 | * @returns The color in gamma space 98 | */ 99 | toGamma(out: Color): Color; 100 | } 101 | -------------------------------------------------------------------------------- /src/core/texture/Texture2D.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '../Engine'; 2 | import { TextureFilterMode } from './enums/TextureFilterMode'; 3 | import { TextureFormat } from './enums/TextureFormat'; 4 | import { TextureWrapMode } from './enums/TextureWrapMode'; 5 | import { Texture } from './Texture'; 6 | 7 | /** 8 | * Two-dimensional texture. 9 | */ 10 | export class Texture2D extends Texture { 11 | /** 12 | * Create Texture2D. 13 | * @param engine Define the engine to use to render this texture. 14 | * @param width Texture width. 15 | * @param height Texture height. 16 | * @param format Texture format. default `TextureFormat.R8G8B8A8`. 17 | * @param mipmap Whether to use multi-level texture. 18 | */ 19 | constructor( 20 | engine: Engine, 21 | width: number, 22 | height: number, 23 | format: TextureFormat = TextureFormat.R8G8B8A8, 24 | mipmap: boolean = true, 25 | ) { 26 | super(); 27 | this._mipmap = mipmap; 28 | this._width = width; 29 | this._height = height; 30 | this._format = format; 31 | this._mipmapCount = this._getMipmapCount(); 32 | 33 | this.filterMode = TextureFilterMode.Bilinear; 34 | this.wrapModeU = this.wrapModeV = TextureWrapMode.Repeat; 35 | 36 | this._gl = engine.gl; 37 | this._glTexture = this._gl.createTexture(); 38 | this._glTarget = this._gl.TEXTURE_2D; 39 | this._formatDetail = Texture._getFormatDetail(format, this._gl); 40 | } 41 | 42 | /** 43 | * Set texture based on pixel buffer. 44 | * @param colorBuffer Color buffer array. 45 | * @param mipLevel Mip level. 46 | * @param x Starting point x position. 47 | * @param y Starting point y position. 48 | * @param width Set width. 49 | * @param height Set height. 50 | */ 51 | setPixelBuffer( 52 | colorBuffer: ArrayBufferView, 53 | mipLevel: number = 0, 54 | x: number = 0, 55 | y: number = 0, 56 | width?: number, 57 | height?: number, 58 | ): void { 59 | const gl = this._gl; 60 | const { internalFormat, baseFormat, dataType } = this._formatDetail; 61 | const mipWidth = Math.max(1, this._width >> mipLevel); 62 | const mipHeight = Math.max(1, this.height >> mipLevel); 63 | 64 | width = width || mipWidth - x; 65 | height = height || mipHeight - y; 66 | 67 | // webgl2 才可以考虑纹理压缩API isCompressed 68 | gl.bindTexture(this._glTarget, this._glTexture); 69 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0); 70 | gl.texParameteri(this._glTarget, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 71 | // gl.texSubImage2D(this._glTarget, mipLevel, x, y, width, height, baseFormat, dataType, colorBuffer); 72 | gl.texImage2D(this._glTarget, mipLevel, internalFormat, width, height, 0, baseFormat, dataType, colorBuffer); 73 | } 74 | 75 | /** 76 | * Set the texture according to the picture. 77 | * @param imageSource Image source. 78 | * @param mipLevel Mip level. 79 | * @param flipY Y axis reversed. 80 | */ 81 | setImageSource( 82 | imageSource: TexImageSource, 83 | mipLevel: number, 84 | flipY: boolean, 85 | // premultiplyAlpha: boolean, 86 | // x: number = 0, 87 | // y: number = 0, 88 | ): void { 89 | const gl = this._gl; 90 | const { baseFormat, dataType, internalFormat } = this._formatDetail; 91 | 92 | gl.bindTexture(this._glTarget, this._glTexture); 93 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, +flipY); 94 | // 将Alpha通道乘以其他颜色通道 95 | // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, +premultiplyAlpha); 96 | // gl.texSubImage2D(this._glTarget, mipLevel, x || 0, y || 0, baseFormat, dataType, imageSource); 97 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 98 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 99 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 100 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 101 | gl.texImage2D(this._glTarget, mipLevel, internalFormat, baseFormat, dataType, imageSource); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /dist/core/base/Constant.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Data type enumeration 3 | */ 4 | export declare enum DataType { 5 | /** Float */ 6 | FLOAT = 5126, 7 | /** Floating-point two-dimensional vector */ 8 | FLOAT_VEC2 = 35664, 9 | /** Floating-point three-dimensional vector */ 10 | FLOAT_VEC3 = 35665, 11 | /** Floating-point four-dimensional vector */ 12 | FLOAT_VEC4 = 35666, 13 | /** Integer */ 14 | INT = 5124, 15 | /** Integer two-dimensional vector */ 16 | INT_VEC2 = 35667, 17 | /** Integer three-dimensional vector */ 18 | INT_VEC3 = 35668, 19 | /** Integer four-dimensional vector */ 20 | INT_VEC4 = 35669, 21 | /** Boolean */ 22 | BOOL = 35670, 23 | /** Boolean two-dimensional vector */ 24 | BOOL_VEC2 = 35671, 25 | /** Boolean three-dimensional vector */ 26 | BOOL_VEC3 = 35672, 27 | /** Boolean four-dimensional vector */ 28 | BOOL_VEC4 = 35673, 29 | /** Second-order matrix */ 30 | FLOAT_MAT2 = 35674, 31 | /** Third-order matrix */ 32 | FLOAT_MAT3 = 35675, 33 | /** Fourth-order matrix */ 34 | FLOAT_MAT4 = 35676, 35 | /** Float array */ 36 | FLOAT_ARRAY = 35677, 37 | /** Floating-point two-dimensional vector array */ 38 | FLOAT_VEC2_ARRAY = 100000, 39 | /** Floating-point three-dimensional vector array */ 40 | FLOAT_VEC3_ARRAY = 100001, 41 | /** Floating-point four-dimensional vector array */ 42 | FLOAT_VEC4_ARRAY = 100002, 43 | /** Integer array */ 44 | INT_ARRAY = 100003, 45 | /** Integer two-dimensional vector array */ 46 | INT_VEC2_ARRAY = 100004, 47 | /** Integer three-dimensional vector array */ 48 | INT_VEC3_ARRAY = 100005, 49 | /** Integer four-dimensional vector array */ 50 | INT_VEC4_ARRAY = 100006, 51 | /** Second-order matrix array */ 52 | FLOAT_MAT2_ARRAY = 100007, 53 | /** Third-order matrix array */ 54 | FLOAT_MAT3_ARRAY = 100008, 55 | /** Fourth-order matrix array */ 56 | FLOAT_MAT4_ARRAY = 100009, 57 | /** 2D texture sampler array */ 58 | SAMPLER_2D_ARRAY = 100010, 59 | /** Cube map texture sampler array */ 60 | SAMPLER_CUBE_ARRAY = 100011, 61 | /** 2D sampler */ 62 | SAMPLER_2D = 35678, 63 | /** Cube map Texture sampler */ 64 | SAMPLER_CUBE = 35680, 65 | /** Byte */ 66 | BYTE = 5120, 67 | /** Unsigned byte */ 68 | UNSIGNED_BYTE = 5121, 69 | /** Short */ 70 | SHORT = 5122, 71 | /** Unsigned short */ 72 | UNSIGNED_SHORT = 5123, 73 | /** Unsigned int */ 74 | UNSIGNED_INT = 5125, 75 | TEXTURE_CUBE_MAP_POSITIVE_X = 34069, 76 | TEXTURE_CUBE_MAP_NEGATIVE_X = 34070, 77 | TEXTURE_CUBE_MAP_POSITIVE_Y = 34071, 78 | TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072, 79 | TEXTURE_CUBE_MAP_POSITIVE_Z = 34073, 80 | TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074 81 | } 82 | /** 83 | * GL Capabilities 84 | * Some capabilities can be smoothed out by extension, and some capabilities must use WebGL 2.0. 85 | * */ 86 | export declare enum GLCapabilityType { 87 | shaderVertexID = "shaderVertexID", 88 | standardDerivatives = "OES_standard_derivatives", 89 | shaderTextureLod = "EXT_shader_texture_lod", 90 | elementIndexUint = "OES_element_index_uint", 91 | depthTexture = "WEBGL_depth_texture", 92 | drawBuffers = "WEBGL_draw_buffers", 93 | vertexArrayObject = "OES_vertex_array_object", 94 | instancedArrays = "ANGLE_instanced_arrays", 95 | multipleSample = "multipleSampleOnlySupportedInWebGL2", 96 | textureFloat = "OES_texture_float", 97 | textureFloatLinear = "OES_texture_float_linear", 98 | textureHalfFloat = "OES_texture_half_float", 99 | textureHalfFloatLinear = "OES_texture_half_float_linear", 100 | WEBGL_colorBufferFloat = "WEBGL_color_buffer_float", 101 | colorBufferFloat = "EXT_color_buffer_float", 102 | colorBufferHalfFloat = "EXT_color_buffer_half_float", 103 | textureFilterAnisotropic = "EXT_texture_filter_anisotropic", 104 | blendMinMax = "EXT_blend_minmax", 105 | astc = "WEBGL_compressed_texture_astc", 106 | astc_webkit = "WEBKIT_WEBGL_compressed_texture_astc", 107 | etc = "WEBGL_compressed_texture_etc", 108 | etc_webkit = "WEBKIT_WEBGL_compressed_texture_etc", 109 | etc1 = "WEBGL_compressed_texture_etc1", 110 | etc1_webkit = "WEBKIT_WEBGL_compressed_texture_etc1", 111 | pvrtc = "WEBGL_compressed_texture_pvrtc", 112 | pvrtc_webkit = "WEBKIT_WEBGL_compressed_texture_pvrtc", 113 | s3tc = "WEBGL_compressed_texture_s3tc", 114 | s3tc_webkit = "WEBKIT_WEBGL_compressed_texture_s3tc" 115 | } 116 | export declare type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array; 117 | -------------------------------------------------------------------------------- /src/core/graphic/BufferUtil.ts: -------------------------------------------------------------------------------- 1 | import { BufferUsage } from './enums/BufferUsage'; 2 | import { VertexElementFormat } from './enums/VertexElementFormat'; 3 | import { DataType } from '../base/Constant'; 4 | import { IndexFormat } from './enums/IndexFormat'; 5 | 6 | /** 7 | * Information about a single vertex element. 8 | */ 9 | export interface ElementInfo { 10 | /** Number of components per vertex. */ 11 | size: number; 12 | /** Type of data. */ 13 | type: DataType; 14 | /** Whether normalization is required. */ 15 | normalized: boolean; 16 | } 17 | 18 | /** 19 | * Utility functions for processing Buffers. 20 | */ 21 | export class BufferUtil { 22 | /** 23 | * Obtain the usage of Buffer according to the incoming enumeration. 24 | * @param gl WebGL rendering context. 25 | * @param bufferUsage Buffer usage. 26 | * @returns The number code used by the internal buffer of gl. 27 | */ 28 | static _getGLBufferUsage(gl: WebGLRenderingContext, bufferUsage: BufferUsage): number { 29 | switch (bufferUsage) { 30 | case BufferUsage.Static: 31 | return gl.STATIC_DRAW; 32 | case BufferUsage.Dynamic: 33 | return gl.DYNAMIC_DRAW; 34 | case BufferUsage.Stream: 35 | return gl.STREAM_DRAW; 36 | } 37 | } 38 | 39 | /** 40 | * Get index type code. 41 | * @param indexFormat Index type enumeration. 42 | * @returns The number code used by the internal type of gl. 43 | */ 44 | static _getGLIndexType(indexFormat: IndexFormat): DataType { 45 | switch (indexFormat) { 46 | case IndexFormat.UInt8: 47 | return DataType.UNSIGNED_BYTE; 48 | case IndexFormat.UInt16: 49 | return DataType.UNSIGNED_SHORT; 50 | case IndexFormat.UInt32: 51 | return DataType.UNSIGNED_INT; 52 | } 53 | } 54 | 55 | /** 56 | * Get gl index byte count. 57 | * @param indexFormat Index type enumeration. 58 | * @returns Index byte count. 59 | */ 60 | static _getGLIndexByteCount(indexFormat: IndexFormat): DataType { 61 | switch (indexFormat) { 62 | case IndexFormat.UInt8: 63 | return 1; 64 | case IndexFormat.UInt16: 65 | return 2; 66 | case IndexFormat.UInt32: 67 | return 4; 68 | } 69 | } 70 | 71 | /** 72 | * Returns vertex information based on the element's vertex format. 73 | */ 74 | static _getElementInfo(format: VertexElementFormat): ElementInfo { 75 | let size: number; 76 | let type: DataType; 77 | let normalized: boolean = false; 78 | 79 | switch (format) { 80 | case VertexElementFormat.Float: 81 | size = 1; 82 | type = DataType.FLOAT; 83 | break; 84 | case VertexElementFormat.Vector2: 85 | size = 2; 86 | type = DataType.FLOAT; 87 | break; 88 | case VertexElementFormat.Vector3: 89 | size = 3; 90 | type = DataType.FLOAT; 91 | break; 92 | case VertexElementFormat.Vector4: 93 | size = 4; 94 | type = DataType.FLOAT; 95 | break; 96 | case VertexElementFormat.Byte4: 97 | size = 4; 98 | type = DataType.BYTE; 99 | break; 100 | case VertexElementFormat.UByte4: 101 | size = 4; 102 | type = DataType.UNSIGNED_BYTE; 103 | break; 104 | case VertexElementFormat.NormalizedByte4: 105 | size = 4; 106 | type = DataType.BYTE; 107 | normalized = true; 108 | break; 109 | case VertexElementFormat.NormalizedUByte4: 110 | size = 4; 111 | type = DataType.UNSIGNED_BYTE; 112 | normalized = true; 113 | break; 114 | case VertexElementFormat.Short2: 115 | size = 2; 116 | type = DataType.SHORT; 117 | break; 118 | case VertexElementFormat.UShort2: 119 | size = 2; 120 | type = DataType.UNSIGNED_SHORT; 121 | break; 122 | case VertexElementFormat.NormalizedShort2: 123 | size = 2; 124 | type = DataType.SHORT; 125 | normalized = true; 126 | break; 127 | case VertexElementFormat.NormalizedUShort2: 128 | size = 2; 129 | type = DataType.UNSIGNED_SHORT; 130 | normalized = true; 131 | break; 132 | case VertexElementFormat.Short4: 133 | size = 4; 134 | type = DataType.SHORT; 135 | break; 136 | case VertexElementFormat.UShort4: 137 | size = 4; 138 | type = DataType.UNSIGNED_SHORT; 139 | break; 140 | case VertexElementFormat.NormalizedShort4: 141 | size = 4; 142 | type = DataType.SHORT; 143 | normalized = true; 144 | break; 145 | case VertexElementFormat.NormalizedUShort4: 146 | size = 4; 147 | type = DataType.UNSIGNED_SHORT; 148 | normalized = true; 149 | break; 150 | default: 151 | break; 152 | } 153 | return { size, type, normalized }; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/core/texture/Texture.ts: -------------------------------------------------------------------------------- 1 | import { TextureFilterMode } from './enums/TextureFilterMode'; 2 | import { TextureFormat } from './enums/TextureFormat'; 3 | import { TextureWrapMode } from './enums/TextureWrapMode'; 4 | 5 | /** 6 | * Texture specific format information. 7 | */ 8 | export interface TextureFormatDetail { 9 | /** Texture color internal format: RGB, RGBA. */ 10 | internalFormat: GLint; 11 | /** Texture color base format: RGB, RGBA. */ 12 | baseFormat?: GLenum; 13 | /** Texel data type. */ 14 | dataType?: GLenum; 15 | // webgl2才开启纹理压缩 16 | /** Whether texture compression. */ 17 | isCompressed: boolean; 18 | } 19 | 20 | /** 21 | * The base class of texture, contains some common functions of texture-related classes. 22 | */ 23 | export abstract class Texture { 24 | name: string; 25 | 26 | /** Whether to enable mipmap. */ 27 | _mipmap: boolean; 28 | /** Texture object storage address. */ 29 | _glTexture: WebGLTexture; 30 | /** Texture sampler. */ 31 | _glTarget: number; 32 | /** Texture format detail. */ 33 | _formatDetail: TextureFormatDetail; 34 | 35 | /** Texture format. */ 36 | protected _format: TextureFormat; 37 | /** Texture width. */ 38 | protected _width: number; 39 | /** Texture height. */ 40 | protected _height: number; 41 | protected _mipmapCount: number; 42 | protected _gl: WebGLRenderingContext; 43 | 44 | private _wrapModeU: TextureWrapMode; 45 | private _wrapModeV: TextureWrapMode; 46 | private _filterMode: TextureFilterMode; 47 | 48 | get format(): TextureFormat { 49 | return this._format; 50 | } 51 | 52 | get width(): number { 53 | return this._width; 54 | } 55 | 56 | get height(): number { 57 | return this._height; 58 | } 59 | 60 | get wrapModeU(): TextureWrapMode { 61 | return this._wrapModeU; 62 | } 63 | 64 | set wrapModeU(value: TextureWrapMode) { 65 | if (value === this._wrapModeU) return; 66 | this._wrapModeU = value; 67 | } 68 | 69 | get wrapModeV(): TextureWrapMode { 70 | return this._wrapModeV; 71 | } 72 | 73 | set wrapModeV(value: TextureWrapMode) { 74 | if (value === this._wrapModeV) return; 75 | this._wrapModeV = value; 76 | } 77 | 78 | get mipmapCount(): number { 79 | return this._mipmapCount; 80 | } 81 | 82 | get filterMode(): TextureFilterMode { 83 | return this._filterMode; 84 | } 85 | 86 | set filterMode(value: TextureFilterMode) { 87 | if (value === this._filterMode) return; 88 | this._filterMode = value; 89 | } 90 | 91 | protected _getMaxMiplevel(size: number): number { 92 | return Math.floor(Math.log2(size)); 93 | } 94 | 95 | protected _getMipmapCount(): number { 96 | return this._mipmap ? Math.floor(Math.log2(Math.max(this._width, this._height))) + 1 : 1; 97 | } 98 | 99 | /** 100 | * Get detailed texture detail information based on texture format. 101 | * @param format Texture format. 102 | * @param gl WebGLRenderingContext. 103 | * @returns Texture format detail. 104 | */ 105 | static _getFormatDetail(format: TextureFormat, gl: WebGLRenderingContext): TextureFormatDetail { 106 | switch (format) { 107 | case TextureFormat.R8G8B8: 108 | return { 109 | internalFormat: gl.RGB, 110 | baseFormat: gl.RGB, 111 | dataType: gl.UNSIGNED_BYTE, 112 | isCompressed: false, 113 | }; 114 | case TextureFormat.R8G8B8A8: 115 | return { 116 | internalFormat: gl.RGBA, 117 | baseFormat: gl.RGBA, 118 | dataType: gl.UNSIGNED_BYTE, 119 | isCompressed: false, 120 | }; 121 | case TextureFormat.R4G4B4A4: 122 | return { 123 | internalFormat: gl.RGBA, 124 | baseFormat: gl.RGBA, 125 | dataType: gl.UNSIGNED_SHORT_4_4_4_4, 126 | isCompressed: false, 127 | }; 128 | case TextureFormat.R5G5B5A1: 129 | return { 130 | internalFormat: gl.RGBA, 131 | baseFormat: gl.RGBA, 132 | dataType: gl.UNSIGNED_SHORT_5_5_5_1, 133 | isCompressed: false, 134 | }; 135 | case TextureFormat.R5G6B5: 136 | return { 137 | internalFormat: gl.RGB, 138 | baseFormat: gl.RGB, 139 | dataType: gl.UNSIGNED_SHORT_5_6_5, 140 | isCompressed: false, 141 | }; 142 | case TextureFormat.Alpha8: 143 | return { 144 | internalFormat: gl.ALPHA, 145 | baseFormat: gl.ALPHA, 146 | dataType: gl.UNSIGNED_BYTE, 147 | isCompressed: false, 148 | }; 149 | case TextureFormat.LuminanceAlpha: 150 | return { 151 | internalFormat: gl.LUMINANCE_ALPHA, 152 | baseFormat: gl.LUMINANCE_ALPHA, 153 | dataType: gl.UNSIGNED_BYTE, 154 | isCompressed: false, 155 | }; 156 | default: 157 | throw new Error(`this TextureFormat is not supported in Oasis Engine: ${format}`); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/core/base/Constant.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Data type enumeration 3 | */ 4 | export enum DataType { 5 | /** Float */ 6 | FLOAT = 5126, // gl.FLOAT 7 | /** Floating-point two-dimensional vector */ 8 | FLOAT_VEC2 = 35664, // gl.FLOAT_VEC2 9 | /** Floating-point three-dimensional vector */ 10 | FLOAT_VEC3 = 35665, // gl.FLOAT_VEC3 11 | /** Floating-point four-dimensional vector */ 12 | FLOAT_VEC4 = 35666, // gl.FLOAT_VEC4 13 | 14 | /** Integer */ 15 | INT = 5124, // gl.INT 16 | /** Integer two-dimensional vector */ 17 | INT_VEC2 = 35667, // gl.INT_VEC2 18 | /** Integer three-dimensional vector */ 19 | INT_VEC3 = 35668, // gl.INT_VEC3 20 | /** Integer four-dimensional vector */ 21 | INT_VEC4 = 35669, // gl.INT_VEC4 22 | 23 | /** Boolean */ 24 | BOOL = 35670, // gl.BOOL 25 | /** Boolean two-dimensional vector */ 26 | BOOL_VEC2 = 35671, // gl.BOOL_VEC2 27 | /** Boolean three-dimensional vector */ 28 | BOOL_VEC3 = 35672, // gl.BOOL_VEC3 29 | /** Boolean four-dimensional vector */ 30 | BOOL_VEC4 = 35673, // gl.BOOL_VEC4 31 | 32 | /** Second-order matrix */ 33 | FLOAT_MAT2 = 35674, // gl.FLOAT_MAT2 34 | /** Third-order matrix */ 35 | FLOAT_MAT3 = 35675, // gl.FLOAT_MAT3 36 | /** Fourth-order matrix */ 37 | FLOAT_MAT4 = 35676, // gl.FLOAT_MAT4 38 | 39 | /** Float array */ 40 | FLOAT_ARRAY = 35677, // gl.FLOAT_ARRAY 41 | /** Floating-point two-dimensional vector array */ 42 | FLOAT_VEC2_ARRAY = 100000, 43 | /** Floating-point three-dimensional vector array */ 44 | FLOAT_VEC3_ARRAY, 45 | /** Floating-point four-dimensional vector array */ 46 | FLOAT_VEC4_ARRAY, 47 | 48 | /** Integer array */ 49 | INT_ARRAY, 50 | /** Integer two-dimensional vector array */ 51 | INT_VEC2_ARRAY, 52 | /** Integer three-dimensional vector array */ 53 | INT_VEC3_ARRAY, 54 | /** Integer four-dimensional vector array */ 55 | INT_VEC4_ARRAY, 56 | 57 | /** Second-order matrix array */ 58 | FLOAT_MAT2_ARRAY, 59 | /** Third-order matrix array */ 60 | FLOAT_MAT3_ARRAY, 61 | /** Fourth-order matrix array */ 62 | FLOAT_MAT4_ARRAY, 63 | 64 | /** 2D texture sampler array */ 65 | SAMPLER_2D_ARRAY, 66 | /** Cube map texture sampler array */ 67 | SAMPLER_CUBE_ARRAY, 68 | 69 | /** 2D sampler */ 70 | SAMPLER_2D = 35678, // gl.SAMPLER_2D 71 | /** Cube map Texture sampler */ 72 | SAMPLER_CUBE = 35680, // gl.SAMPLER_CUBE 73 | 74 | /** Byte */ 75 | BYTE = 5120, // gl.BYTE 76 | /** Unsigned byte */ 77 | UNSIGNED_BYTE = 5121, // gl.UNSIGNED_BYTE 78 | /** Short */ 79 | SHORT = 5122, // gl.SHORT 80 | /** Unsigned short */ 81 | UNSIGNED_SHORT = 5123, // gl.UNSIGNED_SHORT 82 | /** Unsigned int */ 83 | UNSIGNED_INT = 5125, // gl.UNSIGNED_INT 84 | 85 | TEXTURE_CUBE_MAP_POSITIVE_X = 34069, 86 | TEXTURE_CUBE_MAP_NEGATIVE_X, 87 | TEXTURE_CUBE_MAP_POSITIVE_Y, 88 | TEXTURE_CUBE_MAP_NEGATIVE_Y, 89 | TEXTURE_CUBE_MAP_POSITIVE_Z, 90 | TEXTURE_CUBE_MAP_NEGATIVE_Z, 91 | } 92 | 93 | /** 94 | * GL Capabilities 95 | * Some capabilities can be smoothed out by extension, and some capabilities must use WebGL 2.0. 96 | * */ 97 | export enum GLCapabilityType { 98 | shaderVertexID = 'shaderVertexID', 99 | standardDerivatives = 'OES_standard_derivatives', 100 | shaderTextureLod = 'EXT_shader_texture_lod', 101 | elementIndexUint = 'OES_element_index_uint', 102 | depthTexture = 'WEBGL_depth_texture', 103 | drawBuffers = 'WEBGL_draw_buffers', 104 | vertexArrayObject = 'OES_vertex_array_object', 105 | instancedArrays = 'ANGLE_instanced_arrays', 106 | multipleSample = 'multipleSampleOnlySupportedInWebGL2', 107 | textureFloat = 'OES_texture_float', 108 | textureFloatLinear = 'OES_texture_float_linear', 109 | textureHalfFloat = 'OES_texture_half_float', 110 | textureHalfFloatLinear = 'OES_texture_half_float_linear', 111 | WEBGL_colorBufferFloat = 'WEBGL_color_buffer_float', 112 | colorBufferFloat = 'EXT_color_buffer_float', 113 | colorBufferHalfFloat = 'EXT_color_buffer_half_float', 114 | textureFilterAnisotropic = 'EXT_texture_filter_anisotropic', 115 | blendMinMax = 'EXT_blend_minmax', 116 | 117 | astc = 'WEBGL_compressed_texture_astc', 118 | astc_webkit = 'WEBKIT_WEBGL_compressed_texture_astc', 119 | etc = 'WEBGL_compressed_texture_etc', 120 | etc_webkit = 'WEBKIT_WEBGL_compressed_texture_etc', 121 | etc1 = 'WEBGL_compressed_texture_etc1', 122 | etc1_webkit = 'WEBKIT_WEBGL_compressed_texture_etc1', 123 | pvrtc = 'WEBGL_compressed_texture_pvrtc', 124 | pvrtc_webkit = 'WEBKIT_WEBGL_compressed_texture_pvrtc', 125 | s3tc = 'WEBGL_compressed_texture_s3tc', 126 | s3tc_webkit = 'WEBKIT_WEBGL_compressed_texture_s3tc', 127 | // atc = "WEBGL_compressed_texture_atc", 128 | // s3tc_srgb = "WEBGL_compressed_texture_s3tc_srgb" 129 | } 130 | 131 | export type TypedArray = 132 | | Int8Array 133 | | Uint8Array 134 | | Int16Array 135 | | Uint16Array 136 | | Int32Array 137 | | Uint32Array 138 | | Uint8ClampedArray 139 | | Float32Array 140 | | Float64Array; 141 | -------------------------------------------------------------------------------- /src/core/graphic/Mesh.ts: -------------------------------------------------------------------------------- 1 | import { BufferUtil } from '../graphic/BufferUtil'; 2 | import { IndexBufferBinding } from '../graphic/IndexBufferBinding'; 3 | import { VertexBufferBinding } from '../graphic/VertexBufferBinding'; 4 | import { VertexElement } from '../graphic/VertexElement'; 5 | import { SubMesh } from '../graphic/SubMesh'; 6 | import { ShaderProgram } from '../shader/ShaderProgram'; 7 | import { Renderer } from '../Renderer'; 8 | import { MeshTopology } from './enums/MeshTopology'; 9 | 10 | /** 11 | * Grid abstract class. 12 | */ 13 | export abstract class Mesh { 14 | /** Name. */ 15 | name: string; 16 | /** Vertex entity record table, used for caching. */ 17 | _vertexElementMap: Record = {}; 18 | /** The storage type of the index, for example: UInt8. */ 19 | _glIndexType: number; 20 | /** Each index occupies several bytes, 8 bits per byte. */ 21 | _glIndexByteCount: number; 22 | /** A platform that provides rendering capabilities. */ 23 | _platformPrimitive: Renderer; 24 | /** A Mesh may consist of multiple vertex instances. */ 25 | _instanceCount: number = 0; 26 | /** The vertex buffer corresponding to the mesh. */ 27 | _vertexBufferBindings: VertexBufferBinding[] = []; 28 | /** The index buffer corresponding to the mesh */ 29 | _indexBufferBinding: IndexBufferBinding = null; 30 | /** Array of vertex elements. */ 31 | _vertexElements: VertexElement[] = []; 32 | 33 | protected gl: WebGLRenderingContext; 34 | /** Drawing information for each element. */ 35 | private _subMeshes: SubMesh[] = []; 36 | 37 | /** 38 | * First sub-mesh. Rendered using the first material. 39 | */ 40 | get subMesh(): SubMesh | null { 41 | return this._subMeshes[0] || null; 42 | } 43 | 44 | /** 45 | * A collection of sub-mesh, each sub-mesh can be rendered with an independent material. 46 | */ 47 | get subMeshes(): Readonly { 48 | return this._subMeshes; 49 | } 50 | 51 | /** 52 | * Add sub-mesh, each sub-mesh can correspond to an independent material. 53 | * @param subMesh - Start drawing offset, if the index buffer is set, it means the offset in the index buffer, if not set, it means the offset in the vertex buffer 54 | * @returns Sub-mesh 55 | */ 56 | addSubMesh(subMesh: SubMesh): SubMesh; 57 | 58 | /** 59 | * Add sub-mesh, each sub-mesh can correspond to an independent material. 60 | * @param start - Start drawing offset, if the index buffer is set, it means the offset in the index buffer, if not set, it means the offset in the vertex buffer 61 | * @param count - Drawing count, if the index buffer is set, it means the count in the index buffer, if not set, it means the count in the vertex buffer 62 | * @param topology - Drawing topology, default is MeshTopology.Triangles 63 | * @returns Sub-mesh 64 | */ 65 | addSubMesh(start: number, count: number, topology?: MeshTopology): SubMesh; 66 | 67 | addSubMesh( 68 | startOrSubMesh: number | SubMesh, 69 | count?: number, 70 | topology: MeshTopology = MeshTopology.Triangles, 71 | ): SubMesh { 72 | if (typeof startOrSubMesh === 'number') { 73 | startOrSubMesh = new SubMesh(startOrSubMesh, count, topology); 74 | } 75 | this._subMeshes.push(startOrSubMesh); 76 | return startOrSubMesh; 77 | } 78 | 79 | /** 80 | * Remove sub-mesh. 81 | * @param subMesh - Sub-mesh needs to be removed 82 | */ 83 | removeSubMesh(subMesh: SubMesh): void { 84 | const subMeshes = this._subMeshes; 85 | const index = subMeshes.indexOf(subMesh); 86 | if (index !== -1) { 87 | subMeshes.splice(index, 1); 88 | } 89 | } 90 | 91 | /** 92 | * Clear all sub-mesh. 93 | */ 94 | clearSubMesh(): void { 95 | this._subMeshes.length = 0; 96 | } 97 | 98 | constructor(gl: WebGLRenderingContext, name?: string) { 99 | this.gl = gl; 100 | this.name = name; 101 | this._platformPrimitive = new Renderer(gl, this); 102 | } 103 | 104 | _clearVertexElements(): void { 105 | // 这个清空方法妙啊 106 | this._vertexElements.length = 0; 107 | const vertexElementMap = this._vertexElementMap; 108 | for (const k in vertexElementMap) { 109 | delete vertexElementMap[k]; 110 | } 111 | } 112 | 113 | _addVertexElement(element: VertexElement): void { 114 | const { semantic } = element; 115 | this._vertexElementMap[semantic] = element; 116 | this._vertexElements.push(element); 117 | } 118 | 119 | _draw(shaderProgram: ShaderProgram, subMesh: SubMesh): void { 120 | this._platformPrimitive.draw(shaderProgram, subMesh); 121 | // this._platformPrimitive.testDraw(shaderProgram); 122 | } 123 | 124 | _onDestroy(): void { 125 | this._vertexBufferBindings = null; 126 | this._indexBufferBinding = null; 127 | this._vertexElements = null; 128 | this._vertexElementMap = null; 129 | } 130 | 131 | protected _setVertexElements(elements: VertexElement[]): void { 132 | this._clearVertexElements(); 133 | for (let i = 0, n = elements.length; i < n; i++) { 134 | this._addVertexElement(elements[i]); 135 | } 136 | } 137 | 138 | protected _setVertexBufferBinding(index: number, binding: VertexBufferBinding): void { 139 | this._vertexBufferBindings[index] = binding; 140 | } 141 | 142 | protected _setIndexBufferBinding(binding: IndexBufferBinding | null): void { 143 | if (binding) { 144 | this._indexBufferBinding = binding; 145 | this._glIndexType = BufferUtil._getGLIndexType(binding.format); 146 | this._glIndexByteCount = BufferUtil._getGLIndexByteCount(binding.format); 147 | } else { 148 | this._indexBufferBinding = null; 149 | this._glIndexType = undefined; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/core/Engine.ts: -------------------------------------------------------------------------------- 1 | import { Canvas } from './Canvas'; 2 | import { Scene } from './Scene'; 3 | import { Time } from './base'; 4 | import { Texture2D, TextureCubeFace, TextureFormat } from './texture'; 5 | import { ShaderPool } from './shader/ShaderPool'; 6 | import { TextureCube } from './texture/TextureCube'; 7 | 8 | // 引入引擎的时候就将ShaderPool进行初始化 9 | ShaderPool.init(); 10 | 11 | /** 12 | * The engine is the big steward of all content. 13 | */ 14 | export class Engine { 15 | /** The canvas corresponding to the engine. */ 16 | protected _canvas: Canvas; 17 | // TODO: 考虑接入WebGL2. 18 | /** WebGL rendering context. */ 19 | protected _gl: WebGLRenderingContext; 20 | 21 | /** Current active scene. */ 22 | private activeScene: Scene; 23 | /** Used to calculate the interval between each frame rendering. */ 24 | private _time: Time = new Time(); 25 | /** Easy to destroy RAF. */ 26 | private _requestId: number; 27 | 28 | /** Rendered 2D texture when the image has not been loaded yet. */ 29 | _whiteTexture2D: Texture2D; 30 | /** Rendered cube texture when the image has not been loaded yet. */ 31 | _whiteTextureCube: TextureCube; 32 | 33 | get canvas(): Canvas { 34 | return this._canvas; 35 | } 36 | 37 | get gl(): WebGLRenderingContext { 38 | return this._gl; 39 | } 40 | 41 | get time(): Time { 42 | return this._time; 43 | } 44 | 45 | /** 46 | * Animation rendering. 47 | */ 48 | private _animate = () => { 49 | this._requestId = requestAnimationFrame(this._animate); 50 | this.update(); 51 | }; 52 | 53 | /** 54 | * Engine instance. 55 | * @param canvasId HTML canvas id. 56 | */ 57 | constructor(canvasId: string) { 58 | const canvas = document.getElementById(canvasId); 59 | if (canvas instanceof HTMLCanvasElement) { 60 | this._canvas = new Canvas(canvas); 61 | this._canvas.resizeByClientSize(); 62 | } else { 63 | throw `canvas is not a HTMLCanvasElement!`; 64 | } 65 | const gl = canvas.getContext('webgl', {}); 66 | if (!gl) throw `init webgl rendering context failure!`; 67 | this._gl = gl; 68 | // ! 这样实例化场景好吗??? 69 | this.activeScene = new Scene(this); 70 | 71 | const whitePixel = new Uint8Array([255, 255, 255, 255]); 72 | const whiteTexture2D = new Texture2D(this, 1, 1, TextureFormat.R8G8B8A8, false); 73 | whiteTexture2D.setPixelBuffer(whitePixel); 74 | 75 | const whiteTextureCube = new TextureCube(this, 1, TextureFormat.R8G8B8A8, false); 76 | whiteTextureCube.setPixelBuffer(TextureCubeFace.PositiveX, whitePixel); 77 | whiteTextureCube.setPixelBuffer(TextureCubeFace.NegativeX, whitePixel); 78 | whiteTextureCube.setPixelBuffer(TextureCubeFace.PositiveY, whitePixel); 79 | whiteTextureCube.setPixelBuffer(TextureCubeFace.NegativeY, whitePixel); 80 | whiteTextureCube.setPixelBuffer(TextureCubeFace.PositiveZ, whitePixel); 81 | whiteTextureCube.setPixelBuffer(TextureCubeFace.NegativeZ, whitePixel); 82 | 83 | this._whiteTexture2D = whiteTexture2D; 84 | this._whiteTextureCube = whiteTextureCube; 85 | } 86 | 87 | /** 88 | * Update all data. 89 | */ 90 | update() { 91 | const time = this._time; 92 | const deltaTime = time.deltaTime; 93 | const camera = this.activeScene.camera; 94 | // 更新相机位置信息 95 | camera.orbitControl.onUpdate(deltaTime); 96 | 97 | time.tick(); 98 | 99 | this._render(); 100 | } 101 | 102 | /** 103 | * Render based on updated data. 104 | */ 105 | _render(): void { 106 | const gl = this._gl; 107 | gl.viewport(0, 0, this.canvas.width, this.canvas.height); 108 | // 这个放这没问题,不然背景画不出来 109 | gl.depthFunc(gl.LESS); 110 | // TODO: 这些状态不应该每次都进行获取 111 | const scene = this.activeScene; 112 | const globe = scene.globe; 113 | const camera = scene.camera; 114 | camera && camera.render(); 115 | 116 | // 首先渲染地球 117 | const { mesh, material } = globe; 118 | const globeProgram = material.shader._getShaderProgram(this); 119 | globeProgram.uploadAll(globeProgram.sceneUniformBlock, scene.shaderData); 120 | globeProgram.uploadAll(globeProgram.cameraUniformBlock, camera.shaderData); 121 | globeProgram.uploadAll(globeProgram.materialUniformBlock, material.shaderData); 122 | mesh._draw(globeProgram, mesh.subMesh); 123 | 124 | // TODO: 这里要改成递归场景树渲染 125 | // entities.forEach((entity) => { 126 | // const { mesh, material } = entity; 127 | // // ! 这里每次都要去编译shader代码!!! 128 | // // TODO: ShaderProgramPool 129 | // const program = material.shader._getShaderProgram(this); 130 | // // 上传相机的数据,这里还需要上传其他模块的数据,比如:场景,材质等 131 | // // 场景的shaderData主要是光线 132 | // // ! 这里每个实体都要 133 | // program.uploadAll(program.sceneUniformBlock, scene.shaderData); 134 | // program.uploadAll(program.cameraUniformBlock, camera.shaderData); 135 | // program.uploadAll(program.materialUniformBlock, material.shaderData); 136 | // mesh._draw(program, mesh.subMesh); 137 | // }); 138 | 139 | // 最后渲染背景; 140 | gl.depthFunc(gl.LEQUAL); 141 | const { _mesh, _material } = scene.background; 142 | // ! 每次渲染都去实例化不可以!而且bind不应该放在构造函数,否则无法切换program 143 | const skyProgram = _material.shader._getShaderProgram(this); 144 | skyProgram.uploadAll(skyProgram.cameraUniformBlock, camera.shaderData); 145 | skyProgram.uploadAll(skyProgram.materialUniformBlock, _material.shaderData); 146 | _mesh._draw(skyProgram, _mesh.subMesh); 147 | } 148 | 149 | /** 150 | * Timing and rendering. 151 | */ 152 | resume(): void { 153 | this.time.reset(); 154 | this._requestId = requestAnimationFrame(this._animate); 155 | } 156 | 157 | /** 158 | * Engine run. 159 | */ 160 | run() { 161 | this.resume(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/core/Renderer.ts: -------------------------------------------------------------------------------- 1 | import { ShaderProgram } from './shader/ShaderProgram'; 2 | import { Mesh, SubMesh } from './graphic'; 3 | 4 | /** 5 | * Renderer, each Mesh will have a renderer instance. 6 | */ 7 | export class Renderer { 8 | /** Current bind program. */ 9 | static glProgram: ShaderProgram; 10 | // TODO: 要接入webgl2, 应该抽出一个类型 11 | private gl: WebGLRenderingContext; 12 | /** Array of addresses of attribute variables in shader programs. */ 13 | protected attribLocArray: number[]; 14 | /** Mesh to be rendered. */ 15 | protected readonly _primitive: Mesh; 16 | 17 | /** 18 | * Render based on rendering context and grid. 19 | * @param gl WebGL rendering context. 20 | * @param primitive Mesh to be rendered. 21 | */ 22 | constructor(gl: WebGLRenderingContext, primitive: Mesh) { 23 | this._primitive = primitive; 24 | this.gl = gl; 25 | this.initRenderState(); 26 | } 27 | 28 | /** 29 | * Bind buffer and attribute. 30 | */ 31 | protected bindBufferAndAttrib(shaderProgram: ShaderProgram): void { 32 | const gl = this.gl; 33 | const primitive = this._primitive; 34 | const vertexBufferBindings = primitive._vertexBufferBindings; 35 | 36 | this.attribLocArray = []; 37 | const attributeLocation = shaderProgram.attributeLocation; 38 | const attributes = primitive._vertexElementMap; 39 | 40 | let vbo: WebGLBuffer; 41 | let lastBoundVbo: WebGLBuffer; 42 | 43 | for (const name in attributeLocation) { 44 | const loc = attributeLocation[name]; 45 | if (loc === -1) continue; 46 | 47 | const element = attributes[name]; 48 | if (element) { 49 | const { buffer, stride } = vertexBufferBindings[element.bindingIndex]; 50 | vbo = buffer._nativeBuffer; 51 | if (lastBoundVbo !== vbo) { 52 | lastBoundVbo = vbo; 53 | gl.bindBuffer(gl.ARRAY_BUFFER, vbo); 54 | } 55 | 56 | gl.enableVertexAttribArray(loc); 57 | const { size, type, normalized } = element._glElementInfo; 58 | // gl.vertexAttribPointer(loc, size, type, normalized, 0, element.offset); 59 | gl.vertexAttribPointer(loc, size, type, normalized, stride, element.offset); 60 | this.attribLocArray.push(loc); 61 | } else { 62 | console.warn('vertex attribute not found: ' + name); 63 | } 64 | } 65 | gl.bindBuffer(gl.ARRAY_BUFFER, null); 66 | } 67 | 68 | // TODO: 这个渲染状态是不是应该考虑放到材质里面,并且抽出一个RenderState 69 | /** 70 | * Clear depth, color buffer, etc. 71 | */ 72 | initRenderState() { 73 | const gl = this.gl; 74 | gl.clearColor(0, 0, 0, 0); 75 | gl.enable(gl.DEPTH_TEST); 76 | gl.cullFace(gl.FRONT); 77 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 78 | } 79 | 80 | /** 81 | * Draw the primitive. 82 | */ 83 | draw(shaderProgram: ShaderProgram, subMesh: SubMesh): void { 84 | const gl = this.gl; 85 | const primitive = this._primitive; 86 | 87 | this.bindBufferAndAttrib(shaderProgram); 88 | 89 | const { _indexBufferBinding, _instanceCount, _glIndexType, _glIndexByteCount } = primitive; 90 | const { topology, start, count } = subMesh; 91 | 92 | if (!_instanceCount) { 93 | if (_indexBufferBinding) { 94 | const { _nativeBuffer } = _indexBufferBinding.buffer; 95 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _nativeBuffer); 96 | gl.drawElements(topology, count, _glIndexType, start * _glIndexByteCount); 97 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 98 | } else { 99 | gl.drawArrays(topology, start, count); 100 | } 101 | } 102 | } 103 | 104 | testDraw(shaderProgram: ShaderProgram) { 105 | const gl = this.gl; 106 | const position = new Float32Array([ 107 | 1.0, 108 | 1.0, 109 | 1.0, 110 | -1.0, 111 | 1.0, 112 | 1.0, 113 | -1.0, 114 | -1.0, 115 | 1.0, 116 | 1.0, 117 | -1.0, 118 | 1.0, //front面 v0-4 119 | 1.0, 120 | 1.0, 121 | 1.0, 122 | 1.0, 123 | -1.0, 124 | 1.0, 125 | 1.0, 126 | -1.0, 127 | -1.0, 128 | 1.0, 129 | 1.0, 130 | -1.0, //right v0345 131 | 1.0, 132 | 1.0, 133 | 1.0, 134 | 1.0, 135 | 1.0, 136 | -1.0, 137 | -1.0, 138 | 1.0, 139 | -1.0, 140 | -1.0, 141 | 1.0, 142 | 1.0, //up v0561 143 | -1.0, 144 | 1.0, 145 | 1.0, 146 | -1.0, 147 | -1.0, 148 | 1.0, 149 | -1.0, 150 | -1.0, 151 | -1.0, 152 | -1.0, 153 | 1.0, 154 | -1.0, //left 155 | -1.0, 156 | -1.0, 157 | 1.0, 158 | 1.0, 159 | -1.0, 160 | 1.0, 161 | 1.0, 162 | -1.0, 163 | -1.0, 164 | -1.0, 165 | -1.0, 166 | -1.0, //down 167 | 1.0, 168 | -1.0, 169 | -1.0, 170 | 1.0, 171 | 1.0, 172 | -1.0, 173 | -1.0, 174 | 1.0, 175 | -1.0, 176 | -1.0, 177 | -1.0, 178 | -1.0, //back 179 | ]); 180 | var buf = gl.createBuffer(); 181 | gl.bindBuffer(gl.ARRAY_BUFFER, buf); 182 | gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW); 183 | var loc = gl.getAttribLocation(shaderProgram.glProgram, 'POSITION'); 184 | gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); 185 | gl.enableVertexAttribArray(loc); 186 | const indice = new Uint8Array([ 187 | 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 188 | 22, 20, 22, 23, 189 | ]); 190 | var buf = gl.createBuffer(); 191 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf); 192 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indice, gl.STATIC_DRAW); 193 | gl.enable(gl.DEPTH_TEST); 194 | gl.clearColor(1.0, 1.0, 1.0, 1.0); 195 | gl.drawElements(gl.TRIANGLES, indice.length, gl.UNSIGNED_BYTE, 0); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/core/graphic/Buffer.ts: -------------------------------------------------------------------------------- 1 | import { BufferBindFlag } from './enums/BufferBindFlag'; 2 | import { BufferUsage } from './enums/BufferUsage'; 3 | import { BufferUtil } from './BufferUtil'; 4 | 5 | /** 6 | * Buffer base class, 7 | * which can be an array of vertex buffers or an array of index buffers. 8 | */ 9 | export class Buffer { 10 | // TODO: 把gl挂载到RefObject 11 | _gl: WebGLRenderingContext; 12 | _glBindTarget: number; 13 | _glBufferUsage: number; 14 | _nativeBuffer: WebGLBuffer; 15 | 16 | private _type: BufferBindFlag; 17 | private _byteLength: number; 18 | private _bufferUsage: BufferUsage; 19 | 20 | /** 21 | * Buffer binding flag. 22 | */ 23 | get type(): BufferBindFlag { 24 | return this._type; 25 | } 26 | 27 | /** 28 | * Byte length. 29 | */ 30 | get byteLength(): number { 31 | return this._byteLength; 32 | } 33 | 34 | /** 35 | * Buffer usage. 36 | */ 37 | get bufferUsage(): BufferUsage { 38 | return this._bufferUsage; 39 | } 40 | 41 | /** 42 | * Create Buffer. 43 | * @param gl - WebGLRenderingContext 44 | * @param type - Buffer binding flag 45 | * @param byteLength - Byte length 46 | * @param bufferUsage - Buffer usage 47 | */ 48 | constructor(gl: WebGLRenderingContext, type: BufferBindFlag, byteLength: number, bufferUsage?: BufferUsage); 49 | 50 | /** 51 | * Create Buffer. 52 | * @param gl - WebGLRenderingContext 53 | * @param type - Buffer binding flag 54 | * @param data - Byte 55 | * @param bufferUsage - Buffer usage 56 | */ 57 | constructor( 58 | gl: WebGLRenderingContext, 59 | type: BufferBindFlag, 60 | data: ArrayBuffer | ArrayBufferView, 61 | bufferUsage?: BufferUsage, 62 | ); 63 | 64 | constructor( 65 | gl: WebGLRenderingContext, 66 | type: BufferBindFlag, 67 | byteLengthOrData: number | ArrayBuffer | ArrayBufferView, 68 | bufferUsage: BufferUsage = BufferUsage.Static, 69 | ) { 70 | this._gl = gl; 71 | this._type = type; 72 | this._bufferUsage = bufferUsage; 73 | 74 | const glBufferUsage = BufferUtil._getGLBufferUsage(gl, bufferUsage); 75 | const glBindTarget = type === BufferBindFlag.VertexBuffer ? gl.ARRAY_BUFFER : gl.ELEMENT_ARRAY_BUFFER; 76 | 77 | this._nativeBuffer = gl.createBuffer(); 78 | this._glBufferUsage = glBufferUsage; 79 | this._glBindTarget = glBindTarget; 80 | 81 | this.bind(); 82 | if (typeof byteLengthOrData === 'number') { 83 | this._byteLength = byteLengthOrData; 84 | gl.bufferData(glBindTarget, byteLengthOrData, glBufferUsage); 85 | } else { 86 | this._byteLength = byteLengthOrData.byteLength; 87 | gl.bufferData(glBindTarget, byteLengthOrData, glBufferUsage); 88 | } 89 | gl.bindBuffer(glBindTarget, null); 90 | } 91 | 92 | /** 93 | * Bind buffer. 94 | */ 95 | bind(): void { 96 | const gl = this._gl; 97 | gl.bindBuffer(this._glBindTarget, this._nativeBuffer); 98 | } 99 | 100 | /** 101 | * Set buffer data. 102 | * @param data - Input buffer data 103 | */ 104 | setData(data: ArrayBuffer | ArrayBufferView): void; 105 | 106 | /** 107 | * Set buffer data. 108 | * @param data - Input buffer data 109 | * @param bufferByteOffset - buffer byte offset 110 | */ 111 | setData(data: ArrayBuffer | ArrayBufferView, bufferByteOffset: number): void; 112 | 113 | /** 114 | * Set buffer data. 115 | * @param data - Input buffer data 116 | * @param bufferByteOffset - Buffer byte offset 117 | * @param dataOffset - Buffer byte offset 118 | * @param dataLength - Data length 119 | */ 120 | setData(data: ArrayBuffer | ArrayBufferView, bufferByteOffset: number, dataOffset: number, dataLength?: number): void; 121 | 122 | /** 123 | * Set buffer data. 124 | * @param data - Input buffer data 125 | * @param bufferByteOffset - Buffer byte offset 126 | * @param dataOffset - Buffer byte offset 127 | * @param dataLength - Data length 128 | * @param options - Update strategy: None/Discard/NoOverwrite 129 | */ 130 | setData(data: ArrayBuffer | ArrayBufferView, bufferByteOffset: number, dataOffset: number, dataLength: number): void; 131 | 132 | setData( 133 | data: ArrayBuffer | ArrayBufferView, 134 | bufferByteOffset: number = 0, 135 | dataOffset: number = 0, 136 | dataLength?: number, 137 | ): void { 138 | const gl: WebGLRenderingContext = this._gl; 139 | const glBindTarget: number = this._glBindTarget; 140 | this.bind(); 141 | 142 | // 每个元素所占用的字节数 143 | const byteSize = (data).BYTES_PER_ELEMENT || 1; 144 | const dataByteLength = dataLength ? byteSize * dataLength : data.byteLength; 145 | 146 | if (dataOffset !== 0 || dataByteLength < data.byteLength) { 147 | const isArrayBufferView = (data).byteOffset !== undefined; 148 | const subData = new Uint8Array( 149 | isArrayBufferView ? (data).buffer : data, 150 | dataOffset * byteSize, 151 | dataByteLength, 152 | ); 153 | gl.bufferSubData(glBindTarget, bufferByteOffset, subData); 154 | } else { 155 | gl.bufferSubData(glBindTarget, bufferByteOffset, data); 156 | } 157 | gl.bindBuffer(glBindTarget, null); 158 | } 159 | 160 | /** 161 | * Get buffer data. 162 | * @param data - Output buffer data 163 | */ 164 | getData(data: ArrayBufferView): void; 165 | 166 | /** 167 | * Get buffer data. 168 | * @param data - Output buffer data 169 | * @param bufferByteOffset - Buffer byte offset 170 | */ 171 | getData(data: ArrayBufferView, bufferByteOffset: number): void; 172 | 173 | /** 174 | * Get buffer data. 175 | * @param data - Output buffer data 176 | * @param bufferByteOffset - Buffer byte offset 177 | * @param dataOffset - Output data offset 178 | * @param dataLength - Output data length 179 | */ 180 | getData(data: ArrayBufferView, bufferByteOffset: number, dataOffset: number, dataLength: number): void; 181 | 182 | getData(data: ArrayBufferView, bufferByteOffset: number = 0, dataOffset: number = 0, dataLength?: number): void { 183 | throw 'Buffer is write-only on WebGL1.0 platforms.'; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/math/Color.ts: -------------------------------------------------------------------------------- 1 | import { MathUtil } from './MathUtil'; 2 | 3 | /** 4 | * Describes a color in the from of RGBA (in order: R, G, B, A). 5 | */ 6 | export class Color { 7 | /** 8 | * Modify a value from the gamma space to the linear space. 9 | * @param value - The value in gamma space 10 | * @returns The value in linear space 11 | */ 12 | static gammaToLinearSpace(value: number): number { 13 | // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_framebuffer_sRGB.txt 14 | // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_sRGB_decode.txt 15 | 16 | if (value <= 0.0) return 0.0; 17 | else if (value <= 0.04045) return value / 12.92; 18 | else if (value < 1.0) return Math.pow((value + 0.055) / 1.055, 2.4); 19 | else return Math.pow(value, 2.4); 20 | } 21 | 22 | /** 23 | * Modify a value from the linear space to the gamma space. 24 | * @param value - The value in linear space 25 | * @returns The value in gamma space 26 | */ 27 | static linearToGammaSpace(value: number): number { 28 | // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_framebuffer_sRGB.txt 29 | // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_sRGB_decode.txt 30 | 31 | if (value <= 0.0) return 0.0; 32 | else if (value < 0.0031308) return 12.92 * value; 33 | else if (value < 1.0) return 1.055 * Math.pow(value, 0.41666) - 0.055; 34 | else return Math.pow(value, 0.41666); 35 | } 36 | 37 | /** 38 | * Determines whether the specified colors are equals. 39 | * @param left - The first color to compare 40 | * @param right - The second color to compare 41 | * @returns True if the specified colors are equals, false otherwise 42 | */ 43 | static equals(left: Color, right: Color): boolean { 44 | return ( 45 | MathUtil.equals(left.r, right.r) && 46 | MathUtil.equals(left.g, right.g) && 47 | MathUtil.equals(left.b, right.b) && 48 | MathUtil.equals(left.a, right.a) 49 | ); 50 | } 51 | 52 | /** 53 | * Determines the sum of two colors. 54 | * @param left - The first color to add 55 | * @param right - The second color to add 56 | * @param out - The sum of two colors 57 | * @returns The added color 58 | */ 59 | static add(left: Color, right: Color, out: Color): Color { 60 | out.r = left.r + right.r; 61 | out.g = left.g + right.g; 62 | out.b = left.b + right.b; 63 | out.a = left.a + right.a; 64 | 65 | return out; 66 | } 67 | 68 | /** 69 | * Scale a color by the given value. 70 | * @param left - The color to scale 71 | * @param s - The amount by which to scale the color 72 | * @param out - The scaled color 73 | * @returns The scaled color 74 | */ 75 | static scale(left: Color, s: number, out: Color): Color { 76 | out.r = left.r * s; 77 | out.g = left.g * s; 78 | out.b = left.b * s; 79 | out.a = left.a * s; 80 | 81 | return out; 82 | } 83 | 84 | /** The red component of the color, 0~1. */ 85 | public r: number; 86 | /** The green component of the color, 0~1. */ 87 | public g: number; 88 | /** The blue component of the color, 0~1. */ 89 | public b: number; 90 | /** The alpha component of the color, 0~1. */ 91 | public a: number; 92 | 93 | /** 94 | * Constructor of Color. 95 | * @param r - The red component of the color 96 | * @param g - The green component of the color 97 | * @param b - The blue component of the color 98 | * @param a - The alpha component of the color 99 | */ 100 | constructor(r: number = 1, g: number = 1, b: number = 1, a: number = 1) { 101 | this.r = r; 102 | this.g = g; 103 | this.b = b; 104 | this.a = a; 105 | } 106 | 107 | /** 108 | * Set the value of this color. 109 | * @param r - The red component of the color 110 | * @param g - The green component of the color 111 | * @param b - The blue component of the color 112 | * @param a - The alpha component of the color 113 | * @returns This color. 114 | */ 115 | setValue(r: number, g: number, b: number, a: number): Color { 116 | this.r = r; 117 | this.g = g; 118 | this.b = b; 119 | this.a = a; 120 | return this; 121 | } 122 | 123 | /** 124 | * Determines the sum of this color and the specified color. 125 | * @param color - The specified color 126 | * @returns The added color 127 | */ 128 | add(color: Color): Color { 129 | this.r += color.r; 130 | this.g += color.g; 131 | this.b += color.b; 132 | this.a += color.a; 133 | 134 | return this; 135 | } 136 | 137 | /** 138 | * Scale this color by the given value. 139 | * @param s - The amount by which to scale the color 140 | * @returns The scaled color 141 | */ 142 | scale(s: number): Color { 143 | this.r *= s; 144 | this.g *= s; 145 | this.b *= s; 146 | this.a *= s; 147 | 148 | return this; 149 | } 150 | 151 | /** 152 | * Creates a clone of this color. 153 | * @returns A clone of this color 154 | */ 155 | clone(): Color { 156 | const ret = new Color(this.r, this.g, this.b, this.a); 157 | return ret; 158 | } 159 | 160 | /** 161 | * Clones this color to the specified color. 162 | * @param out - The specified color 163 | * @returns The specified color 164 | */ 165 | cloneTo(out: Color): Color { 166 | out.r = this.r; 167 | out.g = this.g; 168 | out.b = this.b; 169 | out.a = this.a; 170 | return out; 171 | } 172 | 173 | /** 174 | * Modify components (r, g, b) of this color from gamma space to linear space. 175 | * @param out - The color in linear space 176 | * @returns The color in linear space 177 | */ 178 | toLinear(out: Color): Color { 179 | out.r = Color.gammaToLinearSpace(this.r); 180 | out.g = Color.gammaToLinearSpace(this.g); 181 | out.b = Color.gammaToLinearSpace(this.b); 182 | return out; 183 | } 184 | 185 | /** 186 | * Modify components (r, g, b) of this color from linear space to gamma space. 187 | * @param out - The color in gamma space 188 | * @returns The color in gamma space 189 | */ 190 | toGamma(out: Color): Color { 191 | out.r = Color.linearToGammaSpace(this.r); 192 | out.g = Color.linearToGammaSpace(this.g); 193 | out.b = Color.linearToGammaSpace(this.b); 194 | return out; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/core/shader/ShaderUniform.ts: -------------------------------------------------------------------------------- 1 | import { Matrix4, Vector2, Vector3, Vector4, Color } from '../../math'; 2 | import { Texture } from '../texture'; 3 | import { ShaderPropertyValueType } from './ShaderData'; 4 | import { ColorSpace } from '../enums/ColorSpace'; 5 | 6 | /** 7 | * The encapsulation of each uniform variable, including its cache value, data upload method, and data storage address. 8 | */ 9 | export class ShaderUniform { 10 | name: string; 11 | propertyId: number; 12 | location: WebGLUniformLocation; 13 | applyFunc: (shaderUniform: ShaderUniform, value: ShaderPropertyValueType) => void; 14 | cacheValue: number | Vector2 | Vector3 | Vector4; 15 | textureIndex: GLenum | GLenum[]; 16 | textureDefault: Texture | Texture[]; 17 | 18 | private _gl: WebGLRenderingContext; 19 | private _colorSpace: ColorSpace; 20 | 21 | constructor(gl: WebGLRenderingContext) { 22 | this._gl = gl; 23 | } 24 | 25 | upload1f(shaderUniform: ShaderUniform, value: number): void { 26 | if (this.cacheValue !== value) { 27 | this._gl.uniform1f(shaderUniform.location, value); 28 | this.cacheValue = value; 29 | } 30 | } 31 | 32 | upload1fv(shaderUniform: ShaderUniform, value: Float32Array): void { 33 | this._gl.uniform1fv(shaderUniform.location, value); 34 | } 35 | 36 | upload2fv(shaderUniform: ShaderUniform, value: Float32Array): void { 37 | this._gl.uniform2fv(shaderUniform.location, value); 38 | } 39 | 40 | upload3f(shaderUniform: ShaderUniform, value: Vector3 | Vector4 | Color): void { 41 | const cacheValue = this.cacheValue; 42 | if ((value).r !== undefined) { 43 | if (cacheValue.x !== (value).r || cacheValue.y !== (value).g || cacheValue.z !== (value).b) { 44 | if (this._colorSpace === ColorSpace.Linear) { 45 | this._gl.uniform3f( 46 | shaderUniform.location, 47 | Color.gammaToLinearSpace((value).r), 48 | Color.gammaToLinearSpace((value).g), 49 | Color.gammaToLinearSpace((value).b), 50 | ); 51 | } else { 52 | this._gl.uniform3f(shaderUniform.location, (value).r, (value).g, (value).b); 53 | } 54 | cacheValue.x = (value).r; 55 | cacheValue.y = (value).g; 56 | cacheValue.z = (value).b; 57 | } 58 | } else { 59 | if ( 60 | cacheValue.x !== (value).x || 61 | cacheValue.y !== (value).y || 62 | cacheValue.z !== (value).z 63 | ) { 64 | this._gl.uniform3f(shaderUniform.location, (value).x, (value).y, (value).z); 65 | cacheValue.x = (value).x; 66 | cacheValue.y = (value).y; 67 | cacheValue.z = (value).z; 68 | } 69 | } 70 | } 71 | 72 | upload3fv(shaderUniform: ShaderUniform, value: Float32Array): void { 73 | this._gl.uniform3fv(shaderUniform.location, value); 74 | } 75 | 76 | upload4f(shaderUniform: ShaderUniform, value: Vector4 | Color): void { 77 | const cacheValue = this.cacheValue; 78 | if ((value).r !== undefined) { 79 | if ( 80 | cacheValue.x !== (value).r || 81 | cacheValue.y !== (value).g || 82 | cacheValue.z !== (value).b || 83 | cacheValue.w !== (value).a 84 | ) { 85 | if (this._colorSpace === ColorSpace.Linear) { 86 | this._gl.uniform4f( 87 | shaderUniform.location, 88 | Color.gammaToLinearSpace((value).r), 89 | Color.gammaToLinearSpace((value).g), 90 | Color.gammaToLinearSpace((value).b), 91 | (value).a, 92 | ); 93 | } else { 94 | this._gl.uniform4f( 95 | shaderUniform.location, 96 | (value).r, 97 | (value).g, 98 | (value).b, 99 | (value).a, 100 | ); 101 | } 102 | cacheValue.x = (value).r; 103 | cacheValue.y = (value).g; 104 | cacheValue.z = (value).b; 105 | cacheValue.w = (value).a; 106 | } 107 | } else { 108 | if ( 109 | cacheValue.x !== (value).x || 110 | cacheValue.y !== (value).y || 111 | cacheValue.z !== (value).z || 112 | cacheValue.w !== (value).w 113 | ) { 114 | this._gl.uniform4f( 115 | shaderUniform.location, 116 | (value).x, 117 | (value).y, 118 | (value).z, 119 | (value).w, 120 | ); 121 | cacheValue.x = (value).x; 122 | cacheValue.y = (value).y; 123 | cacheValue.z = (value).z; 124 | cacheValue.w = (value).w; 125 | } 126 | } 127 | } 128 | 129 | upload4fv(shaderUniform: ShaderUniform, value: Float32Array): void { 130 | this._gl.uniform4fv(shaderUniform.location, value); 131 | } 132 | 133 | upload1i(shaderUniform: ShaderUniform, value: number): void { 134 | if (this.cacheValue !== value) { 135 | this._gl.uniform1i(shaderUniform.location, value); 136 | this.cacheValue = value; 137 | } 138 | } 139 | 140 | upload1iv(shaderUniform: ShaderUniform, value: Int32Array): void { 141 | this._gl.uniform1iv(shaderUniform.location, value); 142 | } 143 | 144 | upload2iv(shaderUniform: ShaderUniform, value: Int32Array): void { 145 | this._gl.uniform2iv(shaderUniform.location, value); 146 | } 147 | 148 | upload3iv(shaderUniform: ShaderUniform, value: Int32Array): void { 149 | this._gl.uniform3iv(shaderUniform.location, value); 150 | } 151 | 152 | upload4iv(shaderUniform: ShaderUniform, value: Int32Array): void { 153 | this._gl.uniform4iv(shaderUniform.location, value); 154 | } 155 | 156 | uploadMat4(shaderUniform: ShaderUniform, value: Matrix4): void { 157 | this._gl.uniformMatrix4fv(shaderUniform.location, false, value.elements); 158 | } 159 | 160 | uploadMat4v(shaderUniform: ShaderUniform, value: Float32Array): void { 161 | this._gl.uniformMatrix4fv(shaderUniform.location, false, value); 162 | } 163 | 164 | uploadTexture(shaderUniform: ShaderUniform, value: Texture): void { 165 | // 开启第x号纹理单元 166 | this._gl.activeTexture(shaderUniform.textureIndex as GLenum); 167 | // 向target绑定纹理对象 168 | this._gl.bindTexture(value._glTarget, value._glTexture); 169 | } 170 | } 171 | --------------------------------------------------------------------------------