OpenGL 金字塔

前言

在上一篇OpenGL 深度测试基础上修改main.cpp文件,完成此demo

代码

代码已做详细注释,如下:


#include "GLMatrixStack.h"
#include "GLFrame.h"
#include "GLFrustum.h"
#include "GLBatch.h"
#include "GLGeometryTransform.h"
#include <math.h>
#include <GLUT/GLUT.h>
#include "GLTools.h"
#include "StopWatch.h"
#include <stdio.h>

GLShaderManager  shaderManager;
GLMatrixStack         modelViewMatrix;
GLMatrixStack         projectionMatrix;
//视景体
GLFrustum                      viewFrustum;
GLFrame                         cameraFrame;
GLFrame                         objectFrame;

GLBatch   pyramidBatch;
//纹理变量ID
GLuint   textureID;

//绘制金字塔
void makePyramid(GLBatch &pyramidBatch) {
    //arg2:顶点个数 arg3:这个批次类中会使用的纹理个数,默认为0
    pyramidBatch.Begin(GL_TRIANGLES, 18,1);
    
    //塔顶
    M3DVector3f vApex = { 0.0f, 1.0f, 0.0f };
    M3DVector3f vFrontLeft = { -1.0f, -1.0f, 1.0f };
    M3DVector3f vFrontRight = { 1.0f, -1.0f, 1.0f };
    M3DVector3f vBackLeft = { -1.0f,  -1.0f, -1.0f };
    M3DVector3f vBackRight = { 1.0f,  -1.0f, -1.0f };
    M3DVector3f n;
    
    //设置三角形
    //从三个点获取一个法线 arg1:结果 arg2-4:顶点数据
    m3dFindNormal(n, vBackLeft, vBackRight, vFrontRight);
    //设置法线
    pyramidBatch.Normal3fv(n);
    //设置纹理坐标 arg1:纹理层次 对于使用存储着色器来进行渲染,设置为0 arg2: 对应x坐标 arg3:对应y坐标 (s,t,r,q对应顶点坐标的x,y,z,w)
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    //向三角形批次类中添加顶点数据
    pyramidBatch.Vertex3fv(vBackLeft);
    
    //vBackRight
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackRight);
    
    //vFrontRight
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    pyramidBatch.Vertex3fv(vFrontRight);
    
    
    //三角形Y =(vFrontLeft,vBackLeft,vFrontRight)
    
    //1.找到三角形X 法线
    m3dFindNormal(n, vFrontLeft, vBackLeft, vFrontRight);
    
    //vFrontLeft
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
    pyramidBatch.Vertex3fv(vFrontLeft);
    
    //vBackLeft
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackLeft);
    
    //vFrontRight
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    pyramidBatch.Vertex3fv(vFrontRight);
    
    
    // 金字塔前面
    //三角形:(Apex,vFrontLeft,vFrontRight)
    m3dFindNormal(n, vApex, vFrontLeft, vFrontRight);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontLeft);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontRight);
    
    //金字塔左边
    //三角形:(vApex, vBackLeft, vFrontLeft)
    m3dFindNormal(n, vApex, vBackLeft, vFrontLeft);
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackLeft);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontLeft);
    
    //金字塔右边
    //三角形:(vApex, vFrontRight, vBackRight)
    m3dFindNormal(n, vApex, vFrontRight, vBackRight);
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontRight);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackRight);
    
    //金字塔后边
    //三角形:(vApex, vBackRight, vBackLeft)
    m3dFindNormal(n, vApex, vBackRight, vBackLeft);
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackRight);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackLeft);
    
    //结束批次设置
    pyramidBatch.End();
}

//将TGA文件加载为2D纹理
bool loadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFileter, GLenum wrapMode) {
    
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    //读取纹理 pBits:指向图像数据的指针 arg2:纹理文件宽度地址 arg4:文件组件地址 arg5:文件格式地址
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    
    if (pBits == NULL) {
        return false;
    }
    
    //设置过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFileter);
    
    //设置环绕模式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    
    //载入纹理 arg2:mip贴图层次 arg7:像素数据类型(GL_UNSIGNED_BYTE 每个颜色分量都是一个8位无符号整型)
    glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
    
    //释放ppBits
    free(pBits);
    
    //加载Mip
    glGenerateMipmap(GL_TEXTURE_2D);
    
    return true;
}

void setupRC() {
    glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
    shaderManager.InitializeStockShaders();
    cameraFrame.MoveForward(-15.0f);
    glEnable(GL_DEPTH_TEST);
    
    //arg1:纹理对象个数 arg2:纹理对象指针
    glGenTextures(1, &textureID);
    //绑定纹理状态 arg1:纹理状态2D arg2:纹理对象
    glBindTexture(GL_TEXTURE_2D, textureID);
    
    loadTGATexture("stone.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
    makePyramid(pyramidBatch);
}

void changeSize(int w, int h) {
    glViewport(0, 0, w, h);
    //设置透视投影
    viewFrustum.SetPerspective(30.0f, float(w) / float(h), 2.0f, 400.0f);
    
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
}

void renderScene() {
    
    static GLfloat vLightPos[] = {1.0f,1.0f,0.0f};
    static GLfloat vWhite[] = {1.0f,1.0f,1.0f,1.0f};
    //清理缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    modelViewMatrix.PushMatrix();
    
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.MultMatrix(mCamera);
    
    M3DMatrix44f mObjectFrame;
    objectFrame.GetMatrix(mObjectFrame);
    modelViewMatrix.MultMatrix(mObjectFrame);
    
    glBindTexture(GL_TEXTURE_2D, textureID);
    
    //arg5:漫反射颜色 arg6:图形颜色(使用纹理时此参数为0,表示不需要设置颜色)
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,modelViewMatrix.GetMatrix(),projectionMatrix.GetMatrix(),vLightPos,
                                 vWhite,0);

    pyramidBatch.Draw();
    
    modelViewMatrix.PopMatrix();
    
    glutSwapBuffers();
    
}

void specialKeys(int key,int x,int y){
    
    float angular = float(m3dDegToRad(6.0f));
    
    if (key == GLUT_KEY_UP) {
        objectFrame.RotateWorld(-angular, 1.0f, 0.0f, 0.0f);
    }
    if (key == GLUT_KEY_DOWN) {
        objectFrame.RotateWorld(angular, 1.0f, 0.0f, 0.0f);
    }
    if (key == GLUT_KEY_LEFT) {
        objectFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
    }
    if (key == GLUT_KEY_RIGHT) {
        objectFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    }
    
    glutPostRedisplay();
}

//删除纹理对象
void shutdownRC(void) {
    glDeleteTextures(1, &textureID);
}


int main(int argc, char* argv[]) {
    
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(600, 600);
    glutCreateWindow("dowZhang");
    glutReshapeFunc(changeSize);
    glutDisplayFunc(renderScene);
    glutSpecialFunc(specialKeys);
    
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        return 1;
    }
    
    setupRC();
    
    glutMainLoop();
    shutdownRC();
    return 0;
}

复制代码

效果图:

转载于:https://juejin.im/post/5cea0c7a6fb9a07f091b7f27

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值