009-OpenGL绘制隧道

2020-07-21  本文已影响0人  沉默Coder

这个案例主要是用多个纹理去绘制一个隧道
效果如下图:

隧道

相关的函数介绍:

setUpRC

设置背景颜色,以及初始化着色器管理类

    //设置背景颜色为黑色
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    //初始化着色器管理类
    shaderManager.InitializeStockShaders();

生成纹理标记并设置纹理参数(过滤方式,环绕方式)

GLbyte * pBytes;
    GLint iWidth,iHeight,iComponets;
    GLenum eFormet;
    GLint iLoop;
    
    //3.生成纹理标记,执行结束后 textures 会填充为纹理id
    /** 分配纹理对象 glGenTextures
     参数1:纹理对象的数量
     参数2:纹理对象标识数组
     */
    glGenTextures(TEXTURE_COUNT, textures);
    
    //循环设置纹理参数,因为有三个纹理,所以这里采用循环去设置
    for(iLoop = 0;iLoop < TEXTURE_COUNT;iLoop++)
    {
        //绑定纹理对象
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
        //加载tga文件,加载完成后 iWidth,iHeight,iComponets 等参数都会被填充为本tga文件的属性
        pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeight, &iComponets, &eFormet);
        
        //设置纹理放大缩小时的过滤方式为邻近过滤
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        //设置纹理在s轴的环绕方式为 GL_CLAMP_TO_EDGE
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        
        //设置纹理在T轴的环绕方式为 GL_CLAMP_TO_EDGE
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        
        /**载入纹理 glTexImage2D
        参数1:纹理维度,GL_TEXTURE_2D
        参数2:mip贴图层次
        参数3:纹理单元存储的颜色成分(从读取像素图中获得)
        参数4:加载纹理宽度
        参数5:加载纹理的高度
        参数6:加载纹理的深度
        参数7:像素数据的数据类型,GL_UNSIGNED_BYTE无符号整型
        参数8:指向纹理图像数据的指针
        */
        glTexImage2D(GL_TEXTURE_2D, 0, iComponets, iWidth, iHeight, 0, eFormet, GL_UNSIGNED_BYTE, pBytes);
        
        /**为纹理对象生成一组完整的mipmap glGenerateMipmap
             参数1:纹理维度,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
         */
        glGenerateMipmap(GL_TEXTURE_2D);
        
        //释放原始纹理数据,不在需要纹理原始数据了
        free(pBytes);
    }

设置纹理的映射关系,这里有三个纹理,四个面

//纹理当前的z坐标
    GLfloat z;
    
    /*
    GLTools库中的容器类,GBatch,
    void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
    参数1:图元枚举值
    参数2:顶点数
    参数3:1组或者2组纹理坐标
    */
    floorBatch.Begin(GL_TRIANGLE_STRIP, 28,1);
    for(z = 60;z >= 0.0f;z -= 10.0f)
    {
        floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        floorBatch.Vertex3f(-10.0f, -10.0f, z);
        
        floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        floorBatch.Vertex3f(10.0f, -10.0f, z);
        
        floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        floorBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
        
        floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        floorBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
    }
    floorBatch.End();
    
    ceilingBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for(z = 60.0f; z >= 0.0f; z -=10.0f)
    {
        ceilingBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
        
        ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
        
        ceilingBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        ceilingBatch.Vertex3f(-10.0f, 10.0f, z);
        
        ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        ceilingBatch.Vertex3f(10.0f, 10.0f, z);
    }
    ceilingBatch.End();
    
    leftWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for(z = 60.0f; z >= 0.0f; z -=10.0f)
    {
        leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        leftWallBatch.Vertex3f(-10.0f, -10.0f, z);
        
        leftWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        leftWallBatch.Vertex3f(-10.0f, 10.0f, z);
        
        leftWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        leftWallBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
        
        leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        leftWallBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
    }
    leftWallBatch.End();
    
    rightWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for(z = 60.0f; z >= 0.0f; z -=10.0f)
    {
        rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        rightWallBatch.Vertex3f(10.0f, -10.0f, z);
        
        rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        rightWallBatch.Vertex3f(10.0f, 10.0f, z);
        
        rightWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        rightWallBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
        
        rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        rightWallBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
    }
    rightWallBatch.End();

changeSize

void changeSize(int width,int height)
{
    if(height == 0)
        height = 1;
    
    //重新设置视口大小
    glViewport(0, 0, width, height);
    
    GLfloat factor = (GLfloat)width/(GLfloat)height;
    
    viewFrustum.SetPerspective(80.0f, factor, 1.0, 120.0);
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);
}

SpecialKeys

void SpecialKeys(int key,int x,int y)
{
    if(key == GLUT_KEY_UP)
    {
        viewZ += 0.5f;
    }
    
    if(key == GLUT_KEY_DOWN)
    {
        viewZ -= 0.5f;
    }
    
    //重新绘制
    glutPostRedisplay();
}

shutDownRC

void shutDownRC()
{
    //删除纹理,本次绘制结束后,需要删除纹理,否则会影响其他绘制
    glDeleteTextures(TEXTURE_COUNT, textures);
}

RenderScene

void RenderScene()
{
    //清除颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT);
    
    //模型视图矩阵压栈
    modelViewMatrix.PushMatrix();
    //z轴平移viewZ距离
    modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
    
    //纹理替换矩阵着色器
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
    floorBatch.Draw();
    
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
    ceilingBatch.Draw();
    
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
    leftWallBatch.Draw();
    rightWallBatch.Draw();
    
    modelViewMatrix.PopMatrix();
    glutSwapBuffers();
}

完整代码在这里:OpenGL Tunel

上一篇 下一篇

猜你喜欢

热点阅读