glTexEnvi

glTexEnvi

void glTexEnv {i f} (GLenum target, GLenum pname, TYPE param);
设置当前的纹理映射方式。参数target必须为GL_TEXTURE_FILTER_CONTROL或GL_TEXTURE_ENV。
如果参数target为GL_TEXTURE_FILTER_CONTROL,pname必须为GL_TEXTURE_LOD_BIAS,而param是一个浮点数,用于指定GL_TEXTURE_LOD_BIAS的值。
参数target为GL_TEXTURE_ENV时,参数pname和param的取值见下表。
参数pname
参数param
GL_TEXTURE_ENV_MODE
GL_DECAL、GL_REPLACE、GL_MODULATE、GL_BLEND、GL_ADD、GL_COMBINE
GL_TEXTURE_ENV_COLOR
包含4个浮点数的数组,表示分量R、G、B、A的值
GL_COMBINE_RGB
GL_REPLACE、GL_MODULATE、GL_ADD、GL_ADD_SIGNED、GL_INTERPOLATE、GL_SUBTRACT、GL_DOT3_RGB、GL_DOT3_RGBA
GL_COMBINE_ALPHA
GL_REPLACE、GL_MODULATE、GL_ADD、GL_ADD_SIGNED、GL_INTERPOLATE、GL_SUBTRACT
GL_SOURCEi_RGB
GL_SOURCEi_ALPHA
(i为1、2或3)
GL_TEXTURE、GL_TEXTUREn(where n denotes the nth texture unit and multitlexturing is enabled)、GL_CONSTANT、GL_PRIMARY_COLOR、GL_PREVIOUS
GL_OPERANDi_RGB
(i为1、2或3)
GL_SRC_COLOR、GL_ONE_MINUS_SRC_COLOR、GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA
GL_OPERANDi_ALPHA
(i为1、2或3)
GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA
GL_RGB_SCALE
表示颜色分量缩放因子的浮点数
GL_ALPHA_SCALE
表示alpha分量缩放因子的浮点数
如果pname为GL_TEXTURE_ENV_MODE,则参数param指定了如何将纹理值和片元的颜色值合并起来。
如果纹理映射方式为GL_BLEND,将使用GL_TEXTURE_ENV_COLOR的值来与片元混合,因此必须设置它。
如果纹理映射方式为GL_COMBINE,还可能需要设置参数GL_COMBINE_RGB、GL_COMBINE_ALPHA、GL_RGB_SCALE或GL_ALPHA_SCALE。如果设置了参数GL_COMBINE_RGB,还可能需要设置参数GL_SOURCEi_RGB和GL_OPERANDi_RGB(其中i 为0、1或2)的值;同样,如果设置了参数GL_COMBINE_ALPHA,还可能需要设置参数GL_SOURCEi_ALPHA和GL_OPERANDi_ALPHA的值。
------------------------------------------------------------------------------------------------------------------------------------

1. 简介

glTexEnv用来设置纹理的环境参数,纹理环境参数主要控制纹理如何与片元颜色进行计算的。

2. 函数原型

void glTexEnvf( GLenum target,
    GLenum pname,
    GLfloat param);
 
void glTexEnvi( GLenum target,
    GLenum pname,
    GLint param);
 
 void glTexEnvfv(   GLenum target,
    GLenum pname,
    const GLfloat * params);
 
void glTexEnviv(    GLenum target,
    GLenum pname,
    const GLint * params);

该函数是一个函数簇,根据具体的参数类型来决定使用哪个版本的函数。 
参数描述: 
1. target:设置操作的目标,可以设置为GL_TEXTURE_ENV, GL_TEXTURE_FILTER_CONTROL 或者GL_POINT_SPRITE 
2. pname:设置项 
3. param:对panme设置项的值

3. 详细描述

  1. 当纹理环境中的target设置为GL_TEXTURE_FILTER_CONTROL的时候,pname的值必须设置为 GL_TEXTURE_LOD_BIAS,当设置pname是GL_TEXTURE_LOD_BIAS的时候,它的值是用来设置MipMap纹理层级选择公式的一个参数,具体可以参考 OpenGL API 之glTexParameter

  2. 当纹理环境中target设置为GL_TEXTURE_ENV,panme设置为GL_TEXTURE_ENV_MODE时候,对应的param的取值包括:

param取值 含义
GL_ADD 处理方式是片段颜色加上纹理采样的颜色
GL_MODULATE 片段颜色与纹理采样颜色相乘
GL_DECAL 见下图中的表
GL_BLEND 两者相混合,参考下图中的表
GL_REPLACE 纹理颜色完全取代片段颜色
GL_COMBINE 参考后面的论述

纹理的格式(参考OpenGL图像格式 )包括有以下几种

纹理的基本格式 颜色成分 Alpha成分
GL_ALPHA (0, 0, 0, 0)
GL_LUMINANCE (,,) 1
GL_LUMINANCE_ALPHA (,,)
GL_INTENSITY (,,)
GL_RGB (,,) 1
GL_RGBA (,,)

我们先用一个程序感性的了解一下这些参数对于程序表现的影响:

#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "freeglut.lib")
#pragma comment(lib, "soil.lib")
 
#include <stdio.h>
#include <gl/glew.h>
#include <gl/glut.h>
#include <iostream>
#include <gl/soil.h>
 
int windowWidth = 0;
int windowHeight = 0;
 
bool leftMouseDown = false;
float mouseX, mouseY;
float cameraAngleX, cameraAngleY;
float xRot, yRot;
 
GLuint texID;
 
void drawCube()
{
    glBindTexture(GL_TEXTURE_2D, texID);
 
    glBegin(GL_QUADS);
    glColor3f(1, 0, 0);
    glTexCoord2d(0.0, 0.0);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2d(1.0, 0.0);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glTexCoord2d(1.0, 1.0);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glTexCoord2d(0.0, 1.0);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glEnd();
}
 
 
void SetupRC()
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
 
    int imageWidth, imageHeight;
    int channels;
 
    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);
 
    unsigned char* imageDataA = SOIL_load_image("../Data/a.png", &imageWidth, &imageHeight,
        &channels, SOIL_LOAD_AUTO);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageDataA);
 
    unsigned char* imageDataB = SOIL_load_image("../Data/b.png", &imageWidth, &imageHeight,
        &channels, SOIL_LOAD_AUTO);
    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageDataB);
 
    unsigned char* imageDataC = SOIL_load_image("../Data/c.png", &imageWidth, &imageHeight,
        &channels, SOIL_LOAD_AUTO);
    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageDataC);
 
    unsigned char* imageDataD = SOIL_load_image("../Data/d.png", &imageWidth, &imageHeight,
        &channels, SOIL_LOAD_AUTO);
    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageDataD);
 
    unsigned char* imageDataE = SOIL_load_image("../Data/e.png", &imageWidth, &imageHeight,
        &channels, SOIL_LOAD_AUTO);
    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageDataE);
 
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 1);
 
    //如果注释掉这行代码,会导致纹理失败,这主要是因为GL_TEXTURE_MIN_FILTER使用的默认值是
    //GL_NEAREST_MIPMAP_LINEAR,但是代码中却没有设置MipMap,对于GL_TEXTURE_MAG_FILTER是否设置并不重要
    //因为GL_TEXTURE_MAG_FILTER默认的取值就是GL_LINEAR
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
 
    ///
    ///测试glTexEnv函数的表现
    //GL_TEXTURE_ENV_MODE 取值:
    //1. GL_REPLACE
    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    //2. GL_MODULATE(默认取值)
    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    //3. GL_ADD
    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
    //4. GL_DECAL 
    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    //5. GL_BLEND
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
 
    //设置与片段颜色进行混合的颜色
    //GLfloat blendColor[] = { 0.8, 0.5, 0.7, 0.5 };
    //glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blendColor);
 
    SOIL_free_image_data(imageDataA);
    SOIL_free_image_data(imageDataB);
    SOIL_free_image_data(imageDataC);
    SOIL_free_image_data(imageDataD);
    SOIL_free_image_data(imageDataE);
 
    glBindTexture(GL_TEXTURE_2D, 0);
}
 
void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
    glTranslated(0, 0, -5);
    glRotated(cameraAngleY*0.5, 1, 0, 0);
    glRotated(cameraAngleX*0.5, 0, 1, 0);
    drawCube();
 
    glutSwapBuffers();
}
 
 
void ChangeSize(int w, int h)
{
    windowWidth = w;
    windowHeight = h;
 
    if (h == 0)
        h = 1;
    glViewport(0, 0, w, h);
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, w*1.0 / h, 0.01, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
 
 
void MouseFuncCB(int button, int state, int x, int y)
{
    mouseX = x;
    mouseY = y;
 
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            leftMouseDown = true;
        }
        else if (state == GLUT_UP)
        {
            leftMouseDown = false;
        }
    }
 
}
 
void MouseMotionFuncCB(int x, int y)
{
    if (leftMouseDown)
    {
        cameraAngleX += (x - mouseX);
        cameraAngleY += (y - mouseY);
 
        mouseX = x;
        mouseY = y;
    }
 
    glutPostRedisplay();
}
 
 
int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("OpenGL");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutMouseFunc(MouseFuncCB);
    glutMotionFunc(MouseMotionFuncCB);
 
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
 
    SetupRC();
 
    glutMainLoop();
    return 0;
}


GL_MODULATE(默认取值) 
Modulate 
GL_REPLACE 
Replace 
GL_ADD 
ADD 
GL_BLEND 
BLEND 
这些最终表现的颜色是怎么计算的呢?实际上计算的公式参考下表: 
表中:【公式参数的简要说明:后缀是v表示最终输出的颜色(也就是我们上面看到的图片颜色),后缀是p表示是片段颜色(尚未应用纹理计算previous texture stage),后缀是s表示纹理图片的颜色(texture source color), 后缀是c表示我们需要通过GL_TEXTURE_ENV_COLOR设置的颜色, C表示颜色成分(RGB),A表示Alpha成分】

纹理格式 最终颜色和Alpha成分结果 GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD
GL_ALPHA  = 未定义
   = * 未定义 * *
GL_LUMINANCE(或者1)  = * 未定义
   = 未定义
GL_LUMINANCE_ALPHA(或者2)  = * 未定义
   = * 未定义 * *
GL_INTENSITY  = * 未定义
   = * 未定义
GL_RGB(或者3)  =
   =
GL_RGBA(或者4)  = C_p+C_s
   =

除了上述对纹理进行的操作外,OpenGL还支持更加复杂的纹理颜色操作方式,这种操作方式成为 纹理组合器。具体的方式如下:

为了使用纹理组合器,需要调用:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

接下来选择对颜色成分还是Alpha成分进行计算的算法选择,可以设置:

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
或者是Alpha的操作:
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);

各种不同参数的含义 
TCB

参数中的Arg0、Arg1和Arg2需要使用下面的方式来设置: 
GL_SOURCEx_RGB,GL_SOURCEx_Alpha(x代表0,1,2),这些参数的取值如下:

取值 含义
GL_TEXTURE 当前活动的纹理单元
GL_TEXTUREx 第x号纹理单元
GL_CONSTANT 使用GL_TEXTURE_ENV_COLOR设置的颜色值
GL_PRIMARY_COLOR 几何体片段的颜色
GL_PREVIOUS 来自上一个纹理单元最后计算出的颜色

例如我们需要设置公式中Arg0代表的是第0号纹理,那么需要调用:

glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);

除此之外,还可以对操作数做一些修改,使用GL_OPERANDx_RGB和GL_OPERANDx_ALPHA(x是0,1,2)来修改操作数,修改的方式包括:

操作数修改方式 含义
GL_SRC_COLOR 颜色原RGB值
GL_ONE_MINUS_SRC_COLOR 1减去颜色原RGB值
GL_SRC_ALPHA 颜色原Alpha值
GL_ONE_MINUS_SRC_ALPHA 1减去颜色原Alpha值

通过上面的组合,模拟 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); 的效果:

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
    glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
    glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
 
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);

上面这些内容简单点说就是通过设置一个等式的各个参数和操作符 
glTex

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值