OpenGL绘制的正反面和GL_TRIANGLE_STRIP

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 n2个三角形。

示例一

核心代码:

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;
}

参考

  1. OpenGL之glPolygonMode函数的用法
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值