render method

void render(
  1. Object3D scene,
  2. Camera camera
)

Implementation

void render(Object3D scene, Camera camera) {

  if (_isContextLost) return;

  // update scene graph
  if (scene.matrixWorldAutoUpdate) scene.updateMatrixWorld();

  // update camera matrices and frustum

  if (camera.parent == null && camera.matrixWorldAutoUpdate) camera.updateMatrixWorld();

  if ( xr.enabled && xr.isPresenting ) {
    if (xr.cameraAutoUpdate) xr.updateCamera( camera );
  	if(kIsWeb) camera = xr.getCamera();
  }

  if (scene is Scene) {
    scene.onBeforeRender?.call(renderer: this, scene: scene, camera: camera, renderTarget: _currentRenderTarget);
  }

  currentRenderState = renderStates.get(scene, renderCallDepth: renderStateStack.length);
  currentRenderState!.init(camera);

  renderStateStack.add(currentRenderState!);

  projScreenMatrix.multiply2(camera.projectionMatrix, camera.matrixWorldInverse);

  _frustum.setFromMatrix(projScreenMatrix);

  _localClippingEnabled = localClippingEnabled;
  _clippingEnabled = clipping.init(clippingPlanes, _localClippingEnabled);

  currentRenderList = renderLists.get(scene, renderListStack.length);
  currentRenderList!.init();

  renderListStack.add(currentRenderList!);

  if ( xr.enabled && xr.isPresenting) {
    final depthSensingMesh = xr.getDepthSensingMesh();
    if ( depthSensingMesh != null ) {
      projectObject( depthSensingMesh, camera, - double.maxFinite.toInt(), this.sortObjects );
    }
  }

  projectObject(scene, camera, 0, sortObjects);

  currentRenderList!.finish();

  if (sortObjects) {
    currentRenderList!.sort(_opaqueSort, _transparentSort);
  }

		renderBackground = !xr.enabled || !xr.isPresenting || !xr.hasDepthSensing();
		if ( renderBackground ) {
    background.addToRenderList( currentRenderList!, scene );
  }

  info.render['frame'] = info.render['frame']!+1;

  if (_clippingEnabled) clipping.beginShadows();
  final shadowsArray = currentRenderState!.state.shadowsArray;
  if(kIsWeb){
    shadowMap.render(shadowsArray, scene, camera);
  }
  if (_clippingEnabled) clipping.endShadows();

  if (info.autoReset) info.reset();

  // render scene
  final opaqueObjects = currentRenderList?.opaque;
		final transmissiveObjects = currentRenderList?.transmissive;

  currentRenderState!.setupLights(physicallyCorrectLights);

  if (camera is ArrayCamera) {

    final cameras = camera.cameras;
    if (transmissiveObjects != null && transmissiveObjects.isNotEmpty) {
      for (int i = 0, l = cameras.length; i < l; i ++ ) {
        final camera2 = cameras[ i ];
        renderTransmissionPass( opaqueObjects!, transmissiveObjects, scene, camera2);
      }
    }
			if (renderBackground) background.render(scene);
    for (int i = 0, l = cameras.length; i < l; i++) {
      final camera2 = cameras[i];
      renderScene(currentRenderList!, scene, camera2, camera2.viewport);
    }
  }
  else {
			if ( renderBackground ) background.render( scene );
    renderScene(currentRenderList!, scene, camera);
    if(transmissiveObjects != null && transmissiveObjects.isNotEmpty) renderTransmissionPass( opaqueObjects!, transmissiveObjects, scene, camera );
  }

  if(!kIsWeb){
    shadowMap.render(shadowsArray, scene, camera);
  }

  if (_currentRenderTarget != null) {
    // resolve multisample renderbuffers to a single-sample texture if necessary
    textures.updateMultisampleRenderTarget(_currentRenderTarget!);
    // Generate mipmap if we're using any kind of mipmap filtering
    textures.updateRenderTargetMipmap(_currentRenderTarget!);
  }

  if (scene is Scene) {
    scene.onAfterRender?.call(renderer: this, scene: scene, camera: camera);
  }

  _gl.flush();

  bindingStates.resetDefaultState();
  _currentMaterialId = -1;
  _currentCamera = null;

  renderStateStack.removeLast();
  if (renderStateStack.isNotEmpty) {
    currentRenderState = renderStateStack[renderStateStack.length - 1];
    if (_clippingEnabled) clipping.setGlobalState(clippingPlanes, currentRenderState!.state.camera! );
  }
  else {
    currentRenderState = null;
  }

  renderListStack.removeLast();

  if (renderListStack.isNotEmpty) {
    currentRenderList = renderListStack[renderListStack.length - 1];
  }
  else {
    currentRenderList = null;
  }
}