renderObjectFiltered method

  1. @override
void renderObjectFiltered(
  1. RenderState renderState,
  2. RenderObject renderObject
)
override

Implementation

@override
void renderObjectFiltered(
    RenderState renderState, RenderObject renderObject) {
  final bounds = renderObject.bounds;
  var filters = renderObject.filters;
  final pixelRatio = math.sqrt(renderState.globalMatrix.det.abs());

  var boundsLeft = bounds.left.floor();
  var boundsTop = bounds.top.floor();
  var boundsRight = bounds.right.ceil();
  var boundsBottom = bounds.bottom.ceil();

  for (var i = 0; i < filters.length; i++) {
    final overlap = filters[i].overlap;
    boundsLeft += overlap.left;
    boundsTop += overlap.top;
    boundsRight += overlap.right;
    boundsBottom += overlap.bottom;
  }

  boundsLeft = (boundsLeft * pixelRatio).floor();
  boundsTop = (boundsTop * pixelRatio).floor();
  boundsRight = (boundsRight * pixelRatio).ceil();
  boundsBottom = (boundsBottom * pixelRatio).ceil();

  final boundsWidth = boundsRight - boundsLeft;
  final boundsHeight = boundsBottom - boundsTop;

  final initialRenderFrameBuffer = activeRenderFrameBuffer;
  final initialProjectionMatrix = activeProjectionMatrix.clone();
  RenderFrameBuffer? filterRenderFrameBuffer =
      getRenderFrameBuffer(boundsWidth, boundsHeight);

  final filterProjectionMatrix = Matrix3D.fromIdentity();
  filterProjectionMatrix.scale(2.0 / boundsWidth, 2.0 / boundsHeight, 1.0);
  filterProjectionMatrix.translate(-1.0, -1.0, 0.0);

  var filterRenderState = RenderState(this);
  filterRenderState.globalMatrix.scale(pixelRatio, pixelRatio);
  filterRenderState.globalMatrix.translate(-boundsLeft, -boundsTop);

  final renderFrameBufferMap = <int, RenderFrameBuffer?>{};
  renderFrameBufferMap[0] = filterRenderFrameBuffer;

  //----------------------------------------------

  activateRenderFrameBuffer(filterRenderFrameBuffer);
  activateProjectionMatrix(filterProjectionMatrix);
  activateBlendMode(BlendMode.NORMAL);
  clear(0);

  if (filters.isEmpty) {
    // Don't render anything
  } else if (filters[0].isSimple &&
      renderObject is _RenderTextureQuadObject) {
    final renderTextureQuad = renderObject.renderTextureQuad;
    renderTextureQuadFiltered(
        filterRenderState, renderTextureQuad, [filters[0]]);
    filters = filters.sublist(1);
  } else {
    renderObject.render(filterRenderState);
  }

  //----------------------------------------------

  for (var i = 0; i < filters.length; i++) {
    RenderTextureQuad sourceRenderTextureQuad;
    final filter = filters[i];

    final renderPassSources = filter.renderPassSources;
    final renderPassTargets = filter.renderPassTargets;

    for (var pass = 0; pass < renderPassSources.length; pass++) {
      final renderPassSource = renderPassSources[pass];
      final renderPassTarget = renderPassTargets[pass];

      final RenderFrameBuffer sourceRenderFrameBuffer;

      // get sourceRenderTextureQuad

      if (renderFrameBufferMap.containsKey(renderPassSource)) {
        sourceRenderFrameBuffer = renderFrameBufferMap[renderPassSource]!;
        if (sourceRenderFrameBuffer.renderTexture == null) {
          throw StateError('Invalid renderPassSource!');
        }
        sourceRenderTextureQuad = RenderTextureQuad(
            sourceRenderFrameBuffer.renderTexture!,
            Rectangle<int>(0, 0, boundsWidth, boundsHeight),
            Rectangle<int>(
                -boundsLeft, -boundsTop, boundsWidth, boundsHeight),
            0,
            pixelRatio);
      } else {
        throw StateError('Invalid renderPassSource!');
      }

      // get targetRenderFrameBuffer

      if (i == filters.length - 1 &&
          renderPassTarget == renderPassTargets.last) {
        filterRenderFrameBuffer = null;
        filterRenderState = renderState;
        activateRenderFrameBuffer(initialRenderFrameBuffer);
        activateProjectionMatrix(initialProjectionMatrix);
        activateBlendMode(filterRenderState.globalBlendMode);
      } else if (renderFrameBufferMap.containsKey(renderPassTarget)) {
        filterRenderFrameBuffer = renderFrameBufferMap[renderPassTarget];
        activateRenderFrameBuffer(filterRenderFrameBuffer);
        activateBlendMode(BlendMode.NORMAL);
      } else {
        filterRenderFrameBuffer =
            getRenderFrameBuffer(boundsWidth, boundsHeight);
        renderFrameBufferMap[renderPassTarget] = filterRenderFrameBuffer;
        activateRenderFrameBuffer(filterRenderFrameBuffer);
        activateBlendMode(BlendMode.NORMAL);
        clear(0);
      }

      // render filter

      filter.renderFilter(filterRenderState, sourceRenderTextureQuad, pass);

      // release obsolete source RenderFrameBuffer

      if (renderPassSources
          .skip(pass + 1)
          .every((rps) => rps != renderPassSource)) {
        renderFrameBufferMap.remove(renderPassSource);
        releaseRenderFrameBuffer(sourceRenderFrameBuffer);
      }
    }

    renderFrameBufferMap.clear();
    renderFrameBufferMap[0] = filterRenderFrameBuffer;
  }
}