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

2019-05-31  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读