glEnable/glDisable(GL_CULL_FACE)与glCullFace()

本文介绍OpenGL中剔除操作与多边形显示模式的设置方法。通过glCullFace函数可以控制多边形的正面或背面是否参与渲染,以减少不必要的计算。glPolygonMode函数则允许开发者选择多边形的显示方式,如点、线或填充。

glEnalbe(GL_CULL_FACE) 开启剔除操作效果

glDisable(GL_CULL_FACE)关闭剔除操作效果

剔除操作

1.glCullFace()参数包括GL_FRONT和GL_BACK。表示禁用多边形正面或者背面上的光照、阴影和颜色计算及操作,消除不必要的渲染计算。

例如某对象无论如何位置变化,我们都只能看到构成其组成的多边形的某一面时,可使用该函数。

2.glPolygonMode

  简介

  glPolygonMode函数用于控制多边形的显示方式。
  原型是:void glPolygonMode(GLenum face,GLenum mode);

参数

  face这个参数确定显示模式将适用于物体的哪些部分,控制多边形的正面和背面的绘图模式:
  GL_FRONT表示显示模式将适用于物体的前向面(也就是物体能看到的面)
  GL_BACK表示显示模式将适用于物体的后向面(也就是物体上不能看到的面)
  GL_FRONT_AND_BACK表示显示模式将适用于物体的所有面
  mode这个参数确定选中的物体的面以何种方式显示(显示模式):
  GL_POINT表示只显示顶点,多边形用点显示
  GL_LINE表示显示线段,多边形用轮廓显示
  GL_FILL表示显示面,多边形采用填充形式
  例:
  glPolygonMode(GL_FRONT, GL_LINE);表示物体的前向面用线段显示
  需要特别注意的是OpenGL3.1只接受GL_FRONT_AND_BACK作为face的值,并且不管是多边形的正面还是背面都以相同的方式渲染。

#include "Lab3_2.h" #include <glad/glad.h> #include <iostream> //#include <glm/glm.hpp> Lab3_2::Lab3_2() { Vertex frontTriangle[] = { { -0.9f, -0.5f, 0.0f}, {-0.1f, -0.5f, 0.0f}, {-0.5f, 0.5f, 0.0f} }; Vertex backTriangle[] = { {0.0f, -0.5f, 0.0f}, {0.8f, -0.5f, 0.0f}, {0.4f, 0.5f, 0.0f} }; int count1 = sizeof(frontTriangle) / sizeof(Vertex); // 正确计算顶点数 int count2 = sizeof(backTriangle) / sizeof(Vertex); vertexShaderSource = R"( #version 460 core layout (location = 0) in vec3 aPos; void main() { gl_Position = vec4(aPos, 1.0); } )"; fragmentShader1Source = R"( #version 460 core out vec4 FragColor; void main() { FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0); // 橙色 } )"; fragmentShader2Source = R"( #version 460 core out vec4 FragColor; void main() { FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0); // 黄色 } )"; leftTriangle.setData(frontTriangle, count1); leftTriangle.setShaderString(vertexShaderSource, fragmentShader1Source); leftTriangle.initData(); rightTriangle.setData(backTriangle, count2); rightTriangle.setShaderString(vertexShaderSource, fragmentShader2Source); rightTriangle.initData(); } Lab3_2::~Lab3_2() { } void Lab3_2::setRenderParameter(bool enableCull, GLenum cullMode, GLenum frontFace) { this->enableCullFace = enableCull; this->cullMode = cullMode; this->frontFace = frontFace; } void Lab3_2::render() { // 应用 OpenGL 面剔除和绕向设置 glFrontFace(frontFace); if (enableCullFace) { glEnable(GL_CULL_FACE); glCullFace(cullMode); } else { glDisable(GL_CULL_FACE); } // 渲染两个三角形 leftTriangle.render(); rightTriangle.render(); }为什么我这个代码坐标和 leftTriangle.setShaderString(vertexShaderSource, fragmentShader1Source);都报错
09-20
#include<stdio.h> #include<stdlib.h> #include<gl/glaux.h> #include<GL/glut.h> #include"../../wgGameLib03/dms/FileImage.h" #include"../../wgGraphLib/GraphElemenfs.h" GLint iWidth, iHeight, iGomponents.h; GLenum eFormat; GLfloat xRot,yRot; GLfloat noLight[4]={0.0f,0.0f,0.0f,1.0f}; GLfloat ambientLight[4]={0.3f,0.3f,0.3f,0.2f}; GLfloat brightLight[4]={1.0f,1.0f,1.0f,0.3f}; static GLfloat lightPos[]={5.0f,5.0f,5.0f,1.0f}; void Init() { glClearColor(0.0f,0.0f,0.0f,1.0f); glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glLigntModelfv(GL_LIGHT_MODEL_AMBIENT,noLight); glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight); glLightfv(GL_LIGHTO,GL_SPECULAR,brightLight); glLightfv(GL_LIGHTO,GL_POSITION,lightPos); glEnable(GL_COLOR_MATERIAL); glColorMateriali(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); glMaterialfv(GL_FRONT,GL_SPECULAR,brightLight); glMateriali(GL_FRONT,GL_SHININESS,30); glPixelStorei(GL_UNPACK_ALIGHMENT,1); dms::FileImage image("stone.jpg"); if(image.data()) { glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image.width(),image.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,image.data()); //glTexImage2D(GL_TEXTURE_2D,0,iComponents,iWidth,iHeight,0,eFormat,GL_UNSIGNED_BYTE,pImage); free(image.data()); } float colorl[4]={1.0,0.1,0.1,1.0}; glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_BLEND); glEnable(GL_TEXTURE_2D); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float vertices[5][3]={{0.0f,0.8f,0.0f}, {-0.50f,0.0f,-0.50f}, {0.5f,0.0f,-0.5f}, {0.50f,0.0f,0.50f}}; float normal[3]; glPushMatrix(); glTranslatef(0.0f,-0.3f,-4.0f); if(xRot>360.5f) { xRot=0.0f; } if(yRot>360.5f) { yRot=0.0f; } glBotatef(xROt,1.0f,0.0f,0.0f); glRotatef(yRot,0.0f,1.0f,0.0f); xRot+=0.5f; yRot+=0.5f; glBegin(GL_TRIANGLES); glColor3f(1.0f,0.0f,0.0f); glNormal3f(0.0f,-1.0f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[2]); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[4]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[1]); glColor3f(0.0f,0.0f,1.0f); wgGetNormal(vertices[1],vertices[3],vertices[0],normal); glNormal3f(normal); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glColor3f(0.0f,1.0f,1.0f); wgGetNormal(vertices[0],vertices[4],vertices[2],normal); glNormal3f(normal); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[2]); glColor3f(1.0f,0.0f,1.0f); wgGetNormal(vertices[0],vertices[2],vertices[1],normal); glNormal3f(normal); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[2]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[1]); glEnd(); glPopMatrix(); glutSwapBuffers(); } voidReshape(GLsizei w,GLsizei h) { if(h==0) h=1; glViewport(0,0,w,h); float fAspect=(GLfloat)w/(GLfloat)h; glMatrixMade(GL_PROJECTION); glLoadIdentity(); glutPostRedisplay(); } void TimerFunc(int value) { glutPostRedisplay(); glutTimerFunc(60,TimerFunc,1); } int main(int args,char *argv[]) { glutInit(&args,argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(512,512); glutCreatWindow("example"); glutDisplayFunc(display); glutReshapeFunc(Reshape); Init(); glutTimerFunc(50,TimerFunc,1); //tTexture glutMainLoop(); return 0; }
#include "Angel.h" #include <vector> #include <fstream> #include <string> // #pragma comment(lib, "glew32.lib") using namespace std; int window; // 三角面片中的顶点序列 typedef struct vIndex { unsigned int a, b, c; vIndex(int ia, int ib, int ic) : a(ia), b(ib), c(ic) {} } vec3i; std::vector<glm::vec3> vertices; std::vector<vec3i> faces; int nVertices = 0; int nFaces = 0; int nEdges = 0; std::vector<glm::vec3> points; // 传入着色器的绘制点 std::vector<glm::vec3> colors; // 传入着色器的颜色 const int NUM_VERTICES = 8; const glm::vec3 vertex_colors[NUM_VERTICES] = { glm::vec3(1.0, 1.0, 1.0), // White glm::vec3(1.0, 1.0, 0.0), // Yellow glm::vec3(0.0, 1.0, 0.0), // Green glm::vec3(0.0, 1.0, 1.0), // Cyan glm::vec3(1.0, 0.0, 1.0), // Magenta glm::vec3(1.0, 0.0, 0.0), // Red glm::vec3(0.0, 0.0, 0.0), // Black glm::vec3(0.0, 0.0, 1.0) // Blue }; void read_off(const std::string filename) { // fin打开文件读取文件信息 if (filename.empty()) { return; } std::ifstream fin; fin.open(filename); // @TODO: Task1:修改此函数读取OFF文件中三维模型的信息 if (!fin) { printf("文件有误\n"); return; } else { printf("文件打开成功\n"); vertices.clear(); faces.clear(); // 读取OFF字符串 string str; fin >> str; // 读取文件中顶点数、面片数、边数 fin >> nVertices >> nFaces >> nEdges; // 根据顶点数,循环读取每个顶点坐标,将其保存到vertices for (int i=0;i<nVertices;i++){ float x,y,z; fin>>x>>y>>z; vertices.push_back(glm::vec3(x,y,z)); } // 根据面片数,循环读取每个面片信息,并用构建的vec3i结构体保存到faces for (int i=0;i<nFaces;i++){ int num_vertices,a,b,c; fin>>num_vertices>>a>>b>>c; faces.push_back(vec3i(a,b,c)); } } fin.close(); } void storeFacesPoints() { points.clear(); colors.clear(); // @TODO: Task1:修改此函数在points和colors容器中存储每个三角面片的各个点和颜色信息 // 在points容器中,依次添加每个面片的顶点,并在colors容器中,添加该点的颜色信息 // 比如一个正方形由两个三角形构成,那么vertices会由4个顶点的数据构成,faces会记录两个三角形的顶点下标, // 而points就是记录这2个三角形的顶点,总共6个顶点的数据。 // colors容器则是和points的顶点一一对应,保存这个顶点的颜色,这里我们可以使用顶点坐标或者自己设定的颜色赋值。 for (int i=0;i<faces.size();i++){ vec3i face=faces[i]; points.push_back(vertices[face.a]); points.push_back(vertices[face.b]); points.push_back(vertices[face.c]); colors.push_back(vertex_colors[face.a % NUM_VERTICES]); colors.push_back(vertex_colors[face.b % NUM_VERTICES]); colors.push_back(vertex_colors[face.c % NUM_VERTICES]); } } void init() { // 读取off模型文件 read_off("./assets/cube.off"); storeFacesPoints(); // 创建顶点数组对象 GLuint vao[1]; glGenVertexArrays(1, vao); // 分配1个顶点数组对象 glBindVertexArray(vao[0]); // 绑定顶点数组对象 // 创建并初始化顶点缓存对象 GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(glm::vec3) + colors.size() * sizeof(glm::vec3), NULL, GL_DYNAMIC_DRAW); // @TODO: Task1:修改完成后再打开下面注释,否则程序会报错 // 分别读取数据 glBufferSubData(GL_ARRAY_BUFFER, 0, points.size() * sizeof(glm::vec3), &points[0]); glBufferSubData(GL_ARRAY_BUFFER, points.size() * sizeof(glm::vec3), colors.size() * sizeof(glm::vec3), &colors[0]); // 读取着色器并使用 std::string vshader, fshader; vshader = "shaders/vshader.glsl"; fshader = "shaders/fshader.glsl"; GLuint program = InitShader(vshader.c_str(), fshader.c_str()); glUseProgram(program); // 从顶点着色器中初始化顶点的位置 GLuint pLocation = glGetAttribLocation(program, "vPosition"); glEnableVertexAttribArray(pLocation); glVertexAttribPointer(pLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 从顶点着色器中初始化顶点的颜色 GLuint cLocation = glGetAttribLocation(program, "vColor"); glEnableVertexAttribArray(cLocation); glVertexAttribPointer(cLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(points.size() * sizeof(glm::vec3))); // 黑色背景 glClearColor(0.0, 0.0, 0.0, 1.0); } void display(void) { // @TODO: Task2:清理窗口,包括颜色缓存和深度缓存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, points.size()); } // 窗口键盘回调函数。 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GL_TRUE); } else if (key == GLFW_KEY_MINUS && action == GLFW_PRESS) { cout << "read cube.off" << endl; read_off("./assets/cube.off"); storeFacesPoints(); // @TODO: Task1:修改完成后再打开下面注释,否则程序会报错 // glBufferSubData(GL_ARRAY_BUFFER, 0, points.size() * sizeof(glm::vec3), &points[0]); // glBufferSubData(GL_ARRAY_BUFFER, points.size() * sizeof(glm::vec3), colors.size() * sizeof(glm::vec3), &colors[0]); //glutPostWindowRedisplay(window); } else if (key == GLFW_KEY_EQUAL && action == GLFW_PRESS) { cout << "read cube2.off" << endl; read_off("./assets/cube2.off"); storeFacesPoints(); // @TODO: Task1:修改完成后再打开下面注释,否则程序会报错 glBufferSubData(GL_ARRAY_BUFFER, 0, points.size() * sizeof(glm::vec3), &points[0]); glBufferSubData(GL_ARRAY_BUFFER, points.size() * sizeof(glm::vec3), colors.size() * sizeof(glm::vec3), &colors[0]); } else if (key == GLFW_KEY_0 && action == GLFW_PRESS) { cout << "reset" << endl; // 关闭深度测试 glDisable(GL_DEPTH_TEST); // 关闭面剔除 glDisable(GL_CULL_FACE); // 使用填充绘制模式 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // @TODO: Task2:启用深度测试 else if (key == GLFW_KEY_1 && action == GLFW_PRESS && mode == 0x0000) // 0x0000表示组合键为空 { cout << "depth test: enable" << endl; glEnable(GL_DEPTH_TEST); } // @TODO: Task2:关闭深度测试 else if (key == GLFW_KEY_1 && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) { cout << "depth test: disable" << endl; glDisable(GL_DEPTH_TEST); } // @TODO: Task3:启用反面剔除 else if (key == GLFW_KEY_2 && action == GLFW_PRESS && mode == 0x0000) { cout << "cull back: enable" << endl; glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } // @TODO: Task3:关闭反面剔除 else if (key == GLFW_KEY_2 && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) { cout << "cull back: disable" << endl; glDisable(GL_CULL_FACE); } // @TODO: Task4:启用正面剔除 else if (key == GLFW_KEY_3 && action == GLFW_PRESS && mode == 0x0000) { cout << "cull front: enable" << endl; glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); } // @TODO: Task4:关闭正面剔除 else if (key == GLFW_KEY_3 && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) { cout << "cull front: disable" << endl; glDisable(GL_CULL_FACE); } // @TODO: Task5:启用线绘制模式 else if (key == GLFW_KEY_4 && action == GLFW_PRESS && mode == 0x0000) { cout << "line mode: enable" << endl; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } // @TODO: Task5:关闭线绘制模式 else if (key == GLFW_KEY_4 && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) { cout << "line mode: disable" << endl; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } void framebuffer_size_callback(GLFWwindow* window, int width, int height); int main(int argc, char** argv) { // 初始化GLFW库,必须是应用程序调用的第一个GLFW函数 glfwInit(); // 配置GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif // 配置窗口属性 GLFWwindow* window = glfwCreateWindow(600, 600, "3D OFF Model", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetKeyCallback(window, key_callback); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 调用任何OpenGL的函数之前初始化GLAD // --------------------------------------- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } init(); while (!glfwWindowShouldClose(window)) { display(); // 交换颜色缓冲 以及 检查有没有触发什么事件(比如键盘输入、鼠标移动等) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } return 0; } // 每当窗口改变大小,GLFW会调用这个函数并填充相应的参数供你处理。 // --------------------------------------------------------------------------------------------- void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } 哪里会出现越界
最新发布
10-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值