Browse Source

Editor: Added Image render section (Realistic shading not ready yet).

Mr.doob 1 year ago
parent
commit
0498e27d1f
4 changed files with 168 additions and 0 deletions
  1. 155 0
      editor/js/Sidebar.Project.Image.js
  2. 3 0
      editor/js/Sidebar.Project.js
  3. 9 0
      editor/js/Strings.js
  4. 1 0
      editor/sw.js

+ 155 - 0
editor/js/Sidebar.Project.Image.js

@@ -0,0 +1,155 @@
+import * as THREE from 'three';
+
+import { UIBreak, UIButton, UIInteger, UIPanel, UIRow, UISelect, UIText } from './libs/ui.js';
+
+import { ViewportPathtracer } from './Viewport.Pathtracer.js';
+
+function SidebarProjectImage( editor ) {
+
+	const strings = editor.strings;
+
+	const container = new UIPanel();
+	container.setId( 'render' );
+
+	// Image
+
+	container.add( new UIText( strings.getKey( 'sidebar/project/image' ) ).setTextTransform( 'uppercase' ) );
+	container.add( new UIBreak(), new UIBreak() );
+
+	// Shading
+
+	const shadingRow = new UIRow();
+	// container.add( shadingRow );
+
+	shadingRow.add( new UIText( strings.getKey( 'sidebar/project/shading' ) ).setClass( 'Label' ) );
+
+	const shadingTypeSelect = new UISelect().setOptions( {
+		0: 'Solid',
+		1: 'Realistic'
+	} ).setWidth( '125px' );
+	shadingTypeSelect.setValue( 0 );
+	shadingRow.add( shadingTypeSelect );
+
+	// Resolution
+
+	const resolutionRow = new UIRow();
+	container.add( resolutionRow );
+
+	resolutionRow.add( new UIText( strings.getKey( 'sidebar/project/resolution' ) ).setClass( 'Label' ) );
+
+	const imageWidth = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' );
+	resolutionRow.add( imageWidth );
+
+	resolutionRow.add( new UIText( '×' ).setTextAlign( 'center' ).setFontSize( '12px' ).setWidth( '12px' ) );
+
+	const imageHeight = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' );
+	resolutionRow.add( imageHeight );
+
+	// Render
+
+	const renderButton = new UIButton( strings.getKey( 'sidebar/project/render' ) );
+	renderButton.setWidth( '170px' );
+	renderButton.setMarginLeft( '120px' );
+	renderButton.onClick( async () => {
+
+		const json = editor.toJSON();
+		const project = json.project;
+
+		//
+
+		const loader = new THREE.ObjectLoader();
+
+		const camera = loader.parse( json.camera );
+		camera.aspect = imageWidth.getValue() / imageHeight.getValue();
+		camera.updateProjectionMatrix();
+		camera.updateMatrixWorld();
+
+		const scene = loader.parse( json.scene );
+
+		const renderer = new THREE.WebGLRenderer( { antialias: true } );		
+		renderer.setSize( imageWidth.getValue(), imageHeight.getValue() );
+
+		if ( project.shadows !== undefined ) renderer.shadowMap.enabled = project.shadows;
+		if ( project.shadowType !== undefined ) renderer.shadowMap.type = project.shadowType;
+		if ( project.toneMapping !== undefined ) renderer.toneMapping = project.toneMapping;
+		if ( project.toneMappingExposure !== undefined ) renderer.toneMappingExposure = project.toneMappingExposure;
+
+		// popup
+
+		const width = imageWidth.getValue() / window.devicePixelRatio;
+		const height = imageHeight.getValue() / window.devicePixelRatio;
+
+		const left = ( screen.width - width ) / 2;
+		const top = ( screen.height - height ) / 2;
+
+		const output = window.open( '', '_blank', `location=no,left=${left},top=${top},width=${width},height=${height}` );
+
+		const meta = document.createElement( 'meta' );
+		meta.name = 'viewport';
+		meta.content = 'width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0';
+		output.document.head.appendChild( meta );
+
+		output.document.body.style.background = '#000';
+		output.document.body.style.margin = '0px';
+		output.document.body.style.overflow = 'hidden';
+
+		const canvas = renderer.domElement;
+		canvas.style.width = width + 'px';
+		canvas.style.height = height + 'px';
+		output.document.body.appendChild( canvas );
+
+		//
+
+		switch ( Number( shadingTypeSelect.getValue() ) ) {
+
+			case 0: // SOLID
+
+				renderer.render( scene, camera );
+				renderer.dispose();
+
+				break;
+			/*
+			case 1: // REALISTIC
+
+				const status = document.createElement( 'div' );
+				status.style.position = 'absolute';
+				status.style.top = '10px';
+				status.style.left = '10px';
+				status.style.color = 'white';
+				status.style.fontFamily = 'system-ui';
+				status.style.fontSize = '12px';
+				output.document.body.appendChild( status );
+
+				const pathtracer = new ViewportPathtracer( renderer );
+				pathtracer.init( scene, camera );
+				pathtracer.setSize( imageWidth.getValue(), imageHeight.getValue());
+
+				function animate() {
+
+					if ( output.closed === true ) return;
+
+					requestAnimationFrame( animate );
+				
+					pathtracer.update();
+
+					// status.textContent = Math.floor( samples );
+
+				}
+
+				animate();
+
+				break;
+			*/
+
+		}
+
+	} );
+	container.add( renderButton );
+
+	//
+
+	return container;
+
+}
+
+export { SidebarProjectImage };

+ 3 - 0
editor/js/Sidebar.Project.js

@@ -3,6 +3,7 @@ import { UISpan } from './libs/ui.js';
 import { SidebarProjectApp } from './Sidebar.Project.App.js';
 /* import { SidebarProjectMaterials } from './Sidebar.Project.Materials.js'; */
 import { SidebarProjectRenderer } from './Sidebar.Project.Renderer.js';
+import { SidebarProjectImage } from './Sidebar.Project.Image.js';
 import { SidebarProjectVideo } from './Sidebar.Project.Video.js';
 
 function SidebarProject( editor ) {
@@ -15,6 +16,8 @@ function SidebarProject( editor ) {
 
 	container.add( new SidebarProjectApp( editor ) );
 
+	container.add( new SidebarProjectImage( editor ) );
+
 	if ( 'SharedArrayBuffer' in window ) {
 
 		container.add( new SidebarProjectVideo( editor ) );

+ 9 - 0
editor/js/Strings.js

@@ -318,7 +318,10 @@ function Strings( config ) {
 			'sidebar/project/app/editable': 'Editable',
 			'sidebar/project/app/publish': 'Publish',
 
+			'sidebar/project/image': 'Image',
 			'sidebar/project/video': 'Video',
+
+			'sidebar/project/shading': 'Shading',
 			'sidebar/project/resolution': 'Resolution',
 			'sidebar/project/duration': 'Duration',
 			'sidebar/project/render': 'Render',
@@ -664,7 +667,10 @@ function Strings( config ) {
 			'sidebar/project/app/editable': 'Modifiable',
 			'sidebar/project/app/publish': 'Publier',
 
+			'sidebar/project/image': 'Image',
 			'sidebar/project/video': 'Video',
+
+			'sidebar/project/shading': 'Shading',
 			'sidebar/project/resolution': 'Resolution',
 			'sidebar/project/duration': 'Duration',
 			'sidebar/project/render': 'Render',
@@ -1010,7 +1016,10 @@ function Strings( config ) {
 			'sidebar/project/app/editable': '编辑性',
 			'sidebar/project/app/publish': '发布',
 
+			'sidebar/project/image': 'Image',
 			'sidebar/project/video': '视频',
+
+			'sidebar/project/shading': 'Shading',
 			'sidebar/project/resolution': '分辨率',
 			'sidebar/project/duration': '时长',
 			'sidebar/project/render': '渲染',

+ 1 - 0
editor/sw.js

@@ -149,6 +149,7 @@ const assets = [
 	'./js/Sidebar.Project.Renderer.js',
 	'./js/Sidebar.Project.Materials.js',
 	'./js/Sidebar.Project.App.js',
+	'./js/Sidebar.Project.Image.js',
 	'./js/Sidebar.Project.Video.js',
 	'./js/Sidebar.Settings.js',
 	'./js/Sidebar.Settings.History.js',