///|
extern "js" fn webgpu_begin_3d(
view_projection : Array[Double],
position_x : Double,
position_y : Double,
position_z : Double,
target_x : Double,
target_y : Double,
target_z : Double,
up_x : Double,
up_y : Double,
up_z : Double,
fovy : Double,
near_z : Double,
far_z : Double,
orthographic : Double,
orthographic_width : Double,
orthographic_height : Double,
) -> Unit =
#| (viewProjection, px, py, pz, tx, ty, tz, ux, uy, uz, fovy, nearZ, farZ, orthographic, orthoWidth, orthoHeight) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.begin3d(viewProjection, px, py, pz, tx, ty, tz, ux, uy, uz, fovy, nearZ, farZ, orthographic, orthoWidth, orthoHeight);
#| }
#| }
///|
extern "js" fn webgpu_canvas_size() -> Array[Double] =
#| () => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (!rt?.canvas) return [1, 1];
#| return [
#| Math.max(1, Math.floor(rt.canvas.width || 1)),
#| Math.max(1, Math.floor(rt.canvas.height || 1)),
#| ];
#| }
///|
extern "js" fn webgpu_end_3d() -> Unit =
#| () => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.end3d();
#| }
#| }
///|
extern "js" fn webgpu_set_lighting_3d(
light_uniform : Array[Double],
directional_shadow_data : Array[Double],
point_shadow_data : Array[Double],
spot_shadow_data : Array[Double],
directional_shadow_map_size : Double,
point_shadow_map_size : Double,
) -> Unit =
#| (lightUniform, directionalShadowData, pointShadowData, spotShadowData, directionalShadowMapSize, pointShadowMapSize) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (!rt) return;
#| const safeLightUniform = Array.isArray(lightUniform) ? lightUniform : [];
#| const safeDirectionalShadowMapSize = Math.max(1, Math.round(Number(directionalShadowMapSize) || 2048));
#| const safePointShadowMapSize = Math.max(1, Math.round(Number(pointShadowMapSize) || 1024));
#| rt.shadow3d = {
#| directional: new Float32Array(Array.isArray(directionalShadowData) ? directionalShadowData : []),
#| point: new Float32Array(Array.isArray(pointShadowData) ? pointShadowData : []),
#| spot: new Float32Array(Array.isArray(spotShadowData) ? spotShadowData : []),
#| directionalShadowMapSize: safeDirectionalShadowMapSize,
#| pointShadowMapSize: safePointShadowMapSize,
#| };
#| rt.lightUniform3d = new Float32Array(safeLightUniform);
#| }
///|
extern "js" fn webgpu_set_shadow_view_projection_3d(
directional_cascades : Array[Double],
spot_matrices : Array[Double],
point_matrices : Array[Double],
) -> Unit =
#| (directionalCascades, spotMatrices, pointMatrices) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (!rt) return;
#| rt.shadowViewProjection3d = {
#| directional: new Float32Array(Array.isArray(directionalCascades) ? directionalCascades : []),
#| spot: new Float32Array(Array.isArray(spotMatrices) ? spotMatrices : []),
#| point: new Float32Array(Array.isArray(pointMatrices) ? pointMatrices : []),
#| };
#| }
///|
extern "js" fn webgpu_upload_lit_primitive_mesh_resource(
cache_key : String,
vertices : Array[Double],
) -> Unit =
#| (cacheKey, vertices) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.uploadLitPrimitiveMeshResource(cacheKey, vertices);
#| }
#| }
///|
extern "js" fn webgpu_draw_lit_primitive_mesh_batch_3d(
cache_key : String,
retained_key : String,
instances : Array[Double],
double_sided : Bool,
cast_shadows : Bool,
) -> Unit =
#| (cacheKey, retainedKey, instances, doubleSided, castShadows) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.pushLitPrimitiveMeshBatch3d(cacheKey, retainedKey, instances, doubleSided, castShadows);
#| }
#| }
///|
extern "js" fn webgpu_release_primitive_mesh_resource(
cache_key : String,
) -> Unit =
#| (cacheKey) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.releasePrimitiveMeshResource(cacheKey);
#| }
#| }
///|
extern "js" fn webgpu_release_retained_instance_buffer_3d(
retained_key : String,
) -> Unit =
#| (retainedKey) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.releaseRetainedInstanceBuffer3d(retainedKey);
#| }
#| }
///|
extern "js" fn webgpu_draw_colored_triangles_3d(
vertices : Array[Double],
double_sided : Bool,
cast_shadows : Bool,
) -> Unit =
#| (vertices, doubleSided, castShadows) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.pushColoredTriangles3d(vertices, doubleSided, castShadows);
#| }
#| }
///|
extern "js" fn webgpu_draw_lines_3d(vertices : Array[Double]) -> Unit =
#| (vertices) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.pushLines3d(vertices);
#| }
#| }
///|
extern "js" fn webgpu_draw_textured_triangles_3d(
base_path : String,
emissive_path : String,
metallic_roughness_path : String,
occlusion_path : String,
normal_path : String,
base_sampler_code : Int,
emissive_sampler_code : Int,
metallic_roughness_sampler_code : Int,
occlusion_sampler_code : Int,
normal_sampler_code : Int,
vertices : Array[Double],
double_sided : Bool,
cast_shadows : Bool,
) -> Unit =
#| (basePath, emissivePath, metallicRoughnessPath, occlusionPath, normalPath, baseSamplerCode, emissiveSamplerCode, metallicRoughnessSamplerCode, occlusionSamplerCode, normalSamplerCode, vertices, doubleSided, castShadows) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.pushTexturedTriangles3d(basePath, emissivePath, metallicRoughnessPath, occlusionPath, normalPath, baseSamplerCode, emissiveSamplerCode, metallicRoughnessSamplerCode, occlusionSamplerCode, normalSamplerCode, vertices, doubleSided, castShadows);
#| }
#| }
///|
extern "js" fn webgpu_draw_skybox_textured_triangles_3d(
base_path : String,
vertices : Array[Double],
) -> Unit =
#| (basePath, vertices) => {
#| const rt = globalThis.__selene_webgpu_runtime;
#| if (rt) {
#| rt.pushSkyboxTexturedTriangles3d(basePath, vertices);
#| }
#| }
///|
pub extern "js" fn Audio::new(path : String) -> Audio =
#| (path) => {
#| const init = globalThis.__selene_init_audio_element || (
#| globalThis.__selene_init_audio_element = (audio) => {
#| if (audio.__seleneAudioInitialized) {
#| return audio;
#| }
#| audio.__seleneAudioInitialized = true;
#| audio.preload = 'auto';
#| audio.__selenePlayState = 0;
#| audio.__selenePlayAttemptEpoch = -1;
#| audio.addEventListener('playing', () => {
#| audio.__selenePlayState = 1;
#| });
#| audio.addEventListener('pause', () => {
#| if (!audio.ended) {
#| audio.__selenePlayState = 0;
#| }
#| });
#| audio.addEventListener('error', () => {
#| audio.__selenePlayState = 3;
#| });
#| return audio;
#| }
#| );
#| return init(new Audio(path));
#| }