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智能筛查分析软件系统。想象一下,如果你有一个超级聪明的小助手,不仅能帮你快速找出问题的关键所在,还能提供精准的解决方案,是不是感觉工作和生活都变得…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...