@@ -42,14 +42,25 @@ public class GrainFilter extends Filter {
4242 @ GenerateFieldPort (name = "tile_size" , hasDefault = true )
4343 private int mTileSize = 640 ;
4444
45- private Program mProgram ;
45+ private Program mGrainProgram ;
46+ private Program mNoiseProgram ;
4647
4748 private int mWidth = 0 ;
4849 private int mHeight = 0 ;
4950 private int mTarget = FrameFormat .TARGET_UNSPECIFIED ;
5051
51- private Frame mNoiseFrame = null ;
52- private Random mRandom ;
52+ private Random mRandom = new Random ();
53+
54+ private final String mNoiseShader =
55+ "precision mediump float;\n " +
56+ "uniform vec2 seed;\n " +
57+ "varying vec2 v_texcoord;\n " +
58+ "float rand(vec2 loc) {\n " +
59+ " return fract(sin(dot(loc, vec2(12.9898, 78.233))) * 43758.5453);\n " +
60+ "}\n " +
61+ "void main() {\n " +
62+ " gl_FragColor = vec4(rand(v_texcoord + seed), 0.0, 0.0, 1.0);\n " +
63+ "}\n " ;
5364
5465 private final String mGrainShader =
5566 "precision mediump float;\n " +
@@ -75,8 +86,6 @@ public class GrainFilter extends Filter {
7586
7687 public GrainFilter (String name ) {
7788 super (name );
78-
79- mRandom = new Random ();
8089 }
8190
8291 @ Override
@@ -93,9 +102,13 @@ public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) {
93102 public void initProgram (FilterContext context , int target ) {
94103 switch (target ) {
95104 case FrameFormat .TARGET_GPU :
96- ShaderProgram shaderProgram = new ShaderProgram (context , mGrainShader );
105+ ShaderProgram shaderProgram = new ShaderProgram (context , mNoiseShader );
106+ shaderProgram .setMaximumTileSize (mTileSize );
107+ mNoiseProgram = shaderProgram ;
108+
109+ shaderProgram = new ShaderProgram (context , mGrainShader );
97110 shaderProgram .setMaximumTileSize (mTileSize );
98- mProgram = shaderProgram ;
111+ mGrainProgram = shaderProgram ;
99112 break ;
100113
101114 default :
@@ -106,82 +119,70 @@ public void initProgram(FilterContext context, int target) {
106119 }
107120
108121 private void updateParameters () {
109- mProgram .setHostValue ("scale" , mScale );
122+ float seed [] = { mRandom .nextFloat (), mRandom .nextFloat () };
123+ mNoiseProgram .setHostValue ("seed" , seed );
124+
125+ mGrainProgram .setHostValue ("scale" , mScale );
110126 }
111127
112128 private void updateFrameSize (int width , int height ) {
113129 mWidth = width ;
114130 mHeight = height ;
115131
116- if (mProgram != null ) {
117- mProgram .setHostValue ("stepX" , 0.5f / mWidth );
118- mProgram .setHostValue ("stepY" , 0.5f / mHeight );
132+ if (mGrainProgram != null ) {
133+ mGrainProgram .setHostValue ("stepX" , 0.5f / mWidth );
134+ mGrainProgram .setHostValue ("stepY" , 0.5f / mHeight );
119135 updateParameters ();
120136 }
121137 }
122138
123139 @ Override
124140 public void fieldPortValueUpdated (String name , FilterContext context ) {
125- if (mProgram != null ) {
141+ if (mGrainProgram != null && mNoiseProgram != null ) {
126142 updateParameters ();
127143 }
128144 }
129145
130- @ Override
131- public void tearDown (FilterContext context ) {
132- if (mNoiseFrame != null ) {
133- mNoiseFrame .release ();
134- mNoiseFrame = null ;
135- }
136- }
137-
138146 @ Override
139147 public void process (FilterContext context ) {
140148 // Get input frame
141149 Frame input = pullInput ("image" );
142150 FrameFormat inputFormat = input .getFormat ();
143151
152+ FrameFormat noiseFormat = ImageFormat .create (inputFormat .getWidth () / 2 ,
153+ inputFormat .getHeight () / 2 ,
154+ ImageFormat .COLORSPACE_RGBA ,
155+ FrameFormat .TARGET_GPU );
156+
157+ // Create noise frame
158+ Frame noiseFrame = context .getFrameManager ().newFrame (inputFormat );
159+
144160 // Create output frame
145161 Frame output = context .getFrameManager ().newFrame (inputFormat );
146162
147163 // Create program if not created already
148- if (mProgram == null || inputFormat .getTarget () != mTarget ) {
164+ if (mNoiseProgram == null || mGrainProgram == null || inputFormat .getTarget () != mTarget ) {
149165 initProgram (context , inputFormat .getTarget ());
150166 updateParameters ();
151167 }
152168
153169 // Check if the frame size has changed
154170 if (inputFormat .getWidth () != mWidth || inputFormat .getHeight () != mHeight ) {
155171 updateFrameSize (inputFormat .getWidth (), inputFormat .getHeight ());
156-
157- int [] buffer = new int [mWidth * mHeight ];
158- for (int i = 0 ; i < mWidth * mHeight ; ++i ) {
159- buffer [i ] = (mRandom .nextInt (256 ) < RAND_THRESHOLD ) ?
160- mRandom .nextInt (256 ) : 0 ;
161- }
162- FrameFormat format = ImageFormat .create (mWidth , mHeight ,
163- ImageFormat .COLORSPACE_RGBA ,
164- FrameFormat .TARGET_GPU );
165- if (mNoiseFrame != null ) {
166- mNoiseFrame .release ();
167- }
168- mNoiseFrame = context .getFrameManager ().newFrame (format );
169- mNoiseFrame .setInts (buffer );
170172 }
171173
172- if (mNoiseFrame .getFormat ().getWidth () != mWidth ||
173- mNoiseFrame .getFormat ().getHeight () != mHeight ) {
174- throw new RuntimeException ("Random map and imput image size mismatch!" );
175- }
174+ Frame [] empty = {};
175+ mNoiseProgram .process (empty , noiseFrame );
176176
177177 // Process
178- Frame [] inputs = {input , mNoiseFrame };
179- mProgram .process (inputs , output );
178+ Frame [] inputs = {input , noiseFrame };
179+ mGrainProgram .process (inputs , output );
180180
181181 // Push output
182182 pushOutput ("image" , output );
183183
184184 // Release pushed frame
185185 output .release ();
186+ noiseFrame .release ();
186187 }
187188}
0 commit comments