LearnOpenGL - Android OpenGL ES 3.0 使用 FBO 进行离屏渲染

news2024/9/22 1:16:09

系列文章目录

  • LearnOpenGL 笔记 - 入门 01 OpenGL
  • LearnOpenGL 笔记 - 入门 02 创建窗口
  • LearnOpenGL 笔记 - 入门 03 你好,窗口
  • LearnOpenGL 笔记 - 入门 04 你好,三角形
  • OpenGL - 如何理解 VAO 与 VBO 之间的关系
  • LearnOpenGL - Android OpenGL ES 3.0 绘制三角形
  • LearnOpenGL - Android OpenGL ES 3.0 绘制纹理
  • LearnOpenGL - Android OpenGL ES 3.0 YUV 渲染

一、前言

利用 FBO(Framebuffer Object),我们可以实现离屏渲染。在前面的章节中,当我们调用 glDrawElements 后,手机屏幕上就会显示出绘制的图像。这意味着 OpenGL 将数据直接渲染到了手机屏幕上。通过使用 FBO,我们可以将数据渲染到纹理上,而不是直接渲染到屏幕,这个过程称为离屏渲染。

通过离屏渲染,我们可以在最终显示之前对图像进行复杂的处理。这种方法非常有用,比如在后期处理效果(如模糊、HDR、阴影等)中,或者在渲染多个场景以进行纹理贴图、环境映射等操作时。

假设你在开发一款图片处理软件,包含美颜、滤镜等功能。用户可以同时应用多种滤镜,如瘦脸、美白、长腿等,每种滤镜都通过 OpenGL Shader 进行处理和渲染。为实现这种功能,你可以设计一个图片渲染链。

一种直观的方法是为每种滤镜创建一个独立的模块,通过组合不同的模块实现多种滤镜的处理链。在处理链完成之前,我们无法将结果渲染到屏幕上。模块与模块之间的处理结果应该通过某种介质进行传递,这里使用的介质就是纹理。这也解释了我们为什么需要使用 FBO。

通过 FBO,我们可以在离屏状态下将渲染结果存储到纹理中,然后将该纹理作为输入传递给下一个滤镜模块。这样,整个处理链就可以逐步处理图像,直到应用所有滤镜后,将最终结果渲染到屏幕上。

在这里插入图片描述
本文所有代码在 FBODrawer.kt

二、FBO 简介

在这里插入图片描述
上图显示了帧缓冲区对象的结构,它提供了颜色缓冲区和深度缓冲区的替代品。如你所见,绘制操作并不是直接发生在帧缓冲区中的,而是发生在帧缓冲区所关联的对象(attachment)上。一个帧缓冲区有多个关联对象:颜色关联对象(color attachment)、深度关联对象(depth attachment)和模板关联对象(stencil attachment),分别用来替代颜色缓冲区、深度缓冲区和模板缓冲区。经过一些设置,OpenGL 就可以向帧缓冲区的关联对象中写入数据,就像写入颜色缓冲区或深度缓冲区一样。我们目前只关注颜色关联对象即可

每个关联对象又可以是两种类型的:纹理对象或渲染缓冲区对象(renderbuffer object)。当我们把纹理对象作为颜色关联对象关联到帧缓冲区对象后,OpenGL 就可以在纹理对象中绘图。渲染缓冲区对象表示一种更加通用的绘图区域,可以向其中写入多种类型的数据。

2.1 渲染缓冲对象

渲染缓冲区对象(Renderbuffer Object)是 OpenGL 和 OpenGL ES 中的一种缓冲区类型,用于离屏渲染。它提供了一种高效的方式来存储图像数据,特别适用于深度缓冲区和模板缓冲区。

渲染缓冲区对象的特点:

  1. 高效存储

    • 渲染缓冲区对象在实现上通常比纹理对象更高效,特别是用于深度和模板数据的存储。
    • 它不需要纹理过滤、MIP 贴图等特性,因此在某些场景下可以提供更好的性能。
  2. 不可直接采样

    • 与纹理对象不同,渲染缓冲区对象不能直接被着色器采样。
    • 这意味着你不能在着色器中直接访问渲染缓冲区对象中的数据,只能用于渲染过程。
  3. 用途广泛

    • 渲染缓冲区对象可以用作颜色、深度或模板缓冲区。
    • 在使用 FBO 进行离屏渲染时,渲染缓冲区对象可以作为这些附件类型附加到 FBO 上。

渲染缓冲区对象的使用步骤:

  1. 创建渲染缓冲区对象

    GLuint rbo;
    glGenRenderbuffers(1, &rbo);
    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    
  2. 分配存储

    • 根据用途分配存储,比如深度缓冲区、颜色缓冲区等。
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
    // 或者为颜色缓冲区分配存储
    // glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
    
  3. 附加到 FBO

    • 将渲染缓冲区对象附加到 FBO 作为附件。
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
    // 如果是颜色缓冲区
    // glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
    

纹理对象与渲染缓冲区对象的对比:

  • 纹理对象

    • 可以在着色器中采样,用于更灵活的图像处理。
    • 适用于需要在多个渲染步骤中反复使用和处理的图像数据。
  • 渲染缓冲区对象

    • 高效的存储和写入,但不能在着色器中采样。
    • 适用于深度缓冲区和模板缓冲区,或者不需要在着色器中采样的颜色缓冲区。

结合使用:

在实际应用中,常常将纹理对象和渲染缓冲区对象结合使用。比如:

  • 使用渲染缓冲区对象存储深度和模板数据,以获得更高的性能。
  • 使用纹理对象存储颜色数据,以便在后续渲染步骤中进行采样和处理。

例子:

假设我们在开发一个图片处理软件,通过 FBO 进行多重滤镜处理。每个滤镜模块会产生一个中间结果,这些中间结果通常存储在纹理对象中,因为它们需要被后续的滤镜模块采样和处理。然而,为了提高性能,我们可以使用渲染缓冲区对象来存储深度数据,因为这些数据通常不需要在滤镜处理中直接访问。

// 创建并绑定 FBO
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// 创建并附加颜色附件(纹理对象)
GLuint colorTex;
glGenTextures(1, &colorTex);
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);

// 创建并附加深度附件(渲染缓冲区对象)
GLuint depthRbo;
glGenRenderbuffers(1, &depthRbo);
glBindRenderbuffer(GL_RENDERBUFFER, depthRbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo);

// 检查 FBO 完整性
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
    // 处理错误
}

// 解绑 FBO 以恢复默认帧缓冲区
glBindFramebuffer(GL_FRAMEBUFFER, 0);

通过这种方式,我们可以高效地实现图像的离屏渲染和多重滤镜处理。

三、FBO 使用流程

GLES30.glGenTextures(1, fboTexIds)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0])
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, GLES30.GL_NONE)

// generate fbo id and config fbo
// 创建 FBO
GLES30.glGenFramebuffers(1, fbo);
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0])
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0])
GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, fboTexIds[0], 0)
GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, imageWidth, imageHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, GLES30.GL_NONE)
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, GLES30.GL_NONE)

这段代码用于在 OpenGL ES 3.0 中创建并配置一个帧缓冲区对象(FBO),并将一个纹理对象附加到这个帧缓冲区对象上作为颜色附件,以便进行离屏渲染。下面是对每行代码的详细解释:

创建和配置纹理对象

// 生成一个纹理对象,并将其ID存储在 fboTexIds 数组中
GLES30.glGenTextures(1, fboTexIds);

// 绑定生成的纹理对象
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]);

// 设置纹理过滤参数,线性过滤
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);

// 解除纹理绑定
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, GLES30.GL_NONE);
  1. 生成纹理对象

    • GLES30.glGenTextures(1, fboTexIds);:生成一个纹理对象,并将其ID存储在 fboTexIds 数组中。
  2. 绑定纹理对象

    • GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]);:将生成的纹理对象绑定到目标 GL_TEXTURE_2D
  3. 设置纹理参数

    • GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);:设置纹理的缩小过滤为线性过滤。
    • GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);:设置纹理的放大过滤为线性过滤。
  4. 解除纹理绑定

    • GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, GLES30.GL_NONE);:解除当前绑定的纹理对象。

创建和配置帧缓冲区对象

// 生成一个帧缓冲区对象,并将其ID存储在 fbo 数组中
GLES30.glGenFramebuffers(1, fbo);

// 绑定生成的帧缓冲区对象
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0]);

// 重新绑定之前创建的纹理对象
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]);

// 将纹理对象附加到帧缓冲区对象的颜色附件上
GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, fboTexIds[0], 0);

// 为纹理对象分配存储空间
GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, imageWidth, imageHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);

// 解除纹理绑定
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, GLES30.GL_NONE);

// 解除帧缓冲区对象的绑定
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, GLES30.GL_NONE);
  1. 生成帧缓冲区对象

    • GLES30.glGenFramebuffers(1, fbo);:生成一个帧缓冲区对象,并将其ID存储在 fbo 数组中。
  2. 绑定帧缓冲区对象

    • GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0]);:将生成的帧缓冲区对象绑定到目标 GL_FRAMEBUFFER
  3. 重新绑定纹理对象

    • GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]);:将之前创建的纹理对象重新绑定到目标 GL_TEXTURE_2D
  4. 附加纹理对象到帧缓冲区对象

    • GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, fboTexIds[0], 0);:将纹理对象作为颜色附件附加到帧缓冲区对象上。
  5. 为纹理对象分配存储空间

    • GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, imageWidth, imageHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);:为纹理对象分配存储空间,并指定其格式和尺寸。
  6. 解除纹理绑定

    • GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, GLES30.GL_NONE);:解除当前绑定的纹理对象。
  7. 解除帧缓冲区对象的绑定

    • GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, GLES30.GL_NONE);:解除当前绑定的帧缓冲区对象。

四、FBO 离屏渲染

为了演示 FBO 离屏渲染,我在 FBODrawer.kt 构建了两个 shader,第一个 shader 将 RGB 图片转换为灰度图,第二个 shader 则将纹理渲染到屏幕上。

companion object {
    val vertexShaderSource =
        """
        #version 300 es
        layout(location = 0) in vec3 a_posit
        layout(location = 1) in vec2 a_texco
        
        out vec2 v_texcoord;
        
        void main()
        {
            gl_Position = vec4(a_position, 1
            v_texcoord = a_texcoord;
        }
        """.trimIndent()
    val fragmentShaderSource =
        """
        #version 300 es
        precision mediump float;
        
        uniform sampler2D texture0;
        in vec2 v_texcoord;
        out vec4 fragColor;
        void main(void)
        {
            fragColor = texture(texture0, v_
        }
        """.trimIndent()
    val fboFragmentShaderSource =
        """
        #version 300 es
        precision mediump float;
        
        uniform sampler2D texture0;
        in vec2 v_texcoord;
        out vec4 fragColor;
        void main(void)
        void main(void)
		{
    		vec4 tempColor = texture(texture0, v_texcoord);
    		float gray = 0.299*tempColor.a + 0.587*tempColor.g + 0.114*tempColor.b;
    		fragColor = vec4(vec3(gray), 1.0);
		}
        """.trimIndent()
}
private val shader = Shader(
    vertexShaderSource,
    fragmentShaderSource
)
private val fboShader = Shader(
    vertexShaderSource,
    fboFragmentShaderSource
)

因此我们需要调用两次 draw 方法:

  1. 第一次,我们的 shader 输入是 rgb 图片的纹理,输出是灰度图纹理
  2. 第二次,我们的 shader 输入是灰度图纹理,然后直接绘制到纹理上
override fun draw() {
    // first, fbo off screen rendering
    GLES30.glViewport(0, 0, imageWidth, imageHeight)
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0])
    fboShader.use()
    fboShader.setInt("texture0", 0)
    GLES30.glBindVertexArray(vaos[0])
    GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexIds[0])
    GLES30.glDrawElements(GLES30.GL_TRIANGLES, indices.size, GLES30.GL_UNSIGNED_INT, 0)
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
    GLES30.glBindVertexArray(0)
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
    // second, draw texture to screen
    GLES30.glViewport(0, 0, screenWidth, screenHeight)
    shader.use()
    shader.setInt("texture0", 0)
    GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
    GLES30.glBindVertexArray(vaos[0])
    GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]) // 用 fbo 渲染的结果作为纹理的输入
    GLES30.glDrawElements(GLES30.GL_TRIANGLES, indices.size, GLES30.GL_UNSIGNED_INT, 0)
    GLES30.glBindVertexArray(0)
}

这段代码展示了如何使用帧缓冲区对象(FBO)进行离屏渲染,然后将离屏渲染的结果绘制到屏幕上。具体分为两个步骤:第一步是将场景渲染到 FBO,第二步是将 FBO 的内容作为纹理绘制到屏幕上。

第一步:离屏渲染到 FBO

// 设置视口为 FBO 的尺寸
GLES30.glViewport(0, 0, imageWidth, imageHeight);

// 绑定 FBO
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0]);

// 使用离屏渲染的着色器程序
fboShader.use();

// 设置着色器程序中纹理单元的位置
fboShader.setInt("texture0", 0);

// 绑定 VAO
GLES30.glBindVertexArray(vaos[0]);

// 激活纹理单元并绑定需要渲染的纹理
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexIds[0]);

// 绘制元素
GLES30.glDrawElements(GLES30.GL_TRIANGLES, indices.size, GLES30.GL_UNSIGNED_INT, 0);

// 解除纹理绑定
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);

// 解除 VAO 绑定
GLES30.glBindVertexArray(0);

// 解除 FBO 绑定,恢复默认帧缓冲区
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
  1. 设置视口GLES30.glViewport(0, 0, imageWidth, imageHeight) 设置渲染区域为 FBO 的尺寸。
  2. 绑定 FBOGLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0]) 绑定帧缓冲区对象。
  3. 使用着色器程序fboShader.use() 使用用于离屏渲染的着色器程序。
  4. 设置纹理单元fboShader.setInt("texture0", 0) 设置着色器程序中的纹理单元。
  5. 绑定 VAOGLES30.glBindVertexArray(vaos[0]) 绑定顶点数组对象(VAO)。
  6. 激活并绑定纹理GLES30.glActiveTexture(GLES30.GL_TEXTURE0)GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexIds[0]) 激活并绑定需要渲染的纹理。
  7. 绘制元素GLES30.glDrawElements(GLES30.GL_TRIANGLES, indices.size, GLES30.GL_UNSIGNED_INT, 0) 使用索引数组绘制三角形。
  8. 解除绑定:解除纹理和 VAO 的绑定,以及 FBO 的绑定,恢复默认帧缓冲区。

第二步:将 FBO 的内容绘制到屏幕上

// 设置视口为屏幕尺寸
GLES30.glViewport(0, 0, screenWidth, screenHeight);

// 使用屏幕渲染的着色器程序
shader.use();

// 设置着色器程序中纹理单元的位置
shader.setInt("texture0", 0);

// 清除颜色缓冲区
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

// 绑定 VAO
GLES30.glBindVertexArray(vaos[0]);

// 激活纹理单元并绑定 FBO 的纹理
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]);

// 绘制元素
GLES30.glDrawElements(GLES30.GL_TRIANGLES, indices.size, GLES30.GL_UNSIGNED_INT, 0);

// 解除 VAO 绑定
GLES30.glBindVertexArray(0);
  1. 设置视口GLES30.glViewport(0, 0, screenWidth, screenHeight) 设置渲染区域为屏幕的尺寸。
  2. 使用着色器程序shader.use() 使用用于屏幕渲染的着色器程序。
  3. 设置纹理单元shader.setInt("texture0", 0) 设置着色器程序中的纹理单元。
  4. 清除颜色缓冲区GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT) 清除颜色缓冲区。
  5. 绑定 VAOGLES30.glBindVertexArray(vaos[0]) 绑定顶点数组对象(VAO)。
  6. 激活并绑定纹理GLES30.glActiveTexture(GLES30.GL_TEXTURE0)GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fboTexIds[0]) 激活并绑定 FBO 的纹理(即离屏渲染的结果)。
  7. 绘制元素GLES30.glDrawElements(GLES30.GL_TRIANGLES, indices.size, GLES30.GL_UNSIGNED_INT, 0) 使用索引数组绘制三角形。
  8. 解除绑定:解除 VAO 的绑定。

总结

  • 第一步:在 FBO 中进行离屏渲染,将结果存储在一个纹理对象中。
  • 第二步:将 FBO 中的纹理对象作为输入,绘制到屏幕上。

这种方法在图形应用程序中非常常见,特别是在实现多重渲染效果(如后期处理、反射、阴影映射等)时。

参考

  • FBODrawer.kt
  • NDK OpenGLES3.0 开发(五):FBO 离屏渲染

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

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

相关文章

【Linux】对共享库加载问题的深入理解——基本原理概述

原理概述 【linux】详解——库-CSDN博客 共享库被加载后,系统会为该共享库创建一个结构,这个结构体中的字段描述了库的各种属性。在内存中可能会加载很多库,每一个库都用一个结构体描述。把这些结构体用一些数据结构管理起来,系…

短说V4.1.5及PC端V3.1.4正式版发布公告

Hi 大家好, 我是给你们带来惊喜的运营小番茄。 本期更新为短说 4.1.5和PC端3.1.4的正式版。 本次修复上个版本中的问题和功能优化,以及新增了如下功能: PC端支持发布秀米帖,可支持部分秀米格式;后台管理类消息新增…

shell编程之免交互(shell脚本)

Here Document 免交互 Here Document 概述 Here Document是一个特殊的用途的代码块。它在linux shell中使用I/O重定向的方式将命令列表提供给交互式程序或命令,比如ftp,cat或read命令。Here Document 是标准输入的一种替代品,可以帮助脚本开…

postman忘记密码发邮件,久久收不到怎么办?

根本原因是需要FQ!!! 重置密码的链接: https://identity.getpostman.com/trouble-signing-in 找个平台或者软件,访问这个链接即可完成修改密码后续操作,不用再傻傻等着验证码了。 有需要协助的朋友也可私信…

运算放大器(运放)输入偏置电流、失调电流

输入偏置电流定义 理想情况下,并无电流进入运算放大器的输入端。而实际操作中,始终存在两个输入偏置电流,即IB和IB-(参见图1)。 I B I_B IB​的值大小不一,在静电计AD549中低至60 fA(每三微秒通过一个电子),而在某些高…

Linux CentOS 宝塔中禁用php8.2的eval函数详细图文教程

PHP_diseval_extension 这个方法是支持PHP8的, Suhosin禁用eval函数,不支持PHP8 一、安装 cd / git clone https://github.com/mk-j/PHP_diseval_extension.gitcd /PHP_diseval_extension/source/www/server/php/82/bin/phpize ./configure --with-php-config/ww…

似然 与 概率

概率似然概率函数与似然函数的关系似然与机器学习的关系最大似然估计 似然与概率分别是针对不同内容的估计和近似 概率 概率:概率表达给定参数 θ \theta θ下样本随机向量 X x \textbf{X} {x} Xx的可能性。 概率密度函数的定义形式是 f ( x ∣ θ ) f(x|\t…

【博士每天一篇文献-综述】A survey on few-shot class-incremental learning

阅读时间:2023-12-19 1 介绍 年份:2024 作者:田松松,中国科学院半导体研究所;李璐思,老道明大学助理教授;李伟军,中国科学院半导体研究所AnnLab; 期刊: Neu…

FastGPT部署和OneAPI部署

FastGPT模型管理 FastGPT只支持openai 格式的restful 的api接口。 就是 chat/completion那个接口。如果不理解可以参考这个文章 https://zhuanlan.zhihu.com/p/656959227 。 支持Python 。JAVA 等后端语言或者 http 访问 因此如果想访问大模型,有以下几种方案&…

一次tcpdump抓包过程

#查询网卡 tcpdump -D # 监听 21100 端口 网卡ens192 (不知道网卡,可以直接不输入 -i 网卡)TCP数据,等待一段时间,执行CtrlC,终止程序 tcpdump -x -s 0 -w /tmp/123.dump -i ens192 -p tcp port 21100 #…

《2024快手行业人群画像报告-大家电类目》

快手商业化品牌行业运营中心与快手商业化用户研究中心联合发布了一份名为《2024快手行业人群画像报告-大家电类目》的研究报告。 这份报告深入分析了大家电市场的用户画像,涵盖了品类划分、用户趋势、交易洞察、人群洞察、搜索洞察以及品牌认知等多个维度的详尽数据和洞察,为理…

海思平台使用ITTP_Stream调试sensor

目录 相关资料1.ISP相关资料2.MIPI RX相关资料3.sensor资料4.MIPI标准 准备工作1.准备sensor驱动2.准备sample vio3.准备上位机和下位机程序 运行1.只运行HiPQTool1.1.板端运行1.2.PC端运行HiPQTool 2.使用ITTP_Stream2.1.板端运行2.2.打开上位机软件 相关资料 1.ISP相关资料 …

基于哈尔小波基的一维密度估计(Python)

先说点其他的东西。 关于强非线性、强间断、多物理场强耦合或高度复杂几何形态问题能够得以有效求解的核心难题之一,是如何构建在多尺度情形、非线性作用下具有准确地识别、定位、捕获以及分离各个尺度特征尤其是小尺度局部特征能力的数值工具,这之中包…

C语言单链表的算法之遍历节点

一:什么是遍历 (1)遍历就是把单链表中的各个节点挨个拿出来,就叫遍历 (2)便利的要点:一是不能遗漏,二是不能重复追求效率 二:如何遍历单链表 (1&#xff0…

element-plus 日期选择添加确定按钮

需求&#xff1a;选择日期后&#xff0c;点击确定按钮关闭面板 思路&#xff1a; 使用shortcuts自定义确定和取消按钮选择日期后使用handleOpen()强制开启面板点击确定后使用handleClose()关闭面板 <template><el-date-pickerref"pickerRef"v-model"…

能量智慧流转:全面升级储能电站的智能网关解决方案

监控系统是电化学储能电站的关键组成部分&#xff0c;储能电站也需要相应的监控系统&#xff0c;通过监控系统对储能设备的状态进行监测&#xff0c;实时感知储能设备的健康状态&#xff0c;控制储能设备的充放电功率和时机等&#xff0c; 一个好的监控系统可以实现储能电站安全…

微软发布Phi-3系列语言模型:手机端的强大AI助手

大模型&#xff08;LLMs&#xff09;在处理复杂任务时展现出的巨大潜力&#xff0c;但却需要庞大的计算资源和存储空间&#xff0c;限制了它们在移动设备等资源受限环境中的应用。微软公司最新发布的Phi-3系列语言模型&#xff0c;以其卓越的性能和小巧的体积&#xff0c;打破了…

[面试题]计算机网络

[面试题]Java【基础】[面试题]Java【虚拟机】[面试题]Java【并发】[面试题]Java【集合】[面试题]MySQL[面试题]Maven[面试题]Spring Boot[面试题]Spring Cloud[面试题]Spring MVC[面试题]Spring[面试题]MyBatis[面试题]Nginx[面试题]缓存[面试题]Redis[面试题]消息队列[面试题]…

AppFlow无代码轻松搭建模型Agent

随着大语言模型发展至今&#xff0c;如何深度开发和使用模型也有了各种各样的答案&#xff0c;在这些答案当中&#xff0c;Agent无疑是一个热点回答。 通过模型也各种插件的组合&#xff0c;可以让你的模型应用具备各种能力&#xff0c;例如&#xff0c;通过天气查询插件机票查…

最新Adobe2024全家桶下载,PS/PR/AE/AI/AU/LR/ID详细安装教程

如大家所熟悉的&#xff0c;Adobe全家桶系列常用的软件有Photoshop&#xff08;PS&#xff09;、Premiere&#xff08;PR&#xff09;、After Effects&#xff08;AE&#xff09;、illustrator&#xff08;AI&#xff09;、Audition&#xff08;AU&#xff09;、Lightroom&…