opengl学习笔记
大作业要做这个,边学边做笔记
遇到的问题:
显示的纹理变成了黑白色,且存在纹理错位的情况,用wps裁剪了一下就好了,不知道为啥
代码解读:
顶点着色器
#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.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
// linearly interpolate between both textures (80% container, 20% awesomeface)
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}
旋转矩形
#define STB_IMAGE_IMPLEMENTATION
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <shader_s.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height)//回调函数,窗口改变的时候也应该调整视口
{
glViewport(0, 0, width, height);//设置OpenGL渲染窗口的尺寸大小
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
/*初始化*/
if(!glfwInit())return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/*定义窗口尺寸和名称*/
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//设置为当前上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//调整窗口大小的时候要调用调整视口的函数
//glad是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们都需要初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
Shader ourShader("5.1.transform.vs", "5.1.transform.fs");//生成顶点着色器 片段着色器
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[] = //每一行是画的三角形用到了vertices哪些点
{
0, 1, 3,//第一个
1, 2, 3 //第二个
};
unsigned int VBO, VAO, 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);//GL_ELEMENT_ARRAY_BUFFER用于处理索引
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);//开启了0这个通道
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//解释顶点数据 纹理坐标
glEnableVertexAttribArray(1);
/*下面用于加载纹理1*/
unsigned int texture1, texture2;
glGenTextures(1, &texture1);//生成纹理1
glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理1
// 为当前绑定的纹理对象设置环绕、过滤方式
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); //这句用来翻转图片y轴,因为图片y轴正方向的定义往往和opengl的相反,所以在加载图片前加上这一句
unsigned char *data = stbi_load("myTexturePic.jpg", &width, &height, &nrChannels, 0);
std::cout<<nrChannels<<std::endl;
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
/*下面用于加载纹理2*/
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);
data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
std::cout<<nrChannels<<std::endl;
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
/*-------------------------------上面是加载纹理-----------------------------------*/
ourShader.use(); //使用着色器
ourShader.setInt("texture1", 0);//设置纹理
ourShader.setInt("texture2", 1);
while (!glfwWindowShouldClose(window))//循环渲染
{
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//设置清空屏幕(就是运行glClear)用啥颜色
glClear(GL_COLOR_BUFFER_BIT);//清空屏幕
glActiveTexture(GL_TEXTURE0);//设置纹理单元
glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理目标
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glm::mat4 transform = glm::mat4(1.0f); // 单位矩阵
transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));//移动
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));//旋转
ourShader.use();
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");//获取着色器内某个参数的位置
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));//写入参数值
glBindVertexArray(VAO);//绑定顶点数组对象
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//用索引画,有6个点
glfwSwapBuffers(window);//交换缓冲(是一个储存所有颜色的大缓冲)
glfwPollEvents();//检查有没有键盘鼠标输入,有就调用回调函数
}
/*删除操作*/
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glfwTerminate();//释放之前分配的所有资源
return 0;
}
旋转立方体
#define STB_IMAGE_IMPLEMENTATION
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <shader_m.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height)//回调函数,窗口改变的时候也应该调整视口
{
glViewport(0, 0, width, height);//设置OpenGL渲染窗口的尺寸大小
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
/*初始化*/
if(!glfwInit())return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/*定义窗口尺寸和名称*/
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//设置为当前上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//调整窗口大小的时候要调用调整视口的函数
//glad是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们都需要初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);//开启更新深度缓冲区的功能,启动它,OpenGL就可以跟踪再Z轴上的像素
Shader ourShader("6.2.coordinate_systems.vs", "6.2.coordinate_systems.fs");//生成顶点着色器 片段着色器
float vertices[] = {//每一行是图形顶点坐标+纹理坐标
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,//前
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);//生成顶点数组对象
glGenBuffers(1, &VBO);//生成顶点缓冲对象
glBindVertexArray(VAO);//绑定顶点数组对象
glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲对象
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把用户定义的数据复制到当前绑定缓冲的函数
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//解释顶点数据 图形顶点坐标
glEnableVertexAttribArray(0);//开启了0这个通道
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//解释顶点数据 纹理坐标
glEnableVertexAttribArray(1);
/*下面用于加载纹理1*/
unsigned int texture1, texture2;
glGenTextures(1, &texture1);//生成纹理1
glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理1
// 为当前绑定的纹理对象设置环绕、过滤方式
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); //这句用来翻转图片y轴,因为图片y轴正方向的定义往往和opengl的相反,所以在加载图片前加上这一句
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
std::cout<<nrChannels<<std::endl;
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
/*下面用于加载纹理2*/
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);
data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
std::cout<<nrChannels<<std::endl;
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
/*-------------------------------上面是加载纹理-----------------------------------*/
ourShader.use();//使用着色器
ourShader.setInt("texture1", 0);//设置纹理
ourShader.setInt("texture2", 1);
while (!glfwWindowShouldClose(window))//循环渲染
{
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//设置清空屏幕(就是运行glClear)用啥颜色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空屏幕+深度缓冲
glActiveTexture(GL_TEXTURE0);//设置纹理单元
glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理目标
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
ourShader.use();
glm::mat4 model = glm::mat4(1.0f);//局部 -> 世界
glm::mat4 view = glm::mat4(1.0f);//世界 -> 观察
glm::mat4 projection = glm::mat4(1.0f);//观察 -> 裁剪
model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
projection = glm::perspective(glm::radians(45.0f)/*视野*/, (float)SCR_WIDTH / (float)SCR_HEIGHT/*宽高比*/, 0.1f/*近平面*/, 100.0f/*远平面*/);
unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model");//获取着色器内某个参数的位置
unsigned int viewLoc = glGetUniformLocation(ourShader.ID, "view");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));//写入参数值
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view[0][0]);
ourShader.setMat4("projection", projection);//更改矩阵
glBindVertexArray(VAO);//绑定顶点数组对象
glDrawArrays(GL_TRIANGLES, 0, 36);//用数组来画,36个点
glfwSwapBuffers(window);//交换缓冲(是一个储存所有颜色的大缓冲)
glfwPollEvents();//检查有没有键盘鼠标输入,有就调用回调函数
}
/*删除操作*/
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();//释放之前分配的所有资源
return 0;
}
有了移动功能
#define STB_IMAGE_IMPLEMENTATION
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <shader_m.h>
#include <iostream>
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);//位置
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);//朝向
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);//UP方向
bool firstMouse = true;
float yaw = -90.0f; // yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction vector pointing to the right so we initially rotate a bit to the left.
float pitch = 0.0f;
float lastX = 800.0f / 2.0;
float lastY = 600.0 / 2.0;
float fov = 45.0f;
float deltaTime = 0.0f; //计算两帧之间的时间差
float lastFrame = 0.0f;
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)//检查是否按住了esc
glfwSetWindowShouldClose(window, true);//按住了就关闭
float cameraSpeed = static_cast<float>(2.5 * deltaTime);//移动距离和每秒帧数有关,防止不同设备体验不一样
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPos += cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPos -= cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)//回调函数,窗口改变的时候也应该调整视口
{
glViewport(0, 0, width, height);//设置OpenGL渲染窗口的尺寸大小
}
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)//鼠标移动
{
float xpos = static_cast<float>(xposIn);
float ypos = static_cast<float>(yposIn);
if (firstMouse)//首次进入
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // 这里是相反的,因为俯仰角的0是竖直向上
lastX = xpos;
lastY = ypos;
float sensitivity = 0.1f; // 灵敏度
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;//偏航角
pitch += yoffset;//俯仰角
if (pitch > 89.0f)//仰角要有范围
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));//计算向量
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)//视野回调函数
{
fov -= (float)yoffset;
if (fov < 1.0f)//fov越小,视野越小,看见的越大
fov = 1.0f;
if (fov > 45.0f)
fov = 45.0f;
}
int main()
{
/*初始化*/
if(!glfwInit())return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/*定义窗口尺寸和名称*/
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//设置为当前上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//调整窗口大小的时候要调用调整视口的函数
glfwSetCursorPosCallback(window, mouse_callback);//鼠标移动的时候调用回调函数
glfwSetScrollCallback(window, scroll_callback);//鼠标滚轮的回调函数
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);//隐藏光标,并控制其不离开窗口
//glad是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们都需要初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);//开启更新深度缓冲区的功能,启动它,OpenGL就可以跟踪再Z轴上的像素
Shader ourShader("6.2.coordinate_systems.vs", "6.2.coordinate_systems.fs");//生成顶点着色器 片段着色器
float vertices[] = {//每一行是图形顶点坐标+纹理坐标
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,//前
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
// world space positions of our cubes
glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);//生成顶点数组对象
glGenBuffers(1, &VBO);//生成顶点缓冲对象
glBindVertexArray(VAO);//绑定顶点数组对象
glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲对象
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把用户定义的数据复制到当前绑定缓冲的函数
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//解释顶点数据 图形顶点坐标
glEnableVertexAttribArray(0);//开启了0这个通道
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//解释顶点数据 纹理坐标
glEnableVertexAttribArray(1);
/*下面用于加载纹理1*/
unsigned int texture1, texture2;
glGenTextures(1, &texture1);//生成纹理1
glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理1
// 为当前绑定的纹理对象设置环绕、过滤方式
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); //这句用来翻转图片y轴,因为图片y轴正方向的定义往往和opengl的相反,所以在加载图片前加上这一句
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
std::cout<<nrChannels<<std::endl;
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
/*下面用于加载纹理2*/
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);
data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
std::cout<<nrChannels<<std::endl;
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
/*-------------------------------上面是加载纹理-----------------------------------*/
ourShader.use();//使用着色器
ourShader.setInt("texture1", 0);//设置纹理
ourShader.setInt("texture2", 1);
while (!glfwWindowShouldClose(window))//循环渲染
{
float currentFrame = static_cast<float>(glfwGetTime());//当前运行的时间
deltaTime = currentFrame - lastFrame;//获得两帧间隔的时间
lastFrame = currentFrame;
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//设置清空屏幕(就是运行glClear)用啥颜色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空屏幕+深度缓冲
glActiveTexture(GL_TEXTURE0);//设置纹理单元
glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理目标
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
ourShader.use();
glm::mat4 projection = glm::perspective(glm::radians(fov)/*视野*/, (float)SCR_WIDTH / (float)SCR_HEIGHT/*宽高比*/, 0.1f/*近平面*/, 100.0f/*远平面*/);
ourShader.setMat4("projection", projection);//更改projection矩阵
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);//设置look矩阵
ourShader.setMat4("view", view);
glBindVertexArray(VAO);//绑定顶点数组对象
for (unsigned int i = 0; i < 10; i++)
{
glm::mat4 model = glm::mat4(1.0f); // 初始化为单位矩阵
model = glm::translate(model, cubePositions[i]);//移动
float angle = 20.0f * i;//确定旋转角度
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f)/*旋转轴*/);//旋转
ourShader.setMat4("model", model);//更改model矩阵
glDrawArrays(GL_TRIANGLES, 0, 36);//用数组来画,36个点
}
glfwSwapBuffers(window);//交换缓冲(是一个储存所有颜色的大缓冲)
glfwPollEvents();//检查有没有键盘鼠标输入,有就调用回调函数
}
/*删除操作*/
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();//释放之前分配的所有资源
return 0;
}
最终版本
/*
功能介绍
0随机纹理 1~5统一纹理 P显示全部 Q仅显示立方体 C清屏 R旋转 T放缩
esc退出 w a s d 移动
*/
#define STB_IMAGE_IMPLEMENTATION
#pragma comment(lib,"glew32.lib")
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
const unsigned int SCR_WIDTH = 1200;
const unsigned int SCR_HEIGHT = 900;
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f),cameraFront = glm::vec3(0.0f, 0.0f, -1.0f),cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);//位置 朝向 UP方向
bool firstMouse = true;
float pitch = 0.0f,yaw = -90.0f/*0是朝向右,-90是向后*/,lastX = 800.0f / 2.0,lastY = 600.0 / 2.0,fov = 45.0f,deltaTime = 0.0f,lastFrame = 0.0f;//俯仰角 偏航角 上一帧的鼠标位置 视野 计算两帧之间的时间差
int draw[6],revolve=0,amplify=0;//是否画图形 是否旋转 是否放大缩小
float angle=0.0f,times=0.0f;//用来计算旋转角度 放缩倍数
unsigned int texture[10],wenliHua[10];//加载纹理用 画纹理的时候用
class Shader//着色器用class包装一下
{
public:
unsigned int ID,vertex, fragment;//着色器程序(=顶点着色器+片段着色器)编号 顶点着色器编号 片段着色器编号
GLint success;
GLchar infoLog[1024];
void init()
{
const char* vertexShaderSource = "#version 330 core\n"//顶点着色器程序
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"uniform mat4 projection,view,model;\n"
"void main()\n"
"{\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0f);\n"//最终坐标要记得吧变化算上
" TexCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"//片段着色器程序
"out vec4 FragColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D texture1;\n"
"void main()\n"
"{\n"
" FragColor =texture(texture1, TexCoord);\n"
"}\0";
vertex = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器 CreateShader返回类型为unsigned int ,返回的是创建出的着色器的id
glShaderSource(vertex, 1, &vertexShaderSource, NULL);//将前面写的着色器源码(vertexShaderSource)附加给着色器对象(vertexShader)
glCompileShader(vertex);//编译这个着色器对象
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//检查顶点着色器对象是否编译成功
if (!success)
{
glGetShaderInfoLog(vertex, 1024, NULL, infoLog);
std::cout << "glGetShaderiv ERROR!" <<infoLog <<std::endl;
}
fragment = glCreateShader(GL_FRAGMENT_SHADER);//创建片段着色器
glShaderSource(fragment, 1, &fragmentShaderSource, NULL);//将前面写的着色器源码(vertexShaderSource)附加给着色器对象(vertexShader)
glCompileShader(fragment);//编译这个着色器对象
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);//检查顶点着色器对象是否编译成功
if (!success)
{
glGetShaderInfoLog(fragment, 1024, NULL, infoLog);
std::cout << "glGetShaderiv ERROR!" <<infoLog <<std::endl;
}
ID = glCreateProgram();//创建着色器程序对象,着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本。
glAttachShader(ID, vertex);//将前面创建的顶点着色器对象附加到着色器程序对象上
glAttachShader(ID, fragment);//将前面创建的片段着色器对象附加到着色器程序对象上
glLinkProgram(ID);//链接程序
glGetProgramiv(ID, GL_LINK_STATUS, &success);//检查链接过程中是否有错误
if (!success)
{
glGetProgramInfoLog(ID, 1024, NULL, infoLog);
std::cout << "glGetShaderiv ERROR!" <<infoLog <<std::endl;
}
glDeleteShader(vertex);//删除着色器对象,已经链接完了,不需要它们了
glDeleteShader(fragment);
}
void setInt(char name[], int value)
{
glUniform1i(glGetUniformLocation(ID, name)/*获取uniform变量tansform的地址 ,shaderProgram为前面定义的着色器程序*/, value);
}
void setMat4(char name[],glm::mat4 mat)
{
glUniformMatrix4fv(glGetUniformLocation(ID, name)/*变量的位置值*/, 1, GL_FALSE, &mat[0][0]);//通过glUniform4f函数设置uniform值
}
}myShader;
void processInput(GLFWwindow *window)//检查键盘情况
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)//检查是否按住了esc
glfwSetWindowShouldClose(window, true);//按住了就关闭
float cameraSpeed = static_cast<float>(2.5 * deltaTime);//移动距离和每秒帧数有关,防止不同设备体验不一样 static_cast是强制类型转化
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)cameraPos += cameraFront * cameraSpeed ;//前后左右移动
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)cameraPos -= cameraFront * cameraSpeed ;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS)draw[1]=draw[2]=draw[3]=draw[4]=draw[5]=1;//按住P 全画
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)draw[1]=1,draw[2]=draw[3]=draw[4]=draw[5]=0;//Q仅立方体
if (glfwGetKey(window, GLFW_KEY_C) == GLFW_PRESS)draw[1]=draw[2]=draw[3]=draw[4]=draw[5]=0;//C清屏
static float lastPressR=0;
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS&&(float)glfwGetTime()-lastPressR>0.5)revolve^=1,lastPressR=(float)glfwGetTime();//R 旋转
static float lastPressT=0;
if (glfwGetKey(window, GLFW_KEY_T) == GLFW_PRESS&&(float)glfwGetTime()-lastPressT>0.5)amplify^=1,lastPressT=(float)glfwGetTime();//T 收缩
static float lastPress0=0;//用随机纹理
if (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS&&(float)glfwGetTime()-lastPress0>0.5)for(int i=1;i<=5;++i)wenliHua[i]=texture[rand()*3%5],lastPress0=(float)glfwGetTime();
static float lastPress1=0;//用统一的几种纹理
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS&&(float)glfwGetTime()-lastPress1>0.5)for(int i=1;i<=5;++i)wenliHua[i]=texture[0],lastPress1=(float)glfwGetTime();
static float lastPress2=0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS&&(float)glfwGetTime()-lastPress2>0.5)for(int i=1;i<=5;++i)wenliHua[i]=texture[1],lastPress2=(float)glfwGetTime();
static float lastPress3=0;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS&&(float)glfwGetTime()-lastPress3>0.5)for(int i=1;i<=5;++i)wenliHua[i]=texture[2],lastPress3=(float)glfwGetTime();
static float lastPress4=0;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS&&(float)glfwGetTime()-lastPress4>0.5)for(int i=1;i<=5;++i)wenliHua[i]=texture[3],lastPress4=(float)glfwGetTime();
static float lastPress5=0;
if (glfwGetKey(window, GLFW_KEY_5) == GLFW_PRESS&&(float)glfwGetTime()-lastPress5>0.5)for(int i=1;i<=5;++i)wenliHua[i]=texture[4],lastPress5=(float)glfwGetTime();
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)//回调函数,窗口改变的时候也应该调整视口
{
glViewport(0, 0, width, height);//设置OpenGL渲染窗口的尺寸大小
}
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)//鼠标移动
{
float xpos = static_cast<float>(xposIn),ypos = static_cast<float>(yposIn);
if (firstMouse)lastX = xpos,lastY = ypos,firstMouse = false;//首次进入
float xoffset = (xpos - lastX)*0.1f,yoffset = (lastY - ypos)*0.1f; // yoffset是相反的,因为俯仰角的0是竖直向上 这里的0.1是灵敏度
yaw += xoffset,pitch += yoffset;pitch=std::max(pitch,-89.0f);pitch=std::min(pitch,89.0f);//偏航角 俯仰角 俯仰角要有范围
lastX = xpos;lastY = ypos;//计算完记得更新
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));//计算向量
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)//视野回调函数
{
fov -= (float)yoffset;
fov=std::max(fov,1.0f);fov=std::min(fov,45.0f);//fov越小,视野越小,看见的越大
}
void wenli(char name[],unsigned int &texture)//用来加载纹理
{
glGenTextures(1, &texture);//生成纹理
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); //这句用来翻转图片y轴,因为图片y轴正方向的定义往往和opengl的相反,所以在加载图片前加上这一句
unsigned char *data = stbi_load(name, &width, &height, &nrChannels, 0);//
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, nrChannels==3?GL_RGB:GL_RGBA/*注意一下看看是几通道*/, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);//生成多级渐远纹理
}
else std::cout << "纹理加载失败!" << std::endl;
stbi_image_free(data);//释放空间
}
void myDraw(int id,float posX,float posY,float posZ,float revolveX,float revolveY,float revolveZ,float revolveTimes,float scaleTimes,int beginPos,int num)
{
glm::mat4 model = glm::mat4(1.0f);
if(!draw[id])return;
glActiveTexture(GL_TEXTURE1);//设置纹理单元
glBindTexture(GL_TEXTURE_2D, wenliHua[id]);//绑定纹理目标
model = glm::translate(model, glm::vec3(posX, posY, posZ));//移动
model = glm::rotate(model, angle*revolveTimes, glm::vec3(revolveX, revolveY, revolveZ)/*旋转轴*/);//旋转
model = glm::scale(model, glm::vec3(1.0f+sin(times)*scaleTimes, 1.0f+sin(times)*scaleTimes, 1.0f+sin(times)*scaleTimes));//放缩
model = glm::translate(model, glm::vec3(-posX, -posY, -posZ));//移动
myShader.setMat4("model", model);//更改model矩阵
glDrawArrays(GL_TRIANGLES, beginPos,num);//用数组来画
}
int main()
{
/*初始化*/
if(!glfwInit())return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//确定版本为3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//使用核心模式
/*定义窗口尺寸和名称*/
GLFWwindow* window = glfwCreateWindow(1200, 900, "TuXing", NULL, NULL);
if (window == NULL)
{
std::cout << "glfwCreateWindow ERROR!" << std::endl;
glfwTerminate();//销毁窗口并释放资源
return -1;
}
glfwMakeContextCurrent(window);//设置为当前上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//调整窗口大小的时候要调用调整视口的函数
glfwSetCursorPosCallback(window, mouse_callback);//鼠标移动的时候调用回调函数
glfwSetScrollCallback(window, scroll_callback);//鼠标滚轮的回调函数
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);//隐藏光标,并控制其不离开窗口
if (glewInit() != 0)std::cout<<"glewInit() ERROR!"<<std::endl;
glEnable(GL_DEPTH_TEST);//开启更新深度缓冲区的功能,启动它,OpenGL就可以跟踪再Z轴上的像素
myShader.init();//生成顶点着色器 片段着色器
float vertices[] = {//每一行是图形顶点坐标+纹理坐标
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,//后
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,//前
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,//左
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,//右
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,//下
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,//上
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-2.5f, -0.5f, 0.5f, 0.0f, 0.0f,//长方形
-1.0f, -0.5f, 0.5f, 1.0f, 0.0f,
-1.0f, 0.5f, 0.5f, 1.0f, 1.0f,
-1.0f, 0.5f, 0.5f, 1.0f, 1.0f,
-2.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-2.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-2.5f, -0.5f, -0.5f, 0.0f, 0.0f,//长方形
-1.0f, -0.5f, -0.5f, 1.0f, 0.0f,
-1.0f, 0.5f, -0.5f, 1.0f, 1.0f,
-1.0f, 0.5f, -0.5f, 1.0f, 1.0f,
-2.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-2.5f, -0.5f, -0.5f, 0.0f, 0.0f,
1.0f, 0.65f, -0.5f, 0.0f,0.65f,//五角星1
1.7f, 0.65f, -0.5f, 0.7f,0.65f,
1.9f, 0.0f, -0.5f, 0.9f, 0.0f,
2.0f, 0.65f, -0.5f, 1.0f,0.65f,//五角星2
1.3f, 0.65f, -0.5f, 0.3f,0.65f,
1.1f, 0.0f, -0.5f, 0.1f, 0.0f,
1.25f, 0.4f, -0.5f, 0.25f, 0.4f,//五角星3
1.75f, 0.4f, -0.5f, 0.75f, 0.4f,
1.5f, 1.2f, -0.5f, 0.5f, 1.2f,
2.25f, 0.0f, -0.5f, 0.25f, 0.0f,//五边形1
2.5f, 1.0f, -0.5f, 0.5f, 1.0f,
2.0f, 0.55f, -0.5f, 0.0f,0.55f,
2.75f, 0.0f, -0.5f, 0.75f, 0.0f,//五边形2
2.5f, 1.0f, -0.5f, 0.5f, 1.0f,
3.0f, 0.55f, -0.5f, 1.0f,0.55f,
2.25f, 0.0f, -0.5f, 0.25f, 0.0f,//五边形3
2.75f, 0.0f, -0.5f, 0.75f, 0.0f,
2.5f, 1.0f, -0.5f, 0.5f, 1.0f
};
draw[1]=draw[2]=draw[3]=draw[4]=draw[5]=1;
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);//生成顶点数组对象
glGenBuffers(1, &VBO);//生成顶点缓冲对象
glBindVertexArray(VAO);//绑定顶点数组对象
glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲对象
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把用户定义的数据复制到当前绑定缓冲的函数
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//解释顶点数据 图形顶点坐标
glEnableVertexAttribArray(0);//开启了0这个通道
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//解释顶点数据 纹理坐标
glEnableVertexAttribArray(1);
wenli("tom.png",texture[0]);wenli("jerry.png",texture[1]);wenli("sunrise.png",texture[2]);wenli("sunflower.png",texture[3]);wenli("starry sky.png",texture[4]);//给纹理编号
glUseProgram(myShader.ID);//使用着色器
myShader.setInt("texture1", 1);//给着色器里的变量编号
wenliHua[0]=wenliHua[1]=wenliHua[2]=wenliHua[3]=wenliHua[4]=wenliHua[5]=texture[4];
while (!glfwWindowShouldClose(window))//循环渲染
{
float currentFrame = static_cast<float>(glfwGetTime());//当前运行的时间
deltaTime = currentFrame - lastFrame;//获得两帧间隔的时间
lastFrame = currentFrame;
processInput(window);//检查键盘情况
glClearColor(0.5f, 0.6f, 0.7f, 1.0f);//设置清空屏幕(就是运行glClear)用啥颜色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空屏幕+深度缓冲
glUseProgram(myShader.ID);//使用myShader着色器程序
glm::mat4 projection = glm::perspective(glm::radians(fov)/*视野*/, (float)SCR_WIDTH / (float)SCR_HEIGHT/*宽高比*/, 0.1f/*近平面*/, 100.0f/*远平面*/);
myShader.setMat4("projection", projection);//更改projection矩阵
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);//设置look矩阵
myShader.setMat4("view", view);
glBindVertexArray(VAO);//绑定顶点数组对象
if(revolve == 1)angle+=deltaTime;//angle 旋转角度
if(amplify == 1)times+=deltaTime;//times 收缩倍数
myDraw(1, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0, 36);
myDraw(2, 0.0f, 0.0f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 36, 6);
myDraw(3, 0.0f, 0.0f, -0.5f,-1.0f, 0.0f, 0.0f, 0.5f, 0.5f, 42, 6);
myDraw(4, 1.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 48, 9);
myDraw(5, 2.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 57, 9);
glfwSwapBuffers(window);//交换缓冲(是一个储存所有颜色的大缓冲)
glfwPollEvents();//检查有没有键盘鼠标输入,有就调用回调函数
}
/*删除操作*/
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();//释放之前分配的所有资源
return 0;
}