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;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/502433.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光缆生产车间可视化,让智能制造更透明

图扑光缆生产车间可视化系统通过实时监控和数据分析&#xff0c;优化生产流程&#xff0c;提升产品质量和产能效率&#xff0c;为光缆制造业提供智能化解决方案&#xff0c;推动产业升级。

深入理解 Java 接口的回调机制

前言 回调是一种非常重要的编程技术&#xff0c;它广泛应用于事件驱动的编程、异步任务和框架设计中。在 Java 中&#xff0c;回调机制通常通过 接口 来实现。本篇博客将详细解析 Java 接口的回调原理、实现方式&#xff0c;以及实际开发中的应用场景。 泪崩了&#xff0c;期末…

LangChain 介绍

LangChain 是一个用于构建语言模型驱动的应用程序&#xff08;Language Model Applications&#xff09;的开发框架&#xff0c;旨在帮助开发者将大型语言模型&#xff08;LLMs&#xff09;集成到更复杂的、具备上下文感知能力的应用中。LangChain 支持使用模型如 OpenAI GPT-3…

Nginx代理本地exe服务http为https

Nginx代理本地exe服务http为https 下载NginxNginx命令exe服务http代理为https 下载Nginx 点击下载Nginx 下载好之后是一个压缩包&#xff0c;解压放到没有中文的路径下就可以了 Nginx命令 调出cmd窗口cd到安装路径 输入&#xff1a;nginx -v 查看版本 nginx -h&#xff…

cursor 使用技巧

一、创建项目前期步骤 1.先给AI设定一个对应项目经理角色&#xff0c; 2.然后跟AI沟通项目功能&#xff0c;生成功能设计文件&#xff1a;README.md README.md项目功能 3.再让AI总结写出开发项目规则文件&#xff1a; .cursorrules 是技术栈进行限定&#xff0c;比如使用什…

创建并配置华为云虚拟私有云

目录 私有云 创建虚拟私有云 私有云 私有云是一种云计算模式&#xff0c;它将云服务部署在企业或组织内部的私有基础设施上&#xff0c;仅供该企业或组织内部使用&#xff0c;不对外提供服务.私有云的主要特点包括&#xff1a; 私密性&#xff1a;私有云的资源&#xff08;如…

【数据结构-堆】力扣2530. 执行 K 次操作后的最大分数

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你的 起始分数 为 0 。 在一步 操作 中&#xff1a; 选出一个满足 0 < i < nums.length 的下标 i &#xff0c; 将你的 分数 增加 nums[i] &#xff0c;并且 将 nums[i] 替换为 ceil(nums[i] / 3) 。 返回在 恰好…

【SpringBoot】当 @PathVariable 遇到 /,如何处理

1. 问题复现 在解析一个 URL 时&#xff0c;我们经常会使用 PathVariable 这个注解。例如我们会经常见到如下风格的代码&#xff1a; RestController Slf4j public class HelloWorldController {RequestMapping(path "/hi1/{name}", method RequestMethod.GET)publ…

【跟着官网学技术系列之MySQL】第2天之MySQL版本:创新和 LTS

前言 在当今信息爆炸的时代&#xff0c;拥有信息检索的能力很重要。 作为一名软件工程师&#xff0c;遇到问题&#xff0c;你会怎么办&#xff1f;带着问题去搜索引擎寻找答案&#xff1f;亦或是去技术官网&#xff0c;技术社区去寻找&#xff1f; 根据个人经验&#xff0c;一…

开源存储详解-分布式存储与ceph

ceph体系结构 rados&#xff1a;reliable, autonomous, distributed object storage, rados rados采用c开发 对象存储 ceph严格意义讲只提供对象存储能力&#xff0c;ceph的块存储能力实际是基于对象存储库librados的rbd 对象存储特点 对象存储采用put/get/delete&#xf…

操作系统大题整理

专题一 程序代码题&#xff1a;程序设计与分析&#xff0c;主要考的是线程&#xff0c;多线程的并发&#xff1f; 大题第一问&#xff08;1&#xff09;操作系统的结构有哪几种常用的结构&#xff1f; 宏内核&#xff1a;宏内核是将操作系统的主要功能模块都集中在内核的一种结…

设计模式学习[14]---状态模式

文章目录 前言1.原理阐述2.引例3.状态模式对象化4.状态模式优化 总结 前言 状态模式&#xff0c;乍一听名字其实好像很好理解的样子&#xff0c;状态嘛&#xff0c;人在不同状态会有不同的行为模式。那软件的状态模式又是什么样子的&#xff1f;根据一个变量的值&#xff0c;执…

【.NET】Kafka消息队列介绍,使用Confluent.Kafka集成Kafka消息队列

一、Kafka介绍 kafka是一种高吞吐量、分布式、可扩展的消息中间件系统&#xff0c;最初由LinkedIn公司开发。随着不断的发展&#xff0c;在最新的版本中它定义为分布式的流处理平台&#xff0c;现在在大数据应用中也是十分广泛。 它可以处理大量的实时数据流&#xff0c;被广…

基于ESP32的桌面小屏幕实战[5]:PCB下单

1. 焊接调试前准备 PCB下单 点击“PCB下单” 检查一下DRC 确认无错误之后&#xff0c;确认下单 然后就会跳转到下面的网页 基本上保持默认选项即可。可以看到“焊盘喷镀”有3个选项。 在选择表面处理工艺时&#xff0c;应综合考虑产品的具体需求、环保法规以及成本等因素。例…

下载b站高清视频

需要使用的edge上的一个扩展插件&#xff0c;所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站&#xff0c;登录自己账号&#xff08;登录后才能下载到高清&#xff01;&#xff01;&#xff09;。打开一个视频&#xff0c;选择自…

【蓝桥杯研究生组】第14届Java试题答案整理

试题链接&#xff1a;链接 A题 满足条件的答案有&#xff1a;35813116 public class TianShu {public static void main(String[] args) {int ans 0;// 2000.1.1 - 2000000.1.1// 年份是月份的倍数&#xff0c;也是日的倍数for (int year2000; year<2000000; year) {for …

从0到机器视觉工程师(二):封装调用静态库和动态库

目录 静态库 编写静态库 使用静态库 方案一 方案二 动态库 编写动态库 使用动态库 方案一 方案二 方案三 总结 静态库 静态库是在编译时将库的代码合并到最终可执行程序中的库。静态库的优势是在编译时将所有代码包含在程序中&#xff0c;可以使程序独立运行&…

【LeetCode Hot100 二分查找】搜索插入位置、搜索二维矩阵、搜索旋转排序数组、寻找两个正序数组的中位数

二分查找 搜索插入位置搜索二维矩阵在排序数组中查找元素的第一个和最后一个位置寻找旋转排序数组中的最小值搜索旋转排序数组寻找两个正序数组的中位数&#xff08;hard&#xff09; 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并…

你已经分清JAVA中JVM、JDK与JRE的作用和关系了吗?

你已经分清JAVA中JVM、JDK与JRE的作用和关系了吗&#xff1f; 一. JVM、JDK与JRE的关系二. JVM、JDK与JRE的作用2.1 什么是JVM&#xff1f;2.2 什么是JDK&#xff1f;2.3 什么是JRE&#xff1f; 前言 点个免费的赞和关注&#xff0c;有错误的地方请指出&#xff0c;看个人主页有…

在不到 5 分钟的时间内将威胁情报 PDF 添加为 AI 助手的自定义知识

作者&#xff1a;来自 Elastic jamesspi 安全运营团队通常会维护威胁情报报告的存储库&#xff0c;这些报告包含由报告提供商生成的大量知识。然而&#xff0c;挑战在于&#xff0c;这些报告的内容通常以 PDF 格式存在&#xff0c;使得在处理安全事件或调查时难以检索和引用相关…