www.jpct.net

jPCT - a 3d engine for Java => Support => Topic started by: ErDetEnAnd? on January 08, 2009, 10:51:42 pm

Title: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 08, 2009, 10:51:42 pm
Hello again!

I'm trying to turn my application into an applet. In the appletviewer software and  hardware render (AWTGLCanvas) works fine. Same for software render when applet is loaded within a browser. The problem arises when using the AWTGLCanvas render inside the browser. What I get is a rendered image every second time, else it's a "near white" color - which is not the background from the rendered image.

The render code only runs on user/event input, thus it has no active render thread. Now, the render problem does not show here, but only on applet repaint eg when another window is dragged on top of the browser or the browser window is dragged from outside the screen and towards the screen center.

My applet painting methods look like this (like i've read http://www.jpct.net/forum2/index.php/topic,202.0.html (http://www.jpct.net/forum2/index.php/topic,202.0.html)):

Code: [Select]
    public void paint(Graphics g) {
        super.paint(g);
        if (worldFrame!=null)
            worldFrame.paint(g);
    }

    public void update(Graphics g) {
        paint(g);
    }

Where the worldframe is a JPanel which is the canvas is added to. The painting is done like this:

Code: [Select]
        if (buffer.usesRenderer(IRenderer.RENDERER_OPENGL))
            if (cGLScene!=null) {
                buffer.displayGLOnly();
                cGLScene.repaint();
            }

Does anyone have any idea?
Title: Re: Applet flickering with LWJGL
Post by: EgonOlsen on January 08, 2009, 11:08:07 pm
Try to remove the super.paint(g); from paint()
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 08, 2009, 11:22:31 pm
Removing that line is actually only makes the problem worse, like the image is only shown ca. each 3rd time.

According to the java applet doc, I'm advised to put in the super call at the top:

Quote
Paints the container. This forwards the paint to any lightweight components that are children of this container. If this method is reimplemented, super.paint(g) should be called so that lightweight components are properly rendered. If a child component is entirely clipped by the current clipping setting in g, paint() will not be forwarded to that child.
Title: Re: Applet flickering with LWJGL
Post by: EgonOlsen on January 08, 2009, 11:58:11 pm
The call to super.paint() should only be needed if you are actually using Swing/AWT components in that applet. However, maybe paul can help here...he did far more in respect to applets than i did.
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 09, 2009, 01:33:28 am
I was a little bit confused about the call to 'worldFrame.paint(g);'.  This looks like you are telling the JFrame to paint onto the JApplet's Graphics instance.  A JFrame will have its own Graphics instance, so if you want it to draw again, you must call repaint() instead of paint().

Personally, I have never tried adding a JFrame with a child Canvas as a child to a JApplet, since JFrame and JApplet are virtually identical as far as their methods go.  You can convert an application into an applet and vice versa by merely changing the word "JFrame" to "Japplet" and commenting out/uncommenting the constructor.  In theory, though, your way seems like it should work just fine, with the minor adjustment of changing that call to paint() into a call to repaint():

Code: [Select]
// JApplet paint() method:
public void paint( Graphics g )
{
    super.paint( g );  // don't know if this is needed, try it both ways
    if( worldFrame != null )
            worldFrame.repaint();
}

Let me know if this doesn't work.  If you simply can't get it to work, the other option (switching between JApplet and JFrame) is demonstrated in the updated source code for my Gears Demo Applet (http://www.paulscode.com/demos/jpct/jPCTGears/jPCTGearsSource.zip).  The comments indicate how to easily switch between JApplet and JFrame.
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 09, 2009, 08:48:43 am
Hi Paul. Thank you for your answer.

The missleading name worldFrame is actually a JPanel, but you're right about the graphic instance. The passed graphic instance is not used at all. So it looks like this:

Code: [Select]
    public void paint(Graphics g) {
        super.paint(g);
        if (worldFrame!=null)
            worldFrame.paint(null);
    }

    public void update(Graphics g) {
        paint(g);
    }

The reason why not calling repaint is that the scene should be drawn at the same time the applet is requested painted. By calling repaint to the JPanel I'm not having same control of when the scene is painted. Dont you agree?

Remember I'm only having this issue when the applet runs in a browser, with the gl canvas enabled.

Unfortunately the gears example is using active rendering.
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 09, 2009, 03:20:08 pm
I agree it would be nice to be able to control exactly when something paints, but unfortunately you can not.  The best you can do is specify a "maximum number of miliseconds" until the paint() method will be called, using 'JPanel.repaint( long milis )'.  In case you were wondering, that is why your JPanel's paint() method calls 'worldFrame.repaint()' rather than 'worldFrame.paint( g )'

The reason you can't call a child component's paint( g ) directly from the parent's paint() method, is because what that does is pass the parent's Graphics instance to the child's paint() method so the child will paint onto the parent (which is hidden behind the child) instead of painting onto itself.  This will slow down your applet, since the JPanel's paint method is being called twice when there are "dirty regions" (once when AWT called the JApplet's paint() method and once when AWT called the JPanel's paint() method).  Not only that, you can't even save a handle to the different Graphics instance to use that instead, since it is different every time paint() gets called.

That being said, it should be pretty easy to change from active rendering into inactive.  I would use something like this (I'm not at a computer where I can test this at the moment, so let me know if it doesn't work):

First, create a method in your JApplet that gets called whenever something changes (you could simply use 'repaint()', unless there are things you want to do first).  If you need to call this method from your JPanel or Canvas classes (which you probably do), then create a global static handle to your JApplet, or pass a handle to it in the constructors for your JPanel and Canvas classes.
Code: [Select]
public void somethingChanged()
{
    // do whatever else you need to do here, then:
    this.repaint();
}

Second, your applet's paint() method, tell the JPanel to repaint().
Code: [Select]
public void paint( Graphics g )
{
    if( worldFrame != null )
            worldFrame.repaint();
}

Finally, your JPanel's paint() method, render the scene and tell the Canvas to repaint().
Code: [Select]
public void paint( Graphics g )
{
    if( buffer != null && world != null )
    {
        buffer.clear();
        world.renderScene( buffer );
        world.draw( buffer );
        buffer.update();
        if ( buffer.usesRenderer( IRenderer.RENDERER_OPENGL ) && cGLScene != null )
        {
            buffer.displayGLOnly();
            cGLScene.repaint();
        }
    }
}
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 09, 2009, 03:36:04 pm
One more thing, if you absolutely need the scene to update at exactly the time the JApplet's paint() method is called (I can't see why this would be necessary, but in case it is), you could create a method in your JPanel that you call from the JApplet's paint() method.  It would update the scene and call repaint() on the JPanel:

Code: [Select]
// For the worldFrame JPanel:
public void updateScene()
{
    if( buffer != null && world != null )
    {
        buffer.clear();
        world.renderScene( buffer );
        world.draw( buffer );
        buffer.update();
        this.repaint();
    }
}
public void paint( Graphics g )
{
        if ( buffer != null && buffer.usesRenderer( IRenderer.RENDERER_OPENGL ) && cGLScene != null )
        {
            buffer.displayGLOnly();
            cGLScene.repaint();
        }
}
Code: [Select]
// For your JApplet:
public void paint( Graphics g )
{
    if( worldFrame != null )
    {
        worldFrame.updateScene();
    }
}

Only reason I would advise against this method if possible, is that paint() may be called before updateScene() gets called, so you'd probably also need to add some type of logic into your paint() method to make sure updateScene() has been called before.
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 09, 2009, 11:37:18 pm
Hi Paul, and once again thanks!

I've with interest read ur posts, and implemented what you suggested.

My applet:
Code: [Select]
    public void paint(Graphics g) {
        if (worldFrame!=null)
            worldFrame.repaint();
    }

    public void update(Graphics g) {
        paint(g);
    }

And the worldFrame which inherits from JPanel:

Code: [Select]
        MyAppletClass.my_static_applet_instance.repaint();

        if (buffer.usesRenderer(IRenderer.RENDERER_OPENGL))
            if (cGLScene!=null) {
                buffer.displayGLOnly();
                cGLScene.repaint();
            }

I've tried calling "MyAppletClass.my_static_applet_instance.repaint();" before and after I've requested a canvas repaint. But same result; flicker on repaint events caused by "dirty regions".

Futhermore I downloaded ur zipped gears example from above, and used primitives instead of 3DS (some how they were currupted). So changed 3 lines like so:
Code: [Select]
redGear = Primitives.getBox(3,3);. This program is also causing flicker within the browser on "dirty region" update. Since you're rendering all the time, its just a matter of short time before the "near white" color, where the applet is running, is updated with a new image. But it is truely flickering as much as my applet.

Could we used ur program as reference?

Edit: I recall to having loaded your gears example from your webpage, but not the flickering. Do you still have it online with an appletloader?
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 09, 2009, 11:43:23 pm
Okay found your online gears, but same problem :(
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 10, 2009, 12:10:01 am
Been testing a while now. Using worldFrame.repaint() in the paint method of the applet is not only causing flicker in the browser with GL enabled, but in all circumstances: software and hardware render + appletviewer and browser.

Code: [Select]
    public void paint(Graphics g) {
        if (worldFrame!=null)
            worldFrame.repaint();
    }

    public void update(Graphics g) {
        paint(g);
    }

Back to paint() the flicker only shows in browser using hardware render.

Code: [Select]
    public void paint(Graphics g) {
        if (worldFrame!=null)
            worldFrame.paint(null);
    }

    public void update(Graphics g) {
        paint(g);
    }
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 10, 2009, 12:46:39 am
Wow, thanks for the information, I didn't realize my applet was flickering in hardware rendering mode - perhaps my PC is too fast for me to notice.  I'll tinker around with this to see if I can solve the problem (it likely affects all my applets since they all use that same basic infrastructure used in the gears demo applet).  When my wife and I get back home on the 20th, I'll see if any of my test computers experience the problem.

Unfortunately, in the mean time, until I figure out what might be causing this, I can't really help you solve you're problem either.  Sorry to send you on a wild goose chase about paint() vs. repaint()! :-[
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 10, 2009, 03:17:11 pm
I have some computers here where I am at (a couple of them are quite slow), but I was unable to see any flicker on my gears demo applet on any of the computers.

Anyone else reading this post, do you experience flicker in hardware mode for the gears demo (http://www.paulscode.com/demos/jpct/jPCTGears/)?

Just to make sure we are on the same page, ErDetEnAnd are you experiencing flicker more-or-less every frame as the gears rotate in hardware rendering mode (in other words, do you start up the applet and it immediately begins flickering), or are you talking about something else?  How do you produce the problem?
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 11, 2009, 12:58:18 pm
It only flickers when another window is dragged on top of the browser or the browser window is dragged from outside the screen and towards the screen center. So when the applet's paint method is called by the system.
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 13, 2009, 01:08:21 am
I see that now.  Never thought it was a problem though - how often is someone going to be dragging the window around while they are playing?

I wonder if this is a limitation of applets in general, or just my applet?  Looking at the code, I don't see any reason this would happen?
Title: Re: Applet flickering with LWJGL
Post by: paulscode on January 13, 2009, 07:45:48 am
I read that thread you mentioned in your first post about overriding the update() method to remove flickering, and I had a thought.  This is just a shot in the dark, but perhaps the problem is coming from the Canvas - it's update() method is not being overridden.  That might explain why you only saw the problem in hardware rendering mode.  If that is what's going on, I don't really see any way around it, since you cannot override that Canvas.
Title: Re: Applet flickering with LWJGL
Post by: ErDetEnAnd? on January 13, 2009, 08:15:57 pm
Thank you for testing and for looking into this.

You're right about the size of the problem, if you're making a game. But thats not the case here :)

I've almost eliminated the flickering by calling canvas.paint(worldFrame.getGraphics()), and drawing several times when requested by the OS. I (hardly) cant get any flicker now. Ugly, but it works, and as written not done when rendering.
Title: Re: Applet flickering with LWJGL
Post by: bromokun on March 17, 2010, 12:52:45 pm
Hi ErDetEnAnd?

I'm experiencing the same flickering on my applet when I enable Hardware rendering ... btw .. I'm using the applet samples (HelloWorld) which posted on WIKI by paulscode in http://www.jpct.net/wiki/index.php/Applets.

So mr. ErDetEnAnd .... can you please share your code in order to eliminate this problem.

BTW .. I'm using a pretty stupid graphic card on my laptop which is: Intel Graphics Media Accelerator driver for Mobile ... is this the caused of my problem?

Thank you in advanced

Bromo
Title: Re: Applet flickering with LWJGL
Post by: bromokun on March 17, 2010, 01:47:54 pm
Okay,

Still using HelloWorld.java like in the wiki

I did set FrameBuffer in my init() method like this:

buffer = new FrameBuffer(getWidth(), getHeight(), FrameBuffer.SAMPLINGMODE_HARDWARE_ONLY);
buffer.usesRenderer(IRenderer.RENDERER_OPENGL);


but then in my paint(Graphic g) method I changed to become like this:

// buffer.displayGLOnly(); --> I commeted this line
buffer.display(myCanvas.getGraphics(), 0, 0); //--> my changed
myCanvas.repaint();


And my flickering has gone ... but my question is: by doing this ... is my Applet using Hardware rendering? or it returned to Software rendering?

Please advice
Title: Re: Applet flickering with LWJGL
Post by: bromokun on March 17, 2010, 04:50:32 pm
Is it possible to use org.lwjgl.opengl.AWTGLCanvas as Canvas to be render by jpct FrameBuffer? ...
Title: Re: Applet flickering with LWJGL
Post by: paulscode on March 17, 2010, 09:00:46 pm
// buffer.displayGLOnly(); --> I commeted this line
buffer.display(myCanvas.getGraphics(), 0, 0); //--> my changed
myCanvas.repaint();

And my flickering has gone ... but my question is: by doing this ... is my Applet using Hardware rendering? or it returned to Software rendering?
In hardware mode, calling buffer.display( Graphics, x, y ) supposedly does exactly the same thing as buffer.displayGLOnly() (i.e. the arguments are ignored).  EDIT: See the JavaDoc (http://www.jpct.net/doc/com/threed/jpct/FrameBuffer.html#display(java.awt.Graphics)) for reference.

But if using a different display() method magically fixes the flickering, then hell - go for it!  Maybe that call to getGraphics() is doing something unexpectedly behind the scenes which results in the flicker disappearing.  One possible way to test if that is what's happening would be to try something like this to see if it also stops the flickering:
Code: [Select]
myCanvas.getGraphics();
buffer.displayGLOnly();

As I mentioned in an earlier post, I don't experience this flicker on my computers here (perhaps the cpus/graphics cards are just too fast).  Does this flicker happen all the time, or just while moving the browser window around?
Title: Re: Applet flickering with LWJGL
Post by: EgonOlsen on March 17, 2010, 09:30:31 pm
However, judging from the code snippets you've posted, i assume that both renderers are active in your setup, which is not what you want (btw: FrameBuffer.useRenderer(...) just returns if the buffer uses this renderer, it doesn't change anything so your call to it is pointless at this stage). Create the FrameBuffer, disable the software renderer and enable the GL-Canvas renderer. Have a look at the HelloWorldAWTGL-example's source for this.

And btw: enableGLCanvasRenderer returns an org.lwjgl.opengl.AWTGLCanvas (or a subclass of it to be more precise).
Title: Re: Applet flickering with LWJGL
Post by: paulscode on March 18, 2010, 12:44:15 am
Good catch, I didn't notice that call to method 'usesRenderer' in your code snippet.  For hardware-accelerated rendering, try this instead:

Code: [Select]
        buffer = new FrameBuffer( width, height, FrameBuffer.SAMPLINGMODE_HARDWARE_ONLY );
        buffer.disableRenderer( IRenderer.RENDERER_SOFTWARE );
        myCanvas = buffer.enableGLCanvasRenderer();
        add( myCanvas, BorderLayout.CENTER);
        myCanvas.setVisible( true );

Then switching between software and hardware rendering modes can be done like this:

For software rendering:
Code: [Select]
                buffer.disableRenderer( IRenderer.RENDERER_OPENGL );
                buffer.enableRenderer(IRenderer.RENDERER_SOFTWARE );
                this.remove( myCanvas );
                this.validate();

For hardware-accelerated rendering:
Code: [Select]
                buffer.disableRenderer( IRenderer.RENDERER_SOFTWARE );
                myCanvas = buffer.enableGLCanvasRenderer();
                this.add( myCanvas, BorderLayout.CENTER);
                this.validate();
                myCanvas.setVisible( true );
                myCanvas.validate();
Title: Re: Applet flickering with LWJGL
Post by: bromokun on March 23, 2010, 11:22:26 am
HELLLLPPPPPP ....

I accidently delete my HelloWorld project .... so I try to recreate the applet I did ...
but now it doesn't work ... I believe its not my code (wishing) ...
But the error message is:

An error occured while loading the applet
Please contact support to resolve this issue
Fatal error occured(7): HelloWorld


What happened? ...
Title: Re: Applet flickering with LWJGL
Post by: paulscode on March 23, 2010, 07:04:09 pm
Fatal Error (7) means your applet crashed during initialization (i.e. before it started to run).  This usually means a typo in your appletloader html file (misspelled class names, filenames, or paths are most common reasons).  Some other common reasons are forgetting to compile the classes into a .jar or forgetting to include it in the al_jars parameter of the applet-loader.  Sometimes there is more useful information in the Java Console, could you please copy that and post it?  Also, post a copy of your html source (use [code] [\code] tags around it to make it readable -- not that you wouldn't, but just a reminder).