美文网首页
009-OpenGL绘制隧道

009-OpenGL绘制隧道

作者: 沉默Coder | 来源:发表于2020-07-21 14:21 被阅读0次

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

隧道

相关的函数介绍:

  • setUpRC:初始化渲染环境,生成纹理对象,设置顶点及纹理坐标
  • changeSize:当视口的大小改变时,此函数会被回调,只要用来重设视口大小,以及设置投影方式
  • SpecialKeys:当键盘被点击后,会回调此方法
  • shutDownRC:删除纹理,绘制结束后没需要将纹理删除,否则纹理数据会存在缓冲区,对其他绘制造成干扰
  • RenderScene:绘制方法,使用对应的着色器绘制纹理

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

相关文章

  • 009-OpenGL绘制隧道

    这个案例主要是用多个纹理去绘制一个隧道效果如下图: 相关的函数介绍: setUpRC:初始化渲染环境,生成纹理对象...

  • OpenGL(七)-纹理(下)

    绘制一个隧道 定义绘制批次类 初始化 窗口设置 调用,绘制场景 效果图

  • OpenGL 案例:隧道

    隧道整体的案例最终效果如下图所示 隧道的绘制过程,整体的流程如下图 主要涉及的函数 main函数、ChangeSi...

  • 案例4——纹理绘制隧道

    整体的效果图如下: 基本流程基本不变,主要介绍下案列的特点 其中main、ChangeSize、ShutdownR...

  • OpenGL案例03

    案例要求:使用指定的纹理绘制一个隧道。效果如下: 该案例绘制主要分为四部分: 地板 左边墙 右边墙 天花板 从效果...

  • OpenGL纹理案例-隧道

    使用OpenGL常用的API,绘制一个简单的隧道模型并贴图。最终下过如下: 完成代码: #include "GLT...

  • OpenGL:纹理隧道

    本案例主要目的多个纹理如何使用,加深对纹理的使用的理解。 整体的案例效果如图所示 下面接着说说隧道的绘制过程,整体...

  • OpenGL案例07:隧道

    本案例主要目的多个纹理如何使用,加深对纹理的使用的理解。 整体的案例效果如图所示 下面接着说说隧道的绘制过程,整体...

  • 案例:隧道

    本案例主要目的多个纹理如何使用,加深对纹理的使用的理解。 整体的案例效果如图所示 隧道的绘制过程,整体的流程图如下...

  • 福州到龙岩隧道知多少 ?

    1菇莲山隧道 2门前山隧道 3方广岩隧道 *A青云山服务区 4天马岭隧道 5岩前隧道 6洋中隧道 7青云山隧道 8...

网友评论

      本文标题:009-OpenGL绘制隧道

      本文链接:https://www.haomeiwen.com/subject/euyikktx.html