Jump to content

View more

Image of the Day

Boxes as reward for our ranking mode. ヾ(☆▽☆)
#indiedev #gamedev #gameart #screenshotsaturday https://t.co/ALF1InmM7K
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

Multiple clipping planes

4: Adsense

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   


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

    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);
    printText(x+TEXT_FIELD_PADDING_X, y+textY, text, font, textSize);

    hasChanged = false;

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

    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 {
        if (cursorPos > selectPos)     // Draw selection
            fillRect(sxPos, y + TEXT_FIELD_PADDING_Y,
                     cxPos-sxPos, height-(2*TEXT_FIELD_PADDING_Y));
            fillRect(cxPos, y + TEXT_FIELD_PADDING_Y,
                     sxPos-cxPos, height-(2*TEXT_FIELD_PADDING_Y));

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

void Container::draw() {
    // 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 ###

    if (scrollBar) {
        glTranslated(x, y, 0);

/* 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);
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

    while(!appQuit) {
        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
            if (msg.message==WM_QUIT) {
                appQuit = true;
            else {
        else {
            Container::drawScreen();  // Draw the screen

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]

#2 XTAL256   Members   


Posted 21 June 2008 - 12:50 PM

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

#3 zedz   Members   


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   


Posted 22 June 2008 - 01:59 PM

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.