@xeokit/xeokit-sdk 2.6.91-renderers-refactor-v9 → 2.6.92
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 +44649 -13016
- package/dist/xeokit-sdk.es.js +44648 -13017
- package/dist/xeokit-sdk.es5.js +3499 -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/AngleMeasurementsPlugin/AngleMeasurement.js +21 -1
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.js +32 -6
- 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 +852 -248
- 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/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 -788
- 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 -29
- 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
|
normalFillTransparentBin.length = normalFillTransparentBinLen; // normalFillTransparentBin reused by renderDrawables calls, so needs to be truncated if necessary
|
|
971
728
|
const byDist = normalFillTransparentBin.map(d => ({ drawable: d, distSq: math.distVec3(d.origin || vec3_0, eye) }));
|
|
972
729
|
byDist.sort((a, b) => b.distSq - a.distSq);
|
|
@@ -1144,29 +901,11 @@ const Renderer = function (scene, options) {
|
|
|
1144
901
|
for (let ii = 0; ii < numVertexAttribs; ii++) {
|
|
1145
902
|
gl.disableVertexAttribArray(ii);
|
|
1146
903
|
}
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
const resetPickFrameCtx = (canvasPos, clipTransformDiv, camera, eye, projMatrix, viewMatrix, frameCtx) => {
|
|
1150
|
-
frameCtx.reset();
|
|
1151
|
-
frameCtx.backfaces = true;
|
|
1152
|
-
frameCtx.frontface = true; // "ccw"
|
|
1153
|
-
|
|
1154
|
-
frameCtx.viewParams.eye = eye;
|
|
1155
|
-
frameCtx.viewParams.projMatrix = projMatrix;
|
|
1156
|
-
frameCtx.viewParams.viewMatrix = viewMatrix;
|
|
1157
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(camera, gl.drawingBufferHeight);
|
|
1158
|
-
|
|
1159
|
-
const resolutionScale = scene.canvas.resolutionScale;
|
|
1160
|
-
frameCtx.pickClipPos = [
|
|
1161
|
-
canvasPos ? ( 2 * canvasPos[0] * resolutionScale / gl.drawingBufferWidth - 1) : 0,
|
|
1162
|
-
canvasPos ? (1 - 2 * canvasPos[1] * resolutionScale / gl.drawingBufferHeight) : 0
|
|
1163
|
-
];
|
|
1164
904
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
};
|
|
905
|
+
if (unbindOutputFrameBuffer) {
|
|
906
|
+
unbindOutputFrameBuffer(params.pass);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
1170
909
|
|
|
1171
910
|
/**
|
|
1172
911
|
* Picks an Entity.
|
|
@@ -1175,18 +914,11 @@ const Renderer = function (scene, options) {
|
|
|
1175
914
|
this.pick = (function () {
|
|
1176
915
|
|
|
1177
916
|
const tempVec3a = math.vec3();
|
|
1178
|
-
const tempVec3b = math.vec3();
|
|
1179
|
-
const tempVec4a = math.vec4();
|
|
1180
|
-
const tempVec4b = math.vec4();
|
|
1181
|
-
const tempVec4c = math.vec4();
|
|
1182
|
-
const tempVec4d = math.vec4();
|
|
1183
|
-
const tempVec4e = math.vec4();
|
|
1184
917
|
const tempMat4a = math.mat4();
|
|
1185
918
|
const tempMat4b = math.mat4();
|
|
1186
|
-
const tempMat4c = math.mat4();
|
|
1187
|
-
const tempMat4d = math.mat4();
|
|
1188
919
|
|
|
1189
|
-
const
|
|
920
|
+
const randomVec3 = math.vec3();
|
|
921
|
+
const up = math.vec3([0, 1, 0]);
|
|
1190
922
|
const _pickResult = new PickResult();
|
|
1191
923
|
|
|
1192
924
|
const nearAndFar = math.vec2();
|
|
@@ -1198,22 +930,16 @@ const Renderer = function (scene, options) {
|
|
|
1198
930
|
const worldSurfacePos = math.vec3();
|
|
1199
931
|
const worldSurfaceNormal = math.vec3();
|
|
1200
932
|
|
|
1201
|
-
const pickBuffer = new RenderBuffer(gl);
|
|
1202
|
-
pickBuffer.setSize([1, 1]);
|
|
1203
|
-
|
|
1204
|
-
const pickNormalBuffer = new RenderBuffer(gl, [gl.RGBA32I]);
|
|
1205
|
-
pickNormalBuffer.setSize([3, 3]);
|
|
1206
|
-
|
|
1207
933
|
return function (params, pickResult = _pickResult) {
|
|
1208
934
|
|
|
1209
935
|
pickResult.reset();
|
|
1210
936
|
|
|
1211
937
|
updateDrawlist();
|
|
1212
938
|
|
|
939
|
+
let look;
|
|
1213
940
|
let pickViewMatrix = null;
|
|
1214
941
|
let pickProjMatrix = null;
|
|
1215
942
|
let projection = null;
|
|
1216
|
-
const camera = scene.camera;
|
|
1217
943
|
|
|
1218
944
|
pickResult.pickSurface = params.pickSurface;
|
|
1219
945
|
|
|
@@ -1222,12 +948,12 @@ const Renderer = function (scene, options) {
|
|
|
1222
948
|
canvasPos[0] = params.canvasPos[0];
|
|
1223
949
|
canvasPos[1] = params.canvasPos[1];
|
|
1224
950
|
|
|
1225
|
-
pickViewMatrix = camera.viewMatrix;
|
|
1226
|
-
pickProjMatrix = camera.projMatrix;
|
|
1227
|
-
projection = camera.projection;
|
|
951
|
+
pickViewMatrix = scene.camera.viewMatrix;
|
|
952
|
+
pickProjMatrix = scene.camera.projMatrix;
|
|
953
|
+
projection = scene.camera.projection;
|
|
1228
954
|
|
|
1229
|
-
nearAndFar[0] = camera.project.near;
|
|
1230
|
-
nearAndFar[1] = camera.project.far;
|
|
955
|
+
nearAndFar[0] = scene.camera.project.near;
|
|
956
|
+
nearAndFar[1] = scene.camera.project.far;
|
|
1231
957
|
|
|
1232
958
|
pickResult.canvasPos = params.canvasPos;
|
|
1233
959
|
|
|
@@ -1239,37 +965,33 @@ const Renderer = function (scene, options) {
|
|
|
1239
965
|
if (params.matrix) {
|
|
1240
966
|
|
|
1241
967
|
pickViewMatrix = params.matrix;
|
|
1242
|
-
pickProjMatrix = camera.projMatrix;
|
|
1243
|
-
projection = camera.projection;
|
|
968
|
+
pickProjMatrix = scene.camera.projMatrix;
|
|
969
|
+
projection = scene.camera.projection;
|
|
1244
970
|
|
|
1245
|
-
nearAndFar[0] = camera.project.near;
|
|
1246
|
-
nearAndFar[1] = camera.project.far;
|
|
971
|
+
nearAndFar[0] = scene.camera.project.near;
|
|
972
|
+
nearAndFar[1] = scene.camera.project.far;
|
|
1247
973
|
|
|
1248
974
|
} else {
|
|
1249
975
|
|
|
1250
976
|
worldRayOrigin.set(params.origin || [0, 0, 0]);
|
|
1251
977
|
worldRayDir.set(params.direction || [0, 0, 1]);
|
|
1252
978
|
|
|
1253
|
-
|
|
1254
|
-
const up = tempVec3b;
|
|
979
|
+
look = math.addVec3(worldRayOrigin, worldRayDir, tempVec3a);
|
|
1255
980
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
math.cross3Vec3(up, worldRayDir, up);
|
|
1263
|
-
math.normalizeVec3(up, up);
|
|
1264
|
-
}
|
|
981
|
+
randomVec3[0] = Math.random();
|
|
982
|
+
randomVec3[1] = Math.random();
|
|
983
|
+
randomVec3[2] = Math.random();
|
|
984
|
+
|
|
985
|
+
math.normalizeVec3(randomVec3);
|
|
986
|
+
math.cross3Vec3(worldRayDir, randomVec3, up);
|
|
1265
987
|
|
|
1266
988
|
pickViewMatrix = math.lookAtMat4v(worldRayOrigin, look, up, tempMat4b);
|
|
1267
|
-
// pickProjMatrix = camera.projMatrix;
|
|
1268
|
-
pickProjMatrix = camera.ortho.matrix;
|
|
989
|
+
// pickProjMatrix = scene.camera.projMatrix;
|
|
990
|
+
pickProjMatrix = scene.camera.ortho.matrix;
|
|
1269
991
|
projection = "ortho";
|
|
1270
992
|
|
|
1271
|
-
nearAndFar[0] = camera.ortho.near;
|
|
1272
|
-
nearAndFar[1] = camera.ortho.far;
|
|
993
|
+
nearAndFar[0] = scene.camera.ortho.near;
|
|
994
|
+
nearAndFar[1] = scene.camera.ortho.far;
|
|
1273
995
|
|
|
1274
996
|
pickResult.origin = worldRayOrigin;
|
|
1275
997
|
pickResult.direction = worldRayDir;
|
|
@@ -1279,42 +1001,23 @@ const Renderer = function (scene, options) {
|
|
|
1279
1001
|
canvasPos[1] = canvas.clientHeight * 0.5;
|
|
1280
1002
|
}
|
|
1281
1003
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
gl.viewport(0, 0, 1, 1);
|
|
1291
|
-
gl.depthMask(true);
|
|
1292
|
-
gl.enable(gl.DEPTH_TEST);
|
|
1293
|
-
gl.disable(gl.CULL_FACE);
|
|
1294
|
-
gl.disable(gl.BLEND);
|
|
1295
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1296
|
-
|
|
1297
|
-
const includeEntityIds = params.includeEntityIds;
|
|
1298
|
-
const excludeEntityIds = params.excludeEntityIds;
|
|
1299
|
-
|
|
1300
|
-
const renderDrawables = function(drawables) {
|
|
1301
|
-
drawables.forEach(drawable => {
|
|
1302
|
-
if (!drawable.culled && drawable.visible && drawable.pickable && drawable.drawPickMesh // TODO: push this logic into drawable
|
|
1303
|
-
&& ((! includeEntityIds) || includeEntityIds[drawable.id])
|
|
1304
|
-
&& ((! excludeEntityIds) || (! excludeEntityIds[drawable.id]))) {
|
|
1305
|
-
drawable.drawPickMesh(frameCtx);
|
|
1004
|
+
for (let type in drawableTypeInfo) {
|
|
1005
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
1006
|
+
const drawableList = drawableTypeInfo[type].drawableList;
|
|
1007
|
+
for (let i = 0, len = drawableList.length; i < len; i++) {
|
|
1008
|
+
const drawable = drawableList[i];
|
|
1009
|
+
if (drawable.setPickMatrices) { // Eg. SceneModel, which needs pre-loading into texture
|
|
1010
|
+
drawable.setPickMatrices(pickViewMatrix, pickProjMatrix);
|
|
1011
|
+
}
|
|
1306
1012
|
}
|
|
1307
|
-
}
|
|
1308
|
-
};
|
|
1309
|
-
|
|
1310
|
-
renderDrawables(postCullDrawableList);
|
|
1311
|
-
if (uiDrawableList.length > 0) {
|
|
1312
|
-
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1313
|
-
renderDrawables(uiDrawableList);
|
|
1013
|
+
}
|
|
1314
1014
|
}
|
|
1315
1015
|
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1016
|
+
const pickBuffer = renderBufferManager.getRenderBuffer("pick", {size: [1, 1]});
|
|
1017
|
+
|
|
1018
|
+
pickBuffer.bind();
|
|
1019
|
+
|
|
1020
|
+
const pickable = gpuPickPickable(pickBuffer, canvasPos, pickViewMatrix, pickProjMatrix, params, pickResult);
|
|
1318
1021
|
|
|
1319
1022
|
if (!pickable) {
|
|
1320
1023
|
pickBuffer.unbind();
|
|
@@ -1334,21 +1037,7 @@ const Renderer = function (scene, options) {
|
|
|
1334
1037
|
|
|
1335
1038
|
if (pickable.canPickTriangle && pickable.canPickTriangle()) {
|
|
1336
1039
|
|
|
1337
|
-
|
|
1338
|
-
resetFrameCtx(1);
|
|
1339
|
-
// frameCtx.pickInvisible = !!params.pickInvisible;
|
|
1340
|
-
|
|
1341
|
-
gl.viewport(0, 0, 1, 1);
|
|
1342
|
-
gl.clearColor(0, 0, 0, 0);
|
|
1343
|
-
gl.enable(gl.DEPTH_TEST);
|
|
1344
|
-
gl.disable(gl.CULL_FACE);
|
|
1345
|
-
gl.disable(gl.BLEND);
|
|
1346
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1347
|
-
|
|
1348
|
-
pickable.drawPickTriangles(frameCtx);
|
|
1349
|
-
|
|
1350
|
-
pickResult.primIndex = 3 * pixelToInt(pickBuffer.read(0, 0)); // Convert from triangle number to first vertex in indices
|
|
1351
|
-
}
|
|
1040
|
+
gpuPickTriangle(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
1352
1041
|
|
|
1353
1042
|
pickable.pickTriangleSurface(pickViewMatrix, pickProjMatrix, projection, pickResult);
|
|
1354
1043
|
|
|
@@ -1358,84 +1047,255 @@ const Renderer = function (scene, options) {
|
|
|
1358
1047
|
|
|
1359
1048
|
if (pickable.canPickWorldPos && pickable.canPickWorldPos()) {
|
|
1360
1049
|
|
|
1361
|
-
|
|
1362
|
-
resetFrameCtx(1);
|
|
1363
|
-
frameCtx.viewParams.near = nearAndFar[0];
|
|
1364
|
-
frameCtx.viewParams.far = nearAndFar[1];
|
|
1050
|
+
gpuPickWorldPos(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult);
|
|
1365
1051
|
|
|
1366
|
-
|
|
1052
|
+
if (params.pickSurfaceNormal !== false) {
|
|
1053
|
+
gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
1054
|
+
}
|
|
1367
1055
|
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1056
|
+
pickResult.pickSurfacePrecision = false;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
pickBuffer.unbind();
|
|
1061
|
+
pickResult.entity = pickedEntity;
|
|
1062
|
+
return pickResult;
|
|
1063
|
+
};
|
|
1064
|
+
})();
|
|
1065
|
+
|
|
1066
|
+
function gpuPickPickable(pickBuffer, canvasPos, pickViewMatrix, pickProjMatrix, params, pickResult) {
|
|
1067
|
+
|
|
1068
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1069
|
+
|
|
1070
|
+
frameCtx.reset();
|
|
1071
|
+
frameCtx.backfaces = true;
|
|
1072
|
+
frameCtx.frontface = true; // "ccw"
|
|
1073
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1074
|
+
frameCtx.pickViewMatrix = pickViewMatrix;
|
|
1075
|
+
frameCtx.pickProjMatrix = pickProjMatrix;
|
|
1076
|
+
frameCtx.pickInvisible = !!params.pickInvisible;
|
|
1077
|
+
frameCtx.pickClipPos = [
|
|
1078
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1079
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
|
|
1080
|
+
];
|
|
1081
|
+
|
|
1082
|
+
gl.viewport(0, 0, 1, 1);
|
|
1083
|
+
gl.depthMask(true);
|
|
1084
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1085
|
+
gl.disable(gl.CULL_FACE);
|
|
1086
|
+
gl.disable(gl.BLEND);
|
|
1087
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1088
|
+
|
|
1089
|
+
const includeEntityIds = params.includeEntityIds;
|
|
1090
|
+
const excludeEntityIds = params.excludeEntityIds;
|
|
1091
|
+
|
|
1092
|
+
const renderDrawables = function(drawables) {
|
|
1093
|
+
for (let i = 0, len = drawables.length; i < len; i++) {
|
|
1094
|
+
const drawable = drawables[i];
|
|
1095
|
+
if (drawable.culled === true || drawable.visible === false) {
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
if (!drawable.drawPickMesh || (params.pickInvisible !== true && drawable.visible === false) || drawable.pickable === false) {
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
if (includeEntityIds && !includeEntityIds[drawable.id]) { // TODO: push this logic into drawable
|
|
1102
|
+
continue;
|
|
1103
|
+
}
|
|
1104
|
+
if (excludeEntityIds && excludeEntityIds[drawable.id]) {
|
|
1105
|
+
continue;
|
|
1106
|
+
}
|
|
1107
|
+
drawable.drawPickMesh(frameCtx);
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1374
1110
|
|
|
1375
|
-
|
|
1111
|
+
renderDrawables(postCullDrawableList);
|
|
1112
|
+
if (uiDrawableList.length > 0) {
|
|
1113
|
+
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1114
|
+
renderDrawables(uiDrawableList);
|
|
1115
|
+
}
|
|
1376
1116
|
|
|
1377
|
-
|
|
1117
|
+
const pix = pickBuffer.read(0, 0);
|
|
1118
|
+
const pickID = pix[0] + (pix[1] << 8) + (pix[2] << 16) + (pix[3] << 24);
|
|
1378
1119
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1120
|
+
if (pickID < 0) {
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1382
1123
|
|
|
1383
|
-
|
|
1124
|
+
const pickable = pickIDs.items[pickID];
|
|
1384
1125
|
|
|
1385
|
-
|
|
1126
|
+
return pickable;
|
|
1127
|
+
}
|
|
1386
1128
|
|
|
1387
|
-
|
|
1388
|
-
dst[0] = x;
|
|
1389
|
-
dst[1] = y;
|
|
1390
|
-
dst[2] = z;
|
|
1391
|
-
dst[3] = 1;
|
|
1392
|
-
math.transformVec4(pvMatInverse, dst, dst);
|
|
1393
|
-
return math.mulVec4Scalar(dst, 1 / dst[3]);
|
|
1394
|
-
};
|
|
1129
|
+
function gpuPickTriangle(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
1395
1130
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1131
|
+
if (!pickable.drawPickTriangles) {
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1398
1134
|
|
|
1399
|
-
|
|
1400
|
-
const worldPos = math.addVec3(world1, math.mulVec4Scalar(dir, screenZ, tempVec4d), tempVec4e);
|
|
1135
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1401
1136
|
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1137
|
+
frameCtx.reset();
|
|
1138
|
+
frameCtx.backfaces = true;
|
|
1139
|
+
frameCtx.frontface = true; // "ccw"
|
|
1140
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1141
|
+
frameCtx.pickViewMatrix = pickViewMatrix; // Can be null
|
|
1142
|
+
frameCtx.pickProjMatrix = pickProjMatrix; // Can be null
|
|
1143
|
+
// frameCtx.pickInvisible = !!params.pickInvisible;
|
|
1144
|
+
frameCtx.pickClipPos = [
|
|
1145
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1146
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
|
|
1147
|
+
];
|
|
1405
1148
|
|
|
1406
|
-
|
|
1149
|
+
gl.viewport(0, 0, 1, 1);
|
|
1407
1150
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1151
|
+
gl.clearColor(0, 0, 0, 0);
|
|
1152
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1153
|
+
gl.disable(gl.CULL_FACE);
|
|
1154
|
+
gl.disable(gl.BLEND);
|
|
1155
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1411
1156
|
|
|
1412
|
-
|
|
1157
|
+
pickable.drawPickTriangles(frameCtx);
|
|
1413
1158
|
|
|
1414
|
-
|
|
1415
|
-
gl.enable(gl.DEPTH_TEST);
|
|
1416
|
-
gl.disable(gl.CULL_FACE);
|
|
1417
|
-
gl.disable(gl.BLEND);
|
|
1418
|
-
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1419
|
-
gl.clearBufferiv(gl.COLOR, 0, new Int32Array([0, 0, 0, 0]));
|
|
1159
|
+
const pix = pickBuffer.read(0, 0);
|
|
1420
1160
|
|
|
1421
|
-
|
|
1161
|
+
let primIndex = pix[0] + (pix[1] * 256) + (pix[2] * 256 * 256) + (pix[3] * 256 * 256 * 256);
|
|
1422
1162
|
|
|
1423
|
-
|
|
1163
|
+
primIndex *= 3; // Convert from triangle number to first vertex in indices
|
|
1424
1164
|
|
|
1425
|
-
|
|
1165
|
+
pickResult.primIndex = primIndex;
|
|
1166
|
+
}
|
|
1426
1167
|
|
|
1427
|
-
|
|
1428
|
-
}
|
|
1168
|
+
const gpuPickWorldPos = (function () {
|
|
1429
1169
|
|
|
1430
|
-
|
|
1170
|
+
const tempVec4a = math.vec4();
|
|
1171
|
+
const tempVec4b = math.vec4();
|
|
1172
|
+
const tempVec4c = math.vec4();
|
|
1173
|
+
const tempVec4d = math.vec4();
|
|
1174
|
+
const tempVec4e = math.vec4();
|
|
1175
|
+
const tempMat4a = math.mat4();
|
|
1176
|
+
const tempMat4b = math.mat4();
|
|
1177
|
+
const tempMat4c = math.mat4();
|
|
1178
|
+
|
|
1179
|
+
return function (pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult) {
|
|
1180
|
+
|
|
1181
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1182
|
+
|
|
1183
|
+
frameCtx.reset();
|
|
1184
|
+
frameCtx.backfaces = true;
|
|
1185
|
+
frameCtx.frontface = true; // "ccw"
|
|
1186
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1187
|
+
frameCtx.pickViewMatrix = pickViewMatrix;
|
|
1188
|
+
frameCtx.pickProjMatrix = pickProjMatrix;
|
|
1189
|
+
frameCtx.pickZNear = nearAndFar[0];
|
|
1190
|
+
frameCtx.pickZFar = nearAndFar[1];
|
|
1191
|
+
frameCtx.pickElementsCount = pickable.pickElementsCount;
|
|
1192
|
+
frameCtx.pickElementsOffset = pickable.pickElementsOffset;
|
|
1193
|
+
frameCtx.pickClipPos = [
|
|
1194
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1195
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
|
|
1196
|
+
];
|
|
1197
|
+
|
|
1198
|
+
gl.viewport(0, 0, 1, 1);
|
|
1199
|
+
|
|
1200
|
+
gl.clearColor(0, 0, 0, 0);
|
|
1201
|
+
gl.depthMask(true);
|
|
1202
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1203
|
+
gl.disable(gl.CULL_FACE);
|
|
1204
|
+
gl.disable(gl.BLEND);
|
|
1205
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1206
|
+
|
|
1207
|
+
pickable.drawPickDepths(frameCtx); // Draw color-encoded fragment screen-space depths
|
|
1208
|
+
|
|
1209
|
+
const pix = pickBuffer.read(0, 0);
|
|
1210
|
+
|
|
1211
|
+
const screenZ = unpackDepth(pix); // Get screen-space Z at the given canvas coords
|
|
1212
|
+
|
|
1213
|
+
// Calculate clip space coordinates, which will be in range of x=[-1..1] and y=[-1..1], with y=(+1) at top
|
|
1214
|
+
const x = (canvasPos[0] - canvas.clientWidth / 2) / (canvas.clientWidth / 2);
|
|
1215
|
+
const y = -(canvasPos[1] - canvas.clientHeight / 2) / (canvas.clientHeight / 2);
|
|
1216
|
+
|
|
1217
|
+
const origin = pickable.origin;
|
|
1218
|
+
let pvMat;
|
|
1219
|
+
|
|
1220
|
+
if (origin) {
|
|
1221
|
+
const rtcPickViewMat = createRTCViewMat(pickViewMatrix, origin, tempMat4a);
|
|
1222
|
+
pvMat = math.mulMat4(pickProjMatrix, rtcPickViewMat, tempMat4b);
|
|
1223
|
+
|
|
1224
|
+
} else {
|
|
1225
|
+
pvMat = math.mulMat4(pickProjMatrix, pickViewMatrix, tempMat4b);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
const pvMatInverse = math.inverseMat4(pvMat, tempMat4c);
|
|
1229
|
+
|
|
1230
|
+
tempVec4a[0] = x;
|
|
1231
|
+
tempVec4a[1] = y;
|
|
1232
|
+
tempVec4a[2] = -1;
|
|
1233
|
+
tempVec4a[3] = 1;
|
|
1234
|
+
|
|
1235
|
+
let world1 = math.transformVec4(pvMatInverse, tempVec4a);
|
|
1236
|
+
world1 = math.mulVec4Scalar(world1, 1 / world1[3]);
|
|
1237
|
+
|
|
1238
|
+
tempVec4b[0] = x;
|
|
1239
|
+
tempVec4b[1] = y;
|
|
1240
|
+
tempVec4b[2] = 1;
|
|
1241
|
+
tempVec4b[3] = 1;
|
|
1242
|
+
|
|
1243
|
+
let world2 = math.transformVec4(pvMatInverse, tempVec4b);
|
|
1244
|
+
world2 = math.mulVec4Scalar(world2, 1 / world2[3]);
|
|
1245
|
+
|
|
1246
|
+
const dir = math.subVec3(world2, world1, tempVec4c);
|
|
1247
|
+
const worldPos = math.addVec3(world1, math.mulVec4Scalar(dir, screenZ, tempVec4d), tempVec4e);
|
|
1248
|
+
|
|
1249
|
+
if (origin) {
|
|
1250
|
+
math.addVec3(worldPos, origin);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
pickResult.worldPos = worldPos;
|
|
1254
|
+
}
|
|
1255
|
+
})();
|
|
1256
|
+
|
|
1257
|
+
function drawSnapInit(frameCtx) {
|
|
1258
|
+
frameCtx.snapPickLayerParams = [];
|
|
1259
|
+
frameCtx.snapPickLayerNumber = 0;
|
|
1260
|
+
|
|
1261
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
1262
|
+
|
|
1263
|
+
const drawable = postCullDrawableList[i];
|
|
1264
|
+
|
|
1265
|
+
if (drawable.drawSnapInit) {
|
|
1266
|
+
if (!drawable.culled && drawable.visible && drawable.pickable) {
|
|
1267
|
+
drawable.drawSnapInit(frameCtx);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return frameCtx.snapPickLayerParams;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
function drawSnap(frameCtx) {
|
|
1275
|
+
frameCtx.snapPickLayerParams = frameCtx.snapPickLayerParams || [];
|
|
1276
|
+
frameCtx.snapPickLayerNumber = frameCtx.snapPickLayerParams.length;
|
|
1277
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
1278
|
+
|
|
1279
|
+
const drawable = postCullDrawableList[i];
|
|
1280
|
+
|
|
1281
|
+
if (drawable.drawSnapInit) {
|
|
1282
|
+
if (drawable.drawSnap) {
|
|
1283
|
+
if (!drawable.culled && drawable.visible && drawable.pickable) {
|
|
1284
|
+
drawable.drawSnap(frameCtx);
|
|
1431
1285
|
}
|
|
1432
1286
|
}
|
|
1433
1287
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1288
|
+
}
|
|
1289
|
+
return frameCtx.snapPickLayerParams;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
function getClipPosX(pos, size) {
|
|
1293
|
+
return 2 * (pos / size) - 1;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
function getClipPosY(pos, size) {
|
|
1297
|
+
return 1 - 2 * (pos / size);
|
|
1298
|
+
}
|
|
1439
1299
|
|
|
1440
1300
|
/**
|
|
1441
1301
|
* @param {[number, number]} canvasPos
|
|
@@ -1449,18 +1309,6 @@ const Renderer = function (scene, options) {
|
|
|
1449
1309
|
|
|
1450
1310
|
const _pickResult = new PickResult();
|
|
1451
1311
|
|
|
1452
|
-
const getVertexPickBuffer = (function() {
|
|
1453
|
-
const cache = { };
|
|
1454
|
-
return (snapRadiusInPixels) => {
|
|
1455
|
-
if (! (snapRadiusInPixels in cache)) {
|
|
1456
|
-
const buf = new RenderBuffer(gl, [gl.RGBA32I, gl.RGBA32I, gl.RGBA8UI], true);
|
|
1457
|
-
buf.setSize([2 * snapRadiusInPixels + 1, 2 * snapRadiusInPixels + 1]);
|
|
1458
|
-
cache[snapRadiusInPixels] = buf;
|
|
1459
|
-
}
|
|
1460
|
-
return cache[snapRadiusInPixels];
|
|
1461
|
-
};
|
|
1462
|
-
})();
|
|
1463
|
-
|
|
1464
1312
|
return function (params, pickResult = _pickResult) {
|
|
1465
1313
|
|
|
1466
1314
|
const {canvasPos, origin, direction, snapRadius, snapToVertex, snapToEdge} = params;
|
|
@@ -1469,21 +1317,40 @@ const Renderer = function (scene, options) {
|
|
|
1469
1317
|
return this.pick({canvasPos, pickSurface: true});
|
|
1470
1318
|
}
|
|
1471
1319
|
|
|
1472
|
-
const
|
|
1320
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1321
|
+
|
|
1322
|
+
frameCtx.reset();
|
|
1323
|
+
frameCtx.backfaces = true;
|
|
1324
|
+
frameCtx.frontface = true; // "ccw"
|
|
1325
|
+
frameCtx.pickZNear = scene.camera.project.near;
|
|
1326
|
+
frameCtx.pickZFar = scene.camera.project.far;
|
|
1327
|
+
|
|
1473
1328
|
const snapRadiusInPixels = snapRadius || 30;
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1329
|
+
|
|
1330
|
+
const vertexPickBuffer = renderBufferManager.getRenderBuffer(
|
|
1331
|
+
`uniquePickColors-aabs-${snapRadiusInPixels}`,
|
|
1332
|
+
{
|
|
1333
|
+
depthTexture: true,
|
|
1334
|
+
size: [
|
|
1335
|
+
2 * snapRadiusInPixels + 1,
|
|
1336
|
+
2 * snapRadiusInPixels + 1,
|
|
1337
|
+
]
|
|
1338
|
+
}
|
|
1339
|
+
);
|
|
1340
|
+
|
|
1341
|
+
frameCtx.snapVectorA = [
|
|
1342
|
+
canvasPos ? getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth) : 0,
|
|
1343
|
+
canvasPos ? getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight) : 0,
|
|
1344
|
+
];
|
|
1345
|
+
|
|
1346
|
+
frameCtx.snapInvVectorAB = [
|
|
1347
|
+
gl.drawingBufferWidth / (2 * snapRadiusInPixels),
|
|
1348
|
+
gl.drawingBufferHeight / (2 * snapRadiusInPixels),
|
|
1349
|
+
];
|
|
1482
1350
|
|
|
1483
1351
|
// Bind and clear the snap render target
|
|
1484
1352
|
|
|
1485
|
-
|
|
1486
|
-
vertexPickBuffer.bind();
|
|
1353
|
+
vertexPickBuffer.bind(gl.RGBA32I, gl.RGBA32I, gl.RGBA8UI);
|
|
1487
1354
|
gl.viewport(0, 0, vertexPickBuffer.size[0], vertexPickBuffer.size[1]);
|
|
1488
1355
|
gl.enable(gl.DEPTH_TEST);
|
|
1489
1356
|
gl.frontFace(gl.CCW);
|
|
@@ -1496,59 +1363,64 @@ const Renderer = function (scene, options) {
|
|
|
1496
1363
|
gl.clearBufferiv(gl.COLOR, 1, new Int32Array([0, 0, 0, 0]));
|
|
1497
1364
|
gl.clearBufferuiv(gl.COLOR, 2, new Uint32Array([0, 0, 0, 0]));
|
|
1498
1365
|
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
frameCtx.
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1366
|
+
//////////////////////////////////
|
|
1367
|
+
// Set view and proj mats for VBO renderers
|
|
1368
|
+
///////////////////////////////////////
|
|
1369
|
+
|
|
1370
|
+
frameCtx.pickViewMatrix = (canvasPos
|
|
1371
|
+
? scene.camera.viewMatrix
|
|
1372
|
+
: math.lookAtMat4v(
|
|
1373
|
+
origin,
|
|
1374
|
+
math.addVec3(origin, direction, math.vec3()),
|
|
1375
|
+
math.vec3([0, 1, 0]),
|
|
1376
|
+
math.mat4()));
|
|
1377
|
+
|
|
1378
|
+
const pickProjMatrix = scene.camera.projMatrix;
|
|
1379
|
+
|
|
1380
|
+
for (let type in drawableTypeInfo) {
|
|
1381
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
1382
|
+
const drawableList = drawableTypeInfo[type].drawableList;
|
|
1383
|
+
for (let i = 0, len = drawableList.length; i < len; i++) {
|
|
1384
|
+
const drawable = drawableList[i];
|
|
1385
|
+
if (drawable.setPickMatrices) { // Eg. SceneModel, which needs pre-loading into texture
|
|
1386
|
+
drawable.setPickMatrices(frameCtx.pickViewMatrix, pickProjMatrix);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1507
1389
|
}
|
|
1508
|
-
}
|
|
1390
|
+
}
|
|
1509
1391
|
|
|
1510
|
-
|
|
1392
|
+
// a) init z-buffer
|
|
1393
|
+
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
|
|
1394
|
+
const layerParamsSurface = drawSnapInit(frameCtx);
|
|
1511
1395
|
|
|
1512
1396
|
// b) snap-pick
|
|
1513
|
-
|
|
1397
|
+
const layerParamsSnap = []
|
|
1398
|
+
frameCtx.snapPickLayerParams = layerParamsSnap;
|
|
1514
1399
|
|
|
1515
1400
|
gl.depthMask(false);
|
|
1516
1401
|
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
|
|
1517
1402
|
|
|
1518
|
-
|
|
1519
|
-
frameCtx.snapMode =
|
|
1520
|
-
frameCtx
|
|
1521
|
-
postCullDrawableList.forEach(drawable => {
|
|
1522
|
-
if (!drawable.culled && drawable.visible && drawable.pickable && drawable.drawSnap) {
|
|
1523
|
-
drawable.drawSnap(frameCtx);
|
|
1524
|
-
}
|
|
1525
|
-
});
|
|
1526
|
-
};
|
|
1403
|
+
if (snapToVertex && snapToEdge) {
|
|
1404
|
+
frameCtx.snapMode = "edge";
|
|
1405
|
+
drawSnap(frameCtx);
|
|
1527
1406
|
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1407
|
+
frameCtx.snapMode = "vertex";
|
|
1408
|
+
frameCtx.snapPickLayerNumber++;
|
|
1409
|
+
|
|
1410
|
+
drawSnap(frameCtx);
|
|
1411
|
+
} else {
|
|
1412
|
+
frameCtx.snapMode = snapToVertex ? "vertex" : "edge";
|
|
1413
|
+
|
|
1414
|
+
drawSnap(frameCtx);
|
|
1533
1415
|
}
|
|
1534
1416
|
|
|
1535
1417
|
gl.depthMask(true);
|
|
1536
1418
|
|
|
1537
|
-
const layerParamsSnap = frameCtx.snapPickLayerParams;
|
|
1538
|
-
|
|
1539
1419
|
// Read and decode the snapped coordinates
|
|
1540
|
-
const readSnapPickBuffer = (source, arrayType, glType) => {
|
|
1541
|
-
const w = vertexPickBuffer.buffer.width;
|
|
1542
|
-
const h = vertexPickBuffer.buffer.height;
|
|
1543
|
-
const pix = new arrayType(4 * w * h);
|
|
1544
|
-
gl.readBuffer(source);
|
|
1545
|
-
gl.readPixels(0, 0, w, h, gl.RGBA_INTEGER, glType, pix, 0);
|
|
1546
|
-
return pix;
|
|
1547
|
-
};
|
|
1548
1420
|
|
|
1549
|
-
const snapPickResultArray
|
|
1550
|
-
const snapPickNormalResultArray =
|
|
1551
|
-
const snapPickIdResultArray
|
|
1421
|
+
const snapPickResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.INT, Int32Array, 4);
|
|
1422
|
+
const snapPickNormalResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.INT, Int32Array, 4, 1);
|
|
1423
|
+
const snapPickIdResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.UNSIGNED_INT, Uint32Array, 4, 2);
|
|
1552
1424
|
|
|
1553
1425
|
vertexPickBuffer.unbind();
|
|
1554
1426
|
|
|
@@ -1567,76 +1439,195 @@ const Renderer = function (scene, options) {
|
|
|
1567
1439
|
|
|
1568
1440
|
if (pickResultMiddleXY[3] !== 0) {
|
|
1569
1441
|
const pickedLayerParmasSurface = layerParamsSurface[Math.abs(pickResultMiddleXY[3]) % layerParamsSurface.length];
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1442
|
+
const origin = pickedLayerParmasSurface.origin;
|
|
1443
|
+
const scale = pickedLayerParmasSurface.coordinateScale;
|
|
1444
|
+
worldPos = [
|
|
1445
|
+
pickResultMiddleXY[0] * scale[0] + origin[0],
|
|
1446
|
+
pickResultMiddleXY[1] * scale[1] + origin[1],
|
|
1447
|
+
pickResultMiddleXY[2] * scale[2] + origin[2],
|
|
1448
|
+
];
|
|
1449
|
+
worldNormal = math.normalizeVec3([
|
|
1450
|
+
pickNormalResultMiddleXY[0] / math.MAX_INT,
|
|
1451
|
+
pickNormalResultMiddleXY[1] / math.MAX_INT,
|
|
1452
|
+
pickNormalResultMiddleXY[2] / math.MAX_INT,
|
|
1453
|
+
]);
|
|
1454
|
+
|
|
1455
|
+
const pickID =
|
|
1456
|
+
pickPickableResultMiddleXY[0]
|
|
1457
|
+
+ (pickPickableResultMiddleXY[1] << 8)
|
|
1458
|
+
+ (pickPickableResultMiddleXY[2] << 16)
|
|
1459
|
+
+ (pickPickableResultMiddleXY[3] << 24);
|
|
1460
|
+
|
|
1461
|
+
pickable = pickIDs.items[pickID];
|
|
1574
1462
|
}
|
|
1575
1463
|
|
|
1576
1464
|
// result 2) hi-precision snapped (to vertex/edge) world position
|
|
1577
1465
|
|
|
1578
|
-
|
|
1466
|
+
let snapPickResult = [];
|
|
1467
|
+
|
|
1579
1468
|
for (let i = 0; i < snapPickResultArray.length; i += 4) {
|
|
1580
|
-
|
|
1581
|
-
if (layerNumber > 0) {
|
|
1469
|
+
if (snapPickResultArray[i + 3] > 0) {
|
|
1582
1470
|
const pixelNumber = Math.floor(i / 4);
|
|
1583
1471
|
const w = vertexPickBuffer.size[0];
|
|
1584
1472
|
const x = pixelNumber % w - Math.floor(w / 2);
|
|
1585
1473
|
const y = Math.floor(pixelNumber / w) - Math.floor(w / 2);
|
|
1474
|
+
const dist = (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
|
1586
1475
|
snapPickResult.push({
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1476
|
+
x,
|
|
1477
|
+
y,
|
|
1478
|
+
dist,
|
|
1479
|
+
isVertex: snapToVertex && snapToEdge ? snapPickResultArray[i + 3] > layerParamsSnap.length / 2 : snapToVertex,
|
|
1480
|
+
result: [
|
|
1481
|
+
snapPickResultArray[i + 0],
|
|
1482
|
+
snapPickResultArray[i + 1],
|
|
1483
|
+
snapPickResultArray[i + 2],
|
|
1484
|
+
snapPickResultArray[i + 3],
|
|
1485
|
+
],
|
|
1486
|
+
normal: [
|
|
1487
|
+
snapPickNormalResultArray[i + 0],
|
|
1488
|
+
snapPickNormalResultArray[i + 1],
|
|
1489
|
+
snapPickNormalResultArray[i + 2],
|
|
1490
|
+
snapPickNormalResultArray[i + 3],
|
|
1491
|
+
],
|
|
1492
|
+
id: [
|
|
1493
|
+
snapPickIdResultArray[i + 0],
|
|
1494
|
+
snapPickIdResultArray[i + 1],
|
|
1495
|
+
snapPickIdResultArray[i + 2],
|
|
1496
|
+
snapPickIdResultArray[i + 3],
|
|
1497
|
+
]
|
|
1592
1498
|
});
|
|
1593
1499
|
}
|
|
1594
1500
|
}
|
|
1595
1501
|
|
|
1596
|
-
|
|
1502
|
+
let snappedWorldPos = null;
|
|
1503
|
+
let snappedWorldNormal = null;
|
|
1504
|
+
let snappedPickable = null;
|
|
1505
|
+
let snapType = null;
|
|
1597
1506
|
|
|
1598
1507
|
if (snapPickResult.length > 0) {
|
|
1599
|
-
//
|
|
1600
|
-
|
|
1601
|
-
|
|
1508
|
+
// vertex snap first, then edge snap
|
|
1509
|
+
snapPickResult.sort((a, b) => {
|
|
1510
|
+
if (a.isVertex !== b.isVertex) {
|
|
1511
|
+
return a.isVertex ? -1 : 1;
|
|
1512
|
+
} else {
|
|
1513
|
+
return a.dist - b.dist;
|
|
1514
|
+
}
|
|
1515
|
+
});
|
|
1516
|
+
|
|
1517
|
+
snapType = snapPickResult[0].isVertex ? "vertex" : "edge";
|
|
1518
|
+
const snapPick = snapPickResult[0].result;
|
|
1519
|
+
const snapPickNormal = snapPickResult[0].normal;
|
|
1520
|
+
const snapPickId = snapPickResult[0].id;
|
|
1521
|
+
|
|
1602
1522
|
const pickedLayerParmas = layerParamsSnap[snapPick[3]];
|
|
1603
|
-
const snappedWorldPos = toWorldPos(snapPick, pickedLayerParmas.origin, pickedLayerParmas.coordinateScale);
|
|
1604
|
-
const snappedCanvasPos = camera.projectWorldPos(snappedWorldPos);
|
|
1605
|
-
|
|
1606
|
-
pickResult.reset();
|
|
1607
|
-
pickResult.snappedToEdge = !res.isVertex;
|
|
1608
|
-
pickResult.snappedToVertex = res.isVertex;
|
|
1609
|
-
pickResult.worldPos = snappedWorldPos;
|
|
1610
|
-
pickResult.worldNormal = toWorldNormal(res.normal);
|
|
1611
|
-
pickResult.entity = getPickedEntity(pickIDs.items[pixelToInt(res.id)]);
|
|
1612
|
-
pickResult.canvasPos = canvasPos || (worldPos && camera.projectWorldPos(worldPos)) || snappedCanvasPos;
|
|
1613
|
-
pickResult.snappedCanvasPos = snappedCanvasPos;
|
|
1614
|
-
return pickResult;
|
|
1615
|
-
|
|
1616
|
-
} else if (worldPos) {
|
|
1617
|
-
|
|
1618
|
-
pickResult.reset();
|
|
1619
|
-
pickResult.snappedToEdge = false;
|
|
1620
|
-
pickResult.snappedToVertex = false;
|
|
1621
|
-
pickResult.worldPos = worldPos;
|
|
1622
|
-
pickResult.worldNormal = worldNormal;
|
|
1623
|
-
pickResult.entity = getPickedEntity(pickable);
|
|
1624
|
-
pickResult.canvasPos = canvasPos || camera.projectWorldPos(worldPos);
|
|
1625
|
-
pickResult.snappedCanvasPos = canvasPos;
|
|
1626
|
-
return pickResult;
|
|
1627
1523
|
|
|
1628
|
-
|
|
1524
|
+
const origin = pickedLayerParmas.origin;
|
|
1525
|
+
const scale = pickedLayerParmas.coordinateScale;
|
|
1526
|
+
|
|
1527
|
+
snappedWorldNormal = math.normalizeVec3([
|
|
1528
|
+
snapPickNormal[0] / math.MAX_INT,
|
|
1529
|
+
snapPickNormal[1] / math.MAX_INT,
|
|
1530
|
+
snapPickNormal[2] / math.MAX_INT,
|
|
1531
|
+
]);
|
|
1532
|
+
|
|
1533
|
+
snappedWorldPos = [
|
|
1534
|
+
snapPick[0] * scale[0] + origin[0],
|
|
1535
|
+
snapPick[1] * scale[1] + origin[1],
|
|
1536
|
+
snapPick[2] * scale[2] + origin[2],
|
|
1537
|
+
];
|
|
1538
|
+
|
|
1539
|
+
snappedPickable = pickIDs.items[
|
|
1540
|
+
snapPickId[0]
|
|
1541
|
+
+ (snapPickId[1] << 8)
|
|
1542
|
+
+ (snapPickId[2] << 16)
|
|
1543
|
+
+ (snapPickId[3] << 24)
|
|
1544
|
+
];
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
if (null === worldPos && null == snappedWorldPos) { // If neither regular pick or snap pick, return null
|
|
1629
1548
|
return null;
|
|
1630
1549
|
}
|
|
1550
|
+
|
|
1551
|
+
let snappedCanvasPos = null;
|
|
1552
|
+
|
|
1553
|
+
if (null !== snappedWorldPos) {
|
|
1554
|
+
snappedCanvasPos = scene.camera.projectWorldPos(snappedWorldPos);
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
const snappedEntity = (snappedPickable && snappedPickable.delegatePickedEntity) ? snappedPickable.delegatePickedEntity() : snappedPickable;
|
|
1558
|
+
if (!snappedEntity && pickable) {
|
|
1559
|
+
pickable = pickable.delegatePickedEntity ? pickable.delegatePickedEntity() : pickable;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
pickResult.reset();
|
|
1563
|
+
pickResult.snappedToEdge = (snapType === "edge");
|
|
1564
|
+
pickResult.snappedToVertex = (snapType === "vertex");
|
|
1565
|
+
pickResult.worldPos = snappedWorldPos || worldPos;
|
|
1566
|
+
pickResult.worldNormal = snappedWorldNormal || worldNormal;
|
|
1567
|
+
pickResult.entity = snappedEntity || pickable;
|
|
1568
|
+
pickResult.canvasPos = canvasPos || scene.camera.projectWorldPos(worldPos || snappedWorldPos);
|
|
1569
|
+
pickResult.snappedCanvasPos = snappedCanvasPos || canvasPos;
|
|
1570
|
+
|
|
1571
|
+
return pickResult;
|
|
1631
1572
|
};
|
|
1632
1573
|
})();
|
|
1633
1574
|
|
|
1575
|
+
function unpackDepth(depthZ) {
|
|
1576
|
+
const vec = [depthZ[0] / 256.0, depthZ[1] / 256.0, depthZ[2] / 256.0, depthZ[3] / 256.0];
|
|
1577
|
+
const bitShift = [1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0];
|
|
1578
|
+
return math.dotVec4(vec, bitShift);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
1582
|
+
|
|
1583
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
1584
|
+
|
|
1585
|
+
frameCtx.reset();
|
|
1586
|
+
frameCtx.backfaces = true;
|
|
1587
|
+
frameCtx.frontface = true; // "ccw"
|
|
1588
|
+
frameCtx.pickOrigin = pickResult.origin;
|
|
1589
|
+
frameCtx.pickViewMatrix = pickViewMatrix;
|
|
1590
|
+
frameCtx.pickProjMatrix = pickProjMatrix;
|
|
1591
|
+
frameCtx.pickClipPos = [
|
|
1592
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
1593
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
|
|
1594
|
+
];
|
|
1595
|
+
|
|
1596
|
+
const pickNormalBuffer = renderBufferManager.getRenderBuffer("pick-normal", {size: [3, 3]});
|
|
1597
|
+
|
|
1598
|
+
pickNormalBuffer.bind(gl.RGBA32I);
|
|
1599
|
+
|
|
1600
|
+
gl.viewport(0, 0, pickNormalBuffer.size[0], pickNormalBuffer.size[1]);
|
|
1601
|
+
|
|
1602
|
+
gl.enable(gl.DEPTH_TEST);
|
|
1603
|
+
gl.disable(gl.CULL_FACE);
|
|
1604
|
+
gl.disable(gl.BLEND);
|
|
1605
|
+
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
1606
|
+
gl.clearBufferiv(gl.COLOR, 0, new Int32Array([0, 0, 0, 0]));
|
|
1607
|
+
|
|
1608
|
+
pickable.drawPickNormals(frameCtx); // Draw color-encoded fragment World-space normals
|
|
1609
|
+
|
|
1610
|
+
const pix = pickNormalBuffer.read(1, 1, gl.RGBA_INTEGER, gl.INT, Int32Array, 4);
|
|
1611
|
+
|
|
1612
|
+
pickNormalBuffer.unbind();
|
|
1613
|
+
|
|
1614
|
+
const worldNormal = [
|
|
1615
|
+
pix[0] / math.MAX_INT,
|
|
1616
|
+
pix[1] / math.MAX_INT,
|
|
1617
|
+
pix[2] / math.MAX_INT,
|
|
1618
|
+
];
|
|
1619
|
+
|
|
1620
|
+
math.normalizeVec3(worldNormal);
|
|
1621
|
+
|
|
1622
|
+
pickResult.worldNormal = worldNormal;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1634
1625
|
/**
|
|
1635
1626
|
* Adds a {@link Marker} for occlusion testing.
|
|
1636
1627
|
* @param marker
|
|
1637
1628
|
*/
|
|
1638
1629
|
this.addMarker = function (marker) {
|
|
1639
|
-
this._occlusionTester = this._occlusionTester || new OcclusionTester(scene);
|
|
1630
|
+
this._occlusionTester = this._occlusionTester || new OcclusionTester(scene, renderBufferManager);
|
|
1640
1631
|
this._occlusionTester.addMarker(marker);
|
|
1641
1632
|
scene.occlusionTestCountdown = 0;
|
|
1642
1633
|
};
|
|
@@ -1667,17 +1658,11 @@ const Renderer = function (scene, options) {
|
|
|
1667
1658
|
|
|
1668
1659
|
updateDrawlist();
|
|
1669
1660
|
|
|
1670
|
-
|
|
1671
|
-
if (readPixelBuf) {
|
|
1672
|
-
readPixelBuf.setSize([gl.drawingBufferWidth, gl.drawingBufferHeight]);
|
|
1673
|
-
readPixelBuf.bind();
|
|
1674
|
-
}
|
|
1661
|
+
this._occlusionTester.bindRenderBuf();
|
|
1675
1662
|
|
|
1676
1663
|
frameCtx.reset();
|
|
1677
1664
|
frameCtx.backfaces = true;
|
|
1678
1665
|
frameCtx.frontface = true; // "ccw"
|
|
1679
|
-
frameCtx.viewParams = getSceneCameraViewParams();
|
|
1680
|
-
frameCtx.nearPlaneHeight = getNearPlaneHeight(scene.camera, gl.drawingBufferHeight);
|
|
1681
1666
|
|
|
1682
1667
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
1683
1668
|
gl.clearColor(0, 0, 0, 0);
|
|
@@ -1686,143 +1671,121 @@ const Renderer = function (scene, options) {
|
|
|
1686
1671
|
gl.disable(gl.BLEND);
|
|
1687
1672
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1688
1673
|
|
|
1689
|
-
postCullDrawableList.forEach(drawable => {
|
|
1690
|
-
if (!drawable.culled && drawable.visible && drawable.pickable && drawable.drawOcclusion) { // TODO: Option to exclude transparent?
|
|
1691
|
-
drawable.drawOcclusion(frameCtx);
|
|
1692
|
-
}
|
|
1693
|
-
});
|
|
1694
1674
|
|
|
1695
|
-
|
|
1675
|
+
for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
|
|
1676
|
+
|
|
1677
|
+
const drawable = postCullDrawableList[i];
|
|
1678
|
+
|
|
1679
|
+
if (!drawable.drawOcclusion || drawable.culled === true || drawable.visible === false || drawable.pickable === false) { // TODO: Option to exclude transparent?
|
|
1680
|
+
continue;
|
|
1681
|
+
}
|
|
1696
1682
|
|
|
1697
|
-
|
|
1698
|
-
const resolutionScale = scene.canvas.resolutionScale;
|
|
1699
|
-
this._occlusionTester.doOcclusionTest( // Updates Marker "visible" properties
|
|
1700
|
-
(x, y) => readPixelBuf.read(Math.round(resolutionScale * x), Math.round(resolutionScale * y)));
|
|
1701
|
-
readPixelBuf.unbind();
|
|
1683
|
+
drawable.drawOcclusion(frameCtx);
|
|
1702
1684
|
}
|
|
1685
|
+
|
|
1686
|
+
this._occlusionTester.drawMarkers(frameCtx);
|
|
1687
|
+
this._occlusionTester.doOcclusionTest(); // Updates Marker "visible" properties
|
|
1688
|
+
this._occlusionTester.unbindRenderBuf();
|
|
1703
1689
|
}
|
|
1704
1690
|
};
|
|
1705
1691
|
|
|
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
|
-
/**
|
|
1738
|
-
* Enter snapshot mode.
|
|
1739
|
-
*
|
|
1740
|
-
* Switches rendering to a hidden snapshot canvas.
|
|
1741
|
-
*
|
|
1742
|
-
* Exit snapshot mode using endSnapshot().
|
|
1743
|
-
*/
|
|
1744
|
-
beginSnapshot: () => {
|
|
1745
|
-
snapshotBuffer.setSize([gl.drawingBufferWidth, gl.drawingBufferHeight]);
|
|
1746
|
-
snapshotBuffer.bind();
|
|
1747
|
-
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
1748
|
-
snapshotBound = true;
|
|
1749
|
-
},
|
|
1750
|
-
|
|
1751
|
-
/**
|
|
1752
|
-
* Returns an HTMLCanvas containing an image of the snapshot canvas.
|
|
1753
|
-
*
|
|
1754
|
-
* - The HTMLCanvas has a CanvasRenderingContext2D.
|
|
1755
|
-
* - Expects the caller to draw more things on the HTMLCanvas (annotations etc).
|
|
1756
|
-
*
|
|
1757
|
-
* @returns {HTMLCanvasElement}
|
|
1758
|
-
*/
|
|
1759
|
-
renderSnapshotToCanvas: () => {
|
|
1760
|
-
const width = snapshotBuffer.buffer.width;
|
|
1761
|
-
const height = snapshotBuffer.buffer.height;
|
|
1762
|
-
|
|
1763
|
-
if ((! snapshotCanvas) || (snapshotCanvas.width !== width) || (snapshotCanvas.height !== height)) {
|
|
1764
|
-
snapshotCanvas = (function() {
|
|
1765
|
-
const canvas = document.createElement('canvas');
|
|
1766
|
-
const context = canvas.getContext('2d');
|
|
1767
|
-
canvas.width = width;
|
|
1768
|
-
canvas.height = height;
|
|
1769
|
-
const pixelData = new Uint8Array(width * height * 4);
|
|
1770
|
-
const imageData = context.createImageData(width, height);
|
|
1771
|
-
|
|
1772
|
-
return {
|
|
1773
|
-
width: width,
|
|
1774
|
-
height: height,
|
|
1775
|
-
getUpdatedCanvas: () => {
|
|
1776
|
-
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
|
|
1777
|
-
|
|
1778
|
-
// flip verically
|
|
1779
|
-
const halfHeight = Math.floor(height / 2);
|
|
1780
|
-
const bytesPerRow = width * 4;
|
|
1781
|
-
const temp = new Uint8Array(bytesPerRow);
|
|
1782
|
-
for (let y = 0; y < halfHeight; ++y) {
|
|
1783
|
-
const topOffset = y * bytesPerRow;
|
|
1784
|
-
const bottomOffset = (height - y - 1) * bytesPerRow;
|
|
1785
|
-
temp.set(pixelData.subarray(topOffset, topOffset + bytesPerRow));
|
|
1786
|
-
pixelData.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
|
|
1787
|
-
pixelData.set(temp, bottomOffset);
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
imageData.data.set(pixelData);
|
|
1791
|
-
|
|
1792
|
-
context.resetTransform(); // Prevents strange scale-accumulation effect with html2canvas
|
|
1793
|
-
context.putImageData(imageData, 0, 0);
|
|
1794
|
-
|
|
1795
|
-
return canvas;
|
|
1796
|
-
}
|
|
1797
|
-
};
|
|
1798
|
-
})();
|
|
1799
|
-
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Read pixels from the renderer's current output. Performs a force-render first.
|
|
1694
|
+
* @param pixels
|
|
1695
|
+
* @param colors
|
|
1696
|
+
* @param len
|
|
1697
|
+
* @param opaqueOnly
|
|
1698
|
+
* @private
|
|
1699
|
+
*/
|
|
1700
|
+
this.readPixels = function (pixels, colors, len, opaqueOnly) {
|
|
1701
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1702
|
+
snapshotBuffer.bind();
|
|
1703
|
+
snapshotBuffer.clear();
|
|
1704
|
+
this.render({force: true, opaqueOnly: opaqueOnly});
|
|
1705
|
+
let color;
|
|
1706
|
+
let i;
|
|
1707
|
+
let j;
|
|
1708
|
+
let k;
|
|
1709
|
+
for (i = 0; i < len; i++) {
|
|
1710
|
+
j = i * 2;
|
|
1711
|
+
k = i * 4;
|
|
1712
|
+
color = snapshotBuffer.read(pixels[j], pixels[j + 1]);
|
|
1713
|
+
colors[k] = color[0];
|
|
1714
|
+
colors[k + 1] = color[1];
|
|
1715
|
+
colors[k + 2] = color[2];
|
|
1716
|
+
colors[k + 3] = color[3];
|
|
1717
|
+
}
|
|
1718
|
+
snapshotBuffer.unbind();
|
|
1719
|
+
imageDirty = true;
|
|
1720
|
+
};
|
|
1800
1721
|
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1722
|
+
/**
|
|
1723
|
+
* Enter snapshot mode.
|
|
1724
|
+
*
|
|
1725
|
+
* Switches rendering to a hidden snapshot canvas.
|
|
1726
|
+
*
|
|
1727
|
+
* Exit snapshot mode using endSnapshot().
|
|
1728
|
+
*/
|
|
1729
|
+
this.beginSnapshot = function (params = {}) {
|
|
1730
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1731
|
+
if (params.width && params.height) {
|
|
1732
|
+
snapshotBuffer.setSize([params.width, params.height]);
|
|
1733
|
+
}
|
|
1734
|
+
snapshotBuffer.bind();
|
|
1735
|
+
snapshotBuffer.clear();
|
|
1736
|
+
snapshotBound = true;
|
|
1737
|
+
};
|
|
1807
1738
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1739
|
+
/**
|
|
1740
|
+
* When in snapshot mode, renders a frame of the current Scene state to the snapshot canvas.
|
|
1741
|
+
*/
|
|
1742
|
+
this.renderSnapshot = function () {
|
|
1743
|
+
if (!snapshotBound) {
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1747
|
+
snapshotBuffer.clear();
|
|
1748
|
+
this.render({force: true, opaqueOnly: false});
|
|
1749
|
+
imageDirty = true;
|
|
1750
|
+
};
|
|
1751
|
+
|
|
1752
|
+
/**
|
|
1753
|
+
* When in snapshot mode, gets an image of the snapshot canvas.
|
|
1754
|
+
*
|
|
1755
|
+
* @private
|
|
1756
|
+
* @returns {String} The image data URI.
|
|
1757
|
+
*/
|
|
1758
|
+
this.readSnapshot = function (params) {
|
|
1759
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1760
|
+
return snapshotBuffer.readImage(params);
|
|
1761
|
+
};
|
|
1762
|
+
|
|
1763
|
+
/**
|
|
1764
|
+
* Returns an HTMLCanvas containing an image of the snapshot canvas.
|
|
1765
|
+
*
|
|
1766
|
+
* - The HTMLCanvas has a CanvasRenderingContext2D.
|
|
1767
|
+
* - Expects the caller to draw more things on the HTMLCanvas (annotations etc).
|
|
1768
|
+
*
|
|
1769
|
+
* @returns {HTMLCanvasElement}
|
|
1770
|
+
*/
|
|
1771
|
+
this.readSnapshotAsCanvas = function () {
|
|
1772
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1773
|
+
return snapshotBuffer.readImageAsCanvas();
|
|
1774
|
+
};
|
|
1775
|
+
|
|
1776
|
+
/**
|
|
1777
|
+
* Exists snapshot mode.
|
|
1778
|
+
*
|
|
1779
|
+
* Switches rendering back to the main canvas.
|
|
1780
|
+
*/
|
|
1781
|
+
this.endSnapshot = function () {
|
|
1782
|
+
if (!snapshotBound) {
|
|
1783
|
+
return;
|
|
1784
|
+
}
|
|
1785
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
1786
|
+
snapshotBuffer.unbind();
|
|
1787
|
+
snapshotBound = false;
|
|
1788
|
+
};
|
|
1826
1789
|
|
|
1827
1790
|
/**
|
|
1828
1791
|
* Destroys this renderer.
|