Generating shadows after simpleInitApp -- possible?

I’m using Swing FYI. I have a checkbox that let’s the user select whether or not to display shadows. The code for shadows (which is working fine) is:



[java]

PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, 512, 2);

pssmRenderer.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());

pssmRenderer.setLambda(0.55f);

pssmRenderer.setShadowIntensity(0.15f);

pssmRenderer.setCompareMode(CompareMode.Software);

pssmRenderer.setFilterMode(FilterMode.Bilinear);

//pssmRenderer.displayDebug();

viewPort.addProcessor(pssmRenderer);

[/java]



Just wondering if I were to call that block of code after simpleInitApp, how I would update the scene so shadows are generated? Is that even possible? Or can I only do it within simpleInitApp?

The scene should update automatically within its update loop

Yeah, but do I want to put that block of code in the update loop? Then it would be adding the processor on each update!

No, that code would go in your swing code… most likely in an ActionListener that you’ve added to one of your components

Yes, I’ve done that. The code gets called, but shadows do not appear. I’m wondering if there’s something else I need to call.



If I put the block of code in simpleInitApp then the shadows display just fine.

Sorry it took so long to respond, here’s what I did :slight_smile:



[java]

public class MyApplication extends SimpleApplication {



private static final Logger logger = Logger.getLogger(MyApplication.class);



private SceneProcessor shadowProcessor;



/**

*

/

public MyApplication() {}



/
(non-Javadoc)

  • @see com.jme3.app.SimpleApplication#simpleInitApp()

    */

    @Override

    public void simpleInitApp() {

    loadStuff();

    setupShadows(true);

    }



    private void setupShadows(boolean usePSSM){

    if(usePSSM){

    shadowProcessor = new PssmShadowRenderer(assetManager,4096,4);

    ((PssmShadowRenderer)shadowProcessor).setDirection(new Vector3f(.25f, -.85f, .75f).normalizeLocal());

    ((PssmShadowRenderer)shadowProcessor).setLambda(0.55f);

    ((PssmShadowRenderer)shadowProcessor).setShadowIntensity(.6f);

    //((PssmShadowRenderer)shadowProcessor).setEdgesThickness(0);

    ((PssmShadowRenderer)shadowProcessor).setCompareMode(CompareMode.Hardware);

    ((PssmShadowRenderer)shadowProcessor).setFilterMode(FilterMode.Nearest);

    //((PssmShadowRenderer)shadowProcessor).displayDebug();

    viewPort.addProcessor(shadowProcessor);

    }

    else{

    shadowProcessor = new BasicShadowRenderer(assetManager, 4096);

    ((BasicShadowRenderer)shadowProcessor).setDirection(new Vector3f(-1, -1, -1).normalizeLocal());

    viewPort.addProcessor(shadowProcessor);

    }



    }



    public void setShadowsEnabled(boolean enabled){

    for(SceneProcessor processor : viewPort.getProcessors()){

    if(processor==shadowProcessor){

    if(!enabled){

    viewPort.removeProcessor(processor);

    return;

    }

    }

    }



    if(enabled) viewPort.addProcessor(shadowProcessor);

    }



    public boolean areShadowsEnabled(){

    for(SceneProcessor processor : viewPort.getProcessors()){

    if(processor==shadowProcessor) return true;

    }



    // If we never found our shadow processor, then the shadows aren’t on

    return false;

    }



    }



    [/java]



    From here, just use the setShadowsEnabled command in your GUI code…

Yes, this code is essentially what I have done. THe problem is that the shadows are disabled when you pass “false” to “setShadowsEnabled”, but when you then pass “true” after that, nothing happens!

No ideas on this, anyone?!

This comes from ViewPort



protected final ArrayList processors = new ArrayList();



public void addProcessor(SceneProcessor processor){

processors.add(processor);

}



public void removeProcessor(SceneProcessor processor){

processors.remove(processor);

processor.cleanup();

}



So nothing is really happening in the background as far as I can see, i.e., ViewPort isn’t doing something odd to the processors it’s just adding and removing them from the ViewPort::processors ArrayList. I wondered if some freaky stuff might be going on inside SceneProcessor::cleanup (rather PssmShadowRenderer::cleanup) but nothing is happening there, empty method.



This may be pointless and off the wall, but strange things happen to data sometimes so I’d do this just to be sure:



Before I call setShadowsEnabled(true), I would check and make sure shadowProcessor is not null or something crazy like that because we did call setShadowsEnabled(false) already and who knows what could have happened to our shadowProcessor since that point and now we want to add it again. It’s always good to keep an eye on those things. Then I would viewPort.addProcessor(shadowProcessor). And then I would check to make sure the processor is definitely in the ArrayList. ArrayList procs = viewPort.getProcessors(). if( procs.contains(shadowProcessor) { GOOD SO FAR } else { WHAT THE HELL? }



Also, you might make sure it’s not in there twice for some reason which could cause problems: procs.indexOf(shadowProcessor) gives the first index, procs.lastIndexOf(shadowProcessor) gives the last index. Obviously if they are 2 different indexes, then you somehow have 2 of them in your array list. I know this is highly unlikely that it has anything to do with your issue, but you never know.



I’m not sure I understand the above code:



[java]public void setShadowsEnabled(boolean enabled){ for(SceneProcessor processor : viewPort.getProcessors()){ if(processor==shadowProcessor){ if(!enabled){ viewPort.removeProcessor(processor); return; } } } if(enabled) viewPort.addProcessor(shadowProcessor); } [/java]



I would think all you need to do for setShadowsEnabled is:



[java]public void setShadowsEnabled(boolean enabled) {

viewPort.removeProcessor(shadowProcessor);

if(enabled) viewPort.addProcessor(shadowProcessor);

}[/java]



And areShadowsEnabled() { return viewPort.getProcessors().contains(shadowProcessor); }



Anyhow, the point is, if you know for a fact that your shadowProcessor is getting removed and added properly to the viewPort, then you can move on and check other more complex things like, how the rendering system deals with the processors it gets from viewPort.

In fact, if you’re really worried about the possibility of having more than one of the same shadowProcessor object in the list( like, I dunno, maybe if there are more than one, they conflict and neither do your shadows), you could change the first line in setShadowsEnabled to



while(viewPort.removeProcessor(shadowProcessor));



Which would just keep removing the processor from the list until there are absolutely no more instances of it in the list. Then, of course, if you want shadows on, you add it after you make sure it’s not already in there.

Well, I take that back, ViewPort::removeProcessor doesn’t return whether or not it changed the list, but it should do that.



So, we just deal with the list directly:



while(viewPort.getProcessors().remove(shadowProcessor)) shadowProcessor.cleanup();



And call shadowProcessor.cleanup() because that’s what ViewPort::removeProcessor did, even though cleanup() does nothing now, it could in the future, or you may change your shadowProcessor to some other class that uses the method.

THanks for taking the time to write all of that. Anyways, I’m 100% sure that the processor is being added/removed correctly. It is added by default, and so shadows are rendered. If I uncheck the box that says to render shadows, then the processor is removed and shadows disappear (and with my simple debugging I can verify that it was indeed removed from the list).



When I then check the box that says to render shadows, the processor is then added to the list of processors again, but no shadows are displayed. Even if I just reinitialize the processor object (mPSSM = new PSSM…) and then add it to the list, still no results.



Here is some code:



[java]

private void setupShadows()

{

mPSSMShadowRenderer = new PssmShadowRenderer(assetManager, 512, 2);

mPSSMShadowRenderer.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());

mPSSMShadowRenderer.setLambda(0.55f);

mPSSMShadowRenderer.setShadowIntensity(0.15f);

mPSSMShadowRenderer.setCompareMode(CompareMode.Software);

mPSSMShadowRenderer.setFilterMode(FilterMode.Bilinear);

viewPort.addProcessor(mPSSMShadowRenderer);

}



public void setShadowsEnabled(final boolean enabled)

{

enqueue(new Callable()

{



@Override

public Object call() throws Exception

{

viewPort.removeProcessor(mPSSMShadowRenderer);

if (enabled)

viewPort.addProcessor(mPSSMShadowRenderer);



return null;

}

});

}

[/java]

jacksmash said:
Yes, this code is essentially what I have done. THe problem is that the shadows are disabled when you pass "false" to "setShadowsEnabled", but when you then pass "true" after that, nothing happens!

post your code you must do something wrong, the code provided by @sbook is working fine.
nehon said:
post your code you must do something wrong, the code provided by @sbook is working fine.


Does the code I just posted help, or not?

Ok, so you verified that your code is doing all it can do.



I’m curious if you will get the same results if you start the program without shadow at first, and then checking the box… will it add shadows the first time the processor is added even though the rendering system is already fully engaged at least, because if not, that would tell us that it has something to do with initialization.



If it works the first time you turn shadows on, then something is getting jacked up with the rendering system and processors. If it wont, then it may have something to do with not being able to process shadows after a certain point in the rendering process. I’m kind of new to 3d graphics, but I know a little from looking at a lot of code and tutorials and even from playing lots of games you find that some settings in the rendering system require a restart of the program to take effect, which could mean that certain processes/filters or whatever you want to call them can only be engaged prior to some point in the rendering system. The issue may have nothing to do with that. I’m going to have to take a look at what the rendering system does with the processors. It may not deal well with processors being there and then not being there and then wanting to come back. For example, if it takes a look at the processors and then makes it’s own list of them and then checks if any processors are removed but doesn’t manage it’s own list well, then it may not even check to see if the processor is back or wont use it because it already knows about it and thinks it is disabled. Errr whatever, I need to learn more about how the processors are used before I can even guess.



In the mean time, let me know what happens when you start up without the processor and try to add it later.



Secondly, again, I’m no 3d graphics guru but I understand there are 2 possible lower level api’s being used, LWJGL and JOGL so if you were able to try each and see if you get the same results, that could clue us into how deep the issue goes and cancel out some presumptions.



If I come up with something after I take a look at the rendering system in more detail(which I should do for learning purposes anyhow), I’ll post again.



I guess I should take a look at that enqueue function too because I’m not sure why you have it like that, I’m guessing it has something to do with threading and you have it like that for a reason. But you stated that the processor did get put back into the viewport’s list so however you are doing it, it’s serving its purpose. It’s got to be something with how the system deals with the viewport’s processors. Which makes me think, another test you could try is using a different kind of processor, maybe something more basic than shading(if it matters, I’m not very familiar), and then see if you can turn that different kind of processor on and off. That would tell us if it’s related to processors in general or specific types.

Hey,



It doesn’t matter whether shadows are on or off by default. They will only work if I initialize the processor within the simpleInitApp function.



As for enqueue, I do that so there is no concurrent modification of the processor list. It happens sometimes…

Ok, well, that pretty much tells me it’s probably something to do with what I mentioned about some features having to be on or off before enguaging the rendering system. I am curious as to why you wouldn’t be able to do it on the fly though. So I’ll try and look into that for you but hopefully some guru who already knows these things could tell us what’s up before we go delving into tons of code.



And, as I recall, it seems like in most games, shadows is something you can turn on and off on the fly.



So, try another processor type and see if we still have the same problem. Oh man, that makes me wonder… if all processors must be added during the init process, and then all you can do later is change the processors’ settings or completely turn them off, but you may not be able to ADD processors after initialization. So, to get around this, if you can adjust the processors on the fly, just have shadows on from the beginning but, if possible, when you uncheck shadows, manipulate the processor so that it doesn’t actually affect anything… like I said, if possible.

Thanks!



I’ve also tried the BasicShadowRenderer and get precisely the same results.

It’s interesting that even the debug info will show up when I call the displayDebug() function. Check out these screens:


  1. App initialized with shadows:



    http://imgur.com/3dmlz


  2. Shadows turned off:



    http://imgur.com/BsWvT


  3. Shadows turned back on:



    http://imgur.com/mJVCx

Oh boy, I just discovered something. I’m using the CartoonEdgeFilter. When I disable that filter, then the shadows turn off and on!! What the heck!!!