美文网首页
OpenGL大小球纹理镜像

OpenGL大小球纹理镜像

作者: 奉灬孝 | 来源:发表于2020-07-21 23:35 被阅读0次

这个案例是基于OpenGL综合练习基础上增加纹理和镜像效果的实现。

OpenGL纹理案例.png

一、SetupRC函数

    //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();

纹理的顶点数据设置完成之后,我们就需要进行以下步骤:

1.分配纹理对象

由于使用了3种纹理,传入的纹理个数为3,并传入纹理数组

glGenTextures(3, uiTextures);
2.绑定纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
3.加载纹理
LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, 
GL_LINEAR, GL_REPEAT);

二、加载纹理loadTGATexture函数

  • 读取纹理 -- gltReadTGABits

参数说明

  • 参数1:纹理文件名称
  • 参数2:文件宽度地址
  • 参数3:文件高度地址
  • 参数4:文件组件地址
  • 参数5:文件格式地址
  • 返回值:pBits,指向图像数据的指针
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, 
&nComponents, &eFormat);
  • 设置纹理参数(S和T的环绕模式、放大/缩小的过滤方式) -- glTexParameteri。参数说明可参考OpenGL纹理API
//设置环绕方式
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, 
nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
  • 释放
free(pBits);
  • 加载Mip,纹理生成所有的Mip层

参数说明

  • GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);

三、RenderScene函数

1. 镜面绘制
  • push压栈:此处压栈的目的是由于观察者矩阵是作用于全局的,为了不影响后续图形的绘制,所以需要压栈
  • 翻转Y轴:通过Scale函数,沿着y轴,从+y翻转到-y绝对值相等的坐标
  • 围绕Y轴平移:平移的目的是为了镜面效果更逼真,现实中的照镜子,镜子里与镜子外也是有一定间隔的
  • 指定顺时针为正面:需要绘制的-y轴的镜面部分,所以需要更改系统默认的逆时针正面,改为顺时针为正面,绘制完成后,在恢复默认设置
  • 绘制镜面部分
  • 恢复逆时针为正面:此处必须恢复,不然会影响后续图形的绘制
  • pop出栈栈顶:恢复到堆栈栈顶是观察者矩阵的状态
    //6.压栈(镜面)
    modelViewMatrix.PushMatrix();
    
    //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();
2.地板绘制
  • 开启混合,并指定混合方程式:开启混合的目的是地板需要与镜面部分进行颜色混合,且地板需要设置一个半透明的基本色,用于颜色混合,如果不设置,则无法看到地面以下内容,将看到的是一个实体的地板
  • 绑定地板纹理
  • 绘制地板
  • 关闭混合
//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层的纹理单元),level
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
                                 transformPipeline.GetModelViewProjectionMatrix(),vFloorColor,0);
   
//开始绘制
 floorBatch.Draw();
//关闭混合
glDisable(GL_BLEND);
3.非镜面绘制drawSomething函数

四、drawSomething函数

1.定义光源位置&漫反射颜色
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
2.绘制悬浮小球球
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();
}
3.绘制大球
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();

Demo:
OpenGL大小球纹理镜像

相关文章

  • OpenGL大小球纹理镜像

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

  • OpenGL纹理加载与镜像

    OpenGL纹理加载步骤以及相关API 在准备工作SetupRC函数中 在渲染函数中不同的纹理需要一一对应再次绑定...

  • OpenGL纹理下的球体世界

    一.先看看整体效果 二.绘制流程 在OpenGl综合案例(地板,大小球,公转,自转,移动)文章中,我们绘制了大小球...

  • GLKit常用API解析

    GLKTextureInfo 创建OpenGL纹理信息 name: OpenGL上下文中纹理名称 target: ...

  • OpenGL ES GLKit 􏰼􏰜常用API解析

    GLKTextureInfo创建OpenGL纹理信息 name : OpenGL上下文中纹理名称 target :...

  • OpenGL纹理内容

    纹理可以理解为一张图片,OpenGL渲染图片会将图片的像素保存在纹理缓存中。 OpenGL常用纹理函数 载入纹理 ...

  • Android OpenGL ES 绘制镜像纹理

    1、背景 只记得有一次面试,面试官提到一个问题,既然你对OpenGL ES有一定的了解,那么可否写一个纹理镜像呢,...

  • OpenGL纹理

    纹理可以理解为一张图片,OpenGL渲染图片会将图片的像素保存在纹理缓存中。OpenGL常用纹理函数 载入纹理 纹...

  • OPenGL ES纹理翻转解决方案

    纹理翻转 在使用OpenGL函数加载纹理到图形时,经常遇到纹理上下颠倒的问题。原因是因为OpenGL要求纹理坐标原...

  • OpenGL坐标概念

    openGL 顶点,坐标系,纹理坐标Android OpenGL es 纹理坐标设定与贴图规则对Android o...

网友评论

      本文标题:OpenGL大小球纹理镜像

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