Home Manual Reference Source

src/gl/S3GLScene.js

import S3Scene from "../basic/S3Scene.js";
import S3Camera from "../basic/S3Camera.js";
import S3GLLight from "./S3GLLight.js";
import S3GLArray from "./S3GLArray.js";
import S3GLModel from "./S3GLModel.js";
import S3Vector from "../math/S3Vector.js";

/**
 * WebGL描画用のシーン(Scene)クラス。
 * 基本のS3Sceneを拡張し、WebGL用のuniformデータ生成(getUniforms)などの機能を追加します。
 * カメラやライト情報をGLSLシェーダ向けにuniform変数としてまとめて提供します。
 *
 * @class
 * @extends S3Scene
 * @module S3
 */
export default class S3GLScene extends S3Scene {
	/**
	 * シーンを初期化します。
	 * モデル・カメラ・ライトの配列等はS3Sceneに準拠します。
	 */
	constructor() {
		super();
	}

	/**
	 * シーン構成要素を初期化します。
	 * カメラは新規作成、モデル・ライトは空配列となります。
	 */
	_init() {
		/**
		 * シーン全体のカメラ
		 * @type {S3Camera}
		 */
		this.camera = null;
		/**
		 * シーン内の3Dモデル配列
		 * @type {Array<S3GLModel>}
		 */
		this.model = [];
		/**
		 * シーン内のライト配列
		 * @type {Array<S3GLLight>}
		 */
		this.light = [];
	}

	/**
	 * シーンにモデルを追加します。
	 * @param {S3GLModel} model 追加する3Dモデル(型はS3Model等を想定)
	 */
	addModel(model) {
		this.model[this.model.length] = model;
	}

	/**
	 * シーンにライトを追加します。
	 * @param {S3GLLight} light 追加するライト(型はS3Light等を想定)
	 */
	addLight(light) {
		this.light[this.light.length] = light;
	}

	/**
	 * シーン内の全モデルを取得します。
	 * @returns {Array<S3GLModel>} モデル配列
	 */
	getModels() {
		return /** @type {Array<S3GLModel>} */ (this.model);
	}

	/**
	 * シーン内の全ライトを取得します。
	 * @returns {Array<S3GLLight>} ライト配列
	 */
	getLights() {
		return /** @type {Array<S3GLLight>} */ (this.light);
	}

	/**
	 * @typedef {Object} S3GLSceneUniform
	 * @property {S3Vector} eyeWorldDirection カメラ情報
	 * @property {S3GLArray} lightsLength ライトの数
	 * @property {S3GLArray[]} lightsData1 モード・レンジ・方向or位置 (vec4)
	 * @property {S3GLArray[]} lightsData2 方向or位置Z成分+カラー情報 (vec4)
	 */

	/**
	 * @typedef {Object} S3GLProgramUniforms
	 * @property {S3GLSceneUniform} uniforms
	 */

	/**
	 * シーン全体のWebGL向けuniformデータを生成して返します。
	 * カメラの視線ベクトルや、最大4つまでのライト情報をuniform用データにまとめます。
	 * 各値はS3GLArrayやGLSLと連携しやすい形式で返されます。
	 *
	 * - uniforms: uniform変数名→データ(カメラ方向ベクトル、ライト属性配列など)
	 * @returns {S3GLProgramUniforms}
	 */
	getUniforms() {
		const LIGHTS_MAX = 4;
		/**
		 * @type {Array<S3GLLight>}
		 */
		const light_array = /** @type {Array<S3GLLight>} */ (this.getLights());
		const lightsLength = Math.min(light_array.length, LIGHTS_MAX);

		/**
		 * @type {S3GLSceneUniform}
		 */
		const uniforms = {
			eyeWorldDirection: this.getCamera().getDirection(),
			lightsLength: new S3GLArray(lightsLength, 1, S3GLArray.datatype.Int32Array),
			lightsData1: [],
			lightsData2: []
		};

		for (let i = 0; i < lightsLength; i++) {
			const data = light_array[i].getGLData();
			uniforms.lightsData1.push(data.lightsData1);
			uniforms.lightsData2.push(data.lightsData2);
		}

		const ret = { uniforms: uniforms };
		return ret;
	}
}