GLSL(OpenGL 着色器语言)基础语法

GLSL(OpenGL 着色器语言)基础语法

GLSL(OpenGL Shading Language)是 OpenGL 计算着色器的语言,语法类似于 C 语言,但提供了针对 GPU 的特殊功能,如向量运算和矩阵运算。

着色器的开头总是要声明版本,接着是输入和输出变量、uniform 和 main 函数。每个着色器的入口点都是main函数,在这个函数中我们处理所有的输入变量,并将结果输出到输出变量中。

#version version_number
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;void main()
{// 处理输入并进行一些图形操作...// 输出处理过的结果到输出变量out_variable_name = weird_stuff_we_processed;
}

基本语法

版本声明

每个 GLSL 着色器的第一行通常需要指定版本号:

#version 330 core // 330 core 表示使用 OpenGL 3.3 及以上的核心模式
#version 120	// OpenGL 2.1
#version 450 core(OpenGL 4.5	// OpenGL 4.5

变量声明

类型 变量名;
常见的基本数据类型
类型说明示例
int整数int a = 5;
float浮点数float b = 3.14;
bool布尔类型bool flag = true;
vec22D向量 (x, y)vec2 v = vec2(1.0, 2.0);
vec33D向量 (x, y, z)vec3 color = vec3(1.0, 0.5, 0.2);
vec44D向量 (x, y, z, w)vec4 position = vec4(1.0, 2.0, 3.0, 1.0);
mat44×4 矩阵mat4 transform;
纹理类型(Texture Types)

纹理类型用于表示不同的纹理对象,它们在图形渲染中用于存储图片或纹理数据

类型说明
sampler2D2D纹理采样器,通常用于访问2D纹理图像
sampler3D3D纹理采样器,用于访问3D纹理
samplerCube立方体纹理采样器,用于访问立方体贴图(环境映射)
sampler2DArray2D纹理数组采样器,访问多个2D纹理层
sampler2DShadow用于阴影映射的2D纹理采样器
samplerCubeShadow用于阴影映射的立方体纹理采样器
纹理采样示例
#version 330 corein vec2 TexCoords; // 传入的纹理坐标
out vec4 FragColor;// 输出的颜色uniform sampler2D texture1; // 纹理变量,代表 GPU 采样的 2D 贴图void main()
{FragColor = texture(texture1, TexCoords); // 从纹理中获取颜色,并输出
}

uniform关键字:uniform 变量用于在 C++ 代码和 Shader 之间传递数据。
与 in/out 不同,uniform 是全局变量,在着色器的所有调用中都保持相同的值。

聚合类型(Aggregate Types)

这些类型可以用来组合多个基本类型,提供更复杂的数据结构。

(1)数组类型(Array types):

float arr[10];	// 一个包含 10 个 float 的数组。
vec3 arr[5];   	// 一个包含 5 个 vec3 向量的数组。

(2)结构体类型(Structure types):

sstruct Light {vec3 position;vec3 color;float intensity;
};
内置变量类型(Built-in Variables)

OpenGL着色器程序中预定义的变量,用于接收从应用程序传递的状态或传递给其他着色器阶段的值。

(1)顶点着色器中常见的内建变量

变量说明
gl_Position指定当前顶点的屏幕空间位置。它是 vec4 类型,必须在顶点着色器中设置
gl_PointSize指定绘制点的大小(只有在 GL_POINTS 绘制模式时有效)
gl_VertexID当前顶点的索引

(2)片元着色器中常见的内建变量

变量说明
gl_FragColor最终输出的颜色。片元着色器必须设置它来确定每个像素的颜色
gl_FragDepth指定片元的深度值

(3)全局变量

变量说明
gl_FragCoord片元着色器中的当前片元坐标
gl_TexCoord纹理坐标,用于在片元着色器中进行纹理采样

向量操作

GLSL 提供了一些专门用于向量操作的语法

vec3 v1 = vec3(1.0, 2.0, 3.0);
vec3 v2 = vec3(0.5, 0.5, 0.5);vec3 sum = v1 + v2;  // 向量加法
vec3 diff = v1 - v2; // 向量减法
vec3 scale = v1 * 2.0; // 向量数乘
float dotProduct = dot(v1, v2); // 点积
vec3 crossProduct = cross(v1, v2); // 叉积

向量分量访问

vec4 color = vec4(1.0, 0.5, 0.2, 1.0);
float red = color.r;    // red = 1.0
float green = color.g;  // green = 0.5
float blue = color.b;   // blue = 0.2
float alpha = color.a;  // alpha = 1.0

xyzw 和 rgba 可以混用

vec3 rgb = color.rgb;  // 取前三个分量
vec2 xy = color.xy;    // 取前两个分量

矩阵运算

mat4 transform = mat4(1.0); // 4×4 单位矩阵
vec4 position = vec4(1.0, 2.0, 3.0, 1.0);
vec4 result = transform * position; // 矩阵-向量乘法

GLSL 变量限定符

GLSL 提供了不同的变量限定符,决定变量的作用范围和生命周期

(1)变量存储限定符(Storage Qualifiers)

限定符作用适用着色器
in输入变量,从上一阶段着色器传入的数据顶点、片元着色器
out输出变量,传递给下一阶段着色器顶点、片元着色器
inout既可作为输入,也可作为输出
uniform全局变量,供 CPU 传入着色器,所有着色器阶段共享顶点、片元着色器
attribute旧版 GLSL(< 3.3),用于顶点着色器的输入变量,已被 in 取代顶点着色器
varying旧版 GLSL(< 3.3),用于顶点着色器和片元着色器之间传递数据,已被 in 和 out 取代顶点、片元着色器
const常量,在编译时确定,不能修改
buffer访问 Shader Storage Buffer Object(SSBO),用于计算着色器
uniform

首先,uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。

代码示范

(1)在着色器中使用 uniform 关键字,并带上类型和名称。

#version 330 core
out vec4 FragColor;
uniform vec4 ourColor;void main() {FragColor = ourColor;
}

(2)在OpenGL程序代码中设置这个变量

float timeValue = glfwGetTime();
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;// 利用时间动态计算颜色或效果
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");// 查询uniform ourColor的位置值
glUseProgram(shaderProgram);// 激活指定的着色器程序
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);// 设置uniform值

QT代码示范
Qt 封装了glGetUniformLocation(),提供了uniformLocation()。

// 获取 uniform 变量的位置
int location = shaderProgram.uniformLocation("ourColor");
if (location != -1) {shaderProgram.setUniformValue(location, QVector4D(0.0f, 1.0f, 0.0f, 1.0f));// 设置uniform值
}

或者,在QOpenGLShaderProgram中,甚至不需要手动获取Location,可以直接使用setUniformValue(),它会自动查找uniformLocation()并设置值😃:

shaderProgram.setUniformValue("ourColor", QVector4D(0.0f, 1.0f, 0.0f, 1.0f));

总结
uniform变量用于在 程序(CPU)和 着色器(GPU)之间传递数据。uniform变量的值在渲染迭代中保持不变,直到显式地更新。可以用于传递光照、变换、时间等不随顶点或片段变化的参数。

“渲染迭代”是指每次绘制调用,每次调用glDrawArrays或 glDrawElements等函数时,都会渲染一批图形。在一次渲染调用中,uniform变量的值是固定的,直到显式地改变它。

(2)变量布局限定符(Layout Qualifiers)

关键字作用
layout(location = N)指定变量的绑定位置(常用于 in/out 变量)
layout(binding = N)指定 uniform buffer、采样器的绑定点
layout(origin_upper_left)设定坐标原点在左上角(用于片元着色器)
layout(pixel_center_integer)指定像素中心对齐规则

(3)变量精度限定符(Precision Qualifiers)

关键字作用
highp高精度(32 位浮点数)
mediump中精度(16 位浮点数)
lowp低精度(10 位或 8 位浮点数)

在 OpenGL ES(移动端)上,必须显式声明精度,但桌面版 GLSL 默认 highp。

(4)插值限定符(Interpolation Qualifiers)

关键字作用
smooth默认插值方式(透视校正插值)
flat禁用插值,所有片元使用同一顶点的值
noperspective线性插值(无透视校正)

(5)片元着色器输出限定符(Fragment Shader Output Qualifiers)

关键字作用
discard丢弃当前片元,不进行颜色写入
depth_any允许片元写入任何深度值
depth_greater片元只能写入更大的深度值
depth_less片元只能写入更小的深度值

渲染管线的基本流程

OpenGL 渲染管线是一个从顶点数据到最终像素颜色输出的流水线处理过程,主要分为以下几个阶段:
在这里插入图片描述

(1)应用阶段(CPU端)

1️⃣ 准备数据(VAO、VBO、EBO、Shader、Texture)
2️⃣设置状态(glEnable(GL_DEPTH_TEST) 等)
3️⃣执行绘制(glDrawArrays() / glDrawElements())

👉GPU 端(渲染管线)

(2)顶点着色器(Vertex Shader)

运行在 GPU 上,对每个顶点执行一次。

关键任务

处理顶点数据(如顶点坐标、颜色、法线、纹理坐标) 。
计算 顶点的最终位置(gl_Position),将物体坐标系转换为相机坐标系(裁剪空间),渲染相机范围内的物体。
计算并输出其他顶点属性:颜色、纹理坐标等数据,以传递给下一阶段。

输入
(1)顶点数据:顶点的位置、法线、颜色、纹理坐标等,这些数据通常保存在顶点缓冲对象(VBO)中。
(2)顶点着色器的输入变量:包括位置、法线、颜色等,通过layout关键字来指定。

处理

(1)顶点坐标变换:
使用 模型矩阵(Model Matrix):将顶点从模型空间转换到世界空间。
使用 视图矩阵(View Matrix):将顶点从世界空间转换到相机空间,通常相当于相机的视图矩阵。
使用投影矩阵(Projection Matrix):将顶点从相机空间转换到裁剪空间,通常有两种类型的投影:
1)正交投影(Orthographic projection)
2)透视投影(Perspective projection)

特性正交投影(Orthographic Projection)透视投影Perspective Projection)
投影线平行收敛(有消失点)
物体大小不受视距影响,距离远近无关物体距离远,投影变小;距离近,投影变大
深度感无深度感,所有物体看起来是平的有深度感,远近物体具有明显的大小差异
常见应用2D 游戏、CAD、技术图纸3D 游戏、虚拟现实、电影动画
适用场景精确的比例和尺寸绘制(如建筑图纸、设计图纸)创建真实的场景深度感,模拟人眼视角
投影效果所有物体大小一致,不会变形物体随着距离远近而缩小或放大,产生透视效果

(2)法线变换:
法线需要从模型空间变换到世界空间或视图空间,通常要用到模型矩阵的逆转置矩阵来正确处理缩放等非线性变换,以防止模型缩放影响法线的方向。

(3)顶点属性计算:
顶点着色器可以根据顶点的其他属性(如法线、颜色、纹理坐标)来计算光照、颜色等值,传递给片段着色器。

输出
(1)gl_Position:这是裁剪空间中的顶点位置,是后续阶段(如光栅化)裁剪的基础。
(2)gl_PointSize:在绘制点时,控制点的大小。
(3)gl_ClipDistance:用于顶点裁剪的距离参数。
(4)其他顶点属性(如颜色、法线、纹理坐标等)可以输出到后续的片段着色器。

代码示例

#version 330 corelayout (location = 0) in vec3 aPos;  // 传入顶点位置(绑定顶点位置到 location = 0)
layout (location = 1) in vec3 aColor; // 传入顶点颜色
layout (location = 2) in vec3 inNormal; // 顶点法线out vec3 vColor; // 传递给片元着色器的颜色
out vec3 fragNormal;  // 法线,传递给片段着色器uniform mat4 model; // 模型矩阵
uniform mat4 view;  // 视图矩阵
uniform mat4 projection; // 投影矩阵void main()
{// 将法线从模型空间变换到世界空间fragNormal = mat3(transpose(inverse(model))) * inNormal;gl_Position = projection * view * model * vec4(aPos, 1.0); // 计算最终的顶点位置,并赋值给 gl_PositionvColor = aColor; // 颜色传递给片元着色器
}
layout(location = n) 解释

layout(location = n) 用来指定顶点属性的绑定位置 n。这个 n 位置是在OpenGL中通过glVertexAttribPointer或glVertexAttribPointer函数指定的。
(1)为了明确匹配顶点数据和着色器变量

顶点着色器需要使用 特定位置的属性 来获得顶点数据,例如顶点位置、颜色或纹理坐标。通过 layout(location = n),可以明确告诉 OpenGL 每个顶点属性的输入顺序和位置索引。避免因顺序错误或不一致导致数据混乱的问题。

(2) 对于多属性的支持

当你顶点数据包含多个属性时,如:位置、颜色、法线、纹理坐标等,需要为每个属性指定一个独立的 location,确保 OpenGL 正确地将数据传递给着色器。

在QT中写法如下:在这里插入图片描述
👉 顶点数据的位置索引(n)必须和着色器中声明的 layout(location = n) 对应。

gl_Position的解释

gl_Position是OpenGL中一个非常特殊的内部变量,其类型是 vec4(四维向量),包含了顶点在三维空间中的位置以及齐次坐标的 w 分量。

vec4 gl_Position = vec4(x, y, z, w);

gl_Position定义顶点在裁剪空间中的位置,位于投影变换后的空间。
gl_Position作用: 当顶点着色器的输出 gl_Position 被送入裁剪阶段和光栅化阶段后,OpenGL 会进行裁剪和透视除法:

  • 裁剪:将视野外的顶点丢弃,只保留视野内的顶点。
  • 透视除法:通过除以 gl_Position.w 来将顶点从裁剪空间转换为屏幕空间,得到最终的窗口坐标。
    注:裁剪阶段和光栅化阶段是OpenGL渲染管线中的固定阶段,由OpenGL内部自动处理。

在上面的示例中,aPos 是传入的顶点坐标。我们将模型矩阵、视图矩阵和投影矩阵与 aPos 相乘,最终得到顶点的位置,并赋值给 gl_Position。

(3)图元装配

将顶点组合成 点(Point)、线(Line)、三角形(Triangle)。

(4)细分着色器(Tessellation Shader,可选)

用于将少量控制点细分成更多的几何数据,以生成更精细的模型(如地形细节)。
细分控制着色器(Tessellation Control Shader, TCS)
细分评估着色器(Tessellation Evaluation Shader, TES)
细分曲面,提高模型精度

(5)几何着色器(Geometry Shader,可选)

运行在 GPU 上,以整个图元(如点、线段、三角形)为单位进行处理,而不是单独处理每个顶点。

关键任务

修改或生成新的顶点(如扩展为线段或面)。
可以输出多个顶点来生成新的几何形状。
继续传递颜色、纹理坐标等数据。

代码示例

#version 330 core
layout(triangles) in;  // 输入图元类型(三角形)
layout(triangle_strip, max_vertices = 3) out; // 输出图元类型(三角形条带)in vec3 vColor[]; // 从顶点着色器接收颜色数据
out vec3 fColor; // 传递给片元着色器void main()
{for (int i = 0; i < 3; i++) // 处理每个输入顶点{gl_Position = gl_in[i].gl_Position; // 继承输入顶点的位置信息fColor = vColor[i]; // 继承颜色信息EmitVertex(); // 输出该顶点}EndPrimitive(); // 结束当前图元
}

(6)光栅化(Rasterization)

将顶点数据转换为像素点(片元),并决定哪些像素应该被绘制填充。以顶点为边界,中间做插值运算,填充像素点。

(7)片元着色器(Fragment Shader)

运行在 GPU 上,对每个片元(像素)执行一次。

关键任务

纹理采样:从纹理的像素 赋值给上一阶段产生的像素点上;
计算最终颜色(纹理、光照、阴影、颜色混合计算);
输出颜色给帧缓冲

【注】假若,顶点着色器4个,到了光栅化,插值后为100 100,那么到了片段着色器,则会进行100 * 100次运算。所以,在这个阶段的运算量是指数级增长。故能在顶点着色器运算的,就不要放到片段着色器中运算,大大影响效率。

代码示例

#version 330 core
in vec3 vColor;  // 从顶点着色器传入的颜色
//in vec3 fColor; // 从几何着色器接收颜色
out vec4 FragColor; // 输出最终颜色void main()
{FragColor = vec4(vColor, 1.0); // 计算最终颜色// FragColor = vec4(fColor, 1.0); // 计算最终颜色
}

注意:顶点着色器输出的变量和片元着色器输入的变量的名称必须一致!

顶点着色器的输出变量(out 变量)会作为输入传递给片元着色器(in 变量)。OpenGL会自动匹配具有相同名称的变量,从而使得顶点着色器的输出可以作为片元着色器的输入。

在OpenGL渲染管线中,着色器阶段之间的数据传递是通过 变量名称、类型和顺序 来确保一致性的。通常,顶点着色器的输出(out 变量)会作为下游阶段(如片元着色器或几何着色器)的输入(in 变量)。确保变量名称、类型和顺序一致是实现数据正确传递的关键。

(8)测试与混合

深度测试(Depth Test) → 确保正确的遮挡关系。
模板测试(Stencil Test) → 实现裁剪效果。
混合(Blending) → 处理透明度,如 glEnable(GL_BLEND)。

(9)Framebuffer帧缓冲

最终颜色数据被写入帧缓冲区(Framebuffer),并显示到屏幕上。帧缓冲有个地址,是在内存里。我们通过不停的向Framebuffer中写入数据, 显示控制器就自动的从Framebuffer中取数据并显示出来。

多个着色器都可以输出颜色?

顶点着色器:负责处理每个顶点的颜色,并传递给几何着色器或片元着色器。
几何着色器:(如果存在) 可以修改顶点的颜色并重新输出给片元着色器。
片元着色器: 计算最终的像素颜色,并写入帧缓冲区。

总结

✅GLSL语法类似C语言,但更适合GPU并行计算。
顶点着色器主要进行坐标变换
片元着色器主要计算像素颜色
✅变量修饰符 in、out、uniform 控制数据流。
✅向量、矩阵 计算是GLSL 的核心,优化GPU性能。

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

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

相关文章

ngx_http_core_merge_srv_conf

定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) {ngx_http_core_srv_conf_t *prev parent;ngx_http_core_srv_conf_t *conf child;ngx_str_t name;ngx_http_server_name_t…

uni-app:firstUI框架的选择器Select改造,添加一个搜索的插槽

<fui-select :show"showSiteType" :options"siteTypeList" textKey"dict_label" title"请选择站点类型" confirm"chooseSiteType" close"onCloseSiteType"><template v-slot:search><view><…

Debian/Ubuntu的networking的`/etc/network/interfaces`配置文件,如何配置route路由

Debian/Ubuntu的networking的/etc/network/interfaces配置文件,如何配置route路由 在 Debian/Ubuntu 系统中&#xff0c;通过 /etc/network/interfaces 配置文件配置路由&#xff08;静态路由或默认路由&#xff09;可以通过以下方式实现。以下是详细配置方法及示例&#xff1…

天梯赛 L2-024 部落

一个并查集题目&#xff0c;难点就在于统计总人数&#xff0c;使用map即可&#xff0c;还有需要注意的是编号不一定是小于N的&#xff0c;小于10000的&#xff0c;需要注意。 #include<bits/stdc.h> using namespace std; const int N 10010; int fa[N]; int find(int …

uniapp 微信小程序 使用ucharts

文章目录 前言一、组件功能概述二、代码结构分析2.1 模板结构 总结 前言 本文介绍一个基于 Vue 框架的小程序图表组件开发方案。该组件通过 uCharts 库实现折线图的绘制&#xff0c;并支持滚动、缩放、触摸提示等交互功能。文章将从代码结构、核心方法、交互实现和样式设计等方…

Axure项目实战:智慧运输平台后台管理端-承运商管理(中继器筛选)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:智慧运输平台后台管理端 主要内容:承运商管理 应用场景:条件筛选、增删改查操作、台账制作 案例展示: 正文内容: 承运商管理模块主要解决平台对承运商的管理,包括新增承运商作,审核承运商申请,修…

[论文笔记] Deepseek技术报告解读: MLAMTP

1. RMSNorm 归一化层 class RMSNorm(nn.Module):def __init__(self, dim: int, eps: float = 1e-8):super().__init__()self.eps = epsself.weight = nn.Parameter(torch.ones(dim)) # 可学习的缩放参数def _norm(self, x: torch.Tensor):return x * torch.rsqrt(x.pow(2).me…

八款内网电脑监控软件:探寻适配企业需求的数字化监管方案组合

数字化办公的时代背景下&#xff0c;企业管理面临着前所未有的挑战。如何实现对员工办公行为的高效管理&#xff0c;确保网络资源的合理利用&#xff0c;成为众多企业决策者和高级管理人员亟待解决的重要问题。内网电脑监控软件作为一种有效的管理工具&#xff0c;应运而生。本…

Flutter求助贴

报错信息&#xff1a;The Dart VM Service was not discovered after 30 seconds. This is taking much longer than expected... 基本情况&#xff1a; 硬件&#xff1a;mac(15.3.1)&#xff0c;iPad(iOS 16.6),iPhone 16 pro(iOS 18.4) 项目环境 flutter&#xff1a;3.16…

React(九)React Hooks

初识Hook 我们到底为什么需要hook那? 函数组件类组件存在问题 函数组件存在的问题&#xff1a; import React, { PureComponent } from reactfunction HelloWorld2(props) {let message"Hello world"// 函数式组件存在的缺陷&#xff1a;// 1.修改message之后&a…

数据清洗的具体内容

&#xff08;一&#xff09;ETL介绍 “ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;、加载&#xff08;Load&#xff09;至目的端的过程。ETL一词较…

【动手学深度学习】#7 现代卷积神经网络

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 概述 硬件性能和大数据的发展为深度卷积神经网络&#xff08;AlexNet&#xff09;的实现提供了条件。VGG首次将块的思想用于搭建网络。NiN将多层感知机应用在…

Jenkins + CICD流程一键自动部署Vue前端项目(保姆级)

git仓库地址&#xff1a;参考以下代码完成,或者采用自己的代码。 南泽/cicd-test 拉取项目代码到本地 使用云服务器或虚拟机采用docker部署jenkins 安装docker过程省略 采用docker部署jenkins&#xff0c;注意这里的命令&#xff0c;一定要映射docker路径&#xff0c;否则无…

使用 libevent 处理 TCP 粘包问题(基于 Content-Length 或双 \r\n)

在基于 libevent 的 TCP 服务器开发中,处理消息边界是常见需求。以下是两种主流分包方案的完整实现: 一、基于 Content-Length 的分包方案 1.1 数据结构设计 typedef struct {struct bufferevent *bev;int content_length; // 当前消息的预期长度int received_bytes; //…

酶动力学预测工具CataPro安装教程

简介&#xff1a;预测酶动力学参数是酶发现和酶工程中的一项重要任务。在此&#xff0c;研究人员基于蛋白质语言模型、小分子语言模型和分子指纹&#xff0c;提出了一种名为 CataPro 的新酶动力学参数预测算法。该研究从 BRENDA 和 SABIO-RK 数据库中收集了最新的转化率&#x…

项目实战:基于Spring WebFlux与LangChain4j实现大语言模型流式输出

一、背景 在大语言模型&#xff08;LLM&#xff09;应用场景中&#xff0c;GPT-4等模型的响应生成往往需要数秒至数十秒的等待时间。传统同步请求会导致用户面对空白页面等待&#xff0c;体验较差。本文通过Spring WebFlux响应式编程与SSE服务器推送技术&#xff0c;实现类似打…

Go语言入门经典:数组与切片详解

Go语言入门经典&#xff1a;数组与切片详解 数组和切片是Go语言中两种重要的数据结构。数组是一种固定长度的集合&#xff0c;而切片则是一种灵活的动态集合。本章将详细讲解数组和切片的定义、初始化、访问元素、动态操作等内容&#xff0c;帮助读者全面掌握这两种数据结构。…

uniapp中如何用iconfont来管理图标集成到我们开发的项目中

我们在开发不管小程序还是APP的过程中都会用到图标这个东西,那么iconfont提供了对应的功能,怎么才能方便的集成到我们的小程序或者APP项目中,目标是方便调用并且方便管理。 首先注册ICONFONT账号 www.iconfont.cn中去注册即可选择我们需要的图标如下 我们搜索我们需要的图…

从实用的角度聊聊Linux下文本编辑器VIM

本文从实用的角度聊聊Vim的常用命令。何为实用&#xff1f;我举个不实用的例子大家就明白了&#xff0c;用vim写代码。;) “vim是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用&#xff0c;和Emacs并列成…

优化程序命名:提升专业感与用户体验

在软件开发的广阔天地中&#xff0c;程序命名这一环节常常被开发者们忽视。不少程序沿用着简单直白、缺乏雕琢的名字&#xff0c;如同素面朝天的璞玉&#xff0c;虽不影响其核心功能的发挥&#xff0c;但却在无形之中错失了许多提升用户印象与拓展应用场景的机会。今天&#xf…