OpenGL教程:6. UV坐标系和利用stb_image库导入纹理贴图

之前的教程都是单一颜色的形状,这并不好看哈。所以我们给他增加个贴图!

stb_image库

我们利用stb_image读取纹理,其仓库地址:https://github.com/nothings/stb

注意我们只需要一个stb_image.h来读取纹理,其他库暂时是用不到的:

image-20230119165736827

UV坐标系

读取纹理需要用到UV坐标系。这个坐标系

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
//
// Created by inver on 2022/9/12.
//
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "Shader/Shader.h"

#include "stb/stb_image.h"

int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

GLFWwindow *window = glfwCreateWindow(800, 600, "纹理和材质", nullptr, nullptr);
if (window == nullptr) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);

if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
glfwTerminate();
return -1;
}

float vertices[] = {
// 顶点坐标 //颜色 //纹理坐标,注意x方向坐标轴为s,y方向坐标轴为T
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};

int indices[] = {
0, 1, 3,
1, 2, 3
};

unsigned int vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) nullptr);
glEnableVertexAttribArray(0);

// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (3 * sizeof(float)));
glEnableVertexAttribArray(1);

// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (6 * sizeof(float)));
glEnableVertexAttribArray(2);

// 下面的步骤不可以更换,要按照先生成纹理,然后读取文件的步骤
// 生成纹理、并绑定纹理0
unsigned int texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// 设置纹理对象的环绕方式、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 读取纹理图片
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
unsigned char *data = stbi_load("texture/happy.jpeg", &width, &height, &nrChannels,
0);
if (data) {
// --------JPEG需要设置对齐方式--------
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// --------JPEG需要设置对齐方式--------
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Error: Failed to Load Texture! \n";
}
stbi_image_free(data);

std::string vsh = "shaders/texture/texture.vsh";
std::string fsh = "shaders/texture/texture.fsh";
Shader shader(vsh, fsh);

glUniform1i(glGetUniformLocation(shader.id, "ourTexture"), 0);

while (!glfwWindowShouldClose(window)) {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

shader.use();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
}

顶点着色器

1
2
3
4
5
6
7
8
9
10
11
12
13
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main(){
gl_Position = vec4(aPos, 1.0f);
ourColor = aColor;
TexCoord = aTexCoord;
}

片元着色器

1
2
3
4
5
6
7
8
9
10
11
#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;

void main(){
FragColor = texture(ourTexture, TexCoord); //参数一为纹理,参数二为纹理坐标
}

OpenGL教程:6. UV坐标系和利用stb_image库导入纹理贴图

http://blog.inverseda.top/2022/11/05/ComputerGraphics/OpenGL/6.纹理/

Author

InverseDa

Posted on

2022-11-05

Updated on

2023-03-30

Licensed under

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×