03源码--007--纹理应用:球体世界

2020-07-26  本文已影响0人  修_远

案例 03源码--004--综合案例:太阳系:讲述了如何绘制一个球体世界,大球自转,小球公转;
案例 03源码--005--纹理应用:金字塔贴图:讲述了如何给一个物体贴图——绘制纹理;

如果将两个案例中的内容结合在一起,就可以得到下图的效果:

综合效果

分析这个球体相对于之前不一样的地方:

  1. 地板不一样了,地板上贴了一层图——这个简单,纹理走一波;
  2. 每个球体表面贴了一层“膜”——同样的操作,纹理走一波;
  3. 地板、大球、小球之间的纹理都不一样——涉及到多个纹理的切换
  4. 地板是透明的,类似于水面一样——颜色要设置透明度
  5. 地板下面有球体,而且是镜像效果——这个比较复杂,后面详解;
  6. 地板下面的球和地板上面的球是不一样的——开启了混合的效果;

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

载入纹理

glGenTextures(3, uiTextures);
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);

RenderScene

球体世界

绘制过程主要分3步:

  1. 对于地板下面和地板上面的大球、小球、大球自转、小球公转,以及大小球的纹理都是一模一样的实现,所以抽离到一个绘制函数:drawSomething 里面;
  2. 一定要保证先绘制地板下的球体,然后再绘制地板。因为地板下面的球体和地板需要进行混合,所以按照这个顺序来控制逻辑最方便。(其他顺序也可以实现,但是矩阵变换会比较复杂);
  3. 在绘制地板下面的视图前,需要修改正面的顺序,glFrontFace(GL_CW);,如果不修改,我们看到的地板下面的效果就是球体的背面,就不是镜像的效果了。使用完之后一定要还原,glFrontFace(GL_CCW);
  4. glBindTexture(GL_TEXTURE_2D, uiTextures[1]);,在绘制前需要先绑定所对应的纹理——这是一个基本操作,一定要牢记。
void drawSomething(GLfloat yRot)
{
    //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();
}
上一篇 下一篇

猜你喜欢

热点阅读