OpenGL中正反面有什么意义?
这个我不清楚,暂时还没找到资料,找到资料再补
正反面是怎么用的?
只知道是绘制图元时,会从正面和反面两个方向绘制
正面绘制方向默认为:逆时针,GL_CCW
反面绘制方向默认为:顺时针,GL_CW
可以通过下面代码设置默认的正面绘制方向:
glFrontFace(GL_CW); //设置正面的绘制方向为顺时针
示例一
核心代码
//用来设置填充方式
#define GL_POINT 0x1B00
#define GL_LINE 0x1B01
#define GL_FILL 0x1B02
//绘制多边形
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_LINE);
glBegin(GL_POLYGON);
glVertex3f(-3.0f, -3.0f, -10.0f);
glVertex3f(0.0f, -3.0f, -10.0f);
glVertex3f(0.0f, 0.0f, -10.0f);
glVertex3f(-3.0f, 0.0f, -10.0f);
glEnd();
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, -10.0f);
glVertex3f(0.0f, 3.0f, -10.0f);
glVertex3f(3.0f, 3.0f, -10.0f);
glVertex3f(3.0f, 0.0f, -10.0f);
glEnd();
完整代码(直接复制粘贴,使用vs 2017就可以运行, 不用配置)
#include<Windows.h>
#include<GL/GL.h>
#include<GL/GLU.h>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#define GL_POINT 0x1B00
#define GL_LINE 0x1B01
#define GL_FILL 0x1B02
LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//windows的入口程序
INT WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
//1. 使用WNDCLASSEX结构体注册一个窗口
WNDCLASSEX wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = NULL;
//wndclass.hCursor = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = NULL;
wndclass.hIconSm = NULL;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = GLWindowProc;
wndclass.lpszClassName = L"GLWindow";
wndclass.lpszMenuName = NULL;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
//注册
ATOM atom = RegisterClassEx(&wndclass);
if (!atom) {
return -1;
}
//2. 创建一个窗口
HWND hwnd = CreateWindowEx(NULL, L"GLWindow", L"OpenGL Window", WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);
//2.1 创建OpenGL 渲染上下文(OpenGL render context)
HDC dc = GetDC(hwnd);
//像素格式描述符,用来选取OpenGL渲染的像素格式
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nVersion = 1;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.cColorBits = 32; //颜色缓冲区:rgba
pfd.cDepthBits = 24; //深度缓冲区
pfd.cStencilBits = 8;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
int pixelFormat = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, pixelFormat, &pfd);
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
// 初始化OpenGL
glClearColor(0.1f, 0.4f, 0.6f, 1.0f); //设置清除缓冲区的颜色
glMatrixMode(GL_PROJECTION); //要操作投影矩阵了,将三维信息(坐标等)投影到二维屏幕上
//角度,宽/高,近景,远景
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);
glMatrixMode(GL_MODELVIEW); //要操作模型视图矩阵了,将坐标系转换为视觉坐标系(相机放在原点,看向z轴负方向)?
glLoadIdentity();
//3. 显示窗口
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (true) {
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//绘制场景
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_LINE);
glBegin(GL_POLYGON);
glVertex3f(-3.0f, -3.0f, -10.0f);
glVertex3f(0.0f, -3.0f, -10.0f);
glVertex3f(0.0f, 0.0f, -10.0f);
glVertex3f(-3.0f, 0.0f, -10.0f);
glEnd();
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, -10.0f);
glVertex3f(0.0f, 3.0f, -10.0f);
glVertex3f(3.0f, 3.0f, -10.0f);
glVertex3f(3.0f, 0.0f, -10.0f);
glEnd();
//场景渲染到屏幕上去
SwapBuffers(dc);
}
return 0;
}
运行效果:
GL_TRIANGLE_STRIP
假设总共有 n n n个点, i = 0 , 1 , 2 , . . . n i =0, 1, 2, ...n i=0,1,2,...n,当 i i i为奇数时,绘制三角形的顺序为 i , i + 1 , i + 2 i, i+1, i+2 i,i+1,i+2,当 i i i为偶数时,绘制三角形的顺序为 i + 1 , i , i + 2 i+1, i, i+2 i+1,i,i+2,总共绘制 n − 2 n-2 n−2个三角形。
示例一
核心代码:
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-3.0f, -2.0f, -10.0f); //A
glVertex3f(3.0f, -2.0f, -10.0f); //B
glVertex3f(0.0f, 2.0f, -10.0f); //C
glVertex3f(0.0f, -4.0f, -10.0f); //D
glEnd();
已知共4个点,总共绘制2个三角形,分别为三角形
A
B
C
ABC
ABC,三角形
C
B
D
CBD
CBD。
可以看到
A
,
B
,
C
A, B, C
A,B,C的顺序为逆时针方向(正面),
C
B
D
CBD
CBD的顺序为顺时针方向。
看一下上述代码的运行效果:
剔除反面(顺时针方向绘制的面被剔除):
glEnable(GL_CULL_FACE); //开启表面剔除,默认剔除背面(默认顺时针旋转)
glCullFace(GL_BACK);
可以看到三角形 C B D CBD CBD被剔除了,只剩下了三角形 A B C ABC ABC
剔除正面(逆时针方向绘制的面被剔除):
glEnable(GL_CULL_FACE); //开启表面剔除,默认剔除背面(默认顺时针旋转)
glCullFace(GL_FRONT);
可以看到绘制三角形 A B C ABC ABC的面被剔除了。
完整代码:
#include<Windows.h>
#include<GL/GL.h>
#include<GL/GLU.h>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//windows的入口程序
INT WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
//1. 使用WNDCLASSEX结构体注册一个窗口
WNDCLASSEX wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = NULL;
//wndclass.hCursor = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = NULL;
wndclass.hIconSm = NULL;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = GLWindowProc;
wndclass.lpszClassName = L"GLWindow";
wndclass.lpszMenuName = NULL;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
//注册
ATOM atom = RegisterClassEx(&wndclass);
if (!atom) {
return -1;
}
//2. 创建一个窗口
HWND hwnd = CreateWindowEx(NULL, L"GLWindow", L"OpenGL Window", WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);
//2.1 创建OpenGL 渲染上下文(OpenGL render context)
HDC dc = GetDC(hwnd);
//像素格式描述符,用来选取OpenGL渲染的像素格式
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nVersion = 1;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.cColorBits = 32; //颜色缓冲区:rgba
pfd.cDepthBits = 24; //深度缓冲区
pfd.cStencilBits = 8;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
int pixelFormat = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, pixelFormat, &pfd);
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
// 初始化OpenGL
glClearColor(0.1f, 0.4f, 0.6f, 1.0f); //设置清除缓冲区的颜色
glMatrixMode(GL_PROJECTION); //要操作投影矩阵了,将三维信息(坐标等)投影到二维屏幕上
//角度,宽/高,近景,远景
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);
glMatrixMode(GL_MODELVIEW); //要操作模型视图矩阵了,将坐标系转换为视觉坐标系(相机放在原点,看向z轴负方向)?
glLoadIdentity();
//glEnable(GL_CULL_FACE); //开启表面剔除,默认剔除背面(默认顺时针旋转)
//glCullFace(GL_FRONT);
//3. 显示窗口
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (true) {
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//绘制场景
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-3.0f, -2.0f, -10.0f);
glVertex3f(3.0f, -2.0f, -10.0f);
glVertex3f(0.0f, 2.0f, -10.0f);
glVertex3f(0.0f, -4.0f, -10.0f);
glEnd();
//场景渲染到屏幕上去
SwapBuffers(dc);
}
return 0;
}