@xeokit/xeokit-sdk 2.6.85-renderers-refactor-v2 → 2.6.86
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/xeokit-sdk.cjs.js +44618 -13007
- package/dist/xeokit-sdk.es.js +44617 -13008
- package/dist/xeokit-sdk.es5.js +3488 -1387
- package/dist/xeokit-sdk.min.cjs.js +8 -8
- package/dist/xeokit-sdk.min.es.js +8 -8
- package/dist/xeokit-sdk.min.es5.js +7 -7
- package/package.json +1 -1
- package/src/plugins/lib/html/MenuEvent.js +2 -2
- package/src/viewer/Viewer.js +103 -55
- package/src/viewer/scene/canvas/Canvas.js +43 -3
- package/src/viewer/scene/geometry/ReadableGeometry.js +25 -0
- package/src/viewer/scene/lights/CubeTexture.js +13 -0
- package/src/viewer/scene/lights/DirLight.js +1 -2
- package/src/viewer/scene/lights/PointLight.js +1 -2
- package/src/viewer/scene/materials/Texture.js +9 -0
- package/src/viewer/scene/math/rtcCoords.js +38 -1
- package/src/viewer/scene/mesh/Mesh.js +212 -454
- package/src/viewer/scene/mesh/draw/DrawRenderer.js +998 -0
- package/src/viewer/scene/mesh/draw/DrawShaderSource.js +1504 -305
- package/src/viewer/scene/mesh/emphasis/EmphasisEdgesRenderer.js +259 -0
- package/src/viewer/scene/mesh/emphasis/EmphasisEdgesShaderSource.js +160 -0
- package/src/viewer/scene/mesh/emphasis/EmphasisFillRenderer.js +286 -0
- package/src/viewer/scene/mesh/emphasis/EmphasisFillShaderSource.js +263 -0
- package/src/viewer/scene/mesh/occlusion/OcclusionRenderer.js +221 -0
- package/src/viewer/scene/mesh/occlusion/OcclusionShaderSource.js +158 -9
- package/src/viewer/scene/mesh/pick/PickMeshRenderer.js +223 -0
- package/src/viewer/scene/mesh/pick/PickMeshShaderSource.js +151 -21
- package/src/viewer/scene/mesh/pick/PickTriangleRenderer.js +200 -0
- package/src/viewer/scene/mesh/pick/PickTriangleShaderSource.js +124 -12
- package/src/viewer/scene/mesh/shadow/ShadowRenderer.js +214 -0
- package/src/viewer/scene/mesh/shadow/ShadowShaderSource.js +97 -22
- package/src/viewer/scene/model/RENDER_PASSES.js +34 -0
- package/src/viewer/scene/model/SceneModel.js +861 -245
- package/src/viewer/scene/model/SceneModelEntity.js +4 -4
- package/src/viewer/scene/model/SceneModelMesh.js +3 -3
- package/src/viewer/scene/model/dtx/BindableDataTexture.js +31 -0
- package/src/viewer/scene/model/dtx/lines/DTXLinesBuffer.js +27 -0
- package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +897 -0
- package/src/viewer/scene/model/dtx/lines/DTXLinesState.js +46 -0
- package/src/viewer/scene/model/dtx/lines/DTXLinesTextureFactory.js +411 -0
- package/src/viewer/scene/model/dtx/lines/dataTextureRamStats.js +49 -0
- package/src/viewer/scene/model/dtx/lines/rebucketPositions.js +208 -0
- package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesColorRenderer.js +389 -0
- package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesRenderers.js +65 -0
- package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1399 -0
- package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesBuffer.js +46 -0
- package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesState.js +250 -0
- package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesTextureFactory.js +518 -0
- package/src/viewer/scene/model/dtx/triangles/lib/dataTextureRamStats.js +54 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +639 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesDepthRenderer.js +464 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesColorRenderer.js +423 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesRenderer.js +431 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesNormalsRenderer.js +345 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesOcclusionRenderer.js +436 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickDepthRenderer.js +466 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickMeshRenderer.js +437 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsFlatRenderer.js +460 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsRenderer.js +437 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesRenderers.js +307 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSilhouetteRenderer.js +472 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +474 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +435 -0
- package/src/viewer/scene/model/vbo/ScratchMemory.js +63 -0
- package/src/viewer/scene/model/vbo/VBORenderer.js +664 -0
- package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +704 -0
- package/src/viewer/scene/model/vbo/batching/lines/lib/VBOBatchingLinesBuffer.js +19 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLineSnapInitRenderer.js +318 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesColorRenderer.js +114 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesRenderers.js +99 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSilhouetteRenderer.js +124 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapInitRenderer.js +313 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +311 -0
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOSceneModelLineBatchingRenderer.js +24 -0
- package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +688 -0
- package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsRenderer.js +24 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsColorRenderer.js +168 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsOcclusionRenderer.js +136 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickDepthRenderer.js +156 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickMeshRenderer.js +148 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsRenderers.js +144 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsShadowRenderer.js +107 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSilhouetteRenderer.js +146 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapInitRenderer.js +315 -0
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapRenderer.js +305 -0
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js +24 -0
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +1346 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesColorRenderer.js +131 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesEmphasisRenderer.js +135 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesRenderer.js +12 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +403 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +35 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +252 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +294 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesDepthRenderer.js +115 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +246 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesNormalsRenderer.js +139 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesOcclusionRenderer.js +125 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPBRRenderer.js +561 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickDepthRenderer.js +144 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickMeshRenderer.js +130 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +121 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsRenderer.js +131 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesShadowRenderer.js +107 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSilhouetteRenderer.js +144 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapInitRenderer.js +313 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +312 -0
- package/src/viewer/scene/model/vbo/float16.js +760 -0
- package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +711 -0
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesColorRenderer.js +148 -0
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderer.js +26 -0
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderers.js +139 -0
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSilhouetteRenderer.js +127 -0
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapInitRenderer.js +308 -0
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +299 -0
- package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +733 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsColorRenderer.js +174 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsDepthRenderer.js +156 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsOcclusionRenderer.js +149 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickDepthRenderer.js +170 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickMeshRenderer.js +152 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderer.js +26 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderers.js +174 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsShadowRenderer.js +119 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSilhouetteRenderer.js +154 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapInitRenderer.js +307 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapRenderer.js +293 -0
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingTrianglesRenderer.js +150 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +1289 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesColorRenderer.js +135 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesEmphasisRenderer.js +137 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesRenderer.js +12 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +403 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +267 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +299 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesDepthRenderer.js +126 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +255 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatNormalsRenderer.js +130 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +32 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesNormalsRenderer.js +138 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesOcclusionRenderer.js +128 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPBRRenderer.js +561 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickDepthRenderer.js +149 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickMeshRenderer.js +136 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +130 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsRenderer.js +145 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesShadowRenderer.js +113 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSilhouetteRenderer.js +148 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapInitRenderer.js +319 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +310 -0
- package/src/viewer/scene/scene/Scene.js +38 -21
- package/src/viewer/scene/webgl/ArrayBuf.js +20 -5
- package/src/viewer/scene/webgl/Attribute.js +23 -0
- package/src/viewer/scene/webgl/FrameContext.js +86 -14
- package/src/viewer/scene/webgl/Program.js +181 -0
- package/src/viewer/scene/webgl/RenderBuffer.js +262 -62
- package/src/viewer/scene/webgl/RenderBufferManager.js +34 -0
- package/src/viewer/scene/webgl/Renderer.js +843 -880
- package/src/viewer/scene/webgl/Sampler.js +18 -0
- package/src/viewer/scene/webgl/Shader.js +49 -0
- package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +132 -60
- package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +328 -167
- package/src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js +324 -0
- package/src/viewer/scene/webgl/sao/SAOOcclusionRenderer.js +384 -0
- package/src/viewer/utils/os.js +9 -0
- package/src/viewer/scene/mesh/draw/LambertShaderSource.js +0 -35
- package/src/viewer/scene/mesh/emphasis/EmphasisShaderSource.js +0 -34
- package/src/viewer/scene/model/layer/DTXLayer.js +0 -940
- package/src/viewer/scene/model/layer/Layer.js +0 -786
- package/src/viewer/scene/model/layer/VBOLayer.js +0 -1019
- package/src/viewer/scene/model/layer/programs/ColorProgram.js +0 -35
- package/src/viewer/scene/model/layer/programs/ColorTextureProgram.js +0 -46
- package/src/viewer/scene/model/layer/programs/DepthProgram.js +0 -11
- package/src/viewer/scene/model/layer/programs/EdgesProgram.js +0 -12
- package/src/viewer/scene/model/layer/programs/FlatColorProgram.js +0 -24
- package/src/viewer/scene/model/layer/programs/OcclusionProgram.js +0 -12
- package/src/viewer/scene/model/layer/programs/PBRProgram.js +0 -180
- package/src/viewer/scene/model/layer/programs/PickDepthProgram.js +0 -30
- package/src/viewer/scene/model/layer/programs/PickMeshProgram.js +0 -12
- package/src/viewer/scene/model/layer/programs/PickNormalsProgram.js +0 -18
- package/src/viewer/scene/model/layer/programs/ShadowProgram.js +0 -23
- package/src/viewer/scene/model/layer/programs/SilhouetteProgram.js +0 -15
- package/src/viewer/scene/model/layer/programs/SnapProgram.js +0 -28
- package/src/viewer/scene/webgl/WebGLRenderer.js +0 -612
|
@@ -5,27 +5,14 @@ import {WEBGL_INFO} from '../webglInfo.js';
|
|
|
5
5
|
import {Map} from "../utils/Map.js";
|
|
6
6
|
import {PickResult} from "./PickResult.js";
|
|
7
7
|
import {OcclusionTester} from "./occlusion/OcclusionTester.js";
|
|
8
|
+
import {SAOOcclusionRenderer} from "./sao/SAOOcclusionRenderer.js";
|
|
8
9
|
import {createRTCViewMat} from "../math/rtcCoords.js";
|
|
9
|
-
import {
|
|
10
|
+
import {SAODepthLimitedBlurRenderer} from "./sao/SAODepthLimitedBlurRenderer.js";
|
|
11
|
+
import {RenderBufferManager} from "./RenderBufferManager.js";
|
|
10
12
|
import {getExtension} from "./getExtension.js";
|
|
11
|
-
import {createProgramVariablesState} from "./WebGLRenderer.js";
|
|
12
|
-
import {ArrayBuf} from "./ArrayBuf.js";
|
|
13
|
-
|
|
14
|
-
const OCCLUSION_TEST_MODE = false;
|
|
15
13
|
|
|
16
14
|
const vec3_0 = math.vec3([0,0,0]);
|
|
17
15
|
|
|
18
|
-
const iota = (n) => { const ret = [ ]; for (let i = 0; i < n; ++i) ret.push(i); return ret; };
|
|
19
|
-
|
|
20
|
-
const bitShiftScreenZ = math.vec4([1.0 / (256.0 * 256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0]);
|
|
21
|
-
|
|
22
|
-
const pixelToInt = pix => pix[0] + (pix[1] << 8) + (pix[2] << 16) + (pix[3] << 24);
|
|
23
|
-
|
|
24
|
-
const toWorldNormal = (n) => math.normalizeVec3(math.divVec3Scalar(n, math.MAX_INT, math.vec3()));
|
|
25
|
-
const toWorldPos = (p, origin, scale) => math.vec3([ p[0] * scale[0] + origin[0],
|
|
26
|
-
p[1] * scale[1] + origin[1],
|
|
27
|
-
p[2] * scale[2] + origin[2] ]);
|
|
28
|
-
|
|
29
16
|
/**
|
|
30
17
|
* @private
|
|
31
18
|
*/
|
|
@@ -33,7 +20,7 @@ const Renderer = function (scene, options) {
|
|
|
33
20
|
|
|
34
21
|
options = options || {};
|
|
35
22
|
|
|
36
|
-
const frameCtx = new FrameContext();
|
|
23
|
+
const frameCtx = new FrameContext(scene);
|
|
37
24
|
const canvas = scene.canvas.canvas;
|
|
38
25
|
/**
|
|
39
26
|
* @type {WebGL2RenderingContext}
|
|
@@ -62,344 +49,15 @@ const Renderer = function (scene, options) {
|
|
|
62
49
|
let pbrEnabled = true;
|
|
63
50
|
let colorTextureEnabled = true;
|
|
64
51
|
|
|
65
|
-
const renderBufferManager = (
|
|
66
|
-
const renderBuffersBasic = {};
|
|
67
|
-
const renderBuffersScaled = {};
|
|
68
|
-
return {
|
|
69
|
-
getRenderBuffer: (id, colorFormats, hasDepthTexture) => {
|
|
70
|
-
const renderBuffers = (scene.canvas.resolutionScale === 1.0) ? renderBuffersBasic : renderBuffersScaled;
|
|
71
|
-
if (! renderBuffers[id]) {
|
|
72
|
-
renderBuffers[id] = new RenderBuffer(gl, colorFormats, hasDepthTexture);
|
|
73
|
-
}
|
|
74
|
-
return renderBuffers[id];
|
|
75
|
-
},
|
|
76
|
-
destroy: () => {
|
|
77
|
-
Object.values(renderBuffersBasic ).forEach(buf => buf.destroy());
|
|
78
|
-
Object.values(renderBuffersScaled).forEach(buf => buf.destroy());
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
})();
|
|
82
|
-
|
|
83
|
-
const SAOProgram = (gl, name, programVariablesState, createOutColorDefinition) => {
|
|
84
|
-
const programVariables = programVariablesState.programVariables;
|
|
85
|
-
|
|
86
|
-
const uViewportInv = programVariables.createUniform("vec2", "uViewportInv");
|
|
87
|
-
const uCameraNear = programVariables.createUniform("float", "uCameraNear");
|
|
88
|
-
const uCameraFar = programVariables.createUniform("float", "uCameraFar");
|
|
89
|
-
const uDepthTexture = programVariables.createUniform("sampler2D", "uDepthTexture");
|
|
90
|
-
|
|
91
|
-
const uv = programVariables.createAttribute("vec2", "uv");
|
|
92
|
-
const vUV = programVariables.createVarying("vec2", "vUV", () => uv);
|
|
93
|
-
const outColor = programVariables.createOutput("vec4", "outColor");
|
|
94
|
-
|
|
95
|
-
const getOutColor = programVariables.createFragmentDefinition(
|
|
96
|
-
"getOutColor",
|
|
97
|
-
(name, src) => {
|
|
98
|
-
const getDepth = "getDepth";
|
|
99
|
-
src.push(`
|
|
100
|
-
float ${getDepth}(const in vec2 uv) {
|
|
101
|
-
return texture(${uDepthTexture}, uv).r;
|
|
102
|
-
}
|
|
103
|
-
`);
|
|
104
|
-
src.push(createOutColorDefinition(name, vUV, uViewportInv, uCameraNear, uCameraFar, getDepth));
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const [program, errors] = programVariablesState.buildProgram(
|
|
108
|
-
gl,
|
|
109
|
-
name,
|
|
110
|
-
{
|
|
111
|
-
clipPos: `vec4(2.0 * ${uv} - 1.0, 0.0, 1.0)`,
|
|
112
|
-
appendFragmentOutputs: (src) => src.push(`${outColor} = ${getOutColor}();`)
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
if (errors) {
|
|
116
|
-
console.error(errors.join("\n"));
|
|
117
|
-
throw errors;
|
|
118
|
-
} else {
|
|
119
|
-
const uvs = new Float32Array([1,1, 0,1, 0,0, 1,0]);
|
|
120
|
-
const uvBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, uvs, uvs.length, 2, gl.STATIC_DRAW);
|
|
121
|
-
|
|
122
|
-
// Mitigation: if Uint8Array is used, the geometry is corrupted on OSX when using Chrome with data-textures
|
|
123
|
-
const indices = new Uint32Array([0, 1, 2, 0, 2, 3]);
|
|
124
|
-
const indicesBuf = new ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, indices.length, 1, gl.STATIC_DRAW);
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
destroy: program.destroy,
|
|
128
|
-
bind: (viewportSize, project, depthTexture) => {
|
|
129
|
-
program.bind();
|
|
130
|
-
uViewportInv.setInputValue([1 / viewportSize[0], 1 / viewportSize[1]]);
|
|
131
|
-
uCameraNear.setInputValue(project.near);
|
|
132
|
-
uCameraFar.setInputValue(project.far);
|
|
133
|
-
uDepthTexture.setInputValue(depthTexture);
|
|
134
|
-
uv.setInputValue(uvBuf);
|
|
135
|
-
},
|
|
136
|
-
draw: () => {
|
|
137
|
-
indicesBuf.bind();
|
|
138
|
-
gl.drawElements(gl.TRIANGLES, indicesBuf.numItems, indicesBuf.itemType, 0);
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
// SAO implementation inspired from previous SAO work in THREE.js by ludobaka / ludobaka.github.io and bhouston
|
|
145
|
-
const saoOcclusionRenderer = (function() {
|
|
146
|
-
let currentRenrerer = null;
|
|
147
|
-
let curNumSamples = null;
|
|
148
|
-
return {
|
|
149
|
-
destroy: () => currentRenrerer && currentRenrerer.destroy(),
|
|
150
|
-
render: (viewportSize, project, sao, depthTexture) => {
|
|
151
|
-
const numSamples = Math.floor(sao.numSamples);
|
|
152
|
-
if (curNumSamples !== numSamples) {
|
|
153
|
-
currentRenrerer && currentRenrerer.destroy();
|
|
154
|
-
|
|
155
|
-
const programVariablesState = createProgramVariablesState();
|
|
156
|
-
|
|
157
|
-
const programVariables = programVariablesState.programVariables;
|
|
158
|
-
|
|
159
|
-
const uProjectMatrix = programVariables.createUniform("mat4", "uProjectMatrix");
|
|
160
|
-
const uInvProjMatrix = programVariables.createUniform("mat4", "uInvProjMatrix");
|
|
161
|
-
const uPerspective = programVariables.createUniform("bool", "uPerspective");
|
|
162
|
-
const uScale = programVariables.createUniform("float", "uScale");
|
|
163
|
-
const uIntensity = programVariables.createUniform("float", "uIntensity");
|
|
164
|
-
const uBias = programVariables.createUniform("float", "uBias");
|
|
165
|
-
const uKernelRadius = programVariables.createUniform("float", "uKernelRadius");
|
|
166
|
-
const uMinResolution = programVariables.createUniform("float", "uMinResolution");
|
|
167
|
-
const uRandomSeed = programVariables.createUniform("float", "uRandomSeed");
|
|
168
|
-
|
|
169
|
-
const program = SAOProgram(
|
|
170
|
-
gl,
|
|
171
|
-
"SAOOcclusionRenderer",
|
|
172
|
-
programVariablesState,
|
|
173
|
-
(name, vUV, uViewportInv, uCameraNear, uCameraFar, getDepth) => {
|
|
174
|
-
return `
|
|
175
|
-
#define EPSILON 1e-6
|
|
176
|
-
#define PI 3.14159265359
|
|
177
|
-
#define PI2 6.28318530718
|
|
178
|
-
#define NUM_SAMPLES ${numSamples}
|
|
179
|
-
#define NUM_RINGS 4
|
|
180
|
-
|
|
181
|
-
const vec3 packFactors = vec3(256. * 256. * 256., 256. * 256., 256.);
|
|
182
|
-
|
|
183
|
-
vec4 packFloatToRGBA(const in float v) {
|
|
184
|
-
vec4 r = vec4(fract(v * packFactors), v);
|
|
185
|
-
r.yzw -= r.xyz / 256.;
|
|
186
|
-
return r * 256. / 255.;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
highp float rand(const in vec2 uv) {
|
|
190
|
-
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
|
|
191
|
-
return fract(sin(mod(dot(uv, vec2(a, b)), PI)) * c);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
vec3 getViewPos(const in vec2 screenPos, const in float depth) {
|
|
195
|
-
float near = ${uCameraNear};
|
|
196
|
-
float far = ${uCameraFar};
|
|
197
|
-
float viewZ = (${uPerspective}
|
|
198
|
-
? ((near * far) / ((far - near) * depth - far))
|
|
199
|
-
: (depth * (near - far) - near));
|
|
200
|
-
float clipW = ${uProjectMatrix}[2][3] * viewZ + ${uProjectMatrix}[3][3];
|
|
201
|
-
return (${uInvProjMatrix} * (clipW * vec4((vec3(screenPos, depth) - 0.5) * 2.0, 1.0))).xyz;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
vec4 ${name}() {
|
|
205
|
-
float centerDepth = ${getDepth}(${vUV});
|
|
206
|
-
if (centerDepth >= (1.0 - EPSILON)) {
|
|
207
|
-
discard;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
vec3 centerViewPosition = getViewPos(${vUV}, centerDepth);
|
|
211
|
-
float scaleDividedByCameraFar = ${uScale} / ${uCameraFar};
|
|
212
|
-
float minResolutionMultipliedByCameraFar = ${uMinResolution} * ${uCameraFar};
|
|
213
|
-
vec3 centerViewNormal = normalize(cross(dFdx(centerViewPosition), dFdy(centerViewPosition)));
|
|
214
|
-
|
|
215
|
-
vec2 radiusStep = ${uKernelRadius} * ${uViewportInv} / float(NUM_SAMPLES);
|
|
216
|
-
vec2 radius = radiusStep;
|
|
217
|
-
const float angleStep = PI2 * float(NUM_RINGS) / float(NUM_SAMPLES);
|
|
218
|
-
float angle = PI2 * rand(${vUV} + ${uRandomSeed});
|
|
219
|
-
|
|
220
|
-
float occlusionSum = 0.0;
|
|
221
|
-
float weightSum = 0.0;
|
|
222
|
-
|
|
223
|
-
for (int i = 0; i < NUM_SAMPLES; i++) {
|
|
224
|
-
vec2 sampleUv = ${vUV} + vec2(cos(angle), sin(angle)) * radius;
|
|
225
|
-
radius += radiusStep;
|
|
226
|
-
angle += angleStep;
|
|
227
|
-
|
|
228
|
-
float sampleDepth = ${getDepth}(sampleUv);
|
|
229
|
-
if (sampleDepth >= (1.0 - EPSILON)) {
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
vec3 sampleViewPosition = getViewPos(sampleUv, sampleDepth);
|
|
234
|
-
vec3 viewDelta = sampleViewPosition - centerViewPosition;
|
|
235
|
-
float scaledScreenDistance = scaleDividedByCameraFar * length(viewDelta);
|
|
236
|
-
occlusionSum += max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - ${uBias}) / (1.0 + scaledScreenDistance * scaledScreenDistance );
|
|
237
|
-
weightSum += 1.0;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return packFloatToRGBA(1.0 - occlusionSum * ${uIntensity} / weightSum);
|
|
241
|
-
}`;
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
currentRenrerer = {
|
|
245
|
-
destroy: program.destroy,
|
|
246
|
-
render: (viewportSize, project, sao, depthTexture) => {
|
|
247
|
-
program.bind(viewportSize, project, depthTexture);
|
|
248
|
-
|
|
249
|
-
uProjectMatrix.setInputValue(project.matrix);
|
|
250
|
-
uInvProjMatrix.setInputValue(project.inverseMatrix);
|
|
251
|
-
uPerspective.setInputValue(project.type === "Perspective");
|
|
252
|
-
uScale.setInputValue(sao.scale * project.far / 5);
|
|
253
|
-
uIntensity.setInputValue(sao.intensity);
|
|
254
|
-
uBias.setInputValue(sao.bias);
|
|
255
|
-
uKernelRadius.setInputValue(sao.kernelRadius);
|
|
256
|
-
uMinResolution.setInputValue(sao.minResolution);
|
|
257
|
-
uRandomSeed.setInputValue(Math.random());
|
|
258
|
-
|
|
259
|
-
program.draw();
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
curNumSamples = numSamples;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
currentRenrerer.render(viewportSize, project, sao, depthTexture);
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
})();
|
|
270
|
-
|
|
271
|
-
const saoDepthLimitedBlurRenderer = (function() {
|
|
272
|
-
const blurStdDev = 4;
|
|
273
|
-
const blurDepthCutoff = 0.01;
|
|
274
|
-
const KERNEL_RADIUS = 16;
|
|
275
|
-
|
|
276
|
-
const createSampleOffsets = (uvIncrement) => {
|
|
277
|
-
const offsets = [];
|
|
278
|
-
for (let i = 0; i <= KERNEL_RADIUS + 1; i++) {
|
|
279
|
-
offsets.push(uvIncrement[0] * i);
|
|
280
|
-
offsets.push(uvIncrement[1] * i);
|
|
281
|
-
}
|
|
282
|
-
return new Float32Array(offsets);
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const sampleOffsetsVer = createSampleOffsets([0, 1]);
|
|
286
|
-
const sampleOffsetsHor = createSampleOffsets([1, 0]);
|
|
287
|
-
|
|
288
|
-
const gaussian = (i, stdDev) => Math.exp(-(i * i) / (2.0 * (stdDev * stdDev))) / (Math.sqrt(2.0 * Math.PI) * stdDev);
|
|
289
|
-
const sampleWeights = new Float32Array(iota(KERNEL_RADIUS + 1).map(i => gaussian(i, blurStdDev))); // TODO: Optimize
|
|
290
|
-
|
|
291
|
-
const programVariablesState = createProgramVariablesState();
|
|
52
|
+
const renderBufferManager = new RenderBufferManager(scene);
|
|
292
53
|
|
|
293
|
-
|
|
54
|
+
let snapshotBound = false;
|
|
294
55
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const uSampleWeights = programVariables.createUniformArray("float", "uSampleWeights", KERNEL_RADIUS + 1);
|
|
56
|
+
const bindOutputFrameBuffer = null;
|
|
57
|
+
const unbindOutputFrameBuffer = null;
|
|
298
58
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const program = SAOProgram(
|
|
302
|
-
gl,
|
|
303
|
-
"SAODepthLimitedBlurRenderer",
|
|
304
|
-
programVariablesState,
|
|
305
|
-
(name, vUV, uViewportInv, uCameraNear, uCameraFar, getDepth) => {
|
|
306
|
-
return `
|
|
307
|
-
#define EPSILON 1e-6
|
|
308
|
-
|
|
309
|
-
const vec3 packFactors = vec3(256. * 256. * 256., 256. * 256., 256.);
|
|
310
|
-
|
|
311
|
-
vec4 packFloatToRGBA(const in float v) {
|
|
312
|
-
vec4 r = vec4(fract(v * packFactors), v);
|
|
313
|
-
r.yzw -= r.xyz / 256.;
|
|
314
|
-
return r * 256. / 255.;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
float getOcclusion(const in vec2 uv) {
|
|
318
|
-
vec4 v = texture(${uOcclusionTex}, uv);
|
|
319
|
-
return dot(floor(v * 255.0 + 0.5) / 255.0, 255. / 256. / vec4(packFactors, 1.)); // unpackRGBAToFloat
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
float getViewZ(const in float depth) {
|
|
323
|
-
return (${uCameraNear} * ${uCameraFar}) / ((${uCameraFar} - ${uCameraNear}) * depth - ${uCameraFar});
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
vec4 ${name}() {
|
|
327
|
-
float centerDepth = ${getDepth}(${vUV});
|
|
328
|
-
if (centerDepth >= (1.0 - EPSILON)) {
|
|
329
|
-
discard;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
float centerViewZ = getViewZ(centerDepth);
|
|
333
|
-
bool rBreak = false;
|
|
334
|
-
bool lBreak = false;
|
|
335
|
-
|
|
336
|
-
float weightSum = ${uSampleWeights}[0];
|
|
337
|
-
float occlusionSum = getOcclusion(${vUV}) * weightSum;
|
|
338
|
-
|
|
339
|
-
for (int i = 1; i <= ${KERNEL_RADIUS}; i++) {
|
|
340
|
-
float sampleWeight = ${uSampleWeights}[i];
|
|
341
|
-
vec2 sampleUVOffset = ${uSampleOffsets}[i] * ${uViewportInv};
|
|
342
|
-
|
|
343
|
-
if (! rBreak) {
|
|
344
|
-
vec2 rSampleUV = ${vUV} + sampleUVOffset;
|
|
345
|
-
if (abs(centerViewZ - getViewZ(${getDepth}(rSampleUV))) > ${uDepthCutoff}) {
|
|
346
|
-
rBreak = true;
|
|
347
|
-
} else {
|
|
348
|
-
occlusionSum += getOcclusion(rSampleUV) * sampleWeight;
|
|
349
|
-
weightSum += sampleWeight;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (! lBreak) {
|
|
354
|
-
vec2 lSampleUV = ${vUV} - sampleUVOffset;
|
|
355
|
-
if (abs(centerViewZ - getViewZ(${getDepth}(lSampleUV))) > ${uDepthCutoff}) {
|
|
356
|
-
lBreak = true;
|
|
357
|
-
} else {
|
|
358
|
-
occlusionSum += getOcclusion(lSampleUV) * sampleWeight;
|
|
359
|
-
weightSum += sampleWeight;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return packFloatToRGBA(occlusionSum / weightSum);
|
|
365
|
-
}`;
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
return {
|
|
369
|
-
destroy: program.destroy,
|
|
370
|
-
render: (viewportSize, project, direction, depthTexture, occlusionTexture) => {
|
|
371
|
-
program.bind(viewportSize, project, depthTexture);
|
|
372
|
-
|
|
373
|
-
uDepthCutoff.setInputValue(blurDepthCutoff);
|
|
374
|
-
uSampleOffsets.setInputValue((direction === 0) ? sampleOffsetsHor : sampleOffsetsVer);
|
|
375
|
-
uSampleWeights.setInputValue(sampleWeights);
|
|
376
|
-
uOcclusionTex.setInputValue(occlusionTexture);
|
|
377
|
-
|
|
378
|
-
program.draw();
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
})();
|
|
382
|
-
|
|
383
|
-
const getSceneCameraViewParams = (function() {
|
|
384
|
-
let params = null; // scene.camera not defined yet
|
|
385
|
-
return function() {
|
|
386
|
-
if (! params) {
|
|
387
|
-
const camera = scene.camera;
|
|
388
|
-
params = {
|
|
389
|
-
get eye() { return camera.eye; },
|
|
390
|
-
get far() { return camera.project.far; },
|
|
391
|
-
get projMatrix() { return camera.projMatrix; },
|
|
392
|
-
get viewMatrix() { return camera.viewMatrix; },
|
|
393
|
-
get viewNormalMatrix() { return camera.viewNormalMatrix; }
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
return params;
|
|
397
|
-
};
|
|
398
|
-
})();
|
|
399
|
-
|
|
400
|
-
const getNearPlaneHeight = (camera, drawingBufferHeight) => ((camera.projection === "ortho")
|
|
401
|
-
? 1.0
|
|
402
|
-
: (drawingBufferHeight / (2 * Math.tan(0.5 * camera.perspective.fov * Math.PI / 180.0))));
|
|
59
|
+
const saoOcclusionRenderer = new SAOOcclusionRenderer(scene);
|
|
60
|
+
const saoDepthLimitedBlurRenderer = new SAODepthLimitedBlurRenderer(scene);
|
|
403
61
|
|
|
404
62
|
this.scene = scene;
|
|
405
63
|
|
|
@@ -451,6 +109,19 @@ const Renderer = function (scene, options) {
|
|
|
451
109
|
imageDirty = true;
|
|
452
110
|
};
|
|
453
111
|
|
|
112
|
+
this.webglContextLost = function () {
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
this.webglContextRestored = function (gl) {
|
|
116
|
+
|
|
117
|
+
// renderBufferManager.webglContextRestored(gl);
|
|
118
|
+
|
|
119
|
+
saoOcclusionRenderer.init();
|
|
120
|
+
saoDepthLimitedBlurRenderer.init();
|
|
121
|
+
|
|
122
|
+
imageDirty = true;
|
|
123
|
+
};
|
|
124
|
+
|
|
454
125
|
/**
|
|
455
126
|
* Inserts a drawable into this renderer.
|
|
456
127
|
* @private
|
|
@@ -530,7 +201,13 @@ const Renderer = function (scene, options) {
|
|
|
530
201
|
const backgroundColor = scene.canvas.backgroundColorFromAmbientLight ? this.lights.getAmbientColorAndIntensity() : scene.canvas.backgroundColor;
|
|
531
202
|
gl.clearColor(backgroundColor[0], backgroundColor[1], backgroundColor[2], 1.0);
|
|
532
203
|
}
|
|
204
|
+
if (bindOutputFrameBuffer) {
|
|
205
|
+
bindOutputFrameBuffer(params.pass);
|
|
206
|
+
}
|
|
533
207
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
208
|
+
if (unbindOutputFrameBuffer) {
|
|
209
|
+
unbindOutputFrameBuffer(params.pass);
|
|
210
|
+
}
|
|
534
211
|
};
|
|
535
212
|
|
|
536
213
|
/**
|
|
@@ -546,10 +223,14 @@ const Renderer = function (scene, options) {
|
|
|
546
223
|
* Renders inserted drawables.
|
|
547
224
|
* @private
|
|
548
225
|
*/
|
|
549
|
-
this.render = function(
|
|
226
|
+
this.render = function (params) {
|
|
227
|
+
params = params || {};
|
|
228
|
+
if (params.force) {
|
|
229
|
+
imageDirty = true;
|
|
230
|
+
}
|
|
550
231
|
updateDrawlist();
|
|
551
232
|
if (imageDirty) {
|
|
552
|
-
draw(
|
|
233
|
+
draw(params);
|
|
553
234
|
stats.frame.frameCount++;
|
|
554
235
|
imageDirty = false;
|
|
555
236
|
}
|
|
@@ -557,175 +238,243 @@ const Renderer = function (scene, options) {
|
|
|
557
238
|
|
|
558
239
|
function updateDrawlist() { // Prepares state-sorted array of drawables from maps of inserted drawables
|
|
559
240
|
if (drawableListDirty) {
|
|
560
|
-
|
|
561
|
-
const drawableListPreCull = drawableInfo.drawableListPreCull;
|
|
562
|
-
let lenDrawableList = 0;
|
|
563
|
-
Object.values(drawableInfo.drawableMap).forEach(drawable => { drawableListPreCull[lenDrawableList++] = drawable; });
|
|
564
|
-
drawableListPreCull.length = lenDrawableList;
|
|
565
|
-
});
|
|
241
|
+
buildDrawableList();
|
|
566
242
|
drawableListDirty = false;
|
|
567
243
|
stateSortDirty = true;
|
|
568
244
|
}
|
|
569
245
|
if (stateSortDirty) {
|
|
570
|
-
|
|
571
|
-
Object.values(drawableTypeInfo).forEach(drawableInfo => {
|
|
572
|
-
drawableInfo.drawableListPreCull.forEach(drawable => { postSortDrawableList[lenDrawableList++] = drawable; });
|
|
573
|
-
});
|
|
574
|
-
postSortDrawableList.length = lenDrawableList;
|
|
575
|
-
postSortDrawableList.sort((a, b) => a.renderOrder - b.renderOrder);
|
|
246
|
+
sortDrawableList();
|
|
576
247
|
stateSortDirty = false;
|
|
577
248
|
imageDirty = true;
|
|
578
249
|
}
|
|
579
250
|
if (imageDirty) { // Image is usually dirty because the camera moved
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
251
|
+
cullDrawableList();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function buildDrawableList() {
|
|
256
|
+
for (let type in drawableTypeInfo) {
|
|
257
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
258
|
+
const drawableInfo = drawableTypeInfo[type];
|
|
259
|
+
const drawableMap = drawableInfo.drawableMap;
|
|
260
|
+
const drawableListPreCull = drawableInfo.drawableListPreCull;
|
|
261
|
+
let lenDrawableList = 0;
|
|
262
|
+
for (let id in drawableMap) {
|
|
263
|
+
if (drawableMap.hasOwnProperty(id)) {
|
|
264
|
+
drawableListPreCull[lenDrawableList++] = drawableMap[id];
|
|
589
265
|
}
|
|
590
266
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
uiDrawableList.length = lenUiList;
|
|
267
|
+
drawableListPreCull.length = lenDrawableList;
|
|
268
|
+
}
|
|
594
269
|
}
|
|
595
270
|
}
|
|
596
271
|
|
|
597
|
-
function
|
|
272
|
+
function sortDrawableList() {
|
|
273
|
+
let lenDrawableList = 0;
|
|
274
|
+
for (let type in drawableTypeInfo) {
|
|
275
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
276
|
+
const drawableInfo = drawableTypeInfo[type];
|
|
277
|
+
const drawableListPreCull = drawableInfo.drawableListPreCull;
|
|
278
|
+
for (let i = 0, len = drawableListPreCull.length; i < len; i++) {
|
|
279
|
+
const drawable = drawableListPreCull[i];
|
|
280
|
+
postSortDrawableList[lenDrawableList++] = drawable;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
postSortDrawableList.length = lenDrawableList;
|
|
285
|
+
postSortDrawableList.sort((a, b) => {
|
|
286
|
+
return a.renderOrder - b.renderOrder;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function cullDrawableList() {
|
|
291
|
+
let lenDrawableList = 0;
|
|
292
|
+
let lenUiList = 0;
|
|
293
|
+
for (let i = 0, len = postSortDrawableList.length; i < len; i++) {
|
|
294
|
+
const drawable = postSortDrawableList[i];
|
|
295
|
+
drawable.rebuildRenderFlags();
|
|
296
|
+
if (!drawable.renderFlags.culled) {
|
|
297
|
+
if (drawable.isUI) {
|
|
298
|
+
uiDrawableList[lenUiList++] = drawable;
|
|
299
|
+
} else {
|
|
300
|
+
postCullDrawableList[lenDrawableList++] = drawable;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
postCullDrawableList.length = lenDrawableList;
|
|
305
|
+
uiDrawableList.length = lenUiList;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function draw(params) {
|
|
598
309
|
|
|
599
310
|
const sao = scene.sao;
|
|
600
|
-
const occlusionTexture = saoEnabled && sao.possible && (sao.numSamples >= 1) && drawSAOBuffers(pass);
|
|
601
|
-
|
|
602
|
-
scene._lightsState.lights.forEach(light => {
|
|
603
|
-
|
|
604
|
-
if (light.castsShadow) {
|
|
605
|
-
const shadowRenderBuf = light.getShadowRenderBuf();
|
|
606
|
-
shadowRenderBuf.bind();
|
|
607
|
-
|
|
608
|
-
frameCtx.reset();
|
|
609
|
-
frameCtx.backfaces = true;
|
|
610
|
-
frameCtx.frontface = true;
|
|
611
|
-
frameCtx.viewParams.viewMatrix = light.getShadowViewMatrix();
|
|
612
|
-
frameCtx.viewParams.projMatrix = light.getShadowProjMatrix();
|
|
613
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(scene.camera, gl.drawingBufferHeight);
|
|
614
|
-
|
|
615
|
-
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
616
|
-
|
|
617
|
-
gl.clearColor(0, 0, 0, 1);
|
|
618
|
-
gl.enable(gl.DEPTH_TEST);
|
|
619
|
-
gl.disable(gl.BLEND);
|
|
620
|
-
|
|
621
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
622
|
-
|
|
623
|
-
Object.values(drawableTypeInfo).forEach(
|
|
624
|
-
drawableInfo => {
|
|
625
|
-
drawableInfo.drawableList.forEach(
|
|
626
|
-
drawable => {
|
|
627
|
-
if ((drawable.visible !== false) && drawable.castsShadow && drawable.drawShadow) {
|
|
628
|
-
if (drawable.renderFlags.colorOpaque) { // Transparent objects don't cast shadows (yet)
|
|
629
|
-
drawable.drawShadow(frameCtx);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
});
|
|
633
|
-
});
|
|
634
311
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}
|
|
312
|
+
if (saoEnabled && sao.possible) {
|
|
313
|
+
drawSAOBuffers(params);
|
|
314
|
+
}
|
|
638
315
|
|
|
639
|
-
|
|
640
|
-
// for (let ii = 0; ii < numVertexAttribs; ii++) {
|
|
641
|
-
// gl.disableVertexAttribArray(ii);
|
|
642
|
-
// }
|
|
643
|
-
//
|
|
644
|
-
shadowsDirty = false;
|
|
316
|
+
drawShadowMaps();
|
|
645
317
|
|
|
646
|
-
drawColor(
|
|
318
|
+
drawColor(params);
|
|
647
319
|
}
|
|
648
320
|
|
|
649
|
-
function drawSAOBuffers(
|
|
321
|
+
function drawSAOBuffers(params) {
|
|
650
322
|
|
|
651
323
|
const sao = scene.sao;
|
|
652
324
|
|
|
653
|
-
const size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
|
|
654
|
-
|
|
655
325
|
// Render depth buffer
|
|
656
|
-
|
|
657
|
-
saoDepthRenderBuffer.
|
|
326
|
+
|
|
327
|
+
const saoDepthRenderBuffer = renderBufferManager.getRenderBuffer("saoDepth", {
|
|
328
|
+
depthTexture: true
|
|
329
|
+
});
|
|
330
|
+
|
|
658
331
|
saoDepthRenderBuffer.bind();
|
|
659
|
-
|
|
332
|
+
saoDepthRenderBuffer.clear();
|
|
333
|
+
drawDepth(params);
|
|
334
|
+
saoDepthRenderBuffer.unbind();
|
|
335
|
+
|
|
336
|
+
// Render occlusion buffer
|
|
337
|
+
|
|
338
|
+
const occlusionRenderBuffer1 = renderBufferManager.getRenderBuffer("saoOcclusion");
|
|
339
|
+
|
|
340
|
+
occlusionRenderBuffer1.bind();
|
|
341
|
+
occlusionRenderBuffer1.clear();
|
|
342
|
+
saoOcclusionRenderer.render(saoDepthRenderBuffer);
|
|
343
|
+
occlusionRenderBuffer1.unbind();
|
|
344
|
+
|
|
345
|
+
if (sao.blur) {
|
|
346
|
+
|
|
347
|
+
// Horizontally blur occlusion buffer 1 into occlusion buffer 2
|
|
348
|
+
|
|
349
|
+
const occlusionRenderBuffer2 = renderBufferManager.getRenderBuffer("saoOcclusion2");
|
|
350
|
+
|
|
351
|
+
occlusionRenderBuffer2.bind();
|
|
352
|
+
occlusionRenderBuffer2.clear();
|
|
353
|
+
saoDepthLimitedBlurRenderer.render(saoDepthRenderBuffer, occlusionRenderBuffer1, 0);
|
|
354
|
+
occlusionRenderBuffer2.unbind();
|
|
355
|
+
|
|
356
|
+
// Vertically blur occlusion buffer 2 back into occlusion buffer 1
|
|
357
|
+
|
|
358
|
+
occlusionRenderBuffer1.bind();
|
|
359
|
+
occlusionRenderBuffer1.clear();
|
|
360
|
+
saoDepthLimitedBlurRenderer.render(saoDepthRenderBuffer, occlusionRenderBuffer2, 1);
|
|
361
|
+
occlusionRenderBuffer1.unbind();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function drawDepth(params) {
|
|
660
366
|
|
|
661
367
|
frameCtx.reset();
|
|
662
|
-
frameCtx.pass = pass;
|
|
663
|
-
frameCtx.viewParams = getSceneCameraViewParams();
|
|
664
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(scene.camera, gl.drawingBufferHeight);
|
|
368
|
+
frameCtx.pass = params.pass;
|
|
665
369
|
|
|
666
370
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
371
|
+
|
|
667
372
|
gl.clearColor(0, 0, 0, 0);
|
|
668
373
|
gl.enable(gl.DEPTH_TEST);
|
|
669
374
|
gl.frontFace(gl.CCW);
|
|
670
375
|
gl.enable(gl.CULL_FACE);
|
|
671
376
|
gl.depthMask(true);
|
|
672
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
673
377
|
|
|
674
|
-
|
|
675
|
-
|
|
378
|
+
if (params.clear !== false) {
|
|
379
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
380
|
+
}
|
|
381
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
382
|
+
|
|
383
|
+
const drawable = postCullDrawableList[i];
|
|
384
|
+
|
|
385
|
+
if (drawable.culled === true || drawable.visible === false || !drawable.drawDepth || !drawable.saoEnabled) {
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (drawable.renderFlags.colorOpaque) {
|
|
676
390
|
drawable.drawDepth(frameCtx);
|
|
677
391
|
}
|
|
678
|
-
}
|
|
392
|
+
}
|
|
679
393
|
|
|
680
|
-
|
|
394
|
+
// const numVertexAttribs = WEBGL_INFO.MAX_VERTEX_ATTRIBS; // Fixes https://github.com/xeokit/xeokit-sdk/issues/174
|
|
395
|
+
// for (let ii = 0; ii < numVertexAttribs; ii++) {
|
|
396
|
+
// gl.disableVertexAttribArray(ii);
|
|
397
|
+
// }
|
|
681
398
|
|
|
682
|
-
|
|
399
|
+
}
|
|
683
400
|
|
|
684
|
-
|
|
401
|
+
function drawShadowMaps() {
|
|
685
402
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
403
|
+
let lights = scene._lightsState.lights;
|
|
404
|
+
|
|
405
|
+
for (let i = 0, len = lights.length; i < len; i++) {
|
|
406
|
+
const light = lights[i];
|
|
407
|
+
if (!light.castsShadow) {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
drawShadowMap(light);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// const numVertexAttribs = WEBGL_INFO.MAX_VERTEX_ATTRIBS; // Fixes https://github.com/xeokit/xeokit-sdk/issues/174
|
|
414
|
+
// for (let ii = 0; ii < numVertexAttribs; ii++) {
|
|
415
|
+
// gl.disableVertexAttribArray(ii);
|
|
416
|
+
// }
|
|
417
|
+
//
|
|
418
|
+
shadowsDirty = false;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function drawShadowMap(light) {
|
|
422
|
+
|
|
423
|
+
const castsShadow = light.castsShadow;
|
|
424
|
+
|
|
425
|
+
if (!castsShadow) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const shadowRenderBuf = light.getShadowRenderBuf();
|
|
430
|
+
|
|
431
|
+
if (!shadowRenderBuf) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
shadowRenderBuf.bind();
|
|
436
|
+
|
|
437
|
+
frameCtx.reset();
|
|
438
|
+
|
|
439
|
+
frameCtx.backfaces = true;
|
|
440
|
+
frameCtx.frontface = true;
|
|
441
|
+
frameCtx.shadowViewMatrix = light.getShadowViewMatrix();
|
|
442
|
+
frameCtx.shadowProjMatrix = light.getShadowProjMatrix();
|
|
443
|
+
|
|
444
|
+
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
689
445
|
|
|
690
|
-
gl.viewport(0, 0, size[0], size[1]);
|
|
691
446
|
gl.clearColor(0, 0, 0, 1);
|
|
692
|
-
gl.
|
|
447
|
+
gl.enable(gl.DEPTH_TEST);
|
|
693
448
|
gl.disable(gl.BLEND);
|
|
694
|
-
gl.frontFace(gl.CCW);
|
|
695
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
696
449
|
|
|
697
|
-
|
|
450
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
698
451
|
|
|
699
|
-
|
|
452
|
+
for (let type in drawableTypeInfo) {
|
|
700
453
|
|
|
701
|
-
|
|
702
|
-
const occlusionRenderBuffer2 = renderBufferManager.getRenderBuffer("saoOcclusion2");
|
|
703
|
-
occlusionRenderBuffer2.setSize(size);
|
|
454
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
704
455
|
|
|
705
|
-
|
|
706
|
-
|
|
456
|
+
const drawableInfo = drawableTypeInfo[type];
|
|
457
|
+
const drawableList = drawableInfo.drawableList;
|
|
707
458
|
|
|
708
|
-
|
|
709
|
-
gl.clearColor(0, 0, 0, 1);
|
|
710
|
-
gl.enable(gl.DEPTH_TEST);
|
|
711
|
-
gl.disable(gl.BLEND);
|
|
712
|
-
gl.frontFace(gl.CCW);
|
|
713
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
459
|
+
for (let i = 0, len = drawableList.length; i < len; i++) {
|
|
714
460
|
|
|
715
|
-
|
|
716
|
-
saoDepthLimitedBlurRenderer.render(size, project, direction, depthTexture, src.colorTextures[0]);
|
|
461
|
+
const drawable = drawableList[i];
|
|
717
462
|
|
|
718
|
-
|
|
719
|
-
|
|
463
|
+
if (drawable.visible === false || !drawable.castsShadow || !drawable.drawShadow) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
720
466
|
|
|
721
|
-
|
|
722
|
-
|
|
467
|
+
if (drawable.renderFlags.colorOpaque) { // Transparent objects don't cast shadows (yet)
|
|
468
|
+
drawable.drawShadow(frameCtx);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
723
472
|
}
|
|
724
473
|
|
|
725
|
-
|
|
474
|
+
shadowRenderBuf.unbind();
|
|
726
475
|
}
|
|
727
476
|
|
|
728
|
-
function drawColor(
|
|
477
|
+
function drawColor(params) {
|
|
729
478
|
|
|
730
479
|
const normalDrawSAOBin = [];
|
|
731
480
|
const normalEdgesOpaqueBin = [];
|
|
@@ -751,12 +500,10 @@ const Renderer = function (scene, options) {
|
|
|
751
500
|
const ambientColorAndIntensity = scene._lightsState.getAmbientColorAndIntensity();
|
|
752
501
|
|
|
753
502
|
frameCtx.reset();
|
|
754
|
-
frameCtx.pass = pass;
|
|
503
|
+
frameCtx.pass = params.pass;
|
|
755
504
|
frameCtx.withSAO = false;
|
|
756
505
|
frameCtx.pbrEnabled = pbrEnabled && !!scene.pbrEnabled;
|
|
757
506
|
frameCtx.colorTextureEnabled = colorTextureEnabled && !!scene.colorTextureEnabled;
|
|
758
|
-
frameCtx.viewParams = getSceneCameraViewParams();
|
|
759
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(scene.camera, gl.drawingBufferHeight);
|
|
760
507
|
|
|
761
508
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
762
509
|
|
|
@@ -775,9 +522,15 @@ const Renderer = function (scene, options) {
|
|
|
775
522
|
|
|
776
523
|
frameCtx.lineWidth = 1;
|
|
777
524
|
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
|
|
525
|
+
const saoPossible = scene.sao.possible;
|
|
526
|
+
|
|
527
|
+
if (saoEnabled && saoPossible) {
|
|
528
|
+
const occlusionRenderBuffer1 = renderBufferManager.getRenderBuffer("saoOcclusion");
|
|
529
|
+
frameCtx.occlusionTexture = occlusionRenderBuffer1 ? occlusionRenderBuffer1.getTexture() : null;
|
|
530
|
+
} else {
|
|
531
|
+
frameCtx.occlusionTexture = null;
|
|
532
|
+
|
|
533
|
+
}
|
|
781
534
|
|
|
782
535
|
let i;
|
|
783
536
|
let len;
|
|
@@ -785,7 +538,11 @@ const Renderer = function (scene, options) {
|
|
|
785
538
|
|
|
786
539
|
const startTime = Date.now();
|
|
787
540
|
|
|
788
|
-
if (
|
|
541
|
+
if (bindOutputFrameBuffer) {
|
|
542
|
+
bindOutputFrameBuffer(params.pass);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (params.clear !== false) {
|
|
789
546
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
790
547
|
}
|
|
791
548
|
|
|
@@ -825,7 +582,7 @@ const Renderer = function (scene, options) {
|
|
|
825
582
|
const renderFlags = drawable.renderFlags;
|
|
826
583
|
|
|
827
584
|
if (renderFlags.colorOpaque) {
|
|
828
|
-
if (
|
|
585
|
+
if (saoEnabled && saoPossible && drawable.saoEnabled) {
|
|
829
586
|
normalDrawSAOBin[normalDrawSAOBinLen++] = drawable;
|
|
830
587
|
} else {
|
|
831
588
|
drawable.drawColorOpaque(frameCtx);
|
|
@@ -966,7 +723,7 @@ const Renderer = function (scene, options) {
|
|
|
966
723
|
// Transparent color fill
|
|
967
724
|
|
|
968
725
|
if (normalFillTransparentBinLen > 0) {
|
|
969
|
-
const eye = frameCtx.
|
|
726
|
+
const eye = frameCtx.pickOrigin || scene.camera.eye;
|
|
970
727
|
const byDist = normalFillTransparentBin.map(d => ({ drawable: d, distSq: math.distVec3(d.origin || vec3_0, eye) }));
|
|
971
728
|
byDist.sort((a, b) => b.distSq - a.distSq);
|
|
972
729
|
for (i = 0; i < normalFillTransparentBinLen; i++) {
|
|
@@ -1143,29 +900,11 @@ const Renderer = function (scene, options) {
|
|
|
1143
900
|
for (let ii = 0; ii < numVertexAttribs; ii++) {
|
|
1144
901
|
gl.disableVertexAttribArray(ii);
|
|
1145
902
|
}
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
const resetPickFrameCtx = (canvasPos, clipTransformDiv, camera, eye, projMatrix, viewMatrix, frameCtx) => {
|
|
1149
|
-
frameCtx.reset();
|
|
1150
|
-
frameCtx.backfaces = true;
|
|
1151
|
-
frameCtx.frontface = true; // "ccw"
|
|
1152
|
-
|
|
1153
|
-
frameCtx.viewParams.eye = eye;
|
|
1154
|
-
frameCtx.viewParams.projMatrix = projMatrix;
|
|
1155
|
-
frameCtx.viewParams.viewMatrix = viewMatrix;
|
|
1156
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(camera, gl.drawingBufferHeight);
|
|
1157
|
-
|
|
1158
|
-
const resolutionScale = scene.canvas.resolutionScale;
|
|
1159
|
-
frameCtx.pickClipPos = [
|
|
1160
|
-
canvasPos ? ( 2 * canvasPos[0] * resolutionScale / gl.drawingBufferWidth - 1) : 0,
|
|
1161
|
-
canvasPos ? (1 - 2 * canvasPos[1] * resolutionScale / gl.drawingBufferHeight) : 0
|
|
1162
|
-
];
|
|
1163
903
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
};
|
|
904
|
+
if (unbindOutputFrameBuffer) {
|
|
905
|
+
unbindOutputFrameBuffer(params.pass);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
1169
908
|
|
|
1170
909
|
/**
|
|
1171
910
|
* Picks an Entity.
|
|
@@ -1174,18 +913,11 @@ const Renderer = function (scene, options) {
|
|
|
1174
913
|
this.pick = (function () {
|
|
1175
914
|
|
|
1176
915
|
const tempVec3a = math.vec3();
|
|
1177
|
-
const tempVec3b = math.vec3();
|
|
1178
|
-
const tempVec4a = math.vec4();
|
|
1179
|
-
const tempVec4b = math.vec4();
|
|
1180
|
-
const tempVec4c = math.vec4();
|
|
1181
|
-
const tempVec4d = math.vec4();
|
|
1182
|
-
const tempVec4e = math.vec4();
|
|
1183
916
|
const tempMat4a = math.mat4();
|
|
1184
917
|
const tempMat4b = math.mat4();
|
|
1185
|
-
const tempMat4c = math.mat4();
|
|
1186
|
-
const tempMat4d = math.mat4();
|
|
1187
918
|
|
|
1188
|
-
const
|
|
919
|
+
const randomVec3 = math.vec3();
|
|
920
|
+
const up = math.vec3([0, 1, 0]);
|
|
1189
921
|
const _pickResult = new PickResult();
|
|
1190
922
|
|
|
1191
923
|
const nearAndFar = math.vec2();
|
|
@@ -1197,22 +929,16 @@ const Renderer = function (scene, options) {
|
|
|
1197
929
|
const worldSurfacePos = math.vec3();
|
|
1198
930
|
const worldSurfaceNormal = math.vec3();
|
|
1199
931
|
|
|
1200
|
-
const pickBuffer = new RenderBuffer(gl);
|
|
1201
|
-
pickBuffer.setSize([1, 1]);
|
|
1202
|
-
|
|
1203
|
-
const pickNormalBuffer = new RenderBuffer(gl, [gl.RGBA32I]);
|
|
1204
|
-
pickNormalBuffer.setSize([3, 3]);
|
|
1205
|
-
|
|
1206
932
|
return function (params, pickResult = _pickResult) {
|
|
1207
933
|
|
|
1208
934
|
pickResult.reset();
|
|
1209
935
|
|
|
1210
936
|
updateDrawlist();
|
|
1211
937
|
|
|
938
|
+
let look;
|
|
1212
939
|
let pickViewMatrix = null;
|
|
1213
940
|
let pickProjMatrix = null;
|
|
1214
941
|
let projection = null;
|
|
1215
|
-
const camera = scene.camera;
|
|
1216
942
|
|
|
1217
943
|
pickResult.pickSurface = params.pickSurface;
|
|
1218
944
|
|
|
@@ -1221,12 +947,12 @@ const Renderer = function (scene, options) {
|
|
|
1221
947
|
canvasPos[0] = params.canvasPos[0];
|
|
1222
948
|
canvasPos[1] = params.canvasPos[1];
|
|
1223
949
|
|
|
1224
|
-
pickViewMatrix = camera.viewMatrix;
|
|
1225
|
-
pickProjMatrix = camera.projMatrix;
|
|
1226
|
-
projection = camera.projection;
|
|
950
|
+
pickViewMatrix = scene.camera.viewMatrix;
|
|
951
|
+
pickProjMatrix = scene.camera.projMatrix;
|
|
952
|
+
projection = scene.camera.projection;
|
|
1227
953
|
|
|
1228
|
-
nearAndFar[0] = camera.project.near;
|
|
1229
|
-
nearAndFar[1] = camera.project.far;
|
|
954
|
+
nearAndFar[0] = scene.camera.project.near;
|
|
955
|
+
nearAndFar[1] = scene.camera.project.far;
|
|
1230
956
|
|
|
1231
957
|
pickResult.canvasPos = params.canvasPos;
|
|
1232
958
|
|
|
@@ -1238,37 +964,33 @@ const Renderer = function (scene, options) {
|
|
|
1238
964
|
if (params.matrix) {
|
|
1239
965
|
|
|
1240
966
|
pickViewMatrix = params.matrix;
|
|
1241
|
-
pickProjMatrix = camera.projMatrix;
|
|
1242
|
-
projection = camera.projection;
|
|
967
|
+
pickProjMatrix = scene.camera.projMatrix;
|
|
968
|
+
projection = scene.camera.projection;
|
|
1243
969
|
|
|
1244
|
-
nearAndFar[0] = camera.project.near;
|
|
1245
|
-
nearAndFar[1] = camera.project.far;
|
|
970
|
+
nearAndFar[0] = scene.camera.project.near;
|
|
971
|
+
nearAndFar[1] = scene.camera.project.far;
|
|
1246
972
|
|
|
1247
973
|
} else {
|
|
1248
974
|
|
|
1249
975
|
worldRayOrigin.set(params.origin || [0, 0, 0]);
|
|
1250
976
|
worldRayDir.set(params.direction || [0, 0, 1]);
|
|
1251
977
|
|
|
1252
|
-
|
|
1253
|
-
const up = tempVec3b;
|
|
978
|
+
look = math.addVec3(worldRayOrigin, worldRayDir, tempVec3a);
|
|
1254
979
|
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
math.cross3Vec3(up, worldRayDir, up);
|
|
1262
|
-
math.normalizeVec3(up, up);
|
|
1263
|
-
}
|
|
980
|
+
randomVec3[0] = Math.random();
|
|
981
|
+
randomVec3[1] = Math.random();
|
|
982
|
+
randomVec3[2] = Math.random();
|
|
983
|
+
|
|
984
|
+
math.normalizeVec3(randomVec3);
|
|
985
|
+
math.cross3Vec3(worldRayDir, randomVec3, up);
|
|
1264
986
|
|
|
1265
987
|
pickViewMatrix = math.lookAtMat4v(worldRayOrigin, look, up, tempMat4b);
|
|
1266
|
-
// pickProjMatrix = camera.projMatrix;
|
|
1267
|
-
pickProjMatrix = camera.ortho.matrix;
|
|
988
|
+
// pickProjMatrix = scene.camera.projMatrix;
|
|
989
|
+
pickProjMatrix = scene.camera.ortho.matrix;
|
|
1268
990
|
projection = "ortho";
|
|
1269
991
|
|
|
1270
|
-
nearAndFar[0] = camera.ortho.near;
|
|
1271
|
-
nearAndFar[1] = camera.ortho.far;
|
|
992
|
+
nearAndFar[0] = scene.camera.ortho.near;
|
|
993
|
+
nearAndFar[1] = scene.camera.ortho.far;
|
|
1272
994
|
|
|
1273
995
|
pickResult.origin = worldRayOrigin;
|
|
1274
996
|
pickResult.direction = worldRayDir;
|
|
@@ -1278,42 +1000,23 @@ const Renderer = function (scene, options) {
|
|
|
1278
1000
|
canvasPos[1] = canvas.clientHeight * 0.5;
|
|
1279
1001
|
}
|
|
1280
1002
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
gl.viewport(0, 0, 1, 1);
|
|
1290
|
-
gl.depthMask(true);
|
|
1291
|
-
gl.enable(gl.DEPTH_TEST);
|
|
1292
|
-
gl.disable(gl.CULL_FACE);
|
|
1293
|
-
gl.disable(gl.BLEND);
|
|
1294
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1295
|
-
|
|
1296
|
-
const includeEntityIds = params.includeEntityIds;
|
|
1297
|
-
const excludeEntityIds = params.excludeEntityIds;
|
|
1298
|
-
|
|
1299
|
-
const renderDrawables = function(drawables) {
|
|
1300
|
-
drawables.forEach(drawable => {
|
|
1301
|
-
if (!drawable.culled && drawable.visible && drawable.pickable && drawable.drawPickMesh // TODO: push this logic into drawable
|
|
1302
|
-
&& ((! includeEntityIds) || includeEntityIds[drawable.id])
|
|
1303
|
-
&& ((! excludeEntityIds) || (! excludeEntityIds[drawable.id]))) {
|
|
1304
|
-
drawable.drawPickMesh(frameCtx);
|
|
1003
|
+
for (let type in drawableTypeInfo) {
|
|
1004
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
1005
|
+
const drawableList = drawableTypeInfo[type].drawableList;
|
|
1006
|
+
for (let i = 0, len = drawableList.length; i < len; i++) {
|
|
1007
|
+
const drawable = drawableList[i];
|
|
1008
|
+
if (drawable.setPickMatrices) { // Eg. SceneModel, which needs pre-loading into texture
|
|
1009
|
+
drawable.setPickMatrices(pickViewMatrix, pickProjMatrix);
|
|
1010
|
+
}
|
|
1305
1011
|
}
|
|
1306
|
-
}
|
|
1307
|
-
};
|
|
1308
|
-
|
|
1309
|
-
renderDrawables(postCullDrawableList);
|
|
1310
|
-
if (uiDrawableList.length > 0) {
|
|
1311
|
-
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1312
|
-
renderDrawables(uiDrawableList);
|
|
1012
|
+
}
|
|
1313
1013
|
}
|
|
1314
1014
|
|
|
1315
|
-
const
|
|
1316
|
-
|
|
1015
|
+
const pickBuffer = renderBufferManager.getRenderBuffer("pick", {size: [1, 1]});
|
|
1016
|
+
|
|
1017
|
+
pickBuffer.bind();
|
|
1018
|
+
|
|
1019
|
+
const pickable = gpuPickPickable(pickBuffer, canvasPos, pickViewMatrix, pickProjMatrix, params, pickResult);
|
|
1317
1020
|
|
|
1318
1021
|
if (!pickable) {
|
|
1319
1022
|
pickBuffer.unbind();
|
|
@@ -1333,21 +1036,7 @@ const Renderer = function (scene, options) {
|
|
|
1333
1036
|
|
|
1334
1037
|
if (pickable.canPickTriangle && pickable.canPickTriangle()) {
|
|
1335
1038
|
|
|
1336
|
-
|
|
1337
|
-
resetFrameCtx(1);
|
|
1338
|
-
// frameCtx.pickInvisible = !!params.pickInvisible;
|
|
1339
|
-
|
|
1340
|
-
gl.viewport(0, 0, 1, 1);
|
|
1341
|
-
gl.clearColor(0, 0, 0, 0);
|
|
1342
|
-
gl.enable(gl.DEPTH_TEST);
|
|
1343
|
-
gl.disable(gl.CULL_FACE);
|
|
1344
|
-
gl.disable(gl.BLEND);
|
|
1345
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1346
|
-
|
|
1347
|
-
pickable.drawPickTriangles(frameCtx);
|
|
1348
|
-
|
|
1349
|
-
pickResult.primIndex = 3 * pixelToInt(pickBuffer.read(0, 0)); // Convert from triangle number to first vertex in indices
|
|
1350
|
-
}
|
|
1039
|
+
gpuPickTriangle(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
1351
1040
|
|
|
1352
1041
|
pickable.pickTriangleSurface(pickViewMatrix, pickProjMatrix, projection, pickResult);
|
|
1353
1042
|
|
|
@@ -1357,84 +1046,255 @@ const Renderer = function (scene, options) {
|
|
|
1357
1046
|
|
|
1358
1047
|
if (pickable.canPickWorldPos && pickable.canPickWorldPos()) {
|
|
1359
1048
|
|
|
1360
|
-
|
|
1361
|
-
resetFrameCtx(1);
|
|
1362
|
-
frameCtx.viewParams.near = nearAndFar[0];
|
|
1363
|
-
frameCtx.viewParams.far = nearAndFar[1];
|
|
1049
|
+
gpuPickWorldPos(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult);
|
|
1364
1050
|
|
|
1365
|
-
|
|
1051
|
+
if (params.pickSurfaceNormal !== false) {
|
|
1052
|
+
gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
1053
|
+
}
|
|
1366
1054
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1055
|
+
pickResult.pickSurfacePrecision = false;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
pickBuffer.unbind();
|
|
1060
|
+
pickResult.entity = pickedEntity;
|
|
1061
|
+
return pickResult;
|
|
1062
|
+
};
|
|
1063
|
+
})();
|
|
1064
|
+
|
|
1065
|
+
function gpuPickPickable(pickBuffer, canvasPos, pickViewMatrix, pickProjMatrix, params, pickResult) {
|
|
1066
|
+
|
|
1067
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1068
|
+
|
|
1069
|
+
frameCtx.reset();
|
|
1070
|
+
frameCtx.backfaces = true;
|
|
1071
|
+
frameCtx.frontface = true; // "ccw"
|
|
1072
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1073
|
+
frameCtx.pickViewMatrix = pickViewMatrix;
|
|
1074
|
+
frameCtx.pickProjMatrix = pickProjMatrix;
|
|
1075
|
+
frameCtx.pickInvisible = !!params.pickInvisible;
|
|
1076
|
+
frameCtx.pickClipPos = [
|
|
1077
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1078
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
|
|
1079
|
+
];
|
|
1080
|
+
|
|
1081
|
+
gl.viewport(0, 0, 1, 1);
|
|
1082
|
+
gl.depthMask(true);
|
|
1083
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1084
|
+
gl.disable(gl.CULL_FACE);
|
|
1085
|
+
gl.disable(gl.BLEND);
|
|
1086
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1087
|
+
|
|
1088
|
+
const includeEntityIds = params.includeEntityIds;
|
|
1089
|
+
const excludeEntityIds = params.excludeEntityIds;
|
|
1090
|
+
|
|
1091
|
+
const renderDrawables = function(drawables) {
|
|
1092
|
+
for (let i = 0, len = drawables.length; i < len; i++) {
|
|
1093
|
+
const drawable = drawables[i];
|
|
1094
|
+
if (drawable.culled === true || drawable.visible === false) {
|
|
1095
|
+
continue;
|
|
1096
|
+
}
|
|
1097
|
+
if (!drawable.drawPickMesh || (params.pickInvisible !== true && drawable.visible === false) || drawable.pickable === false) {
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
if (includeEntityIds && !includeEntityIds[drawable.id]) { // TODO: push this logic into drawable
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
if (excludeEntityIds && excludeEntityIds[drawable.id]) {
|
|
1104
|
+
continue;
|
|
1105
|
+
}
|
|
1106
|
+
drawable.drawPickMesh(frameCtx);
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1373
1109
|
|
|
1374
|
-
|
|
1110
|
+
renderDrawables(postCullDrawableList);
|
|
1111
|
+
if (uiDrawableList.length > 0) {
|
|
1112
|
+
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1113
|
+
renderDrawables(uiDrawableList);
|
|
1114
|
+
}
|
|
1375
1115
|
|
|
1376
|
-
|
|
1116
|
+
const pix = pickBuffer.read(0, 0);
|
|
1117
|
+
const pickID = pix[0] + (pix[1] << 8) + (pix[2] << 16) + (pix[3] << 24);
|
|
1377
1118
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1119
|
+
if (pickID < 0) {
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1381
1122
|
|
|
1382
|
-
|
|
1123
|
+
const pickable = pickIDs.items[pickID];
|
|
1383
1124
|
|
|
1384
|
-
|
|
1125
|
+
return pickable;
|
|
1126
|
+
}
|
|
1385
1127
|
|
|
1386
|
-
|
|
1387
|
-
dst[0] = x;
|
|
1388
|
-
dst[1] = y;
|
|
1389
|
-
dst[2] = z;
|
|
1390
|
-
dst[3] = 1;
|
|
1391
|
-
math.transformVec4(pvMatInverse, dst, dst);
|
|
1392
|
-
return math.mulVec4Scalar(dst, 1 / dst[3]);
|
|
1393
|
-
};
|
|
1128
|
+
function gpuPickTriangle(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
1394
1129
|
|
|
1395
|
-
|
|
1396
|
-
|
|
1130
|
+
if (!pickable.drawPickTriangles) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1397
1133
|
|
|
1398
|
-
|
|
1399
|
-
const worldPos = math.addVec3(world1, math.mulVec4Scalar(dir, screenZ, tempVec4d), tempVec4e);
|
|
1134
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1400
1135
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1136
|
+
frameCtx.reset();
|
|
1137
|
+
frameCtx.backfaces = true;
|
|
1138
|
+
frameCtx.frontface = true; // "ccw"
|
|
1139
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1140
|
+
frameCtx.pickViewMatrix = pickViewMatrix; // Can be null
|
|
1141
|
+
frameCtx.pickProjMatrix = pickProjMatrix; // Can be null
|
|
1142
|
+
// frameCtx.pickInvisible = !!params.pickInvisible;
|
|
1143
|
+
frameCtx.pickClipPos = [
|
|
1144
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1145
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
|
|
1146
|
+
];
|
|
1404
1147
|
|
|
1405
|
-
|
|
1148
|
+
gl.viewport(0, 0, 1, 1);
|
|
1406
1149
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1150
|
+
gl.clearColor(0, 0, 0, 0);
|
|
1151
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1152
|
+
gl.disable(gl.CULL_FACE);
|
|
1153
|
+
gl.disable(gl.BLEND);
|
|
1154
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1410
1155
|
|
|
1411
|
-
|
|
1156
|
+
pickable.drawPickTriangles(frameCtx);
|
|
1412
1157
|
|
|
1413
|
-
|
|
1414
|
-
gl.enable(gl.DEPTH_TEST);
|
|
1415
|
-
gl.disable(gl.CULL_FACE);
|
|
1416
|
-
gl.disable(gl.BLEND);
|
|
1417
|
-
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1418
|
-
gl.clearBufferiv(gl.COLOR, 0, new Int32Array([0, 0, 0, 0]));
|
|
1158
|
+
const pix = pickBuffer.read(0, 0);
|
|
1419
1159
|
|
|
1420
|
-
|
|
1160
|
+
let primIndex = pix[0] + (pix[1] * 256) + (pix[2] * 256 * 256) + (pix[3] * 256 * 256 * 256);
|
|
1421
1161
|
|
|
1422
|
-
|
|
1162
|
+
primIndex *= 3; // Convert from triangle number to first vertex in indices
|
|
1423
1163
|
|
|
1424
|
-
|
|
1164
|
+
pickResult.primIndex = primIndex;
|
|
1165
|
+
}
|
|
1425
1166
|
|
|
1426
|
-
|
|
1427
|
-
}
|
|
1167
|
+
const gpuPickWorldPos = (function () {
|
|
1428
1168
|
|
|
1429
|
-
|
|
1169
|
+
const tempVec4a = math.vec4();
|
|
1170
|
+
const tempVec4b = math.vec4();
|
|
1171
|
+
const tempVec4c = math.vec4();
|
|
1172
|
+
const tempVec4d = math.vec4();
|
|
1173
|
+
const tempVec4e = math.vec4();
|
|
1174
|
+
const tempMat4a = math.mat4();
|
|
1175
|
+
const tempMat4b = math.mat4();
|
|
1176
|
+
const tempMat4c = math.mat4();
|
|
1177
|
+
|
|
1178
|
+
return function (pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult) {
|
|
1179
|
+
|
|
1180
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1181
|
+
|
|
1182
|
+
frameCtx.reset();
|
|
1183
|
+
frameCtx.backfaces = true;
|
|
1184
|
+
frameCtx.frontface = true; // "ccw"
|
|
1185
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1186
|
+
frameCtx.pickViewMatrix = pickViewMatrix;
|
|
1187
|
+
frameCtx.pickProjMatrix = pickProjMatrix;
|
|
1188
|
+
frameCtx.pickZNear = nearAndFar[0];
|
|
1189
|
+
frameCtx.pickZFar = nearAndFar[1];
|
|
1190
|
+
frameCtx.pickElementsCount = pickable.pickElementsCount;
|
|
1191
|
+
frameCtx.pickElementsOffset = pickable.pickElementsOffset;
|
|
1192
|
+
frameCtx.pickClipPos = [
|
|
1193
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1194
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
|
|
1195
|
+
];
|
|
1196
|
+
|
|
1197
|
+
gl.viewport(0, 0, 1, 1);
|
|
1198
|
+
|
|
1199
|
+
gl.clearColor(0, 0, 0, 0);
|
|
1200
|
+
gl.depthMask(true);
|
|
1201
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1202
|
+
gl.disable(gl.CULL_FACE);
|
|
1203
|
+
gl.disable(gl.BLEND);
|
|
1204
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1205
|
+
|
|
1206
|
+
pickable.drawPickDepths(frameCtx); // Draw color-encoded fragment screen-space depths
|
|
1207
|
+
|
|
1208
|
+
const pix = pickBuffer.read(0, 0);
|
|
1209
|
+
|
|
1210
|
+
const screenZ = unpackDepth(pix); // Get screen-space Z at the given canvas coords
|
|
1211
|
+
|
|
1212
|
+
// Calculate clip space coordinates, which will be in range of x=[-1..1] and y=[-1..1], with y=(+1) at top
|
|
1213
|
+
const x = (canvasPos[0] - canvas.clientWidth / 2) / (canvas.clientWidth / 2);
|
|
1214
|
+
const y = -(canvasPos[1] - canvas.clientHeight / 2) / (canvas.clientHeight / 2);
|
|
1215
|
+
|
|
1216
|
+
const origin = pickable.origin;
|
|
1217
|
+
let pvMat;
|
|
1218
|
+
|
|
1219
|
+
if (origin) {
|
|
1220
|
+
const rtcPickViewMat = createRTCViewMat(pickViewMatrix, origin, tempMat4a);
|
|
1221
|
+
pvMat = math.mulMat4(pickProjMatrix, rtcPickViewMat, tempMat4b);
|
|
1222
|
+
|
|
1223
|
+
} else {
|
|
1224
|
+
pvMat = math.mulMat4(pickProjMatrix, pickViewMatrix, tempMat4b);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
const pvMatInverse = math.inverseMat4(pvMat, tempMat4c);
|
|
1228
|
+
|
|
1229
|
+
tempVec4a[0] = x;
|
|
1230
|
+
tempVec4a[1] = y;
|
|
1231
|
+
tempVec4a[2] = -1;
|
|
1232
|
+
tempVec4a[3] = 1;
|
|
1233
|
+
|
|
1234
|
+
let world1 = math.transformVec4(pvMatInverse, tempVec4a);
|
|
1235
|
+
world1 = math.mulVec4Scalar(world1, 1 / world1[3]);
|
|
1236
|
+
|
|
1237
|
+
tempVec4b[0] = x;
|
|
1238
|
+
tempVec4b[1] = y;
|
|
1239
|
+
tempVec4b[2] = 1;
|
|
1240
|
+
tempVec4b[3] = 1;
|
|
1241
|
+
|
|
1242
|
+
let world2 = math.transformVec4(pvMatInverse, tempVec4b);
|
|
1243
|
+
world2 = math.mulVec4Scalar(world2, 1 / world2[3]);
|
|
1244
|
+
|
|
1245
|
+
const dir = math.subVec3(world2, world1, tempVec4c);
|
|
1246
|
+
const worldPos = math.addVec3(world1, math.mulVec4Scalar(dir, screenZ, tempVec4d), tempVec4e);
|
|
1247
|
+
|
|
1248
|
+
if (origin) {
|
|
1249
|
+
math.addVec3(worldPos, origin);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
pickResult.worldPos = worldPos;
|
|
1253
|
+
}
|
|
1254
|
+
})();
|
|
1255
|
+
|
|
1256
|
+
function drawSnapInit(frameCtx) {
|
|
1257
|
+
frameCtx.snapPickLayerParams = [];
|
|
1258
|
+
frameCtx.snapPickLayerNumber = 0;
|
|
1259
|
+
|
|
1260
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
1261
|
+
|
|
1262
|
+
const drawable = postCullDrawableList[i];
|
|
1263
|
+
|
|
1264
|
+
if (drawable.drawSnapInit) {
|
|
1265
|
+
if (!drawable.culled && drawable.visible && drawable.pickable) {
|
|
1266
|
+
drawable.drawSnapInit(frameCtx);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
return frameCtx.snapPickLayerParams;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
function drawSnap(frameCtx) {
|
|
1274
|
+
frameCtx.snapPickLayerParams = frameCtx.snapPickLayerParams || [];
|
|
1275
|
+
frameCtx.snapPickLayerNumber = frameCtx.snapPickLayerParams.length;
|
|
1276
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
1277
|
+
|
|
1278
|
+
const drawable = postCullDrawableList[i];
|
|
1279
|
+
|
|
1280
|
+
if (drawable.drawSnapInit) {
|
|
1281
|
+
if (drawable.drawSnap) {
|
|
1282
|
+
if (!drawable.culled && drawable.visible && drawable.pickable) {
|
|
1283
|
+
drawable.drawSnap(frameCtx);
|
|
1430
1284
|
}
|
|
1431
1285
|
}
|
|
1432
1286
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1287
|
+
}
|
|
1288
|
+
return frameCtx.snapPickLayerParams;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
function getClipPosX(pos, size) {
|
|
1292
|
+
return 2 * (pos / size) - 1;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
function getClipPosY(pos, size) {
|
|
1296
|
+
return 1 - 2 * (pos / size);
|
|
1297
|
+
}
|
|
1438
1298
|
|
|
1439
1299
|
/**
|
|
1440
1300
|
* @param {[number, number]} canvasPos
|
|
@@ -1448,18 +1308,6 @@ const Renderer = function (scene, options) {
|
|
|
1448
1308
|
|
|
1449
1309
|
const _pickResult = new PickResult();
|
|
1450
1310
|
|
|
1451
|
-
const getVertexPickBuffer = (function() {
|
|
1452
|
-
const cache = { };
|
|
1453
|
-
return (snapRadiusInPixels) => {
|
|
1454
|
-
if (! (snapRadiusInPixels in cache)) {
|
|
1455
|
-
const buf = new RenderBuffer(gl, [gl.RGBA32I, gl.RGBA32I, gl.RGBA8UI], true);
|
|
1456
|
-
buf.setSize([2 * snapRadiusInPixels + 1, 2 * snapRadiusInPixels + 1]);
|
|
1457
|
-
cache[snapRadiusInPixels] = buf;
|
|
1458
|
-
}
|
|
1459
|
-
return cache[snapRadiusInPixels];
|
|
1460
|
-
};
|
|
1461
|
-
})();
|
|
1462
|
-
|
|
1463
1311
|
return function (params, pickResult = _pickResult) {
|
|
1464
1312
|
|
|
1465
1313
|
const {canvasPos, origin, direction, snapRadius, snapToVertex, snapToEdge} = params;
|
|
@@ -1468,21 +1316,40 @@ const Renderer = function (scene, options) {
|
|
|
1468
1316
|
return this.pick({canvasPos, pickSurface: true});
|
|
1469
1317
|
}
|
|
1470
1318
|
|
|
1471
|
-
const
|
|
1319
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1320
|
+
|
|
1321
|
+
frameCtx.reset();
|
|
1322
|
+
frameCtx.backfaces = true;
|
|
1323
|
+
frameCtx.frontface = true; // "ccw"
|
|
1324
|
+
frameCtx.pickZNear = scene.camera.project.near;
|
|
1325
|
+
frameCtx.pickZFar = scene.camera.project.far;
|
|
1326
|
+
|
|
1472
1327
|
const snapRadiusInPixels = snapRadius || 30;
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1328
|
+
|
|
1329
|
+
const vertexPickBuffer = renderBufferManager.getRenderBuffer(
|
|
1330
|
+
`uniquePickColors-aabs-${snapRadiusInPixels}`,
|
|
1331
|
+
{
|
|
1332
|
+
depthTexture: true,
|
|
1333
|
+
size: [
|
|
1334
|
+
2 * snapRadiusInPixels + 1,
|
|
1335
|
+
2 * snapRadiusInPixels + 1,
|
|
1336
|
+
]
|
|
1337
|
+
}
|
|
1338
|
+
);
|
|
1339
|
+
|
|
1340
|
+
frameCtx.snapVectorA = [
|
|
1341
|
+
canvasPos ? getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth) : 0,
|
|
1342
|
+
canvasPos ? getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight) : 0,
|
|
1343
|
+
];
|
|
1344
|
+
|
|
1345
|
+
frameCtx.snapInvVectorAB = [
|
|
1346
|
+
gl.drawingBufferWidth / (2 * snapRadiusInPixels),
|
|
1347
|
+
gl.drawingBufferHeight / (2 * snapRadiusInPixels),
|
|
1348
|
+
];
|
|
1481
1349
|
|
|
1482
1350
|
// Bind and clear the snap render target
|
|
1483
1351
|
|
|
1484
|
-
|
|
1485
|
-
vertexPickBuffer.bind();
|
|
1352
|
+
vertexPickBuffer.bind(gl.RGBA32I, gl.RGBA32I, gl.RGBA8UI);
|
|
1486
1353
|
gl.viewport(0, 0, vertexPickBuffer.size[0], vertexPickBuffer.size[1]);
|
|
1487
1354
|
gl.enable(gl.DEPTH_TEST);
|
|
1488
1355
|
gl.frontFace(gl.CCW);
|
|
@@ -1495,59 +1362,64 @@ const Renderer = function (scene, options) {
|
|
|
1495
1362
|
gl.clearBufferiv(gl.COLOR, 1, new Int32Array([0, 0, 0, 0]));
|
|
1496
1363
|
gl.clearBufferuiv(gl.COLOR, 2, new Uint32Array([0, 0, 0, 0]));
|
|
1497
1364
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
frameCtx.
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1365
|
+
//////////////////////////////////
|
|
1366
|
+
// Set view and proj mats for VBO renderers
|
|
1367
|
+
///////////////////////////////////////
|
|
1368
|
+
|
|
1369
|
+
frameCtx.pickViewMatrix = (canvasPos
|
|
1370
|
+
? scene.camera.viewMatrix
|
|
1371
|
+
: math.lookAtMat4v(
|
|
1372
|
+
origin,
|
|
1373
|
+
math.addVec3(origin, direction, math.vec3()),
|
|
1374
|
+
math.vec3([0, 1, 0]),
|
|
1375
|
+
math.mat4()));
|
|
1376
|
+
|
|
1377
|
+
const pickProjMatrix = scene.camera.projMatrix;
|
|
1378
|
+
|
|
1379
|
+
for (let type in drawableTypeInfo) {
|
|
1380
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
1381
|
+
const drawableList = drawableTypeInfo[type].drawableList;
|
|
1382
|
+
for (let i = 0, len = drawableList.length; i < len; i++) {
|
|
1383
|
+
const drawable = drawableList[i];
|
|
1384
|
+
if (drawable.setPickMatrices) { // Eg. SceneModel, which needs pre-loading into texture
|
|
1385
|
+
drawable.setPickMatrices(frameCtx.pickViewMatrix, pickProjMatrix);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1506
1388
|
}
|
|
1507
|
-
}
|
|
1389
|
+
}
|
|
1508
1390
|
|
|
1509
|
-
|
|
1391
|
+
// a) init z-buffer
|
|
1392
|
+
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
|
|
1393
|
+
const layerParamsSurface = drawSnapInit(frameCtx);
|
|
1510
1394
|
|
|
1511
1395
|
// b) snap-pick
|
|
1512
|
-
|
|
1396
|
+
const layerParamsSnap = []
|
|
1397
|
+
frameCtx.snapPickLayerParams = layerParamsSnap;
|
|
1513
1398
|
|
|
1514
1399
|
gl.depthMask(false);
|
|
1515
1400
|
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
|
|
1516
1401
|
|
|
1517
|
-
|
|
1518
|
-
frameCtx.snapMode =
|
|
1519
|
-
frameCtx
|
|
1520
|
-
postCullDrawableList.forEach(drawable => {
|
|
1521
|
-
if (!drawable.culled && drawable.visible && drawable.pickable && drawable.drawSnap) {
|
|
1522
|
-
drawable.drawSnap(frameCtx);
|
|
1523
|
-
}
|
|
1524
|
-
});
|
|
1525
|
-
};
|
|
1402
|
+
if (snapToVertex && snapToEdge) {
|
|
1403
|
+
frameCtx.snapMode = "edge";
|
|
1404
|
+
drawSnap(frameCtx);
|
|
1526
1405
|
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1406
|
+
frameCtx.snapMode = "vertex";
|
|
1407
|
+
frameCtx.snapPickLayerNumber++;
|
|
1408
|
+
|
|
1409
|
+
drawSnap(frameCtx);
|
|
1410
|
+
} else {
|
|
1411
|
+
frameCtx.snapMode = snapToVertex ? "vertex" : "edge";
|
|
1412
|
+
|
|
1413
|
+
drawSnap(frameCtx);
|
|
1532
1414
|
}
|
|
1533
1415
|
|
|
1534
1416
|
gl.depthMask(true);
|
|
1535
1417
|
|
|
1536
|
-
const layerParamsSnap = frameCtx.snapPickLayerParams;
|
|
1537
|
-
|
|
1538
1418
|
// Read and decode the snapped coordinates
|
|
1539
|
-
const readSnapPickBuffer = (source, arrayType, glType) => {
|
|
1540
|
-
const w = vertexPickBuffer.buffer.width;
|
|
1541
|
-
const h = vertexPickBuffer.buffer.height;
|
|
1542
|
-
const pix = new arrayType(4 * w * h);
|
|
1543
|
-
gl.readBuffer(source);
|
|
1544
|
-
gl.readPixels(0, 0, w, h, gl.RGBA_INTEGER, glType, pix, 0);
|
|
1545
|
-
return pix;
|
|
1546
|
-
};
|
|
1547
1419
|
|
|
1548
|
-
const snapPickResultArray
|
|
1549
|
-
const snapPickNormalResultArray =
|
|
1550
|
-
const snapPickIdResultArray
|
|
1420
|
+
const snapPickResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.INT, Int32Array, 4);
|
|
1421
|
+
const snapPickNormalResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.INT, Int32Array, 4, 1);
|
|
1422
|
+
const snapPickIdResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.UNSIGNED_INT, Uint32Array, 4, 2);
|
|
1551
1423
|
|
|
1552
1424
|
vertexPickBuffer.unbind();
|
|
1553
1425
|
|
|
@@ -1566,76 +1438,195 @@ const Renderer = function (scene, options) {
|
|
|
1566
1438
|
|
|
1567
1439
|
if (pickResultMiddleXY[3] !== 0) {
|
|
1568
1440
|
const pickedLayerParmasSurface = layerParamsSurface[Math.abs(pickResultMiddleXY[3]) % layerParamsSurface.length];
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1441
|
+
const origin = pickedLayerParmasSurface.origin;
|
|
1442
|
+
const scale = pickedLayerParmasSurface.coordinateScale;
|
|
1443
|
+
worldPos = [
|
|
1444
|
+
pickResultMiddleXY[0] * scale[0] + origin[0],
|
|
1445
|
+
pickResultMiddleXY[1] * scale[1] + origin[1],
|
|
1446
|
+
pickResultMiddleXY[2] * scale[2] + origin[2],
|
|
1447
|
+
];
|
|
1448
|
+
worldNormal = math.normalizeVec3([
|
|
1449
|
+
pickNormalResultMiddleXY[0] / math.MAX_INT,
|
|
1450
|
+
pickNormalResultMiddleXY[1] / math.MAX_INT,
|
|
1451
|
+
pickNormalResultMiddleXY[2] / math.MAX_INT,
|
|
1452
|
+
]);
|
|
1453
|
+
|
|
1454
|
+
const pickID =
|
|
1455
|
+
pickPickableResultMiddleXY[0]
|
|
1456
|
+
+ (pickPickableResultMiddleXY[1] << 8)
|
|
1457
|
+
+ (pickPickableResultMiddleXY[2] << 16)
|
|
1458
|
+
+ (pickPickableResultMiddleXY[3] << 24);
|
|
1459
|
+
|
|
1460
|
+
pickable = pickIDs.items[pickID];
|
|
1573
1461
|
}
|
|
1574
1462
|
|
|
1575
1463
|
// result 2) hi-precision snapped (to vertex/edge) world position
|
|
1576
1464
|
|
|
1577
|
-
|
|
1465
|
+
let snapPickResult = [];
|
|
1466
|
+
|
|
1578
1467
|
for (let i = 0; i < snapPickResultArray.length; i += 4) {
|
|
1579
|
-
|
|
1580
|
-
if (layerNumber > 0) {
|
|
1468
|
+
if (snapPickResultArray[i + 3] > 0) {
|
|
1581
1469
|
const pixelNumber = Math.floor(i / 4);
|
|
1582
1470
|
const w = vertexPickBuffer.size[0];
|
|
1583
1471
|
const x = pixelNumber % w - Math.floor(w / 2);
|
|
1584
1472
|
const y = Math.floor(pixelNumber / w) - Math.floor(w / 2);
|
|
1473
|
+
const dist = (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
|
1585
1474
|
snapPickResult.push({
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1475
|
+
x,
|
|
1476
|
+
y,
|
|
1477
|
+
dist,
|
|
1478
|
+
isVertex: snapToVertex && snapToEdge ? snapPickResultArray[i + 3] > layerParamsSnap.length / 2 : snapToVertex,
|
|
1479
|
+
result: [
|
|
1480
|
+
snapPickResultArray[i + 0],
|
|
1481
|
+
snapPickResultArray[i + 1],
|
|
1482
|
+
snapPickResultArray[i + 2],
|
|
1483
|
+
snapPickResultArray[i + 3],
|
|
1484
|
+
],
|
|
1485
|
+
normal: [
|
|
1486
|
+
snapPickNormalResultArray[i + 0],
|
|
1487
|
+
snapPickNormalResultArray[i + 1],
|
|
1488
|
+
snapPickNormalResultArray[i + 2],
|
|
1489
|
+
snapPickNormalResultArray[i + 3],
|
|
1490
|
+
],
|
|
1491
|
+
id: [
|
|
1492
|
+
snapPickIdResultArray[i + 0],
|
|
1493
|
+
snapPickIdResultArray[i + 1],
|
|
1494
|
+
snapPickIdResultArray[i + 2],
|
|
1495
|
+
snapPickIdResultArray[i + 3],
|
|
1496
|
+
]
|
|
1591
1497
|
});
|
|
1592
1498
|
}
|
|
1593
1499
|
}
|
|
1594
1500
|
|
|
1595
|
-
|
|
1501
|
+
let snappedWorldPos = null;
|
|
1502
|
+
let snappedWorldNormal = null;
|
|
1503
|
+
let snappedPickable = null;
|
|
1504
|
+
let snapType = null;
|
|
1596
1505
|
|
|
1597
1506
|
if (snapPickResult.length > 0) {
|
|
1598
|
-
//
|
|
1599
|
-
|
|
1600
|
-
|
|
1507
|
+
// vertex snap first, then edge snap
|
|
1508
|
+
snapPickResult.sort((a, b) => {
|
|
1509
|
+
if (a.isVertex !== b.isVertex) {
|
|
1510
|
+
return a.isVertex ? -1 : 1;
|
|
1511
|
+
} else {
|
|
1512
|
+
return a.dist - b.dist;
|
|
1513
|
+
}
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
snapType = snapPickResult[0].isVertex ? "vertex" : "edge";
|
|
1517
|
+
const snapPick = snapPickResult[0].result;
|
|
1518
|
+
const snapPickNormal = snapPickResult[0].normal;
|
|
1519
|
+
const snapPickId = snapPickResult[0].id;
|
|
1520
|
+
|
|
1601
1521
|
const pickedLayerParmas = layerParamsSnap[snapPick[3]];
|
|
1602
|
-
const snappedWorldPos = toWorldPos(snapPick, pickedLayerParmas.origin, pickedLayerParmas.coordinateScale);
|
|
1603
|
-
const snappedCanvasPos = camera.projectWorldPos(snappedWorldPos);
|
|
1604
|
-
|
|
1605
|
-
pickResult.reset();
|
|
1606
|
-
pickResult.snappedToEdge = !res.isVertex;
|
|
1607
|
-
pickResult.snappedToVertex = res.isVertex;
|
|
1608
|
-
pickResult.worldPos = snappedWorldPos;
|
|
1609
|
-
pickResult.worldNormal = toWorldNormal(res.normal);
|
|
1610
|
-
pickResult.entity = getPickedEntity(pickIDs.items[pixelToInt(res.id)]);
|
|
1611
|
-
pickResult.canvasPos = canvasPos || (worldPos && camera.projectWorldPos(worldPos)) || snappedCanvasPos;
|
|
1612
|
-
pickResult.snappedCanvasPos = snappedCanvasPos;
|
|
1613
|
-
return pickResult;
|
|
1614
|
-
|
|
1615
|
-
} else if (worldPos) {
|
|
1616
|
-
|
|
1617
|
-
pickResult.reset();
|
|
1618
|
-
pickResult.snappedToEdge = false;
|
|
1619
|
-
pickResult.snappedToVertex = false;
|
|
1620
|
-
pickResult.worldPos = worldPos;
|
|
1621
|
-
pickResult.worldNormal = worldNormal;
|
|
1622
|
-
pickResult.entity = getPickedEntity(pickable);
|
|
1623
|
-
pickResult.canvasPos = canvasPos || camera.projectWorldPos(worldPos);
|
|
1624
|
-
pickResult.snappedCanvasPos = canvasPos;
|
|
1625
|
-
return pickResult;
|
|
1626
1522
|
|
|
1627
|
-
|
|
1523
|
+
const origin = pickedLayerParmas.origin;
|
|
1524
|
+
const scale = pickedLayerParmas.coordinateScale;
|
|
1525
|
+
|
|
1526
|
+
snappedWorldNormal = math.normalizeVec3([
|
|
1527
|
+
snapPickNormal[0] / math.MAX_INT,
|
|
1528
|
+
snapPickNormal[1] / math.MAX_INT,
|
|
1529
|
+
snapPickNormal[2] / math.MAX_INT,
|
|
1530
|
+
]);
|
|
1531
|
+
|
|
1532
|
+
snappedWorldPos = [
|
|
1533
|
+
snapPick[0] * scale[0] + origin[0],
|
|
1534
|
+
snapPick[1] * scale[1] + origin[1],
|
|
1535
|
+
snapPick[2] * scale[2] + origin[2],
|
|
1536
|
+
];
|
|
1537
|
+
|
|
1538
|
+
snappedPickable = pickIDs.items[
|
|
1539
|
+
snapPickId[0]
|
|
1540
|
+
+ (snapPickId[1] << 8)
|
|
1541
|
+
+ (snapPickId[2] << 16)
|
|
1542
|
+
+ (snapPickId[3] << 24)
|
|
1543
|
+
];
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
if (null === worldPos && null == snappedWorldPos) { // If neither regular pick or snap pick, return null
|
|
1628
1547
|
return null;
|
|
1629
1548
|
}
|
|
1549
|
+
|
|
1550
|
+
let snappedCanvasPos = null;
|
|
1551
|
+
|
|
1552
|
+
if (null !== snappedWorldPos) {
|
|
1553
|
+
snappedCanvasPos = scene.camera.projectWorldPos(snappedWorldPos);
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
const snappedEntity = (snappedPickable && snappedPickable.delegatePickedEntity) ? snappedPickable.delegatePickedEntity() : snappedPickable;
|
|
1557
|
+
if (!snappedEntity && pickable) {
|
|
1558
|
+
pickable = pickable.delegatePickedEntity ? pickable.delegatePickedEntity() : pickable;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
pickResult.reset();
|
|
1562
|
+
pickResult.snappedToEdge = (snapType === "edge");
|
|
1563
|
+
pickResult.snappedToVertex = (snapType === "vertex");
|
|
1564
|
+
pickResult.worldPos = snappedWorldPos || worldPos;
|
|
1565
|
+
pickResult.worldNormal = snappedWorldNormal || worldNormal;
|
|
1566
|
+
pickResult.entity = snappedEntity || pickable;
|
|
1567
|
+
pickResult.canvasPos = canvasPos || scene.camera.projectWorldPos(worldPos || snappedWorldPos);
|
|
1568
|
+
pickResult.snappedCanvasPos = snappedCanvasPos || canvasPos;
|
|
1569
|
+
|
|
1570
|
+
return pickResult;
|
|
1630
1571
|
};
|
|
1631
1572
|
})();
|
|
1632
1573
|
|
|
1574
|
+
function unpackDepth(depthZ) {
|
|
1575
|
+
const vec = [depthZ[0] / 256.0, depthZ[1] / 256.0, depthZ[2] / 256.0, depthZ[3] / 256.0];
|
|
1576
|
+
const bitShift = [1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0];
|
|
1577
|
+
return math.dotVec4(vec, bitShift);
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
function gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
1581
|
+
|
|
1582
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1583
|
+
|
|
1584
|
+
frameCtx.reset();
|
|
1585
|
+
frameCtx.backfaces = true;
|
|
1586
|
+
frameCtx.frontface = true; // "ccw"
|
|
1587
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1588
|
+
frameCtx.pickViewMatrix = pickViewMatrix;
|
|
1589
|
+
frameCtx.pickProjMatrix = pickProjMatrix;
|
|
1590
|
+
frameCtx.pickClipPos = [
|
|
1591
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1592
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
|
|
1593
|
+
];
|
|
1594
|
+
|
|
1595
|
+
const pickNormalBuffer = renderBufferManager.getRenderBuffer("pick-normal", {size: [3, 3]});
|
|
1596
|
+
|
|
1597
|
+
pickNormalBuffer.bind(gl.RGBA32I);
|
|
1598
|
+
|
|
1599
|
+
gl.viewport(0, 0, pickNormalBuffer.size[0], pickNormalBuffer.size[1]);
|
|
1600
|
+
|
|
1601
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1602
|
+
gl.disable(gl.CULL_FACE);
|
|
1603
|
+
gl.disable(gl.BLEND);
|
|
1604
|
+
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1605
|
+
gl.clearBufferiv(gl.COLOR, 0, new Int32Array([0, 0, 0, 0]));
|
|
1606
|
+
|
|
1607
|
+
pickable.drawPickNormals(frameCtx); // Draw color-encoded fragment World-space normals
|
|
1608
|
+
|
|
1609
|
+
const pix = pickNormalBuffer.read(1, 1, gl.RGBA_INTEGER, gl.INT, Int32Array, 4);
|
|
1610
|
+
|
|
1611
|
+
pickNormalBuffer.unbind();
|
|
1612
|
+
|
|
1613
|
+
const worldNormal = [
|
|
1614
|
+
pix[0] / math.MAX_INT,
|
|
1615
|
+
pix[1] / math.MAX_INT,
|
|
1616
|
+
pix[2] / math.MAX_INT,
|
|
1617
|
+
];
|
|
1618
|
+
|
|
1619
|
+
math.normalizeVec3(worldNormal);
|
|
1620
|
+
|
|
1621
|
+
pickResult.worldNormal = worldNormal;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1633
1624
|
/**
|
|
1634
1625
|
* Adds a {@link Marker} for occlusion testing.
|
|
1635
1626
|
* @param marker
|
|
1636
1627
|
*/
|
|
1637
1628
|
this.addMarker = function (marker) {
|
|
1638
|
-
this._occlusionTester = this._occlusionTester || new OcclusionTester(scene);
|
|
1629
|
+
this._occlusionTester = this._occlusionTester || new OcclusionTester(scene, renderBufferManager);
|
|
1639
1630
|
this._occlusionTester.addMarker(marker);
|
|
1640
1631
|
scene.occlusionTestCountdown = 0;
|
|
1641
1632
|
};
|
|
@@ -1666,17 +1657,11 @@ const Renderer = function (scene, options) {
|
|
|
1666
1657
|
|
|
1667
1658
|
updateDrawlist();
|
|
1668
1659
|
|
|
1669
|
-
|
|
1670
|
-
if (readPixelBuf) {
|
|
1671
|
-
readPixelBuf.setSize([gl.drawingBufferWidth, gl.drawingBufferHeight]);
|
|
1672
|
-
readPixelBuf.bind();
|
|
1673
|
-
}
|
|
1660
|
+
this._occlusionTester.bindRenderBuf();
|
|
1674
1661
|
|
|
1675
1662
|
frameCtx.reset();
|
|
1676
1663
|
frameCtx.backfaces = true;
|
|
1677
1664
|
frameCtx.frontface = true; // "ccw"
|
|
1678
|
-
frameCtx.viewParams = getSceneCameraViewParams();
|
|
1679
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(scene.camera, gl.drawingBufferHeight);
|
|
1680
1665
|
|
|
1681
1666
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
1682
1667
|
gl.clearColor(0, 0, 0, 0);
|
|
@@ -1685,143 +1670,121 @@ const Renderer = function (scene, options) {
|
|
|
1685
1670
|
gl.disable(gl.BLEND);
|
|
1686
1671
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1687
1672
|
|
|
1688
|
-
postCullDrawableList.forEach(drawable => {
|
|
1689
|
-
if (!drawable.culled && drawable.visible && drawable.pickable && drawable.drawOcclusion) { // TODO: Option to exclude transparent?
|
|
1690
|
-
drawable.drawOcclusion(frameCtx);
|
|
1691
|
-
}
|
|
1692
|
-
});
|
|
1693
1673
|
|
|
1694
|
-
|
|
1674
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
1675
|
+
|
|
1676
|
+
const drawable = postCullDrawableList[i];
|
|
1677
|
+
|
|
1678
|
+
if (!drawable.drawOcclusion || drawable.culled === true || drawable.visible === false || drawable.pickable === false) { // TODO: Option to exclude transparent?
|
|
1679
|
+
continue;
|
|
1680
|
+
}
|
|
1695
1681
|
|
|
1696
|
-
|
|
1697
|
-
const resolutionScale = scene.canvas.resolutionScale;
|
|
1698
|
-
this._occlusionTester.doOcclusionTest( // Updates Marker "visible" properties
|
|
1699
|
-
(x, y) => readPixelBuf.read(Math.round(resolutionScale * x), Math.round(resolutionScale * y)));
|
|
1700
|
-
readPixelBuf.unbind();
|
|
1682
|
+
drawable.drawOcclusion(frameCtx);
|
|
1701
1683
|
}
|
|
1684
|
+
|
|
1685
|
+
this._occlusionTester.drawMarkers(frameCtx);
|
|
1686
|
+
this._occlusionTester.doOcclusionTest(); // Updates Marker "visible" properties
|
|
1687
|
+
this._occlusionTester.unbindRenderBuf();
|
|
1702
1688
|
}
|
|
1703
1689
|
};
|
|
1704
1690
|
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
},
|
|
1735
|
-
|
|
1736
|
-
/**
|
|
1737
|
-
* Enter snapshot mode.
|
|
1738
|
-
*
|
|
1739
|
-
* Switches rendering to a hidden snapshot canvas.
|
|
1740
|
-
*
|
|
1741
|
-
* Exit snapshot mode using endSnapshot().
|
|
1742
|
-
*/
|
|
1743
|
-
beginSnapshot: () => {
|
|
1744
|
-
snapshotBuffer.setSize([gl.drawingBufferWidth, gl.drawingBufferHeight]);
|
|
1745
|
-
snapshotBuffer.bind();
|
|
1746
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1747
|
-
snapshotBound = true;
|
|
1748
|
-
},
|
|
1749
|
-
|
|
1750
|
-
/**
|
|
1751
|
-
* Returns an HTMLCanvas containing an image of the snapshot canvas.
|
|
1752
|
-
*
|
|
1753
|
-
* - The HTMLCanvas has a CanvasRenderingContext2D.
|
|
1754
|
-
* - Expects the caller to draw more things on the HTMLCanvas (annotations etc).
|
|
1755
|
-
*
|
|
1756
|
-
* @returns {HTMLCanvasElement}
|
|
1757
|
-
*/
|
|
1758
|
-
renderSnapshotToCanvas: () => {
|
|
1759
|
-
const width = snapshotBuffer.buffer.width;
|
|
1760
|
-
const height = snapshotBuffer.buffer.height;
|
|
1761
|
-
|
|
1762
|
-
if ((! snapshotCanvas) || (snapshotCanvas.width !== width) || (snapshotCanvas.height !== height)) {
|
|
1763
|
-
snapshotCanvas = (function() {
|
|
1764
|
-
const canvas = document.createElement('canvas');
|
|
1765
|
-
const context = canvas.getContext('2d');
|
|
1766
|
-
canvas.width = width;
|
|
1767
|
-
canvas.height = height;
|
|
1768
|
-
const pixelData = new Uint8Array(width * height * 4);
|
|
1769
|
-
const imageData = context.createImageData(width, height);
|
|
1770
|
-
|
|
1771
|
-
return {
|
|
1772
|
-
width: width,
|
|
1773
|
-
height: height,
|
|
1774
|
-
getUpdatedCanvas: () => {
|
|
1775
|
-
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
|
|
1776
|
-
|
|
1777
|
-
// flip verically
|
|
1778
|
-
const halfHeight = Math.floor(height / 2);
|
|
1779
|
-
const bytesPerRow = width * 4;
|
|
1780
|
-
const temp = new Uint8Array(bytesPerRow);
|
|
1781
|
-
for (let y = 0; y < halfHeight; ++y) {
|
|
1782
|
-
const topOffset = y * bytesPerRow;
|
|
1783
|
-
const bottomOffset = (height - y - 1) * bytesPerRow;
|
|
1784
|
-
temp.set(pixelData.subarray(topOffset, topOffset + bytesPerRow));
|
|
1785
|
-
pixelData.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
|
|
1786
|
-
pixelData.set(temp, bottomOffset);
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
imageData.data.set(pixelData);
|
|
1790
|
-
|
|
1791
|
-
context.resetTransform(); // Prevents strange scale-accumulation effect with html2canvas
|
|
1792
|
-
context.putImageData(imageData, 0, 0);
|
|
1793
|
-
|
|
1794
|
-
return canvas;
|
|
1795
|
-
}
|
|
1796
|
-
};
|
|
1797
|
-
})();
|
|
1798
|
-
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Read pixels from the renderer's current output. Performs a force-render first.
|
|
1693
|
+
* @param pixels
|
|
1694
|
+
* @param colors
|
|
1695
|
+
* @param len
|
|
1696
|
+
* @param opaqueOnly
|
|
1697
|
+
* @private
|
|
1698
|
+
*/
|
|
1699
|
+
this.readPixels = function (pixels, colors, len, opaqueOnly) {
|
|
1700
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1701
|
+
snapshotBuffer.bind();
|
|
1702
|
+
snapshotBuffer.clear();
|
|
1703
|
+
this.render({force: true, opaqueOnly: opaqueOnly});
|
|
1704
|
+
let color;
|
|
1705
|
+
let i;
|
|
1706
|
+
let j;
|
|
1707
|
+
let k;
|
|
1708
|
+
for (i = 0; i < len; i++) {
|
|
1709
|
+
j = i * 2;
|
|
1710
|
+
k = i * 4;
|
|
1711
|
+
color = snapshotBuffer.read(pixels[j], pixels[j + 1]);
|
|
1712
|
+
colors[k] = color[0];
|
|
1713
|
+
colors[k + 1] = color[1];
|
|
1714
|
+
colors[k + 2] = color[2];
|
|
1715
|
+
colors[k + 3] = color[3];
|
|
1716
|
+
}
|
|
1717
|
+
snapshotBuffer.unbind();
|
|
1718
|
+
imageDirty = true;
|
|
1719
|
+
};
|
|
1799
1720
|
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1721
|
+
/**
|
|
1722
|
+
* Enter snapshot mode.
|
|
1723
|
+
*
|
|
1724
|
+
* Switches rendering to a hidden snapshot canvas.
|
|
1725
|
+
*
|
|
1726
|
+
* Exit snapshot mode using endSnapshot().
|
|
1727
|
+
*/
|
|
1728
|
+
this.beginSnapshot = function (params = {}) {
|
|
1729
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1730
|
+
if (params.width && params.height) {
|
|
1731
|
+
snapshotBuffer.setSize([params.width, params.height]);
|
|
1732
|
+
}
|
|
1733
|
+
snapshotBuffer.bind();
|
|
1734
|
+
snapshotBuffer.clear();
|
|
1735
|
+
snapshotBound = true;
|
|
1736
|
+
};
|
|
1806
1737
|
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1738
|
+
/**
|
|
1739
|
+
* When in snapshot mode, renders a frame of the current Scene state to the snapshot canvas.
|
|
1740
|
+
*/
|
|
1741
|
+
this.renderSnapshot = function () {
|
|
1742
|
+
if (!snapshotBound) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1746
|
+
snapshotBuffer.clear();
|
|
1747
|
+
this.render({force: true, opaqueOnly: false});
|
|
1748
|
+
imageDirty = true;
|
|
1749
|
+
};
|
|
1750
|
+
|
|
1751
|
+
/**
|
|
1752
|
+
* When in snapshot mode, gets an image of the snapshot canvas.
|
|
1753
|
+
*
|
|
1754
|
+
* @private
|
|
1755
|
+
* @returns {String} The image data URI.
|
|
1756
|
+
*/
|
|
1757
|
+
this.readSnapshot = function (params) {
|
|
1758
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1759
|
+
return snapshotBuffer.readImage(params);
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
/**
|
|
1763
|
+
* Returns an HTMLCanvas containing an image of the snapshot canvas.
|
|
1764
|
+
*
|
|
1765
|
+
* - The HTMLCanvas has a CanvasRenderingContext2D.
|
|
1766
|
+
* - Expects the caller to draw more things on the HTMLCanvas (annotations etc).
|
|
1767
|
+
*
|
|
1768
|
+
* @returns {HTMLCanvasElement}
|
|
1769
|
+
*/
|
|
1770
|
+
this.readSnapshotAsCanvas = function () {
|
|
1771
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1772
|
+
return snapshotBuffer.readImageAsCanvas();
|
|
1773
|
+
};
|
|
1774
|
+
|
|
1775
|
+
/**
|
|
1776
|
+
* Exists snapshot mode.
|
|
1777
|
+
*
|
|
1778
|
+
* Switches rendering back to the main canvas.
|
|
1779
|
+
*/
|
|
1780
|
+
this.endSnapshot = function () {
|
|
1781
|
+
if (!snapshotBound) {
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1785
|
+
snapshotBuffer.unbind();
|
|
1786
|
+
snapshotBound = false;
|
|
1787
|
+
};
|
|
1825
1788
|
|
|
1826
1789
|
/**
|
|
1827
1790
|
* Destroys this renderer.
|