FBO/Textures/Window Scaling

threeam
Unregistered
 
Post: #1
I've implemented Ping-Pong FBO's (for some iterative graphical effects). My problem has to do with the fact that when I scale the window my performance decreases dramatically.

Now, I do know it is possible to scale the window and have textures display without performance loss due to the fact that I'm watching WinAmp do it right now. Their visualization plug-in MilkDrop seems to detect an ideal texture size and render that on to the window how ever the window is scaled. I do know the application is written in DirectX, if that matters.

I'm trying to find a way to achieve that effect.

I assumed that glViewPort(0, 0, 256, 256) would force GLSL Shaders to only execute 256*256 times regardless of the window size. What seems to be the behavior is that the dimensions of the window width*height worth of executions are taking place since the performance increases as I scale down and the performance decreases as I scale up.

I don't understand how to implement the viewport/opengl settings in such a way that it renders the texture to the quad in the fashion I'd like.

Will someone please take a look at this code I've posted and help me figure out where my error lies.

Thanks,



Code:
    // Send previous texture to glsl shader
    glBindTexture(GL_TEXTURE_2D, FBOTex[TexRenderWrite]);
    GLint TexLoc = glGetUniformLocation(p, "tex");
    glUniform1i(TexLoc, 0);

    // Bind FBO and set viewport
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO[FBOA]);
    glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT);
    glViewport(0, 0, SD, SD);

    // Set the active texture to draw to
    glDrawBuffer(AttchPoint[TexRenderRead]);
    glActiveTexture(GL_TEXTURE0 + TexRenderRead);
    
    // This will be drawn to the texture
    glPushMatrix();
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0); glVertex3f(-da, -da,  0.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(-da,  da,  0.0);
        glTexCoord2f(1.0, 1.0); glVertex3f( da,  da,  0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f( da, -da,  0.0);
    glEnd();
    glPopMatrix();

    // Unbinding the FBO will return to the default buffer so we
    // can draw to the screen
    glPopAttrib();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    // Resetting the viewport and drawing
    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glPushMatrix();
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0); glVertex3f(-da, -da,  0.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(-da,  da,  0.0);
        glTexCoord2f(1.0, 1.0); glVertex3f( da,  da,  0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f( da, -da,  0.0);
    glEnd();
    glPopMatrix();
    
    // Swap the buffer targets
    TexRenderRead = (TexRenderRead + 1)%2;
    TexRenderWrite = (TexRenderWrite + 1)%2;
    
    glutSwapBuffers();
    Sleep(1);
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #2
Off the top of my head the only performance killer I see is the gl{Push|Pop}Attrib. And while that's expensive, it's not that expensive.

Can you describe ping-ponging? I've done fullscreen glsl convolutions so I'm familiar with what I think you're doing, but I have not heard about ping ponging before...
Quote this message in a reply
threeam
Unregistered
 
Post: #3
Two parts, the FBO explaination, and beneath that my continuation so read through! Thanks...

----------
The FBO "Ping-Pong" is in the code I showed you, and that specifically I'm sure is unrelated to my problem, I'll explain it anyway.

I use an FBO to render to a texture A, on the next iteration of my codes execution I send Texture A to a sampler2D in my shader, and render to a Texture B. I can use the values of texture A to draw a next iteration on B. The third iteration is why it's called Ping-Pong. I send texture B to the sampler2D and render on to texture A.

In brief;

Frame +0:
TexA -> sampler2d
FBO -> TexB

Frame +1:
TexB -> sampler2d
FBO -> TexA

Frame +2:
TexA -> sampler2d
FBO -> TexB

... etc


See how the textures swap around the FBO? Iterative changes to my texture by swapping the buffer's texture around. It works great. The reason this technique is implemented this way is because an FBO can *only render to a target. Allowing me to side-step glCopyTexImage2D().

The benefit is the FBO method allows scaling. I need for that ability, only I need for it to occur in a very specific way which is the challenge I'm having, and it's frustrating for me now. : )

No one seems to know.



----------
I don't believe the problem is in that aspect of the FBO, I believe the problem might be glViewport while rendering to the FBO.

If my glViewport is telling the FBO to execute on a 256x256 texture, why does the performance hit count so dramatically in OpenGL when I scale?

I can only *assume it's not static, that the fragment shader is executing on every pixel on the screen not on the texture. I believe that because the more I scale my window the level of detail remains, where in actuality it should become more blurry as the "pixels" are scaled up and the performance should be hit only very slightly in that scenario. (Just like in WinAmp's MilkDrop Plug-in.)

I hope I've been clear enough, if not I'll explain further anything you'd like, I am very desperate to make this work so all help is much appreciated.


I'm expecting 256*256 fragment shader executions no matter what the scale of my window. I can only assume width*height number of executions are occurring, even when I specifically set the viewport for the FBO render to be 256x256.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
glViewport doesn't cause clipping, if the viewport is smaller than the drawable. You need glScissor as well.
Quote this message in a reply
threeam
Unregistered
 
Post: #5
I'm not really sure I understand what you're saying.

The only thing that comes to mind based on that statement alone is using glScalef to adjust the size of the quad, and since the quad would then be outside the range of the viewport to use scissoring to keep rendering down to a limited area?

I'll admit I don't entirely understand OpenGL as well as others so go easy on me of that wasn't what you mean or if it wasn't even correct.

Could you say more about what you mean?

I'll add I've already tried to use glScalef and scale up my applications window that was rendering a 256x256 texture. When scaled up it looked as though the effects (by the shaders) were still occurring pixel by pixel instead of at the textures resolution. That being unexpected since I'm trying to deliberately tell the FBO's to work on a texture of 256x256. There should not be this much detail in a 256x256 texture scaled up this high. Why is scaling not doing what I expect?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
OneSadCookie Wrote:glViewport doesn't cause clipping, if the viewport is smaller than the drawable. You need glScissor as well.

Sure seems to in my experience, but maybe I haven't tested with enough drivers/cards to see ones that don't.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
threeam Wrote:When I scale the window my performance decreases dramatically.
This is a good indication that you're fill rate limited. The main question here is "what does your fragment shader do?"

Quote:Now, I do know it is possible to scale the window and have textures display without performance loss due to the fact that I'm watching WinAmp do it right now.
That doesn't mean anything, unless you're using the exact same shader with the exact same textures and state that they're using.

Quote:I assumed that glViewPort(0, 0, 256, 256) would force GLSL Shaders to only execute 256*256 times regardless of the window size.

To clarify how things are drawn:

1) you submit vertices (like your quad)
2) vertices are transformed by the vertex stage into clip coordinates
3) anything outside of the clip frustum is clipped
4) the result is scaled by the viewport
5) each fragment is rasterized in the fragment stage
6) shaded fragments go through raster ops
7) fragments that pass all raster ops become pixels in the framebuffer

Re: clipping, it is stage 3 that does that. Not the viewport.

Triangles usually appear to be clipped by the viewport because the viewport is scaling the post-clip results of the vertex transform. But the viewport doesn't actually clip. Non-triangle primitives (like DrawPixels, or wide lines, or big points) can be rasterized outside of the viewport.

Quote:I don't understand how to implement the viewport/opengl settings in such a way that it renders the texture to the quad in the fashion I'd like.

There isn't enough info in your code to tell what's going on.

It sounds like you want to:

1) create two FBOs of fixed size (i.e. 256x256)
2) bind FBO A and set the viewport to match the FBO
3) draw effect A with your effect state (shader, etc)
4) bind window, set the viewport to the window dimensions
5) draw simple textured quad using FBO texture A (simple REPLACE texenv, etc)
6) repeat from step 2, except with FBO B. Texture from FBO A if you want.

But to figure out if you're fill rate limited, forget about the FBOs. Just draw your effect directly to the window as fast as you can and measure the fps. Then resize the window and watch what happens.
Quote this message in a reply
threeam
Unregistered
 
Post: #8
There's nothing much significant about the Shaders I'm writing at the moment. Just some trig functions on the RGB values to change them over time. Regardless of what combination of trig functions, I can't imagine any specific one will matter over the next. After all, visualization applications like WinAmp cycle through a wide variety, obviously, just look at it.

Say I change the entire thread to a new request. Can someone just simply describe to me in OpenGL terms what's going on in WinAmp's visualizations (specifically MilkDrop) when you scale the window they render in? How do I write an OpenGL application with the exact same configuration to allow for that behavior? (Being steady performance regardless of the size of the window being rendered to.)

If you tell me it can't be done, then you're admitting DirectX is capable of something OpenGL is not.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Copying from OpenGL window to other window Ingemar 7 4,890 Nov 4, 2006 03:50 AM
Last Post: OneSadCookie
  2D OpenGL With SDL Rotation + Scaling Problem Greywhind 4 4,102 Jun 2, 2006 04:16 PM
Last Post: Greywhind