c - 如何使用 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;
}
//--------------------------------------------------------------------
解决方案
请注意,按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_LINE
为GL_FILL
:
推荐阅读
- javascript - 排序函数中a和b分别代表什么
- vue.js - vuex:带有自定义参数的 mapActions
- swift - Firebase、Google Maps 和 Geofire 集成 ios swift
- api - Instagram - 获取直接消息
- javascript - Redis SCAN 没有给出 NodeJS 中的所有匹配项
- javascript - 从对象访问数组
- julia - Julia - 如何按组聚合许多列
- laravel - 从 docker 容器运行 laravel 迁移到远程主机
- dynamics-crm - 在多个资源之间分配 CRM 中的收入。
- c# - 如何处理多行 AddModelError 错误?