OpenGL(七)-纹理(上)

设定金字塔坐标

金字塔.png
注意纹理坐标的设置方式:

1
2
3
4
5
6
7
//设置顶点对应的纹理坐标
// s , t 相当于 x , y
// MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
//参数1:纹理的层次
//参数2:s坐标
//参数3:t坐标
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

绘制金字塔纹理

1.顶点/纹理坐标数据设置及图形绘制
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
GLBatch             pyramidBatch;//绘制批次类
//1.pyramidBatch
//通过三角形批次类pyramidBatch 来组件图形
//参数1:类型
//参数2:顶点数 6 * 3 = 18
//参数3:需要使用到纹理,默认为0,可以不写这个参数
pyramidBatch.Begin(GL_TRIANGLES, 18,1);

//2.金字塔各个面的点坐标设置

//金字塔底部
//底部四边形 = 三角形X + 三角形Y
//三角形X
//----------vBlackLeft------------
//设置法线坐标-光照
pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);

//设置顶点对应的纹理坐标
// MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
//参数1:纹理的层次
//参数2:s坐标
//参数3:t坐标
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

//设置顶点坐标
pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);

//------vBackRight------------
pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3f(1.0f, -1.0f, -1.0f);

//------vFrontRight点------------
pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);


//三角形Y
pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
pyramidBatch.Vertex3f(-1.0f, -1.0f, 1.0f);

pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);

pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);

//塔顶
M3DVector3f vApex = {0.0f,1.0f,0.0f};
M3DVector3f vFrontLeft = {-1.0f,-1.0f,1.0f};
M3DVector3f vFrontRight = {1.0f,-1.0f,1.0f};
M3DVector3f vBackLeft = {-1.0f,-1.0f,-1.0f};
M3DVector3f vBackRight = {1.0f,-1.0f,-1.0f};

//目的:为了临时存储法线向量
M3DVector3f n;

//金字塔的前面
//三角形:(Apex,vFrontLeft,vFrontRight)

//找法线
//m3dFindNormal(M3DVector3f result, const M3DVector3f point1, const M3DVector3f point2,const M3DVector3f point3);
//参数1:结果
//参数2-4:3个顶点
m3dFindNormal(n, vApex, vFrontLeft, vFrontRight);

//vApex
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.5, 1.0f);
pyramidBatch.Vertex3fv(vApex);

//vFrontLeft
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontLeft);

//vFrongRight
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontRight);


//金字塔的左边
//三角形:(Apex,vBackLeft,vFrontLeft)
m3dFindNormal(n, vApex, vBackLeft, vFrontLeft);

//vApex
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);

//vBackLeft
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackLeft);

//vFrontLeft
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontLeft);

//金字塔右边
//三角形:(vApex, vFrontRight, vBackRight)
m3dFindNormal(n, vApex, vFrontRight, vBackRight);
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);

pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontRight);

pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackRight);

//金字塔后边
//三角形:(vApex, vBackRight, vBackLeft)
m3dFindNormal(n, vApex, vBackRight, vBackLeft);
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);

pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackRight);

pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackLeft);

//结束批次设置
pyramidBatch.End();
2.加载2D纹理
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
// 将TGA文件加载为2D纹理。
//参数1:纹理文件名称
//参数2:缩小时过滤器使用的哪一种
//参数3:放大小时过滤器使用的哪一种
//参数4:纹理坐标环绕方式
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
GLbyte *pBits;
int nWidth,nHeight,nComponents;
GLenum eFormat;

//1.读取纹理的像素
//参数1:纹理文件的名称
//参数2:文件的宽度地址
//参数3:文件的高度地址
//参数4:文件的组件地址
//参数5:文件格式地址
//返回值:pBits ,指向图像数据的指针
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);

if (pBits == NULL) {

printf("读取纹理像素失败\n");
return false;
}

//2.设置纹理参数
//设置s,t的环绕方式
//glTexParameteri (GLenum target, GLenum pname, GLint param);
//参数1:纹理维度
//参数2:为S/T坐标设置环绕模式
//参数3:wrapMode,环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);

//设置放大\缩小的过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);


//3.精密包装像素数据
//glPixelStorei (GLenum pname, GLint param);
//参数1:GL_UNPACK_ALIGNMENT ,OpenGL 如何从数据缓存区中解包图像数据
//参数2:设置GL_UNPACK_ALIGNMENT的值
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

//4.载入纹理
//glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
//参数1:纹理的维度
//参数2:mip贴图层次
//参数3:加载纹理颜色成分(从读取像素图获取的)
//参数4:加载纹理的宽
//参数5:加载纹理的高
//参数6:纹理的边框
//参数7:像素数据的类型
//参数8:指向纹理数据的指针
//详细可参考PPT
glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);


//使用完释放
free(pBits);

//只有minFilter 等于以下四种模式,才可以生成Mip贴图
//GL_NEAREST_MIPMAP_NEAREST具有非常好的性能,并且闪烁现象非常弱
//GL_LINEAR_MIPMAP_NEAREST常常用于对游戏进行加速,它使用了高质量的线性过滤器
//GL_LINEAR_MIPMAP_LINEAR 和GL_NEAREST_MIPMAP_LINEAR 过滤器在Mip层之间执行了一些额外的插值,以消除他们之间的过滤痕迹。
//GL_LINEAR_MIPMAP_LINEAR 三线性Mip贴图。纹理过滤的黄金准则,具有最高的精度。
if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)

//加载Mip,纹理生成所有的Mip层
//参数:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);


return true;
}
3.SetUp
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
void SetupRC()
{

glClearColor(0.7f, 0.7f,0.7f, 1.0f);

shaderManager.InitializeStockShaders();

//开启深度测试
glEnable(GL_DEPTH_TEST);

//纹理对象的处理
//1.分配纹理对象
// glGenTextures (GLsizei n, GLuint *textures);
//参数1:纹理对象的个数
//参数2:纹理对象的指针
glGenTextures(1, &textureID);

//2.绑定纹理状态
//glBindTexture (GLenum target, GLuint texture);
//参数1:纹理的状态,GL_TEXTURE_1D\GL_TEXTURE_2D\GL_TEXTURE_3D
glBindTexture(GL_TEXTURE_2D, textureID);


//3.将TGA文件加载成2D纹理
//函数是开发者自己设计的
//参数1:纹理文件名称
//参数2:缩小时过滤器使用的哪一种
//参数3:放大小时过滤器使用的哪一种
//参数4:纹理坐标环绕方式
LoadTGATexture("brick.tga", GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);

//4.设置渲染图像的顶点--金字塔
MakePyramid(pyramidBatch);

cameraFrame.MoveForward(-10.0);

}
4.渲染
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
void RenderScene(void)
{
//光照位置
static GLfloat vLightPos[] = {1.0f,1.0f,0.0f};

//关照颜色
static GLfloat vWhite[] = {1.0f,0.0f,0.0f,1.0f};

//glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER|GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

modelViewMatrix.PushMatrix();

//观察者
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);

//
M3DMatrix44f mObjectFrame;
objectFrame.GetMatrix(mObjectFrame);
modelViewMatrix.MultMatrix(mObjectFrame);

//错误地方!!!
//glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, textureID);


//点光源着色器
//参数1:GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF
//参数2:模型视图矩阵
//参数3:投影矩阵
//参数4:光源的位置
//参数5:光的颜色
//参数6:图形颜色(如使用了纹理,则设置为0)
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vWhite,0);


pyramidBatch.Draw();

modelViewMatrix.PopMatrix();

glutSwapBuffers();



}
效果图

image.png
image.png

谢谢你赏我糖果吃