UNPKG

@itwin/core-frontend

Version:
169 lines 7.9 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module WebGL */ import { assert, dispose } from "@itwin/core-bentley"; import { Gradient, RenderTexture, ThematicDisplayMode, ThematicGradientMode, ThematicGradientTransparencyMode, } from "@itwin/core-common"; import { TextureUnit } from "./RenderFlags"; import { desync, sync } from "./Sync"; import { TextureHandle } from "./Texture"; import { ThematicSensors } from "./ThematicSensors"; import { Angle, Range3d, Vector3d } from "@itwin/core-geometry"; import { System } from "./System"; import { FloatRgba } from "./FloatRGBA"; /** Maintains state for uniforms related to thematic display. * @internal */ export class ThematicUniforms { _sensors; // NB: This is only used if no distance cutoff is applied (this is shared among all batches) _texture; _range = new Float32Array(2); _colorMix = 0.0; _axis = new Float32Array(3); _sunDirection = new Float32Array(3); _marginColor = new FloatRgba(); _displayMode = new Float32Array(1); _fragSettings = new Float32Array(4); // gradientMode, distanceCutoff, stepCount, > 0.0 if multiply gradient alpha _numSensors = 0; _gradientDimension = _getGradientDimension(); _thematicDisplay; syncKey = 0; get _distanceCutoff() { return this._fragSettings[1]; } get thematicDisplay() { return this._thematicDisplay; } get wantIsoLines() { if (undefined !== this.thematicDisplay) return ThematicDisplayMode.Height === this._displayMode[0] && ThematicGradientMode.IsoLines === this.thematicDisplay.gradientSettings.mode; return false; } get wantSlopeMode() { return (undefined !== this.thematicDisplay) ? ThematicDisplayMode.Slope === this._displayMode[0] : false; } get wantHillShadeMode() { return (undefined !== this.thematicDisplay) ? ThematicDisplayMode.HillShade === this._displayMode[0] : false; } get wantGlobalSensorTexture() { return !(this._distanceCutoff > 0); } get bytesUsed() { return this._sensors ? this._sensors.bytesUsed : 0; } _scratchVector = new Vector3d(); _updateAxis(axis, viewMatrix) { const tAxis = (viewMatrix !== undefined) ? viewMatrix.multiplyVector(axis, this._scratchVector) : axis; tAxis.normalizeInPlace(); this._axis[0] = tAxis.x; this._axis[1] = tAxis.y; this._axis[2] = tAxis.z; } _updateSunDirection(sunDir, viewMatrix) { viewMatrix.multiplyVector(sunDir, this._scratchVector); this._scratchVector.negate(this._scratchVector); this._scratchVector.normalizeInPlace(); this._sunDirection[0] = this._scratchVector.x; this._sunDirection[1] = this._scratchVector.y; this._sunDirection[2] = this._scratchVector.z; } update(target) { const plan = target.plan; if (this.thematicDisplay && plan.thematic && this.thematicDisplay.equals(plan.thematic) && this._texture) { if (undefined !== this._sensors) this._sensors.update(target.uniforms.frustum.viewMatrix); if (ThematicDisplayMode.Slope === this.thematicDisplay.displayMode) { this._updateAxis(this.thematicDisplay.axis, target.uniforms.frustum.viewMatrix); desync(this); } else if (ThematicDisplayMode.HillShade === this.thematicDisplay.displayMode) { this._updateSunDirection(this.thematicDisplay.sunDirection, target.uniforms.frustum.viewMatrix); desync(this); } return; } desync(this); this._thematicDisplay = plan.thematic; this._texture = dispose(this._texture); if (!this.thematicDisplay) return; if (ThematicDisplayMode.Slope === this.thematicDisplay.displayMode) { this._range[0] = Angle.degreesToRadians(this.thematicDisplay.range.low); this._range[1] = Angle.degreesToRadians(this.thematicDisplay.range.high); } else { this._range[0] = this.thematicDisplay.range.low; this._range[1] = this.thematicDisplay.range.high; } this._colorMix = this.thematicDisplay.gradientSettings.colorMix; this._updateAxis(this.thematicDisplay.axis, (ThematicDisplayMode.Slope === this.thematicDisplay.displayMode) ? target.uniforms.frustum.viewMatrix : undefined); if (ThematicDisplayMode.HillShade === this.thematicDisplay.displayMode) this._updateSunDirection(this.thematicDisplay.sunDirection, target.uniforms.frustum.viewMatrix); this._marginColor.setColorDef(this.thematicDisplay.gradientSettings.marginColor); this._displayMode[0] = this.thematicDisplay.displayMode; this._fragSettings[0] = this.thematicDisplay.gradientSettings.mode; const sensorSettings = this.thematicDisplay.sensorSettings; this._fragSettings[1] = (undefined === sensorSettings) ? 0 : this.thematicDisplay.sensorSettings.distanceCutoff; this._fragSettings[2] = Math.min(this.thematicDisplay.gradientSettings.stepCount, this._gradientDimension); this._fragSettings[3] = this.thematicDisplay.gradientSettings.transparencyMode === ThematicGradientTransparencyMode.SurfaceOnly ? 0.0 : 1.0; // If we want sensors and have no distance cutoff, then create a global shared sensor texture. if (target.wantThematicSensors && !(this._distanceCutoff > 0)) { this._numSensors = sensorSettings.sensors.length; this._sensors = dispose(this._sensors); this._sensors = ThematicSensors.create(target, Range3d.createNull()); } const symb = Gradient.Symb.createThematic(this.thematicDisplay.gradientSettings); const image = symb.getThematicImageForRenderer(this._gradientDimension); this._texture = TextureHandle.createForImageBuffer(image, RenderTexture.Type.ThematicGradient); } bindRange(uniform) { if (!sync(this, uniform)) uniform.setUniform2fv(this._range); } bindAxis(uniform) { if (!sync(this, uniform)) uniform.setUniform3fv(this._axis); } bindSunDirection(uniform) { if (!sync(this, uniform)) uniform.setUniform3fv(this._sunDirection); } bindMarginColor(uniform) { if (!sync(this, uniform)) this._marginColor.bind(uniform); } bindDisplayMode(uniform) { if (!sync(this, uniform)) uniform.setUniform1fv(this._displayMode); } bindFragSettings(uniform) { if (!sync(this, uniform)) uniform.setUniform4fv(this._fragSettings); } bindTexture(uniform, unit) { assert(undefined !== this._texture); this._texture.bindSampler(uniform, unit); } bindNumSensors(uniform) { if (!sync(this, uniform)) uniform.setUniform1i(this._numSensors); } bindSensors(uniform) { assert(undefined !== this._sensors); this._sensors.texture.bindSampler(uniform, TextureUnit.ThematicSensors); } get isDisposed() { return undefined === this._texture && undefined === this._sensors; } [Symbol.dispose]() { this._texture = dispose(this._texture); this._sensors = dispose(this._sensors); } } function _getGradientDimension() { const preferDimension = 8192; const maxDimension = System.instance.maxTextureSize; return (preferDimension > maxDimension) ? maxDimension : preferDimension; } //# sourceMappingURL=ThematicUniforms.js.map