OpenGL 金字塔

前言

在上一篇OpenGL 深度測試基礎上修改main.cpp文件,完成此demobash

代碼

代碼已作詳細註釋,以下:oop

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

複製代碼

效果圖:post

相關文章
相關標籤/搜索