[SOLVED] Ambient Shadow filter drops my fps a lot

Hi
When enabling ambient shadow may fps drops from 77 to 8 . Is it usual ? or I am doing some thing wrong?

No ambient :

With Ambient:

package mygame;

import com.jme3.app.BasicProfilerState;
import com.jme3.app.SimpleApplication;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Node;

public class Main extends SimpleApplication {
    
    
   
    public static void main(String[] args) {

        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp() {
      
        stateManager.attach(new BasicProfilerState(false));
        FilterPostProcessor fpp= new FilterPostProcessor(assetManager);
        viewPort.addProcessor(fpp);
        flyCam.setEnabled(true);
        flyCam.setMoveSpeed(10);
       
        Node world = (Node) assetManager.loadModel("Scenes/ShadowTest.j3o");

        rootNode.attachChild(world);
       
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection((new Vector3f(-0.5f, -0.70710677f, -0.70710677f)).normalizeLocal());
        sun.setColor((ColorRGBA.White).mult(1.7f));
        rootNode.addLight(sun);
        
        SSAOFilter ssaoFilter = new SSAOFilter(12.94f, 43.93f, 0.33f, 0.60f);
        fpp.addFilter(ssaoFilter); 
    }

    @Override
    public void simpleUpdate(float tpf) {

    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }

}


I lose 10 to 20 percent of frames per second.
All standard settings for the SSAOFilter.
What hardware / driver do you have?
Me:

Running on jMonkeyEngine 3.0.10
Extraction Directory: C:\Users\Pilot\AppData\Roaming\.jmonkeyplatform\3.0
Lwjgl 2.9.0 context running on thread LWJGL Renderer Thread
Adapter: nvd3dumx,nvwgf2umx,nvwgf2umx
Driver Version: 10.18.13.5891
Vendor: NVIDIA Corporation
OpenGL Version: 4.5.0 NVIDIA 358.91
Renderer: GeForce GTX 760/PCIe/SSE2
GLSL Ver: 4.50 NVIDIA
Audio Device: OpenAL Soft
Audio Vendor: OpenAL Community
Audio Renderer: OpenAL Soft
Audio Version: 1.1 ALSOFT 1.15.1
AudioRenderer supports 64 channels
Audio effect extension version: 1.0
Audio max auxilary sends: 4
Running on jMonkeyEngine 3.1-5359
 * Branch: master
 * Git Hash: 6cb6915
 * Build Date: 2015-12-27
LWJGL 2.9.3 context running on thread jME3 Main
 * Graphics Adapter: igdumd64
 * Driver Version: 9.17.10.4229
 * Scaling Factor: 1
OpenGL Renderer Information
 * Vendor: ATI Technologies Inc.
 * Renderer: AMD Radeon HD 6300M Series
 * OpenGL Version: 4.5.13394 Compatibility Profile Context 15.200.1023.7
 * GLSL Version: 4.40
 * Profile: Compatibility
Audio Renderer Information
 * Device: OpenAL Soft
 * Vendor: OpenAL Community
 * Renderer: OpenAL Soft
 * Version: 1.1 ALSOFT 1.15.1
 * Supported channels: 64
 * ALC extensions: ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX ALC_EXT_thread_local_context ALC_SOFT_loopback
 * AL extensions: AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_source_latency
Pausing audio device not supported.
Audio effect extension version: 1.0
Audio max auxiliary sends: 4
Returning hash code of content
Checking page id 1,387,040,574 vs stored id 1,387,040,574

Other INFO:
Laptop Lenovo G570
RAM 4GB (640 MHz)
Graphic : Radeon 6300M . 1 GB
Intel Core i3
Windows 10 .

You could try this SSAO

Had almost no effect on my FPS, not quite as nice looking, but decent

1 Like

Just curious, what display settings are you running with? AA? etc.

6300M is a low-end card whereas SSAO is a high-end effect.
Consider using the faster version @JESTERRRRRR suggested.

Can you help with using this BasicSSAO ?
I know nothing about shader programming .
I created BassicSSAO.java class and copy and paste code from @t0neg0d .
then created two materials in MatDefs folder . BassicSSAO.j3md and BassicSSAOBlur.j3md and copy and paste code to them.
then created two shader in Shaders folder. BasicSSAO.frag and BasicSSAOBlur.frag and copy and paste code there.
and in my application :




FilterPostProcessor fpp= new FilterPostProcessor(assetManager);
      viewPort.addProcessor(fpp);
      BasicSSAO ssao = new BasicSSAO(3.0f, 10.5f, 0.5f, 0.025f);

       ssao.setUseDetailPass(true); 
       
       ssao.setUseDistanceFalloff(true);

       ssao.setFalloffStartDistance(250f);

       ssao.setFalloffRate(4.0f); 
       fpp.addFilter(ssao);

and when running my game get this error :

Uncaught exception thrown in Thread[jME3 Main,5,main]
RendererException: compile error in: ShaderSource[name=Shaders/BasicSSAO.frag, defines, type=Fragment, language=GLSL100]
Fragment shader failed to compile with the following errors:
ERROR: 0:83: error(#132) Syntax error: "00.25" parse error
ERROR: error(#273) 1 compilation errors.  No code generated


    at com.jme3.renderer.opengl.GLRenderer.updateShaderSourceData(GLRenderer.java:1133)
    at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1160)
    at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1224)
    at com.jme3.material.Material.render(Material.java:1215)
    at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:564)
    at com.jme3.post.FilterPostProcessor.renderProcessing(FilterPostProcessor.java:218)
    at com.jme3.post.FilterPostProcessor.renderFilterChain(FilterPostProcessor.java:269)
    at com.jme3.post.FilterPostProcessor.postFrame(FilterPostProcessor.java:320)
    at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1045)
    at com.jme3.renderer.RenderManager.render(RenderManager.java:1088)
    at com.jme3.app.SimpleApplication.update(SimpleApplication.java:260)
    at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
    at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:192)
    at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
    at java.lang.Thread.run(Thread.java:745)


My BasicSSAO.frag file :

uniform vec2 g_Resolution;

uniform vec2 m_FrustumNearFar;

uniform sampler2D m_Texture;

uniform sampler2D m_Normals;

uniform sampler2D m_Noise;

uniform sampler2D m_DepthTexture;

uniform vec3 m_FrustumCorner;

uniform float m_SampleRadius;

uniform float m_Intensity;

uniform float m_Scale;

uniform float m_Bias;

uniform bool m_EnableFD;

uniform float m_SampleRadiusFD;

uniform float m_IntensityFD;

uniform float m_ScaleFD;

uniform float m_BiasFD;

uniform vec3[12] m_Samples;



uniform bool m_UseDistanceFalloff;

uniform float m_FalloffStartDistance;

uniform float m_FalloffRate;



varying vec2 texCoord;



float depthv;

float shadowFactor;



vec3 getPosition(in vec2 uv){

depthv = texture2D(m_DepthTexture,uv).r;

float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - depthv* (m_FrustumNearFar.y-m_FrustumNearFar.x));

float x = mix(-m_FrustumCorner.x, m_FrustumCorner.x, uv.x);

float y = mix(-m_FrustumCorner.y, m_FrustumCorner.y, uv.y);

return depth* vec3(x, y, m_FrustumCorner.z);

}



vec3 getNormal(in vec2 uv){

return normalize(texture2D(m_Normals, uv).xyz * 2.0 - 1.0);

}



vec3 getRandom(in vec2 uv){

float rand=(fract(uv.x*(g_Resolution.x/2.0))0.25)+(fract(uv.y(g_Resolution.y/2.0))*0.5);

return normalize(vec3(rand,rand,rand));

}



vec3 getNoise(in vec2 uv){

vec4 noise = texture2D(m_Noise, uv*25.0);

return (noise.xyz);

}



float doAmbientOcclusion(in vec2 tc, in vec3 pos, in vec3 norm){

vec3 diff = getPosition(tc)- pos;

vec3 v = normalize(diff);

float d = length(diff) * m_Scale;

return step(0.00002,d)*max(0.0, dot(norm, v) - m_Bias) * ( 1.0/(1.0 + d) ) * (m_Intensity+shadowFactor) * smoothstep(0.00002,0.0027,d);

}



float doAmbientOcclusionFD(in vec2 tc, in vec3 pos, in vec3 norm){

vec3 diff = getPosition(tc)- pos;

vec3 v = normalize(diff);

float d = length(diff) * m_ScaleFD;

return step(0.00002,d)*max(0.0, dot(norm, v) - m_BiasFD) * ( 1.0/(1.0 + d) ) * (m_IntensityFD+shadowFactor) * smoothstep(0.00002,0.0027,d);

}



vec3 reflection(in vec3 v1,in vec3 v2){

vec3 result= 2.0 * dot(v2, v1) * v2;

result=v1-result;

return result;

}



void main(){

float result;

vec3 position = getPosition(texCoord);

if(depthv==1.0){

gl_FragColor=vec4(1.0);

return;

}

vec3 normal = getNormal(texCoord);

vec3 rand = getRandom(texCoord);



float ao = 0.0;

shadowFactor = 0.075;//0.0;//(position.z*0.002);

float rad = m_SampleRadius/position.z+shadowFactor;

float radFD = m_SampleRadiusFD/position.z+shadowFactor;



int iterations = 12;

if (m_UseDistanceFalloff) {

float LOG2 = 1.442695;

vec2 m_DistanceFrustum = vec2(1.0,m_FalloffStartDistance);

float depth= (m_DistanceFrustum.x / 4.0) /

(m_DistanceFrustum.y - depthv *

(m_DistanceFrustum.y));



float falloffFactor = exp2( -m_FalloffRate * m_FalloffRate * depth * depth * LOG2 );

falloffFactor = clamp(falloffFactor, 0.0, 1.0);



if (falloffFactor < 1.0) {

for (int j = 0; j < iterations; ++j) {

vec3 coord1 = reflection(vec3(m_Samples[j]), rand) * vec3(rad);

ao += doAmbientOcclusion(texCoord + coord1.xy * 0.125, position, normal) - shadowFactor;

// Fine Detail

if (m_EnableFD) {

vec3 coord2 = reflection(vec3(m_Samples[j]), rand) * vec3(radFD*0.5);

ao += doAmbientOcclusionFD(texCoord + coord2.xy * 0.05, position, normal) * (0.25-shadowFactor);

}

}

ao /= float(iterations) * (2.35-shadowFactor);

result = 1.0-ao;

result = mix(result,1.0,1.0-falloffFactor);

} else {

result = 1.0;

}

} else {

for (int j = 0; j < iterations; ++j) {

vec3 coord1 = reflection(vec3(m_Samples[j]), rand) * vec3(rad);

ao += doAmbientOcclusion(texCoord + coord1.xy * 0.125, position, normal) - shadowFactor;

// Fine Detail

if (m_EnableFD) {

vec3 coord2 = reflection(vec3(m_Samples[j]), rand) * vec3(radFD*0.5);

ao += doAmbientOcclusionFD(texCoord + coord2.xy * 0.05, position, normal) * (0.25-shadowFactor);

}

}

ao /= float(iterations) * (2.35-shadowFactor);

result = 1.0-ao;

}



gl_FragColor = vec4(vec3(result),1.0);

}

@nehon and @t0neg0d this question looks at you . Can you please help me ?
Where shold i fix “00.25” syntax parse error ? it was not inside BasicSSAO.frag.

A drop of 77 to 8 sounds reasonable to me give such low end hardware. The relatively simple scene in the first shot I would expect to see several hundred fps on my medium spec rig, so I think it is just slow to begin with.

This argument really doesn’t hold up. I enabled SSAO on my GTX970M graphics card, and my FPS dropped by over 70%.

It’s not an argument, it’s an explanation. SSAO is a very expensive operation, and the low end specs will explain the “dramatic” loss of performance. There is currently no cheap way of calculating SSAO.

Can you explain what this means?

An FPS drop of 100% would be 0 no matter what the FPS started as.

Ugh, apologies. 70%. I meant 70%.

Ok, for an M card that might be about right depending on what the FPS was before that. (If you were getting 1000 FPS before then that’s pretty bad… but 60-70 FPS? 70% is pretty likely then.)

Not sure if this is offtopic (as it may still be relevant to why shadow filters drop FPS), but could you explain why specifically being an M card would cause an FPS drop? What if it was an MX card? An X card?

As far as I know, the 970M a pretty powerful card. On popular MMOs such as World Of Tanks and War Thunder, it runs shadows at the highest quality with over 100 FPS.

First, let’s get this straight… even though the topic is talking about shadows… it’s not shadows. It’s “screen space ambient occlusion”. And it’s slow. Butt-ass-slug-in-molasses slow. It has to do a lot of processing per pixel… in addition to a second normal rendering pass, it then has to cast about in that texture to determine per-pixel occlusion, etc…

Second, regarding the ‘M’, my experience is that the mobile GPUs are always worse than the desktop counterparts. Maybe that’s changed. Either way, something has to give to fit it into the laptop… and I guess it’s the exact same memory bandwidth+speed stuff that affects full screen per-pixel-lots-of-random-access crap like SSAO.

I could fix syntax error by adding a “+” before 0.25 .

now just get this

Uncaught exception thrown in Thread[jME3 Main,5,main]
RendererException: compile error in: ShaderSource[name=Shaders/BasicSSAO.frag, defines, type=Fragment, language=GLSL100]
Fragment shader failed to compile with the following errors:
ERROR: error(#273) 0 compilation errors.  No code generated

Did this even work for anyone?
I think i have to give it up !!! :disappointed:

Paste this into BasicSSAO.frag

uniform vec2 g_Resolution;
uniform vec2 m_FrustumNearFar;
uniform sampler2D m_Texture;
uniform sampler2D m_Normals;
uniform sampler2D m_Noise;
uniform sampler2D m_DepthTexture;
uniform vec3 m_FrustumCorner;
uniform float m_SampleRadius;
uniform float m_Intensity;
uniform float m_Scale;
uniform float m_Bias;
uniform bool m_EnableFD;
uniform float m_SampleRadiusFD;
uniform float m_IntensityFD;
uniform float m_ScaleFD;
uniform float m_BiasFD;
uniform vec3[12] m_Samples;

uniform bool m_UseDistanceFalloff;
uniform float m_FalloffStartDistance;
uniform float m_FalloffRate;

varying vec2 texCoord;

float depthv;
float shadowFactor;

vec3 getPosition(in vec2 uv){
depthv = texture2D(m_DepthTexture,uv).r;
float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - depthv* (m_FrustumNearFar.y-m_FrustumNearFar.x));
float x = mix(-m_FrustumCorner.x, m_FrustumCorner.x, uv.x);
float y = mix(-m_FrustumCorner.y, m_FrustumCorner.y, uv.y);
return depth* vec3(x, y, m_FrustumCorner.z);
}

vec3 getNormal(in vec2 uv){
return normalize(texture2D(m_Normals, uv).xyz * 2.0 - 1.0);
}

vec3 getRandom(in vec2 uv){
float rand=(fract(uv.x*(g_Resolution.x/2.0))*0.25)+(fract(uv.y*(g_Resolution.y/2.0))*0.5);
return normalize(vec3(rand,rand,rand));
}

vec3 getNoise(in vec2 uv){
vec4 noise = texture2D(m_Noise, uv*25.0);
return (noise.xyz);
}

float doAmbientOcclusion(in vec2 tc, in vec3 pos, in vec3 norm){
vec3 diff = getPosition(tc)- pos;
vec3 v = normalize(diff);
float d = length(diff) * m_Scale;
return step(0.00002,d)*max(0.0, dot(norm, v) - m_Bias) * ( 1.0/(1.0 + d) ) * (m_Intensity+shadowFactor) * smoothstep(0.00002,0.0027,d);
}

float doAmbientOcclusionFD(in vec2 tc, in vec3 pos, in vec3 norm){
vec3 diff = getPosition(tc)- pos;
vec3 v = normalize(diff);
float d = length(diff) * m_ScaleFD;
return step(0.00002,d)*max(0.0, dot(norm, v) - m_BiasFD) * ( 1.0/(1.0 + d) ) * (m_IntensityFD+shadowFactor) * smoothstep(0.00002,0.0027,d);
}

vec3 reflection(in vec3 v1,in vec3 v2){
vec3 result= 2.0 * dot(v2, v1) * v2;
result=v1-result;
return result;
}

void main(){
float result;
vec3 position = getPosition(texCoord);
if(depthv==1.0){
gl_FragColor=vec4(1.0);
return;
}
vec3 normal = getNormal(texCoord);
vec3 rand = getRandom(texCoord);

float ao = 0.0;
shadowFactor = 0.075;//0.0;//(position.z*0.002);
float rad = m_SampleRadius/position.z+shadowFactor;
float radFD = m_SampleRadiusFD/position.z+shadowFactor;

int iterations = 12;
if (m_UseDistanceFalloff) {
float LOG2 = 1.442695;
vec2 m_DistanceFrustum = vec2(1.0,m_FalloffStartDistance);
float depth= (m_DistanceFrustum.x / 4.0) /
(m_DistanceFrustum.y - depthv *
(m_DistanceFrustum.y));

float falloffFactor = exp2( -m_FalloffRate * m_FalloffRate * depth * depth * LOG2 );
falloffFactor = clamp(falloffFactor, 0.0, 1.0);

if (falloffFactor < 1.0) {
for (int j = 0; j < iterations; ++j) {
vec3 coord1 = reflection(vec3(m_Samples[j]), rand) * vec3(rad);
ao += doAmbientOcclusion(texCoord + coord1.xy * 0.125, position, normal) - shadowFactor;
// Fine Detail
if (m_EnableFD) {
vec3 coord2 = reflection(vec3(m_Samples[j]), rand) * vec3(radFD*0.5);
ao += doAmbientOcclusionFD(texCoord + coord2.xy * 0.05, position, normal) * (0.25-shadowFactor);
}
}
ao /= float(iterations) * (2.35-shadowFactor);
result = 1.0-ao;
result = mix(result,1.0,1.0-falloffFactor);
} else {
result = 1.0;
}
} else {
for (int j = 0; j < iterations; ++j) {
vec3 coord1 = reflection(vec3(m_Samples[j]), rand) * vec3(rad);
ao += doAmbientOcclusion(texCoord + coord1.xy * 0.125, position, normal) - shadowFactor;
// Fine Detail
if (m_EnableFD) {
vec3 coord2 = reflection(vec3(m_Samples[j]), rand) * vec3(radFD*0.5);
ao += doAmbientOcclusionFD(texCoord + coord2.xy * 0.05, position, normal) * (0.25-shadowFactor);
}
}
ao /= float(iterations) * (2.35-shadowFactor);
result = 1.0-ao;
}

gl_FragColor = vec4(vec3(result),1.0);
}
1 Like

YES ! It DID WORK. HAHA! :grinning:
THANKS a lot my friend.

1 Like

Very cool. I should try this too.
Marked as [SOLVED].

1 Like