Skip to content

Commit d1290c4

Browse files
committed
add gaussian blur renderer && update samples
1 parent b8947a3 commit d1290c4

File tree

12 files changed

+225
-39
lines changed

12 files changed

+225
-39
lines changed

app/src/main/java/io/github/kenneycode/fusion/demo/fragment/SampleBasicUsage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import io.github.kenneycode.fusion.process.RenderChain
1414
import io.github.kenneycode.fusion.process.RenderPipeline
1515
import io.github.kenneycode.fusion.program.GLProgramPool
1616
import io.github.kenneycode.fusion.renderer.CropRenderer
17+
import io.github.kenneycode.fusion.renderer.GaussianBlurRenderer
1718
import io.github.kenneycode.fusion.renderer.LUTRenderer
1819
import io.github.kenneycode.fusion.renderer.ScaleRenderer
1920
import io.github.kenneycode.fusion.texture.TexturePool
@@ -44,6 +45,7 @@ class SampleBasicUsage : Fragment() {
4445
.addRenderer(ScaleRenderer().apply { setFlip(false, true); setScale(0.8f) })
4546
.addRenderer(CropRenderer().apply { setCropRect(0.1f, 0.9f, 0.8f, 0.2f) })
4647
.addRenderer(LUTRenderer().apply { setLUTImage(Util.decodeBitmapFromAssets("test_lut.png")!!); setLUTStrength(0.8f) })
48+
.addRenderer(GaussianBlurRenderer().apply { setBlurRadius(10) })
4749

4850
// 创建RenderPipeline,连接输入、渲染器与输出
4951
renderPipeline = RenderPipeline

app/src/main/java/io/github/kenneycode/fusion/demo/fragment/SampleVideo.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ import io.github.kenneycode.fusion.input.FusionVideo
1414
import io.github.kenneycode.fusion.process.RenderChain
1515
import io.github.kenneycode.fusion.process.RenderPipeline
1616
import io.github.kenneycode.fusion.program.GLProgramPool
17-
import io.github.kenneycode.fusion.renderer.CropRenderer
18-
import io.github.kenneycode.fusion.renderer.LUTRenderer
19-
import io.github.kenneycode.fusion.renderer.OES2RGBARenderer
20-
import io.github.kenneycode.fusion.renderer.ScaleRenderer
17+
import io.github.kenneycode.fusion.renderer.*
2118
import io.github.kenneycode.fusion.texture.TexturePool
2219
import kotlinx.android.synthetic.main.fragment_sample_fusion_gl_texture_view.*
2320

@@ -45,6 +42,7 @@ class SampleVideo : Fragment() {
4542
val renderer = RenderChain.create()
4643
.addRenderer(OES2RGBARenderer())
4744
.addRenderer(LUTRenderer().apply { setLUTImage(Util.decodeBitmapFromAssets("test_lut.png")!!); setLUTStrength(0.8f) })
45+
.addRenderer(GaussianBlurRenderer().apply { setBlurRadius(10) })
4846

4947
// 创建RenderPipeline,连接输入、渲染器与输出
5048
renderPipeline = RenderPipeline

libfusion/src/main/java/io/github/kenneycode/fusion/common/Constants.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,30 @@ class Constants {
101101
" gl_FragColor = newColor;\n" +
102102
"}"
103103

104+
val GAUSSIAN_BLUR_FRAGMENT_SHADER =
105+
"precision mediump float;\n" +
106+
"varying vec2 v_textureCoordinate;\n" +
107+
"uniform sampler2D u_texture;\n" +
108+
"uniform float weights[6];\n" +
109+
"uniform float hOffset;\n" +
110+
"uniform float vOffset;\n" +
111+
"uniform int orientation;\n" +
112+
"void main() {\n" +
113+
"\tvec4 color = texture2D(u_texture, v_textureCoordinate) * weights[0];\n" +
114+
"\tif (orientation == 0) {\n" +
115+
"\t\tfor (int i = 1; i < 6; ++i) {\n" +
116+
"\t\t\tcolor += texture2D(u_texture, vec2(v_textureCoordinate.x - float(i) * hOffset, v_textureCoordinate.y)) * weights[i];\n" +
117+
"\t\t\tcolor += texture2D(u_texture, vec2(v_textureCoordinate.x + float(i) * hOffset, v_textureCoordinate.y)) * weights[i];\n" +
118+
"\t\t}\n" +
119+
"\t} else {\n" +
120+
"\t\tfor (int i = 1; i < 6; ++i) {\n" +
121+
"\t\t\tcolor += texture2D(u_texture, vec2(v_textureCoordinate.x, v_textureCoordinate.y - float(i) * vOffset)) * weights[i];\n" +
122+
"\t\t\tcolor += texture2D(u_texture, vec2(v_textureCoordinate.x, v_textureCoordinate.y + float(i) * vOffset)) * weights[i];\n" +
123+
"\t\t}\n" +
124+
"\t}\n" +
125+
" gl_FragColor = color;\n" +
126+
"}"
127+
104128
val SIMPLE_VERTEX = floatArrayOf(-1f, -1f, -1f, 1f, 1f, 1f, -1f, -1f, 1f, 1f, 1f, -1f)
105129
val SIMPLE_VERTEX_FLIP_X = floatArrayOf(1f, -1f, 1f, 1f, -1f, 1f, 1f, -1f, -1f, 1f, -1f, -1f)
106130
val SIMPLE_VERTEX_FLIP_Y = floatArrayOf(-1f, 1f, -1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, 1f, 1f)

libfusion/src/main/java/io/github/kenneycode/fusion/input/FusionVideo.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class FusionVideo(private val videoPath: String) : RenderPipeline.Input {
4646
surface = Surface(surfaceTexture)
4747
videoPlayer.setDataSource(videoPath)
4848
videoPlayer.setSurface(surface)
49+
videoPlayer.isLooping = true
4950
videoPlayer.prepare()
5051
videoSize = Size(videoPlayer.videoWidth, videoPlayer.videoHeight)
5152
}

libfusion/src/main/java/io/github/kenneycode/fusion/parameter/AttributeParameter.kt

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package io.github.kenneycode.fusion.parameter
22

33
import android.opengl.GLES20
4+
import java.nio.ByteBuffer
5+
import java.nio.ByteOrder
6+
7+
import android.opengl.GLES20.GL_FLOAT
8+
import android.opengl.GLES20.glEnableVertexAttribArray
9+
import android.opengl.GLES20.glVertexAttribPointer
410
import io.github.kenneycode.fusion.util.Util
511

612
/**
@@ -9,11 +15,11 @@ import io.github.kenneycode.fusion.util.Util
915
*
1016
* http://www.github.com/kenneycode/fusion
1117
*
12-
* Shader attribute参数基类
18+
* Shader attribute参数
1319
*
1420
*/
1521

16-
abstract class AttributeParameter(key : String) : Parameter(key) {
22+
class AttributeParameter(key: String, private var value: FloatArray, private val componentCount: Int = 2) : Parameter(key) {
1723

1824
/**
1925
*
@@ -30,4 +36,22 @@ abstract class AttributeParameter(key : String) : Parameter(key) {
3036
onBind(location)
3137
}
3238

39+
override fun onBind(location: Int) {
40+
val vertexBuffer = ByteBuffer.allocateDirect(value.size * java.lang.Float.SIZE / 8)
41+
.order(ByteOrder.nativeOrder())
42+
.asFloatBuffer()
43+
.apply {
44+
put(value)
45+
position(0)
46+
}
47+
glVertexAttribPointer(location, componentCount, GL_FLOAT, false, 0, vertexBuffer)
48+
glEnableVertexAttribArray(location)
49+
}
50+
51+
override fun update(value: Any) {
52+
(value as? FloatArray)?.let {
53+
this.value = it
54+
}
55+
}
56+
3357
}

libfusion/src/main/java/io/github/kenneycode/fusion/parameter/FloatArrayParameter.kt

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package io.github.kenneycode.fusion.parameter
22

3-
import java.nio.ByteBuffer
4-
import java.nio.ByteOrder
5-
6-
import android.opengl.GLES20.GL_FLOAT
7-
import android.opengl.GLES20.glEnableVertexAttribArray
8-
import android.opengl.GLES20.glVertexAttribPointer
3+
import android.opengl.GLES20.*
94

105
/**
116
*
@@ -17,18 +12,10 @@ import android.opengl.GLES20.glVertexAttribPointer
1712
*
1813
*/
1914

20-
class FloatArrayParameter(key: String, private var value: FloatArray, private val componentCount: Int = 2) : AttributeParameter(key) {
15+
class FloatArrayParameter(key: String, private var value: FloatArray) : UniformParameter(key) {
2116

2217
override fun onBind(location: Int) {
23-
val vertexBuffer = ByteBuffer.allocateDirect(value.size * java.lang.Float.SIZE / 8)
24-
.order(ByteOrder.nativeOrder())
25-
.asFloatBuffer()
26-
.apply {
27-
put(value)
28-
position(0)
29-
}
30-
glVertexAttribPointer(location, componentCount, GL_FLOAT, false, 0, vertexBuffer)
31-
glEnableVertexAttribArray(location)
18+
glUniform1fv(location, value.size, value, 0)
3219
}
3320

3421
override fun update(value: Any) {

libfusion/src/main/java/io/github/kenneycode/fusion/process/RenderChain.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import io.github.kenneycode.fusion.texture.Texture
1414
*
1515
*/
1616

17-
class RenderChain private constructor(): Renderer {
17+
open class RenderChain protected constructor(): Renderer {
1818

1919
private val renderGraph = RenderGraph.create()
2020
private var tailRenderer: Renderer? = null
@@ -116,6 +116,10 @@ class RenderChain private constructor(): Renderer {
116116
return renderGraph.render()
117117
}
118118

119+
fun getInput(): List<Texture> {
120+
return renderGraph.getInput()
121+
}
122+
119123
/**
120124
*
121125
* 释放资源

libfusion/src/main/java/io/github/kenneycode/fusion/program/GLProgram.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
package io.github.kenneycode.fusion.program
22

3+
import android.opengl.GLES20.*
4+
import android.util.Log
35
import io.github.kenneycode.fusion.common.Ref
46
import io.github.kenneycode.fusion.common.Shader
57
import io.github.kenneycode.fusion.parameter.Parameter
68

7-
import android.opengl.GLES20.GL_FRAGMENT_SHADER
8-
import android.opengl.GLES20.GL_VERTEX_SHADER
9-
import android.opengl.GLES20.glAttachShader
10-
import android.opengl.GLES20.glCompileShader
11-
import android.opengl.GLES20.glCreateProgram
12-
import android.opengl.GLES20.glCreateShader
13-
import android.opengl.GLES20.glDeleteProgram
14-
import android.opengl.GLES20.glDeleteShader
15-
import android.opengl.GLES20.glIsProgram
16-
import android.opengl.GLES20.glLinkProgram
17-
import android.opengl.GLES20.glShaderSource
18-
import android.opengl.GLES20.glUseProgram
9+
import io.github.kenneycode.fusion.util.Util
1910

2011
/**
2112
*
@@ -49,12 +40,28 @@ class GLProgram(val shader: Shader) : Ref() {
4940
glShaderSource(fragmentShader, shader!!.fragmentShader)
5041

5142
glCompileShader(vertexShader)
43+
glGetShaderInfoLog(vertexShader).let {
44+
if (it.isNotEmpty()) {
45+
Log.e("debug", "vertex shader info log = $it")
46+
}
47+
}
48+
5249
glCompileShader(fragmentShader)
50+
glGetShaderInfoLog(fragmentShader).let {
51+
if (it.isNotEmpty()) {
52+
Log.e("debug", "fragment shader info log = $it")
53+
}
54+
}
5355

5456
glAttachShader(program, vertexShader)
5557
glAttachShader(program, fragmentShader)
5658

5759
glLinkProgram(program)
60+
glGetProgramInfoLog(program).let {
61+
if (it.isNotEmpty()) {
62+
Log.e("debug", "program info log = $it")
63+
}
64+
}
5865

5966
glDeleteShader(vertexShader)
6067
glDeleteShader(fragmentShader)

libfusion/src/main/java/io/github/kenneycode/fusion/renderer/GLRenderer.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,26 @@ interface GLRenderer : Renderer {
8888
*/
8989
fun setUniformFloat(key: String, value: Float)
9090

91+
/**
92+
*
93+
* 设置float数组参数
94+
*
95+
* @param key float数组参数名
96+
* @param value float数组参数
97+
*
98+
*/
99+
fun setUniformFloatArray(key: String, value: FloatArray)
100+
101+
/**
102+
*
103+
* 设置int参数
104+
*
105+
* @param key int参数名
106+
* @param value int参数
107+
*
108+
*/
109+
fun setUniformInt(key: String, value: Int)
110+
91111
/**
92112
*
93113
* 设置MVP
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package io.github.kenneycode.fusion.renderer
2+
3+
import io.github.kenneycode.fusion.common.Constants
4+
import io.github.kenneycode.fusion.process.RenderChain
5+
import io.github.kenneycode.fusion.texture.Texture
6+
7+
/**
8+
*
9+
* Coded by kenney
10+
*
11+
* http://www.github.com/kenneycode/fusion
12+
*
13+
* 高斯模糊 renderer
14+
*
15+
*/
16+
17+
class GaussianBlurRenderer : RenderChain() {
18+
19+
companion object {
20+
21+
class ParameterKey {
22+
23+
companion object {
24+
val WEIGHTS = "weights"
25+
val H_OFFSET = "hOffset"
26+
val V_OFFSET = "vOffset"
27+
val ORIENTATION = "orientation"
28+
}
29+
30+
}
31+
32+
private val HALF_SAMPLE_POINTS = 5
33+
34+
}
35+
36+
private val hRenderer = SimpleRenderer(Constants.SIMPLE_VERTEX_SHADER, Constants.GAUSSIAN_BLUR_FRAGMENT_SHADER)
37+
private val vRenderer = SimpleRenderer(Constants.SIMPLE_VERTEX_SHADER, Constants.GAUSSIAN_BLUR_FRAGMENT_SHADER)
38+
private var blurRadius = 3
39+
40+
override fun init() {
41+
val weights = normalize(calculateWeights(5f))
42+
hRenderer.apply {
43+
setUniformInt(ParameterKey.ORIENTATION, 0)
44+
setUniformFloatArray(ParameterKey.WEIGHTS, weights)
45+
addRenderer(this)
46+
}
47+
vRenderer.apply {
48+
setUniformInt(ParameterKey.ORIENTATION, 1)
49+
setUniformFloatArray(ParameterKey.WEIGHTS, weights)
50+
addRenderer(this)
51+
}
52+
super.init()
53+
}
54+
55+
/**
56+
*
57+
* 设置模糊半径
58+
*
59+
* @param blurRadius 模糊半径
60+
*
61+
*/
62+
fun setBlurRadius(blurRadius: Int) {
63+
this.blurRadius = blurRadius
64+
}
65+
66+
override fun render() {
67+
val inputWidth = getInput().first().width
68+
val inputHeight = getInput().first().height
69+
hRenderer.setUniformFloat(ParameterKey.H_OFFSET, blurRadius.toFloat() / inputWidth / HALF_SAMPLE_POINTS)
70+
hRenderer.setUniformFloat(ParameterKey.V_OFFSET, blurRadius.toFloat() / inputHeight / HALF_SAMPLE_POINTS)
71+
vRenderer.setUniformFloat(ParameterKey.H_OFFSET, blurRadius.toFloat() / inputWidth / HALF_SAMPLE_POINTS)
72+
vRenderer.setUniformFloat(ParameterKey.V_OFFSET, blurRadius.toFloat() / inputHeight / HALF_SAMPLE_POINTS)
73+
super.render()
74+
}
75+
76+
private fun calculateWeights(sigma: Float): FloatArray {
77+
val weights = FloatArray(6)
78+
weights[0] = gaussianFunc(0f, 0f, sigma)
79+
for (i in 1 until 6) {
80+
weights[i] = gaussianFunc(i.toFloat(), 0f, sigma)
81+
}
82+
return weights
83+
}
84+
85+
private fun normalize(weights: FloatArray): FloatArray {
86+
var sum = weights[0]
87+
for (i in 1 until weights.size) {
88+
sum += weights[i] * 2
89+
}
90+
for (i in weights.indices) {
91+
weights[i] /= sum
92+
}
93+
return weights
94+
}
95+
96+
private fun gaussianFunc(x: Float, y: Float, sigma: Float): Float {
97+
return ((1f / (2.0 * Math.PI * sigma * sigma)) * Math.pow(Math.E, -(x * x + y * y) / (2.0 * sigma))).toFloat()
98+
}
99+
100+
}

libfusion/src/main/java/io/github/kenneycode/fusion/renderer/OES2RGBARenderer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class OES2RGBARenderer : SimpleRenderer(Constants.OES_VERTEX_SHADER, Constants.O
2020
}
2121

2222
override fun update(data: MutableMap<String, Any>): Boolean {
23-
setUniformMat4("u_stMatrix", data[DataKeys.ST_MATRIX] as FloatArray? ?: Constants.IDENTITY_MATRIX)
23+
setUniformMat4("u_stMatrix", data[DataKeys.ST_MATRIX] as? FloatArray ?: Constants.IDENTITY_MATRIX)
2424
return true
2525
}
2626

0 commit comments

Comments
 (0)