OpenGL--环境映射

  • 理论基础
    三维场景中的物体不仅受光照影响,而且受周围环境的影响,如金属,水面等材质都可以映射出周围环境的图像。模拟物体光滑表面能够映射出周围环境的技术叫做环境映射(也称反射映射)。
    其原理是通过立方体纹理(cube)实现的,具体是:把摄像机放在反射物体旁边,分别朝6个方向照得6张纹理,组成立方体纹理。然后就是利用这个立方体纹理通过一些复杂的数学计算,把反射纹理映射到我们的光亮物体表面,从而形成物体反射周围环境的效果。其本质还是纹理贴图,只是纹理来源于周围环境。

  • 代码示例
#include <GLTools.h>

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

//立方体6个面纹理:其实就是摄像机在光亮物体附件分别朝6个方向照下的纹理,这里直接手动指定。
const char *szCubeFaces[6] = {
    "/Users/app05/Desktop/opengl/pos_x.tga",
    "/Users/app05/Desktop/opengl/neg_x.tga",
    "/Users/app05/Desktop/opengl/pos_y.tga",
    "/Users/app05/Desktop/opengl/neg_y.tga",
    "/Users/app05/Desktop/opengl/pos_z.tga",
    "/Users/app05/Desktop/opengl/neg_z.tga" };

//立方体6个面
GLenum  cube[6] = {  GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };

GLuint              cubeTexture;
void init()
{
    GLbyte *pBytes;
    GLint iWidth, iHeight, iComponents;
    GLenum eFormat;
    int i;

    glCullFace(GL_BACK);//剔除背面
    glFrontFace(GL_CCW);//设置逆时针方向为正面
    glEnable(GL_DEPTH_TEST);

    glGenTextures(1, &cubeTexture);
    glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTexture);//创建立方体纹理对象

    //设置立方体纹理过滤方式
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    for(i = 0; i < 6; i++)
    {
        pBytes = gltReadTGABits(szCubeFaces[i], &iWidth, &iHeight, &iComponents, &eFormat);
        //指定立方体6个面纹理
        glTexImage2D(cube[i], 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
        free(pBytes);
    }

    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);//为立方体每个面生成多级纹理
}

void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_TEXTURE_CUBE_MAP_ARB);//激活立方体纹理
    glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cubeTexture);//指定当前立方体纹理为活动纹理

    //用立方体纹理绘制场景
    glBegin(GL_QUADS);
    glTexCoord3f(1.0f, 1.0f, -1.0f); glVertex3f(12.0f, 12.0f, -20.0f);
    glTexCoord3f(-1.0f, 1.0f, -1.0f); glVertex3f(-12.0f, 12.0f, -20.0f);
    glTexCoord3f(-1.0f, -1.0f, -1.0f); glVertex3f(-12.0f, -12.0f, -20.0f);
    glTexCoord3f(1.0f, -1.0f, -1.0f); glVertex3f(12.0f, -12.0f, -20.0f);
    glEnd();

    //自动生成立方体纹理坐标
    glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);//反射
    glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
    glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);
    glEnable(GL_TEXTURE_GEN_R);
    glutSolidSphere (2.0, 30, 30);//绘制球体,立方体纹理贴到球体上

    glutSwapBuffers();
}

void ChangeSize(int w, int h)
{
    if(h == 0)
        h = 1;

    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(35.0, (GLfloat) w/(GLfloat) h, 1.0, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -15.0f);
}

//退出时,删除纹理
void ShutdownRC(void)
{
    glDeleteTextures(1, &cubeTexture);
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500,500);
    glutCreateWindow("OpenGL Cube Maps");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    init();
    glutMainLoop();
    ShutdownRC();
    return 0;
}

这里写图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值