OpenGL Chan视频学习-7 Writing a Shader inOpenGL

news2025/5/29 15:08:13

bilibili视频链接:
【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p=5&vd_source=44b77bde056381262ee55e448b9b1973

函数网站:

docs.gl

说明:
1.之后就不再整理具体函数了,网站直接翻译会更直观也会有更多注意点。直接通过csdn索引查找反而会慢。

2.代码区域会单独注释功能参数返回值和相关注意事项。
3.课程学习从4-本节,如果有些函数没有注释可以看专栏里面的前面发表的文章,一般会有解释。

4.如果觉得代码注释白色字体不太直观可以直接copy到相应软件看。
5.有两种版本的可供查看:注释全面的和值注释功能的简洁版的,可以在索引里面找到相关代码查看。
6.希望能帮到你。

7.有错误请跟我说明一下,可能整理的时候没有检查好。

一、知识点整理

1.1着色器程序

1.1.1 解释

  • 功能:创建着色器程序
  • 参数:顶点着色器代码、片段着色器代码

1.1.2过程

连接两个着色器到单独着色器程序,并返回唯一标识符,所以可以绑定一个顶点着色器,用顶点缓冲获得一个返回id并在glGenBuffers里面去访问。

1.1.3 程序

static unsigned int CompilesShader(unsigned int type, const std::string& source)

//功能:编译着色器代码
//参数:1.type表示着色器类型,GL_VERTEX_SHADER表示顶点着色器,GL_FRAGMENT_SHADER表示片段着色器
//2.source表示着色器源代码的字符串
//返回值:编译成功的着色器对象ID,失败则返回0
static unsigned int CompilesShader(unsigned int type, const std::string& source)
{
    //功能:创建着色器对象
    //参数:1.type表示着色器类型,GL_VERTEX_SHADER表示顶点着色器,GL_FRAGMENT_SHADER表示片段着色器
    //返回值:着色器对象ID
    unsigned int id = glCreateShader(type);
    //功能:设置着色器源代码.
    //通过传递的字符串指针,将源代码复制到着色器对象中
    //注意:这里的src指针必须指向以null结尾的字符串,否则会导致编译错误
    //c_str()函数可以将std::string转换为const char*类型
    //也可const char* src = &source[0];
    const char* src = source.c_str();
    //功能:替换着色器对象中的源代码。将该id的指定着色器的源代码设置为src指针指向的字符串
    //参数:1.id表示着色器对象ID
    //2.1表示着色器源代码的数量
    //3.src指针表示着色器源代码的字符串指针
    //4.nullptr表示长度为0的字符串指针
    glShaderSource(id, 1, &src, nullptr);
    //功能:编译着色器对象的源代码
    //参数:1.id表示着色器对象ID
    glCompileShader(id);

    //设置返回着色器的对象ID
    //这里不能写成unsigned,会报错——
    // "unsigned int *" 类型的实参与 "GLint *" (aka "int *") 类型的形参不兼容
    int result;
    //功能:从着色器对象返回一个参数,表示编译是否成功。
    //参数:1.id表示着色器对象ID
    //2.GL_COMPILE_STATUS表示对象的参数
    //3.result指针表示编译成功/请求的对象参数值
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);

    //如果编译失败,则输出错误信息
    if (result == GL_FALSE)
    {
        int length;
        //功能:获取编译错误信息的长度
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        //分配内存,用于存储编译错误信息
        //alloca()函数用于分配堆栈内存,避免堆内存碎片化
        //alloca和new的区别:alloca分配的内存不会被自动释放,而new分配的内存会被自动释放
        //alloca和malloc的区别:alloca分配的内存大小必须是编译器确定的,而malloc分配的内存大小可以由用户指定
        char* message = (char*)alloca(length*sizeof(char));
        //功能:获取编译错误信息
        //参数:1.id表示着色器对象ID
        //2.length表示编译错误信息的长度,指定用于存储返回的信息日志的字符缓冲区大小。
        //3.length指针表示实际获取的编译错误信息的长度,返回在infoLog中返回的字符串长度(不包括终止符)。
        //4.message指针表示编译错误信息的字符串指针
        glGetShaderInfoLog(id, length, &length, message);
        std::cout << "Failed to compile shader!" << (type == GL_VERTEX_SHADER? "Vertex" : "Fragment") << "shader!" << std::endl;
        std::cout << message << std::endl;
        //删除着色器对象
        glDeleteShader(id);
        return 0;
    }

    //TODO:错误处理ing
    return id;
}

static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)

//功能:创建着色器程序
//将顶点着色器和片段着色器的代码连接(作为字符串)编译为一个程序对象,并返回程序对象
//参数:顶点着色器代码、片段着色器代码
//返回值:着色器程序对象的ID
//定义为静态函数:
// 静态函数可以使函数的可见性降低,仅限于被定义的文件内部使用。
// 这有助于封装代码,使得其他文件无法直接调用这个函数。
// 可以避免命名冲突
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
    //创建程序对象
    //返回:程序对象ID。创建的程序对象是一个ID值,用于标识一个OpenGL程序对象
    unsigned int program = glCreateProgram();
    //编译顶点着色器对象
    //参数:1.GL_VERTEX_SHADER表示创建顶点着色器对象
    //2.vertexShader.c_str()表示顶点着色器源代码的字符串指针
    //返回值:编译成功的着色器对象ID
    unsigned int vs = CompilesShader(GL_VERTEX_SHADER, vertexShader);
    //编译片段着色器对象
    //参数:1.GL_FRAGMENT_SHADER表示创建片段着色器对象
    //2.fragmentShader.c_str()表示片段着色器源代码的字符串指针
    //返回值:编译成功的着色器对象ID
    unsigned int fs = CompilesShader(GL_FRAGMENT_SHADER, fragmentShader);

    //功能:将编译好的着色器对象附加到程序对象中
    //参数:1.program表示程序对象ID
    //2.vs表示顶点着色器对象ID
    //3.fs表示片段着色器对象ID
    glAttachShader(program, vs);
    glAttachShader(program, fs);

    //功能:链接程序对象
    //实际上链接是通过把所有着色器对象中的代码合并到一个程序对象中,然后编译这个程序对象来实现的。
    //参数:1.program表示程序对象ID
    glLinkProgram(program);

    //功能:验证着色器程序对象是否可以在当前OpenGL状态中执行。检查着色器程序的完整性和可执行性。
    //如果验证失败,OpenGL会设置一个错误标志,可以通过glGetProgramiv函数查询验证结果和错误信息。
    //验证过程生成的信息将存储在 program 的信息日志中。
    // 验证信息可能是一个空字符串,或者是一个包含当前程序对象与当前OpenGL状态其余部分如何交互的信息的字符串。
    // 验证操作的状态将作为程序对象状态的一部分被存储。
    // 如果验证成功,此值将被设置为GL_TRUE,否则将被设置为GL_FALSE。
    //可以通过调用glGetProgram并传入参数program和GL_VALIDATE_STATUS来查询。
    glValidateProgram(program);

    //删除着色器对象,因为它们已经被链接到程序对象中
    glDeleteShader(vs);
    glDeleteShader(fs);

    //返回着色器程序
    return program;
}

int main增加代码

 //准备着色器代码
 //core表示使用的是核心配置文件,它移除了旧版本中一些过时的OpenGL函数和功能,使得代码更加清晰和高效。
 //layout(location = 0) : 这是一个布局限定符(layout qualifier)
 // 用于指定输入变量在着色器程序中的位置索引。
 //in vec4 position; : 这是一个输入变量声明。
 // in关键字表示该变量是输入到顶点着色器的,
 // vec4表示数据类型为4维浮点数向量(vec4),
 // position是变量的名称。
 // 这行代码的意思是顶点着色器接收一个4维浮点数向量的输入,变量名是position,用于表示顶点的位置。
 // 实际应用中,通常只使用前三个分量(x, y, z)来表示顶点的位置,第四个分量(w)用于透视除法等操作。
 //void main(): 这是顶点着色器的主函数声明。每个顶点着色器程序都必须有一个名为main的函数。
 //gl_Position = position;将输入的顶点位置position赋值给gl_Position。
 // gl_Position是OpenGL内置的变量,用于存储顶点在裁剪空间中的位置。
 //在这个简单的例子中,顶点着色器不做任何额外的处理,只是将输入的顶点位置直接输出到裁剪空间。
 // 这意味着顶点的位置不会被变换,而是直接基于裁剪空间的坐标系来绘制。
 std::string vertexShader =
     "#version 330 core\n"
     "\n"
     "layout (location = 0) in vec4 position;\n"
     "void main()\n"
     "{\n"
     "   gl_Position = position;\n"
     "}\n";
 //vec4 是 GLSL(OpenGL Shading Language)中的一个内置类型,表示一个包含四个浮点数的向量。
 // 这四个浮点数通常用于表示颜色的 RGBA 值,即红(R)、绿(G)、蓝(B)和透明度(A)。
 //color 是片段着色器中的一个输出变量。用于设置最终输出到屏幕上的颜色。
 std::string fragmentShader =
     "#version 330 core\n"
     "\n"
     "layout (location = 0) out vec4 color;\n"
     "void main()\n"
     "{\n"
     "   color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
     "}\n";

 //创建着色器程序
 unsigned int shader = CreateShader(vertexShader, fragmentShader);
 //使用着色器程序
 glUseProgram(shader);

1.2 glCreateProgram

1.2.1c规范

1.2.2功能

创建程序对象

1.2.3实例

unsigned int program = glCreateProgram();

1.2.4描述

创建一个空的程序对象并返回一个非零值,通过该值可以引用它。程序对象是一个可以附加着色器对象的对象。这提供了一种指定将要链接以创建程序的着色器对象的机制。它还提供了一种检查将用于创建程序的着色器兼容性的方法(例如,检查顶点着色器和片段着色器之间的兼容性)。当不再作为程序对象的一部分所需时,着色器对象可以被分离。

通过成功地使用glAttachShader将着色器对象附加到程序对象上,成功地使用glCompileShader编译着色器对象,并成功地使用glLinkProgram链接程序对象,可以在程序对象中创建一个或多个可执行文件。当调用glUseProgram时,这些可执行文件将被加入到当前状态中。程序对象可以通过调用glDeleteProgram来删除。当程序对象不再属于任何上下文的当前渲染状态时,与程序对象相关的内存将被删除。

像显示列表和纹理对象一样,程序对象的命名空间也可以在一组上下文中共享,只要这些上下文的服务器端共享相同的地址空间。如果命名空间在上下文中共享,任何附加的对象及其相关数据也会被共享。

如果在创建程序对象时发生错误,此函数将返回0。

1.3glCreateShader

1.3.1c规范

1.3.2功能

创建着色器对象

1.3.3描述

创建一个空的着色器对象并返回一个非零值,通过该值可以引用它。着色器对象用于维护定义着色器的源代码字符串。shaderType 指示要创建的着色器类型。支持两种类型的着色器。类型为 GL_VERTEX_SHADER 的着色器是旨在在可编程顶点处理器上运行的着色器。类型为 GL_FRAGMENT_SHADER 的着色器是旨在在可编程片段处理器上运行的着色器。 当创建着色器对象时,其GL_SHADER_TYPE参数设置为GL_VERTEX_SHADER或GL_FRAGMENT_SHADER,具体取决于shaderType的值。

像纹理对象一样,着色器对象的命名空间可以在一组上下文中共享,只要这些上下文的服务器端共享相同的地址空间。如果命名空间在上下文中共享,任何附加的对象及其相关数据也会被共享。

如果在创建着色器对象时发生错误,此函数将返回0。

GL_INVALID_ENUM 生成如果 shaderType 不是可接受的值。

1.4glShaderSource

1.4.1c规范

1.4.2功能

替换着色器对象中的源代码

1.4.3参数

  • shader

指定要替换源代码的着色器对象的句柄。

  • count

指定 string 和 length 数组中的元素数量。

  • string

指定一个字符串数组的指针,这些字符串包含要加载到着色器中的源代码。

  • length

指定一个字符串长度的数组。

 1.4.4代码

glShaderSource(id, 1, &src, nullptr);

1.4.5描述

glShaderSource 将源代码设置为 shader 中指定的字符串数组。任何之前存储在着色器对象中的源代码将被完全替换。字符串数组的长度由 string 指定。如果 count 为 length,则每个字符串被认为是 null 终止的。如果 NULL 是一个值,它指向一个包含每个相应元素的字符串长度的数组。每个元素在 length 数组中可能包含相应字符串的长度(不包括 null 字符作为字符串长度的一部分)或一个小于 0 的值,表示字符串是 null 终止的。源代码字符串在此时不会被扫描或解析;它们只是被复制到指定的着色器对象中。

OpenGL在glShaderSource被调用时复制着色器源代码字符串,因此应用程序可以在函数返回后立即释放其源代码字符串的副本。

GL_INVALID_VALUE 生成,如果 shader 不是 OpenGL 生成的值。

GL_INVALID_OPERATION 生成 shader 如果不是着色器对象。

GL_INVALID_VALUE 生成如果 count 小于 0。

1.5glCompileShader

1.5.1c规范

1.5.2功能

编译着色器对象

1.5.3参数

  • hader

    指定要编译的着色器对象。

 1.5.4代码

glCompileShader(id);

1.5.5描述

对于支持着色器编译的实现,glCompileShader 编译由 shader 指定的着色器对象中存储的源代码字符串。 编译状态将作为着色器对象状态的一部分进行存储。如果着色器编译时没有错误并且可以使用,则此值将被设置为GL_TRUE,否则为GL_FALSE。可以通过调用glGetShaderiv并传入参数shader和GL_COMPILE_STATUS来查询。 着色器的编译可能会因多种原因失败,具体原因由OpenGL ES 着色语言规范规定。无论编译是否成功,都可以通过调用glGetShaderInfoLog从着色器对象的信息日志中获取编译信息。

着色器编译器支持是可选的,因此在使用之前必须通过调用 glGet 与参数 GL_SHADER_COMPILER 进行查询。glShaderSource、glCompileShader、glGetShaderPrecisionFormat 和 glReleaseShaderCompiler 在不支持着色器编译器的实现中将分别生成 GL_INVALID_OPERATION。此类实现提供了 glShaderBinary 作为提供预编译着色器二进制数据的替代方案。

GL_INVALID_OPERATION如果不受支持的着色器编译器生成。

GL_INVALID_VALUE 生成,如果 shader 不是 OpenGL 生成的值。

GL_INVALID_OPERATION 生成 shader 如果不是着色器对象。

1.6glAttachShader

1.6.1c规范

1.6.2功能

 将着色器对象附加到程序对象

1.6.3参数

  • program

指定将着色器对象附加到的程序对象。

  • shader

指定要附加的着色器对象。

 1.6.4代码

glAttachShader(program, vs);
glAttachShader(program, fs);

1.6.5描述

为了创建一个可执行文件,必须有一种方法来指定将要链接在一起的一系列事物。程序对象提供了这种机制。要链接在一起的着色器必须首先附加到该程序对象。glAttachShader将由shader指定的着色器对象附加到由program指定的程序对象。shader这表示program将被包含在对

可以对着色器对象执行的所有操作在着色器对象是否附加到程序对象上都是有效的。允许在将源代码加载到着色器对象中或编译着色器对象之前将着色器对象附加到程序对象上。允许附加多个相同类型的着色器对象,因为每个着色器对象可能包含完整着色器的一部分。还允许将着色器对象附加到一个以上的程序对象上。如果在着色器对象附加到程序对象时删除它,它将被标记为删除,直到调用glDetachShader 将其从所有附加的程序对象中分离出来,才会进行删除。

1.7glValidateProgram

1.7.1c规范

1.7.2功能

根据当前 GL 状态验证程序管道对象。
验证着色器程序对象是否可以在当前OpenGL状态中执行。具体来说,它会检查着色器程序中所有着色器的接口是否匹配,包括输入和输出变量的类型、名称和数量。此外,它还会检查着色器程序是否可以在当前的OpenGL版本和上下文中正确执行。

1.7.3参数

  • program

    指定要验证的程序对象的句柄。即要验证的着色器程序对象的ID。这个ID在之前通过glCreateProgram()创建,并通过glAttachShaderglLinkProgram附加和链接了顶点着色器和片段着色器。

 1.7.4代码

glValidateProgram(program);

1.7.5描述

这个函数会检查着色器程序的完整性和可执行性。它验证着色器程序的接口是否正确,并且在特定的OpenGL环境中是否可以正确地执行。

如果验证失败,OpenGL会设置一个错误标志,可以通过glGetProgramiv函数查询验证结果和错误信息。

glValidateProgram 检查是否可以在当前OpenGL状态下调用包含在 program 中的可执行文件。验证过程生成的信息将存储在 program 的信息日志中。验证信息可能是一个空字符串,或者是一个包含当前程序对象与当前OpenGL状态其余部分如何交互的信息的字符串。这为OpenGL实现者提供了一种传达当前程序为何效率低下、不优化、无法执行等更多信息的方法。 验证操作的状态将作为程序对象状态的一部分被存储。如果验证成功,此值将被设置为GL_TRUE,否则将被设置为GL_FALSE。可以通过调用glGetProgram并传入参数program和GL_VALIDATE_STATUS来查询。如果验证成功,program在当前状态下保证会被执行。否则,program保证不会执行。 此功能通常仅在应用程序开发期间有用。存储在信息日志中的信息字符串完全取决于实现;因此,应用程序不应期望不同的 OpenGL 实现产生相同的信息字符串。

此函数模拟了当渲染命令发出时,OpenGL 实现必须执行的验证操作,此时可编程着色器是当前状态的一部分。如果发生以下情况,将生成错误GL_INVALID_OPERATION:

        当前程序对象中的任意两个活动采样器是不同类型的,但引用相同的纹理图像单元,

         程序中活动采样器的数量超过了允许的最大纹理图像单元数量。

当发出渲染命令时,应用程序可能难以捕获这些错误或会导致性能下降。因此,建议应用程序在开发过程中调用glValidateProgram以检测这些问题。

GL_INVALID_VALUE 生成,如果 program 不是 OpenGL 生成的值。

GL_INVALID_OPERATION 生成 program 如果不是程序对象。

1.8glLinkProgram

1.8.1c规范

1.8.2功能

链接程序对象

1.8.3参数

  • program

    指定要链接的程序对象的句柄。

 1.8.4代码

glLinkProgram(program);

1.8.5描述

glLinkProgram 将指定的程序对象链接 program。如果 GL_VERTEX_SHADER类型的任何着色器对象附加到 program,它们将被用来创建一个将在可编程顶点处理器上运行的可执行文件。如果 GL_GEOMETRY_SHADER类型的任何着色器对象附加到 program,它们将被用来创建一个将在可编程几何处理器上运行的可执行文件。如果 GL_FRAGMENT_SHADER类型的任何着色器对象附加到 program,它们将被用来创建一个将在可编程片段处理器上运行的可执行文件。

链接操作的状态将作为程序对象状态的一部分被存储。如果程序对象链接成功且无错误,该值将被设置为GL_TRUE,否则为GL_FALSE。可以通过调用glGetProgram并传入参数program和GL_LINK_STATUS来查询。

成功的链接操作后,属于program的所有活动的用户定义的统一变量将被初始化为0,并且每个程序对象的活动统一变量将被分配一个可以通过调用glGetUniformLocation查询的位置。同时,任何未绑定到通用顶点属性索引的活动用户定义的属性变量将在此时绑定到一个。

程序对象的链接可能会因多种原因失败,具体原因请参阅OpenGL着色语言规范。以下列出了一些会导致链接错误的条件。

实现所支持的活动属性变量数量已超出。

均匀变量的存储限制已超出。

实现支持的活动统一变量数量已超出。

顶点、几何或片段着色器的main函数缺失。

在片段着色器中实际使用的可变变量没有以相同的方式声明(或根本未声明)在顶点着色器中,如果存在几何着色器,则在几何着色器中也是如此。

对函数或变量名的引用未解析。

声明一个全局共享变量,有两种不同类型或两种不同的初始值。

一个或多个附加的着色器对象编译未成功。

绑定通用属性矩阵时导致矩阵的一些行超出了允许的最大值GL_MAX_VERTEX_ATTRIBS。

无法找到足够的连续顶点属性插槽来绑定属性矩阵。

程序对象包含用于形成片段着色器的对象,但不包含用于形成顶点着色器的对象。

程序对象包含用于形成几何着色器的对象,但不包含用于形成顶点着色器的对象。

程序对象包含用于形成几何着色器的对象,但未在任何编译的几何着色器对象中指定输入原始类型、输出原始类型或最大输出顶点数。

程序对象包含用于形成几何着色器的对象,并且在多个几何着色器对象中几何输入类型、几何输出类型或最大输出顶点数的指定方式不同。

片段着色器中活动输出的数量大于GL_MAX_DRAW_BUFFERS的值。

该程序有一个活动输出被分配到一个大于或等于GL_MAX_DUAL_SOURCE_DRAW_BUFFERS的值的位置。

该程序有一个活动输出被分配到一个大于或等于一的索引。

多个变化输出变量绑定到相同的编号和索引。

显式绑定分配没有为链接器自动分配一个位置留下足够的空间,对于需要多个连续位置的可变输出数组来说是这样。

glTransformFeedbackVaryingscount指定的值非零,但程序对象没有顶点或几何着色器。

任何在glTransformFeedbackVaryings中指定的变量名在varyings数组中未在顶点着色器(或启用时的几何着色器)中声明为输出。

数组中的任意两个条目varyings由glTransformFeedbackVaryings指定相同的可变变量。

在任何变换反馈可变变量中捕获的组件总数大于常量GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,缓冲模式是GL_SEPARATE_ATTRIBS.。

当程序对象成功链接后,可以通过调用glUseProgram使程序对象成为当前状态的一部分。无论链接操作是否成功,程序对象的信息日志都会被覆盖。信息日志可以通过调用glGetProgramInfoLog来检索。

glLinkProgram 如果链接操作成功,并且指定的程序对象在之前调用 glUseProgram 后已经正在使用中,则还会将生成的可执行文件安装为当前渲染状态的一部分。如果当前正在使用的程序对象链接不成功,其链接状态将被设置为 GL_FALSE ,但其可执行文件和相关状态将保持在当前状态中,直到后续调用 glUseProgram 将其从使用中移除。在移除之前,它不能在成功重新链接之前成为当前状态的一部分。

如果program包含类型为GL_VERTEX_SHADER的着色器对象,并且可以包含类型为GL_GEOMETRY_SHADER的着色器对象,但不包含类型为GL_FRAGMENT_SHADER的着色器对象,顶点着色器可执行文件将被安装在可编程顶点处理器上,如果存在几何着色器可执行文件,将被安装在可编程几何处理器上,但不会在片段处理器上安装任何可执行文件。使用这种程序渲染原语的结果将是未定义的。

程序对象的信息日志会在链接操作时更新并生成程序。链接操作完成后,应用程序可以自由修改附加的着色器对象、编译附加的着色器对象、分离着色器对象、删除着色器对象以及附加额外的着色器对象。这些操作都不会影响程序对象的一部分的信息日志或程序。

如果链接操作不成功,任何关于之前链接操作的信息都会丢失(即,失败的链接不会恢复program的旧状态)。某些信息即使在链接操作不成功后仍然可以从program检索出来。例如programglGetActiveAttrib和glGetActiveUniform。

 1.9glDeleteShader

1.9.1c规范

1.9.2功能

删除着色器对象

1.9.3参数

  • shader

    指定要删除的着色器对象。

 1.9.4代码

glDeleteShader(vs);
glDeleteShader(fs);

1.9.5描述

glDeleteShader 释放指定的着色器对象所关联的内存并使该名称无效 shader。此命令有效地撤销了对 glCreateShader 的调用效果。

如果要删除的着色器对象附加到一个程序对象上,它将被标记为删除,但在它不再附加到任何程序对象、任何渲染上下文之前不会被删除(即,它必须从之前附加的位置 detachment 才会被删除)。shader的值为0将被静默忽略。

要确定一个对象是否已被标记删除,请调用 glGetShader 并传入参数 shader 和 GL_DELETE_STATUS。

GL_INVALID_VALUE 生成,如果 shader 不是 OpenGL 生成的值。

 1.10glGetShaderInfoLog

1.10.1c规范

1.10.2功能

返回着色器对象的信息日志

1.10.3参数

  • shader

指定要查询信息日志的着色器对象。

  • maxLength

指定用于存储返回的信息日志的字符缓冲区的大小。

  • length

返回在infoLog中返回的字符串长度(不包括终止符)。

  • infoLog

指定用于返回信息日志的字符数组。

 1.10.4代码

char* message = (char*)alloca(length*sizeof(char));
glGetShaderInfoLog(id, length, &length, message);

1.10.5描述

glGetShaderInfoLog返回指定着色器对象的信息日志。当着色器编译时,着色器对象的信息日志会进行修改。返回的字符串将是以空字符结尾的。

glGetShaderInfoLog 返回 infoLog 尽可能多的信息日志,最多 maxLength 个字符。实际返回的字符数(不包括空终止字符)由 length 指定。如果不需要返回字符串的长度,可以在 NULL 中传递 length 的值。通过调用 glGetShader 和传递值 GL_INFO_LOG_LENGTH 可以获得存储返回信息日志所需的缓冲区大小。

着色器对象的信息日志是一个字符串,可能包含诊断消息、警告消息和其他关于上次编译操作的信息。当着色器对象创建时,其信息日志将是一个长度为0的字符串。

GL_INVALID_VALUE 生成,如果 shader 不是 OpenGL 生成的值。

GL_INVALID_OPERATION 如果 shader 不是着色器对象,则生成。

GL_INVALID_VALUE 生成如果 maxLength 小于 0。

1.11glGetShaderiv

1.11.1c规范

1.11.2功能

从着色器对象返回一个参数

1.11.3参数

  • shader

指定要查询的着色器对象。

  • pname

指定对象参数。接受的符号名称是 GL_SHADER_TYPE、GL_DELETE_STATUS、GL_COMPILE_STATUS、GL_INFO_LOG_LENGTH、GL_SHADER_SOURCE_LENGTH。

  • params

返回请求的对象参数。

 1.11.4代码

glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);

1.11.5描述

如果生成错误,则不会更改params的内容。

GL_INVALID_VALUE 生成,如果 shader 不是 OpenGL 生成的值。

GL_INVALID_OPERATION 如果 shader 不是指向着色器对象,则生成

GL_INVALID_ENUM 生成 pname 如果不是接受的值。

 1.12glUseProgram

1.12.1c规范

1.12.2功能

将程序对象安装为当前渲染状态的一部分

1.12.3参数

  • program

指定用于当前渲染状态的程序对象的句柄。

 1.12.4代码

glUseProgram(shader);

1.12.5描述

 1.13glGetShaderInfoLog

1.13.1c规范

1.13.2功能

返回着色器对象的信息日志

1.13.3参数

  • shader

指定要查询信息日志的着色器对象。

  • maxLength

指定用于存储返回的信息日志的字符缓冲区大小。

  • length

返回在infoLog中返回的字符串长度(不包括终止符)。

  • infoLog

指定用于返回信息日志的字符数组。

 1.13.4代码

glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile shader!" << (type == GL_VERTEX_SHADER? "Vertex" : "Fragment") << "shader!" << std::endl;
std::cout << message << std::endl;

1.13.5描述

GL_INVALID_VALUE 生成,如果 shader 不是 OpenGL 生成的值。

GL_INVALID_OPERATION 生成 shader 如果不是着色器对象。

GL_INVALID_VALUE 生成如果 maxLength 小于 0。

二、代码

2.1 代码

全注释版

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include<iostream>

//功能:编译着色器代码
//参数:1.type表示着色器类型,GL_VERTEX_SHADER表示顶点着色器,GL_FRAGMENT_SHADER表示片段着色器
//2.source表示着色器源代码的字符串
//返回值:编译成功的着色器对象ID,失败则返回0
static unsigned int CompilesShader(unsigned int type, const std::string& source)
{
    //功能:创建着色器对象
    //参数:1.type表示着色器类型,GL_VERTEX_SHADER表示顶点着色器,GL_FRAGMENT_SHADER表示片段着色器
    //返回值:着色器对象ID
    unsigned int id = glCreateShader(type);
    //功能:设置着色器源代码.
    //通过传递的字符串指针,将源代码复制到着色器对象中
    //注意:这里的src指针必须指向以null结尾的字符串,否则会导致编译错误
    //c_str()函数可以将std::string转换为const char*类型
    //也可const char* src = &source[0];
    const char* src = source.c_str();
    //功能:替换着色器对象中的源代码。将该id的指定着色器的源代码设置为src指针指向的字符串
    //参数:1.id表示着色器对象ID
    //2.1表示着色器源代码的数量
    //3.src指针表示着色器源代码的字符串指针
    //4.nullptr表示长度为0的字符串指针
    glShaderSource(id, 1, &src, nullptr);
    //功能:编译着色器对象的源代码
    //参数:1.id表示着色器对象ID
    glCompileShader(id);

    //设置返回着色器的对象ID
    //这里不能写成unsigned,会报错——
    // "unsigned int *" 类型的实参与 "GLint *" (aka "int *") 类型的形参不兼容
    int result;
    //功能:从着色器对象返回一个参数,表示编译是否成功。
    //参数:1.id表示着色器对象ID
    //2.GL_COMPILE_STATUS表示对象的参数
    //3.result指针表示编译成功/请求的对象参数值
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);

    //如果编译失败,则输出错误信息
    if (result == GL_FALSE)
    {
        int length;
        //功能:获取编译错误信息的长度
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        //分配内存,用于存储编译错误信息
        //alloca()函数用于分配堆栈内存,避免堆内存碎片化
        //alloca和new的区别:alloca分配的内存不会被自动释放,而new分配的内存会被自动释放
        //alloca和malloc的区别:alloca分配的内存大小必须是编译器确定的,而malloc分配的内存大小可以由用户指定
        char* message = (char*)alloca(length*sizeof(char));
        //功能:获取编译错误信息
        //参数:1.id表示着色器对象ID
        //2.length表示编译错误信息的长度,指定用于存储返回的信息日志的字符缓冲区大小。
        //3.length指针表示实际获取的编译错误信息的长度,返回在infoLog中返回的字符串长度(不包括终止符)。
        //4.message指针表示编译错误信息的字符串指针
        glGetShaderInfoLog(id, length, &length, message);
        std::cout << "Failed to compile shader!" << (type == GL_VERTEX_SHADER? "Vertex" : "Fragment") << "shader!" << std::endl;
        std::cout << message << std::endl;
        //删除着色器对象
        glDeleteShader(id);
        return 0;
    }

    //TODO:错误处理ing
    return id;
}


//功能:创建着色器程序
//将顶点着色器和片段着色器的代码连接(作为字符串)编译为一个程序对象,并返回程序对象
//参数:顶点着色器代码、片段着色器代码
//返回值:着色器程序对象的ID
//定义为静态函数:
// 静态函数可以使函数的可见性降低,仅限于被定义的文件内部使用。
// 这有助于封装代码,使得其他文件无法直接调用这个函数。
// 可以避免命名冲突
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
    //创建程序对象
    //返回:程序对象ID。创建的程序对象是一个ID值,用于标识一个OpenGL程序对象
    unsigned int program = glCreateProgram();
    //编译顶点着色器对象
    //参数:1.GL_VERTEX_SHADER表示创建顶点着色器对象
    //2.vertexShader.c_str()表示顶点着色器源代码的字符串指针
    //返回值:编译成功的着色器对象ID
    unsigned int vs = CompilesShader(GL_VERTEX_SHADER, vertexShader);
    //编译片段着色器对象
    //参数:1.GL_FRAGMENT_SHADER表示创建片段着色器对象
    //2.fragmentShader.c_str()表示片段着色器源代码的字符串指针
    //返回值:编译成功的着色器对象ID
    unsigned int fs = CompilesShader(GL_FRAGMENT_SHADER, fragmentShader);

    //功能:将编译好的着色器对象附加到程序对象中
    //参数:1.program表示程序对象ID
    //2.vs表示顶点着色器对象ID
    //3.fs表示片段着色器对象ID
    glAttachShader(program, vs);
    glAttachShader(program, fs);

    //功能:链接程序对象
    //实际上链接是通过把所有着色器对象中的代码合并到一个程序对象中,然后编译这个程序对象来实现的。
    //参数:1.program表示程序对象ID
    glLinkProgram(program);

    //功能:验证着色器程序对象是否可以在当前OpenGL状态中执行。检查着色器程序的完整性和可执行性。
    //如果验证失败,OpenGL会设置一个错误标志,可以通过glGetProgramiv函数查询验证结果和错误信息。
    //验证过程生成的信息将存储在 program 的信息日志中。
    // 验证信息可能是一个空字符串,或者是一个包含当前程序对象与当前OpenGL状态其余部分如何交互的信息的字符串。
    // 验证操作的状态将作为程序对象状态的一部分被存储。
    // 如果验证成功,此值将被设置为GL_TRUE,否则将被设置为GL_FALSE。
    //可以通过调用glGetProgram并传入参数program和GL_VALIDATE_STATUS来查询。
    glValidateProgram(program);

    //删除着色器对象,因为它们已经被链接到程序对象中
    glDeleteShader(vs);
    glDeleteShader(fs);

    //返回着色器程序
    return program;
}


int main(void)
{
    GLFWwindow* window;

    //初始化glfw
    if (!glfwInit())
        return -1;

    //创建一个窗口模式的窗口并设置OpenGL上下文
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)//如果窗口创建失败,则终止程序
    {
        glfwTerminate();//释放glfw资源
        return -1;
    }

    //设置当前窗口的上下文,之后所有的OpenGL调用都会在这个上下文中进行
    glfwMakeContextCurrent(window);

    //初始化GLEW
    if (glewInit() != GLEW_OK)
        std::cout << "Error!" << std::endl;

    //打印OpenGL版本信息
    std::cout << glGetString(GL_VERSION) << std::endl;

    //准备数据
    float position[6] = {
        0.0f, 0.5f,
        -0.5f, -0.5f,
        0.5f, -0.5f
    };

    //定义缓冲区对象
    unsigned int buffer;
    //功能:生成缓冲区对象,并将数据写入缓冲区
    glGenBuffers(1, &buffer);
    //功能:将缓冲区对象绑定到目标
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    //功能:将数据写入缓冲区
    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);

    //功能:配置顶点属性指针
    //参数:1.0表示顶点属性数组的索引
    glEnableVertexAttribArray(0);
    //功能:指定顶点属性数组的索引、大小、数据类型、是否归一化、偏移量、数据指针
    //参数:1.0表示顶点属性数组的索引.和下面vertexShader(location=0)的0匹配
    //2.2表示顶点属性数组的大小,这里是2D坐标
    //3.GL_FLOAT表示数据类型
    //4.GL_FALSE表示是否归一化
    //5.sizeof(float)*2表示数据指针的字节大小
    //6.0表示偏移量
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    //准备着色器代码
    //core表示使用的是核心配置文件,它移除了旧版本中一些过时的OpenGL函数和功能,使得代码更加清晰和高效。
    //layout(location = 0) : 这是一个布局限定符(layout qualifier)
    // 用于指定输入变量在着色器程序中的位置索引。
    //in vec4 position; : 这是一个输入变量声明。
    // in关键字表示该变量是输入到顶点着色器的,
    // vec4表示数据类型为4维浮点数向量(vec4),
    // position是变量的名称。
    // 这行代码的意思是顶点着色器接收一个4维浮点数向量的输入,变量名是position,用于表示顶点的位置。
    // 实际应用中,通常只使用前三个分量(x, y, z)来表示顶点的位置,第四个分量(w)用于透视除法等操作。
    //void main(): 这是顶点着色器的主函数声明。每个顶点着色器程序都必须有一个名为main的函数。
    //gl_Position = position;将输入的顶点位置position赋值给gl_Position。
    // gl_Position是OpenGL内置的变量,用于存储顶点在裁剪空间中的位置。
    //在这个简单的例子中,顶点着色器不做任何额外的处理,只是将输入的顶点位置直接输出到裁剪空间。
    // 这意味着顶点的位置不会被变换,而是直接基于裁剪空间的坐标系来绘制。
    std::string vertexShader =
        "#version 330 core\n"
        "\n"
        "layout (location = 0) in vec4 position;\n"
        "void main()\n"
        "{\n"
        "   gl_Position = position;\n"
        "}\n";
    //vec4 是 GLSL(OpenGL Shading Language)中的一个内置类型,表示一个包含四个浮点数的向量。
    // 这四个浮点数通常用于表示颜色的 RGBA 值,即红(R)、绿(G)、蓝(B)和透明度(A)。
    //color 是片段着色器中的一个输出变量。用于设置最终输出到屏幕上的颜色。
    std::string fragmentShader =
        "#version 330 core\n"
        "\n"
        "layout (location = 0) out vec4 color;\n"
        "void main()\n"
        "{\n"
        "   color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
        "}\n";

    //创建着色器程序
    unsigned int shader = CreateShader(vertexShader, fragmentShader);
    //使用着色器程序
    glUseProgram(shader);

    //渲染循环,直到窗口被关闭
    while (!glfwWindowShouldClose(window))
    {
        //清除颜色缓冲区
        glClear(GL_COLOR_BUFFER_BIT);

        //功能:绘制三角形
        glDrawArrays(GL_TRIANGLES, 0, 3);

        //刷新缓冲区并交换窗口
        glfwSwapBuffers(window);

        //处理窗口事件,如键盘输入、鼠标移动等
        glfwPollEvents();
    }

    //删除着色器程序
    glDeleteProgram(shader);

    //释放 GLFW 库占用的所有资源。它在程序结束时调用,以确保不会出现资源泄漏。
    //调用 glfwTerminate() 后,GLFW 将释放所有与 OpenGL 上下文相关的资源,包括窗口、OpenGL 对象等。
    glfwTerminate();
    return 0;
}

简洁版,纯功能注释

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include<iostream>

//功能:编译着色器代码
static unsigned int CompilesShader(unsigned int type, const std::string& source)
{
    //功能:创建着色器对象
    unsigned int id = glCreateShader(type);
    //功能:设置着色器源代码.
    const char* src = source.c_str();
    //功能:替换着色器对象中的源代码。将该id的指定着色器的源代码设置为src指针指向的字符串
    glShaderSource(id, 1, &src, nullptr);
    //功能:编译着色器对象的源代码
    glCompileShader(id);

    //设置返回着色器的对象ID
    int result;
    //功能:从着色器对象返回一个参数,表示编译是否成功。
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);

    //如果编译失败,则输出错误信息
    if (result == GL_FALSE)
    {
        int length;
        //功能:获取编译错误信息的长度
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        //分配内存,用于存储编译错误信息
        char* message = (char*)alloca(length*sizeof(char));
        //功能:获取编译错误信息
        glGetShaderInfoLog(id, length, &length, message);
        std::cout << "Failed to compile shader!" << (type == GL_VERTEX_SHADER? "Vertex" : "Fragment") << "shader!" << std::endl;
        std::cout << message << std::endl;
        //删除着色器对象
        glDeleteShader(id);
        return 0;
    }

    //TODO:错误处理ing
    return id;
}


//功能:创建着色器程序
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
    //创建程序对象
    unsigned int program = glCreateProgram();
    //编译顶点着色器对象
    unsigned int vs = CompilesShader(GL_VERTEX_SHADER, vertexShader);
    //编译片段着色器对象
    unsigned int fs = CompilesShader(GL_FRAGMENT_SHADER, fragmentShader);

    //功能:将编译好的着色器对象附加到程序对象中
    glAttachShader(program, vs);
    glAttachShader(program, fs);

    //功能:链接程序对象
    glLinkProgram(program);

    //功能:验证着色器程序对象是否可以在当前OpenGL状态中执行。检查着色器程序的完整性和可执行性。
    glValidateProgram(program);

    //删除着色器对象,因为它们已经被链接到程序对象中
    glDeleteShader(vs);
    glDeleteShader(fs);

    //返回着色器程序
    return program;
}


int main(void)
{
    GLFWwindow* window;

    //初始化glfw
    if (!glfwInit())
        return -1;

    //创建一个窗口模式的窗口并设置OpenGL上下文
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)//如果窗口创建失败,则终止程序
    {
        glfwTerminate();//释放glfw资源
        return -1;
    }

    //设置当前窗口的上下文,之后所有的OpenGL调用都会在这个上下文中进行
    glfwMakeContextCurrent(window);

    //初始化GLEW
    if (glewInit() != GLEW_OK)
        std::cout << "Error!" << std::endl;

    //打印OpenGL版本信息
    std::cout << glGetString(GL_VERSION) << std::endl;

    //准备数据
    float position[6] = {
        0.0f, 0.5f,
        -0.5f, -0.5f,
        0.5f, -0.5f
    };

    //定义缓冲区对象
    unsigned int buffer;
    //功能:生成缓冲区对象,并将数据写入缓冲区
    glGenBuffers(1, &buffer);
    //功能:将缓冲区对象绑定到目标
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    //功能:将数据写入缓冲区
    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);

    //功能:配置顶点属性指针
    glEnableVertexAttribArray(0);
    //功能:指定顶点属性数组的索引、大小、数据类型、是否归一化、偏移量、数据指针
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    //准备着色器代码
    std::string vertexShader =
        "#version 330 core\n"
        "\n"
        "layout (location = 0) in vec4 position;\n"
        "void main()\n"
        "{\n"
        "   gl_Position = position;\n"
        "}\n";

    std::string fragmentShader =
        "#version 330 core\n"
        "\n"
        "layout (location = 0) out vec4 color;\n"
        "void main()\n"
        "{\n"
        "   color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
        "}\n";

    //创建着色器程序
    unsigned int shader = CreateShader(vertexShader, fragmentShader);
    //使用着色器程序
    glUseProgram(shader);

    //渲染循环,直到窗口被关闭
    while (!glfwWindowShouldClose(window))
    {
        //清除颜色缓冲区
        glClear(GL_COLOR_BUFFER_BIT);

        //功能:绘制三角形
        glDrawArrays(GL_TRIANGLES, 0, 3);

        //刷新缓冲区并交换窗口
        glfwSwapBuffers(window);

        //处理窗口事件,如键盘输入、鼠标移动等
        glfwPollEvents();
    }

    //删除着色器程序
    //glDeleteProgram(shader);

    //释放 GLFW 库占用的所有资源。
    glfwTerminate();
    return 0;
}

2.2运行结果

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

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

相关文章

顶会新方向:卡尔曼滤波+目标检测

卡尔曼虑波&#xff0b;目标检测创新结合&#xff0c;新作准确率突破100%! 一个有前景且好发论文的方向:卡尔曼滤波&#xff0b;目标检测! 这种创新结合&#xff0c;得到学术界的广泛认可&#xff0c;多篇成果陆续登上顶会顶刊。例如无人机竞速系统 Swift&#xff0c;登上nat…

一起学数据结构和算法(二)| 数组(线性结构)

数组&#xff08;Array&#xff09; 数组是最基础的数据结构&#xff0c;在内存中连续存储&#xff0c;支持随机访问。适用于需要频繁按索引访问元素的场景。 简介 数组是一种线性结构&#xff0c;将相同类型的元素存储在连续的内存空间中。每个元素通过其索引值&#xff08;数…

Linux基本指令篇 —— touch指令

touch是Linux和Unix系统中一个非常基础但实用的命令&#xff0c;主要用于操作文件的时间戳和创建空文件。下面我将详细介绍这个命令的用法和功能。 目录 一、基本功能 1. 创建空文件 2. 同时创建多个文件 3. 创建带有空格的文件名&#xff08;需要使用引号&#xff09; 二、…

【后端高阶面经:消息队列篇】23、Kafka延迟消息:实现高并发场景下的延迟任务处理

一、延迟消息的核心价值与Kafka的局限性 在分布式系统中,延迟消息是实现异步延迟任务的核心能力,广泛应用于订单超时取消、库存自动释放、消息重试等场景。 然而,Apache Kafka作为高吞吐的分布式消息队列,原生并不支持延迟消息功能,需通过业务层或中间层逻辑实现。 1.1…

Mac安装MongoDB数据库以及MongoDB Compass可视化连接工具

目录 一、安装 MongoDB 社区版 1、下载 MongoDB 2、配置环境变量 3、配置数据和日志目录 4、启动MongoDB服务 5、使用配置文件启动 6、验证服务运行 二、MongoDB可视化工具MongoDB Compass 一、安装 MongoDB 社区版 1、下载 MongoDB 大家可以直接在官方文档下安装Mo…

城市地下“隐形卫士”:激光甲烷传感器如何保障燃气安全?

城市“生命线”面临的安全挑战 城市地下管网如同人体的“血管”和“神经”&#xff0c;承载着燃气、供水、电力、通信等重要功能&#xff0c;一旦发生泄漏或爆炸&#xff0c;将严重影响城市运行和居民安全。然而&#xff0c;由于管线老化、违规施工、监管困难等问题&#xff0…

MySQL推出全新Hypergraph优化器,正式进军OLAP领域!

在刚刚过去的 MySQL Summit 2025 大会上&#xff0c;Oracle 发布了一个用于 MySQL 的全新 Hypergraph&#xff08;超图&#xff09;优化器&#xff0c;能够为复杂的多表查询生成更好的执行计划&#xff0c;从而优化查询性能。 这个功能目前只在 MySQL HeatWave 云数据库中提供&…

飞牛fnNAS手机相册备份及AI搜图

目录 一、相册安装应用 二、手机开启自动备份 三、开始备份 四、照片检索 五、AI搜图设置 六、AI搜图测试 七、照片传递 现代的手机,已经成为我们最亲密的“伙伴”。自从手机拍照性能提升后,手机已经完全取代了简单的卡片相机,而且与入门级“单反”相机发起了挑战。在…

消费类,小家电产品如何做Type-C PD快充快速充电

随着快充技术的快速发展现在市场上的产品接口都在逐渐转为Type-C接口&#xff0c;Type-C可以支持最大20V100W的功率。未来Type-C大概会变成最通用的接口&#xff0c;而你的产品却还是还在用其他的接口必然会被淘汰, 而要使小家电用到PD快充&#xff0c;就需要使用到Type-C快充诱…

连接表、视图和存储过程

1. 视图 1.1. 视图的概念 视图&#xff08;View&#xff09;&#xff1a;虚拟表&#xff0c;本身不存储数据&#xff0c;而是封装了一个 SQL 查询的结果集。 用途&#xff1a; 只显示部分数据&#xff0c;提高数据访问的安全性。简化复杂查询&#xff0c;提高复用性和可维护…

银河麒麟V10×R²AIN SUITE:用AI重构安全,以国产化生态定义智能未来

前言 银河麒麟是由国防科技大学研发、现由麒麟软件运营的国产操作系统&#xff0c;旨在打破国外技术垄断&#xff0c;保障国家信息安全。自2002年国家“863计划”启动以来&#xff0c;历经技术迭代与生态整合&#xff0c;现为国产操作系统领军品牌。其应用覆盖党政、国防、能源…

JavaScript- 3.2 JavaScript实现不同显示器尺寸的响应式主题和页面

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在HBuilder中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML和CSS系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查看&#xff…

15.进程间通信(一)

一、进程间通信介绍 进程间通信目的&#xff1a; 数据传输&#xff1a;一个进程需要将它的数据发送给另⼀个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xf…

AI 数据采集实战指南:基于 Bright Data 快速获取招标讯息

AI 数据采集实战指南&#xff1a;基于Bright Data快速获取招标讯息 在招标行业中&#xff0c;快速、准确地获取招标公告、项目详情、投标截止日期和其他关键招标信息&#xff0c;是投标企业提高竞标成功率的核心竞争力。然而&#xff0c;招标信息往往分散在不同的平台和网页&a…

cursor使用mcp

问题说明 mcp就相当于给AI安装了工具包&#xff0c;它可以调用获取接口文档&#xff0c;网页&#xff0c;数据库等&#xff0c;基本上所有的mcp都是node程序&#xff0c;少数需要python环境 使用说明 使用mcp-mysql举例&#xff0c;下面是配置json "mysql": {&qu…

小白成长之路-计算机网络(四)

文章目录 前言一、网络连接查看1.netstat2.ss3.bond绑定3.1准备好这三个文件3.2添加bond配置文件3.3关闭网络图形化服务3.4重启 4.Linux下的抓包工具Wireshark 5、web压力测试工具6、路由追踪命令 二、[练习题](https://blog.csdn.net/m0_70730767/article/details/148262716?…

【Agent】MLGym: A New Framework and Benchmark for Advancing AI Research Agents

arxiv: https://arxiv.org/pdf/2502.14499 简介 Meta 推出的 MLGym 框架及配套基准 MLGym-Bench&#xff0c;为评估和开发LLM Agent在 AI 研究任务中的表现提供了全新工具。作为首个基于 Gym 的机器学习任务环境&#xff0c;MLGym 支持强化学习等算法对代理的训练&#xff0c…

Web安全测试-文件上传绕过-DVWA

Web安全测试-文件上传绕过-DVWA 很多网站都有上传资源(图片或者文件)的功能&#xff0c;资源上传后一般会存储在服务器的一个文件夹里面&#xff0c;如果攻击者绕过了上传时候的文件类型验证&#xff0c;传了木马或者其他可执行的代码上去&#xff0c;那服务器就危险了。 我用…

现代 CSS 高阶技巧:实现平滑内凹圆角的工程化实践

通过 数学计算 CSS mask 复合遮罩 实现的真正几何内凹效果&#xff1a; 背景是一张图片&#xff0c;用来证明中间的凹陷是透明的。 完整代码&#xff1a; app.js import FormPage from "./pages/formPage"; import "./App.css"; const App () > {re…

【运维自动化-标准运维】如何实现在不同步骤间传递参数

当流程有多个步骤时&#xff0c;经常需要把前面某个个步骤处理的结果传递给下一个或后面的步骤使用&#xff08;输出作为输入&#xff09;&#xff0c;这就是跨步骤传参的场景&#xff0c;标准运维通过特有的标记符号"<SOPS_VAR>key:value</SOPS_VAR> "来…