/* | |
* 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); | |
} | |
} | |