bg2e-js 2.1.2 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bg2e-js.js +7031 -6989
- package/dist/bg2e-js.js.map +1 -1
- package/package.json +20 -2
- package/src/app/AppController.ts +39 -0
- package/src/app/Bg2KeyboardEvent.ts +54 -0
- package/src/app/Bg2MouseEvent.ts +82 -0
- package/src/app/Bg2TouchEvent.ts +18 -0
- package/src/app/Canvas.ts +108 -0
- package/src/app/EventBase.ts +10 -0
- package/src/app/MainLoop.ts +273 -0
- package/src/app/index.ts +25 -0
- package/src/base/Color.ts +134 -0
- package/src/base/Environment.ts +183 -0
- package/src/base/Light.ts +192 -0
- package/src/base/Material.ts +619 -0
- package/src/base/PolyList.ts +365 -0
- package/src/base/Texture.ts +620 -0
- package/src/base/index.ts +81 -0
- package/src/db/Bg2LoaderPlugin.ts +129 -0
- package/src/db/DBPluginApi.ts +48 -0
- package/src/db/Loader.ts +116 -0
- package/src/db/LoaderPlugin.ts +34 -0
- package/src/db/MtlParser.ts +7 -0
- package/src/db/ObjLoaderPlugin.ts +55 -0
- package/src/db/ObjParser.ts +252 -0
- package/src/db/ObjWriterPlugin.ts +19 -0
- package/src/db/VitscnjLoaderPlugin.ts +100 -0
- package/src/db/Writer.ts +52 -0
- package/src/db/WriterPlugin.ts +22 -0
- package/src/db/index.ts +44 -0
- package/src/debug/DebugRenderer.ts +173 -0
- package/src/debug/WebGLTextureViewer.ts +75 -0
- package/src/debug/index.ts +7 -0
- package/src/index.html +11 -0
- package/src/index.ts +33 -0
- package/src/manipulation/SelectionBuffer.ts +82 -0
- package/src/manipulation/SelectionHighlight.ts +85 -0
- package/src/manipulation/SelectionIdAssignVisitor.ts +97 -0
- package/src/manipulation/SelectionManager.ts +166 -0
- package/src/manipulation/SelectionMode.ts +6 -0
- package/src/math/Mat3.ts +259 -0
- package/src/math/Mat4.ts +706 -0
- package/src/math/MatrixStrategy.ts +25 -0
- package/src/math/Quat.ts +65 -0
- package/src/math/Vec.ts +753 -0
- package/src/math/constants.ts +47 -0
- package/src/math/functions.ts +103 -0
- package/src/math/index.ts +74 -0
- package/src/phsics/joint.ts +137 -0
- package/src/primitives/arrow.ts +58 -0
- package/src/primitives/cone.ts +138 -0
- package/src/primitives/cube.ts +60 -0
- package/src/primitives/cylinder.ts +216 -0
- package/src/primitives/index.ts +13 -0
- package/src/primitives/plane.ts +31 -0
- package/src/primitives/sphere.ts +809 -0
- package/src/render/BRDFIntegrationMap.ts +4 -0
- package/src/render/Environment.ts +136 -0
- package/src/render/FrameBuffer.ts +35 -0
- package/src/render/MaterialRenderer.ts +34 -0
- package/src/render/Pipeline.ts +109 -0
- package/src/render/PolyListRenderer.ts +47 -0
- package/src/render/RenderBuffer.ts +197 -0
- package/src/render/RenderQueue.ts +199 -0
- package/src/render/RenderState.ts +116 -0
- package/src/render/Renderer.ts +248 -0
- package/src/render/SceneAppController.ts +238 -0
- package/src/render/SceneRenderer.ts +373 -0
- package/src/render/Shader.ts +32 -0
- package/src/render/ShadowRenderer.ts +176 -0
- package/src/render/SkyCube.ts +106 -0
- package/src/render/SkySphere.ts +118 -0
- package/src/render/TextureMergerRenderer.ts +70 -0
- package/src/render/TextureRenderer.ts +34 -0
- package/src/render/index.ts +67 -0
- package/src/render/webgl/FrameBuffer.ts +10 -0
- package/src/render/webgl/MaterialRenderer.ts +113 -0
- package/src/render/webgl/Pipeline.ts +89 -0
- package/src/render/webgl/PolyListRenderer.ts +260 -0
- package/src/render/webgl/RenderBuffer.ts +227 -0
- package/src/render/webgl/Renderer.ts +262 -0
- package/src/render/webgl/SceneRenderer.ts +68 -0
- package/src/render/webgl/ShaderProgram.ts +424 -0
- package/src/render/webgl/ShadowRenderer.ts +6 -0
- package/src/render/webgl/SkyCube.ts +16 -0
- package/src/render/webgl/SkySphere.ts +16 -0
- package/src/render/webgl/State.ts +152 -0
- package/src/render/webgl/TextureRenderer.ts +167 -0
- package/src/render/webgl/VertexBuffer.ts +137 -0
- package/src/render/webgl/index.ts +35 -0
- package/src/scene/Camera.ts +458 -0
- package/src/scene/Chain.ts +44 -0
- package/src/scene/ChainJoint.ts +58 -0
- package/src/scene/Component.ts +173 -0
- package/src/scene/ComponentMap.ts +107 -0
- package/src/scene/Drawable.ts +154 -0
- package/src/scene/EnvironmentComponent.ts +142 -0
- package/src/scene/FindNodeVisitor.ts +60 -0
- package/src/scene/LightComponent.ts +155 -0
- package/src/scene/MatrixState.ts +46 -0
- package/src/scene/Node.ts +314 -0
- package/src/scene/NodeVisitor.ts +15 -0
- package/src/scene/OrbitCameraController.ts +450 -0
- package/src/scene/SmoothOrbitCameraController.ts +99 -0
- package/src/scene/Transform.ts +73 -0
- package/src/scene/index.ts +57 -0
- package/src/shaders/BasicDiffuseColorShader.ts +111 -0
- package/src/shaders/BasicPBRLightShader.ts +277 -0
- package/src/shaders/DebugRenderShader.ts +98 -0
- package/src/shaders/DepthRenderShader.ts +91 -0
- package/src/shaders/IrradianceMapCubeShader.ts +116 -0
- package/src/shaders/PBRLightIBLShader.ts +487 -0
- package/src/shaders/PickSelectionShader.ts +101 -0
- package/src/shaders/PresentDebugFramebufferShader.ts +118 -0
- package/src/shaders/PresentTextureShader.ts +99 -0
- package/src/shaders/SelectionHighlightShader.ts +127 -0
- package/src/shaders/ShaderFunction.ts +318 -0
- package/src/shaders/SkyCubeShader.ts +94 -0
- package/src/shaders/SkySphereShader.ts +102 -0
- package/src/shaders/SpecularMapCubeShader.ts +165 -0
- package/src/shaders/TextureMergerShader.ts +171 -0
- package/src/shaders/index.ts +37 -0
- package/src/shaders/webgl/color_correction.glsl +47 -0
- package/src/shaders/webgl/constants.glsl +6 -0
- package/src/shaders/webgl/index.ts +70 -0
- package/src/shaders/webgl/normal_map.glsl +9 -0
- package/src/shaders/webgl/pbr.glsl +173 -0
- package/src/shaders/webgl/uniforms.glsl +91 -0
- package/src/shaders/webgl_shader_lib.ts +213 -0
- package/src/tools/BinaryResourceProvider.ts +14 -0
- package/src/tools/ImageResourceProvider.ts +66 -0
- package/src/tools/MaterialModifier.ts +276 -0
- package/src/tools/Resource.ts +203 -0
- package/src/tools/ResourceProvider.ts +69 -0
- package/src/tools/TextResourceProvider.ts +24 -0
- package/src/tools/TextureCache.ts +52 -0
- package/src/tools/TextureResourceDatabase.ts +100 -0
- package/src/tools/UserAgent.ts +362 -0
- package/src/tools/VideoResourceProvider.ts +50 -0
- package/src/tools/WriteStrategy.ts +22 -0
- package/src/tools/base64.ts +11 -0
- package/src/tools/crypto.ts +19 -0
- package/src/tools/endiantess.ts +13 -0
- package/src/tools/image.ts +18 -0
- package/src/tools/index.ts +41 -0
- package/src/tools/processType.ts +38 -0
- package/src/vite-env.d.ts +12 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import Texture, { TextureChannel, TextureTargetName } from "../../base/Texture";
|
|
2
|
+
import Material from "../../base/Material";
|
|
3
|
+
import MaterialRenderer from "../MaterialRenderer";
|
|
4
|
+
import WebGLTextureRenderer from "./TextureRenderer";
|
|
5
|
+
import TextureMerger from "../TextureMergerRenderer";
|
|
6
|
+
import ShaderProgram from "./ShaderProgram";
|
|
7
|
+
import Renderer from "../Renderer";
|
|
8
|
+
import { whiteTexture, createWhiteTexture, blackTexture, createBlackTexture } from "../../tools/TextureResourceDatabase";
|
|
9
|
+
|
|
10
|
+
export default class WebGLMaterialRenderer extends MaterialRenderer {
|
|
11
|
+
protected _whiteTexture: WebGLTextureRenderer;
|
|
12
|
+
protected _blackTexture: WebGLTextureRenderer;
|
|
13
|
+
protected _textureMerger: TextureMerger;
|
|
14
|
+
|
|
15
|
+
static async InitResources(renderer: Renderer) {
|
|
16
|
+
await createWhiteTexture(renderer);
|
|
17
|
+
await createBlackTexture(renderer);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor(renderer: Renderer, material: Material) {
|
|
21
|
+
super(renderer, material);
|
|
22
|
+
if (material.renderer) {
|
|
23
|
+
throw new Error("Duplicate material renderer set to material. Please, use the Renderer factory to get material renderer instance.");
|
|
24
|
+
}
|
|
25
|
+
// Link this material renderer to the material. This property is internal but should be accessed from the renderer
|
|
26
|
+
// The use of 'as any' is to provide access to the internal property like a friend class in C++
|
|
27
|
+
(material as any)._renderer = this;
|
|
28
|
+
|
|
29
|
+
this._whiteTexture = renderer.factory.texture(whiteTexture(renderer)) as WebGLTextureRenderer;
|
|
30
|
+
this._blackTexture = renderer.factory.texture(blackTexture(renderer)) as WebGLTextureRenderer;
|
|
31
|
+
this._textureMerger = renderer.factory.textureMerger();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
mergeTextures() {
|
|
35
|
+
if (this.material.dirty) {
|
|
36
|
+
const getTexture = (att: keyof Material, fallbackTexture = this._whiteTexture) => {
|
|
37
|
+
if (this.material[att] instanceof Texture) {
|
|
38
|
+
return this.material[att];
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return fallbackTexture.texture;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this._textureMerger.setTexture(getTexture('metalnessTexture'), TextureChannel.R, TextureChannel.R + this.material.metalnessChannel);
|
|
46
|
+
this._textureMerger.setTexture(getTexture('roughnessTexture'), TextureChannel.G, TextureChannel.R + this.material.roughnessChannel);
|
|
47
|
+
this._textureMerger.setTexture(getTexture('lightEmission', this._blackTexture), TextureChannel.B, TextureChannel.R + this.material.lightEmissionChannel);
|
|
48
|
+
this._textureMerger.setTexture(getTexture('ambientOcclussion'), TextureChannel.A, TextureChannel.R + this.material.ambientOcclussionChannel);
|
|
49
|
+
this._textureMerger.update();
|
|
50
|
+
this.material.dirty = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get metalnessRoughnessHeightAOTexture() {
|
|
55
|
+
return this._textureMerger.mergedTexture;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
destroy() {
|
|
59
|
+
console.log("Destroy material renderer");
|
|
60
|
+
if (this.material) {
|
|
61
|
+
// The use of 'as any' is to provide access to the internal property like a friend class in C++
|
|
62
|
+
(this.material as any)._renderer = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Bind the metalness, roughness, height and ambient occlussion combined texture
|
|
67
|
+
bindMetalnessRoughnessHeightAOTexture(shaderProgram: ShaderProgram, uniformName: string, textureUnit: number): boolean {
|
|
68
|
+
const texRenderer = this.renderer.factory.texture(this.metalnessRoughnessHeightAOTexture) as WebGLTextureRenderer;
|
|
69
|
+
shaderProgram.bindTexture(uniformName, texRenderer, textureUnit);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Binds the property to the uniformName uniform of the shader program, if the
|
|
74
|
+
// material property ies a texture. If not, it binds the fallbackTexture. If the fallbackTexture
|
|
75
|
+
// value is null, it binds a 2x2 px white texture
|
|
76
|
+
bindTexture(shaderProgram: ShaderProgram, property: keyof Material, uniformName: string, textureUnit: number, fallbackTexture: Texture | null = null) {
|
|
77
|
+
if (this.material[property] instanceof Texture) {
|
|
78
|
+
shaderProgram.bindTexture(uniformName, this.getTextureRenderer(property) as WebGLTextureRenderer, textureUnit);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
else if (fallbackTexture instanceof Texture) {
|
|
82
|
+
const texRenderer = this.renderer.factory.texture(fallbackTexture) as WebGLTextureRenderer;
|
|
83
|
+
shaderProgram.bindTexture(uniformName, texRenderer, textureUnit);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
shaderProgram.bindTexture(uniformName, this._whiteTexture, textureUnit);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Bind the property to the uniformName uniform of the shader program, if the
|
|
93
|
+
// material property is a color. If not, it binds the fallbackColor vector
|
|
94
|
+
bindColor(shaderProgram: ShaderProgram, property: keyof Material, uniformName: string, fallbackColor = [1, 1, 1, 1]) {
|
|
95
|
+
if (this.material[property].length>=4) {
|
|
96
|
+
shaderProgram.uniform4fv(uniformName, this.material[property]);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
shaderProgram.uniform4fv(uniformName, fallbackColor);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Bind the property to the uniformName uniform of the shader program, if the
|
|
104
|
+
// material property is a number. If not, it binds the fallbackValue value
|
|
105
|
+
bindValue(shaderProgram: ShaderProgram, property: keyof Material, uniformName: string, fallbackValue = 1) {
|
|
106
|
+
if (typeof(this.material[property]) === "number") {
|
|
107
|
+
shaderProgram.uniform1f(uniformName, this.material[property]);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
shaderProgram.uniform1f(uniformName, fallbackValue);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
|
|
2
|
+
import Pipeline, { BlendEquation, BlendFunction } from "../Pipeline";
|
|
3
|
+
|
|
4
|
+
const getBlendEquation = (gl: WebGLRenderingContext, blendEquation: BlendEquation): number => {
|
|
5
|
+
switch (blendEquation) {
|
|
6
|
+
case BlendEquation.ADD:
|
|
7
|
+
return gl.FUNC_ADD;
|
|
8
|
+
case BlendEquation.SUBTRACT:
|
|
9
|
+
return gl.FUNC_SUBTRACT;
|
|
10
|
+
case BlendEquation.REVERSE_SUBTRACT:
|
|
11
|
+
return gl.FUNC_REVERSE_SUBTRACT;
|
|
12
|
+
}
|
|
13
|
+
throw new Error(`Invalid blend equation specified in WebGLPipeline: ${ blendEquation }`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const getBlendFunc = (gl: WebGLRenderingContext, blendFunc: BlendFunction): number | null => {
|
|
17
|
+
switch (blendFunc) {
|
|
18
|
+
case BlendFunction.NULL:
|
|
19
|
+
return null;
|
|
20
|
+
case BlendFunction.ZERO:
|
|
21
|
+
return gl.ZERO;
|
|
22
|
+
case BlendFunction.ONE:
|
|
23
|
+
return gl.ONE;
|
|
24
|
+
case BlendFunction.SRC_COLOR:
|
|
25
|
+
return gl.SRC_COLOR;
|
|
26
|
+
case BlendFunction.ONE_MINUS_SRC_COLOR:
|
|
27
|
+
return gl.ONE_MINUS_SRC_COLOR;
|
|
28
|
+
case BlendFunction.DST_COLOR:
|
|
29
|
+
return gl.DST_COLOR;
|
|
30
|
+
case BlendFunction.ONE_MINUS_DST_COLOR:
|
|
31
|
+
return gl.ONE_MINUS_DST_COLOR;
|
|
32
|
+
case BlendFunction.SRC_ALPHA:
|
|
33
|
+
return gl.SRC_ALPHA;
|
|
34
|
+
case BlendFunction.ONE_MINUS_SRC_ALPHA:
|
|
35
|
+
return gl.ONE_MINUS_SRC_ALPHA;
|
|
36
|
+
case BlendFunction.DST_ALPHA:
|
|
37
|
+
return gl.DST_ALPHA;
|
|
38
|
+
case BlendFunction.ONE_MINUS_DST_ALPHA:
|
|
39
|
+
return gl.ONE_MINUS_DST_ALPHA;
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`Invalid blend function specified in WebGLPipeline: ${ blendFunc }`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default class WebGLPipeline extends Pipeline {
|
|
45
|
+
private _blendEquation!: number;
|
|
46
|
+
private _blendFuncSrcColor!: number | null;
|
|
47
|
+
private _blendFuncSrcAlpha!: number | null;
|
|
48
|
+
private _blendFuncDstColor!: number | null;
|
|
49
|
+
private _blendFuncDstAlpha!: number | null;
|
|
50
|
+
private _blendFunc!: (a: number | null, b: number | null, c?: number | null, d?: number | null) => void;
|
|
51
|
+
|
|
52
|
+
create(): void {
|
|
53
|
+
const { gl } = this.renderer;
|
|
54
|
+
|
|
55
|
+
// Set the webgl equivalent values
|
|
56
|
+
this._blendEquation = getBlendEquation(gl, this.blendState.blendEquation);
|
|
57
|
+
this._blendFuncSrcColor = getBlendFunc(gl, this.blendState.blendFuncSrc);
|
|
58
|
+
this._blendFuncSrcAlpha = getBlendFunc(gl, this.blendState.blendFuncSrcAlpha);
|
|
59
|
+
this._blendFuncDstColor = getBlendFunc(gl, this.blendState.blendFuncDst);
|
|
60
|
+
this._blendFuncDstAlpha = getBlendFunc(gl, this.blendState.blendFuncDstAlpha);
|
|
61
|
+
if ((this._blendFuncDstAlpha === null && this._blendFuncSrcAlpha !== null) ||
|
|
62
|
+
(this._blendFuncDstAlpha !== null && this._blendFuncSrcAlpha === null))
|
|
63
|
+
{
|
|
64
|
+
throw new Error("WebGLPipeline.create(): Invalid values of blendFuncDstAlpha and blendFuncSrcAlpha");
|
|
65
|
+
}
|
|
66
|
+
this._blendFunc = this._blendFuncDstAlpha !== null ? (a,b) => gl.blendFunc(a,b) : (a,b,c,d) => gl.blendFuncSeparate(a,b,c,d);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
activate(): void {
|
|
70
|
+
const { gl, state } = this.renderer;
|
|
71
|
+
this.blendState.enabled ? gl.enable(gl.BLEND) : gl.disable(gl.BLEND);
|
|
72
|
+
gl.blendEquation(this._blendEquation);
|
|
73
|
+
this._blendFunc(
|
|
74
|
+
this._blendFuncSrcColor,
|
|
75
|
+
this._blendFuncDstColor,
|
|
76
|
+
this._blendFuncSrcAlpha,
|
|
77
|
+
this._blendFuncDstAlpha
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
state.depthTestEnabled = this.depthTest;
|
|
81
|
+
|
|
82
|
+
if (this.cullFace) {
|
|
83
|
+
gl.enable(gl.CULL_FACE);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
gl.disable(gl.CULL_FACE);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
|
|
2
|
+
import { DrawMode, PolyListCullFace, PolyListFrontFace } from "../../base/PolyList";
|
|
3
|
+
import PolyListRenderer from "../PolyListRenderer";
|
|
4
|
+
import VertexBuffer, { BufferTarget } from "./VertexBuffer";
|
|
5
|
+
import type Renderer from "../Renderer";
|
|
6
|
+
import WebGLRenderer from "./Renderer";
|
|
7
|
+
import type PolyList from "../../base/PolyList";
|
|
8
|
+
|
|
9
|
+
interface Offsets {
|
|
10
|
+
vertex: number;
|
|
11
|
+
normal: number;
|
|
12
|
+
texCoord0: number;
|
|
13
|
+
texCoord1: number;
|
|
14
|
+
texCoord2: number;
|
|
15
|
+
color: number;
|
|
16
|
+
tangent: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default class WebGLPolyListRenderer extends PolyListRenderer {
|
|
20
|
+
private _vertexBuffer: VertexBuffer | null = null;
|
|
21
|
+
private _indexBuffer: VertexBuffer | null = null;
|
|
22
|
+
private _indexArrayFormat: number | null = null;
|
|
23
|
+
private _stride: number = 0;
|
|
24
|
+
private _offsets: Offsets = { vertex: 0, normal: 0, texCoord0: 0, texCoord1: 0, texCoord2: 0, color: 0, tangent: 0 };
|
|
25
|
+
|
|
26
|
+
constructor(renderer: Renderer, polyList: PolyList) {
|
|
27
|
+
super(renderer, polyList);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
init(): void {
|
|
31
|
+
this._vertexBuffer = null;
|
|
32
|
+
this._indexBuffer = null;
|
|
33
|
+
this._indexArrayFormat = null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get valid(): boolean {
|
|
37
|
+
return this._vertexBuffer !== null && this._indexArrayFormat !== null && this._indexBuffer !== null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
refresh(): void {
|
|
41
|
+
const gl = (this.renderer as WebGLRenderer)?.gl;
|
|
42
|
+
if (!gl) {
|
|
43
|
+
throw new Error("WebGLPolyListRenderer: refresh() called without a valid WebGL context");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const getVector = (items: number[] | null | undefined, current: number, stride: number): number[] | null => {
|
|
47
|
+
if (!items || items.length === 0) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const offset = current * stride;
|
|
52
|
+
if (stride === 2) {
|
|
53
|
+
return [items[offset], items[offset + 1]];
|
|
54
|
+
} else if (stride === 3) {
|
|
55
|
+
return [items[offset], items[offset + 1], items[offset + 2]];
|
|
56
|
+
} else {
|
|
57
|
+
return [items[offset], items[offset + 1], items[offset + 2], items[offset + 3]];
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const numElements = this.polyList.vertex.length / 3;
|
|
62
|
+
const result = [];
|
|
63
|
+
for (let i = 0; i < numElements; ++i) {
|
|
64
|
+
const v = getVector(this.polyList.vertex, i, 3);
|
|
65
|
+
const n = getVector(this.polyList.normal, i, 3);
|
|
66
|
+
const t0 = getVector(this.polyList.texCoord0, i, 2);
|
|
67
|
+
const t1 = getVector(this.polyList.texCoord1, i, 2);
|
|
68
|
+
const t2 = getVector(this.polyList.texCoord2, i, 2);
|
|
69
|
+
const c = getVector(this.polyList.color, i, 4);
|
|
70
|
+
const t = getVector(this.polyList.tangent , i, 3);
|
|
71
|
+
|
|
72
|
+
if (v) {
|
|
73
|
+
result.push(...v);
|
|
74
|
+
}
|
|
75
|
+
if (n) {
|
|
76
|
+
result.push(...n);
|
|
77
|
+
}
|
|
78
|
+
if (t0) {
|
|
79
|
+
result.push(...t0);
|
|
80
|
+
}
|
|
81
|
+
if (t1) {
|
|
82
|
+
result.push(...t1);
|
|
83
|
+
}
|
|
84
|
+
if (t2) {
|
|
85
|
+
result.push(...t2);
|
|
86
|
+
}
|
|
87
|
+
if (c) {
|
|
88
|
+
result.push(...c);
|
|
89
|
+
}
|
|
90
|
+
if (t) {
|
|
91
|
+
result.push(...t);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this._stride = 3;
|
|
96
|
+
const vertex = 0;
|
|
97
|
+
const normal = 3;
|
|
98
|
+
let texCoord0 = 3;
|
|
99
|
+
let texCoord1 = 3;
|
|
100
|
+
let texCoord2 = 3;
|
|
101
|
+
let color = 3;
|
|
102
|
+
let tangent = 3;
|
|
103
|
+
if (this.hasNormal) {
|
|
104
|
+
this._stride += 3;
|
|
105
|
+
texCoord0 += 3;
|
|
106
|
+
texCoord1 += 3;
|
|
107
|
+
texCoord2 += 3;
|
|
108
|
+
color += 3;
|
|
109
|
+
tangent += 3;
|
|
110
|
+
}
|
|
111
|
+
if (this.hasTexCoord0) {
|
|
112
|
+
this._stride += 2;
|
|
113
|
+
texCoord1 += 2;
|
|
114
|
+
texCoord2 += 2;
|
|
115
|
+
color += 2;
|
|
116
|
+
tangent += 2;
|
|
117
|
+
}
|
|
118
|
+
if (this.hasTexCoord1) {
|
|
119
|
+
this._stride += 2;
|
|
120
|
+
texCoord2 += 2;
|
|
121
|
+
color += 2;
|
|
122
|
+
tangent += 2;
|
|
123
|
+
}
|
|
124
|
+
if (this.hasTexCoord2) {
|
|
125
|
+
this._stride += 2;
|
|
126
|
+
color += 2;
|
|
127
|
+
tangent += 2;
|
|
128
|
+
}
|
|
129
|
+
if (this.hasColor) {
|
|
130
|
+
this._stride += 4;
|
|
131
|
+
tangent += 4;
|
|
132
|
+
}
|
|
133
|
+
if (this.hasTangent) {
|
|
134
|
+
this._stride += 3;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this._offsets = { vertex, normal, texCoord0, texCoord1, texCoord2, color, tangent };
|
|
138
|
+
this._vertexBuffer = VertexBuffer.CreateArrayBuffer(gl, new Float32Array(result));
|
|
139
|
+
const indexArray = this.polyList.index.length < 65535 ? new Uint16Array(this.polyList.index) : new Uint32Array(this.polyList.index);
|
|
140
|
+
this._indexBuffer = VertexBuffer.CreateElementArrayBuffer(gl, indexArray);
|
|
141
|
+
this._indexArrayFormat = indexArray instanceof Uint16Array ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
get hasNormal(): boolean {
|
|
145
|
+
return this._polyList.normal.length > 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
get hasTexCoord0(): boolean {
|
|
149
|
+
return this._polyList.texCoord0.length > 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get hasTexCoord1(): boolean {
|
|
153
|
+
return this._polyList.texCoord1.length > 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get hasTexCoord2(): boolean {
|
|
157
|
+
return this._polyList.texCoord2.length > 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get hasColor(): boolean {
|
|
161
|
+
return this._polyList.color.length > 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
get hasTangent(): boolean {
|
|
165
|
+
return this._polyList.tangent && this._polyList.tangent?.length > 0 || false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
positionAttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
169
|
+
return { name, stride: this._stride, size: 3, offset: 0, enable: true }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
normalAttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
173
|
+
return { name, stride: this._stride, size: 3, offset: this._offsets.normal, enable: true }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
texCoord0AttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
177
|
+
return { name, stride: this._stride, size: 2, offset: this._offsets.texCoord0, enable: true }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
texCoord1AttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
181
|
+
return { name, stride: this._stride, size: 2, offset: this._offsets.texCoord1, enable: true }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
texCoord2AttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
185
|
+
return { name, stride: this._stride, size: 2, offset: this._offsets.texCoord2, enable: true }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
colorAttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
189
|
+
return { name, stride: this._stride, size: 4, offset: this._offsets.color, enable: true }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
tangentAttribParams(name: string): { name: string; stride: number; size: number; offset: number; enable: boolean } {
|
|
193
|
+
return { name, stride: this._stride, size: 3, offset: this._offsets.tangent, enable: true }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
bindBuffers(): void {
|
|
197
|
+
this._vertexBuffer?.bind(BufferTarget.ARRAY_BUFFER);
|
|
198
|
+
this._indexBuffer?.bind(BufferTarget.ELEMENT_ARRAY_BUFFER);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
draw(): void {
|
|
202
|
+
const { gl, state } = this.renderer as WebGLRenderer;
|
|
203
|
+
|
|
204
|
+
state.cullFaceEnabled = this.polyList.enableCullFace;
|
|
205
|
+
|
|
206
|
+
switch (this.polyList.frontFace) {
|
|
207
|
+
case PolyListFrontFace.CCW:
|
|
208
|
+
state.frontFace = state.CCW;
|
|
209
|
+
break;
|
|
210
|
+
case PolyListFrontFace.CW:
|
|
211
|
+
state.frontFace = state.CW;
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
switch (this.polyList.cullFace) {
|
|
216
|
+
case PolyListCullFace.BACK:
|
|
217
|
+
state.cullFace = state.BACK;
|
|
218
|
+
break;
|
|
219
|
+
case PolyListCullFace.FRONT:
|
|
220
|
+
state.cullFace = state.FRONT;
|
|
221
|
+
break;
|
|
222
|
+
case PolyListCullFace.FRONT_AND_BACK:
|
|
223
|
+
state.cullFace = state.FRONT_AND_BACK;
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
let mode = 0;
|
|
230
|
+
switch (this._polyList.drawMode) {
|
|
231
|
+
case DrawMode.POINTS:
|
|
232
|
+
mode = gl.POINTS;
|
|
233
|
+
break;
|
|
234
|
+
case DrawMode.TRIANGLES:
|
|
235
|
+
mode = gl.TRIANGLES;
|
|
236
|
+
break;
|
|
237
|
+
case DrawMode.TRIANGLE_FAN:
|
|
238
|
+
mode = gl.TRIANGLE_FAN
|
|
239
|
+
break;
|
|
240
|
+
case DrawMode.TRIANGLE_STRIP:
|
|
241
|
+
mode = gl.TRIANGLE_STRIP;
|
|
242
|
+
break;
|
|
243
|
+
case DrawMode.LINES:
|
|
244
|
+
mode = gl.LINES;
|
|
245
|
+
break;
|
|
246
|
+
case DrawMode.LINE_STRIP:
|
|
247
|
+
mode = gl.LINE_STRIP;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
gl.lineWidth(this.polyList.lineWidth);
|
|
252
|
+
|
|
253
|
+
gl.drawElements(mode, this.polyList.index.length, this._indexArrayFormat || 0, 0);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
destroy(): void {
|
|
257
|
+
if (this._vertexBuffer) VertexBuffer.Delete(this._vertexBuffer);
|
|
258
|
+
if (this._indexBuffer) VertexBuffer.Delete(this._indexBuffer);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
|
|
2
|
+
import { TextureRenderTargetAttachment, TextureTargetName } from "../../base/Texture";
|
|
3
|
+
import Vec from "../../math/Vec";
|
|
4
|
+
import RenderBuffer, { RenderBufferType, CubeMapFace } from "../RenderBuffer";
|
|
5
|
+
import Texture from "../../base/Texture";
|
|
6
|
+
|
|
7
|
+
function glEnumToString(gl: WebGLRenderingContext, value: number): string {
|
|
8
|
+
for(var key in gl) {
|
|
9
|
+
if (gl[key as keyof WebGLRenderingContext] === value) {
|
|
10
|
+
return key;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return "0x" + value.toString(16);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getAttachmentPoint(gl: WebGLRenderingContext, att: number | string): number {
|
|
17
|
+
switch (Number(att)) {
|
|
18
|
+
case TextureRenderTargetAttachment.COLOR_ATTACHMENT_0:
|
|
19
|
+
return gl.COLOR_ATTACHMENT0;
|
|
20
|
+
case TextureRenderTargetAttachment.DEPTH_ATTACHMENT:
|
|
21
|
+
return gl.DEPTH_ATTACHMENT;
|
|
22
|
+
case TextureRenderTargetAttachment.STENCIL_ATTACHMENT:
|
|
23
|
+
return gl.STENCIL_ATTACHMENT;
|
|
24
|
+
default:
|
|
25
|
+
throw new Error(`RenderBuffer.beginUpdate() Error creating render buffer. Invalid attachment ${att}.`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getTextureTarget(gl: WebGLRenderingContext, texture: Texture): number {
|
|
30
|
+
return gl[TextureTargetName[texture.target] as keyof WebGLRenderingContext] as number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default class WebGLRenderBuffer extends RenderBuffer {
|
|
34
|
+
private _framebuffer?: WebGLFramebuffer | null;
|
|
35
|
+
private _depthBuffer?: WebGLRenderbuffer | null;
|
|
36
|
+
private _framebuffers?: WebGLFramebuffer[] | null;
|
|
37
|
+
private _depthBuffers?: WebGLRenderbuffer[] | null;
|
|
38
|
+
private _screenViewport?: Vec;
|
|
39
|
+
private _prevArrayBufferBinding?: WebGLBuffer | null;
|
|
40
|
+
private _prevElementBufferBinding?: WebGLBuffer | null;
|
|
41
|
+
constructor(renderer: any) {
|
|
42
|
+
super(renderer);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get frameBuffer(): any {
|
|
46
|
+
return this.renderer.frameBuffer;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
saveVertexBufferState(): void {
|
|
50
|
+
const { gl } = this.renderer;
|
|
51
|
+
this._prevArrayBufferBinding = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
|
|
52
|
+
this._prevElementBufferBinding = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
restoreVertexBufferState(): void {
|
|
56
|
+
const { gl } = this.renderer;
|
|
57
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._prevArrayBufferBinding);
|
|
58
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._prevElementBufferBinding);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
beginUpdate(textureFace: CubeMapFace = CubeMapFace.NONE): void {
|
|
62
|
+
if (this.type === RenderBufferType.TEXTURE) {
|
|
63
|
+
this.beginUpdateTexture();
|
|
64
|
+
}
|
|
65
|
+
else if (this.type === RenderBufferType.CUBE_MAP) {
|
|
66
|
+
this.beginUpdateCubemap(textureFace);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
throw new Error("The render buffer is not initialized");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
endUpdate(textureFace: CubeMapFace = CubeMapFace.NONE): void {
|
|
74
|
+
if (this.type === RenderBufferType.TEXTURE) {
|
|
75
|
+
this.endUpdateTexture();
|
|
76
|
+
}
|
|
77
|
+
else if (this.type === RenderBufferType.CUBE_MAP) {
|
|
78
|
+
this.endUpdateCubemap();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw new Error("The render buffer is not initialized");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
destroy(): void {
|
|
86
|
+
const { gl } = this.renderer;
|
|
87
|
+
if (this.type === RenderBufferType.TEXTURE) {
|
|
88
|
+
if (this._framebuffer) {
|
|
89
|
+
gl.deleteFramebuffer(this._framebuffer);
|
|
90
|
+
this._framebuffer = null;
|
|
91
|
+
}
|
|
92
|
+
if (this._depthBuffer) {
|
|
93
|
+
gl.deleteRenderbuffer(this._depthBuffer);
|
|
94
|
+
this._depthBuffer = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (this.type === RenderBufferType.CUBE_MAP) {
|
|
98
|
+
if (this._framebuffers?.length) {
|
|
99
|
+
this._framebuffers.forEach(fb => gl.deleteFramebuffer(fb));
|
|
100
|
+
}
|
|
101
|
+
if (this._depthBuffers?.length) {
|
|
102
|
+
this._depthBuffers.forEach(db => gl.deleteRenderbuffer(db));
|
|
103
|
+
}
|
|
104
|
+
this._framebuffers = null;
|
|
105
|
+
this._depthBuffers = null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
readPixels(x: number, y: number, width: number, height: number): Uint8Array | undefined {
|
|
110
|
+
const textureRenderer = this.attachments[0];
|
|
111
|
+
const texture = textureRenderer?.texture;
|
|
112
|
+
if (texture) {
|
|
113
|
+
const { gl } = this.renderer;
|
|
114
|
+
const data = new Uint8Array(width * height * 4);
|
|
115
|
+
gl.readPixels(x, texture.size.height - y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
116
|
+
return data;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
private beginUpdateTexture(): void {
|
|
122
|
+
const { gl } = this.renderer;
|
|
123
|
+
|
|
124
|
+
if (this.dirty) {
|
|
125
|
+
if (this._framebuffer) {
|
|
126
|
+
gl.deleteFramebuffer(this._framebuffer);
|
|
127
|
+
}
|
|
128
|
+
this._framebuffer = gl.createFramebuffer();
|
|
129
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer);
|
|
130
|
+
|
|
131
|
+
let depthBufferPresent = false;
|
|
132
|
+
for (const attachment in this.attachments) {
|
|
133
|
+
const textureRenderer = this.attachments[attachment];
|
|
134
|
+
const textureApi = textureRenderer.getApiObject();
|
|
135
|
+
const attachmentPoint = getAttachmentPoint(gl,attachment);
|
|
136
|
+
const textureTarget = getTextureTarget(gl,textureRenderer.texture);
|
|
137
|
+
const level = 0;
|
|
138
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, textureTarget, textureApi, level);
|
|
139
|
+
depthBufferPresent = depthBufferPresent || Number(attachment) === TextureRenderTargetAttachment.DEPTH_ATTACHMENT;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!depthBufferPresent) {
|
|
143
|
+
this._depthBuffer = gl.createRenderbuffer();
|
|
144
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthBuffer);
|
|
145
|
+
|
|
146
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.size.width, this.size.height);
|
|
147
|
+
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthBuffer);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.setUpdated(true);
|
|
151
|
+
|
|
152
|
+
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
|
|
153
|
+
throw new Error("Error initializing render buffer: the framebuffer is not complete");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer);
|
|
158
|
+
|
|
159
|
+
this._screenViewport = this.renderer.state.viewport;
|
|
160
|
+
this.renderer.state.viewport = this.size;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private endUpdateTexture(): void {
|
|
164
|
+
const { gl } = this.renderer;
|
|
165
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
166
|
+
this.renderer.state.viewport = this._screenViewport;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private beginUpdateCubemap(face: CubeMapFace): void {
|
|
170
|
+
const { gl } = this.renderer;
|
|
171
|
+
const textureRenderer = this.attachments[0];
|
|
172
|
+
const textureApi = textureRenderer?.getApiObject();
|
|
173
|
+
const texture = textureRenderer?.texture;
|
|
174
|
+
|
|
175
|
+
if (this.dirty) {
|
|
176
|
+
// Cubemap render only supports ONE texture target
|
|
177
|
+
// to COLOR_ATTACHMENT_0, check this and throw an exception
|
|
178
|
+
// if there are more attachments
|
|
179
|
+
if (Object.keys(this.attachments).length !== 1) {
|
|
180
|
+
throw new Error(`Unexpected number of texture attachments rendering cube map. The cube map renderer supports only one color attachment.`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
this.destroy();
|
|
184
|
+
this._framebuffers = [];
|
|
185
|
+
this._depthBuffers = [];
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
const { width, height } = texture.size;
|
|
189
|
+
for (let i = 0; i < 6; ++i) {
|
|
190
|
+
const fb = gl.createFramebuffer();
|
|
191
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
192
|
+
this._framebuffers.push(fb);
|
|
193
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, textureApi, 0);
|
|
194
|
+
|
|
195
|
+
const rb = gl.createRenderbuffer();
|
|
196
|
+
this._depthBuffers.push(rb);
|
|
197
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
|
|
198
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
|
|
199
|
+
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
|
|
200
|
+
|
|
201
|
+
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
|
|
202
|
+
const statusCode = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
203
|
+
throw new Error(`Cubemap frame buffer not complete in cube side #${i}: ${glEnumToString(gl, statusCode)}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
this.setUpdated(true);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// bind face
|
|
211
|
+
// CubeMapFace.POSITIVE_X === 1, see CubeMapFace definition at render/RenderBuffer.js
|
|
212
|
+
const faceIndex = face - 1;
|
|
213
|
+
if (!this._framebuffers || faceIndex < 0 || faceIndex >= this._framebuffers.length) {
|
|
214
|
+
throw new Error(`RenderBuffer.beginUpdateCubemap(): invalid cube map face index ${faceIndex}`);
|
|
215
|
+
}
|
|
216
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffers[faceIndex]);
|
|
217
|
+
|
|
218
|
+
this._screenViewport = this.renderer.state.viewport;
|
|
219
|
+
this.renderer.state.viewport = texture.size;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private endUpdateCubemap(): void {
|
|
223
|
+
const { gl } = this.renderer;
|
|
224
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
225
|
+
this.renderer.state.viewport = this._screenViewport;
|
|
226
|
+
}
|
|
227
|
+
}
|