Skip to content

Latest commit

History

History
343 lines (270 loc) 路 6.98 KB

WORLD.md

File metadata and controls

343 lines (270 loc) 路 6.98 KB

馃寪 signal-gl/world

Game engine built on top of signal-gl

Overview

Components

Scene component

root-component of signal-gl/world

Usage

import { Scene } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    ...
  </Scene>
)

type CanvasProps see

Group component

create a parent-child relationship by cascading model-view's matrix transformations aka grouping signal-gl/world-objects in cyberspace

Usage

import { Scene, Group } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    <Group position={[0, 0, 5]}>
      ...
    </Group>
  </Scene>
)

type Pose

type Pose = {
  position: Vector3 | vec3
  rotation: Vector3 | vec3
  scale: Vector3 | vec3
  matrix: mat4
}

type GroupProps

type GroupProps = ParentProps<Pose>

Camera component

control the scene's model- and projection-view aka a camera in cyberspace

Usage

import { Scene, Group } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    <Camera position={[0, 0, 5]} fov={90}/>
    ...
  </Scene>
)

type CameraProps

type CameraProps = ParentProps<Pose & {
  active: boolean
  fov: number
  near: number
  far: number
  realMatrix: mat4
}>

Shape component

a <Program/> with a default vertex- and fragment-shader wrapped with a <Group/> aka a shape in cyberspace

Usage

import { Shape } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    <Shape vertices={new UInt16Array(...)} position={[0, 20, 0]}/>
    ...
  </Scene>
)

type ShapeProps

type ShapeProps = ParentProps<Pose & {
  fragment?: ShaderToken
  vertex?: ShaderToken
  indices: number[]
  color?: Vector3 | vec3 // [1, 1, 1]
  opacity?: number // 1
  vertices: Float32Array
  mode?: RenderMode // 'TRIANGLES'
}>

default shaders

vertex
glsl`#version 300 es
  precision mediump float;
  out vec4 model;
  out vec4 view;
  out vec4 clip;
  void main(void) {
    model = ${scene.model.uniform} * vec4(${attribute.vec3(() => props.vertices)}, 1.);
    view = ${scene.view.uniform} * model;
    clip = ${scene.projection.uniform} * view;
    gl_Position = clip;
  }`

in the fragment-shader you have access to the following varying

  • model model-space
  • view view-space
  • clip clip-space
fragment
glsl`#version 300 es
  precision mediump float;
  out vec4 color_out;
  void main(void) {
    color_out = vec4(${uniform.vec3(() => props.color)}, ${uniform.float(() => props.opacity)});
  }`

Cube component

a <Shape/> with vertices and indices describing a cube aka a cube in cyberspace

Usage

import { Shape } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    <Shape vertices={new UInt16Array(...)} position={[0, 20, 0]}/>
    ...
  </Scene>
)

type ShapeProps

type ShapeProps = ParentProps<Pose & {
  fragment?: ShaderToken
  vertex?: ShaderToken
  indices: number[]
  color?: Vector3 | vec3 // [1, 1, 1]
  opacity?: number // 1
  vertices: Float32Array
  mode?: RenderMode // 'TRIANGLES'
}>

ColliderProvider component

dependency inject collider-functionality into your signal-gl/world-scene

Usage

import { ColliderProvider, createRaycaster, Shape } from '@bigmistqke/signal-gl/world'
const raycaster = createRaycaster()
return (
  <Scene>
    <ColliderProvider plugins={[raycaster]}>
    ...
    </ColliderProvider>
  </Scene>
)

type ColliderProviderProps

type ColliderPlugin = Raycaster

type ColliderProviderProps = ParentProps<{
  plugins: ColliderPlugin[]
}>

ColliderPlugins

AxisAlignedBoxCollider component

an AABB-collider see

Usage

import { Shape, AxisAlignedBoxCollider } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    <ColliderProvider>
      <AxisAlignedBoxCollider onEvent={({hit}) => console.log('hit?', hit)}>
        <Cube>
      </AxisAlignedBoxCollider>
    </ColliderProvider>
  </Scene>
)

you can also visualise AxisAlignedBoxCollider by assigning it a color

import { Shape, AxisAlignedBoxCollider } from '@bigmistqke/signal-gl/world'
return (
  <Scene>
    <ColliderProvider>
      <AxisAlignedBoxCollider color={[0, 2, 0]} />
    </ColliderProvider>
  </Scene>
)

type AxisAlignedBoxColliderProps

type AxisAlignedBoxColliderProps = ParentProps<{
  scale?: Vector3 | vec3
  position?: Vector3 | vec3
  color?: Vector3 | vec3
  onEvent?: (event: { type: string; hit: boolean }) => void
  mode?: RenderMode
}>

Hooks

useScene hook

  • access signal-gl/world state through context
  • only available inside scope of a <Scene/>

Usage

import { useScene } from "@bigmistqke/signal-gl/world"

const Object = () => {
  const scene = useScene()
  if(!scene) throw 'scene is not defined'
  console.log(scene.model.matrix)
  ...
}

SceneContext

type SceneContext = SignalGLContext & {
  projection: {
    uniform: ReturnType<typeof uniform.mat4>
    matrix: mat4
    invertedMatrix: mat4
  },
  view: {
    uniform: ReturnType<typeof uniform.mat4>
    matrix: mat4
    invertedMatrix: mat4
  },
  model: {
    uniform: ReturnType<typeof uniform.mat4>
    matrix: mat4
  },
  setView(view: mat4) : void
  setProjection(view: mat4) : void
}

createRaycaster hook

Usage

import { createRaycaster } from "@bigmistqke/signal-gl/world"

const raycaster = createRaycaster()
if(!scene) throw 'scene is not defined'
const raycaster = createRaycaster()
// raycast direction of the cursor 
// whenever the camera or any of the collider's update
createEffect(raycaster.castCursor)
return (
  // raycast from the center of the camera
  <Scene onMouseDown={raycaster.castCenter}>
    <ColliderProvider plugins={[raycaster]}>
      <AxisAlignedBoxCollider onEvent={({type, hit}) => console.log(type, hit)}/>
    </ColliderProvider>
  </Scene>
)