glTexEnv

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

该函数是一个函数簇,根据具体的参数类型来决定使用哪个版本的函数。 
参数描述: 
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图像格式 )包括有以下几种

纹理的基本格式 颜色成分 Cs Alpha成分 As
GL_ALPHA (0, 0, 0, 0) At
GL_LUMINANCE ( Lt , Lt , Lt ) 1
GL_LUMINANCE_ALPHA ( Lt , Lt , Lt ) At
GL_INTENSITY ( It , It , It ) It
GL_RGB ( Rt , Gt , Bt ) 1
GL_RGBA ( Rt , Gt , Bt ) At

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

#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;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197

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 Cv  = Cp Cp 未定义 Cp Cp
  Av  = As As * Ap 未定义 As * Ap As * Ap
GL_LUMINANCE(或者1) Cv  = Cs Cp * Cs 未定义 Cp(1Cs)+CcCs Cp+Cs
  Av  = Ap Ap 未定义 Ap Ap
GL_LUMINANCE_ALPHA(或者2) Cv  = Cs Cp * Cs 未定义 Cp(1Cs)+CcCs Cp+Cs
  Av  = As As * Ap 未定义 As * Ap As * Ap
GL_INTENSITY Cv  = Cs Cp * Cs 未定义 Cp(1Cs)+CcCs Cp+Cs
  Av  = As As * Ap 未定义 Ap(1As)+AcAs Ap+As
GL_RGB(或者3) Cv  = Cs CpCs Cs Cp(1Cs)+CcCs Cp+Cs
  Av  = Ap Ap Ap Ap Ap
GL_RGBA(或者4) Cv  = Cs CpCs Cp(1As)+CsAs Cp(1Cs)+CcCs C_p+C_s
  Av  = As ApAs Ap ApAs ApAs

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

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

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
   
   
  • 1
  • 1

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

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

各种不同参数的含义 
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);
   
   
  • 1
  • 1

除此之外,还可以对操作数做一些修改,使用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);
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值