unity 实现水的波纹效果

news2024/10/7 6:43:07

之前的实现过这个效果,可惜没有记笔记,所以现在有点遗忘,连多个波纹一起在水面上实现的效果都忘记了,所以,查看了下之前实现的代码,现在再记一下笔记。

基础的波纹效果

要实现波纹,首先要知道波纹的中心点,这个位置应该是世界空间坐标系的位置,然后还要知道扩散到了哪里,也需要传入,知道了这两个值以后,就可以实现一个最简易的效果,只需要通过脚本更新这两个值,就可以实现最简单的波纹扩散效果。
波纹中心点我命名为了_HitPos,扩散到了尺寸就命名为HitSize,在片元里面求出世界空间坐标位置和中心点的位置,然后再减去_HitSize,就可以得出一个扩散的圆,调节_HitSize的大小,就可以发现圆会变大变小。

half dis = distance(input.positionWS, _HitPos.xyz);
dis -= _HitSize;

在这里插入图片描述
里面黑外面白,用一下反值
在这里插入图片描述
里面白外面黑,这样我们就找到了散的边界,我们会返现有一片纯黑和纯白的区域,这一片区域就是大于1和小于0的区域,而边缘渐变的部分就是从0-1的渐变。我们做效果,其实就只需要这个0-1的范围即可,将其定义为波纹的宽度。

然后,我们再命名一个_HitSpread作为扩散范围的调整,用边界值去除以这个值,就去修改,但是我为了保证0-1的范围中心处于边缘,我这里使用smoothstep方法,获取了0到-1的区域,然后使用_HitSpread去控制拾取的范围值。0就是刚好对应尺寸的起点。

    half disMask = distance(input.positionWS, _HitPos.xyz);
    half range = -clamp((disMask - _HitSize) / _HitSpread, -1, 0);

这样保证了区域的设置。
有了这个值以后,美术可以准确的去设置具体的显示范围,然后我们再给一个贴图,可以去拾取一张渐变图,美术也就可以简单的调节具体如何去渐变。
在这里插入图片描述
这里我使用了这张Ramp图片,然后使用上面的值作为采样的x轴,y轴默认0.5,就可以准确拾取过渡值。

    half disMask = distance(input.positionWS, _HitPos.xyz);
    half range = -clamp((disMask - _HitSize) / _HitSpread, -1, 0);
    half2 rampUV = half2(range, 0.5);
    half ramp = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).r;

采样出来的效果就是:
在这里插入图片描述
这种方法_HitSpread能准确的控制范围,而且_HitSize也能准确的控制移动的位置

    half noise = SAMPLE_TEXTURE2D(_NoiseTex, sampler_NoiseTex, noiseUV).r;
    half disMask = distance(input.positionWS, _HitPos.xyz);
    half range = -clamp((disMask - _HitSize + noise) / _HitSpread, -1, 0);
    half2 rampUV = half2(range, 0.5);
    half ramp = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).r;

再加上一张扰动图进行偏移,让渐变没有这么的平滑
在这里插入图片描述
接下来实现了基本的效果,然后我们还需要设置一个终点,到终点位置以后,就渐渐的消失的效果,这个效果的实现,首先就是我们需要设置一个渐变消失位置_HitFadeDistance,然后用之前求出的范围值除以它,然后再设置_HitFadePower和这个值相乘,主要是为了防止它的效果太早的变淡。

half hitFade = saturate((1.0 - disMask / _HitFadeDistance) * _HitFadePower); 

在这里插入图片描述
这个效果就是这样
然后用这个求出的值,再乘以之前的ramp,就实现了这个效果限制的显示范围。

在这里插入图片描述
就实现了我们所需要的效果。

实现脚本控制

既然实现了shader,但是位置和渐变的值需要我们手动传入啊。
为了实现这个效果,我们还需要设置全局变量,方便从脚本向shader传入变量。将_HitPos和_HitSize注销,这两个值我们需要从一个全局变量传入。这个全局变量前三个值设置为_HitPos的值,w通道则设置_HitSize的值,这样用一个四维向量就存储了两个值。

half4 HitParams;

声明一个HitParams,不要写在CBUFFER_START(UnityPerMaterial)里面,因为我们不需要合批,它们只是一个全局变量,然后还需要将Properties里面的值也注销掉,如果哪里设置了值,将会直接传入。
然后在运算前面重新声明它们

    half3 _HitPos = HitParams.xyz;
    half _HitSize = HitParams.w;

    half noise = SAMPLE_TEXTURE2D(_NoiseTex, sampler_NoiseTex, noiseUV).r;
    half disMask = distance(input.positionWS, _HitPos.xyz);
    half range = -clamp((disMask - _HitSize + noise) / _HitSpread, -1, 0);
    half2 rampUV = half2(range, 0.5);
    half ramp = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).r;
    half hitFade = saturate((1.0 - disMask / _HitFadeDistance) * _HitFadePower); 
    half hitResult = hitFade * ramp;

这样,就不用动原来代码,就实现。

接着是脚本,我声明了一个WaterRipple的脚本,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode()] //在编辑模式下也可以运行
public class WaterRipple : MonoBehaviour
{
    public string triggerTag = "ForceField";
    private Vector4 HitPos;
    private float HitSize;
    private float clickTimer = 0.0f; //防止频繁触发间隔

    void Start()
    {
    }

    void RayCast()
    {
        RaycastHit hitInfo;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //从屏幕点击位置,在相机3D空间中发射一条射线

        if (Physics.Raycast(ray, out hitInfo, 1000)) //通过射线拾取物体,拾取到返回true
        {
            if (hitInfo.transform.CompareTag(triggerTag)) //判断当前拾取到的物体的tag是否正确
            {
                Vector3 pos = hitInfo.point;
                HitPos.x = pos.x;
                HitPos.y = pos.y;
                HitPos.z = pos.z;
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        clickTimer += Time.deltaTime;
        if (Input.GetMouseButtonDown(0))
        {
            if (clickTimer > 0.5f)
            {
                clickTimer = 0.0f;
                RayCast();
            }
        }

        //设置shader的全局变量
        HitPos.w = clickTimer;
        Shader.SetGlobalVector("HitParams", HitPos);
    }
}

先附上代码,然后讲解里面主要的部分:
在update里面,首先对鼠标是否按下进行了判断,然后用一个数值进行放误触处理,这个值后面也可以设置一个可以修改的变量

clickTimer += Time.deltaTime;
if (Input.GetMouseButtonDown(0))
{
    if (clickTimer > 0.5f)
    {
        clickTimer = 0.0f;
        RayCast();
    }
}

如果可以触发RayCast函数,那么,将调用此函数

void RayCast()
{
    RaycastHit hitInfo;
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //从屏幕点击位置,在相机3D空间中发射一条射线

    if (Physics.Raycast(ray, out hitInfo, 1000)) //通过射线拾取物体,拾取到返回true
    {
        if (hitInfo.transform.CompareTag(triggerTag)) //判断当前拾取到的物体的tag是否正确
        {
            Vector3 pos = hitInfo.point;
            HitPos.x = pos.x;
            HitPos.y = pos.y;
            HitPos.z = pos.z;
        }
    }
}

这个函数里面主要是获取了点击在场景中拾取到的位置,而且设置了一个tag判断,主要是防止不需要触发的物体也会触发此事件问题。

        //设置shader的全局变量
        HitPos.w = clickTimer;
        Shader.SetGlobalVector("HitParams", HitPos);

最后则是在update函数里面设置全局变量,所有的shader只要声明了HitParams,都可以获取到此变量的值。
只要在平面上面设置一个ForceField的Tag,然后设置好材质,点击即可看到效果。但是这种设置,我们只能实现一个效果的点击,如果点击第二个,那么,第一个的效果将直接消失,接下来,我们将实现多个效果一起播放。

多个波纹的实现

在这里插入图片描述

在实现多个波纹的需求下,我们还需要继续修改Shader,将之前的参数作为数组传入,这样可以处理多个,然后循环计算得到结果。

int HitAmount;
half4 HitParams[20]; //xyz:pos  w:size

首先声明三个新的变量,HitAmount代表循环次数,HitParams直接作为数组传入,就是可以实现当前的操作,然后将循环修改成一个函数:

half Hit(half hitNoise, half3 positionWS)
{
    float hitResult;
    //循环处理多个点的波纹
    for (int i = 0; i < HitAmount; i++)
    {
        half disMask = distance(positionWS, HitParams[i].xyz);
        half range = -clamp((disMask - HitParams[i].w + hitNoise) / _HitSpread, -1, 0);
        half2 rampUV = half2(range, 0.5);
        half ramp = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).r;
        half hitFade = saturate((1.0 - disMask / _HitFadeDistance) * _HitFadePower);
        hitResult += hitFade * ramp;
    }

    return saturate(hitResult);
}

用来可以实现多个点的波纹,只是将HitPos和HitSize修改成了数组里面的值,这样就可以实现多个相加,然后最后限制到0-1的范围内即可。
然后是脚本修改,这次使用了粒子系统来模拟,渐变,然后获取到渐变的时间,然后乘以设置的大小,传入即可。
在这里插入图片描述
粒子系统的设置。
在这里插入图片描述
脚本的设置

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// [ExecuteInEditMode()] //在编辑模式下也可以运行
public class WaterRipple : MonoBehaviour
{
    public ParticleSystem PS;
    public string triggerTag = "ForceField";
    public float HitSize = 1;
    public int HitAmount; //当前粒子可以生成的粒子的个数
    private Vector4[] HitParams;
    private float clickTimer = 0.0f; //防止频繁触发间隔
    private ParticleSystem.Particle[] particles; //用于获取粒子系统里面的粒子

    void Start()
    {
    }

    void RayCast()
    {
        RaycastHit hitInfo;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //从屏幕点击位置,在相机3D空间中发射一条射线

        if (Physics.Raycast(ray, out hitInfo, 1000)) //通过射线拾取物体,拾取到返回true
        {
            if (hitInfo.transform.CompareTag(triggerTag)) //判断当前拾取到的物体的tag是否正确
            {
                PS.transform.position = hitInfo.point;
                PS.Emit(1);
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        clickTimer += Time.deltaTime;
        if (Input.GetMouseButtonDown(0))
        {
            if (clickTimer > 0.2f)
            {
                clickTimer = 0.0f;
                RayCast();
            }
        }

        ParticleSystem.MainModule PSmain = PS.main;
        PSmain.maxParticles = HitAmount; //设置最大粒子数

        HitParams = new Vector4[HitAmount];
        particles = new ParticleSystem.Particle[HitAmount];
        PS.GetParticles(particles);
        for (int i = 0; i < HitAmount; i++)
        {
            Vector3 pos = particles[i].position; //位置
            float size = particles[i].GetCurrentSize(PS) * HitSize; //尺寸
            HitParams[i].Set(pos.x, pos.y, pos.z, size);
        }

        Shader.SetGlobalVectorArray("HitParams", HitParams);
        Shader.SetGlobalFloat("HitAmount", HitAmount);
    }
}

脚本代码,会发现,我增加了一个HitAmount用来设置最多显示波浪的个数,然后从粒子系统拿到粒子的信息生成数组信息,传递给Shader的全局变量,其实我们也可以单独的传给Shader,这里我就不修改了。
下面,我列一下Shader的完整代码,基于URP的Unlit修改的:

Shader "Unlit/WaterRipple"
{
    Properties
    {
        [MainTexture] _BaseMap("Texture", 2D) = "white" {}
        [MainColor] _BaseColor("Color", Color) = (1, 1, 1, 1)
        _Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.5

        _NoiseTex("扰动图", 2D) = "white" {}
        _RampTex("渐变图", 2D) = "white" {}
        // _HitPos("点击位置", Vector) = (0, 0, 0, 0)
        // _HitSize("波纹尺寸", Float) = 0
        _HitSpread("扩散范围", Float) = 1
        _HitFadeDistance("范围渐变", Float) = 6
        _HitFadePower("范围渐变", Float) = 1

        // BlendMode
        _Surface("__surface", Float) = 0.0
        _Blend("__mode", Float) = 0.0
        _Cull("__cull", Float) = 2.0
        [ToggleUI] _AlphaClip("__clip", Float) = 0.0
        [HideInInspector] _BlendOp("__blendop", Float) = 0.0
        [HideInInspector] _SrcBlend("__src", Float) = 1.0
        [HideInInspector] _DstBlend("__dst", Float) = 0.0
        [HideInInspector] _ZWrite("__zw", Float) = 1.0
    }

    SubShader
    {
        Tags {"RenderType" = "Opaque" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" "ShaderModel"="3.5"}
        LOD 100

        Blend [_SrcBlend][_DstBlend]
        ZWrite [_ZWrite]
        Cull [_Cull]

        Pass
        {
            Name "Unlit"

            HLSLPROGRAM
            #pragma target 3.5

            #pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT
            #pragma shader_feature_local_fragment _ALPHATEST_ON
            #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fog
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
            #pragma multi_compile _ DEBUG_DISPLAY

            #pragma vertex UnlitPassVertex
            #pragma fragment UnlitPassFragment

            #include "./WaterRippleInput.hlsl"
            #include "./WaterRippleForwardPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}

            ZWrite On
            ColorMask 0

            HLSLPROGRAM
            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local_fragment _ALPHATEST_ON

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #include "Packages/com.unity.render-pipelines.universal/Shaders/UnlitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            Name "DepthNormalsOnly"
            Tags{"LightMode" = "DepthNormalsOnly"}

            ZWrite On

            HLSLPROGRAM
            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            #pragma vertex DepthNormalsVertex
            #pragma fragment DepthNormalsFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local_fragment _ALPHATEST_ON

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT // forward-only variant

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #include "Packages/com.unity.render-pipelines.universal/Shaders/UnlitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/UnlitDepthNormalsPass.hlsl"
            ENDHLSL
        }
    }
    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    // CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.UnlitShader"
}

WaterRippleInput.hlsl

#ifndef UNIVERSAL_WATERRIPPLE_INPUT_INCLUDED
#define UNIVERSAL_WATERRIPPLE_INPUT_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"

CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float4 _NoiseTex_ST;
half4 _BaseColor;
half _Cutoff;
half _Surface;
// half4 _HitPos;
// half _HitSize;
half _HitSpread;
half _HitFadeDistance;
half _HitFadePower;
CBUFFER_END

TEXTURE2D(_NoiseTex);           SAMPLER(sampler_NoiseTex);
TEXTURE2D(_RampTex);           SAMPLER(sampler_RampTex);

int HitAmount;
half4 HitParams[20]; //xyz:pos  w:size

#endif

WaterRippleForwardPass.hlsl


#ifndef URP_WATERRIPPLE_FORWARD_PASS_INCLUDED
#define URP_WATERRIPPLE_FORWARD_PASS_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Unlit.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

struct Attributes
{
    float4 positionOS : POSITION;
    float2 uv : TEXCOORD0;
    float3 normalOS : NORMAL;
    float4 tangentOS : TANGENT;

    UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings
{
    float4 uv : TEXCOORD0;
    float fogCoord : TEXCOORD1;
    float4 positionCS : SV_POSITION;
    float3 positionWS : TEXCOORD2;
    float3 normalWS : TEXCOORD3;
    float3 viewDirWS : TEXCOORD4;

    UNITY_VERTEX_INPUT_INSTANCE_ID
    UNITY_VERTEX_OUTPUT_STEREO
};

void InitializeInputData(Varyings input, out InputData inputData)
{
    inputData = (InputData)0;

    inputData.positionWS = input.positionWS;
    inputData.normalWS = input.normalWS;
    inputData.viewDirectionWS = input.viewDirWS;
    inputData.shadowCoord = 0;
    inputData.fogCoord = 0;
    inputData.vertexLighting = half3(0, 0, 0);
    inputData.bakedGI = half3(0, 0, 0);
    inputData.normalizedScreenSpaceUV = 0;
    inputData.shadowMask = half4(1, 1, 1, 1);
}

Varyings UnlitPassVertex(Attributes input)
{
    Varyings output = (Varyings)0;

    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_TRANSFER_INSTANCE_ID(input, output);
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);

    VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);

    output.positionCS = vertexInput.positionCS;
    output.uv.xy = TRANSFORM_TEX(input.uv, _BaseMap);
    output.uv.zw = TRANSFORM_TEX(input.uv, _NoiseTex);
    #if defined(_FOG_FRAGMENT)
        output.fogCoord = vertexInput.positionVS.z;
    #else
        output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
    #endif

    VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
    half3 viewDirWS = GetWorldSpaceViewDir(vertexInput.positionWS);

    // already normalized from normal transform to WS.
    output.positionWS = vertexInput.positionWS;
    output.normalWS = normalInput.normalWS;
    output.viewDirWS = viewDirWS;

    return output;
}

half Hit(half hitNoise, half3 positionWS)
{
    float hitResult;
    //循环处理多个点的波纹
    for (int i = 0; i < HitAmount; i++)
    {
        half disMask = distance(positionWS, HitParams[i].xyz);
        half range = -clamp((disMask - HitParams[i].w + hitNoise) / _HitSpread, -1, 0);
        half2 rampUV = half2(range, 0.5);
        half ramp = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).r;
        half hitFade = saturate((1.0 - disMask / _HitFadeDistance) * _HitFadePower);
        hitResult += hitFade * ramp;
    }

    return saturate(hitResult);
}

half4 UnlitPassFragment(Varyings input) : SV_Target
{
    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

    half2 uv = input.uv.xy;
    half2 noiseUV = input.uv.zw;
    half4 texColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv);
    half3 color = texColor.rgb * _BaseColor.rgb;
    half alpha = texColor.a * _BaseColor.a;

    AlphaDiscard(alpha, _Cutoff);

    #if defined(_ALPHAPREMULTIPLY_ON)
        color *= alpha;
    #endif

    InputData inputData;
    InitializeInputData(input, inputData);
    SETUP_DEBUG_TEXTURE_DATA(inputData, input.uv, _BaseMap);

    #ifdef _DBUFFER
        ApplyDecalToBaseColor(input.positionCS, color);
    #endif

    #if defined(_FOG_FRAGMENT)
        #if (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
            float viewZ = -input.fogCoord;
            float nearToFarZ = max(viewZ - _ProjectionParams.y, 0);
            half fogFactor = ComputeFogFactorZ0ToFar(nearToFarZ);
        #else
            half fogFactor = 0;
        #endif
    #else
        half fogFactor = input.fogCoord;
    #endif
    half4 finalColor = UniversalFragmentUnlit(inputData, color, alpha);

    half noise = SAMPLE_TEXTURE2D(_NoiseTex, sampler_NoiseTex, noiseUV).r;
    // half disMask = distance(input.positionWS, _HitPos.xyz);
    // half range = -clamp((disMask - _HitSize + noise) / _HitSpread, -1, 0);
    // half2 rampUV = half2(range, 0.5);
    // half ramp = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).r;
    // half hitFade = saturate((1.0 - disMask / _HitFadeDistance) * _HitFadePower);
    // half hitResult = hitFade * ramp;

    half hitResult = Hit(noise, input.positionWS);

    finalColor.rgb += hitResult;
    finalColor.rgb = MixFog(finalColor.rgb, fogFactor);
    // finalColor.rgb = hitFade;

    return finalColor;
}

#endif

如果有问题,请及时联系我。

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

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

相关文章

技术转管理,先来试试管理好项目

今天分享的主题是&#xff1a;如果你想技术转管理&#xff0c;先来试试管好一个项目 技术转管理&#xff0c;是很多技术人员的梦想&#xff0c;这也是30多岁之前还在做技术的人&#xff0c;也会对自己常常发出居安思危的意识表现&#xff0c;所以经常有人问我&#xff0c;怎么样…

chatGPT润色中英论文软件-文章修改润色器

chatGPT可以润色英文论文吗&#xff1f; ChatGPT可以润色英文论文&#xff0c;它具备自动纠错、自动完善语法和严格全面的语法、句法和内容结构检查等功能&#xff0c;可以对英文论文进行高质量的润色和优化。此外&#xff0c;ChatGPT还支持学术翻译润色、查重及语言改写等服务…

Java每日一练(20230510) 生成器类、螺旋矩阵II、删除链表的重复元素II

目录 1. 定义一个类Generator &#x1f31f;&#x1f31f; 2. 螺旋矩阵 II &#x1f31f;&#x1f31f; 3. 删除排序链表中的重复元素 II &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日…

Linux 设备树

1 什么是设备树&#xff1f; 设备树(Device Tree)&#xff0c;将这个词分开就是“设备”和“树”&#xff0c;描述设备树的文件叫做 DTS(Device Tree Source)&#xff0c;这个 DTS 文件采用树形结构描述板级设备&#xff0c;也就是开发板上的设备信息&#xff0c;比如 CPU 数量…

【Proteus仿真】| 05——问题记录

系列文章目录 【Proteus仿真】| 01——软件安装 【Proteus仿真】| 02——基础使用 【Proteus仿真】| 03——超详细使用教程 【Proteus仿真】| 04——绘制原理图模板 【Proteus仿真】| 05——问题记录 文章目录 前言1、51单片机仿真2、stm32仿真1. stm32 adc 采集电压一直为0 3、…

显卡3080设备CentOS 7.9 环境安装最新anconda、tensorflow-gpu 、cudatoolkit、cudnn、 python

目标&#xff1a;使用3080显卡搭建环境 系统安装 显卡驱动安装&#xff1a; 安装anconda 安装 python 安装 :cuda 安装&#xff1a;cudnn 安装 :tensorflow 一&#xff1a;系统安装&#xff1a;详见历史文档 二&#xff1a;显卡驱动安装&#xff1a;详见历史 三&#xff1a;整…

安装2023最新版_华为欧拉操作系统_OpenEuler操作系统_并配置IP地址_联网---linux工作笔记055

强调,一定要记得,硬盘多给点,50G根本不够用,搭建集群的话,自己测试都要100G才行哈.. 要不然麻烦,因为别的可以动态修改,但是硬盘大小修改了,不起作用,需要在 linux中再设置分区很麻烦 https://www.openeuler.org/zh/download/ 首先去下载安装包 然后找到这个安装包下载 然…

虚拟机中linux操作系统如何连网

文章目录 方法镜像来源本文前提创建centos7虚拟机1. 创建新的虚拟机&#xff0c;选择典型配置2. 安装来源选择上述下载的centos3. 命名虚拟机时注意事项如下图所示4. 后面配置硬盘大小默认20GB足以&#xff0c;然后调整虚拟机设置&#xff0c;可参考下图5.运行虚拟机 实操建议 …

混频器IP3的测量以及测试误差的来源分析

混频器线性度一直是射频系统设计面临的一个关键问题。混频器的非线性会产生不需要的、不可滤的杂散、互调和非线性失真。例如&#xff0c;非线性混频可能导致不希望的杂散&#xff0c;例如2fRF✕2fLO 或2fRF✕fLO 频率分量&#xff0c;加剧射频系统频谱再生问题。 1、IP3和IMD…

工具接口调用报错:“error“: “Unsupported Media Type“

工具接口调用报错&#xff1a;"error": "Unsupported Media Type" 问题原因&#xff1a; Media Type&#xff0c;即是Internet Media Type&#xff0c;互联网媒体类型&#xff0c;也叫做MIME类型&#xff0c;在Http协议消息头中&#xff0c;使用Content-T…

安全成就未来|Fortinet Accelerate 2023·中国区巡展首站启幕

Fortinet Accelerate 2023中国区巡展 年度网络安全盛会 Fortinet Accelerate 2023中国区巡展&#xff0c;昨日在深圳拉开帷幕&#xff0c;开启15城巡展的“首城之站”。本年度巡展主题“安全成就未来”&#xff0c;Fortinet与中企通信、亚马逊云科技等生态合作伙伴&#xff0c…

【动态代理】JDK动态代理与cglib动态代理源码解析

JDK动态代理 demo展示 UserService&#xff0c;接口类 public interface UserService {void addUser(); }UserServiceImpl&#xff0c;实现类 public class UserServiceImpl implements UserService {Overridepublic void addUser() {System.out.println("register al…

【运动规划算法项目实战】如何实现Dubins曲线和Reeds-Shepp曲线(附ROS C++代码)

文章目录 前言一、Dubins曲线二、Reeds-Shepp曲线三、应用场景四、代码实现4.1 Dubins曲线实现4.2 Reeds-Shepp曲线实现4.3 RVIZ显示五、总结前言 Dubins曲线和Reeds-Shepp曲线在机器人、自动驾驶行业中是非常重要的路径规划算法,它们能够有效地在不同的场景中生成最短路径,…

zlmediakit 新增可以使用硬件加速的转码http api接口方法

根据项目需求&#xff0c;我们需要使用硬件解码的方式进行网络摄像头数据帧的解析&#xff0c;给到算法模块使用 1、通过ffmpeg命令实验&#xff0c;ffmpeg -i IPC_URL -f rtsp rtsp://*/live 该命令默认是使用cpu进行解码的&#xff0c;我们需要使用GPU进行解码。 2、ffmpe…

皮特测评:蓝牙耳机哪个品牌最好?300元内最好的蓝牙耳机

大家好&#xff0c;我是皮特&#xff0c;今天要发布的测评主题是&#xff1a;“蓝牙耳机哪个品牌最好&#xff1f;”粉丝们私信给我希望能分享一期平价好用的蓝牙耳机&#xff0c;我购入十多款蓝牙耳机进行了多角度的测评后&#xff0c;总结了五款表现最优秀的蓝牙耳机&#xf…

神仙级python入门教程(非常详细),从零基础入门到精通,从看这篇开始

一.初聊Python 1.为什么要学习Python&#xff1f; 在学习Python之前&#xff0c;你不要担心自己没基础或“脑子笨”&#xff0c;我始终认为&#xff0c;只要你想学并为之努力&#xff0c;就能学好&#xff0c;就能用Python去做很多事情。在这个喧嚣的时代&#xff0c;很多技术…

前端开发之Echarts 图表渐变两种实现方式和动态改变图表类型

前端开发之Echarts 图表渐变两种实现方式 前言效果图一、echarts中存在两种渐变方式1、color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{}&#xff0c;{}&#xff0c;{}])简单案例 2、{type: linear,x: 0,y: 0,x2: 0,y2: 1, [{}&#xff0c;{}&#xff0c;{}]}案例 二…

硬件通信之 从单片机到C/C++指针详解

一 单片机理论概述 1.1 单片微型计算机&#xff08;Single Chip Microcomputer&#xff09;简称单片机&#xff0c;是把组成微型计算机的主要功能部件&#xff08;CPU、RAM、ROM、I/O口、定时/计数器、串行口等&#xff09;集成在一块芯片中&#xff0c;构成一个完整的微型计…

centos7安装nginx

1.配置环境 1).gcc yum install -y gcc2).安装第三方库 pcre-devel yum install -y pcre pcre-devel3).安装第三方库 zlib yum install -y zlib zlib-devel2.下载安装包并解压 nginx官网下载&#xff1a;http://nginx.org/en/download.html 或者 使用wget命令进行下载 wg…

第一期 | ICASSP 2023 论文预讲会

ICASSP 2023 论文预讲会是由CCF语音对话与听觉专委会、语音之家主办&#xff0c;旨在为学者们提供更多的交流机会&#xff0c;更方便、快捷地了解领域前沿。活动将邀请 ICASSP 2023 录用论文的作者进行报告交流。 ICASSP &#xff08;International Conference on Acoustics, …