原神角色渲染详解

 

整体效果展示:主要方案是对下面几张图做不同的处理

身体

基础颜色光照:主要贴图+卡通贴图+ramp图+法线图+光照图

金属度与高光,头发部分高光:光照图,头发部分用高光black图

深度边缘光:用额外pass DepthNormals 获取深度信息

 描边:额外pass对描边进行处理,用光照图的a通道对不同区域做颜色区分

方案:主要贴图+卡通贴图+ramp图+SDF+描边

需要用到的贴图

将光照图,ramp图的sRGB关闭,法线图Type改成法线 

妮露基础图的a通道储存的是神之眼灰度信息

光照图的rba存储材质信息,r通道储存金属强度,g通道储存AO信息,b通道储存高光形状与细节

ramp图上五行是白天暗部颜色,下五行是夜晚暗部颜色

卡通图用来做底部光照体积

准备阶段

//数据准备
Properties{[Space][Space][Space][Space]_AmbientColor ("基础颜色", Color) = (0.667,0.667,0.667,1)_DiffuseColor ("漫反射颜色", Color) = (0.906,0.906,0.906,1)_ShadowColor ("阴影颜色", Color) = (0.737,0.737,0.737,1)[Space][Space][Space][Space]_DiffuseTexFac("漫反射Fac",Range(0,1))=1_DiffuseTex ("漫反射贴图", 2D) = "white" {}[Space][Space][Space][Space]_ToonTexFac("卡通Fac",Range(0,1))=1_ToonTex ("卡通贴图", 2D) = "white" {}[Space][Space][Space][Space]_SphereTexHair ("头发高光", 2D) = "black" {}_SphereHair("头发高光强度",Range(0,128))=68[Space][Space][Space][Space]_DoubleSided("双面",Range(0,1))=0_Alpha("透明值",Range(0,1))=1[Space][Space][Space][Space]_MetalTex("金属贴图", 2D) = "black" {}_SpecExpon("高光强度",Range(1,128))=58_KsNonMetallic("非金属",Range(0,3))=1_KsMetallic("金属度",Range(0,3))=1[Space][Space][Space][Space]_NormalMap("法线贴图", 2D) = "bump" {}[Space][Space][Space][Space]_ILM("光照贴图",2D)="black"{}[Space][Space][Space][Space]_RampTex("Ramp贴图", 2D) = "white" {}_RampMapRow0("Ramp0",Range(1,5))=1_RampMapRow1("Ramp1",Range(1,5))=4_RampMapRow2("Ramp2",Range(1,5))=3_RampMapRow3("Ramp3",Range(1,5))=5_RampMapRow4("Ramp4",Range(1,5))=2[Space][Space][Space][Space]_OutlineOffset("描边值",Float)=0.0007_OutlineMapColor0("描边颜色0",Color)=(0,0,0,0)_OutlineMapColor1("描边颜色1",Color)=(0,0,0,0)_OutlineMapColor2("描边颜色2",Color)=(0,0,0,0)_OutlineMapColor3("描边颜色3",Color)=(0,0,0,0)_OutlineMapColor4("描边颜色4",Color)=(0,0,0,0)[Space][Space][Space][Space]_rimStrength("边缘光宽度",Range(0,10))=0.8_rimMax("边缘光强度",Range(0,20))=0.8}
//准备pass,阴影和深度信息
Pass{Name"ShadowCaster"Tags{"LightMode"="ShadowCaster"}ZWrite OnZTest LEqualColorMask 0Cull offHLSLPROGRAM#pragma exclude_renderers gles gles3 glcore#pragma target 4.5//材质关键字#pragma shader_feature_local_fragment _ALPHATEST_ON#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A//显卡实例化#pragma multi_compile_instancing#pragma multi_compile _ DOTS_INSTANCING_ON//管线配置关键字#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW#pragma vertex ShadowPassVertex#pragma fragment ShadowPassFragment#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//Shaders/LitInput.hlsl"#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//Shaders/ShadowCasterPass.hlsl"ENDHLSL}Pass{Name"DepthNormals"Tags{"LightMode"="DepthNormals"}ZWrite OnCull offHLSLPROGRAM#pragma exclude_renderers gles gles3 glcore#pragma target 4.5#pragma vertex DepthNormalsVertex#pragma fragment DepthNormalsFragment//材质关键字#pragma shader_feature_local _NORMALMAP#pragma shader_feature_local _PARALLAXMAP#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED#pragma shader_feature_local_fragment _ALPHATEST_ON#pragma shader_feature_local_fragment _SMODTHNESS_TEXTURE_ALBEDO_CHANNEL_A//显卡实例化#pragma multi_compile_instancing#pragma multi_compile _ DOTS_INSTANCING_ON#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//Shaders/LitInput.hlsl"#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//Shaders/LitDepthNormalsPass.hlsl"ENDHLSL}

 开始主题,准备好变体与顶点数据

            Tags{"RenderPipeline"="UniversalPipeline""RenderType"="Opaque""LightMode"="UniversalForward"}Cull offHLSLPROGRAM#pragma multi_compile _MAIN_LIGHT_SHADOWS#pragma multi_compile _MAIN_LIGHT_SHADOWS_CASCADE#pragma multi_compile _SHADOWS_SOFT#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//ShaderLibrary/Core.hlsl"#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//ShaderLibrary/Lighting.hlsl"#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//ShaderLibrary/DeclareDepthTexture.hlsl"#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//ShaderLibrary/Shadows.hlsl"struct appdata{float4 vertex:POSITION ;half3 normal:NORMAL ;half4 tangent:TANGENT ;float2 uv:TEXCOORD0 ;half4 color:COLOR0 ;};struct v2f{float4 positionCS:SV_POSITION ;float2 uv:TEXCOORD0 ;float3 positionWS:TEXCOORD1;float3 positionVS:TEXCOORD2;float4 positionNDC:TEXCOORD3;float3 normalWS:TEXCOORD4 ;float3 tangentWS:TEXCOORD5 ;float3 bitangentWS:TEXCOORD6 ;float fogCooed:TEXCOORD7 ;float4 shadowCooed:TEXCOORD8 ;};
        v2f vert(appdata v){v2f o;VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);o.uv = TRANSFORM_TEX(v.uv,_DiffuseTex);o.positionWS=vertexInput.positionWS;o.positionVS=vertexInput.positionVS;o.positionCS=vertexInput.positionCS;o.positionNDC=vertexInput.positionNDC;VertexNormalInputs vertexNormalInput = GetVertexNormalInputs(v.normal,v.tangent);o.tangentWS = vertexNormalInput.tangentWS;o.bitangentWS=vertexNormalInput.bitangentWS;o.normalWS = vertexNormalInput.normalWS;o.fogCooed=ComputeFogFactor(vertexInput.positionCS.z);o.shadowCooed=TransformWorldToShadowCoord(vertexInput.positionWS);return o;}
URP中 非常便利的将需要的模型数据封装到了VertexPositionInputs中,可直接取出使用。
VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
注意雾和阴影的计算

接下来开始写片元着色器

准备好需要用到的函数

            Light light =GetMainLight(i.shadowCooed);float4 normalMap=tex2D(_NormalMap,i.uv);float3 normalTS=float3(normalMap.ag*2-1,0);normalTS.z=sqrt(1-dot(normalTS.xy,normalTS.xy));float3 N=normalize(mul(normalTS,float3x3(i.tangentWS,i.bitangentWS,i.normalWS)));float3 V=normalize(mul((float3x3)UNITY_MATRIX_I_V,i.positionVS*(-1)));float3 L=normalize(light.direction);float3 H=normalize(L+V);float NoL=dot(N,L);float NoH=dot(N,H);float NoV=dot(N,V);

法线的xy分量储存在法线图的ag通道,将其映射到-1—1得到xy分量,z分量通过勾股定理算出,再乘以TBN矩阵将其转换到世界空间

视向量是将视线的反方向乘以视图矩阵的逆矩阵将其变换到世界空间(V矩阵是将世界坐标转换到观察坐标)

            float3 normalVS=normalize(mul((float3x3)UNITY_MATRIX_V,N));float2 matcapUV=normalVS.xy*0.5+0.5;float4 baseTex=tex2D(_DiffuseTex,i.uv);float4 toonTex=tex2D(_ToonTex,matcapUV);           float3 baseColor=_AmbientColor.rgb;baseColor=saturate(lerp(baseColor,baseColor+_DiffuseColor.rgb,0.6));baseColor=lerp(baseColor,baseColor*baseTex.rgb,_DiffuseTexFac);baseColor=lerp(baseColor,baseColor*toonTex.rgb,_ToonTexFac);

再做法线matcap对toon图采样(matcap:将法线转换到视线空间,并计算到适合采样UV纹理的区间,进行采样。 问题:非物理,固定性无法与环境交互,倾向用于补光)

tex2D(sampler2D tex, float2 s)函数,这是CG程序中用来在一张贴图中对一个点进行采样的方法

至此基础颜色部分完成,可以打开unity写写看。

光照部分

处理ramp图

 光照图的a通道储存材质枚举,与ramp图的行对应

黑到白分别为—0,0.3,0.5,0.7,1

定义灰阶枚举,用step函数与光照图a通道做判断,再用lerp函数取ramp的行

以左上角为原点,除以10减去0.05得到v坐标

0的部分不需要额外计算 可删减

            float matEnum1=0.3;float matEnum2=0.5;float matEnum3=0.7;float matEnum4=1.0;float ramp0=_RampMapRow0/10.0-0.05;float ramp1=_RampMapRow1/10.0-0.05;float ramp2=_RampMapRow2/10.0-0.05;float ramp3=_RampMapRow3/10.0-0.05;float ramp4=_RampMapRow4/10.0-0.05;float dayRampV=lerp(ramp4,ramp3,step(ilm.a,matEnum4));dayRampV=lerp(dayRampV,ramp2,step(ilm.a,matEnum3));dayRampV=lerp(dayRampV,ramp1,step(ilm.a,matEnum2));dayRampV=lerp(dayRampV,ramp0,step(ilm.a,matEnum1));float nightRampv=dayRampV+0.5;

下一步 加入兰伯特光照模型(半兰伯特让暗部更通透)

把半兰伯特当作ramp图的u坐标,平滑半兰伯特的过度部分,并且将其钳制在设定值内,防止错误采样(clamp函数:x,a,b 小于a返回a,大于b返回b ab之间返回x)

uv坐标得到后,用光照方向的y值来选择采样ramp图

用半兰伯特平滑混合基础颜色和暗部颜色(smoothstep 平滑 a,b,x x小于a 返回0,x大于b返回1,在ab之间就平滑)

将g通道乘以2 用saturate函数将超过1的部分去掉,混合常暗区域(AO),将g通道减0.5乘2 用saturate函数将小于0的部分去掉,混合常亮部分(眼睛)(saturate函数:x大于1返回1,x小于0返回0)

            float lambert=saturate(NoL);float halflambert=pow(lambert*0.5+0.5,2);float lanbertStep=smoothstep(0.423,0.460,halflambert);float rampClampMin=0.003;float rampClampMax=0.997;float rampGrayU=clamp(smoothstep(0.2,0.4,halflambert),rampClampMin,rampClampMax);float2 rampGrayDayUV=float2(rampGrayU,1-dayRampV);float2 rampGrayNightUV=float2(rampGrayU,1-nightRampv);float rampDarkU=rampGrayU;float2 rampDarkDayUV=float2(rampDarkU,1-dayRampV);float2 rampDarkNightUV=float2(rampDarkU,1-nightRampv);float isDay=(L.y + 1)/2;float3 rampGrayColor=lerp(tex2D(_RampTex,rampGrayNightUV).rgb,tex2D(_RampTex,rampGrayDayUV).rgb,isDay);float3 rampDarkColor=lerp(tex2D(_RampTex,rampDarkNightUV).rgb,tex2D(_RampTex,rampDarkDayUV).rgb,isDay);float3 grayShadowColor=baseColor*rampGrayColor*_ShadowColor.rgb;float3 darkShadowColor=baseColor*rampDarkColor*_ShadowColor.rgb;float3 diffuse;diffuse=lerp(grayShadowColor,baseColor,lanbertStep);diffuse=lerp(darkShadowColor,diffuse,saturate(ilm.g*2));//diffuse=lerp(darkShadowColor,diffuse,light.shadowAttenuation);//自阴影diffuse=lerp(diffuse,baseColor,saturate(ilm.g-0.5)*2);       

漫反射部分完成

下一步,高光部分

前面说到光照图r通道储存高光强度,b通道储存高光形状与细节,这里主要对这两个通道做计算

非金属高光 

布林冯取反用step取值乘高光强度,可以加上头发高光,头发高光乘以基础颜色感觉更自然

金属高光

用光照图的r通道乘以半兰伯特做强度变化,乘以基础颜色得到金属质感

r通道为1的是金属,小于1的为非金属。用step做判断,混合金属和非金属高光得到最终高光

金属还有反射细节,这里用金属贴图简单实现,用法线采样金属图,用isMetal混合

将漫反射 高光 金属度加起来,到此光照部分完成。

            float blinnPhong=step(0,NoL)*pow(max(0,NoH),_SpecExpon);float3 specularT=(tex2D(_SphereTexHair,i.uv))*blinnPhong*_SphereHair*baseColor;float3 nonMetallicSpec=step(1.04-blinnPhong,ilm.b)*ilm.r*_KsNonMetallic+specularT;float3 metallicSpec=blinnPhong*ilm.b*(lanbertStep*3.5)*baseColor*_KsMetallic;//*(tex2D(_SphereTextf,i.uv)*20)float isMetal=step(0.95,ilm.r);float3 specular=lerp(nonMetallicSpec,metallicSpec,isMetal);float3 metallic=lerp(0,tex2D(_MetalTex,matcapUV).r*baseColor,isMetal)*2;float3 albedo=diffuse+specular+metallic;

屏幕空间边缘光部分

用NDC算出物体屏幕uv位置,用SampleSceneDepth方法采样深度图,用LinearDepth方法把深度纹理的采样结果转换到视角空间下的线性深度值

用观察空间法线x坐标做内偏移,再重新采样偏移后的深度值,相减得到边缘

再与菲涅尔计算,产生边缘光变化,得到最终边缘光效果。

加上双面渲染摄制,混合雾效,得到最终效果。

            float2 screenUV=i.positionNDC.xy/i.positionNDC.w;float rawDepth=SampleSceneDepth(screenUV);//float linearDepth=LinearEyeDepth(rawDepth,_ZBufferParams);//负责把深度纹理的采样结果转换到视角view空间下的线性深度值float2 screenOffset=float2(lerp(-1,1,step(0,normalVS.x))*rimOffset/_ScreenParams.x/max(1,pow(linearDepth,2)),0);float offsetDepth=SampleSceneDepth(screenUV+screenOffset);float offsetLinearDepth=LinearEyeDepth(offsetDepth,_ZBufferParams);float rim=saturate(offsetLinearDepth-linearDepth);rim=step(rimThreshold,rim)*clamp(rim*_rimStrength,0,_rimMax);float fresnelPower=6;float fresnelClamp=0.8;float fresnel=1-saturate(NoV);fresnel=pow(fresnel,fresnelPower);fresnel=fresnel*fresnelClamp+(1-fresnelClamp);albedo=1-(1-rim*fresnel)*(1-albedo);float alpha=_Alpha*_DiffuseColor.a*toonTex.a*sphereTex.a;alpha=saturate(min(max(IsFacing,_DoubleSided),alpha));float4 col=float4(albedo,alpha);clip(col.a-0.5);col.rgb=MixFog(col.rgb,i.fogCooed);return col;

至此,身体部分的片元着色器完成。

下一步,描边效果pass

剔除正面

和ramp一样,用光照图a通道枚举来定义不同材质的描边颜色。

        Pass{Name"Outline"Tags{"Renderpipeline"="UniversalPipeline""RenderType"="Opaque"}Cull FrontHLSLPROGRAM#pragma vertex vert#pragma fragment frag#pragma  multi_compile_fog#include "Library/PackageCache/com.unity.render-pipelines.universal@12.1.7//ShaderLibrary/Core.hlsl"struct appdata{float4 vertex:POSITION ;float2 uv:TEXCOORD0 ;float3 normal:NORMAL ;float4 tangent:TANGENT ;float4 color:COLOR0 ;};struct v2f{float2 uv:TEXCOORD0 ;float4 positionCS:SV_POSITION ;float fogcoord:TEXCOORD1 ;};CBUFFER_START(UnituPerMaterial)sampler2D _DiffuseTex;float4 _DiffuseTex_ST;sampler2D _ILM;float4 _OutlineMapColor0;float4 _OutlineMapColor1;float4 _OutlineMapColor2;float4 _OutlineMapColor3;float4 _OutlineMapColor4;float _OutlineOffset;CBUFFER_ENDv2f vert(appdata v){v2f o;//VertexPositionInputs vertexInput=GetVertexPositionInputs(v.vertex.xyz+v.normal.xyz*_OutlineOffset);VertexPositionInputs vertexInput=GetVertexPositionInputs(v.vertex.xyz+v.tangent.xyz*_OutlineOffset);o.uv=TRANSFORM_TEX(v.uv,_DiffuseTex);o.positionCS=vertexInput.positionCS;o.fogcoord=ComputeFogFactor(vertexInput.positionCS.z);return o;}float4 frag(v2f i,bool isFacing:SV_IsFrontFace):SV_Target{float4 ilm =tex2D(_ILM,i.uv);//float matEnum0=0.0;float matEnum1=0.3;float matEnum2=0.5;float matEnum3=0.7;float matEnum4=1.0;float4 color =lerp(_OutlineMapColor4,_OutlineMapColor3,step(ilm.a,matEnum4));color=lerp(color,_OutlineMapColor2,step(ilm.a,matEnum3));color=lerp(color,_OutlineMapColor1,step(ilm.a,matEnum2));color=lerp(color,_OutlineMapColor0,step(ilm.a,matEnum1));float3 albedo =color.rgb;float4 col =float4(albedo,1);col.rgb=MixFog(col.rgb,i.fogcoord);return col;}ENDHLSL}

法线偏移会使过渡剧烈的地方出现断边,所以我们采用切线偏移方法。

用脚本对顶点做平滑,将同位置的顶点法线相加,结果存到切线里,在shader里改成向切线方向偏移。

c#脚本如下

public class Normal : MonoBehaviour
{private void Awake(){Mesh mesh = GetComponent<SkinnedMeshRenderer>().sharedMesh;IEnumerable<IEnumerable<KeyValuePair<Vector3, int>>> groups = mesh.vertices.Select((vertex, index) => new KeyValuePair<Vector3, int>(vertex, index)).GroupBy(pair => pair.Key);Vector3[] normals = mesh.normals;Vector4[] smoothNormals =normals.Select((normal, index) => new Vector4(normal.x, normal.y, normal.z,0f)).ToArray();foreach (IEnumerable<KeyValuePair<Vector3,int>> group in groups){if (group.Count()==1){continue;}Vector3 smoothNormal = Vector3.zero;foreach (KeyValuePair<Vector3,int> pair in group){smoothNormal += normals[pair.Value];}smoothNormal.Normalize();foreach (KeyValuePair<Vector3,int> pair in group){smoothNormals[pair.Value] = new Vector4(smoothNormal.x, smoothNormal.y, smoothNormal.z);}}mesh.tangents = smoothNormals;}
}

至此,描边部分完成。

下一步脸部综合效果

复制身体shader,修改一下,把不需要的去掉

脸部需要的参数,脸部的描边和ramp只需要一个参数就行

        _ShadowTex("阴影图", 2D) = "black" {}_SDF("SDF",2D)="black"{}_ForwardVector("_ForwardVector",Vector)=(0,0,1,0)_RightVector("_RightVector",Vector)=(1,0,0,0)_RampTex ("Ramp贴图", 2D) = "white" {}_RampRow("Ramp排",Range(1,5))=3_OutlineOffset("描边值",Float)=0.00007_OutlineColor("描边颜色0",Color)=(0,0,0,0)

重点:SDF采样,SDF朝向

求出光照向量在上向量上的投影向量,即光向量乘以光向量与上向量夹角的余弦值,再乘以上向量的单位向量,就得到了光向量在上向量的投影向量。

将灯光向量与投影向量相减,得到新的灯光向量参与SDF计算

将投影向量与右向量点乘反余弦得到夹角,除以Π映射到0-1,也就是说0-0.5光线是照在脸的右边,0.5-1是左边。

用step函数来区分脸左右

将左右脸重新映射,都映射到0-1,平方让接近边缘时更加平滑,混合起来

采样左右脸的SDF,混合

判断,SDF灰阶阈值大于光照映射区域为1,小于为0

再判断朝向,防止后脑勺采样SDF

加上阴影颜色控制,得到脸部SDF最终效果

            float3 upVector=cross(forwardVec,rightVec);float3 LpU=dot(L,upVector)/pow(length(upVector),2)*upVector;float3 LpHeadHorizon=L-LpU;float pi=3.141592654;float value=acos(dot(normalize(LpHeadHorizon),normalize(rightVec)))/pi;float exposeRight=step(value,0.5);float valueR=pow(1-value*2,3);float valueL=pow(value*2-1,3);float mixValue=lerp(valueL,valueR,exposeRight);float sdfRembrandL=tex2D(_SDF,float2(1-i.uv.x,i.uv.y)).r;float sdfRembrandR=tex2D(_SDF,i.uv).r;float mixSdf=lerp(sdfRembrandR,sdfRembrandL,exposeRight);float sdf=step(mixValue,mixSdf);sdf=lerp(0,sdf,step(0,dot(normalize(LpHeadHorizon),normalize(forwardVec))));float3 shadowColor=baseColor*rampColor*_ShadowColor.rgb;float3 diffuse =lerp(shadowColor,baseColor,sdf);//diffuse=lerp(shadowColor,diffuse,light.shadowAttenuation);float3 albedo =diffuse;

SDF朝向问题,当角色倒过来时,SDF会反向,所以需要C#脚本控制,方法如下

在角色头上绑定两个空物体,取名,一个放在头的前面,一个放在头的右边,方向不用调整

在C#中找到对象和材质球,将位置传到shader里,大功告成!

public class Face : MonoBehaviour
{private Transform headTransform;private Transform headForward;private Transform headRight;private Material[] faceMaterials;private void Start(){headTransform = transform.Find("頭").GetComponent<Transform>();headForward = transform.Find("頭/HeadForward").GetComponent<Transform>();headRight = transform.Find("頭/HeadRight").GetComponent<Transform>();SkinnedMeshRenderer render = transform.Find("角色_mesh").GetComponent<SkinnedMeshRenderer>();Material[] allMaterials = render.materials;faceMaterials = new Material[1];faceMaterials[0] = allMaterials[脸的材质球序号];Update();}private void Update(){Vector3 forwardVector = headForward.position - headTransform.position;Vector3 rightVector = headRight.position - headTransform.position;forwardVector = forwardVector.normalized;rightVector = rightVector.normalized;Vector4 forwardVector4 = new Vector4(forwardVector.x, forwardVector.y, forwardVector.z);Vector4 rightVector4 = new Vector4(rightVector.x, rightVector.y, rightVector.z);for (int i = 0; i < faceMaterials.Length; i++){Material material = faceMaterials[i];material.SetVector("_ForwardVector", forwardVector4);material.SetVector("_RightVector", rightVector4);}}}

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

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

相关文章

打脸了兄弟们,Go1.20 arena 来了!

大家好&#xff0c;我是煎鱼。 大概半年前&#xff0c;我写过一篇文章《Go 要违背初心吗&#xff1f;新提案&#xff1a;手动管理内存》。有兴趣了深入解的同学&#xff0c;可以再回顾一下。 当时我们还想着 Go 团队应该不会接纳&#xff0c;至少不会那么快&#xff1a; 没想到…

对正在打野发育的红队同学的一次反制

文章目录 故事开始其他反制思路隐蔽C2CS重定向器实验 故事开始 真的是对同学的反制哈&#xff0c;我们最近都在学习内网&钓鱼就互相”攻击“&#xff0c;就有那么一天我就在想我偷懒把CS登录密码设置的很简单&#xff0c;会不会其它人也偷懒&#xff0c;于是就抱着尝试的心…

zsteg安装及CTF打野wp

下载文件解压后拖进kali里&#xff0c;移到root目录下 使用命令 zsteg 文件名 执行成功后即可获取qwxf{you_say_chick_beautiful?} 下面介绍zsteg的安装 使用命令 git clone http://www.github.com/zed-0xff/zsteg apt-get install gem gem install zsteg 若报错&#xff0c;…

AI版女网红“半藏森林”上线,服务项目让人意想不到

目前首批网红明星“AI克隆人”已提前上线&#xff0c;主营业务就是打造各种名人版AI聊天机器人&#xff0c;用户付费便可与之聊天。其后台报名参加AI克隆人的网红明星“全网粉丝总数已超过5亿”。该公司这波上线的网红明星AI克隆人&#xff0c;包括此前因“疑似插足他人恋情”&…

炉石传说 爬取全部卡牌

之前我30行爬了英雄联盟全部皮肤 这次爬炉石稍稍麻烦点&#xff0c;50行 网页分析 首先&#xff0c;我们分析炉石官方网站卡牌工具https://hs.blizzard.cn/cards/ 通过源代码和Network分析&#xff0c;发现返回的卡牌是用post请求的json文件 请求数据为&#xff1a; cardCla…

我用python玩炉石传说(3)-----炉石卡牌套牌自动构建算法

本文共三个部分&#xff1a; 我用python玩炉石传说&#xff08;1&#xff09;-----炉石卡牌相关度分析的手动打分器我用python玩炉石传说&#xff08;2&#xff09;-----炉石卡牌套牌爬取器及自动分析卡牌相关度我用python玩炉石传说&#xff08;3&#xff09;-----炉石卡牌套…

(写着玩)Python仿网络游戏《炉石传说》,继上次部分代码展示

上一期&#xff1a; &#xff08;写着玩&#xff09;Python仿网络游戏《炉石传说》&#xff0c;使用LOL的卡牌进行模拟对局&#xff08;版本1.0&#xff09;_AMarvelZ的博客-CSDN博客

手动爬取炉石传说所有卡牌

笔者还记得是从大学开始的时候玩的炉石传说&#xff0c;还记得当时的版本只有黑石山&#xff0c;纳克萨玛斯&#xff0c;地精大战侏儒这些卡包&#xff0c;转眼间到了现在&#xff0c;炉石传说早已和之前的那个炉石传说不再一样了&#xff0c;还记得以前的卡牌套路冰法&#xf…

革命炉石传说,Gods Unchained

欢迎各位新老朋友&#xff0c;我们细说P2E&#xff08;Play to Earn&#xff09;&#xff0c;为广大用户提供一个深入了解链游的平台。不定期的跟大家分享一些精品项目和最新链游方向&#xff0c;也欢迎大家关注我们。 我们第七期分享的是Gods Unchained&#xff0c;Gods Uncha…

卷没用的,我要被 AI 大模型抢走饭碗了

SOTA AI Devs Park 是专注于生成式 AI 领域的公益开发者社区&#xff0c;由生成式 AI 产业加速营 SOTA AI 支持建设&#xff0c;正在策划举办系列 Meetup 与闭门会&#xff0c;聚焦于同频交流生成式 AI 的前沿趋势与一线技术实践。 前不久我们出了一篇文章《AGI 变革&#xff1…

关于《更新win11之后我的edge浏览器打不开》这件事

win11更新后打不开edge浏览器的解决方法 1.打开此电脑&#xff0c;打开路径C:\Program Files (x86)\Microsoft\Edge\Application下的106.0.1370.42文件夹&#xff08;版本可能不同&#xff0c;总之找到全是数字的文件夹&#xff09; 2.找到msedgewebview2.exe文件&#xff0c;…

Edge地址栏搜索引擎换成Bing

‘设置’找到‘隐私&#xff0c;搜索和服务’ 地址栏和搜索 管理搜索引擎 添加保存设为默认值即可 以%s代替查询的URL: {bing:baseURL}search?q%s&{bing:cvid}

【PTA】 统计成绩2 (10分)

给定N个学生的基本信息&#xff0c;包括学号&#xff08;由12个数字组成的字符串&#xff09;、姓名&#xff08;长度小于20的不包含空白字符的非空字符串&#xff09;、高等数学成绩、C语言程序设计成绩&#xff0c;成绩均为[0,100]区间内的整数&#xff0c;要求统计高等数学成…

好分数网查成绩分数查排名服务平台_好分数免费查年级排名

好分数在线查年段排名,好分数在线查班级排名,好分数免费查询同学成绩 分数API是一个公益性的在线免费查排名软件 由作者一木独立开发 如果您方便的话可以下载软件后投币来支持我们 以维持服务器的正常支出&#xff0c;感谢各位 所需软件下载地址☞点我下载 教程开始 1.打开…

好分数学生家长查排名成绩-在线好分数查成绩入口

好分数在线查年段排名,好分数在线查班级排名,好分数免费查询同学成绩 分数API是一个公益性的在线免费查排名软件 由作者一木独立开发 如果您方便的话可以投币来支持我们 以维持服务器的正常支出&#xff0c;感谢各位 所需软件链接在文末 教程开始咯 1.打开 分数API APP&…

PTA 统计学生平均成绩与及格人数

7-3 统计学生平均成绩与及格人数 分数 15 作者 C课程组 单位 浙江大学 本题要求编写程序&#xff0c;计算学生们的平均成绩&#xff0c;并统计及格&#xff08;成绩不低于60分&#xff09;的人数。题目保证输入与输出均在整型范围内。 输入格式: 输入在第一行中给出非负整…

AI杂谈04 与Chat AI沟通代码与绘画的提词

BING AI&#xff1a;“与AI交流应该像与人交流一样&#xff0c;尊重对方的感受和权力。” 图源&#xff1a;文心一言 | 提词&#xff1a;少女机器人 漫画风格 作为小白&#xff0c;在使用AI生成代码的时候&#xff0c;耗过不少时间&#xff0c;栽过不少跟头&#xff0c;因此总…

一建证挂出去一年多少钱?

看专业、看专业、看专业&#xff0c;重要的事情说三遍。 目前在社保全国联网的情况下&#xff0c;如果不能转社保&#xff0c;一般很难挂出去&#xff0c;之前建筑、机电三年10万的光景已经一去不复返了&#xff01; 价位建筑和机电一般1年2万最多&#xff0c;大部分需求是半年…

计算机二级考试和一建哪个难,一建比二建难很多吗?终于明白了

原标题&#xff1a;一建比二建难很多吗&#xff1f;终于明白了 作为一个报考过一建二建考生&#xff0c;发自内心的说一句一建比二建要难很多&#xff0c;不过这也可能是因为我不聪明吧&#xff0c;不是那种说只要我想学&#xff0c;就能学会的&#xff0c;我在学习方面是比较适…