Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Don't forget to read Tuesday's email newsletter for your chance to win a free copy of Construct 2!


Multiple clipping planes


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 XTAL256   Members   -  Reputation: 103

Like
0Likes
Like

Posted 20 June 2008 - 01:33 AM

I am making a game using OpenGL (Visual C++, Windows) and i need to use multiple clipping planes. I use glScissor to clip a region of text within a GUI component (i.e. a label or textbox) and also to clip components within a container (i.e. window). How do i do both of these at the same time? Is it possible?
Here is a screenshot showing how i have my GUI:


EDIT: oh, i should mention how i am currently attempting to do it. See, i create an OpenGL display list for each GUI component (button, label, etc) and call that dl when i want to draw the component. I do this mainly because i only need to create the image when and if the component changes position or size. So i thought i could clip the text on a TextBox when i create the display list for it. And then when i draw the TextBox on the container in my screenshot, the image created by the dl would be clipped to the container. But that doesn't quite work.
Here is some of my code:
//// TextField.cpp ///////////////////

/* Updates the component's image when one of it's properties changes */
void TextField::update() {
    // Create display lists to draw the image
    createComponentDL(dlImg,img,x,y,width,height,divLeft,divRight);

    const int textSize = (int)(height*TEXT_FIELD_SIZE);
    const int textY = (int)(height/2.0f - textSize/2.0f);

    // Clip text to component edge
    clipRect(getAbsX()+TEXT_FIELD_PADDING_X, getAbsY(),
             width-(2*TEXT_FIELD_PADDING_X), height);
    buildList(dlText);
    printText(x+TEXT_FIELD_PADDING_X, y+textY, text, font, textSize);
    endList();
    disableClip();

    hasChanged = false;
}

void TextField::draw() {
    if (hasChanged) update();  // Update image if need be
    callList(dlImg);
    callList(dlText);

    int cxPos = x + getCharCoord(cursorPos);
    int sxPos = x + getCharCoord(selectPos);
    if (cxPos > width) cxPos = width;
    if (sxPos > width) sxPos = width;
    if (cursorPos == selectPos)
        drawLine(cxPos, y + TEXT_FIELD_PADDING_Y,
                 cxPos, y + height - TEXT_FIELD_PADDING_Y); // Draw cursor
    else {
        setLogicOp(GL_INVERT);
        if (cursorPos > selectPos)     // Draw selection
            fillRect(sxPos, y + TEXT_FIELD_PADDING_Y,
                     cxPos-sxPos, height-(2*TEXT_FIELD_PADDING_Y));
        else
            fillRect(cxPos, y + TEXT_FIELD_PADDING_Y,
                     sxPos-cxPos, height-(2*TEXT_FIELD_PADDING_Y));
        setLogicOp(GL_COPY);
    }
}

//// Container.cpp ////////////

void Container::draw() {
    glPushMatrix();
    // Clip to container bounds.
    clipRect(getAbsX(), getAbsY()+2, width, height);
    glTranslated(x + cX, y + cY, 0);   // Draw relative to container pos
    for (int i = 0; i < numComponents(); i++) {
        components[i]->draw();         //### Draw each component in this container ###
    }
    disableClip();
    glPopMatrix();

    if (scrollBar) {
        glPushMatrix();
        glTranslated(x, y, 0);
        scrollBar->draw();
        glPopMatrix();
    }
}

/* Draws the currently active Window/Panel and any other visible */
/* components (i.e. a Panel behind another Panel)                */
void Container::drawScreen() {
    for (int i = MAX_SCREENS; i >= 0; i--) { // Draw first one last
        if (Component::visible[i])
            Component::visible[i]->draw();  //### This draws the window shown in the screenshot ###
    }
}

//// Graphics.h /////////////
inline void clipRect(int x, int y, int width, int height) {
    glScissor(x, y, width, height);
    glEnable(GL_SCISSOR_TEST);
}
inline void disableClip() { glDisable(GL_SCISSOR_TEST); }


The textboxes (TextFields) in my screenshot are components in the Container, they are drawn in Container::draw().
I currently draw the screen in the WinMain loop (until i find a better way of doing it):
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int wndState) {
    MSG msg;
    // Init stuff
    ...
    loadGUIData();
    createUIScreens();

    while(!appQuit) {
        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
            if (msg.message==WM_QUIT) {
                appQuit = true;
            }
            else {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        else {
            clearScreen();
            Container::drawScreen();  // Draw the screen
            SwapBuffers(hdc);
            Sleep(20);
        }
    }
    ...
}


I haven't provided the code for the rest of my GUI (window code and stuff) but comments with ### explain what happens.

[Edited by - XTAL256 on June 20, 2008 7:50:52 PM]

Sponsor:

#2 XTAL256   Members   -  Reputation: 103

Like
0Likes
Like

Posted 21 June 2008 - 12:50 PM

Can anyone help me? Even if it's just a link to a tutorial online or something.
thanks

#3 zedz   Members   -  Reputation: 291

Like
0Likes
Like

Posted 21 June 2008 - 08:26 PM

i think youre over complicating things, overworrying but anyways
one possible method would be to use the stencil test
eg clear the stencil to 0, and set the window to 1, and the box to 2.
and then set it to only draw if the current stencil value of the pixel is > 0

also surely u only need to clip to one region at once? ie glScissor should be enuf

#4 XTAL256   Members   -  Reputation: 103

Like
0Likes
Like

Posted 22 June 2008 - 01:59 PM

Quote:
Original post by zedz
i think youre over complicating things, overworrying but anyways...

I don't see any other way of doing it. Like i mentioned, i am clipping each component when i create a display list for them and then clipping when the display list is drawn (so i am only using glScissor once at a time, sort of) but that doesn't work. I will read up on how to do it the way you mentioned but i would really like to know how i would do it a simpler way.
btw, i am sort of a n00b at OpenGL which is why i am "overworrying" :)

[Edited by - XTAL256 on June 23, 2008 7:59:59 PM]




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS