美文网首页
OpenGL从零开始 -- 给图加上纹理

OpenGL从零开始 -- 给图加上纹理

作者: 尤先森 | 来源:发表于2019-05-31 10:34 被阅读0次

    在上一篇文章中,我们已经画出了一个看上去没什么问题的圆圈,并且怎么转动也没出现奇奇怪怪的显示问题。
    今天我们就来为这个圆圈贴图(加上纹理)。
    这次是在上一篇文章的基础上,加点代码,来实现这样的效果。


    image.png

    先说说我这次都做了什么

    1.把圆圈换成圆
    2.给绘制出来的图像上了纹理

    在上一篇文章的基础上多了这些内容
    1.一张纹理图


    image.png

    2.一个用于绑定纹理的ID

    //纹理变量,一般使用无符号整型
    GLuint              textureID;
    

    3.一个加载纹理的方法
    参数说明:
    szFileName:纹理文件的名称
    minFilter:需要缩小的过滤器
    magFilter:需要放大的过滤器
    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;
    }
    

    4.应用textureID & LoadTGATexture

    void SetupRC()
    {
        //黑色背景
        glClearColor(0, 0, 0, 1);
        //视角往前移动
        viewFrame.MoveForward(7);
        //初始化管理器
        shaderManager.InitializeStockShaders();
        
        //分配纹理对象 参数1:纹理对象个数,参数2:纹理对象指针
        glGenTextures(1, &textureID);
        
        //绑定纹理状态 参数1:纹理状态2D 参数2:纹理对象
        glBindTexture(GL_TEXTURE_2D, textureID);
        
        //将TGA文件加载为2D纹理。
        //参数1:纹理文件名称
        //参数2&参数3:需要缩小&放大的过滤器
        //参数4:纹理坐标环绕模式
        LoadTGATexture("MoonLike.tga", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, GL_CLAMP_TO_EDGE);
        //画圈
        gltMakeSphere(torusBatch, 1, 40, 20);  
    }
    
    //渲染场景
    void RenderScene()
    {
        //清理各种缓存
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        //开启表⾯面剔除(默认背⾯面剔除)
        glEnable(GL_CULL_FACE);
        //用户指定哪个环绕顺序为正面 可选值为:GL_CW、 GL_CCW
        //默认传入GL_CCW
        glFrontFace(GL_CCW);
        //⽤户选择剔除哪个面(正面/背面)
        //默认为背面
        glCullFace(GL_BACK);
        
        glEnable(GL_DEPTH_TEST);
        
        //矩阵压栈,注意这里push了viewFrame进去
        modelViewMatix.PushMatrix(viewFrame);
        
    
        //定义光源位置&漫反射颜色
        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, textureID);
        
        /*点光源着色器
         参数1:GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF(着色器标签)
         参数2:模型视图矩阵
         参数3:投影矩阵
         参数4:视点坐标系中的光源位置
         参数5:基本漫反射颜色
         参数6:图形颜色(用纹理就不需要设置颜色。设置为0)
         */
        shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
                                     modelViewMatix.GetMatrix(),
                                     transformPipeline.GetProjectionMatrix(),
                                     vLightPos,
                                     vWhite,
                                     0);
        //绘制
        torusBatch.Draw();
        //出栈
        modelViewMatix.PopMatrix();
        
        glutSwapBuffers();
        
    }
    

    至此,就可以画出文章刚开始时的月亮了,有兴趣的朋友也可以改变一下图元,可以换成各种形状,比如:


    image.png

    相关文章

      网友评论

          本文标题:OpenGL从零开始 -- 给图加上纹理

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