当前位置:网站首页>OpenGL Chapter 9 lighting map
OpenGL Chapter 9 lighting map
2022-06-11 03:34:00 【Carefree young heart】
//LightingMaps
#include "Shader.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow* window);
// settings
const unsigned int SCR_WIDTH = 800; // Define the size of screen space
const unsigned int SCR_HEIGHT = 600;
// camera
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);
bool firstMouse = true;
float yaw = -90.0f; // Yaw is initialized to -90.0 degree , Because the yaw is 0.0 Will result in a direction vector pointing to the right , So we initially rotated a little to the left .
float pitch = 0.0f; // Initialize pitch angle
float lastX = 800.0f / 2.0;// In order to set the initial position as the center of the screen, take half the size of the screen space
float lastY = 600.0 / 2.0;
float fov = 45.0f;// Initial field angle
// timing
float deltaTime = 0.0f; // time between current frame and last frame
float lastFrame = 0.0f;
//glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
void processInput(GLFWwindow* window);
float vertices[] = {
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
// Define a vec3 Type array to store the displacement matrix
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)
};
int main()
{
//Glfw: Initialization and configuration
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
//glfw Window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);// Use the size of the defined screen space
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// First we have to tell GLFW, It should hide the cursor , And capture (Capture) it .
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Load all OpenGL A function pointer
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Configure global opengl state
// -----------------------------
glEnable(GL_DEPTH_TEST);
// Build and compile our shader Program
// ------------------------------------
Shader ourShader("shaderSampler.vs", "shaderSampler.fs");
Shader modelShader("LightingMaps.vs", "LightingMaps.fs");
Shader lightShader("lightShader.vs", "lightShader.fs");
// Create and compile vertex data ( And buffer ), Configure vertex attributes
// ------------------------------------------------------------------
unsigned int VBO, VAO,VAO2;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(VAO);
// Location properties
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Then in the vertex shader layout (location = 1) in vec3 aNormal;// tell GPU Location 1 Properties of
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
// Location properties
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Normal attributes
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// Load and create a texture
// -------------------------
unsigned int texture1, texture2;
// texture 1
// ---------
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// Set the texture wrapping Parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set the texture filtering Parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load image , Create textures and generate mipmaps // Multi level principle texture
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true); // tell stb_image.h stay y Flip the loaded texture on the axis .
// Why do you need to flip Y The axis is because the starting position of the texture image is the upper right and the coordinates of our vertices (0,0) The point is lower left
unsigned char* data = stbi_load("container2.png", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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);
// texture 2
// ---------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// Set the texture wrapping Parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set the texture filtering Parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
//data = stbi_load(("aotu.jpg"), &width, &height, &nrChannels, 0);
//data = stbi_load(("shanshui.jpg"), &width, &height, &nrChannels, 0);
data = stbi_load(("container2_specular.png"), &width, &height, &nrChannels, 0);
if (data)
{
// If there is no map, please give priority to this RGBA Medium alpha(A) passageway If your map has alpha Please be sure to use RGBA Otherwise, the map cannot be displayed
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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);
// Tell... For each sampler opengl Which texture unit does it belong to ( Just do it once )
// -------------------------------------------------------------------------------------------
modelShader.use();
modelShader.setInt("material.diffuse", 0);
modelShader.setInt("material.specular", 1);
// ourShader.setVec3("lightPos", lightPos);
// Render loop
// -----------
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// -----
processInput(window);
// Rendering
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the color buffer of the previous frame as well as Depth test buffer
// bind textures on corresponding texture units
// Activate shader
float angle = 20.0f * 0 * (float)glfwGetTime();// Give me a glfwGetTime Let the model rotate
glm::mat4 projection = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 model = glm::mat4(1.0f);
glm::vec3 lightPos = glm::vec3(cubePositions[2]);// Light source location
ourShader.use();
projection = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);// Projection matrix Parameters : Viewport size , Screen aspect ratio , as well as near and far
view = glm::lookAt(cameraPos, cameraPos+cameraFront, cameraUp);//lookAt matrix Parameters : Camera position , Observe the position of the target , A vertical upward direction
model = glm::translate(model, cubePositions[0]);// Pass in the array to each new model, which has different displacement in world coordinates
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
lightShader.use();
lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f;
lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f;
model = glm::mat4(1.0f);
model = glm::translate(model, lightPos);// Pass in the array to each new model, which has different displacement in world coordinates
angle = 20.0f * 2 * (float)glfwGetTime();// Give me a glfwGetTime Let the model rotate
model = glm::rotate(model, glm::radians(angle) * 0, glm::vec3(1.0f, 0.3f, 0.5f));
lightShader.setMat4("model", model);
lightShader.setMat4("projection", projection);
lightShader.setMat4("view", view);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
modelShader.use();
model = glm::mat4(1.0f);
model = glm::translate(model, cubePositions[0]);// Pass in the array to each new model, which has different displacement in world coordinates
angle = 20.0f * 1 * (float)glfwGetTime();// Give me a glfwGetTime Let the model rotate
model = glm::rotate(model, glm::radians(angle)*0, glm::vec3(1.0f, 0.5f, 0.5f));//rotate Model location Rotation angle Rotation axis
modelShader.setMat4("model", model);// Set the model transformation matrix
modelShader.setMat4("projection", projection);// Set the projection change matrix
modelShader.setMat4("view", view);// Set the view change matrix
modelShader.setVec3("objectColor",1,0.5,0.5);// Set the color of the object
modelShader.setVec3("lightColor", 1, 1, 1);// Set the color of the light source. Of course, you can also set a uniform To set variables
modelShader.setVec3("lightPos", lightPos);// Set the light source position
modelShader.setVec3("viewPos", cameraPos);// Set the position of the camera to the viewing position
// Set each component of the material
//modelShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
// modelShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
//modelShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
modelShader.setFloat("material.shininess", 32.0f);
modelShader.setVec3("light.ambient", 1.0f, 1.0f, 1.0f);
modelShader.setVec3("light.diffuse", 1.0f, 1.0f, 1.0f); // Dim the light a little to match the scene
modelShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
modelShader.setVec3("light.position", lightPos);
glm::vec3 lightColor;
lightColor.x = sin(glfwGetTime() * 2.0f);
lightColor.y = sin(glfwGetTime() * 0.7f);
lightColor.z = sin(glfwGetTime() * 1.3f);
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // Reduce the impact
glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // Very low impact
modelShader.setVec3("light.ambient", ambientColor);
modelShader.setVec3("light.diffuse", diffuseColor);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glBindVertexArray(VAO2);
glDrawArrays(GL_TRIANGLES, 0, 36);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
float cameraSpeed = 5.5f * deltaTime;; // adjust accordingly
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;
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)// Here is a space bar so that we can Y Move on the axis
cameraPos += cameraUp * cameraSpeed;
//cameraPos.y = 0.0f;
// You can do this by Y The vector in the direction is set to 0 Make him FPS This type of camera can only be used in XZ Move on the plane
}
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{
float xpos = static_cast<float>(xposIn);
float ypos = static_cast<float>(yposIn);
// This bool The variable is initially set to true Of
// We need to set it as the center of the screen at the beginning
// If you don't do this At the beginning of the program, it will call the callback function to point to the position of the screen when you enter the mouse
// So it's far from the center
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
// Then, in the mouse callback function, we calculate the offset of the mouse position between the current frame and the previous frame :
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // y The coordinates are from bottom to top
lastX = xpos;
lastY = ypos;
float sensitivity = 0.1f; // sensitivity This value can be set arbitrarily
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
// To make sure the camera doesn't roll over
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
// stay xz Look at... On the plane Y Axis
// Here we only update y value , Observe carefully x and z The component is also affected . From the triangles, we can see that their value is equal to :
//direction.x = cos(glm::radians(pitch));
//direction.y = sin(glm::radians(pitch)); // Notice that we first turn the angle into radians
//direction.z = cos(glm::radians(pitch));// here Y Axis updates do affect Z But I don't quite understand why it's directly equal to cos(pitch)
//
//
//
// Here we only update y value , Observe carefully x and z The component is also affected . From the triangles, we can see that their value is equal to :
//direction.x = cos(glm::radians(yaw));
//direction.y =1 // Y unchanged
//direction.z = sin(glm::radians(yaw));
//
// The following equation is equivalent to first completing the rotation transformation of the pitch angle and then multiplying it by the yaw angle
// Combine the above two steps
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);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
//yoffset Is the direction in which our roller rolls vertically
if (fov >= 1.0f && fov <= 45.0f)
fov -= yoffset;
// Set a boundary for him stay 1 To 45 Between
if (fov < 1.0f)
fov = 1.0f;
if (fov > 45.0f)
fov = 45.0f;
}
//LightingMap.fs
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
// ambient
vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}
//LightingMap.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
gl_Position = projection * view * vec4(FragPos, 1.0);
}
边栏推荐
猜你喜欢

單片機通信數據延遲問題排查

Dépannage du problème de retard des données de communication du micro - ordinateur à puce unique

【ELT.ZIP】OpenHarmony啃论文俱乐部——多层存储分级数据压缩

Integrated MP code generator

Free flying animation of paper plane based on SVG

用Fragment实现图片简易浏览

Canvas+svg line particle animation web page background

GD32F4串口dma接收问题解决

Unity's data persistence -- Jason

J. Balanced Tree
随机推荐
【ELT.ZIP】OpenHarmony啃论文俱乐部——多层存储分级数据压缩
B_ QuRT_ User_ Guide(18)
Canvas drawing -- how to place the drawing in the center of the canvas
Unity's data persistence -- Jason
The dependent version number in the dependencymanagement in the POM project parent in the idea is red
B_ QuRT_ User_ Guide(16)
js顶部图标菜单点击切换背景色js特效
RHEL7 切换字符编码为GBK
SSL library selection
亚马逊测评自养号,小白应该如何开始?
Computer vision (AI) interview
HikariPool-1 - Shutdown initiated... HikariPool-1 - Shutdown completed.
联易融一面(已过)
postgresql 语句
Free flying animation of paper plane based on SVG
Dépannage du problème de retard des données de communication du micro - ordinateur à puce unique
Integrated MP code generator
Mavros控制无人机在gazebo环境下进行双目SLAM
Canvas interactive star animation background JS special effect
canvas+svg线条粒子动画网页背景