blob: 28f916c864c7f99f13bd68f578e4f54aabd329bb [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.testapp;
import java.util.ArrayList;
import com.android.scenegraph.*;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.renderscript.*;
import android.renderscript.Allocation.MipmapControl;
import android.renderscript.Element.Builder;
import android.renderscript.Font.Style;
import android.renderscript.Program.TextureType;
import android.renderscript.ProgramStore.DepthFunc;
import android.util.Log;
class FullscreenBlur {
static TextureRenderTarget sRenderTargetBlur0Color;
static TextureRenderTarget sRenderTargetBlur0Depth;
static TextureRenderTarget sRenderTargetBlur1Color;
static TextureRenderTarget sRenderTargetBlur1Depth;
static TextureRenderTarget sRenderTargetBlur2Color;
static TextureRenderTarget sRenderTargetBlur2Depth;
static FragmentShader mPF_BlurH;
static FragmentShader mPF_BlurV;
static FragmentShader mPF_SelectColor;
static FragmentShader mPF_Texture;
static VertexShader mPV_Paint;
static VertexShader mPV_Blur;
static int targetWidth;
static int targetHeight;
// This is only used when full screen blur is enabled
// Basically, it's the offscreen render targets
static void createRenderTargets(RenderScriptGL rs, int w, int h) {
targetWidth = w/8;
targetHeight = h/8;
Type.Builder b = new Type.Builder(rs, Element.RGBA_8888(rs));
Type renderType = b.setX(targetWidth).setY(targetHeight).create();
int usage = Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET;
sRenderTargetBlur0Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
sRenderTargetBlur1Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
sRenderTargetBlur2Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
b = new Type.Builder(rs, Element.createPixel(rs, Element.DataType.UNSIGNED_16,
Element.DataKind.PIXEL_DEPTH));
renderType = b.setX(targetWidth).setY(targetHeight).create();
usage = Allocation.USAGE_GRAPHICS_RENDER_TARGET;
sRenderTargetBlur0Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
sRenderTargetBlur1Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
sRenderTargetBlur2Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
}
static void addOffsets(Renderable quad, float advance) {
quad.appendSourceParams(new Float4Param("blurOffset0", - advance * 2.5f));
quad.appendSourceParams(new Float4Param("blurOffset1", - advance * 0.5f));
quad.appendSourceParams(new Float4Param("blurOffset2", advance * 1.5f));
quad.appendSourceParams(new Float4Param("blurOffset3", advance * 3.5f));
}
static RenderPass addPass(Scene scene, Camera cam, TextureRenderTarget color, TextureRenderTarget depth) {
RenderPass pass = new RenderPass();
pass.setColorTarget(color);
pass.setDepthTarget(depth);
pass.setShouldClearColor(false);
pass.setShouldClearDepth(false);
pass.setCamera(cam);
scene.appendRenderPass(pass);
return pass;
}
static void addBlurPasses(Scene scene, RenderScriptGL rs, Camera cam) {
SceneManager sceneManager = SceneManager.getInstance();
ArrayList<RenderableBase> allDraw = scene.getRenderables();
int numDraw = allDraw.size();
ProgramRaster cullNone = ProgramRaster.CULL_NONE(rs);
ProgramStore blendAdd = SceneManager.BLEND_ADD_DEPTH_NONE(rs);
ProgramStore blendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(rs);
RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture, blendAdd, cullNone);
RenderState selectCol = new RenderState(mPV_Blur, mPF_SelectColor, blendNone, cullNone);
RenderState hBlur = new RenderState(mPV_Blur, mPF_BlurH, blendNone, cullNone);
RenderState vBlur = new RenderState(mPV_Blur, mPF_BlurV, blendNone, cullNone);
// Renders the scene off screen
RenderPass blurSourcePass = addPass(scene, cam,
sRenderTargetBlur0Color,
sRenderTargetBlur0Depth);
blurSourcePass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f));
blurSourcePass.setShouldClearColor(true);
blurSourcePass.setClearDepth(1.0f);
blurSourcePass.setShouldClearDepth(true);
for (int i = 0; i < numDraw; i ++) {
blurSourcePass.appendRenderable((Renderable)allDraw.get(i));
}
// Pass for selecting bright colors
RenderPass selectColorPass = addPass(scene, cam,
sRenderTargetBlur2Color,
sRenderTargetBlur2Depth);
Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadS", selectCol);
quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur0Color));
selectColorPass.appendRenderable(quad);
// Horizontal blur
RenderPass horizontalBlurPass = addPass(scene, cam,
sRenderTargetBlur1Color,
sRenderTargetBlur1Depth);
quad = sceneManager.getRenderableQuad("ScreenAlignedQuadH", hBlur);
quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));
addOffsets(quad, 1.0f / (float)targetWidth);
horizontalBlurPass.appendRenderable(quad);
// Vertical Blur
RenderPass verticalBlurPass = addPass(scene, cam,
sRenderTargetBlur2Color,
sRenderTargetBlur2Depth);
quad = sceneManager.getRenderableQuad("ScreenAlignedQuadV", vBlur);
quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur1Color));
addOffsets(quad, 1.0f / (float)targetHeight);
verticalBlurPass.appendRenderable(quad);
}
// Additively renders the blurred colors on top of the scene
static void addCompositePass(Scene scene, RenderScriptGL rs, Camera cam) {
SceneManager sceneManager = SceneManager.getInstance();
RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture,
SceneManager.BLEND_ADD_DEPTH_NONE(rs),
ProgramRaster.CULL_NONE(rs));
RenderPass compositePass = addPass(scene, cam, null, null);
Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadComposite", drawTex);
quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));
compositePass.appendRenderable(quad);
}
static private FragmentShader getShader(Resources res, RenderScriptGL rs,
int resID, Type constants) {
FragmentShader.Builder fb = new FragmentShader.Builder(rs);
fb.setShader(res, resID);
fb.addTexture(TextureType.TEXTURE_2D, "color");
if (constants != null) {
fb.setObjectConst(constants);
}
FragmentShader prog = fb.create();
prog.getProgram().bindSampler(Sampler.CLAMP_LINEAR(rs), 0);
return prog;
}
static void initShaders(Resources res, RenderScriptGL rs) {
ScriptField_BlurOffsets blurConst = new ScriptField_BlurOffsets(rs, 1);
VertexShader.Builder vb = new VertexShader.Builder(rs);
vb.addInput(ScriptField_VertexShaderInputs.createElement(rs));
vb.setShader(res, R.raw.blur_vertex);
mPV_Blur = vb.create();
mPF_Texture = getShader(res, rs, R.raw.texture, null);
mPF_Texture.getProgram().bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(rs), 0);
mPF_BlurH = getShader(res, rs, R.raw.blur_h, blurConst.getAllocation().getType());
mPF_BlurV = getShader(res, rs, R.raw.blur_v, blurConst.getAllocation().getType());
mPF_SelectColor = getShader(res, rs, R.raw.select_color, null);
}
}