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