【问题标题】:gluPerspective not workinggluPerspective 不工作
【发布时间】:2014-01-10 06:29:39
【问题描述】:

我使用 gluPerspective 主要是增加绘制距离,但它似乎不起作用。

这是它在我的代码中的显示方式:

gluPerspective(0, 70/70, 0, 4333);

ratio:窗口的宽度和高度都是 700 并且它们是恒定的,以防万一。

fovy:我放 0 是因为“他们”说使用 45 画起来非常好,但它会停止在屏幕上画。

这是完整的代码:

#include <Windows.h>
#include <gl\GL.h>
#include <gl/glut.h>

    WNDCLASSEX wclass;
    MSG msg;
    HWND hwnd;
    HDC hdc;

    HDC p_hdc;

    float t;
    int red, green, blue, x, y, z;
    void update()
    {
        RECT rec;
        GetClientRect(hwnd, &rec);
        InvalidateRect(hwnd, &rec, false);
        UpdateWindow(hwnd);
        t += 0.5f;
    }
    void game()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0, 0, 0, 0);
        float norm = 1;
        float z = 0;
        red = 255;
        green = 255;
        glPushMatrix();
        glRotatef(t, 0, 1, 1);
        glBegin(GL_TRIANGLES);
        glColor3f(255, 0, 0);
        glVertex3f(-norm, norm, z);
        glVertex3f(norm, norm, z);
        glColor3f(0, 110, 10);
        glVertex3f(-norm, -norm, z);
        glEnd();
        gluPerspective(45, 70/70, 0.01f, 4333);
        glPopMatrix();
        SwapBuffers(hdc);
    }
    HGLRC hrc;
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpstr, int nCmdShow)
{

    wclass.cbSize = sizeof(WNDCLASSEX);
    wclass.style = 0;
    wclass.lpfnWndProc = WinProc;
    wclass.cbClsExtra = 0;
    wclass.cbWndExtra = 0;
    wclass.hInstance = hInstance;
    wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    wclass.lpszMenuName = NULL;
    wclass.lpszClassName = "CLASS";
    wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wclass))
    {
         MessageBox(0, "Windows Class Registration Failure Detected!\nProgram Can't Be Initialized..", "Failure Detected", MB_ICONERROR | MB_OK);
         return 0;
    }

    hwnd = CreateWindowEx(
    0, "CLASS", "OPENGL WORLD", WS_OVERLAPPEDWINDOW,
    0, 0, 700, 700,
    HWND_DESKTOP, NULL, hInstance, NULL
    );

    EnableOpenGL(hwnd, &hdc, &hrc);
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    if(hwnd == NULL)
    {
        MessageBox(0, "Windows Form Creation Failure..", "Failure", MB_ICONERROR | MB_OK);
    }
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
    {
        case WM_CREATE:
            SetTimer(hwnd, 1, 1, NULL);
            break;
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        case WM_TIMER:
            game();
            update();
            break;
        case WM_PAINT:
            PAINTSTRUCT ps;
            HDC win;
            win = BeginPaint(hwnd, &ps);
            p_hdc = win;
            game();
            EndPaint(hwnd, &ps);
            break;
        default:
                return DefWindowProc (hwnd, msg, wParam, lParam);
    }

    return 0;
}

void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
    PIXELFORMATDESCRIPTOR pfd;

    int iFormat;

    *hDC = GetDC(hwnd);

    ZeroMemory(&pfd, sizeof(pfd));

    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW |
                  PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE;

    iFormat = ChoosePixelFormat(*hDC, &pfd);

    SetPixelFormat(*hDC, iFormat, &pfd);

    *hRC = wglCreateContext(*hDC);

    wglMakeCurrent(*hDC, *hRC);
}

怎么办?

编辑:新代码

#include <Windows.h>
#include <gl\GL.h>
#include <gl/glut.h>

    WNDCLASSEX wclass;
    MSG msg;
    HWND hwnd;
    HDC hdc;

    HDC p_hdc;

    float t;
    int red, green, blue, x, y, z;
    float cx, cy, cz;

    void handle_resize()
    {
        RECT rec;
        GetClientRect(hwnd, &rec);
        long width = rec.right - rec.left;
        long height = rec.top - rec.bottom;
        float aspect = (float)width/(float)height;

        glViewport(0, 0, 700, 700);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, aspect, 0.01f, 99999);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
    void update()
    {
        RECT rec;
        GetClientRect(hwnd, &rec);
        InvalidateRect(hwnd, &rec, false);
        UpdateWindow(hwnd);
        t += 0.5f;
        cz = -3;
    }
    void game()
    {
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        float norm = 1;
        float z = 0;
        red = 255;
        green = 255;

        glPushMatrix();
        glRotatef(t, 0, 1, 1);
        glBegin(GL_TRIANGLES);
        glColor3f(255, 0, 0);
        glVertex3f(-norm, norm, z);
        glVertex3f(norm, norm, z);
        glColor3f(0, 110, 10);
        glVertex3f(-norm, -norm, z);
        glEnd();
        glPopMatrix();

        SwapBuffers(hdc);
    }
    HGLRC hrc;
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpstr, int nCmdShow)
{

    wclass.cbSize = sizeof(WNDCLASSEX);
    wclass.style = 0;
    wclass.lpfnWndProc = WinProc;
    wclass.cbClsExtra = 0;
    wclass.cbWndExtra = 0;
    wclass.hInstance = hInstance;
    wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    wclass.lpszMenuName = NULL;
    wclass.lpszClassName = "CLASS";
    wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wclass))
    {
         MessageBox(0, "Windows Class Registration Failure Detected!\nProgram Can't Be Initialized..", "Failure Detected", MB_ICONERROR | MB_OK);
         return 0;
    }

    hwnd = CreateWindowEx(
    0, "CLASS", "OPENGL WORLD", WS_OVERLAPPEDWINDOW,
    0, 0, 700, 700,
    HWND_DESKTOP, NULL, hInstance, NULL
    );

    EnableOpenGL(hwnd, &hdc, &hrc);
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    glMatrixMode(GL_PROJECTION);
    glMatrixMode(GL_MODELVIEW);
    if(hwnd == NULL)
    {
        MessageBox(0, "Windows Form Creation Failure..", "Failure", MB_ICONERROR | MB_OK);
    }
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
    {
        case WM_CREATE:
            SetTimer(hwnd, 1, 1, NULL);
            break;
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        case WM_TIMER:
            game();
            update();
            break;
        case WM_PAINT:
            PAINTSTRUCT ps;
            HDC win;
            win = BeginPaint(hwnd, &ps);
            p_hdc = win;
            game();
            EndPaint(hwnd, &ps);
            break;
        case WM_SIZE:
            handle_resize();
            break;
        default:
                return DefWindowProc (hwnd, msg, wParam, lParam);
    }

    return 0;
}

void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
    PIXELFORMATDESCRIPTOR pfd;

    int iFormat;

    *hDC = GetDC(hwnd);

    ZeroMemory(&pfd, sizeof(pfd));

    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW |
                  PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE;

    iFormat = ChoosePixelFormat(*hDC, &pfd);

    SetPixelFormat(*hDC, iFormat, &pfd);

    *hRC = wglCreateContext(*hDC);

    wglMakeCurrent(*hDC, *hRC);
}

【问题讨论】:

  • “绘制距离”究竟是什么意思?
  • @derhass 远平面
  • 你在这段代码中做的事情完全是乱序的,你也对所有事情都使用了单一的矩阵模式。您的投影矩阵应在初始化和/或窗口尺寸更改时设置。您的一般查看转换(例如glRotate (...))应该使用 ModelView 矩阵模式而不是投影来完成。
  • @AndonM.Coleman 所以我写了 glMatrixMode(GL_MODELVIEW);。结果显然没有改变。你能写一个答案而不是评论,更具体吗?
  • @AndonM.Coleman update() 用于更新窗口。获取客户端窗口的矩形大小,使其无效并更新窗口。它更像是 Win32,而不是其他任何东西。它不是 OpenGL。我似乎不明白什么是 WM_RESIZE,谷歌也没有告诉我。 glViewport 没有改变任何东西。该死!

标签: c++ opengl drawing


【解决方案1】:
gluPerspective(0, 70/70, 0, 4333);
               ^ nope    ^ nope

fovyzNear 必须都是正数且非零。

试试这个:

gluPerspective( 45, 70/70, 0.1, 4333 );

编辑:把你的相机也往后推一点:

#include <GL/glut.h>

float t = 0;
void timer( int val )
{
    t += 0.5f;
    glutTimerFunc( 10, timer, 0 );
    glutPostRedisplay();
}

void display()
{
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    gluPerspective( 45, w / h, 0.1, 4333.0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glTranslatef( 0, 0, -5 );

    float norm = 1;
    float z = 0;
    glPushMatrix();
    glRotatef(t, 0, 1, 1);
    glBegin(GL_TRIANGLES);
    glColor3f(255, 0, 0);
    glVertex3f(-norm, norm, z);
    glVertex3f(norm, norm, z);
    glColor3f(0, 110, 10);
    glVertex3f(-norm, -norm, z);
    glEnd();
    glPopMatrix();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 640, 480 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutTimerFunc( 0, timer, 0 );
    glutMainLoop();
    return 0;
}

【讨论】:

  • @HelderArmando:那完全是一个不同的问题。但是,在透视投影矩阵中对 zNear 使用 0.0 无效。事实上,如果 gluPerspective (...) 实际上是 OpenGL API 的一部分,那么如果您尝试这样做,它会引发 GL_INVALID_VALUE 错误。同样,垂直视野的 0 也是无效的——不过这个问题几乎从来没有出现过,因为有谁会尝试设置 0 度 FoV? :P
  • @AndonM.Coleman 是的。我只是愚蠢。但就像我说的,我还处于 OpenGL 的初级阶段......我应该把 gluPerspective() 函数放在 SwapBuffers() 之前和绘制之后,对吧?!
  • @HelderArmando:不,你把它放在你需要画东西之前。它为设置后绘制的所有内容定义了在图像平面(用于所有意图和目的的监视器/窗口)上的投影。你真的只需要设置一次,因为 GL 是一个状态机,它会记住你设置的所有状态,直到你改变它们。
  • @AndonM.Coleman 但是,当我在绘制之前设置它时,它根本不绘制任何东西......我错过了一些非常重要的东西吗?
  • @HelderArmando:从事物的声音来看,是的。但是您在原始问题中没有包含足够的信息来回答此评论。我建议您编辑原始问题,而不是在对此答案的评论中创建一串新问题。
【解决方案2】:

根据我们的 cmets,我对您的代码进行了一些更改,这些更改对于正确处理透视投影矩阵和窗口大小是必要的。这段代码还有很多我不喜欢的地方,比如使用计时器绘图,但这至少应该解决一些小问题。

新代码:

void handle_resize (void)
{
    RECT rec;
    GetClientRect(hwnd, &rec);

    long width  = rec.right - rec.left;
    long height = rec.top   - rec.bottom;

    float aspect = (float)width/(float)height;

    glViewport     (0, 0, width, height);

    glMatrixMode   (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (45, aspect, 0.01f, 4333);

    glMatrixMode   (GL_MODELVIEW);
    glLoadIdentity ();
}

void game()
{
    glClearColor(0, 0, 0, 0); // Do this first
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float norm = 1;
    float z = 0;
    red = 255;
    green = 255;
    glMatrixMode (GL_MODELVIEW);
    glPushMatrix();
    glRotatef(t, 0, 1, 1);
    glBegin(GL_TRIANGLES);
    glColor3ub(255, 0, 0);
    glVertex3f(-norm, norm, z);
    glVertex3f(norm, norm, z);
    glColor3ub(0, 110, 10);
    glVertex3f(-norm, -norm, z);
    glEnd();
    //gluPerspective(45, 70/70, 0.01f, 4333); // GET THIS OUT OF HERE!!!
    glPopMatrix();
    SwapBuffers(hdc);
}

对窗口消息处理程序的更改:

switch (msg)
{
    case WM_CREATE:
        SetTimer(hwnd, 1, 1, NULL);
        break;

    // NEW EVENT: Handle window size change
    case WM_SIZE:
        handle_resize ();
        break;

其他注意事项:

glColor3f 将浮点值限制在 [0.0,1.0] 范围内,您使用的是 255 的值,这仅在您使用 glColor3ub 时才适用,本质上是相同的glColor3f (1.0f, 1.0f, 1.0f)

【讨论】:

  • 不显示任何内容。我要编辑问题并放入当前代码...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多