SDL изменяемая программа не рисует OpenGL правильно - PullRequest
2 голосов
/ 02 марта 2012

На прошлой неделе я купил старую книгу по OpenGL (супербиблию OpenGL, разработанную для Windows 95) за доллар, думая, что смогу получить некоторые идеи рисования в 3D и OpenGL. Весь код использует эту странную библиотеку Windows, поэтому я переносил примеры на SDL OpenGL. Я застрял на примере окна с изменяемым размером, в котором квадрат рисуется в центре независимо от размера окна. По какой-то причине квадрат отображается только при первом изменении размера, и после этого я его больше не вижу, независимо от того, как изменить размер окна.

Кто-нибудь знает, в чем проблема?

#include <stdio.h>
#include <stdlib.h>
#include "SDL.h"
#include "SDL_opengl.h"

#define TRUE 1
#define FALSE 0

#define WIN_WIDTH 500
#define WIN_HEIGHT 400
#define BPP 32

//go through and get the values to see if everything was set
int check_gl_init(int r_size, int g_size, int b_size, int dbuff) {
    int red, green, blue, doublebuf;

    SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &red);
    if(red != r_size) { return FALSE; }
    SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &green);
    if(green != g_size) { return FALSE; }
    SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &blue);
    if(blue != b_size) { return FALSE; }
    SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuf);
    if(dbuff != doublebuf) { return FALSE; }

    return TRUE;
}

int main(int argc, char** argv) {
    SDL_Init(SDL_INIT_EVERYTHING);
    atexit(SDL_Quit);

    SDL_Surface* screen;
    SDL_Event e;
    int w = WIN_WIDTH; int h = WIN_HEIGHT;
    Uint32 vid_flags = SDL_OPENGL | SDL_RESIZABLE;

    if(SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
    if(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
    if(SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
    if(SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
    if(SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
    if(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) < 0) {
        printf("couldn't set double buffering: %s\n", SDL_GetError());
    } else { vid_flags |= SDL_DOUBLEBUF; }

    const SDL_VideoInfo* info = SDL_GetVideoInfo();
    if(info->hw_available == TRUE) { vid_flags |= SDL_HWSURFACE; } else { vid_flags |= SDL_SWSURFACE; }
    printf("hardware surfaces available?: %s\n", (info->hw_available == TRUE ? "yes" : "no"));
    if(info->blit_hw == TRUE) { vid_flags |= SDL_HWACCEL; }
    printf("hardware blits available?: %s\n", (info->blit_hw == TRUE ? "yes" : "no"));

    if(SDL_VideoModeOK(WIN_WIDTH, WIN_HEIGHT, BPP, vid_flags) == 0) {
        printf("error: video mode not supported: `%s'\n", SDL_GetError());
        return 0;
    }
    else {
        screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, BPP, vid_flags);
        if(screen == NULL) {
            printf("no video: `%s'\n", SDL_GetError());
            return 0;
        }
    }

    if(check_gl_init(BPP / 4, BPP / 4, BPP / 4, TRUE) == FALSE) {
        printf("problem setting up opengl: %s\n", glGetString(glGetError()));
        return 0;
    }

    int running = TRUE;
    for(;running;) {
        //process events
        while(SDL_PollEvent(&e)) {
            if(e.type == SDL_VIDEORESIZE) {
                w = e.resize.w; h = e.resize.h;
                if(h == 0) { h = 1; } //prevent division by zero
                screen = SDL_SetVideoMode(w, h, BPP, vid_flags);
                if(screen == NULL) {
                    printf("sdl error, screen died: `%s'\n", SDL_GetError());
                }

                glViewport(0, 0, w, h); //x, y, w, h
                glLoadIdentity(); //reset coordinate system
                glMatrixMode(GL_PROJECTION);

                if(w <= h) {
                    glOrtho(0.0f, 250.0f, 0.0f, 250.0f * (h / w), 1.0, -1.0);
                }
                else {
                    glOrtho(0.0f, 250.0f * (w / h), 0.0f, 250.0f, 1.0, -1.0);
                }

                glMatrixMode(GL_MODELVIEW);
                glLoadIdentity();

                if(glGetError() != GL_NO_ERROR) {
                    printf("opengl error: %s\n", glGetString(glGetError()));
                }
            }
            if(e.type == SDL_QUIT) { running = FALSE; }
            if(e.type == SDL_KEYDOWN) { if(e.key.keysym.sym == SDLK_q) { running = FALSE; } }
        }

        glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //clear with blue
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glColor3f(1.0f, 0.0f, 0.0f); //red
        glRectf(100.0f, 150.0f, 150.0f, 100.0f);

        glFlush();
        SDL_GL_SwapBuffers();
        SDL_Delay(100);
    }

    SDL_Quit();
    return 0;
}

1 Ответ

2 голосов
/ 02 марта 2012

У вас есть это:

glLoadIdentity(); //reset coordinate system
glMatrixMode(GL_PROJECTION);

Эта последовательность загрузит матрицу идентификаторов в стек GL_MODELVIEW, так как это был самый последний стек, установленный через glMatrixMode() во время последнего изменения размера.

glOrtho() затем умножает новую матрицу ортопроекции на последнюю.Как вы видели, это не очень хорошо работает.

Установите режим матрицы, , а затем загрузите матрицу идентификации:

glMatrixMode(GL_PROJECTION);
glLoadIdentity(); //reset coordinate system
...