openGL API之glFrontFace()详解

openGL系列文章目录

前言

glFrontFace()官方文档说明
Name
glFrontFace — define front- and back-facing polygons

C Specification
void glFrontFace( GLenum mode);

Parameters
mode
Specifies the orientation of front-facing polygons. GL_CW and GL_CCW are accepted. The initial value is GL_CCW.

Description
In a scene composed entirely of opaque closed surfaces, back-facing polygons are never visible. Eliminating these invisible polygons has the obvious benefit of speeding up the rendering of the image. To enable and disable elimination of back-facing polygons, call glEnable and glDisable with argument GL_CULL_FACE.

The projection of a polygon to window coordinates is said to have clockwise winding if an imaginary object following the path from its first vertex, its second vertex, and so on, to its last vertex, and finally back to its first vertex, moves in a clockwise direction about the interior of the polygon. The polygon’s winding is said to be counterclockwise if the imaginary object following the same path moves in a counterclockwise direction about the interior of the polygon. glFrontFace specifies whether polygons with clockwise winding in window coordinates, or counterclockwise winding in window coordinates, are taken to be front-facing. Passing GL_CCW to mode selects counterclockwise polygons as front-facing; GL_CW selects clockwise polygons as front-facing. By default, counterclockwise polygons are taken to be front-facing.

Errors
GL_INVALID_ENUM is generated if mode is not an accepted value.

Associated Gets
glGet with argument GL_FRONT_FACE

Version Support
OpenGL Version
Function / Feature Name 2.0 2.1 3.0 3.1 3.2 3.3 4.0 4.1 4.2 4.3 4.4 4.5
glFrontFace ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔
See Also
glCullFace,

Copyright
Copyright © 1991-2006 Silicon Graphics, Inc. Copyright © 2010-2014 Khronos Group. This document is licensed under the SGI Free Software B License. For details, see https://khronos.org/registry/OpenGL-Refpages/LICENSES/LicenseRef-FreeB.txt.

二、翻译

名称

glFrontFace-指定正面和背面可以剔除

C规格

void glFrontFace( GLenum mode);

参数

模式

指定正面或背面的方面是否适用于剔除。 接受的符号常量 _ 为 gl 前、gl _ 后和 gl _ 前后的 _ _ 情况。 默认值为 GL _ 回。

描述

在完全由不透明闭合曲面组成的场景中,后向多边形永远不可见。消除这些不可见多边形明显有利于加快图像的渲染速度。要启用和禁用背面多边形的消除,请使用参数GL_CULL_FACE调用glEnable和glDisable。

如果一个假想物体沿着从其第一个顶点、第二个顶点等到最后一个顶点、最后回到第一个顶点的路径沿顺时针方向围绕多边形内部移动,则多边形到窗口坐标的投影称为顺时针弯曲。如果沿着同一路径的假想对象围绕多边形内部沿逆时针方向移动,则称多边形的缠绕为逆时针方向。glFrontFace指定在窗口坐标中顺时针缠绕或在窗口坐标中逆时针缠绕的多边形是否被视为正面。将GL_CCW传递到模式选择逆时针多边形作为正面;GL_CW选择顺时针多边形作为正面。默认情况下,逆时针方向的多边形被视为正面。

GlCullFace 函数指定在启用方面剔除时,是按模式) (按 模式 指定面向正面还是向后的方面。 使用 glEnable 和 GLDISABLE 以及参数 GL 剔除面来启用和禁用方面 _ 剔除 _ 。 方面包括三角形、quadrilaterals、多边形和矩形。

GlFrontFace函数指定哪个顺时针和逆时针小平面朝正面和反面。

如果 模式 是 GL _ 正面 _ 和 _ 背面,则不绘制任何方面,而是绘制其他基元,如点和线条。

以下函数检索与 glCullFace 相关的信息:

带参数的 glGet _ 精选 _ 面部 _ 模式

带参数的 glIsEnabled的 _ 精选 _ 脸

错误

如果模式不是可接受的值,则生成GL_无效_枚举。

关联get

带参数GL_前面的glGet

版本支持

OpenGL版本

功能/特征名称2.0 2.1 3.0 3.1 3.2 3.3 4.0 4.1 4.2 4.3 4.4.5

正面✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔

另见

我的脸,

版权

版权所有©1991-2006 Silicon Graphics,Inc.版权所有©2010-2014 Khronos Group。本文档根据SGI自由软件B许可证进行许可。有关详细信息,请参阅https://khronos.org/registry/OpenGL-Refpages/LICENSES/LicenseRef-FreeB.txt.

例子

#include "glew/glew.h"
#include "glfw/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "Sphere.h"
#include "Utils.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

static const int screen_width = 1920;
static const int screen_height = 1080;

int width = 0, height = 0;
float aspect = 0.f;
float cameraX = 0.f, cameraY = 0.f, cameraZ = 0.f;
float sphereLocX = 0.f, spherelocY = 0.f, sphereLocZ = 0.f;

GLuint renderingProgram = 0;
static const int numberVAOs = 1;
static const int numberVBOs = 3;
GLuint vao[numberVAOs] = { 0 };
GLuint vbo[numberVBOs] = { 0 };

glm::mat4 mMat(1.f), vMat(1.f), mvMat(1.f), pMat(1.f);
int mvLoc = 0;
int projLoc = 0;
float rotAmt = 0.f;

GLuint earthTextureId = 0;

Sphere earth = Sphere(48);

void setupVertices()
{
	vector<int> ind = earth.getIndices();
	vector<glm::vec3> vert = earth.getVertices();
	vector<glm::vec2> tex = earth.getTexCoords();
	vector<glm::vec3> norm = earth.getNormals();
	vector<glm::vec3> tang = earth.getTangents();

	vector<float> pValues;
	vector<float> tValues;
	vector<float> nValues;

	int numIndices = earth.getNumIndices();
	for (int i=0; i<numIndices; i++)
	{
		pValues.push_back((vert[ind[i]]).x);
		pValues.push_back((vert[ind[i]]).y);
		pValues.push_back((vert[ind[i]]).z);

		tValues.push_back((tex[ind[i]]).s);
		tValues.push_back((tex[ind[i]]).t);

		nValues.push_back((norm[ind[i]]).x);
		nValues.push_back((norm[ind[i]]).y);
		nValues.push_back((norm[ind[i]]).z);
	}

	glGenVertexArrays(numberVAOs, vao);
	glBindVertexArray(vao[0]);

	glGenBuffers(numberVBOs, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, pValues.size() * 4, &pValues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, tValues.size() * 4, &tValues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
	glBufferData(GL_ARRAY_BUFFER, nValues.size() * 4, &nValues[0], GL_STATIC_DRAW);
}

void init(GLFWwindow* window)
{
	renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");
	cameraX = 0.f, cameraY = 0.f, cameraZ = 6.f;
	sphereLocX = 0.f, spherelocY = 0.f, sphereLocZ = 0.f;
	glfwGetFramebufferSize(window, &width, &height);

	//屏幕坐标和窗口的帧缓冲
	/*GLFW在这里和这里解释文档中的两个坐标系。
		简而言之,窗口坐标是相对于监视器和 / 或窗口的,并且以不一定对应于真实屏幕像素的人造单元给出。 当DPI缩放被激活时(例如,在带有视网膜显示器的Mac上),情况尤其如此。
		与窗口坐标相比,帧缓冲区的大小与像素相关,以便与glViewport OpenGLs要求相匹配。
		请注意,在某些系统上,窗口坐标和像素坐标可以相同,但这不一定是正确的。*/
	aspect = (float)width / (float)height;
	pMat = glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);

	setupVertices();

	earthTextureId = Utils::loadTexture("resource/earth.jpg");
}

void display(GLFWwindow* window, float currentTime)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.1f, 0.2f, 1.f, 1.f);

	//必不可少!!!否则窗口是黑的,不会渲染任何东西
	glUseProgram(renderingProgram);

	mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");

	//移动相机矩阵:这里必须是-cameraZ,否则相机看不到球体
	vMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, -cameraZ));
	mMat = glm::translate(glm::mat4(1.f), glm::vec3(sphereLocX, spherelocY, sphereLocZ));
	mMat = glm::rotate(glm::mat4(1.f), currentTime * 0.5f, glm::vec3(0.f, 1.f, 0.f));


	//右乘规则
	//mvMat = mMat * vMat;   //金字塔会离开视口
	mvMat = vMat * mMat;

	//更改一个uniform矩阵变量或数组的值。要更改的uniform变量的位置由location指定,location的值应该由glGetUniformLocation函数返回
	// 将透视矩阵和MV 矩阵复制给相应的统一变量
	/*通过一致变量(uniform修饰的变量)引用将一致变量值传入渲染管线。
	  location : uniform的位置。
	  count : 需要加载数据的数组元素的数量或者需要修改的矩阵的数量。
	  transpose : 指明矩阵是列优先(column major)矩阵(GL_FALSE)还是行优先(row major)矩阵(GL_TRUE)。
	  value : 指向由count个元素的数组的指针。
	*/
	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));

	//绑定到球体顶点缓冲区
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	//指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置
	/*Parameters
	index
		指定要修改的顶点属性的索引值

		size
		指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(梦维:如position是由3个(x, y, z)组成,而颜色是4个(r, g, b, a))

		type
		指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。

		normalized
		指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。

		stride
		指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。

		pointer
		指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0。*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	//启用或禁用通用顶点属性数组,参数0索引和着色器中的layout(location = 0)中的0相对应,顶点位置
	glEnableVertexAttribArray(0);

	//绑定到纹理坐标
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

	//激活纹理坐标 
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, earthTextureId);

	//背面剔除,默认情况下,背面剔除是关闭的
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);

	glDrawArrays(GL_TRIANGLES, 0, earth.getNumIndices());
	//glDrawArrays(GL_TRIANGLES, 0, earth.getNumVertices());
}

void window_size_callback(GLFWwindow* window, int newWidth, int newHeight)
{
	glViewport(0, 0, newWidth, newHeight);
	aspect = (float)newWidth / (float)newHeight;
	pMat = glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);
}

int main(int argc, char** argv)
{
	int glfwState = glfwInit();
	if (GLFW_FALSE == glfwState)
	{
		cout << "GLFW initialize failed,invoke glfwInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
	glfwWindowHint(GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);

	GLFWwindow* window = glfwCreateWindow(screen_width, screen_height, "Sphere Draw", nullptr, nullptr);
	if (!window)
	{
		cout << "GLFW create window failed,invoke glfwCreateWindow()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwMakeContextCurrent(window);

	glfwSetWindowSizeCallback(window, window_size_callback);

	glfwSwapInterval(1);

	int glewState = glewInit();
	if (GLEW_OK != glewState)
	{
		cout << "GLEW initialize failed,invoke glewInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	init(window);

	while (!glfwWindowShouldClose(window))
	{
		display(window, (float)glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);

	return 0;
}

顶点着色器

#version 460 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoords;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

//uniform sampler2D samp;
layout (binding = 0) uniform sampler2D samp;

//out vec4 color;
out vec2 tc;

void main()
{
	gl_Position = proj_matrix * mv_matrix * vec4(position, 1.f);
	tc = texCoords;
}


片元着色器

#version 460 core

in vec2 tc;
out vec4 color;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

layout(binding = 0) uniform sampler2D samp;

void main()
{
	color = texture(samp, tc);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值