文章目录
- 环境
- 代码
- CMakeLists.txt文件内容不变。
- vertexShaderSource.vs
- main.cpp
- 总结
- 参考
环境
- 系统:ubuntu20.04
- opengl版本:4.6
- glfw版本:3.3
- glad版本:4.6
- cmake版本:3.16.3
- gcc版本:10.3.0
在<opengl学习日记10-opengl使用多个纹理示例>的基础上,进行修改,实现变换效果。
代码
CMakeLists.txt文件内容不变。
vertexShaderSource.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;uniform mat4 transform;void main()
{gl_Position = transform * vec4(aPos, 1.0f);
// gl_Position = vec4(aPos, 1.0);TexCoord = vec2(aTexCoord.x,1.0 - aTexCoord.y);
}
main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>#include "stbimage.h"#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>#include <iostream>
#include <fstream>
#include <iosfwd>
#include <sstream>
#include <string>//定义窗口大小
int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;std::string readFile(const std::string filename)
{std::string data;data = readFile(filename.c_str());return data;
}std::string readFile(const char* filename)
{std::string data;std::ifstream infile;infile.open(filename);std::stringstream neirong;neirong << infile.rdbuf();infile.close();data = neirong.str();return data;
}int main()
{std::cout << "Hello World!" << std::endl;std::cout << "初始化" << std::endl;glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "transformtions", NULL, NULL);if (window == NULL) {std::cout << "创建窗口失败" << std::endl;return -1;}glfwMakeContextCurrent(window);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "初始化glad失败" << std::endl;return -1;}std::cout << "顶点定义,VAO,VBO,EBO" << std::endl;float vertices[] = {0.5f, 0.5f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.0f, 0.0f, 1.0f };//索引缓冲区unsigned int indices[] = { 0, 1, 3,1, 2, 3 };unsigned int VAO, VBO, EBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//定位点关系glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);std::cout << "着色器定义" << std::endl;std::cout << "着色器定义:顶点着色器" << std::endl;std::string vertexShaderSource = readFile("vertexShaderSource.vs");const char* vertexShaderSourceCtr = vertexShaderSource.c_str();unsigned int vertexShader;vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSourceCtr, NULL);glCompileShader(vertexShader);int success;char infolog[512] = { 0 };glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertexShader, 512, NULL, infolog);std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"<< infolog << std::endl;}std::cout << "着色器定义:片段着色器" << std::endl;std::string fragmentShaderSource = readFile("fragmentShaderSource.fs");const char* fragmentShaderSourceCtr = fragmentShaderSource.c_str();unsigned int fragmentShader;fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSourceCtr, NULL);glCompileShader(fragmentShader);glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragmentShader, 512, NULL, infolog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"<< infolog << std::endl;}std::cout << "着色器定义:启用着色器程序" << std::endl;unsigned int shaderProgram;shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infolog);std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"<< infolog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);std::cout << "纹理定义" << std::endl;unsigned int texture1;glGenTextures(1, &texture1);glBindTexture(GL_TEXTURE_2D, texture1);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);stbi_set_flip_vertically_on_load(true);std::cout << "读取纹理图片" << std::endl;int width, height, nrChannels;unsigned char* texturesData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);if (texturesData) {//绑定和纹理图片数据结合glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,texturesData);glGenerateMipmap(GL_TEXTURE_2D);} else {std::cout << "读取图片数据错误" << std::endl;}stbi_image_free(texturesData);std::cout << "纹理定义2" << std::endl;unsigned int texture2;glGenTextures(1, &texture2);glBindTexture(GL_TEXTURE_2D, texture2);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);std::cout << "读取纹理图片" << std::endl;// int width, height, nrChannels;texturesData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);if (texturesData) {//绑定和纹理图片数据结合glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,texturesData);glGenerateMipmap(GL_TEXTURE_2D);} else {std::cout << "读取图片数据错误" << std::endl;}stbi_image_free(texturesData);glUseProgram(shaderProgram);glUniform1i(glGetUniformLocation((GLuint)shaderProgram, "texture1"), 0);glUniform1i(glGetUniformLocation((GLuint)shaderProgram, "texture2"), 1);// glm::mat4 trans = glm::mat4(1.0f);
// trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
// trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));std::cout << "绘制" << std::endl;while (!glfwWindowShouldClose(window)) {glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);glUseProgram(shaderProgram);glm::mat4 trans = glm::mat4(1.0f);trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *) 0);glfwSwapBuffers(window);glfwPollEvents();}std::cout << "内存释放" << std::endl;glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);glDeleteProgram(shaderProgram);glfwTerminate();return 0;
}
总结
- 对于矩阵变换效果,如果静态变换效果,例如旋转30度,可以将矩阵变换数据放置在绘制流程之外(while外面),如果是动态变换效果,例如连续旋转,则需要将矩阵变换数据放置在绘制流程内(while内)
静态效果
glm::mat4 trans = glm::mat4(1.0f);trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));std::cout << "绘制" << std::endl;while (!glfwWindowShouldClose(window)) {glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);glUseProgram(shaderProgram);// glm::mat4 trans = glm::mat4(1.0f);
// trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
// trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *) 0);glfwSwapBuffers(window);glfwPollEvents();}
动态效果
// glm::mat4 trans = glm::mat4(1.0f);
// trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
// trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));std::cout << "绘制" << std::endl;while (!glfwWindowShouldClose(window)) {glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);glUseProgram(shaderProgram);glm::mat4 trans = glm::mat4(1.0f);trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *) 0);glfwSwapBuffers(window);glfwPollEvents();}
- 做效果变换一般是改变顶点着色器的内容,顶点变换了,效果才会跟着变,所以绑定的全局shader变量是顶点着色器内的
unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
- 定义
glm::mat4
时,需要使用glm::mat4 trans = glm::mat4(1.0f);
的方式,在官网教程中示例使用glm::mat4 trans;
有误,会导致图像不显示