首页 > 解决方案 > 如何使用 OpenGL 绘制冰淇淋

问题描述

作为问题,如何绘制 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;
}
//--------------------------------------------------------------------

标签: cwinapiopengl

解决方案


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


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

 pfd.cDepthBits = 24;

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

旁注,颜色缓冲区位数应为 24 而不是 32,请参阅以下文档cColorBits

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


要使用深度缓冲区,必须通过 启用深度测试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();
}

查看预览,我将gluQuadricDrawStyle球体的从更改GLU_LINEGL_FILL


推荐阅读