使用一个uniform变量作为mix函数的第三个参数来改变两个纹理可见度,使用上和下键来改变箱子或笑脸的可见度
fs.in

1 #version 330 core
2 out vec4 FragColor;
3
4 in vec3 ourColor;
5 in vec2 TexCoord;
6
7 // texture samplers
8 uniform sampler2D texture1;
9 uniform sampler2D texture2;
10 uniform float rate;
11
12 void main()
13 {
14 // linearly interpolate between both textures (80% container, 20% awesomeface)
15 FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), rate);
16 }
main函数

1 #include <glad/glad.h>
2 #include <GLFW/glfw3.h>
3 #define STB_IMAGE_IMPLEMENTATION
4 #include <stb/stb_image.h>
5
6 #include <Shader/shader.h>
7
8 #include <iostream>
9
10 void framebuffer_size_callback(GLFWwindow* window, int width, int height);
11 void processInput(GLFWwindow *window);
12
13 // settings
14 const unsigned int SCR_WIDTH = 800;
15 const unsigned int SCR_HEIGHT = 600;
16
17 float rate = 0.2f;
18
19 int main()
20 {
21 // glfw: initialize and configure
22 // ------------------------------
23 glfwInit();
24 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
25 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
26 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
27
28 #ifdef __APPLE__
29 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
30 #endif
31
32 // glfw window creation
33 // --------------------
34 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
35 if (window == NULL)
36 {
37 std::cout << "Failed to create GLFW window" << std::endl;
38 glfwTerminate();
39 return -1;
40 }
41 glfwMakeContextCurrent(window);
42 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
43
44 // glad: load all OpenGL function pointers
45 // ---------------------------------------
46 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
47 {
48 std::cout << "Failed to initialize GLAD" << std::endl;
49 return -1;
50 }
51
52 // build and compile our shader zprogram
53 // ------------------------------------
54 Shader ourShader("vs.in", "fs.in");
55
56 // set up vertex data (and buffer(s)) and configure vertex attributes
57 // ------------------------------------------------------------------
58 float vertices[] = {
59 // positions // colors // texture coords
60 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
61 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
62 -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
63 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
64 };
65 unsigned int indices[] = {
66 0, 1, 3, // first triangle
67 1, 2, 3 // second triangle
68 };
69 unsigned int VBO, VAO, EBO;
70 glGenVertexArrays(1, &VAO);
71 glGenBuffers(1, &VBO);
72 glGenBuffers(1, &EBO);
73
74 glBindVertexArray(VAO);
75
76 glBindBuffer(GL_ARRAY_BUFFER, VBO);
77 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
78
79 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
80 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
81
82 // position attribute
83 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
84 glEnableVertexAttribArray(0);
85 // color attribute
86 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
87 glEnableVertexAttribArray(1);
88 // texture coord attribute
89 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
90 glEnableVertexAttribArray(2);
91
92
93 // load and create a texture
94 // -------------------------
95 unsigned int texture1, texture2;
96 // texture 1
97 // ---------
98 glGenTextures(1, &texture1);
99 glBindTexture(GL_TEXTURE_2D, texture1);
100 // set the texture wrapping parameters
101 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
103 // set texture filtering parameters
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
106 // load image, create texture and generate mipmaps
107 int width, height, nrChannels;
108 stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
109 // The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
110 unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
111 if (data)
112 {
113 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
114 glGenerateMipmap(GL_TEXTURE_2D);
115 }
116 else
117 {
118 std::cout << "Failed to load texture" << std::endl;
119 }
120 stbi_image_free(data);
121 // texture 2
122 // ---------
123 glGenTextures(1, &texture2);
124 glBindTexture(GL_TEXTURE_2D, texture2);
125 // set the texture wrapping parameters
126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
128 // set texture filtering parameters
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
131 // load image, create texture and generate mipmaps
132 data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
133 if (data)
134 {
135 // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
136 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
137 glGenerateMipmap(GL_TEXTURE_2D);
138 }
139 else
140 {
141 std::cout << "Failed to load texture" << std::endl;
142 }
143 stbi_image_free(data);
144
145 // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
146 // -------------------------------------------------------------------------------------------
147 ourShader.use(); // don't forget to activate/use the shader before setting uniforms!
148 // either set it manually like so:
149 glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
150 // or set it via the texture class
151 ourShader.setInt("texture2", 1);
152
153
154
155 // render loop
156 // -----------
157 while (!glfwWindowShouldClose(window))
158 {
159 // input
160 // -----
161 processInput(window);
162
163 // render
164 // ------
165 glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
166 glClear(GL_COLOR_BUFFER_BIT);
167
168 // bind textures on corresponding texture units
169 glActiveTexture(GL_TEXTURE0);
170 glBindTexture(GL_TEXTURE_2D, texture1);
171 glActiveTexture(GL_TEXTURE1);
172 glBindTexture(GL_TEXTURE_2D, texture2);
173
174 // render container
175 ourShader.use();
176 ourShader.setFloat("rate", rate);
177 glBindVertexArray(VAO);
178 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
179
180 // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
181 // -------------------------------------------------------------------------------
182 glfwSwapBuffers(window);
183 glfwPollEvents();
184 }
185
186 // optional: de-allocate all resources once they've outlived their purpose:
187 // ------------------------------------------------------------------------
188 glDeleteVertexArrays(1, &VAO);
189 glDeleteBuffers(1, &VBO);
190 glDeleteBuffers(1, &EBO);
191
192 // glfw: terminate, clearing all previously allocated GLFW resources.
193 // ------------------------------------------------------------------
194 glfwTerminate();
195 return 0;
196 }
197
198 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
199 // ---------------------------------------------------------------------------------------------------------
200 void processInput(GLFWwindow *window)
201 {
202 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
203 glfwSetWindowShouldClose(window, true);
204 if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS){
205 rate += 0.001f;
206 if (rate > 1.0f)rate = 1.0f;
207 }
208 if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS){
209 rate -= 0.001f;
210 if (rate < 0.0f)rate = 0.0f;
211 }
212 }
213
214 // glfw: whenever the window size changed (by OS or user resize) this callback function executes
215 // ---------------------------------------------------------------------------------------------
216 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
217 {
218 // make sure the viewport matches the new window dimensions; note that width and
219 // height will be significantly larger than specified on retina displays.
220 glViewport(0, 0, width, height);
221 }
2019/11/27
