美文网首页
OpenGL纹理案例-球体世界

OpenGL纹理案例-球体世界

作者: 过气的程序员DZ | 来源:发表于2020-07-22 14:34 被阅读0次

开场白

本文在我之前的文章OpenGL-公转自转demo中的demo为基础,添加纹理。效果图:

简述逻辑

SetupRC

在初始设置函数SetupRC中,增加设置纹理的代码。示例中有三个纹理,分别是地板,大球,小球。

void SetupRC() {
    //......
    //大球小球初始化相关代码
    //......
    
    //申请3个纹理对象
    glGenTextures(3, uiTextures);
    
    //设置纹理状态模式:2D
    glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
    //调用自定义方法
    LoadTGATexture("Marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
    
    glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
    LoadTGATexture("Marslike.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
    
    glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    LoadTGATexture("MoonLike.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
}

三个纹理的设置相似,所以将设置纹理的相关函数进行自定义函数封装,
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFileter, GLenum wrapMode)

  • 参数1:文件名
  • 参数2:缩小过滤方式
  • 参数3:放大过滤方式
  • 参数4:环绕方式
 */
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFileter, GLenum wrapMode){
    //定义局部变量
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    
    //加载TGA文件,获取TGA文件的宽、高、组件、格式,并返回一个纹理图像数据的指针
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    if (pBits == NULL) {
        return false;
    }
    
    //设置纹理的S、T的环绕方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    
    //设置纹理放大、缩小的过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFileter);
    
    /**
     载入纹理:
     参数1:纹理2D模式
     参数2:mip贴图层次,通常设置为0
     参数3:纹理单元存储成分,使用压缩RGB格式
     参数4、5:纹理宽、高
     参数6:纹理深度
     参数7:像素格式
     参数8:像素数据的数据类型(GL_UNSIGNED_BYTE,每个颜色分量都是一个8位无符号整数)
     参数9:指向纹理图像数据的指针
     */
    glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
    free(pBits);
    
    /*
     只有minFilter等于这四种模式的时候,纹理生成所有mip层。
     因为GL_LINEAR和GL_NEAREST模式下只有基层纹理会加载,所以生成所有mip层也没用
     */
    if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
        minFilter == GL_LINEAR_MIPMAP_NEAREST ||
        minFilter == GL_NEAREST_MIPMAP_LINEAR ||
        minFilter == GL_NEAREST_MIPMAP_NEAREST) {
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    
    return true;
}
RenderScene

将绘制的代码封装成了函数中,因为有倒影的原因,整个球体世界需要绘制两遍,中间用地面相隔开。倒影的世界运动轨迹是完全相反的,并且地面和倒影要有一个混合的效果。

void RenderScene(void) {
    static GLfloat vFloorColor[] = {1.0, 1.0, 0.0, 0.75};
    
    static CStopWatch rotTimer;
    float yRot = rotTimer.GetElapsedSeconds() * 60;
    
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
    modelViewMatrix.PushMatrix();
    
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.MultMatrix(mCamera);
    
    modelViewMatrix.PushMatrix(mCamera);
    //倒影
    modelViewMatrix.Scale(1, -1, 1);
    modelViewMatrix.Translate(0, 0.8, 0);
    glFrontFace(GL_CW);
    drawSomething(yRot);
    glFrontFace(GL_CCW);
    modelViewMatrix.PopMatrix();
    
    //地面-与倒影进行了混合
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor, 0);
    floorBatch.Draw();
    glDisable(GL_BLEND);
    
    //地面上面的部分
    drawSomething(yRot);
    
    modelViewMatrix.PopMatrix();
    
    //将在后台缓冲区进行渲染,然后在结束时交换到前台
    glutSwapBuffers();
    //9触发重新绘制
    glutPostRedisplay();
}
  1. 地板颜色vFloorColor要有一定的透明度,为了与倒影进行混合
  2. 倒影设置就是进行翻转y轴modelViewMatrix.Scale(1, -1, 1);
  3. 因为倒影的运动方向是反的,所以需要设置顶点绕序glFrontFace(GL_CW);
  4. 调用自定义封装函数drawSomething(yRot);
  5. 顶掉绕序修改回来glFrontFace(GL_CCW);,因为一会还有绘制地面上放的球体。
  6. 绘制地面
  7. 绘制地面上面的球体,调用自定义封装函数drawSomething(yRot);

==drawSomething()函数就是球体的绘制过程,可以下载demo看看==

demo地址

相关文章

  • OpenGL纹理案例-球体世界

    开场白 本文在我之前的文章OpenGL-公转自转demo中的demo为基础,添加纹理。效果图: 简述逻辑 Setu...

  • OpenGL 案例:球体世界

    球体世界案例是基于 OpenGL 综合案例的学习 的基础上增加了纹理和镜像显示。最终效果图: 总体流程图可以使用下...

  • OpenGL学习之路(7.1) 球体世界添加纹理案例

    效果 这次要实现的效果,通过加载纹理给球体贴上一层纹理图最终效果图 那么如何做呢?看步骤 步骤 第一步导入一些头文...

  • OpenGL纹理下的球体世界

    一.先看看整体效果 二.绘制流程 在OpenGl综合案例(地板,大小球,公转,自转,移动)文章中,我们绘制了大小球...

  • OpenGL球体纹理填充

    上篇文章我们介绍过 纹理的使用,以及常用函数。今天我们来使用纹理填充球体,以及镜面效果的绘制。 首先我们来看一下绘...

  • OpenGL案例08:球体世界

    本案例是基于案例06:大球自转+小球公转+移动[https://www.jianshu.com/p/4896498...

  • OpenGL绘制球体世界

    本文主要记录使用所学OpenGL相关知识绘制OpenGL中的一个经典案例--球体世界,最终实现效果如下: 准备工作...

  • 案例08:隧道

    OpenGL + OpenGL ES +Metal 系列文章汇总 本案例主要目的多个纹理如何使用,加深对纹理的使用...

  • 案例07:纹理金字塔

    OpenGL + OpenGL ES +Metal 系列文章汇总 本次案例的目的在于理解纹理的使用 案例整体效果图...

  • OpenGL ----- 球体世界

网友评论

      本文标题:OpenGL纹理案例-球体世界

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