美文网首页OpenGL
OpenGL纹理案例解析

OpenGL纹理案例解析

作者: 爱看书de图图 | 来源:发表于2020-07-21 11:50 被阅读0次

这个案例是在之前的案例球体旋转Demo的基础上,加以改动做的,主要是给了球体添加纹理,以及做了一个镜面的效果,具体效果如下:

效果图

镜面效果其实很简单,就是对镜面上的球体做了翻转重新绘制,然后平移一段距离,看起来是像是镜面反射一样。首先我们需要知道纹理加载的流程。

1、生成纹理对象glGenTextures
2、绑定纹理glBindTexture
3、读取纹理数据gltReadTGABits
4、设置纹理参数glTexParameteri
5、载入纹理glTexImage2D
6、释放,喊出纹理

  增加函数LoadTGATexture,其中将设置纹理参数,载入纹理,释放都封装了起来。

/// 载入纹理函数
/// @param szFileName 纹理名称
/// @param minFilter 环绕方式
/// @param magFilter 环绕方式
/// @param wrapMode 环绕方式
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{

    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    
    //1.读取纹理数据
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    if(pBits == NULL)
        return false;
    
    //2、设置纹理参数
    //参数1:纹理维度
    //参数2:为S/T坐标设置模式
    //参数3:wrapMode,环绕模式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    
    //参数1:纹理维度
    //参数2:线性过滤
    //参数3:wrapMode,环绕模式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
    
    //3.载入纹理
    //参数1:纹理维度
    //参数2:mip贴图层次
    //参数3:纹理单元存储的颜色成分(从读取像素图是获得)-将内部参数nComponents改为了通用压缩纹理格式GL_COMPRESSED_RGB
    //参数4:加载纹理宽
    //参数5:加载纹理高
    //参数6:加载纹理的深度
    //参数7:像素数据的数据类型(GL_UNSIGNED_BYTE,每个颜色分量都是一个8位无符号整数)
    //参数8:指向纹理图像数据的指针
    glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
                 eFormat, GL_UNSIGNED_BYTE, pBits);
    
    //使用完毕释放pBits
    free(pBits);
    
    //只有minFilter 等于以下四种模式,才可以生成Mip贴图
    //GL_NEAREST_MIPMAP_NEAREST具有非常好的性能,并且闪烁现象非常弱
    //GL_LINEAR_MIPMAP_NEAREST常常用于对游戏进行加速,它使用了高质量的线性过滤器
    //GL_LINEAR_MIPMAP_LINEAR 和GL_NEAREST_MIPMAP_LINEAR 过滤器在Mip层之间执行了一些额外的插值,
    //以消除他们之间的过滤痕迹。
    //GL_LINEAR_MIPMAP_LINEAR 三线性Mip贴图。纹理过滤的黄金准则,具有最高的精度。
    if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
       minFilter == GL_LINEAR_MIPMAP_NEAREST ||
       minFilter == GL_NEAREST_MIPMAP_LINEAR ||
       minFilter == GL_NEAREST_MIPMAP_NEAREST)
    //4.加载Mip,纹理生成所有的Mip层
    //参数:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
    glGenerateMipmap(GL_TEXTURE_2D);
    
    
    return true;
}

  SetupRC函数增加了生成纹理对象,绑定纹理,然后调用LoadTGATexture函数。

    //8.命名纹理对象
    glGenTextures(3, uiTextures);
    
    //9.将TGA文件加载为2D纹理。
    //参数1:纹理文件名称
    //参数2&参数3:需要缩小&放大的过滤器
    //参数4:纹理坐标环绕模式
    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);

  因为要绘制球体以及球体的镜像,所以我们把绘制球体的代码封装起来,然后再RenderScene函数里,调用两次,一次正常调用,一次围绕y轴旋转后再调用一次。

//7.---添加反光效果---
    //翻转Y轴
    modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);
    //镜面世界围绕Y轴平移一定间距
    modelViewMatrix.Translate(0.0f, 0.8f, 0.0f);
    
    //8.指定顺时针为正面
    glFrontFace(GL_CW);
  
    //9.绘制地面以外其他部分(镜面)
    drawSomething(yRot);
   
    //10.恢复为逆时针为正面
    glFrontFace(GL_CCW);
    
    //11.绘制镜面,恢复矩阵
    modelViewMatrix.PopMatrix();
    
    //12.开启混合功能(绘制地板)
    glEnable(GL_BLEND);
    //13. 指定glBlendFunc 颜色混合方程式
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    //14.绑定地面纹理
    glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
    
    /*15.
     纹理调整着色器(将一个基本色乘以一个取自纹理的单元nTextureUnit的纹理)
     参数1:GLT_SHADER_TEXTURE_MODULATE
     参数2:模型视图投影矩阵
     参数3:颜色
     参数4:纹理单元(第0层的纹理单元)
     
     */
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vFloorColor,
                                 0);
    //开始绘制
    floorBatch.Draw();
    //取消混合
    glDisable(GL_BLEND);
    //16.绘制地面以外其他部分
    drawSomething(yRot);
    //17.绘制完,恢复矩阵
    modelViewMatrix.PopMatrix();

  地板数据由原来的线条相交,更改为仅设置4个顶点坐标&纹理坐标。

    //6.设置地板顶点数据&地板纹理
    GLfloat texSize = 10.0f;
    floorBatch.Begin(GL_TRIANGLE_FAN, 4,1);
    floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    floorBatch.Vertex3f(-20.f, -0.41f, 20.0f);
    
    floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
    floorBatch.Vertex3f(20.0f, -0.41f, 20.f);
    
    floorBatch.MultiTexCoord2f(0, texSize, texSize);
    floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
    
    floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
    floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
    floorBatch.End();

完整Demo

相关文章

  • OpenGL纹理案例解析

    这个案例是在之前的案例球体旋转Demo的基础上,加以改动做的,主要是给了球体添加纹理,以及做了一个镜面的效果,具体...

  • 案例08:隧道

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

  • 案例07:纹理金字塔

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

  • OpenGL纹理坐标&&隧道案例(二)

    一.隧道案例效果 二.纹理坐标 纹理坐标主要是把图形映射到OpenGL中去,图形中每个顶点关联到对应的纹理坐标下,...

  • OpenGL 纹理隧道案例

    隧道示例程序使用了和纹理有关的内容,并在视觉上显示了不同的过滤器和贴图模式。 该示例程序在启动时加载3个纹理用于对...

  • OpenGL 纹理案例探索

    1

  • OpenGL 纹理案例-隧道

    在学习了纹理之后,我们尝试着用纹理来实现一个类似于下图这样的隧道效果,并且让他可以通过键盘的上下键可以来进行前进和...

  • OpenGL纹理案例-隧道

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

  • OpenGL纹理综合案例

    之前用OpenGL做了一个关于大球公转,小球自转的案例,现在我们通过纹理去绘制大球小球和地板,呈现出一个有倒影的画...

  • OpenGL纹理案例-隧道

    OpenGL纹理案例-隧道 之前我写过一些关于纹理的一些基本API和API的方法参数的解释,现在我们来弄一个隧道案...

网友评论

    本文标题:OpenGL纹理案例解析

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