• OpenGL_Learn07(变换)


    1.  向量

    向量有一个方向和一个大小。如果一个向量有2个维度,它表示一个平面的方向(想象一下2D的图像),当它有3个维度的时候它可以表达一个3D世界的方向。

    可以把这些2D向量当做z坐标为0的3D向量。

    2. 向量内积和外积

    向量的点乘(内积):简单来说就是可以判断向量方向的相似性

    向量外积:简单来说就是可以得到其法向量

    3. 向量的加减和长度

    向量的加法可以被定义为是分量的(Component-wise)相加,即将一个向量中的每一个分量加上另一个向量的对应分量。

    v = (4, 2)k = (1, 2)相加得到(4+1,2+2)

    向量的减法等于加上第二个向量的相反向量。两个向量的相减会得到这两个向量指向位置的差。

    我们使用勾股定理(Pythagoras Theorem)来获取向量的长度(Length)/大小(Magnitude)。如果你把向量的x与y分量画出来,该向量会和x与y分量为边形成一个三角形。

    4. 旋转

    5. 代码实现旋转和缩放

    texture.vs

    1. #version 330 core
    2. layout (location = 0) in vec3 aPos;
    3. layout (location = 1) in vec2 aTexCorrd;
    4. out vec2 TexCoord;
    5. uniform mat4 transform;
    6. void main()
    7. {
    8. gl_Position = transform * vec4(aPos, 1.0);
    9. TexCoord=vec2(aTexCorrd.x,1.0-aTexCorrd.y);
    10. }

    texture.fs

    1. #version 330 core
    2. out vec4 FragColor;
    3. in vec3 ourColor;
    4. in vec2 TexCoord;
    5. uniform float mixValue;
    6. //texture sampler
    7. uniform sampler2D textureone;
    8. uniform sampler2D texturetwo;
    9. void main()
    10. {
    11. FragColor = mix(texture(textureone,TexCoord),texture(texturetwo,TexCoord),mixValue);
    12. }

    shader.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. class Shader {
    8. public:
    9. //程序ID
    10. unsigned int ID;
    11. //构造器读取并构建着色器
    12. Shader(const char* vertexPath, const char* fagmentPath) {
    13. std::string vertexCode;
    14. std::string fragmentCode;
    15. std::ifstream vShaderFile;
    16. std::ifstream fShaderFile;
    17. vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    18. fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    19. try {
    20. vShaderFile.open(vertexPath);
    21. fShaderFile.open(fagmentPath);
    22. std::stringstream vShaderStream, fShaderStream;
    23. vShaderStream << vShaderFile.rdbuf();
    24. fShaderStream << fShaderFile.rdbuf();
    25. vShaderFile.close();
    26. fShaderFile.close();
    27. vertexCode = vShaderStream.str();
    28. fragmentCode = fShaderStream.str();
    29. }
    30. catch (std::ifstream::failure& e) {
    31. std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
    32. }
    33. const char* vShaderCode = vertexCode.c_str();
    34. const char* fShaderCode = fragmentCode.c_str();
    35. //2.complie shaders
    36. unsigned int vertex, fragment;
    37. //vertex shader
    38. vertex = glCreateShader(GL_VERTEX_SHADER);
    39. glShaderSource(vertex, 1, &vShaderCode, NULL);
    40. glCompileShader(vertex);
    41. checkCompileErros(vertex, "VERTEX");
    42. //fragment Shader
    43. fragment = glCreateShader(GL_FRAGMENT_SHADER);
    44. glShaderSource(fragment, 1, &fShaderCode, NULL);
    45. glCompileShader(fragment);
    46. checkCompileErros(fragment, "FRAGMENT");
    47. //shader Program
    48. ID = glCreateProgram();
    49. glAttachShader(ID, vertex);
    50. glAttachShader(ID, fragment);
    51. glLinkProgram(ID);
    52. checkCompileErros(ID, "PROGAM");
    53. glDeleteShader(vertex);
    54. glDeleteShader(fragment);
    55. }
    56. //使用/激活程序
    57. void use() {
    58. glUseProgram(ID);
    59. }
    60. //uniform工具函数
    61. void setBool(const std::string& name, bool value) const {
    62. glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
    63. }
    64. void setInt(const std::string& name, int value) const {
    65. glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
    66. }
    67. void setFloat(const std::string& name, float value) const {
    68. glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
    69. }
    70. private:
    71. void checkCompileErros(unsigned int shader, std::string type) {
    72. int success;
    73. char infoLog[1024];
    74. if (type != "PROGRAM") {
    75. glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    76. if (!success) {
    77. glGetShaderInfoLog(shader, 1024, NULL, infoLog);
    78. std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
    79. }
    80. }
    81. else
    82. {
    83. glGetProgramiv(shader, GL_LINK_STATUS, &success);
    84. if (!success)
    85. {
    86. glGetProgramInfoLog(shader, 1024, NULL, infoLog);
    87. std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
    88. }
    89. }
    90. }
    91. };

    main.cpp

    下载glm

    Tags · g-truc/glm (github.com)

    1. #include
    2. #include
    3. #include
    4. #include "stb_image.h"
    5. #include
    6. #include "shader.h"
    7. #include
    8. #include
    9. #include
    10. void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    11. void processInput(GLFWwindow* window);
    12. // settings
    13. const unsigned int SCR_WIDTH = 800;
    14. const unsigned int SCR_HEIGHT = 600;
    15. float mixValue = 0.2f;
    16. int main() {
    17. //1.初始化配置
    18. glfwInit();
    19. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    20. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    21. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    22. #ifdef __APPLE__
    23. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
    24. #endif // __APPLE__
    25. //2.gltf 窗口创建
    26. GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LeranOpenGL", NULL, NULL);
    27. if (window == NULL) {
    28. std::cout << "Failed to create GLFW window" << std::endl;
    29. glfwTerminate();
    30. return -1;
    31. }
    32. glfwMakeContextCurrent(window);
    33. glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    34. //3. 加载所有GL函数指针
    35. if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
    36. std::cout << "Failed to initialize GLAD" << std::endl;
    37. return -1;
    38. }
    39. Shader ourShader("./texture.vs", "./texture.fs");
    40. //4. 设置顶点数据
    41. float vertices[] = {
    42. // positions // colors // texture coords
    43. 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right
    44. 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right
    45. -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left
    46. -0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left
    47. };
    48. unsigned int indices[] = {
    49. 0, 1, 3, // first triangle
    50. 1, 2, 3 // second triangle
    51. };
    52. unsigned int VBO, VAO, EBO;
    53. glGenVertexArrays(1, &VAO);
    54. glGenBuffers(1, &VBO);
    55. glGenBuffers(1,&EBO);//元素缓冲对象:Element Buffer Object,EBO
    56. glBindVertexArray(VAO);
    57. //复制顶点数组到缓冲区中供opengl使用
    58. glBindBuffer(GL_ARRAY_BUFFER, VBO);
    59. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    60. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    61. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    62. //设置顶点属性指针
    63. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    64. glEnableVertexAttribArray(0);
    65. //设置纹理属性指针
    66. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    67. glEnableVertexAttribArray(1);
    68. //加载和创建纹理
    69. unsigned int textureone,texturetwo;
    70. glGenTextures(1, &textureone);
    71. glBindTexture(GL_TEXTURE_2D, textureone);
    72. //设置纹理环绕参数
    73. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    74. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    75. //设置纹理过滤参数
    76. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    77. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    78. //加载图像和生成mipmaps
    79. int width, height, nrChannels;
    80. stbi_set_flip_vertically_on_load(true);
    81. std::string filePath = R"(D:\CPlusProject\LearnOpenGL\DataSet\container.jpg)";
    82. unsigned char* data = stbi_load(filePath.c_str(), &width, &height, &nrChannels, 0);
    83. if (data) {
    84. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    85. glGenerateMipmap(GL_TEXTURE_2D);
    86. }
    87. else {
    88. std::cout << "Failed to load texture" << std::endl;
    89. }
    90. stbi_image_free(data);
    91. glGenTextures(1, &texturetwo);
    92. glBindTexture(GL_TEXTURE_2D, texturetwo);
    93. //设置纹理环绕参数
    94. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    95. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    96. //设置纹理过滤参数
    97. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    98. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    99. //加载图像和生成mipmaps
    100. filePath = R"(D:\CPlusProject\LearnOpenGL\DataSet\awesomeface.png)";
    101. unsigned char* data2 = stbi_load(filePath.c_str(), &width, &height, &nrChannels, 0);
    102. if (data2) {
    103. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
    104. glGenerateMipmap(GL_TEXTURE_2D);
    105. }
    106. else {
    107. std::cout << "Failed to load texture" << std::endl;
    108. }
    109. stbi_image_free(data2);
    110. ourShader.use();
    111. glUniform1i(glGetUniformLocation(ourShader.ID, "textureone"), 0);//二选一
    112. ourShader.setInt("texturetwo", 1);//二选一
    113. //glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
    114. 译注:下面就是矩阵初始化的一个例子,如果使用的是0.9.9及以上版本
    115. //glm::mat4 trans = glm::mat4(1.0f);
    116. //trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
    117. //vec = trans * vec;
    118. //std::cout << vec.x << vec.y << vec.z << std::endl;
    119. glm::mat4 trans = glm::mat4(1.0f);
    120. trans = glm::rotate(trans, glm::radians(90.f), glm::vec3(0.0, 0.0, 1.0));
    121. trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));
    122. unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
    123. glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
    124. //5. 循环渲染
    125. while (!glfwWindowShouldClose(window)) {
    126. processInput(window);
    127. // render
    128. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    129. glClear(GL_COLOR_BUFFER_BIT);
    130. //绑定纹理
    131. glActiveTexture(GL_TEXTURE0);
    132. glBindTexture(GL_TEXTURE_2D, textureone);
    133. glActiveTexture(GL_TEXTURE1);
    134. glBindTexture(GL_TEXTURE_2D, texturetwo);
    135. ourShader.setFloat("mixValue", mixValue);
    136. ourShader.use();
    137. glBindVertexArray(VAO);
    138. glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
    139. glfwSwapBuffers(window);
    140. glfwPollEvents();
    141. }
    142. glDeleteVertexArrays(1, &VAO);
    143. glDeleteBuffers(1, &VBO);
    144. glDeleteBuffers(1, &EBO);
    145. glfwTerminate();
    146. return 0;
    147. }
    148. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
    149. // ---------------------------------------------------------------------------------------------------------
    150. void processInput(GLFWwindow* window)
    151. {
    152. if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    153. glfwSetWindowShouldClose(window, true);
    154. if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
    155. std::cout << "up" << std::endl;
    156. mixValue += 0.001f;
    157. if (mixValue >= 1.0f) {
    158. mixValue = 1.0f;
    159. }
    160. }
    161. if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
    162. {
    163. std::cout << "down" << std::endl;
    164. mixValue -= 0.001f; // change this value accordingly (might be too slow or too fast based on system hardware)
    165. if (mixValue <= 0.0f)
    166. mixValue = 0.0f;
    167. }
    168. std::cout << "mixValue:" << mixValue <
    169. }
    170. // glfw: whenever the window size changed (by OS or user resize) this callback function executes
    171. // ---------------------------------------------------------------------------------------------
    172. void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    173. {
    174. // make sure the viewport matches the new window dimensions; note that width and
    175. // height will be significantly larger than specified on retina displays.
    176. glViewport(0, 0, width, height);
    177. }

    6. 持续旋转

    要让箱子随着时间推移旋转,我们必须在游戏循环中更新变换矩阵。也就是在while结构体中。

    在这里我们先把箱子围绕原点(0, 0, 0)旋转,之后,我们把旋转过后的箱子位移到屏幕的右下角。

    1. //5. 循环渲染
    2. while (!glfwWindowShouldClose(window)) {
    3. processInput(window);
    4. // render
    5. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    6. glClear(GL_COLOR_BUFFER_BIT);
    7. //绑定纹理
    8. glActiveTexture(GL_TEXTURE0);
    9. glBindTexture(GL_TEXTURE_2D, textureone);
    10. glActiveTexture(GL_TEXTURE1);
    11. glBindTexture(GL_TEXTURE_2D, texturetwo);
    12. ourShader.setFloat("mixValue", mixValue);
    13. glm::mat4 trans = glm::mat4(1.0f);
    14. trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
    15. trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
    16. unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
    17. glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
    18. ourShader.use();
    19. glBindVertexArray(VAO);
    20. glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
    21. glfwSwapBuffers(window);
    22. glfwPollEvents();
    23. }

    7. 先平移后旋转And先旋转后平移

    上面的例子是先平移后旋转,下面的代码是先旋转后平移

    1. //5. 循环渲染
    2. while (!glfwWindowShouldClose(window)) {
    3. processInput(window);
    4. // render
    5. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    6. glClear(GL_COLOR_BUFFER_BIT);
    7. //绑定纹理
    8. glActiveTexture(GL_TEXTURE0);
    9. glBindTexture(GL_TEXTURE_2D, textureone);
    10. glActiveTexture(GL_TEXTURE1);
    11. glBindTexture(GL_TEXTURE_2D, texturetwo);
    12. ourShader.setFloat("mixValue", mixValue);
    13. glm::mat4 trans = glm::mat4(1.0f);
    14. //先平移后旋转
    15. //trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
    16. //trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
    17. //先旋转后平移
    18. trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
    19. trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
    20. unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
    21. glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
    22. ourShader.use();
    23. glBindVertexArray(VAO);
    24. glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
    25. glfwSwapBuffers(window);
    26. glfwPollEvents();
    27. }

    8. 绘制两个三角形,不同的显示方式

    尝试再次调用glDrawElements画出第二个箱子,使用变换将其摆放在不同的位置。让这个箱子被摆放在窗口的左上角,并且会不断的缩放(而不是旋转)。(sin函数在这里会很有用,不过注意使用sin函数时应用负值会导致物体被翻转)。

    1. //5. 循环渲染
    2. while (!glfwWindowShouldClose(window)) {
    3. processInput(window);
    4. // render
    5. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    6. glClear(GL_COLOR_BUFFER_BIT);
    7. //绑定纹理
    8. glActiveTexture(GL_TEXTURE0);
    9. glBindTexture(GL_TEXTURE_2D, textureone);
    10. glActiveTexture(GL_TEXTURE1);
    11. glBindTexture(GL_TEXTURE_2D, texturetwo);
    12. ourShader.setFloat("mixValue", mixValue);
    13. glm::mat4 trans = glm::mat4(1.0f);
    14. //先平移后旋转
    15. //trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
    16. //trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
    17. //先旋转后平移
    18. trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
    19. trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
    20. unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
    21. glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
    22. ourShader.use();
    23. glBindVertexArray(VAO);
    24. glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
    25. //second transformation
    26. trans = glm::mat4(1.0f);
    27. trans = glm::translate(trans, glm::vec3(-0.5f, 0.5f, 0.0f));
    28. float scaleAmount = static_cast<float>(sin(glfwGetTime()));
    29. trans = glm::scale(trans, glm::vec3(scaleAmount, scaleAmount, scaleAmount));
    30. glUniformMatrix4fv(transformLoc, 1, GL_FALSE, &trans[0][0]);// this time take the matrix value array's first element as its memory pointer value
    31. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    32. glfwSwapBuffers(window);
    33. glfwPollEvents();
    34. }

    向量点乘与叉乘的概念及几何意义 - 知乎 (zhihu.com)

    变换 - LearnOpenGL CN (learnopengl-cn.github.io)

  • 相关阅读:
    古记事法:Windows 下 16 位汇编环境搭建指南(DOSBox-X 篇)
    文件上传漏洞
    Https握手过程
    【LittleXi】C程序预处理、编译、汇编、链接步骤
    【AtCoder Beginner Contest 260 (A·B·C)】
    Selenium java 控制当前已经打开的 chrome浏览器窗口
    【JS】—垃圾回收机制
    指针笔试题讲解(让指针变得简单易懂)
    postgresql参数优化
    下载安装 VMware &虚拟机
  • 原文地址:https://blog.csdn.net/qq_59068750/article/details/134235558