OpenGL材质系统和贴图纹理
上一篇文章当中笔者为大家介绍了风氏光照模型,相信大家也发现了光照着色器当中有设置有很多控制光照强度的参数,而所谓的材质系统就是我们可以人为的去调节这些参数,让一个物体的反光效果能够更加接近我们现实生活当中的一些物体。
材质系统
当描述一个表面时,我们可以分别为三个光照分量定义一个材质颜色(Material Color):环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting)。通过为每个分量指定一个颜色,我们就能够对表面的颜色输出有细粒度的控制了。现在,我们再添加一个反光度(Shininess)分量,结合上述的三个颜色,我们就有了全部所需的材质属性了
#version 450 core
struct Material {vec3 ambient;vec3 diffuse;vec3 specular;float shininess;
}; uniform Material material;
如你所见,我们为风氏光照模型的每个分量都定义一个颜色向量。ambient材质向量定义了在环境光照下这个表面反射的是什么颜色,通常与表面的颜色相同。diffuse材质向量定义了在漫反射光照下表面的颜色。漫反射颜色(和环境光照一样)也被设置为我们期望的物体颜色。specular材质向量设置的是表面上镜面高光的颜色(或者甚至可能反映一个特定表面的颜色)。最后,shininess影响镜面高光的散射/半径。
使用材质
我们在片段着色器中创建了一个材质结构体的uniform,所以下面我们希望修改一下光照的计算来遵从新的材质属性。由于所有材质变量都储存在一个结构体中,我们可以从uniform变量material中访问它们:
void main()
{ // 环境光vec3 ambient = lightColor * material.ambient;// 漫反射 vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = lightColor * (diff * material.diffuse);// 镜面光vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);vec3 specular = lightColor * (spec * material.specular); vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);
}
我们可以看到,和之前光照模型几乎没有什么不同的,我们只是通过结构体的方式来访问这些向量,这样做的好处是我们可以人为的控制这些材质的向量了。
lightingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
lightingShader.setFloat("material.shininess", 32.0f);
不过到现在还是有一个问题,那就是整个光照模型看上去会特别的亮,这是因为我们还没有设置照射光的属性,我们需要调整光的亮度。
struct Light {vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};uniform Light light;
片段着色器修改成如下的代码
void main()
{ // 环境光vec3 ambient = light.ambient * material.ambient;// 漫反射 vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * (diff * material.diffuse);// 镜面光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 * material.specular); vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);
}
设置光照的属性
lightingShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
lightingShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); // 将光照调暗了一些以搭配场景
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
好的到了这里,我们材质系统就为大家介绍到这里了,不过通过上面的代码我们知道,这个材质系统影响的是整个立方体的材质状况,但我们也知道现实生活当中这种单一材质物体是很少见的,一般我们看到的物体都是好几种材质组合而来的。要想表现出这种复杂的纹理,我们组好要能控制每个像素颜色,那怎样才能做到这种事了?可能有的朋友已经想到了,那就是使用之前的纹理,就可以控制片段着色器当中的像素颜色了!
纹理贴图
我们使用下面两个纹理图片来制作一个带有贴边的木箱子。


可能有的朋友想问,为什么铁框的贴图的中间的部分是黑色的,其实这个目的就在于减小木制材料部分中间的反光程度。整个光照着色器代码如下:
#type vertex
#version 450 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 color;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec2 texCoord;layout(location = 0) out vec4 v_Position;
layout(location = 1) out vec3 v_Color;
layout(location = 2) out vec3 v_Normal;
layout(location = 3) out vec2 v_texCoord;uniform mat4 u_ViewProject;void main(){gl_Position = u_ViewProject * position;v_Position = position;v_Color = color;v_Normal = normal;v_texCoord = texCoord;
}#type fragment
#version 450 corelayout(location = 0) out vec4 o_Color;layout(location = 0) in vec4 v_Position;
layout(location = 1) in vec3 v_Color;
layout(location = 2) in vec3 v_Normal;
layout(location = 3) in vec2 v_texCoord;struct Material {int diffuse;int specular;int shininess;
};struct Light{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};uniform sampler2D u_Textures[2];uniform vec3 u_ViewPos;
uniform Material material;
uniform Light light;void main(){vec3 v_position3 = vec3(v_Position.x,v_Position.y,v_Position.z);//环境亮度vec3 ambient = light.ambient * texture(u_Textures[material.diffuse],v_texCoord).rgb;//漫反射亮度vec3 vertex2light = normalize(light.position - v_position3);float diff = max(dot(vertex2light,normalize(v_Normal)),0.0f);vec3 diffuse = light.diffuse * diff * texture(u_Textures[material.diffuse],v_texCoord).rgb;//镜面反射vec3 viewDir = normalize(u_ViewPos - v_position3);vec3 reflectDir = reflect(-vertex2light,normalize(v_Normal));float spec = pow(max(dot(viewDir,reflectDir),0.0f),material.shininess);vec3 specular = light.specular * spec * texture(u_Textures[material.specular],v_texCoord).rgb;vec3 result = ambient + diffuse + specular;o_Color = vec4(result,1.0f);
}
这样我们就可得到一个边框反光的木箱子了,这一章总体是比较简单的,主函数代码贴在下面,如果对主函数当中的一些变量不清楚的话可以到这个网站获取此案例的所有的代码,包括纹理贴图:https://gitee.com/HonyOrange_227/opengl-light-lab
我们来看一下最后的效果

此文章到这里就结束了,希望能帮助到大家
#include<glad/glad.h>
#include<GLFW/glfw3.h>#include<iostream>
#include<glm/gtc/matrix_transform.hpp>#include"Shader.h"
#include"Texture.h"
#include"Camera.h"static Camera camera(glm::vec3(0.0f, 0.0f, 5.0f));
static bool run = true;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);int main() {glfwInit();GLFWwindow* window = glfwCreateWindow(640, 480, "Triangles", NULL, NULL);glfwMakeContextCurrent(window);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);glfwSetKeyCallback(window, key_callback);glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);//需要初始化GLADif (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "Failed to initialize GLAD" << std::endl;return -1;}float lightVertexes[] = {//front surface-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //00.5f, -0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //10.5f, 0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //2-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //3//back surface-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //40.5f, -0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //50.5f, 0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //6-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //7//up surface-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //80.5f, 0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //90.5f, 0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //10-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //11//down surface-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //120.5f, -0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //130.5f, -0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //14-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //15//left surface-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //16-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //17-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //18-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //19//right surface0.5f, -0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f, //200.5f, -0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //210.5f, 0.5f, 0.5f, 1.0f, 1.0f,1.0f,1.0f, //220.5f, 0.5f, -0.5f, 1.0f, 1.0f,1.0f,1.0f //23}; float vertexes[] = {//front surface-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,1.0f, 0.0f,0.0f,//00.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,1.0f, 1.0f,0.0f,//10.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,1.0f, 1.0f,1.0f,//2-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,1.0f, 0.0f,1.0f,//3//back surface-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,-1.0f, 0.0f,0.0f,//40.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,-1.0f, 1.0f,0.0f,//50.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,-1.0f, 1.0f,1.0f,//6-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,0.0f,-1.0f, 0.0f,1.0f,//7//up surface-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,1.0f,0.0f, 0.0f,0.0f,//80.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,1.0f,0.0f, 1.0f,0.0f,//90.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,1.0f,0.0f, 1.0f,1.0f,//10-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,1.0f,0.0f, 0.0f,1.0f,//11//down surface-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,-1.0f,0.0f, 0.0f,0.0f,//120.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,-1.0f,0.0f, 1.0f,0.0f,//130.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,-1.0f,0.0f, 1.0f,1.0f,//14-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 0.0f,-1.0f,0.0f, 0.0f,1.0f,//15//left surface-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, -1.0f,0.0f,0.0f, 0.0f,0.0f,//16-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, -1.0f,0.0f,0.0f, 1.0f,0.0f,//17-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, -1.0f,0.0f,0.0f, 1.0f,1.0f,//18-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, -1.0f,0.0f,0.0f, 0.0f,1.0f,//19//right surface0.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 1.0f,0.0f,0.0f, 0.0f,0.0f,//200.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 1.0f,0.0f,0.0f, 1.0f,0.0f,//210.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f,0.2f, 1.0f,0.0f,0.0f, 1.0f,1.0f,//220.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f,0.2f, 1.0f,0.0f,0.0f, 0.0f,1.0f,//23};glm::vec4 originVertexes[24] = {{-0.5f, -0.5f, 0.5f, 1.0f},{0.5f, -0.5f, 0.5f, 1.0f},{0.5f, 0.5f, 0.5f, 1.0f},{-0.5f, 0.5f, 0.5f, 1.0f},//back surface{-0.5f, -0.5f, -0.5f, 1.0f},{0.5f, -0.5f, -0.5f, 1.0f},{0.5f, 0.5f, -0.5f, 1.0f},{-0.5f, 0.5f, -0.5f, 1.0f},//up surface{-0.5f, 0.5f, 0.5f, 1.0f},{0.5f, 0.5f, 0.5f, 1.0f},{0.5f, 0.5f, -0.5f, 1.0f},{-0.5f, 0.5f, -0.5f, 1.0f},//down surface{-0.5f, -0.5f, 0.5f, 1.0f},{0.5f, -0.5f, 0.5f, 1.0f},{0.5f, -0.5f, -0.5f, 1.0f},{-0.5f, -0.5f, -0.5f, 1.0f},//left surface{-0.5f, -0.5f, -0.5f, 1.0f},{-0.5f, -0.5f, 0.5f, 1.0f},{-0.5f, 0.5f, 0.5f, 1.0f} ,{-0.5f, 0.5f, -0.5f, 1.0f},//right surface{0.5f, -0.5f, -0.5f, 1.0f},{0.5f, -0.5f, 0.5f, 1.0f},{0.5f, 0.5f, 0.5f, 1.0f},{0.5f, 0.5f, -0.5f, 1.0f}};unsigned int indexes[] = {//front surface0,1,2,2,3,0,//back surface4,5,6,6,7,4,//up surface8,9,10,10,11,8,//down surface12,13,14,14,15,12,//left surface16,17,18,18,19,16,//right surface20,21,22,22,23,20};glEnable(GL_DEPTH_TEST);unsigned int buffer = 0, lightbuffer = 0,vertexArray = 0, lightVertexArray = 0,indexBuffer = 0;glCreateVertexArrays(1, &vertexArray);glBindVertexArray(vertexArray);glCreateBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 12 * sizeof(float), NULL);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (const void*)(4 * sizeof(float)));glEnableVertexAttribArray(2);glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (const void*)(7 * sizeof(float)));glEnableVertexAttribArray(3);glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (const void*)(10 * sizeof(float)));glCreateVertexArrays(1, &lightVertexArray);glBindVertexArray(lightVertexArray);glCreateBuffers(1, &lightbuffer);glBindBuffer(GL_ARRAY_BUFFER, lightbuffer);glBufferData(GL_ARRAY_BUFFER, sizeof(lightVertexes), lightVertexes, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), NULL);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (const void*)(4 * sizeof(float)));glCreateBuffers(1, &indexBuffer);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexes), indexes, GL_STATIC_DRAW);Shader* pShader = new Shader("assets/shaders/TextureShader.glsl");Shader* pLightShader = new Shader("assets/shaders/LightShader.glsl");Texture* pTextureWood = new Texture("assets/Textures/container2.png");Texture* pTextureSteel = new Texture("assets/Textures/container2_specular.png");glm::mat4 transform = glm::translate(glm::mat4(1.0), glm::vec3(0.3f, 1.5f, 1.5f));glm::vec4 orginCenter(0.0f, 0.0f, 0.0f, 1.0f);int textureIndexes[2] = { 0,1 };while (!glfwWindowShouldClose(window) && run) {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glm::mat4 project = glm::perspective(glm::radians(camera.GetCameraZoom()), 640.0f / 480.0f, 0.1f, 100.0f);glm::mat4 view = camera.GetViewMatrix();glm::mat4 ViewProject = project * view;for (int i = 0; i < 24; i++) {glm::vec4 originPoint = originVertexes[i];originPoint = transform * glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f)) * originPoint;lightVertexes[i * 7] = originPoint.x;lightVertexes[i * 7 + 1] = originPoint.y;lightVertexes[i * 7 + 2] = originPoint.z;lightVertexes[i * 7 + 3] = originPoint.w;}glBindBuffer(GL_ARRAY_BUFFER, lightbuffer);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(lightVertexes), lightVertexes);pShader->Bind();pShader->UploadUniformat4("u_ViewProject", ViewProject);glBindVertexArray(lightVertexArray);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);glm::vec4 centerMove = transform * orginCenter;for (int i = 0; i < 24; i++) {glm::vec4 originPoint = originVertexes[i];originPoint = glm::scale(glm::mat4(1.0f), glm::vec3(1.5f, 1.5f, 1.5f)) * originPoint;vertexes[i * 12] = originPoint.x;vertexes[i * 12 + 1] = originPoint.y;vertexes[i * 12 + 2] = originPoint.z;vertexes[i * 12 + 3] = originPoint.w;}glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexes), vertexes);pTextureWood->Bind(0);pTextureSteel->Bind(1);pLightShader->Bind();pLightShader->UploadUniformat4("u_ViewProject", ViewProject);pLightShader->UploadUnifromFloat3("u_ViewPos",camera.GetPosition());pLightShader->UploadUnifromFloat3("light.position", { centerMove.x, centerMove.y, centerMove.z });pLightShader->UploadUnifromFloat3("light.ambient", { 0.2f,0.2f,0.2f });pLightShader->UploadUnifromFloat3("light.diffuse", { 0.5f,0.5f,0.5f });pLightShader->UploadUnifromFloat3("light.specular", { 1.0f,1.0f,1.0f });pLightShader->UploadUniform1i("material.diffuse", 0);pLightShader->UploadUniform1i("material.specular", 1);pLightShader->UploadUniform1i("material.shininess", 64);pLightShader->UplaodUniform1iv("u_Textures", 2, textureIndexes);glBindVertexArray(vertexArray);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);glfwSwapBuffers(window);glfwPollEvents();}delete pShader;delete pLightShader;glfwDestroyWindow(window);glfwTerminate();
}void mouse_callback(GLFWwindow* window, double xposIn, double yposIn) {static float lastX = 320.0f, lastY = 240.0f;static bool firstMouse = true;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;lastX = xpos, lastY = ypos;camera.ProcessMouseMovement(xoffset, yoffset);
}void scroll_callback(GLFWwindow* window, double xoffsetIn, double yoffsetIn) {camera.ProcessMouseScroll(static_cast<float>(yoffsetIn));
}void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)run = false;
}
相关文章:
OpenGL材质系统和贴图纹理
上一篇文章当中笔者为大家介绍了风氏光照模型,相信大家也发现了光照着色器当中有设置有很多控制光照强度的参数,而所谓的材质系统就是我们可以人为的去调节这些参数,让一个物体的反光效果能够更加接近我们现实生活当中的一些物体。 材质系统…...
Markdown中类图的用法
Markdown中类图的用法 前言语法详解基本流程图几何图形节点默认的节点分离节点的ID与内容节点形状圆角形节点的语法圆形节点的语法。非对称节点语法菱形节点的语法。六角形节点的语法。平行四边形节点的语法。梯形节点的语法。 连接线基本的连接线语法。无向线段连接线。点状连…...
钓鱼攻击(Phishing)详解和实现 (网络安全)
钓鱼攻击(Phishing)详解和实现 钓鱼攻击是一种社会工程学攻击,攻击者通过伪装成可信任的实体诱使受害者泄露敏感信息,如用户名、密码、信用卡号等。以下详细介绍钓鱼攻击的原理、种类、实现方式,以及防御措施。 一、钓…...
window11 wsl mysql8 错误分析:1698 - Access denied for user ‘root‘@‘kong.mshome.net‘
🚨 错误分析:1698 - Access denied for user rootkong.mshome.net 这个错误是因为 MySQL 的 root 用户 使用 auth_socket 插件进行身份验证,而不是使用密码。因此,当你尝试从 远程主机 连接时,MySQL 会拒绝访问。 ✅ …...
C++线程同步之条件变量
C线程同步之条件变量 文章目录 C线程同步之条件变量什么是条件变量(Condition Variable)?条件变量的主要用途常见的应用场景C11中的条件变量condition_variable的使用方法std::condition_variable的使用步骤典型的使用示例:生产者…...
如何实现多条件搜索
我们先来看多条件查询的样式是什么样的! 给查询按钮添加点击事件,然后获取到对应输入框中的值 然后通过filter过滤,对获取到的数据进行筛选 ,然后调用渲染函数将过滤搜索到的数据在页面中显示出来。 这就是进行多条件搜索出来的效…...
深入MySQL复杂查询优化技巧
在上一篇文章中,我们介绍了 MySQL 的关联关系理论与基础实践。本篇文章将进一步探讨 MySQL 复杂查询的优化技巧,帮助开发者应对大型数据集和高并发场景中的性能挑战。我们将涵盖索引设计、查询计划分析、分区技术以及事务管理的优化。 一、索引优化 索引…...
Fabric环境部署-Git和Node安装
一.安装Git(v2.43.0) Git 是一个开源的分布式版本管理系统(也是全球最大的开源软件存储服务器),用于敏捷高效地处理任何或小或大的项目。搭建区块链需要使用Git,因为区块链的开发和部署需要使用版本控制工…...
如何弥补开源大语言模型解决推理任务的不足
在实际应用中,大语言模型(LLM)可以通过与其他专门的推理技术结合,克服其在严格逻辑推理、深度推理或因果推理领域的不足。以下是几种有效的结合方式,分别从不同角度解决LLM在推理中的局限性。 一、结合符号推理系统 …...
Ubuntu 下载安装 Consul1.17.1
下载 wget https://releases.hashicorp.com/consul/1.17.1/consul_1.17.1_linux_amd64.zip解压: unzip -d consul_1.17.1_linux_amd64.zip /opt/module将解压出的二进制文件移动到 /usr/local/bin 目录中以便在系统中全局使用: sudo mv consul /usr/l…...
【数据库系统概论】并发控制--复习
1. 并发控制概述 并发控制是数据库系统处理多个事务同时执行时,保证数据一致性和事务隔离性的关键技术。 1.1并发操作的特点 数据库系统允许多个用户并发访问。典型应用场景: 飞机订票系统银行数据库系统网上购物系统 1.2并发操作可能带来的问题 并…...
MySQL(六)MySQL 案例
1. MySQL 案例 1.1. 设计数据库 1、首先根据相关业务需求(主要参考输出输入条件)规划出表的基本结构 2、根据业务规则进行状态字段设计 3、预估相关表的数据量进行容量规划 4、确定主键 5、根据对相关处理语句的分析对数据结构进行相应的变更。 设计表的时…...
DDcGAN_多分辨率图像融合的双鉴别条件生成对抗网络_y译文马佳义
摘要: 在本文中,我们提出了一种新的端到端模型,称为双鉴别条件生成对抗网络(DDcGAN),用于融合不同分辨率的红外和可见光图像。我们的方法建立了一个生成器和两个鉴别器之间的对抗博弈。生成器的目的是基于特…...
[读书日志]从零开始学习Chisel 第一篇:书籍介绍,Scala与Chisel概述,Scala安装运行(敏捷硬件开发语言Chisel与数字系统设计)
简介:从20世纪90年代开始,利用硬件描述语言和综合技术设计实现复杂数字系统的方法已经在集成电路设计领域得到普及。随着集成电路集成度的不断提高,传统硬件描述语言和设计方法的开发效率低下的问题越来越明显。近年来逐渐崭露头角的敏捷化设…...
二、用例图
二、用例图 (一)、用例图的基本概念 1、用例图的定义: 用例图是表示一个系统中用例与参与者关系之间的图。它描述了系统中相关的用户和系统对不同用户提供的功能和服务。 用例图相当于从用户的视角来描述和建模整个系统,分析系统的功能与…...
LWIP之一:使用STM32CubeMX搭建基于FreeRTOS的LWIP工程并分析协议栈初始化过程
工程搭建及LWIP协议栈初始化过程 一、使用STM32CubeMX快速生成工程二、修改测试三、LWIP协议栈初始化过程分析3.1 tcpip_init()3.1.1 lwip_init()3.1.1.1 sys_init()3.1.1.2 mem_init()3.1.1.3 memp_init()3.1.1.4 netif_init()3.1.1.5 udp_init()3.1.1.6 tcp_init()3.1.1.7 ig…...
个性化电影推荐系统|Java|SSM|JSP|
【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7 4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、JSP、jquery,html 5⃣️数据库可…...
UE5AI感知组件
官方解释: AI感知系统为Pawn提供了一种从环境中接收数据的方式,例如噪音的来源、AI是否遭到破坏、或AI是否看到了什么。 AI感知组件(AIPerception Component)是用于实现游戏中的非玩家角色(NPC)对环境和其…...
每日一学——日志管理工具(ELK Stack)
5.1 ELK Stack 5.1.1 Elasticsearch索引机制 嘿,小伙伴们!今天我们要聊聊ELK Stack——一套由Elasticsearch、Logstash和Kibana组成的强大日志管理工具集。通过这套工具,我们可以轻松地收集、存储、搜索和可视化日志数据。首先,…...
“智能筛查新助手:AI智能筛查分析软件系统如何改变我们的生活
嘿,朋友们!今天咱们来聊聊一个特别厉害的工具——AI智能筛查分析软件系统。想象一下,如果你有一个超级聪明的小助手,不仅能帮你快速找出问题的关键所在,还能提供精准的解决方案,是不是感觉工作和生活都变得…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
