剪纸效果的纹理贴图

对于一幅图像来说,可以看做是一个二维像素点的矩阵。剪纸效果的纹理贴图是指一张图片有的像素点正常显示,有的像素点则不显示(完全透明)。有的图片的每个像素有 3 个通道 R、G、B(分别代表红、绿、蓝),其值 0 ~ 255;也有的图片的每个像素有 4 个通道R、G、B、A(alpha值,代表透明度,opengl中可用于混合)。

一般 opengl 中比较常用的图片格式为 bmp,其仅仅含有 RGB 三个通道,并不含 alpha 通道。因此,如果要使用 bmp 制作剪纸效果的纹理的话,这里提出2个方法:

方法一:使用透明的方法显示纹理图片

  1. 在初始化时,调用 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)glEnable(GL_BLEND) 开启混合功能。

  2. 在初始化时调用 glEnable(GL_TEXTURE_2D) 开启纹理贴图的功能。使用 pImage = auxDIBImageLoad(fileName) 加载图片。

    其中pImage的数据类型为

    typedef struct _AUX_RGBImageRec {
        GLint sizeX, sizeY;//像素的x,y数值
        unsigned char *data;//像素的内容,对于bmp来说,其大小为3*sizeX*sizeY
    } AUX_RGBImageRec;
    
  3. 虽然图片中并没有 alpha 通道,但是对于一般剪纸图片来说,可以假定不显示的部门为白色,而显示的部分为其他颜色。由此可以新建一个 4 通道的数组

    unsigned char* pPic = new unsigned char[4 * pImage->sizeX * pImage->sizeY];
    size_t NUM = pImage->sizeX * pImage->sizeY;
    for (int i=0; idata[idx0];// 因为GL_BLEND模式下,图片会反色显示
    bool r = pPic[idx1] < 10;
    pPic[idx1+1] = 255 - pImage->data[idx0+1];
    bool g = pPic[idx1+1] < 10;
    pPic[idx1+2] = 255 - pImage->data[idx0+2];
    bool b = pPic[idx1+2] < 10;
    
    if (r && g && b)
        pPic[idx1+3] = 0; // 若像素点的颜色接近白色,则设置alpha值为0,表示完全透明
    else
        pPic[idx1+3] = 255;// 若像素点的颜色不为白色,则设置alpha值为255,表示完全不透明
    }
    
  4. 绑定并生成纹理图片

    glBindTexture(GL_TEXTURE_2D, m_Texture[texName]);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //Set texture environment parameter
    // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
    
    /* gluBuild2DMipmaps(GL_TEXTURE_2D
            , 4 // 表示有RGBA四个通道
            , pImage->sizeX
            , pImage->sizeY
            , GL_RGBA // 重要
            , GL_UNSIGNED_BYTE
            , pPic);*/ // 这个函数也可以
    
    glTexImage2D(GL_TEXTURE_2D
            , 0
            , GL_RGBA // 重要
            , pImage->sizeX
            , pImage->sizeY
            , 0
            , GL_RGBA // 重要
            , GL_UNSIGNED_BYTE
            , pPic);
    
  5. 删除pPic和pImage的内存

  6. 显示剪纸效果的纹理图片

  7. 为了清楚看出剪纸效果,这里画一个黄色的矩形作为背景。

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);// 设置为GL_DECAL
    
    float oldColor[4];
    glGetFloatv(GL_CURRENT_COLOR, oldColor);
    glColor4f(1.0f, 1.0f, 0.0f, 1.0f);// 设置alpha值为1,表示完全不透明
    glPushMatrix();
    glBegin(GL_POLYGON);
    glVertex3f(-150.0f, -150.0f, -100.0f);
    glVertex3f(150.0f, -150.0f, -100.0f);
    glVertex3f(150.0f, 150.0f, -100.0f);
    glVertex3f(-150.0f, 150.0f, -100.0f);
    glEnd();
    glPopMatrix();
    
    glColor4fv(oldColor);
    
    // 然后再绘制纹理图片
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);//设置为GL_BLEND
    
    glBindTexture(GL_TEXTURE_2D, m_Texture[0]);
    
    glBegin(GL_POLYGON);
    glTexCoord2f(0, 0);
    glVertex3f(-60.0f, -120.0f, 100.0f);
    glTexCoord2f(1, 0);
    glVertex3f( 60.0f, -120.0f, 100.0f);
    glTexCoord2f(1, 1);
    glVertex3f( 60.0f, 120.0f, 100.0f);
    glTexCoord2f(0, 1);
    glVertex3f(-60.0f, 120.0f, 100.0f);
    glEnd();
    
  8. 显示结果

    背景为白色的一幅图片:

    剪纸效果的纹理贴图_第1张图片
    image

    显示的纹理结果为:

    剪纸效果的纹理贴图_第2张图片
    image
    剪纸效果的纹理贴图_第3张图片
    image

方法二:不使用透明的方法显示纹理图片,但使用模板缓冲区的方法显示纹理图片

待续~~_

你可能感兴趣的:(剪纸效果的纹理贴图)