OpenGL-8️⃣-隐藏面消除的解决方案代码

//演示了OpenGL背面剔除,深度测试,和多边形模式
#include "GLTools.h"    
#include "GLMatrixStack.h"
#include "GLFrame.h"
#include "GLFrustum.h"
#include "GLGeometryTransform.h"

#include <math.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

////设置角色帧,作为相机
//设置观察者位置
GLFrame             viewFrame;
//使用GLFrustum类来设置透视投影
//设置图元绘制时的投影方式.

GLFrustum           viewFrustum;
//三角形批次类
/*
 批次类是帮我们管理和渲染图形,并且把数据传到固定管线里面的。
 帮助类/容器类
 */
GLTriangleBatch     torusBatch;
//模型视图矩阵
GLMatrixStack       modelViewMatix;
//投影矩阵
GLMatrixStack       projectionMatrix;
/*
 变换管道.存储模型视图/投影/模型视图投影矩阵.
 
 */
GLGeometryTransform transformPipeline;
GLShaderManager     shaderManager;

//标记:背面剔除、深度测试
int iCull = 0;
int iDepth = 0;

//渲染场景
//屏幕发生改变 都会掉RenderScene
void RenderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    //根据设置iCull标记来判断是否开启背⾯面剔除
    if (iCull) {
        //开启
        glEnable(GL_CULL_FACE);
        //开启背后测试
        glFrontFace(GL_CCW);
    }else{
        glDisable(GL_CULL_FACE);
    }
    
    //1. viewFrumpush 到 模型视图里面
    modelViewMatix.PushMatrix(viewFrame);
    //2 设置画笔颜色
    GLfloat vRed[] = {1.0f,0.0,0.0,1};
    //3. 使用着色器了
    
    
    /**
     
     让我们在OpenGL使用矩阵
     
     绘制默认OpenGL坐标系(-1,1)下图形,图形所有片段都会以一种颜色填充。

     @param GLT_SHADER_FLAT 平面着色器
     @param  transformPipeline 里面会计算 模型矩阵和视图矩阵 相乘的结果 是一个管理类
     @return MVP
     */
//    shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vRed);
    
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vRed);
    
    torusBatch.Draw();
    //pop
    modelViewMatix.PopMatrix();
    //提交渲染
    glutSwapBuffers();
    
}
//负责图形相关的初始化
void SetupRC()
{
    //设置背景颜色
    glClearColor(0.3f, 0.3f, 0.3f, 1);
    shaderManager.InitializeStockShaders();
    //移动深度 移动Z值  往里移动负的, 往外移动正的,
    viewFrame.MoveForward(7.0f);
    
    //图片相关顶点
    //顶点一般开发者不管,有设计师给你,甜甜圈模型有专门的API
    //
    
    /**
     初始化花托的顶点批次
     甜甜圈的API

     @param torusBatch 批次类
     @param majorRadius#> 内半径 description#>
     @param minorRadius#> 外半径 description#>
     @param numMajor#> 三角形个数 description#>
     @param numMinor#> 细密成都 description#>
     @return
     */
    gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);
    
    
    //3 点 线 面的方式 d填充
    //4 线的宽度
    glPointSize(4.0f);
    
}

//键位设置,通过不同的键位对其进行设置
//控制Camera的移动,从而改变视口
void SpecialKeys(int key, int x, int y)
{
    if (key == GLUT_KEY_UP) {
        viewFrame.RotateWorld(m3dDegToRad(-5.0f), 1, 0, 0);
    }
    if (key == GLUT_KEY_DOWN) {
        viewFrame.RotateWorld(m3dDegToRad(5.0f), 1, 0, 0);
    }
    if (key == GLUT_KEY_LEFT) {
        viewFrame.RotateWorld(m3dDegToRad(-5.0f), 0, 1, 0);
    }
    if (key == GLUT_KEY_RIGHT) {
        viewFrame.RotateWorld(m3dDegToRad(5.0f), 0, 1, 0);
    }
    //重新渲染  GLTools 里面的函数
    glutPostRedisplay();
}

//窗口改变
void ChangeSize(int w, int h)
{
    //1.设置投影方式
    glViewport(0, 0, w, h);
    //2.设置投影方式 角度、纵横比 near flear   通过设置它来拿到投影矩阵
    //拿到投影矩阵 viewFrustum.GetProjectionMatrix()
    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
    //3 加载到矩阵堆栈里面   矩阵堆栈只放一个元素的时候  跟数组里面放一个元素一样
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    //4. 初始化模型矩阵  加载一个单元矩阵
    /*
        1,0,0
        0,1,0
        0,0,1
     */
    modelViewMatix.LoadIdentity();
    
    //5. 把 模型矩阵 和 视图矩阵 放进去 方便管理,可以拿到模型矩阵和视图矩阵
    transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);
    
}

void ProcessMenu(int value){
    switch (value) {
        case 1:
            //深度测试
            iDepth = !iDepth;
            break;
            
        case 2:
            //正背面剔除
            iCull = !iCull;
            break;
        case 3:
            //颜色填充
            //填充方式
            //GL_FRONT_AND_BACK 正背面完全填充(GL_FILL)
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            break;
        case 4:
            //线段填充"
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            break;
        case 5:
            //点填充
            glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
            break;
            
        default:
            break;
    }
    //发生改变 就需要重新渲染
    glutPostRedisplay();
}


int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
    
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Geometry Test Program");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
    
    //注册 右键按钮回调
    glutCreateMenu(ProcessMenu);
    
    //添加几个按钮  相当于微信上面 + 下来的添加朋友等几个按钮 只不过这个是在pc端
    glutAddMenuEntry("深度测试", 1);
    glutAddMenuEntry("正背面剔除", 2);
    glutAddMenuEntry("颜色填充", 3);
    glutAddMenuEntry("线段填充", 4);
    glutAddMenuEntry("点填充", 5);
    
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    
    
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    
    SetupRC();
    
    glutMainLoop();
    return 0;
}

在RenderScene里面if (iCull) 根据判断来开启或者关闭正背面剔除,效果


5530658-912810b76782dc74.png
1.png
5530658-abfeb6139c1c4e9b.png
2.png

带来了新的问题,就是少一个缺口。
代码讲解

main函数里面的
glutAddMenuEntry("深度测试", 1);

效果图


5530658-0ef3e0f07d816619.png
menu.png
ProcessMenu函数里面的case 
3、4、5的效果,下面的效果图 命名是3.png、4.png、5.png;
5530658-ef5755d3bea2aa9a.png
3.png
5530658-aa99b22938dfa9c4.png
4.png
5530658-a552e356f05b0bba.png
5.png

猜你喜欢

转载自blog.csdn.net/weixin_34393428/article/details/90852397