【Unity】RenderFeature笔记

【Unity】RenderFeature笔记

RenderFeature是在urp中添加的额外渲染pass,并可以将这个pass插入到渲染列队中的任意位置。内置渲染管线中Graphics 的功能需要在RenderFeature里实现,常见的如DrawMesh和Blit

​ 可以实现的效果包括但不限于

  1. 后处理,可以编写shader对整个渲染画面进行修改。比如一些全局特效包括:场景描边,地形扫描;

  2. 创建网格,通过DrawMesh绘制定义的网格;

  3. 渲染画面,将场景渲染到纹理;

一、RanderFeature简介

1. 创建RanderFeature

在project中Create→Rendering→URPRenderFeature

2.RanderFeature结构
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class CustomRenderPassFeatureTest : ScriptableRendererFeature
{class CustomRenderPass : ScriptableRenderPass{// 在执行渲染通道之前调用// 创建临时渲染目标纹理。//为Execute提前准备需要的RenderTexture或者其它变量public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData){}//核心方法,实现这个renderPass的逻辑public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}//释放在OnCameraSetup里,声明的变量如TemporaryRenderTexturepublic override void OnCameraCleanup(CommandBuffer cmd) {}}CustomRenderPass m_ScriptablePass;/// <inheritdoc/>public override void Create(){m_ScriptablePass = new CustomRenderPass();//定义渲染的位置m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;}// 这里你可以在渲染器中注入一个或多个渲染通道。//每一帧都执行public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){//把实例化的CustomRenderPass插入渲染管线renderer.EnqueuePass(m_ScriptablePass);}
}
3.RenderFeatrue使用

在Universal Render Pipeline Asset_Renderer直接Add RenderFeatrue

二、后处理效果

关键词
1、CommandBuffer.Blit

Blit是很常用的后期效果方法,在Build_in中常常是在OnRenderImage里被调用,与urp不同的是,在build_in里是通过Graphics.Blit调用。

Graphics.Blit

常用的接口: Blit(RenderTexturesource, RenderTexture dest, Material mat);

即使用着色器将源纹理复制到目标渲染纹理。

CommandBuffer.Blit

常用的接口:public void Blit (Rendering.RenderTargetIdentifier source, Rendering.RenderTargetIdentifier dest, Material mat);

这与 Graphics.Blit相似 - 主要用于从一个(渲染)纹理复制到其他纹理,可能使用自定义着色器;

源纹理或渲染目标将作为“_MainTex”属性传递给材质。

在shader中,_MainTex对应的是source,最后retrun对应的是dest

2、RenderTargetIdentifier

渲染目标标识符,标识 CommandBuffer的 RenderTexture;

使用 CommandBuffer.GetTemporaryRT 创建的具有名称的临时渲染纹理;

ScriptableRenderPass中有colorAttachment和depthAttachment是可以直接使用;

RenderTargetHandle.CameraTarget.Identifier()可以得到当前的渲染标识符

renderingData.cameraData.renderer.cameraColorTarget 也可以得到当前的渲染标识符

简单实现

实现脚本

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class CustomRenderPassFeatureTest : ScriptableRendererFeature
{//结构说明class CustomRenderPass : ScriptableRenderPass{// 在执行渲染通道之前调用// 创建临时渲染目标纹理。//为Execute提前准备需要的RenderTexture或者其它变量public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {}//核心方法,实现这个renderPass的逻辑public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}//释放在OnCameraSetup里,声明的变量如TemporaryRenderTexturepublic override void OnCameraCleanup(CommandBuffer cmd){}}//后处理效果class CustomRenderShaderPostPass : ScriptableRenderPass{  //定义渲染材质,通过Create方法赋值public Material _Material;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){//创建一个CommandBufferCommandBuffer cmd = CommandBufferPool.Get("ShowShader");//这里有一个疑问,渲染标识符不管怎么传都不影响结果cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);//执行CommandBuffercontext.ExecuteCommandBuffer(cmd);//回收CommandBufferCommandBufferPool.Release(cmd);}}CustomRenderShaderPostPass m_ScriptablePassPost;public Shader shader;/// <inheritdoc/>public override void Create(){m_ScriptablePassPost = new CustomRenderShaderPostPass();//通过创建一个渲染材质m_ScriptablePassPost._Material = new Material(shader);//定义渲染的位置m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;}// 这里你可以在渲染器中注入一个或多个渲染通道。//每一帧都执行public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){//把实例化的CustomRenderPass插入渲染管线renderer.EnqueuePass(m_ScriptablePassPost);}
}
1.实现饱和度和对比度调整

用shaderGraph实现

用shader实现

Shader "Unlit/SaturationContrastShader"
{SubShader{Pass{ZTest Always ZWrite OffCGPROGRAM#pragma vertex vert_img  // 使用内置的vert_img顶点着色器#pragma fragment frag#include "UnityCG.cginc"sampler2D _CameraColorTexture; //饱和度fixed3   Saturation_float(float3 In, float Saturation){float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));return luma.xxx + Saturation.xxx * (In - luma.xxx);}//对比度fixed3  Contrast_float(float3 In, float Contrast){float midpoint = pow(0.5, 2.2);return (In - midpoint) * Contrast + midpoint;}fixed4 frag (v2f_img i) : SV_Target{fixed4 col = tex2D(_CameraColorTexture, i.uv);fixed3  Saturation =  Saturation_float(col, 5);fixed3  Contrast = Saturation_float(Saturation, 5);return fixed4(Contrast.x, Contrast.y, Contrast.z,0.1);}ENDCG}}FallBack Off
}

使用前

使用后

三、创建网格

关键词
1、CommandBuffer.DrawMesh

常用的接口:DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material);

这个接口相对简单,传入mesh,变换矩阵,和材质

简单实现

这里接着上一个CustomRenderPassFeatureTest写,同时实现后处理和网格创建


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class CustomRenderPassFeatureTest : ScriptableRendererFeature
{//结构说明class CustomRenderPass : ScriptableRenderPass{// 在执行渲染通道之前调用// 创建临时渲染目标纹理。//为Execute提前准备需要的RenderTexture或者其它变量public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {}//核心方法,实现这个renderPass的逻辑public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}//释放在OnCameraSetup里,声明的变量如TemporaryRenderTexturepublic override void OnCameraCleanup(CommandBuffer cmd){}}//后处理效果class CustomRenderShaderPostPass : ScriptableRenderPass{  //定义渲染材质,通过Create方法赋值public Material _Material;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){//创建一个CommandBufferCommandBuffer cmd = CommandBufferPool.Get("ShowShader");//这里有一个疑问,渲染标识符不管怎么传都不影响结果cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);//执行CommandBuffercontext.ExecuteCommandBuffer(cmd);//回收CommandBufferCommandBufferPool.Release(cmd);}}//绘制网格class CustomRenderPassCreateMesh : ScriptableRenderPass{public Material _Material;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){CommandBuffer cmd = CommandBufferPool.Get("CreateMesh");cmd.DrawMesh(CreateMesh(), Matrix4x4.identity, _Material);//这里和后处理一样的操作context.ExecuteCommandBuffer(cmd);CommandBufferPool.Release(cmd);}//创建网格Mesh CreateMesh(){Mesh mesh = new Mesh();mesh.vertices = new Vector3[4] { new Vector3(1, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, 1, -1), new Vector3(1, 1, -1) };int[] indices = new int[8] { 0, 1, 1, 2, 2, 3, 3, 0 };//创建简单的线网格mesh.SetIndices(indices, MeshTopology.Lines, 0);return mesh;}}CustomRenderShaderPostPass m_ScriptablePassPost;CustomRenderPassCreateMesh m_ScriptablePassCreateMesh;public Shader shaderPost;public Shader shaderMesh;/// <inheritdoc/>public override void Create(){m_ScriptablePassPost = new CustomRenderShaderPostPass();//通过创建一个渲染材质m_ScriptablePassPost._Material = new Material(shaderPost);//定义渲染的位置m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRendering;m_ScriptablePassCreateMesh = new CustomRenderPassCreateMesh();m_ScriptablePassCreateMesh._Material = new Material(shaderMesh);m_ScriptablePassCreateMesh.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;}// 这里你可以在渲染器中注入一个或多个渲染通道。//每一帧都执行public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){//把实例化的CustomRenderPass插入渲染管线renderer.EnqueuePass(m_ScriptablePassPost);renderer.EnqueuePass(m_ScriptablePassCreateMesh);}
}

实现效果

知识点:RenderPassEvent控制渲染的顺序,上图我们可以看到,创建的线是可以被模型遮挡和遮挡模型的。但是如果把m_ScriptablePassCreateMesh.renderPassEvent=RenderPassEvent.AfterRendering 就会发现线完全遮挡模型,即线最后渲染

四、渲染画面到图片

关键词
1、GetTemporaryRT

获取临时渲染纹理

可使用给定参数创建临时渲染纹理,并使用 nameID 将其设置为全局着色器属性。使用 Shader.PropertyToID创建整数名称。

2、Shader.PropertyToID

获取着色器属性名称的唯一标识符。

static string RtName = "_TestRT";
static int RT_ID = Shader.PropertyToID(RtName);

简单实现

同样接着上一个CustomRenderPassFeatureTest写,同时实现后处理和网格创建


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class CustomRenderPassFeatureTest : ScriptableRendererFeature
{//结构说明class CustomRenderPass : ScriptableRenderPass{// 在执行渲染通道之前调用// 创建临时渲染目标纹理。//为Execute提前准备需要的RenderTexture或者其它变量public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {}//核心方法,实现这个renderPass的逻辑public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}//释放在OnCameraSetup里,声明的变量如TemporaryRenderTexturepublic override void OnCameraCleanup(CommandBuffer cmd){}}//后处理效果class CustomRenderShaderPostPass : ScriptableRenderPass{  //定义渲染材质,通过Create方法赋值public Material _Material;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){//创建一个CommandBufferCommandBuffer cmd = CommandBufferPool.Get("ShowShader");//这里有一个疑问,渲染标识符不管怎么传都不影响结果cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);//执行CommandBuffercontext.ExecuteCommandBuffer(cmd);//回收CommandBufferCommandBufferPool.Release(cmd);}}//创建网格class CustomRenderPassCreateMesh : ScriptableRenderPass{public Material _Material;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){CommandBuffer cmd = CommandBufferPool.Get("CreateMesh");cmd.DrawMesh(CreateMesh(), Matrix4x4.identity, _Material);context.ExecuteCommandBuffer(cmd);CommandBufferPool.Release(cmd);}//创建网格Mesh CreateMesh(){Mesh mesh = new Mesh();mesh.vertices = new Vector3[4] { new Vector3(1, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, 1, -1), new Vector3(1, 1, -1) };int[] indices = new int[8] { 0, 1, 1, 2, 2, 3, 3, 0 };mesh.SetIndices(indices, MeshTopology.Lines, 0);return mesh;}}//渲染画面class CustomRenderPassRT : ScriptableRenderPass{static string RtName = "_TestRT";//获取着色器属性名称的唯一标识符。static int RT_ID = Shader.PropertyToID(RtName);public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData){//新建一个RenderTextureDescriptorRenderTextureDescriptor textureDescriptor = new RenderTextureDescriptor(1920, 1080, RenderTextureFormat.Default, 0);//获取临时渲染纹理cmd.GetTemporaryRT(RT_ID, textureDescriptor);}public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){CommandBuffer cmd = CommandBufferPool.Get("ShowRT");//下面三段实现效果一样cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget, RT_ID);// cmd.Blit(RenderTargetHandle.CameraTarget.Identifier(), RT_ID);// cmd.Blit(colorAttachment, RT_ID);context.ExecuteCommandBuffer(cmd);CommandBufferPool.Release(cmd);}public override void OnCameraCleanup(CommandBuffer cmd){cmd.ReleaseTemporaryRT(RT_ID);}}CustomRenderShaderPostPass m_ScriptablePassPost;CustomRenderPassCreateMesh m_ScriptablePassCreateMesh;CustomRenderPassRT m_ScriptablePassRenderTextrue;public Shader shaderPost;public Shader shaderMesh;/// <inheritdoc/>public override void Create(){#region 后处理效果m_ScriptablePassPost = new CustomRenderShaderPostPass();//通过创建一个渲染材质m_ScriptablePassPost._Material = new Material(shaderPost);//定义渲染的位置m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRendering;#endregion#region 创建网格m_ScriptablePassCreateMesh = new CustomRenderPassCreateMesh();m_ScriptablePassCreateMesh._Material = new Material(shaderMesh);m_ScriptablePassCreateMesh.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;#endregion#region 渲染画面m_ScriptablePassRenderTextrue = new CustomRenderPassRT();m_ScriptablePassRenderTextrue.renderPassEvent = RenderPassEvent.AfterRendering;#endregion}// 这里你可以在渲染器中注入一个或多个渲染通道。//每一帧都执行public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){//把实例化的CustomRenderPass插入渲染管线renderer.EnqueuePass(m_ScriptablePassRenderTextrue);renderer.EnqueuePass(m_ScriptablePassPost);renderer.EnqueuePass(m_ScriptablePassCreateMesh);}
}

五、RenderFeatrue参数赋值

1、VolumeComponent

在Volume中提供Render Feature读取参数数据,通过VolumeManager单列,拿到stack,可以直接取得Volume中的数据。

以修改上文后处理的饱和度和对比度为例

1)创建一个全局的Global Volume

右击Hierarchy面板空白处选择Volume→Global Volume

2)自定义一个VolumeComponent
using UnityEngine.Rendering;public class VolumeComponentTest : VolumeComponent
{public ClampedFloatParameter Saturation = new ClampedFloatParameter(1f, 0, 3);public ClampedFloatParameter Contrast = new ClampedFloatParameter(1f, 0, 3);
}

可以在Volume中添加VolumeComponentTest组件

3)在shader中添加控制的参数

这添加了Saturation和Contrast两个控制参数

Shader "Unlit/SaturationContrastShader"
{Properties{_Saturation("Saturation", Range(0, 3)) = 1.0_Contrast("Contrast", Range(0, 3)) = 1.0}SubShader{Pass{ZTest Always ZWrite OffCGPROGRAM#pragma vertex vert_img  // 使用内置的vert_img顶点着色器#pragma fragment frag#include "UnityCG.cginc"float _Saturation;float _Contrast;sampler2D _CameraColorTexture; //饱和度fixed3   Saturation_float(float3 In, float Saturation){float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));return luma.xxx + Saturation.xxx * (In - luma.xxx);}//对比度fixed3  Contrast_float(float3 In, float Contrast){float midpoint = pow(0.5, 2.2);return (In - midpoint) * Contrast + midpoint;}fixed4 frag (v2f_img i) : SV_Target{fixed4 col = tex2D(_CameraColorTexture, i.uv);fixed3  Saturation =  Saturation_float(col, _Saturation);fixed3  Contrast = Saturation_float(Saturation, _Contrast);return fixed4(Contrast.x, Contrast.y, Contrast.z,0.1);}ENDCG}}FallBack Off
}

用shaderGraph实现的也是一样的添加两个参数

4)在RenderFeatrue中读取参数

对CustomRenderShaderPostPass修过如下

  class CustomRenderShaderPostPass : ScriptableRenderPass{  //定义渲染材质,通过Create方法赋值public Material _Material;//定义一个VolumeComponentTestVolumeComponentTest volumeComponentTest;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){//读取VolumeManager的单列取得stackvar stack = VolumeManager.instance.stack;//为volumeComponentTest赋值volumeComponentTest = stack.GetComponent<VolumeComponentTest>();if (!volumeComponentTest) return;//直接从volumeComponentTest中读取数据_Material.SetFloat("_Saturation", volumeComponentTest.Saturation.value);_Material.SetFloat("_Contrast", volumeComponentTest.Contrast.value);//创建一个CommandBufferCommandBuffer cmd = CommandBufferPool.Get("ShowShader");//这里有一个疑问,渲染标识符不管怎么传都不影响结果cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);//执行CommandBuffercontext.ExecuteCommandBuffer(cmd);//回收CommandBufferCommandBufferPool.Release(cmd);}}

实现效果

2、代码直接赋值

在RenderFeatrue中开放参数,用代码直接赋值

以后处理的饱和度和对比度为例

1)开放参数

在CustomRenderPassFeatureTest和CustomRenderShaderPostPass下分别定义饱和度和对比度,并赋值

public class CustomRenderPassFeatureTest : ScriptableRendererFeature
{//后处理效果class CustomRenderShaderPostPass : ScriptableRenderPass{  //定义渲染材质,通过Create方法赋值public Material _Material;public float _Contrast;public float _Saturation;public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){_Material.SetFloat("_Saturation", _Saturation);_Material.SetFloat("_Contrast", _Contrast);//创建一个CommandBufferCommandBuffer cmd = CommandBufferPool.Get("ShowShader");//这里有一个疑问,渲染标识符不管怎么传都不影响结果cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);//执行CommandBuffercontext.ExecuteCommandBuffer(cmd);//回收CommandBufferCommandBufferPool.Release(cmd);}}CustomRenderShaderPostPass m_ScriptablePassPost;public Shader shaderPost;public float Saturation;public float Contrast;/// <inheritdoc/>public override void Create(){#region 后处理效果m_ScriptablePassPost = new CustomRenderShaderPostPass();//通过创建一个渲染材质m_ScriptablePassPost._Material = new Material(shaderPost);//将饱和度和对比度赋值给CustomRenderShaderPostPassm_ScriptablePassPost._Contrast = Contrast;m_ScriptablePassPost._Saturation = Saturation;//定义渲染的位置m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRendering;#endregion}// 这里你可以在渲染器中注入一个或多个渲染通道。//每一帧都执行public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){//把实例化的CustomRenderPass插入渲染管线renderer.EnqueuePass(m_ScriptablePassPost);}
}

2)对参数进行修改

//得到RenderFeatrue    
CustomRenderPassFeatureTest custom=renderData.rendererFeatures.OfType<CustomRenderPassFeatureTest>().FirstOrDefault();
//对值进行修改
custom.Saturation =0;
custom.Contrast =0;
//设置数据
custom.SetParam();

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

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

相关文章

AI伦理:如何确保人工智能的公平与透明

文章目录 什么是AI伦理&#xff1f;AI公平性AI透明性 为什么AI公平性和透明性重要&#xff1f;确保AI公平性的方法1. 数据收集和准备2. 算法和模型3. 解释和可解释性4. 持续监测 确保AI透明性的方法1. 记录决策2. 可解释性工具3. 用户教育 AI伦理的挑战和未来结论 &#x1f389…

MongoDB——window11安装mongodb5.0.21版本服务端(图解版)

目录 一、mongodb官网下载地址二、安装步骤三、配置环境变量四、运行mongodb 一、mongodb官网下载地址 mongodb官网下载地址&#xff1a;https://www.mongodb.com/try/download/community 二、安装步骤 双击运行下载好的mongodb-windows-x86_64-5.0.21-signed.msi安装包&am…

golang gin——中间件编程以及jwt认证和跨域配置中间件案例

中间件编程jwt认证 在不改变原有方法的基础上&#xff0c;添加自己的业务逻辑。相当于grpc中的拦截器一样&#xff0c;在不改变grpc请求的同时&#xff0c;插入自己的业务。 简单例子 func Sum(a, b int) int {return a b }func LoggerMiddleware(in func(a, b int) int) f…

【Java 进阶篇】HTML块级元素详解

HTML&#xff08;Hypertext Markup Language&#xff09;是用于创建网页的标记语言。在HTML中&#xff0c;元素被分为块级元素和内联元素两种主要类型。块级元素通常用于构建网页的结构&#xff0c;而内联元素则嵌套在块级元素内&#xff0c;用于添加文本和其他内容。本文将重点…

电梯安全监测丨S271W无线水浸传感器用于电梯机房/电梯基坑水浸监测

城市化进程中&#xff0c;电梯与我们的生活息息相关。高层住宅、医院、商场、学校、车站等各种商业体建筑、公共建筑中电梯为我们生活工作提供了诸多便利。 保障电梯系统的安全至关重要&#xff01;特别是电梯机房和电梯基坑可通过智能化改造提高其安全性和稳定性。例如在暴风…

微服务技术栈-Docker应用部署

文章目录 前言一、数据卷二、Docker 应用部署1、MySQL部署2、Tomcat部署3、Nginx部署4、Redis部署5、Kafka部署 总结 前言 之前文章讲到过&#xff0c;docker运行程序的过程就是去仓库把镜像拉到本地&#xff0c;然后用一条命令把镜像运行起来变成容器&#xff0c;接下来我们将…

C++设计模式-适配器(Adapter)

目录 C设计模式-适配器&#xff08;Adapter&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-适配器&#xff08;Adapter&#xff09; 一、意图 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工…

【jvm--方法区】

文章目录 1. 栈、堆、方法区的交互关系2. 方法区的内部结构3. 运行时常量池4. 方法区的演进细节5. 方法区的垃圾回收 1. 栈、堆、方法区的交互关系 方法区的基本理解&#xff1a; 方法区&#xff08;Method Area&#xff09;与 Java 堆一样&#xff0c;是各个线程共享的内存区…

如何使用百度“云一朵”来分析PDF文件

PDF 文件是一种常见的文件格式&#xff0c;用于存储文档、图像和其他内容。在许多情况下&#xff0c;我们需要对 PDF 文件进行分析&#xff0c;以提取其中的信息。百度“云一朵”提供了一个 PDF 分析 API&#xff0c;可以帮助我们轻松地对 PDF 文件进行分析。 在本博客文章中&…

qt开发从入门到实战2

以下是本人学习笔记 原视频&#xff1a;最新QT从入门到实战完整版|传智教育 qt开发从入门到实战1 练习示例 设计一个按钮&#xff0c;点击时弹出新窗口&#xff0c;再次点击时新窗口关闭 // exerciseQWidget* second_window new QWidget();QPushButton* btn3 new QPushBu…

【Java】微服务——Feign远程调用

目录 1.Feign替代RestTemplate1&#xff09;引入依赖2&#xff09;添加注解3&#xff09;编写Feign的客户端4&#xff09;测试5&#xff09;总结 2.自定义配置2.1.配置文件方式2.2.Java代码方式 3.Feign使用优化4.最佳实践4.1.继承方式4.2.抽取方式4.3.实现基于抽取的最佳实践1…

Kettle连接数据库[MySQL]报错

在连接数据库页面填写完成后点击“测试” 报错信息&#xff1a; 错误连接数据库 [ETLqiangzi] : org.pentaho.di.core.exception.KettleDatabaseException: Error occurred while trying to connect to the databaseDriver class org.gjt.mm.mysql.Driver could not be found…