11/*
2- * Copyright (c) 2009-2021 jMonkeyEngine
2+ * Copyright (c) 2009-2025 jMonkeyEngine
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
4040import com .jme3 .math .Vector2f ;
4141import com .jme3 .math .Vector3f ;
4242import com .jme3 .post .Filter ;
43- import com .jme3 .post .Filter .Pass ;
4443import com .jme3 .renderer .RenderManager ;
4544import com .jme3 .renderer .Renderer ;
4645import com .jme3 .renderer .ViewPort ;
6261public class SSAOFilter extends Filter {
6362
6463 private Pass normalPass ;
65- private Vector3f frustumCorner ;
66- private Vector2f frustumNearFar ;
67- private Vector2f [] samples = {new Vector2f (1.0f , 0.0f ), new Vector2f (-1.0f , 0.0f ), new Vector2f (0.0f , 1.0f ), new Vector2f (0.0f , -1.0f )};
64+ private final Vector2f [] samples = {
65+ new Vector2f (1.0f , 0.0f ),
66+ new Vector2f (-1.0f , 0.0f ),
67+ new Vector2f (0.0f , 1.0f ),
68+ new Vector2f (0.0f , -1.0f )
69+ };
6870 private float sampleRadius = 5.1f ;
6971 private float intensity = 1.5f ;
7072 private float scale = 0.2f ;
7173 private float bias = 0.1f ;
74+ private boolean approximateNormals = false ;
7275 private boolean useOnlyAo = false ;
7376 private boolean useAo = true ;
7477 private Material ssaoMat ;
75- private Pass ssaoPass ;
76- // private Material downSampleMat;
77- // private Pass downSamplePass;
78- private float downSampleFactor = 1f ;
7978 private RenderManager renderManager ;
8079 private ViewPort viewPort ;
81- private boolean approximateNormals = false ;
8280
8381 /**
8482 * Create a Screen Space Ambient Occlusion Filter
@@ -89,10 +87,11 @@ public SSAOFilter() {
8987
9088 /**
9189 * Create a Screen Space Ambient Occlusion Filter
90+ *
9291 * @param sampleRadius The radius of the area where random samples will be picked. default 5.1f
93- * @param intensity intensity of the resulting AO. default 1.2f
94- * @param scale distance between occluders and occludee. default 0.2f
95- * @param bias the width of the occlusion cone considered by the occludee. default 0.1f
92+ * @param intensity intensity of the resulting AO. default 1.5f
93+ * @param scale distance between occluders and occludee. default 0.2f
94+ * @param bias the width of the occlusion cone considered by the occludee. default 0.1f
9695 */
9796 public SSAOFilter (float sampleRadius , float intensity , float scale , float bias ) {
9897 this ();
@@ -126,38 +125,32 @@ protected Material getMaterial() {
126125 }
127126
128127 @ Override
129- protected void initFilter (AssetManager manager , RenderManager renderManager , ViewPort vp , int w , int h ) {
128+ protected void initFilter (AssetManager assetManager , RenderManager renderManager , ViewPort vp , int w , int h ) {
130129 this .renderManager = renderManager ;
131130 this .viewPort = vp ;
132131 int screenWidth = w ;
133132 int screenHeight = h ;
133+ float downSampleFactor = 1f ;
134134 postRenderPasses = new ArrayList <Pass >();
135135
136136 normalPass = new Pass ();
137137 normalPass .init (renderManager .getRenderer (), (int ) (screenWidth / downSampleFactor ), (int ) (screenHeight / downSampleFactor ), Format .RGBA8 , Format .Depth );
138138
139-
140- frustumNearFar = new Vector2f ();
141-
139+ Vector2f frustumNearFar = new Vector2f ();
142140 float farY = (vp .getCamera ().getFrustumTop () / vp .getCamera ().getFrustumNear ()) * vp .getCamera ().getFrustumFar ();
143141 float farX = farY * (screenWidth / (float ) screenHeight );
144- frustumCorner = new Vector3f (farX , farY , vp .getCamera ().getFrustumFar ());
142+ Vector3f frustumCorner = new Vector3f (farX , farY , vp .getCamera ().getFrustumFar ());
145143 frustumNearFar .x = vp .getCamera ().getFrustumNear ();
146144 frustumNearFar .y = vp .getCamera ().getFrustumFar ();
147145
148-
149-
150-
151-
152146 //ssao Pass
153- ssaoMat = new Material (manager , "Common/MatDefs/SSAO/ssao.j3md" );
147+ ssaoMat = new Material (assetManager , "Common/MatDefs/SSAO/ssao.j3md" );
154148 ssaoMat .setTexture ("Normals" , normalPass .getRenderedTexture ());
155- Texture random = manager .loadTexture ("Common/MatDefs/SSAO/Textures/random.png" );
149+ Texture random = assetManager .loadTexture ("Common/MatDefs/SSAO/Textures/random.png" );
156150 random .setWrap (Texture .WrapMode .Repeat );
157151 ssaoMat .setTexture ("RandomMap" , random );
158152
159- ssaoPass = new Pass ("SSAO pass" ) {
160-
153+ Pass ssaoPass = new Pass ("SSAO pass" ) {
161154 @ Override
162155 public boolean requiresDepthAsTexture () {
163156 return true ;
@@ -168,18 +161,18 @@ public boolean requiresDepthAsTexture() {
168161// ssaoPass.getRenderedTexture().setMinFilter(Texture.MinFilter.Trilinear);
169162// ssaoPass.getRenderedTexture().setMagFilter(Texture.MagFilter.Bilinear);
170163 postRenderPasses .add (ssaoPass );
171- material = new Material (manager , "Common/MatDefs/SSAO/ssaoBlur.j3md" );
164+ material = new Material (assetManager , "Common/MatDefs/SSAO/ssaoBlur.j3md" );
172165 material .setTexture ("SSAOMap" , ssaoPass .getRenderedTexture ());
166+ material .setVector2 ("FrustumNearFar" , frustumNearFar );
167+ material .setBoolean ("UseAo" , useAo );
168+ material .setBoolean ("UseOnlyAo" , useOnlyAo );
173169
174170 ssaoMat .setVector3 ("FrustumCorner" , frustumCorner );
175171 ssaoMat .setFloat ("SampleRadius" , sampleRadius );
176172 ssaoMat .setFloat ("Intensity" , intensity );
177173 ssaoMat .setFloat ("Scale" , scale );
178174 ssaoMat .setFloat ("Bias" , bias );
179- material .setBoolean ("UseAo" , useAo );
180- material .setBoolean ("UseOnlyAo" , useOnlyAo );
181175 ssaoMat .setVector2 ("FrustumNearFar" , frustumNearFar );
182- material .setVector2 ("FrustumNearFar" , frustumNearFar );
183176 ssaoMat .setParam ("Samples" , VarType .Vector2Array , samples );
184177 ssaoMat .setBoolean ("ApproximateNormals" , approximateNormals );
185178
@@ -189,7 +182,6 @@ public boolean requiresDepthAsTexture() {
189182 float blurScale = 2f ;
190183 material .setFloat ("XScale" , blurScale * xScale );
191184 material .setFloat ("YScale" , blurScale * yScale );
192-
193185 }
194186
195187 @ Override
@@ -198,18 +190,20 @@ protected void cleanUpFilter(Renderer r) {
198190 }
199191
200192 /**
201- * Return the bias<br>
202- * see {@link #setBias(float bias)}
203- * @return bias
193+ * Returns the bias value used in the SSAO calculation.
194+ *
195+ * @return The bias value.
196+ * @see #setBias(float)
204197 */
205198 public float getBias () {
206199 return bias ;
207200 }
208201
209202 /**
210- * Sets the width of the occlusion cone considered by the occludee default is 0.1f
203+ * Sets the width of the occlusion cone considered by the occludee.
204+ * A higher bias means a wider cone, resulting in less self-occlusion.
211205 *
212- * @param bias the desired width (default=0.1)
206+ * @param bias The desired bias value (default: 0.1f).
213207 */
214208 public void setBias (float bias ) {
215209 this .bias = bias ;
@@ -219,62 +213,65 @@ public void setBias(float bias) {
219213 }
220214
221215 /**
222- * returns the ambient occlusion intensity
223- * @return intensity
216+ * Returns the ambient occlusion intensity.
217+ *
218+ * @return The intensity value.
224219 */
225220 public float getIntensity () {
226221 return intensity ;
227222 }
228223
229224 /**
230- * Sets the Ambient occlusion intensity default is 1.5
225+ * Sets the ambient occlusion intensity. A higher intensity makes the ambient
226+ * occlusion effect more pronounced.
231227 *
232- * @param intensity the desired intensity (default=1.5)
228+ * @param intensity The desired intensity (default: 1.5f).
233229 */
234230 public void setIntensity (float intensity ) {
235231 this .intensity = intensity ;
236232 if (ssaoMat != null ) {
237233 ssaoMat .setFloat ("Intensity" , intensity );
238234 }
239-
240235 }
241236
242237 /**
243- * returns the sample radius<br>
244- * see {link setSampleRadius(float sampleRadius)}
245- * @return the sample radius
238+ * Returns the sample radius used in the SSAO calculation.
239+ *
240+ * @return The sample radius.
241+ * @see #setSampleRadius(float)
246242 */
247243 public float getSampleRadius () {
248244 return sampleRadius ;
249245 }
250246
251247 /**
252- * Sets the radius of the area where random samples will be picked default 5.1f
248+ * Sets the radius of the area where random samples will be picked for SSAO.
249+ * A larger radius considers more distant occluders.
253250 *
254- * @param sampleRadius the desired radius (default=5.1)
251+ * @param sampleRadius The desired radius (default: 5.1f).
255252 */
256253 public void setSampleRadius (float sampleRadius ) {
257254 this .sampleRadius = sampleRadius ;
258255 if (ssaoMat != null ) {
259256 ssaoMat .setFloat ("SampleRadius" , sampleRadius );
260257 }
261-
262258 }
263259
264260 /**
265- * returns the scale<br>
266- * see {@link #setScale(float scale)}
267- * @return scale
261+ * Returns the scale value used in the SSAO calculation.
262+ *
263+ * @return The scale value.
264+ * @see #setScale(float)
268265 */
269266 public float getScale () {
270267 return scale ;
271268 }
272269
273270 /**
274- *
275- * Returns the distance between occluders and occludee. default 0.2f
271+ * Sets the distance between occluders and occludee for SSAO.
272+ * This essentially controls the "thickness" of the ambient occlusion.
276273 *
277- * @param scale the desired distance (default=0.2)
274+ * @param scale The desired distance (default: 0.2f).
278275 */
279276 public void setScale (float scale ) {
280277 this .scale = scale ;
@@ -284,15 +281,38 @@ public void setScale(float scale) {
284281 }
285282
286283 /**
287- * debugging only , will be removed
284+ * Sets whether to use approximate normals for the SSAO calculation.
285+ * If `true`, normals are derived from the depth buffer. If `false`, a separate
286+ * normal pass is rendered.
287+ *
288+ * @param approximateNormals `true` to use approximate normals, `false` to use a normal pass.
289+ */
290+ public void setApproximateNormals (boolean approximateNormals ) {
291+ this .approximateNormals = approximateNormals ;
292+ if (ssaoMat != null ) {
293+ ssaoMat .setBoolean ("ApproximateNormals" , approximateNormals );
294+ }
295+ }
296+
297+ /**
298+ * Checks if approximate normals are being used for SSAO calculation.
299+ *
300+ * @return `true` if approximate normals are used, `false` otherwise.
301+ */
302+ public boolean isApproximateNormals () {
303+ return approximateNormals ;
304+ }
305+
306+ /**
307+ * debugging only, will be removed
288308 * @return true if using ambient occlusion
289309 */
290310 public boolean isUseAo () {
291311 return useAo ;
292312 }
293313
294314 /**
295- * debugging only , will be removed
315+ * debugging only, will be removed
296316 *
297317 * @param useAo true to enable, false to disable (default=true)
298318 */
@@ -301,30 +321,18 @@ public void setUseAo(boolean useAo) {
301321 if (material != null ) {
302322 material .setBoolean ("UseAo" , useAo );
303323 }
304-
305- }
306-
307- public void setApproximateNormals (boolean approximateNormals ) {
308- this .approximateNormals = approximateNormals ;
309- if (ssaoMat != null ) {
310- ssaoMat .setBoolean ("ApproximateNormals" , approximateNormals );
311- }
312- }
313-
314- public boolean isApproximateNormals () {
315- return approximateNormals ;
316324 }
317325
318326 /**
319- * debugging only , will be removed
327+ * debugging only, will be removed
320328 * @return useOnlyAo
321329 */
322330 public boolean isUseOnlyAo () {
323331 return useOnlyAo ;
324332 }
325333
326334 /**
327- * debugging only , will be removed
335+ * debugging only, will be removed
328336 *
329337 * @param useOnlyAo true to enable, false to disable (default=false)
330338 */
@@ -343,6 +351,7 @@ public void write(JmeExporter ex) throws IOException {
343351 oc .write (intensity , "intensity" , 1.5f );
344352 oc .write (scale , "scale" , 0.2f );
345353 oc .write (bias , "bias" , 0.1f );
354+ oc .write (approximateNormals , "approximateNormals" , false );
346355 }
347356
348357 @ Override
@@ -353,5 +362,6 @@ public void read(JmeImporter im) throws IOException {
353362 intensity = ic .readFloat ("intensity" , 1.5f );
354363 scale = ic .readFloat ("scale" , 0.2f );
355364 bias = ic .readFloat ("bias" , 0.1f );
365+ approximateNormals = ic .readBoolean ("approximateNormals" , false );
356366 }
357367}
0 commit comments