美文网首页
OpenGL纹理综合案例

OpenGL纹理综合案例

作者: 大橘猪猪侠 | 来源:发表于2020-07-21 15:59 被阅读0次

之前用OpenGL做了一个关于大球公转,小球自转的案例,现在我们通过纹理去绘制大球小球和地板,呈现出一个有倒影的画面。
运行效果图如下:


QQ20200721-155909-HD.gif

之前没有用纹理做出来的效果可以转到另一篇博客当中。

在这篇中,我就直接写关键代码和有差别的地方,首先定义的批次类容器都是不变的。
地板的坐标之前利用的是网格呈现出来的,在这个案例中,并不需要利用网格呈现。因此直接利用四个顶点坐标去绘制纹理图片:

SetupRC函数中

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();
    
     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 magFilter, GLenum wrapMode){
    
    GLbyte *pBits;
    int nWidth,nHeight,nComponets;
    GLenum eFormat;
    
    //1.读取纹理数据
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponets, &eFormat);
    if(pBits == NULL)
        return false;
    
    //2、设置纹理参数
        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, magFilter);
    
    //3.载入纹理
   
    glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
                 eFormat, GL_UNSIGNED_BYTE, pBits);
    
    //使用完毕释放pBits
    free(pBits);
    
       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;
}

在RenderScene函数中,需要渲染场景,由于大球小球需要转动,因此还是需要计时器而要做出有倒影的效果,又该如何实现呢?
首先可以将大球小球的画面封装成一个函数,下面这个函数利用点光源纹理着色器去绘制大球和小球。

void drawSomething(GLfloat yRot){
    static GLfloat vWhite[] = {1.0f,1.0f,1.0f,1.0f};
    static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
    
    glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    for (int i = 0; i<NUM_SPHERES; i++) {
        modelViewMatrix.PushMatrix();
        modelViewMatrix.MultMatrix(spheres[i]);
        shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,modelViewMatrix.GetMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vWhite,0);
        
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    }
    
    
    modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
    modelViewMatrix.PushMatrix();
    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
                                 modelViewMatrix.GetMatrix(),
                                 transformPipeline.GetProjectionMatrix(),
                                 vLightPos,
                                 vWhite,
                                 0);
    torusBatch.Draw();
    modelViewMatrix.PopMatrix();
    
    //4.绘制公转小球球(公转自转)
    modelViewMatrix.PushMatrix();
    modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
                                 modelViewMatrix.GetMatrix(),
                                 transformPipeline.GetProjectionMatrix(),
                                 vLightPos,
                                 vWhite,
                                 0);
    sphereBatch.Draw();
    modelViewMatrix.PopMatrix();
}

在绘制完大球和小球之后,回到RenderScene函数去绘制整个图形,在上面的图形当中,倒影和实物图与地面呈现出了间隙,那么我们需要利用一个单元矩阵去翻转和平移y轴距离,去实现这个效果。然而,倒影旋转的方向与实物的旋转方向要一致的,那我们就需要指定顺时针面为正面,在绘制完后,需要复原。

 //单元矩阵入栈
    modelViewMatrix.PushMatrix();
    
    //翻转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]);
     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vFloorColor,
                                 0);
    //shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
    
    //开始绘制
    floorBatch.Draw();
    //取消混合
    glDisable(GL_BLEND);
    
    //16.绘制地面以外其他部分
    drawSomething(yRot);
    
    //17.绘制完,恢复矩阵
    modelViewMatrix.PopMatrix();

这个案例在之前那个案例上增加了纹理的样式和倒影,运行的效果比之前的要好看很多。

相关文章

  • OpenGL纹理综合案例

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

  • OpenGL大小球纹理镜像

    这个案例是基于OpenGL综合练习基础上增加纹理和镜像效果的实现。 一、SetupRC函数 纹理的顶点数据设置完成...

  • 案例08:隧道

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

  • 案例07:纹理金字塔

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

  • OpenGL 案例:球体世界

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

  • 纹理在OpenGL中的实际运用

    这次的案例我们在OpenGL综合练习的基础上配上纹理和镜面效果,提升整理的视觉效果。具体代码如下: 主要模块讲解 ...

  • 案例06:大球自转+小球公转+移动

    OpenGL + OpenGL ES +Metal 系列文章汇总 这个案例是OpenGL中的一个比较经典的综合案例...

  • OpenGL(九)-- 综合案例(公、自转)

    OpenGL(九)-- 综合案例(公、自转) 相信学习过OpenGL的同学应该过玩过这个经典案例:总和案例.gif...

  • OpenGL纹理综合练习

    球体 金字塔 隧道 针对以上三种立体图形添加纹理后的效果图,其绘制流程均是一下流程: 主要针对纹理添加过程作出分析...

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

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

网友评论

      本文标题:OpenGL纹理综合案例

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