import * as THREE from 'three'; import { UINumber, UIPanel, UIRow, UISelect, UIText } from './libs/ui.js'; import { UIBoolean } from './libs/ui.three.js'; import { OrbitControls } from '/examples/jsm/controls/OrbitControls.js'; import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'; function SidebarProjectRenderer( editor ) { const config = editor.config; const signals = editor.signals; const strings = editor.strings; let currentRenderer = null; let currentCSSRenderer = null; const container = new UIPanel(); const headerRow = new UIRow(); headerRow.add( new UIText( strings.getKey( 'sidebar/project/renderer' ).toUpperCase() ) ); container.add( headerRow ); // Antialias const antialiasRow = new UIRow(); container.add( antialiasRow ); antialiasRow.add( new UIText( strings.getKey( 'sidebar/project/antialias' ) ).setWidth( '90px' ) ); const antialiasBoolean = new UIBoolean( config.getKey( 'project/renderer/antialias' ) ).onChange( createRenderer ); antialiasRow.add( antialiasBoolean ); // Physically Correct lights const physicallyCorrectLightsRow = new UIRow(); container.add( physicallyCorrectLightsRow ); physicallyCorrectLightsRow.add( new UIText( strings.getKey( 'sidebar/project/physicallyCorrectLights' ) ).setWidth( '90px' ) ); const physicallyCorrectLightsBoolean = new UIBoolean( config.getKey( 'project/renderer/physicallyCorrectLights' ) ).onChange( function () { currentRenderer.physicallyCorrectLights = this.getValue(); signals.rendererUpdated.dispatch(); } ); physicallyCorrectLightsRow.add( physicallyCorrectLightsBoolean ); // Shadows const shadowsRow = new UIRow(); container.add( shadowsRow ); shadowsRow.add( new UIText( strings.getKey( 'sidebar/project/shadows' ) ).setWidth( '90px' ) ); const shadowsBoolean = new UIBoolean( config.getKey( 'project/renderer/shadows' ) ).onChange( updateShadows ); shadowsRow.add( shadowsBoolean ); const shadowTypeSelect = new UISelect().setOptions( { 0: 'Basic', 1: 'PCF', 2: 'PCF Soft', // 3: 'VSM' } ).setWidth( '125px' ).onChange( updateShadows ); shadowTypeSelect.setValue( config.getKey( 'project/renderer/shadowType' ) ); shadowsRow.add( shadowTypeSelect ); function updateShadows() { currentRenderer.shadowMap.enabled = shadowsBoolean.getValue(); currentRenderer.shadowMap.type = parseFloat( shadowTypeSelect.getValue() ); signals.rendererUpdated.dispatch(); } // Tonemapping const toneMappingRow = new UIRow(); container.add( toneMappingRow ); toneMappingRow.add( new UIText( strings.getKey( 'sidebar/project/toneMapping' ) ).setWidth( '90px' ) ); const toneMappingSelect = new UISelect().setOptions( { 0: 'No', 1: 'Linear', 2: 'Reinhard', 3: 'Cineon', 4: 'ACESFilmic' } ).setWidth( '120px' ).onChange( updateToneMapping ); toneMappingSelect.setValue( config.getKey( 'project/renderer/toneMapping' ) ); toneMappingRow.add( toneMappingSelect ); const toneMappingExposure = new UINumber( config.getKey( 'project/renderer/toneMappingExposure' ) ); toneMappingExposure.setDisplay( toneMappingSelect.getValue() === '0' ? 'none' : '' ); toneMappingExposure.setWidth( '30px' ).setMarginLeft( '10px' ); toneMappingExposure.setRange( 0, 10 ); toneMappingExposure.onChange( updateToneMapping ); toneMappingRow.add( toneMappingExposure ); function updateToneMapping() { toneMappingExposure.setDisplay( toneMappingSelect.getValue() === '0' ? 'none' : '' ); currentRenderer.toneMapping = parseFloat( toneMappingSelect.getValue() ); currentRenderer.toneMappingExposure = toneMappingExposure.getValue(); signals.rendererUpdated.dispatch(); } // function createRenderer() { currentRenderer = new THREE.WebGLRenderer( { antialias: antialiasBoolean.getValue() } ); currentRenderer.outputEncoding = THREE.sRGBEncoding; currentRenderer.physicallyCorrectLights = physicallyCorrectLightsBoolean.getValue(); currentRenderer.shadowMap.enabled = shadowsBoolean.getValue(); currentRenderer.shadowMap.type = parseFloat( shadowTypeSelect.getValue() ); currentRenderer.toneMapping = parseFloat( toneMappingSelect.getValue() ); currentRenderer.toneMappingExposure = toneMappingExposure.getValue(); signals.rendererCreated.dispatch( currentRenderer ); signals.rendererUpdated.dispatch(); } function createCSS2DRenderer() { let css2dRenderer = new CSS2DRenderer(); css2dRenderer.setSize(window.innerWidth, window.innerHeight); css2dRenderer.domElement.style.position = 'absolute'; css2dRenderer.domElement.style.top = '0px';//信息弹窗界面高度一半 // css2dRenderer.domElement.style.left = '0px';//信息弹窗界面宽度一半 css2dRenderer.domElement.style.pointerEvents = 'none'; signals.rendererCSSCreated.dispatch(css2dRenderer); signals.rendererCSSUpdated.dispatch(); } createCSS2DRenderer(); createRenderer(); // Signals signals.editorCleared.add( function () { currentRenderer.physicallyCorrectLights = false; currentRenderer.shadowMap.enabled = true; currentRenderer.shadowMap.type = THREE.PCFShadowMap; currentRenderer.toneMapping = THREE.NoToneMapping; currentRenderer.toneMappingExposure = 1; physicallyCorrectLightsBoolean.setValue( currentRenderer.physicallyCorrectLights ); shadowsBoolean.setValue( currentRenderer.shadowMap.enabled ); shadowTypeSelect.setValue( currentRenderer.shadowMap.type ); toneMappingSelect.setValue( currentRenderer.toneMapping ); toneMappingExposure.setValue( currentRenderer.toneMappingExposure ); toneMappingExposure.setDisplay( currentRenderer.toneMapping === 0 ? 'none' : '' ); signals.rendererUpdated.dispatch(); } ); signals.rendererUpdated.add( function () { config.setKey( 'project/renderer/antialias', antialiasBoolean.getValue(), 'project/renderer/physicallyCorrectLights', physicallyCorrectLightsBoolean.getValue(), 'project/renderer/shadows', shadowsBoolean.getValue(), 'project/renderer/shadowType', parseFloat( shadowTypeSelect.getValue() ), 'project/renderer/toneMapping', parseFloat( toneMappingSelect.getValue() ), 'project/renderer/toneMappingExposure', toneMappingExposure.getValue() ); } ); return container; } export { SidebarProjectRenderer };