OpenGL(七)-纹理(上)

设定金字塔坐标

金字塔.png

注意纹理坐标的设置方式:
//设置顶点对应的纹理坐标
// s , t 相当于 x , y
// MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
//参数1:纹理的层次
//参数2:s坐标
//参数3:t坐标
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

绘制金字塔纹理

1. 顶点/纹理坐标数据设置及图形绘制
    GLBatch             pyramidBatch;//绘制批次类
    //1.pyramidBatch
    //通过三角形批次类pyramidBatch 来组件图形
    //参数1:类型
    //参数2:顶点数 6 * 3 = 18
    //参数3:需要使用到纹理,默认为0,可以不写这个参数
    pyramidBatch.Begin(GL_TRIANGLES, 18,1);

    //2.金字塔各个面的点坐标设置

    //金字塔底部
    //底部四边形 = 三角形X + 三角形Y
    //三角形X
    //----------vBlackLeft------------
    //设置法线坐标-光照
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
 
    //设置顶点对应的纹理坐标
    // MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
    //参数1:纹理的层次
    //参数2:s坐标
    //参数3:t坐标
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    
    //设置顶点坐标
    pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
    
    //------vBackRight------------
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3f(1.0f, -1.0f, -1.0f);
   
    //------vFrontRight点------------
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);
    
    
    //三角形Y
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
    pyramidBatch.Vertex3f(-1.0f, -1.0f, 1.0f);
    
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
    
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);

    //塔顶
    M3DVector3f vApex = {0.0f,1.0f,0.0f};
    M3DVector3f vFrontLeft = {-1.0f,-1.0f,1.0f};
    M3DVector3f vFrontRight = {1.0f,-1.0f,1.0f};
    M3DVector3f vBackLeft = {-1.0f,-1.0f,-1.0f};
    M3DVector3f vBackRight = {1.0f,-1.0f,-1.0f};
    
    //目的:为了临时存储法线向量
    M3DVector3f n;
    
    //金字塔的前面
    //三角形:(Apex,vFrontLeft,vFrontRight)
    
    //找法线
    //m3dFindNormal(M3DVector3f result, const M3DVector3f point1, const M3DVector3f point2,const M3DVector3f point3);
    //参数1:结果
    //参数2-4:3个顶点
    m3dFindNormal(n, vApex, vFrontLeft, vFrontRight);
    
    //vApex
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    //vFrontLeft
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontLeft);
    
    //vFrongRight
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontRight);

    
    //金字塔的左边
    //三角形:(Apex,vBackLeft,vFrontLeft)
    m3dFindNormal(n, vApex, vBackLeft, vFrontLeft);

    //vApex
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    //vBackLeft
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackLeft);
    
    //vFrontLeft
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontLeft);
    
    //金字塔右边
    //三角形:(vApex, vFrontRight, vBackRight)
    m3dFindNormal(n, vApex, vFrontRight, vBackRight);
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vFrontRight);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackRight);
    
    //金字塔后边
    //三角形:(vApex, vBackRight, vBackLeft)
    m3dFindNormal(n, vApex, vBackRight, vBackLeft);
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
    pyramidBatch.Vertex3fv(vApex);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackRight);
    
    pyramidBatch.Normal3fv(n);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    pyramidBatch.Vertex3fv(vBackLeft);
    
    //结束批次设置
    pyramidBatch.End();
2.加载2D纹理
// 将TGA文件加载为2D纹理。
//参数1:纹理文件名称
//参数2:缩小时过滤器使用的哪一种
//参数3:放大小时过滤器使用的哪一种
//参数4:纹理坐标环绕方式
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
    GLbyte *pBits;
    int nWidth,nHeight,nComponents;
    GLenum eFormat;
    
    //1.读取纹理的像素
    //参数1:纹理文件的名称
    //参数2:文件的宽度地址
    //参数3:文件的高度地址
    //参数4:文件的组件地址
    //参数5:文件格式地址
    //返回值:pBits ,指向图像数据的指针
    pBits =  gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    
    if (pBits == NULL) {
        
        printf("读取纹理像素失败\n");
        return  false;
    }
    
    //2.设置纹理参数
    //设置s,t的环绕方式
    //glTexParameteri (GLenum target, GLenum pname, GLint param);
    //参数1:纹理维度
    //参数2:为S/T坐标设置环绕模式
    //参数3:wrapMode,环绕模式
    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.精密包装像素数据
    //glPixelStorei (GLenum pname, GLint param);
    //参数1:GL_UNPACK_ALIGNMENT ,OpenGL 如何从数据缓存区中解包图像数据
    //参数2:设置GL_UNPACK_ALIGNMENT的值
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
    //4.载入纹理
    //glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
    //参数1:纹理的维度
    //参数2:mip贴图层次
    //参数3:加载纹理颜色成分(从读取像素图获取的)
    //参数4:加载纹理的宽
    //参数5:加载纹理的高
    //参数6:纹理的边框
    //参数7:像素数据的类型
    //参数8:指向纹理数据的指针
    //详细可参考PPT
    glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, 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)
        
        //加载Mip,纹理生成所有的Mip层
        //参数:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
        glGenerateMipmap(GL_TEXTURE_2D);

    
    return true;
}

3.SetUp
void SetupRC()
{
    
    glClearColor(0.7f, 0.7f,0.7f, 1.0f);
    
    shaderManager.InitializeStockShaders();
    
    //开启深度测试
    glEnable(GL_DEPTH_TEST);
    
    //纹理对象的处理
    //1.分配纹理对象
    // glGenTextures (GLsizei n, GLuint *textures);
    //参数1:纹理对象的个数
    //参数2:纹理对象的指针
    glGenTextures(1, &textureID);

    //2.绑定纹理状态
    //glBindTexture (GLenum target, GLuint texture);
    //参数1:纹理的状态,GL_TEXTURE_1D\GL_TEXTURE_2D\GL_TEXTURE_3D
    glBindTexture(GL_TEXTURE_2D, textureID);
    
    
    //3.将TGA文件加载成2D纹理
    //函数是开发者自己设计的
    //参数1:纹理文件名称
    //参数2:缩小时过滤器使用的哪一种
    //参数3:放大小时过滤器使用的哪一种
    //参数4:纹理坐标环绕方式
    LoadTGATexture("brick.tga", GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
    
    //4.设置渲染图像的顶点--金字塔
    MakePyramid(pyramidBatch);
    
    cameraFrame.MoveForward(-10.0);
    
}
4.渲染
void RenderScene(void)
{
    //光照位置
    static GLfloat vLightPos[] = {1.0f,1.0f,0.0f};
    
    //关照颜色
    static GLfloat vWhite[] = {1.0f,0.0f,0.0f,1.0f};
    
    //glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER|GL_STENCIL_BUFFER_BIT);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    modelViewMatrix.PushMatrix();
    
    //观察者
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.MultMatrix(mCamera);
    
    //
    M3DMatrix44f mObjectFrame;
    objectFrame.GetMatrix(mObjectFrame);
    modelViewMatrix.MultMatrix(mObjectFrame);
    
    //错误地方!!!
    //glBindTexture(GL_TEXTURE_2D, 0);
    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,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vWhite,0);
    
  
    pyramidBatch.Draw();
    
    modelViewMatrix.PopMatrix();
    
    glutSwapBuffers();
    
    
    
}
效果图
image.png

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。