前言
在上一篇OpenGL 深度测试基础上修改main.cpp
文件,完成此demo
。
代码
代码已做详细注释,如下:
#include "GLMatrixStack.h"
#include "GLFrame.h"
#include "GLFrustum.h"
#include "GLBatch.h"
#include "GLGeometryTransform.h"
#include
#include
#include "GLTools.h"
#include "StopWatch.h"
#include
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;
}
复制代码
效果图: