import { Env , ExtrudedPolygonTechnique } from "@here/harp-datasource-protocol" ; import { ColorUtils } from "@here/harp-datasource-protocol/lib/ColorUtils" ; import { enforceBlending , MapMeshStandardMaterial } from "@here/harp-materials" ; import * as THREE from "three" ; import { evaluateBaseColorProperty } from "./DecodedTileHelpers" ; internal export const DEPTH_PRE_PASS_STENCIL_MASK = 0x01 ; /**
 * Render order offset for the depth pre-pass to ensure that it's rendered first.
 */ const DEPTH_PRE_PASS_RENDER_ORDER_OFFSET = 1e-6 ; remarks param technique param env -  {@link @here/harp-datasource-protocol#Env} instance used
 *              to evaluate  {@link @here/harp-datasource-protocol#Expr} *              based properties of `Technique`
 *
 *  internal export function isRenderDepthPrePassEnabled ( technique , env ) { if ( technique . enableDepthPrePass === false ) { return false ; } let transparent = technique . opacity !== undefined && technique . opacity > 0.0 && technique . opacity < 1.0 ; if ( ! transparent ) { const color = evaluateBaseColorProperty ( technique , env ) ; if ( color !== undefined ) { const alpha = ColorUtils . getAlphaFromHex ( color ) ; transparent = alpha > 0.0 && alpha < 1.0 ; } } return transparent ; } /**
 * Property identifying a material that is being used as a DepthPrePass material.
 */ export interface DepthPrePassProperties { /**
     * This material is a special depth prepass material.
     */ isDepthPrepassMaterial ? : true ; } remarks param baseMaterial returns internal export function createDepthPrePassMaterial ( baseMaterial ) { baseMaterial . depthWrite = false ; baseMaterial . depthFunc = THREE . EqualDepth ; baseMaterial . colorWrite = true ; enforceBlending ( baseMaterial ) ; const depthPassMaterial = baseMaterial . clone ( ) ; depthPassMaterial . isDepthPrepassMaterial = true ; depthPassMaterial . depthWrite = true ; depthPassMaterial . depthTest = true ; depthPassMaterial . depthFunc = THREE . LessDepth ; depthPassMaterial . colorWrite = false ; depthPassMaterial . opacity = 1.0 ; depthPassMaterial . blending = THREE . NoBlending ; return depthPassMaterial ; } param object returns internal export function isDepthPrePassMesh ( object ) { if ( ( object as any ) . isMesh !== true ) { return false ; } const mesh = object as THREE . Mesh ; return mesh . material instanceof Array ? mesh . material . every ( material => ( material as any ) . isDepthPrepassMaterial === true ) : ( mesh . material as any ) . isDepthPrepassMaterial === true ; } remarks param mesh returns internal export function createDepthPrePassMesh ( mesh ) { const originalGeometry = mesh . geometry ; if ( ! ( originalGeometry instanceof THREE . BufferGeometry ) ) { throw new Error ( "#createDepthPassMesh only BufferGeometry is supported" ) ; } const positionAttribute = originalGeometry . getAttribute ( "position" ) ; if ( ! positionAttribute ) { throw new Error ( "#createDepthPassMesh position attribute not found" ) ; } const depthPassGeometry = new THREE . BufferGeometry ( ) ; depthPassGeometry . setAttribute ( "position" , positionAttribute ) ; const uvAttribute = originalGeometry . getAttribute ( "uv" ) ; if ( uvAttribute ) { depthPassGeometry . setAttribute ( "uv" , uvAttribute ) ; } const normalAttribute = originalGeometry . getAttribute ( "normal" ) ; if ( normalAttribute ) { depthPassGeometry . setAttribute ( "normal" , normalAttribute ) ; } const extrusionAxisAttribute = originalGeometry . getAttribute ( "extrusionAxis" ) ; if ( extrusionAxisAttribute ) { depthPassGeometry . setAttribute ( "extrusionAxis" , extrusionAxisAttribute ) ; } if ( originalGeometry . index ) { depthPassGeometry . setIndex ( originalGeometry . index ) ; } for ( const group of originalGeometry . groups ) { const { start , count , materialIndex } = group ; depthPassGeometry . addGroup ( start , count , materialIndex ) ; } const depthPassMaterial = mesh . material instanceof Array ? mesh . material . map ( createDepthPrePassMaterial ) : createDepthPrePassMaterial ( mesh . material ) ; const depthPassMesh = new THREE . Mesh ( depthPassGeometry , depthPassMaterial ) ; depthPassMesh . renderOrder = mesh . renderOrder - DEPTH_PRE_PASS_RENDER_ORDER_OFFSET ; return depthPassMesh ; } remarks param depthMesh param colorMesh internal export function setDepthPrePassStencil ( depthMesh , colorMesh ) { function setupDepthMaterialStencil ( depthMeshMaterial ) { const depthMaterial = depthMeshMaterial as MapMeshStandardMaterial ; depthMaterial . stencilWrite = true ; depthMaterial . stencilFail = THREE . KeepStencilOp ; depthMaterial . stencilZFail = THREE . KeepStencilOp ; depthMaterial . stencilZPass = THREE . ReplaceStencilOp ; depthMaterial . stencilFunc = THREE . AlwaysStencilFunc ; depthMaterial . stencilRef = 0xff ; ( depthMaterial as any ) . stencilFuncMask = DEPTH_PRE_PASS_STENCIL_MASK ; } function setupColorMaterialStencil ( colorMeshMaterial ) { const colorMaterial = colorMeshMaterial as MapMeshStandardMaterial ; colorMaterial . stencilWrite = true ; colorMaterial . stencilFail = THREE . KeepStencilOp ; colorMaterial . stencilZFail = THREE . KeepStencilOp ; colorMaterial . stencilZPass = THREE . ZeroStencilOp ; colorMaterial . stencilFunc = THREE . EqualStencilFunc ; colorMaterial . stencilRef = 0xff ; ( colorMaterial as any ) . stencilFuncMask = DEPTH_PRE_PASS_STENCIL_MASK ; } if ( depthMesh . material instanceof Array ) { depthMesh . material . map ( setupDepthMaterialStencil ) ; } else { setupDepthMaterialStencil ( depthMesh . material ) ; } if ( colorMesh . material instanceof Array ) { colorMesh . material . map ( setupColorMaterialStencil ) ; } else { setupColorMaterialStencil ( colorMesh . material ) ; } }