【问题标题】:How to draw Ice Cream with OpenGL如何使用 OpenGL 绘制冰淇淋
【发布时间】:2019-04-29 01:43:54
【问题描述】:

作为问题,如何绘制 3d 冰淇淋?我画了一个圆锥和一个球。但是球不能装进锥体……我尝试了很多方法,但是球要么在锥体后面,要么在整个锥体中……任何人都可以对此感到满意。我已经按照讲师的说明进行了操作,但仍然无法获得。

#include <Windows.h>
#include <gl/GL.h>
#include <math.h>
#include <time.h>
#include <gl/GLU.h>
#pragma comment (lib, "OpenGL32.lib")
#pragma comment (lib, "GLU32.lib")

#define WINDOW_TITLE "OpenGL Window"

LRESULT WINAPI WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        break;
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}
//--------------------------------------------------------------------

bool initPixelFormat(HDC hdc)
{
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));

    pfd.cAlphaBits = 8;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 0;

    pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;

    pfd.iLayerType = PFD_MAIN_PLANE;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;

    // choose pixel format returns the number most similar pixel format available
    int n = ChoosePixelFormat(hdc, &pfd);

    // set pixel format returns whether it sucessfully set the pixel format
    if (SetPixelFormat(hdc, n, &pfd))
    {
        return true;
    }
    else
    {
        return false;
    }
}
//--------------------------------------------------------------------

void display()
{
    glPushMatrix();
    glRotatef(120, 1.0, 0, 0);

    GLUquadricObj  * cylinder = NULL;
    cylinder = gluNewQuadric();
    glColor3f(1, 0, 0);
    gluQuadricDrawStyle(cylinder, GLU_FILL);
    gluCylinder(cylinder, 0.52, 0.0, 2.0, 30, 20);
    gluDeleteQuadric(cylinder);

    GLUquadricObj  * sphere = NULL;
    sphere = gluNewQuadric();
    glColor3f(1, 1, 1);
    gluQuadricDrawStyle(sphere, GLU_LINE);
    gluSphere(sphere, 0.5, 20, 20);
    gluDeleteQuadric(sphere);

    glPopMatrix();
}
//--------------------------------------------------------------------

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpfnWndProc = WindowProcedure;
    wc.lpszClassName = WINDOW_TITLE;
    wc.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClassEx(&wc)) return false;

    HWND hWnd = CreateWindow(WINDOW_TITLE, WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 640,
        NULL, NULL, wc.hInstance, NULL);

    //--------------------------------
    //  Initialize window for OpenGL
    //--------------------------------

    HDC hdc = GetDC(hWnd);

    //  initialize pixel format for the window
    initPixelFormat(hdc);

    //  get an openGL context
    HGLRC hglrc = wglCreateContext(hdc);

    //  make context current
    if (!wglMakeCurrent(hdc, hglrc)) return false;

    //--------------------------------
    //  End initialization
    //--------------------------------

    ShowWindow(hWnd, nCmdShow);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2.0f, +3.0f, -2.0f, +2.0f, -10.0f, +10.0f);

    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT) break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        display();

        SwapBuffers(hdc);
    }

    UnregisterClass(WINDOW_TITLE, wc.hInstance);

    return true;
}
//--------------------------------------------------------------------

【问题讨论】:

  • 您是否启用了深度测试? glEnable(GL_DEPTH_TEST)?

标签: c winapi opengl


【解决方案1】:

请注意,由glBegin/glEnd 序列绘制、固定函数管道矩阵堆栈和每个顶点光照模型的固定函数管道,几十年来已被弃用。 阅读Fixed Function Pipeline 并查看Vertex SpecificationShader,了解最先进的渲染方式。


无论如何,在PIXELFORMATDESCRIPTOR 中正确指定了深度缓冲区:

 pfd.cDepthBits = 24;

现在您必须使用深度缓冲区。

附注,颜色缓冲位的数量应该是 24 而不是 32 请参阅cColorBits 的文档:

指定每个颜色缓冲区中颜色位平面的数量。 对于 RGBA 像素类型,它是颜色缓冲区的大小,不包括 alpha 位平面。对于颜色索引像素,它是颜色索引缓冲区的大小。


要使用深度缓冲区,Depth Test 必须由 glEnable 启用。
此外,默认帧缓冲区的颜色缓冲区和深度缓冲区必须在每帧开始时由 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) 清除。

void display()
{
    glEnable( GL_DEPTH_TEST );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glPushMatrix();
    glRotatef(120, 1.0, 0, 0);

    GLUquadricObj  * cylinder = NULL;
    cylinder = gluNewQuadric();
    glColor3f(1, 0.5, 0);
    gluQuadricDrawStyle(cylinder, GLU_FILL);
    gluCylinder(cylinder, 0.52, 0.0, 2.0, 30, 20);
    gluDeleteQuadric(cylinder);

    GLUquadricObj  * sphere = NULL;
    sphere = gluNewQuadric();
    glColor3f(1, 1, 0.5);
    gluQuadricDrawStyle(sphere, GLU_FILL);
    gluSphere(sphere, 0.5, 20, 20);
    gluDeleteQuadric(sphere);

    glPopMatrix();
}

查看预览,我将球体的 gluQuadricDrawStyleGLU_LINE 更改为 GL_FILL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-11
    • 2014-03-26
    • 2012-03-21
    • 1970-01-01
    相关资源
    最近更新 更多