@@ -0,0 +1,3309 @@
+/*%0A * Copyright 2016 Mario Guggenberger %3Cmg@protyposis.net%3E%0A *%0A * Licensed under the Apache License, Version 2.0 (the %22License%22);%0A * you may not use this file except in compliance with the License.%0A * You may obtain a copy of the License at%0A *%0A *     http://www.apache.org/licenses/LICENSE-2.0%0A *%0A * Unless required by applicable law or agreed to in writing, software%0A * distributed under the License is distributed on an %22AS IS%22 BASIS,%0A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.%0A * See the License for the specific language governing permissions and%0A * limitations under the License.%0A */%0A%0Apackage net.protyposis.android.spectaculum.effects;%0A%0Aimport net.protyposis.android.spectaculum.gles.Framebuffer;%0Aimport net.protyposis.android.spectaculum.gles.Texture2D;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.Collections;%0Aimport java.util.Iterator;%0Aimport java.util.List;%0A%0A/**%0A * Creates a stack of effects that are applied sequentially one by one. Useful to combine effects%0A * together, e.g. convert the image with a toon effect, adjust its brightness and add a watermark on top.%0A */%0Apublic class StackEffect extends BaseEffect %7B%0A%0A    private List%3CEffect%3E mEffects;%0A    private Framebuffer mFramebuffer;%0A%0A    public StackEffect(String name) %7B%0A        super(name);%0A        mEffects = new ArrayList%3C%3E();%0A    %7D%0A%0A    public StackEffect(String name, Effect... effects) %7B%0A        this(name);%0A        addEffects(effects);%0A    %7D%0A%0A    public StackEffect() %7B%0A        this((String)null);%0A    %7D%0A%0A    public StackEffect(Effect... effects) %7B%0A        this(null, effects);%0A    %7D%0A%0A    public void addEffects(Effect... effects) %7B%0A        Collections.addAll(mEffects, effects);%0A    %7D%0A%0A    @Override%0A    public void init(int width, int height) %7B%0A        mFramebuffer = new Framebuffer(width, height);%0A%0A        for (Effect e : mEffects) %7B%0A            e.init(width, height);%0A        %7D%0A    %7D%0A%0A    @Override%0A    public void apply(Texture2D source, Framebuffer target) %7B%0A        Iterator%3CEffect%3E i = mEffects.iterator();%0A%0A        /*%0A         * The first source texture must always be the passed in texture, the last output framebuffer%0A         * must always be the passed in target framebuffer. In between, we need to switch source%0A         * textures and target framebuffers between the passed in external framebuffer and the internal%0A         * framebuffer, because we cannot read and write to the same framebuffer in one render pass.%0A         * If the number of effects is even, we start by writing the internal framebuffer, else we%0A         * start with the external framebuffer.%0A         */%0A        Framebuffer internalFB = mFramebuffer;%0A        Framebuffer externalFB = target;%0A        boolean useInternalFB = mEffects.size() %25 2 == 0; // keeps track of which framebuffer to use as target%0A%0A        while(i.hasNext()) %7B%0A            Effect e = i.next();%0A%0A            if(i.hasNext()) %7B%0A                e.apply(source, useInternalFB ? internalFB : externalFB);%0A                source = useInternalFB ? internalFB.getTexture() : externalFB.getTexture();%0A                useInternalFB = !useInternalFB; // switch framebuffer flag%0A            %7D else %7B%0A                // Last effect; always write result to the target framebuffer%0A                e.apply(source, target);%0A            %7D%0A        %7D%0A    %7D%0A%7D%0A

Add StackEffect to combine multiple effects