diff --git a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
index aa8896a951..fa0e14ab77 100644
--- a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
+++ b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2022 jMonkeyEngine
+ * Copyright (c) 2009-2025 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,18 +32,28 @@
package com.jme3.post;
import com.jme3.asset.AssetManager;
-import com.jme3.export.*;
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.export.Savable;
import com.jme3.material.Material;
-import com.jme3.profile.*;
-import com.jme3.renderer.*;
+import com.jme3.profile.AppProfiler;
+import com.jme3.profile.SpStep;
+import com.jme3.renderer.Camera;
+import com.jme3.renderer.Caps;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.Renderer;
+import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer;
+import com.jme3.texture.FrameBuffer.FrameBufferTarget;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
-import com.jme3.texture.FrameBuffer.FrameBufferTarget;
import com.jme3.ui.Picture;
import com.jme3.util.SafeArrayList;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -52,13 +62,22 @@
import java.util.List;
/**
- * A FilterPostProcessor is a processor that can apply several {@link Filter}s to a rendered scene
- * It manages a list of filters that will be applied in the order in which they've been added to the list
- * @author Rémy Bouquet aka Nehon
+ * A `FilterPostProcessor` is a {@link SceneProcessor} that can apply several
+ * {@link Filter}s to a rendered scene. It manages a list of filters that will be
+ * applied in the order in which they have been added. This processor handles
+ * rendering the main scene to an offscreen framebuffer, then applying each enabled
+ * filter sequentially, optionally with anti-aliasing (multisampling) and depth texture
+ * support.
+ *
+ * @author Nehon
*/
public class FilterPostProcessor implements SceneProcessor, Savable {
+ /**
+ * The simple name of this class, used for profiling.
+ */
public static final String FPP = FilterPostProcessor.class.getSimpleName();
+
private RenderManager renderManager;
private Renderer renderer;
private ViewPort viewPort;
@@ -89,23 +108,28 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
private Format depthFormat = Format.Depth;
/**
- * Create a FilterProcessor
- * @param assetManager the assetManager
+ * Creates a new `FilterPostProcessor`.
+ *
+ * @param assetManager The asset manager to be used by filters for loading assets.
*/
public FilterPostProcessor(AssetManager assetManager) {
this.assetManager = assetManager;
}
/**
- * Don't use this constructor, use {@link #FilterPostProcessor(AssetManager assetManager)}
- * This constructor is used for serialization only
+ * Serialization-only constructor. Do not use this constructor directly;
+ * use {@link #FilterPostProcessor(AssetManager)}.
*/
protected FilterPostProcessor() {
}
/**
- * Adds a filter to the filters list
- * @param filter the filter to add
+ * Adds a filter to the list of filters to be applied. Filters are applied
+ * in the order they are added. If the processor is already initialized,
+ * the filter is immediately initialized as well.
+ *
+ * @param filter The filter to add (not null).
+ * @throws IllegalArgumentException If the provided filter is null.
*/
public void addFilter(Filter filter) {
if (filter == null) {
@@ -118,13 +142,14 @@ public void addFilter(Filter filter) {
}
setFilterState(filter, filter.isEnabled());
-
}
/**
- * removes this filters from the filters list
+ * Removes a specific filter from the list. The filter's `cleanup` method
+ * is called upon removal.
*
- * @param filter the Filter to remove (not null)
+ * @param filter The filter to remove (not null).
+ * @throws IllegalArgumentException If the provided filter is null.
*/
public void removeFilter(Filter filter) {
if (filter == null) {
@@ -135,10 +160,22 @@ public void removeFilter(Filter filter) {
updateLastFilterIndex();
}
+ /**
+ * Returns an iterator over the filters currently managed by this processor.
+ *
+ * @return An `Iterator` of {@link Filter} objects.
+ */
public Iterator getFilterIterator() {
return filters.iterator();
}
+ /**
+ * Initializes the `FilterPostProcessor`. This method is called by the
+ * `RenderManager` when the processor is added to a viewport.
+ *
+ * @param rm The `RenderManager` instance.
+ * @param vp The `ViewPort` this processor is attached to.
+ */
@Override
public void initialize(RenderManager rm, ViewPort vp) {
renderManager = rm;
@@ -148,10 +185,11 @@ public void initialize(RenderManager rm, ViewPort vp) {
fsQuad.setWidth(1);
fsQuad.setHeight(1);
+ // Determine optimal framebuffer format based on renderer capabilities
if (!renderer.getCaps().contains(Caps.PackedFloatTexture)) {
- if(renderer.getCaps().contains(Caps.FloatColorBufferRGB)){
+ if (renderer.getCaps().contains(Caps.FloatColorBufferRGB)) {
fbFormat = Format.RGB16F;
- } else if(renderer.getCaps().contains(Caps.FloatColorBufferRGBA)){
+ } else if (renderer.getCaps().contains(Caps.FloatColorBufferRGBA)) {
fbFormat = Format.RGBA16F;
} else {
fbFormat = Format.RGB8;
@@ -160,34 +198,47 @@ public void initialize(RenderManager rm, ViewPort vp) {
Camera cam = vp.getCamera();
- //save view port dimensions
+ // Save original viewport dimensions
left = cam.getViewPortLeft();
right = cam.getViewPortRight();
top = cam.getViewPortTop();
bottom = cam.getViewPortBottom();
originalWidth = cam.getWidth();
originalHeight = cam.getHeight();
- //first call to reshape
+
+ // First call to reshape to set up internal framebuffers and textures
reshape(vp, cam.getWidth(), cam.getHeight());
}
+ /**
+ * Returns the default color buffer format used for the internal rendering
+ * passes of the filters. This format is determined during initialization
+ * based on the renderer's capabilities.
+ *
+ * @return The default `Format` for the filter pass textures.
+ */
public Format getDefaultPassTextureFormat() {
return fbFormat;
}
/**
- * init the given filter
- * @param filter
- * @param vp
+ * Initializes a single filter. This method is called when a filter is added
+ * or when the post-processor is initialized/reshaped. It sets the processor
+ * for the filter, handles depth texture requirements, and calls the filter's
+ * `init` method.
+ *
+ * @param filter The {@link Filter} to initialize.
+ * @param vp The `ViewPort` associated with this processor.
*/
private void initFilter(Filter filter, ViewPort vp) {
filter.setProcessor(this);
if (filter.isRequiresDepthTexture()) {
if (!computeDepth && renderFrameBuffer != null) {
+ // If depth texture is required and not yet created, create it
depthTexture = new Texture2D(width, height, depthFormat);
renderFrameBuffer.setDepthTarget(FrameBufferTarget.newTarget(depthTexture));
}
- computeDepth = true;
+ computeDepth = true; // Mark that depth texture is needed
filter.init(assetManager, renderManager, vp, width, height);
filter.setDepthTexture(depthTexture);
} else {
@@ -196,45 +247,52 @@ private void initFilter(Filter filter, ViewPort vp) {
}
/**
- * renders a filter on a fullscreen quad
- * @param r
- * @param buff
- * @param mat
+ * Renders a filter's material onto a full-screen quad. This method
+ * handles setting up the rendering context (framebuffer, camera, material)
+ * for a filter pass. It correctly resizes the camera and adjusts material
+ * states based on whether the target buffer is the final output buffer or an
+ * intermediate filter buffer.
+ *
+ * @param r The `Renderer` instance.
+ * @param buff The `FrameBuffer` to render to.
+ * @param mat The `Material` to use for rendering the filter.
*/
private void renderProcessing(Renderer r, FrameBuffer buff, Material mat) {
+ // Adjust camera and viewport based on target framebuffer
if (buff == outputBuffer) {
viewPort.getCamera().resize(originalWidth, originalHeight, false);
viewPort.getCamera().setViewPort(left, right, bottom, top);
- // update is redundant because resize and setViewPort will both
- // run the appropriate (and same) onXXXChange methods.
- // Also, update() updates some things that don't need to be updated.
- //viewPort.getCamera().update();
- renderManager.setCamera( viewPort.getCamera(), false);
+ // viewPort.getCamera().update(); // Redundant as resize and setViewPort call onXXXChange
+ renderManager.setCamera(viewPort.getCamera(), false);
+ // Disable depth test/write for final pass to prevent artifacts
if (mat.getAdditionalRenderState().isDepthWrite()) {
mat.getAdditionalRenderState().setDepthTest(false);
mat.getAdditionalRenderState().setDepthWrite(false);
}
} else {
+ // Rendering to an intermediate framebuffer for a filter pass
viewPort.getCamera().resize(buff.getWidth(), buff.getHeight(), false);
viewPort.getCamera().setViewPort(0, 1, 0, 1);
- // update is redundant because resize and setViewPort will both
- // run the appropriate (and same) onXXXChange methods.
- // Also, update() updates some things that don't need to be updated.
- //viewPort.getCamera().update();
- renderManager.setCamera( viewPort.getCamera(), false);
+ // viewPort.getCamera().update(); // Redundant as resize and setViewPort call onXXXChange
+ renderManager.setCamera(viewPort.getCamera(), false);
+ // Enable depth test/write for intermediate passes if material needs it
mat.getAdditionalRenderState().setDepthTest(true);
mat.getAdditionalRenderState().setDepthWrite(true);
}
-
fsQuad.setMaterial(mat);
fsQuad.updateGeometricState();
r.setFrameBuffer(buff);
- r.clearBuffers(true, true, true);
+ r.clearBuffers(true, true, true); // Clear color, depth, and stencil buffers
renderManager.renderGeometry(fsQuad);
}
+ /**
+ * Checks if the `FilterPostProcessor` has been initialized.
+ *
+ * @return True if initialized, false otherwise.
+ */
@Override
public boolean isInitialized() {
return viewPort != null;
@@ -244,30 +302,44 @@ public boolean isInitialized() {
public void postQueue(RenderQueue rq) {
for (Filter filter : filters.getArray()) {
if (filter.isEnabled()) {
- if (prof != null) prof.spStep(SpStep.ProcPostQueue, FPP, filter.getName());
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPostQueue, FPP, filter.getName());
+ }
filter.postQueue(rq);
}
}
}
/**
- * iterate through the filter list and renders filters
- * @param r
- * @param sceneFb
+ * Renders the chain of filters. This method is the core of the post-processing.
+ * It iterates through each enabled filter, handling pre-filter passes,
+ * setting up textures (scene, depth), performing the main filter rendering,
+ * and managing intermediate framebuffers.
+ *
+ * @param r The `Renderer` instance.
+ * @param sceneFb The framebuffer containing the rendered scene (either MS or single-sample).
*/
private void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
Texture2D tex = filterTexture;
FrameBuffer buff = sceneFb;
boolean msDepth = depthTexture != null && depthTexture.getImage().getMultiSamples() > 1;
+
for (int i = 0; i < filters.size(); i++) {
Filter filter = filters.get(i);
- if (prof != null) prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName());
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName());
+ }
+
if (filter.isEnabled()) {
+ // Handle additional passes a filter might have (e.g., blur passes)
if (filter.getPostRenderPasses() != null) {
- for (Iterator it1 = filter.getPostRenderPasses().iterator(); it1.hasNext();) {
- Filter.Pass pass = it1.next();
- if (prof != null) prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), pass.toString());
+ for (Filter.Pass pass : filter.getPostRenderPasses()) {
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), pass.toString());
+ }
pass.beforeRender();
+
+ // Set scene texture if required by the pass
if (pass.requiresSceneAsTexture()) {
pass.getPassMaterial().setTexture("Texture", tex);
if (tex.getImage().getMultiSamples() > 1) {
@@ -277,6 +349,8 @@ private void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
}
}
+
+ // Set depth texture if required by the pass
if (pass.requiresDepthAsTexture()) {
pass.getPassMaterial().setTexture("DepthTexture", depthTexture);
if (msDepth) {
@@ -288,7 +362,9 @@ private void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
renderProcessing(r, pass.getRenderFrameBuffer(), pass.getPassMaterial());
}
}
- if (prof != null) prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), "postFrame");
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), "postFrame");
+ }
filter.postFrame(renderManager, viewPort, buff, sceneFb);
Material mat = filter.getMaterial();
@@ -305,23 +381,31 @@ private void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
}
}
+ // Apply bilinear filtering if requested by the filter
boolean wantsBilinear = filter.isRequiresBilinear();
if (wantsBilinear) {
tex.setMagFilter(Texture.MagFilter.Bilinear);
tex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
}
+ // Determine target framebuffer and source texture for the next pass
buff = outputBuffer;
if (i != lastFilterIndex) {
buff = filter.getRenderFrameBuffer();
tex = filter.getRenderedTexture();
-
}
- if (prof != null) prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), "render");
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), "render");
+ }
+ // Render the main filter pass
renderProcessing(r, buff, mat);
- if (prof != null) prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), "postFilter");
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPostFrame, FPP, filter.getName(), "postFilter");
+ }
+ // Call filter's postFilter for final adjustments
filter.postFilter(r, buff);
+ // Revert texture filtering if it was changed
if (wantsBilinear) {
tex.setMagFilter(Texture.MagFilter.Nearest);
tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
@@ -339,10 +423,14 @@ public void postFrame(FrameBuffer out) {
} else if (renderFrameBufferMS != null) {
sceneBuffer = renderFrameBufferMS;
}
+
+ // Execute the filter chain
renderFilterChain(renderer, sceneBuffer);
+
+ // Restore the original output framebuffer for the viewport
renderer.setFrameBuffer(outputBuffer);
- //viewport can be null if no filters are enabled
+ // viewport can be null if no filters are enabled
if (viewPort != null) {
renderManager.setCamera(viewPort.getCamera(), false);
}
@@ -351,40 +439,44 @@ public void postFrame(FrameBuffer out) {
@Override
public void preFrame(float tpf) {
if (filters.isEmpty() || lastFilterIndex == -1) {
- //If the camera is initialized and there are no filter to render, the camera viewport is restored as it was
+ // If no filters are enabled, restore the camera's original viewport
+ // and output framebuffer to bypass the post-processor.
if (cameraInit) {
viewPort.getCamera().resize(originalWidth, originalHeight, true);
viewPort.getCamera().setViewPort(left, right, bottom, top);
viewPort.setOutputFrameBuffer(outputBuffer);
cameraInit = false;
}
-
} else {
- setupViewPortFrameBuffer();
- //if we are in a multiview situation we need to resize the camera
- //to the viewport size so that the back buffer is rendered correctly
- if (multiView) {
+ setupViewPortFrameBuffer();
+ // If in a multi-view situation, resize the camera to the viewport size
+ // so that the back buffer is rendered correctly for filtering.
+ if (multiView) {
viewPort.getCamera().resize(width, height, false);
viewPort.getCamera().setViewPort(0, 1, 0, 1);
viewPort.getCamera().update();
renderManager.setCamera(viewPort.getCamera(), false);
- }
+ }
}
+ // Call preFrame on all enabled filters
for (Filter filter : filters.getArray()) {
if (filter.isEnabled()) {
- if (prof != null) prof.spStep(SpStep.ProcPreFrame, FPP, filter.getName());
+ if (prof != null) {
+ prof.spStep(SpStep.ProcPreFrame, FPP, filter.getName());
+ }
filter.preFrame(tpf);
}
}
-
}
/**
- * sets the filter to enabled or disabled
+ * Sets the enabled state of a specific filter. If the filter is part of
+ * this processor's list, its `enabled` flag is updated, and the
+ * `lastFilterIndex` is recomputed.
*
- * @param filter the Filter to modify (not null)
- * @param enabled true to enable, false to disable
+ * @param filter The {@link Filter} to modify (not null).
+ * @param enabled True to enable the filter, false to disable it.
*/
protected void setFilterState(Filter filter, boolean enabled) {
if (filters.contains(filter)) {
@@ -394,26 +486,27 @@ protected void setFilterState(Filter filter, boolean enabled) {
}
/**
- * compute the index of the last filter to render
+ * Computes the index of the last enabled filter in the list. This is used
+ * to determine which filter should render to the final output framebuffer
+ * and which should render to intermediate framebuffers. If no filters are
+ * enabled, the viewport's output framebuffer is restored to its original.
*/
private void updateLastFilterIndex() {
lastFilterIndex = -1;
for (int i = filters.size() - 1; i >= 0 && lastFilterIndex == -1; i--) {
if (filters.get(i).isEnabled()) {
lastFilterIndex = i;
- // The FPP is initialized, but the viewport framebuffer is the
- // original out framebuffer, so we must recover from a situation
- // where no filter was enabled. So we set the correct framebuffer
- // on the viewport.
- if(isInitialized() && viewPort.getOutputFrameBuffer()==outputBuffer){
+ // If the FPP is initialized but the viewport framebuffer is the
+ // original output framebuffer (meaning no filter was enabled
+ // previously), then redirect it to the FPP's internal framebuffer.
+ if (isInitialized() && viewPort.getOutputFrameBuffer() == outputBuffer) {
setupViewPortFrameBuffer();
}
return;
}
}
+ // If no filters are enabled, restore the original framebuffer to the viewport.
if (isInitialized() && lastFilterIndex == -1) {
- //There is no enabled filter, we restore the original framebuffer
- //to the viewport to bypass the fpp.
viewPort.setOutputFrameBuffer(outputBuffer);
}
}
@@ -421,40 +514,56 @@ private void updateLastFilterIndex() {
@Override
public void cleanup() {
if (viewPort != null) {
- //reset the viewport camera viewport to its initial value
+ // Reset the viewport camera and output framebuffer to their initial values
viewPort.getCamera().resize(originalWidth, originalHeight, true);
viewPort.getCamera().setViewPort(left, right, bottom, top);
viewPort.setOutputFrameBuffer(outputBuffer);
viewPort = null;
- if(renderFrameBuffer != null){
+ // Dispose of internal framebuffers and textures
+ if (renderFrameBuffer != null) {
renderFrameBuffer.dispose();
}
- if(depthTexture!=null){
- depthTexture.getImage().dispose();
+ if (depthTexture != null) {
+ depthTexture.getImage().dispose();
}
filterTexture.getImage().dispose();
- if(renderFrameBufferMS != null){
- renderFrameBufferMS.dispose();
+ if (renderFrameBufferMS != null) {
+ renderFrameBufferMS.dispose();
}
for (Filter filter : filters.getArray()) {
filter.cleanup(renderer);
}
}
-
}
+ /**
+ * Sets the profiler instance for this processor.
+ *
+ * @param profiler The `AppProfiler` instance to use for performance monitoring.
+ */
@Override
public void setProfiler(AppProfiler profiler) {
this.prof = profiler;
}
+ /**
+ * Reshapes the `FilterPostProcessor` when the viewport or canvas size changes.
+ * This method recalculates internal framebuffer dimensions, creates new
+ * framebuffers and textures if necessary (e.g., for anti-aliasing), and
+ * reinitializes all filters with the new dimensions. It also detects
+ * multi-view scenarios.
+ *
+ * @param vp The `ViewPort` being reshaped.
+ * @param w The new width of the viewport's canvas.
+ * @param h The new height of the viewport's canvas.
+ */
@Override
public void reshape(ViewPort vp, int w, int h) {
Camera cam = vp.getCamera();
- //this has no effect at first init but is useful when resizing the canvas with multi views
+ // This sets the camera viewport to its full extent (0-1) for rendering to the FPP's internal buffer.
cam.setViewPort(left, right, bottom, top);
- //resizing the camera to fit the new viewport and saving original dimensions
+ // Resizing the camera to fit the new viewport and saving original dimensions
cam.resize(w, h, true);
left = cam.getViewPortLeft();
right = cam.getViewPortRight();
@@ -463,16 +572,16 @@ public void reshape(ViewPort vp, int w, int h) {
originalWidth = w;
originalHeight = h;
- //computing real dimension of the viewport and resizing the camera
+ // Computing real dimension of the viewport based on its relative size within the canvas
width = (int) (w * (Math.abs(right - left)));
height = (int) (h * (Math.abs(bottom - top)));
width = Math.max(1, width);
height = Math.max(1, height);
- //Testing original versus actual viewport dimension.
- //If they are different we are in a multiview situation and
- //camera must be handled differently
- if(originalWidth!=width || originalHeight!=height){
+ // Test if original dimensions differ from actual viewport dimensions.
+ // If they are different, we are in a multiview situation, and the
+ // camera must be handled differently (e.g., resized to the sub-viewport).
+ if (originalWidth != width || originalHeight != height) {
multiView = true;
}
@@ -485,9 +594,11 @@ public void reshape(ViewPort vp, int w, int h) {
Collection caps = renderer.getCaps();
- //antialiasing on filters only supported in opengl 3 due to depth read problem
+ // antialiasing on filters only supported in opengl 3 due to depth read problem
if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample)) {
renderFrameBufferMS = new FrameBuffer(width, height, numSamples);
+
+ // If OpenGL 3.2+ is supported, multisampled textures can be attached directly
if (caps.contains(Caps.OpenGL32)) {
Texture2D msColor = new Texture2D(width, height, numSamples, fbFormat);
Texture2D msDepth = new Texture2D(width, height, numSamples, depthFormat);
@@ -496,11 +607,14 @@ public void reshape(ViewPort vp, int w, int h) {
filterTexture = msColor;
depthTexture = msDepth;
} else {
+ // Otherwise, multisampled framebuffer must use internal texture, which cannot be directly read
renderFrameBufferMS.setDepthTarget(FrameBufferTarget.newTarget(depthFormat));
renderFrameBufferMS.addColorTarget(FrameBufferTarget.newTarget(fbFormat));
}
}
+ // Setup single-sampled framebuffer if no multisampling, or if OpenGL 3.2+ is not supported
+ // (because for non-GL32, a single-sampled buffer is still needed to copy MS content into).
if (numSamples <= 1 || !caps.contains(Caps.OpenGL32) || !caps.contains(Caps.FrameBufferMultisample)) {
renderFrameBuffer = new FrameBuffer(width, height, 1);
renderFrameBuffer.setDepthTarget(FrameBufferTarget.newTarget(depthFormat));
@@ -508,6 +622,7 @@ public void reshape(ViewPort vp, int w, int h) {
renderFrameBuffer.addColorTarget(FrameBufferTarget.newTarget(filterTexture));
}
+ // Set names for debugging
if (renderFrameBufferMS != null) {
renderFrameBufferMS.setName("FilterPostProcessor MS");
}
@@ -516,6 +631,7 @@ public void reshape(ViewPort vp, int w, int h) {
renderFrameBuffer.setName("FilterPostProcessor");
}
+ // Initialize all existing filters with the new dimensions
for (Filter filter : filters.getArray()) {
initFilter(filter, vp);
}
@@ -523,16 +639,16 @@ public void reshape(ViewPort vp, int w, int h) {
}
/**
- * return the number of samples for antialiasing
- * @return numSamples
+ * Returns the number of samples used for anti-aliasing.
+ *
+ * @return The number of samples.
*/
public int getNumSamples() {
return numSamples;
}
/**
- *
- * Removes all the filters from this processor
+ * Removes all filters currently added to this processor.
*/
public void removeAllFilters() {
filters.clear();
@@ -540,8 +656,12 @@ public void removeAllFilters() {
}
/**
- * Sets the number of samples for antialiasing
- * @param numSamples the number of Samples
+ * Sets the number of samples for anti-aliasing. A value of 1 means no
+ * anti-aliasing. This method should generally be called before the
+ * processor is initialized to have an effect.
+ *
+ * @param numSamples The number of samples. Must be greater than 0.
+ * @throws IllegalArgumentException If `numSamples` is less than or equal to 0.
*/
public void setNumSamples(int numSamples) {
if (numSamples <= 0) {
@@ -561,27 +681,30 @@ public void setAssetManager(AssetManager assetManager) {
}
/**
- * Sets the format to be used for the internal frame buffer's color buffer
+ * Sets the preferred `Image.Format` to be used for the internal frame buffer's
+ * color buffer.
*
- * @param fbFormat the format
+ * @param fbFormat The desired `Format` for the color buffer.
*/
public void setFrameBufferFormat(Format fbFormat) {
this.fbFormat = fbFormat;
}
/**
- * Sets the format to be used for the internal frame buffer's depth buffer
+ * Sets the preferred `Image.Format` to be used for the internal frame buffer's
+ * depth buffer.
*
- * @param depthFormat the format
+ * @param depthFormat The desired `Format` for the depth buffer.
*/
public void setFrameBufferDepthFormat(Format depthFormat) {
this.depthFormat = depthFormat;
}
/**
- * Returns the depth format currently used for the internal frame buffer's depth buffer
- *
- * @return the depth format
+ * Returns the `Image.Format` currently used for the internal frame buffer's
+ * depth buffer.
+ *
+ * @return The current depth `Format`.
*/
public Format getFrameBufferDepthFormat() {
return depthFormat;
@@ -609,43 +732,50 @@ public void read(JmeImporter im) throws IOException {
}
/**
- * For internal use only
- * returns the depth texture of the scene
- * @return the depth texture
+ * For internal use only.
+ * Returns the depth texture generated from the scene's depth buffer.
+ * This texture is available if any filter requires a depth texture.
+ *
+ * @return The `Texture2D` containing the scene's depth information, or null if not computed.
*/
public Texture2D getDepthTexture() {
return depthTexture;
}
/**
- * For internal use only
- * returns the rendered texture of the scene
- * @return the filter texture
+ * For internal use only.
+ * Returns the color texture that contains the rendered scene or the output
+ * of the previous filter in the chain. This texture serves as input for subsequent filters.
+ *
+ * @return The `Texture2D` containing the scene's color information or the intermediate filter output.
*/
public Texture2D getFilterTexture() {
return filterTexture;
}
/**
- * returns the first filter in the list assignable from the given type
+ * Returns the first filter in the managed list that is assignable from the
+ * given filter type. Useful for retrieving specific filters to modify their properties.
*
- * @param the filter type
- * @param filterType the filter type
- * @return a filter assignable from the given type
+ * @param The type of the filter to retrieve.
+ * @param filterType The `Class` object representing the filter type.
+ * @return A filter instance assignable from `filterType`, or null if no such filter is found.
*/
@SuppressWarnings("unchecked")
public T getFilter(Class filterType) {
- for (Filter c : filters.getArray()) {
- if (filterType.isAssignableFrom(c.getClass())) {
- return (T) c;
+ for (Filter f : filters.getArray()) {
+ if (filterType.isAssignableFrom(f.getClass())) {
+ return (T) f;
}
}
return null;
}
/**
- * returns an unmodifiable version of the filter list.
- * @return the filters list
+ * Returns an unmodifiable version of the list of filters currently
+ * managed by this processor.
+ *
+ * @return An unmodifiable `List` of {@link Filter} objects.
*/
public List getFilterList(){
return Collections.unmodifiableList(filters);
@@ -658,4 +788,4 @@ private void setupViewPortFrameBuffer() {
viewPort.setOutputFrameBuffer(renderFrameBuffer);
}
}
- }
+}