title category import { OrbitControl } from "@oasis-engine/controls" ; import { Buffer , BufferBindFlag , BufferMesh , BufferUsage , Camera , Engine , IndexFormat , Material , Mesh , MeshRenderer , Shader , Vector3 , VertexElement , VertexElementFormat , WebGLEngine } from "oasis-engine" ; const engine = new WebGLEngine ( "canvas" ) ; engine . canvas . resizeByClientSize ( ) ; const scene = engine . sceneManager . activeScene ; const rootEntity = scene . createRootEntity ( "Root" ) ; const shader = initCustomShader ( ) ; const cameraEntity = rootEntity . createChild ( "Camera" ) ; const camera = cameraEntity . addComponent ( Camera ) ; cameraEntity . addComponent ( OrbitControl ) ; cameraEntity . transform . setPosition ( 0 , 10 , 160 ) ; cameraEntity . transform . lookAt ( new Vector3 ( 0 , 0 , 0 ) ) ; camera . farClipPlane = 300 ; const cubeEntity = rootEntity . createChild ( "Cube" ) ; const cubeRenderer = cubeEntity . addComponent ( MeshRenderer ) ; const material = new Material ( engine , shader ) ; cubeEntity . transform . rotate ( 0 , 60 , 0 ) ; cubeRenderer . mesh = createCustomMesh ( engine , 1.0 ) ; cubeRenderer . setMaterial ( material ) ; engine . run ( ) ; param engine param size returns function createCustomMesh ( engine , size ) { const geometry = new BufferMesh ( engine , "CustomCubeGeometry" ) ; const vertices = new Float32Array ( [ - size , size , - size , 0 , 1 , 0 , size , size , - size , 0 , 1 , 0 , size , size , size , 0 , 1 , 0 , - size , size , size , 0 , 1 , 0 , - size , - size , - size , 0 , - 1 , 0 , size , - size , - size , 0 , - 1 , 0 , size , - size , size , 0 , - 1 , 0 , - size , - size , size , 0 , - 1 , 0 , - size , size , - size , - 1 , 0 , 0 , - size , size , size , - 1 , 0 , 0 , - size , - size , size , - 1 , 0 , 0 , - size , - size , - size , - 1 , 0 , 0 , size , size , - size , 1 , 0 , 0 , size , size , size , 1 , 0 , 0 , size , - size , size , 1 , 0 , 0 , size , - size , - size , 1 , 0 , 0 , - size , size , size , 0 , 0 , 1 , size , size , size , 0 , 0 , 1 , size , - size , size , 0 , 0 , 1 , - size , - size , size , 0 , 0 , 1 , - size , size , - size , 0 , 0 , - 1 , size , size , - size , 0 , 0 , - 1 , size , - size , - size , 0 , 0 , - 1 , - size , - size , - size , 0 , 0 , - 1 ] ) ; const instanceCount = 4000 ; const instanceStride = 6 ; const instanceData = new Float32Array ( instanceCount * instanceStride ) ; for ( let i = 0 ; i < instanceCount ; i ++ ) { const offset = i * instanceStride ; instanceData [ offset ] = ( Math . random ( ) - 0.5 ) * 60 ; instanceData [ offset + 1 ] = ( Math . random ( ) - 0.5 ) * 60 ; instanceData [ offset + 2 ] = ( Math . random ( ) - 0.5 ) * 60 ; instanceData [ offset + 3 ] = Math . random ( ) ; instanceData [ offset + 4 ] = Math . random ( ) ; instanceData [ offset + 5 ] = Math . random ( ) ; } const indices = new Uint16Array ( [ 0 , 2 , 1 , 2 , 0 , 3 , 4 , 6 , 7 , 6 , 4 , 5 , 8 , 10 , 9 , 10 , 8 , 11 , 12 , 14 , 15 , 14 , 12 , 13 , 16 , 18 , 17 , 18 , 16 , 19 , 20 , 22 , 23 , 22 , 20 , 21 ] ) ; const vertexBuffer = new Buffer ( engine , BufferBindFlag . VertexBuffer , vertices , BufferUsage . Static ) ; const instanceVertexBuffer = new Buffer ( engine , BufferBindFlag . VertexBuffer , instanceData , BufferUsage . Static ) ; const indexBuffer = new Buffer ( engine , BufferBindFlag . IndexBuffer , indices , BufferUsage . Static ) ; geometry . setVertexBufferBinding ( vertexBuffer , 24 , 0 ) ; geometry . setVertexBufferBinding ( instanceVertexBuffer , 24 , 1 ) ; geometry . setIndexBufferBinding ( indexBuffer , IndexFormat . UInt16 ) ; geometry . setVertexElements ( [ new VertexElement ( "POSITION" , 0 , VertexElementFormat . Vector3 , 0 , 0 ) , new VertexElement ( "NORMAL" , 12 , VertexElementFormat . Vector3 , 0 , 0 ) , new VertexElement ( "INSTANCE_OFFSET" , 0 , VertexElementFormat . Vector3 , 1 , 1 ) , new VertexElement ( "INSTANCE_COLOR" , 12 , VertexElementFormat . Vector3 , 1 , 1 ) ] ) ; geometry . addSubMesh ( 0 , indices . length ) ; geometry . instanceCount = instanceCount ; return geometry ; } /**
 * Create custom instance shader.
 */ function initCustomShader ( ) { const shader = Shader . create ( "CustomShader" , `uniform mat4 u_MVPMat;
      attribute vec4 POSITION;
      attribute vec3 INSTANCE_OFFSET;
      attribute vec3 INSTANCE_COLOR;
      
      uniform mat4 u_MVMat;
      
      varying vec3 v_position;
      varying vec3 v_color;
      
      void main() {
        vec4 position = POSITION;
        position.xyz += INSTANCE_OFFSET;
        gl_Position = u_MVPMat * position;

        v_color = INSTANCE_COLOR;
      }` , `
      varying vec3 v_color;
      uniform vec4 u_color;
      
      void main() {
        vec4 color = vec4(v_color,1.0);
        gl_FragColor = color;
      }
      ` ) ; return shader ; }