网易首页 > 网易号 > 正文 申请入驻

深度分析屏幕空间反射算法以及在URP中的实现(二)

0
分享至

【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!

这是侑虎科技第2051篇文章,感谢作者毅毅供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)

作者主页:

https://www.zhihu.com/people/20-85-47-35

前言

湿润的地面,倒映着远方青山,什么样的技术才能造就如此绚丽的效果呢?

本文实现的效果:

使用法线贴图的效果


平滑地面

代码仓库:

GitHub: Screen Space Reflection in URP

https://github.com/MrZhou-art/ScreenSpaceFeflection

Unity版本:2022.3.60f1c1

URP版本:14.0.12

使用延迟渲染

本文承接。

二分搜索

核心代码实现:

// 屏幕空间RayMarching判断
bool ScreenSpaceRayMarching(inout float2 currPosSS, inout float currInvW, float2 dPosSS, float dInvW,
float rayZ, bool isVertical, out float deltaZ, inout float2 hitUV, float2 endSS, float dir, float stepCount)
{
// 同时考虑方向和大小,用end判断步进结束
float end = endSS.x * dir;
float preZ = rayZ;

// 进行屏幕空间射线步近
UNITY_LOOP
for (int i = 0; i < stepCount && currPosSS.x * dir <= end; i++)
{
// 步近
currPosSS += dPosSS;
currInvW += dInvW;

// 得到步近前后两点的深度
float rayNearZ = preZ;
float rayFarZ = -1 / (dInvW * 0.5 + currInvW);
preZ = rayFarZ;
// 视图空间中相机朝向 -Z 方向
if (rayNearZ < rayFarZ) Swap(rayNearZ, rayFarZ);

// 得到交点uv
hitUV = isVertical ? currPosSS.yx : currPosSS;// 复原
hitUV *= _ScreenSize.zw;

if (any(hitUV < 0.0) || any(hitUV > 1.0)) returnfalse;

float surfaceZ = -LinearEyeDepth(SampleSceneDepth(hitUV), _ZBufferParams);
deltaZ = abs(surfaceZ - rayNearZ);

if (rayFarZ <= surfaceZ) returntrue;
}
returnfalse;
}

// 二分搜索
bool BinarySearchRayMarching(float3 posVS, float3 reflDirVS, float3 normalVS, inout float2 hitUV,
float stepCount, float thickness, float stride, float rayOffset, float maxDistance, float binaryCount)
{
// 视图空间中射线起始位置和结束位置
float3 startVS = posVS;

float endVSZ = posVS.z + reflDirVS.z * maxDistance;
if (endVSZ > -_ProjectionParams.y)
maxDistance = (-_ProjectionParams.y - startVS.z) / reflDirVS.z;
float3 endVS = startVS + reflDirVS * maxDistance;

// inverse w
// w = -Vz , 为了后面方便在屏幕空间插值深度
float startInvW = 0;
float endInvW = 0;

// 屏幕空间中射线起始位置和结束位置
// 其实 startSS = uv * _ScreenSize.xy ([0, 1]^2 -> [0, w-1],[0, h-1])
// 但是为了拿到裁剪空间的w分量, 我们必须使用自定义的 TransformViewToScreen函数
float2 startSS = TransformViewToScreen(startVS, _ScreenSize.xy, startInvW);
float2 endSS = TransformViewToScreen(endVS, _ScreenSize.xy, endInvW);

// DDA算法
float2 deltaSS = endSS - startSS; // 注意方向性!
bool isVertical = false;
// 我们默认的是以横轴为主导向,如果纵轴为主导向,则进行反转,并在之后进行复原
if (abs(deltaSS.x) < abs(deltaSS.y))
{
isVertical = true;

deltaSS = deltaSS.yx;
startSS = startSS.yx;
endSS = endSS.yx;
}

// 计算屏幕坐标、inverse-w的线性增量
float dir = sign(deltaSS.x); // 屏幕空间增量方向
float invdx = dir / deltaSS.x; // 1 / 屏幕空间增量 (绝对值)
float2 dPosSS = float2(dir, invdx * deltaSS.y);
float dInvW = (endInvW - startInvW) * invdx;

// 步长的调整
dPosSS *= stride;
dInvW *= stride;

// 存在自反射,需要加一定的偏移
float3 rayVS = posVS + normalVS * rayOffset;

// 起始数据
float2 currPosSS = startSS;
float currInvW = startInvW;

float deltaZ = 0;
float rayZ = rayVS.z;

UNITY_LOOP
for (int i = 0; i < binaryCount; i++)
{
currPosSS += dPosSS;
currInvW += dInvW;

if (ScreenSpaceRayMarching(currPosSS, currInvW, dPosSS, dInvW, rayZ, isVertical, deltaZ, hitUV, endSS, dir, stepCount))
{
if (deltaZ < thickness) returntrue;

currPosSS -= dPosSS;
currInvW -= dInvW;
rayZ = -1 / currInvW;

dPosSS *= 0.5;
dInvW *= 0.5;
}
else
{
returnfalse;
}
}
returnfalse;
}

二分搜索核心在于回溯并减半步长,当我们在屏幕空间步进到一处恰好被遮挡的地方时,我们进行一次判断,如果这个被遮挡的深度与反射点的深度差值DeltaZ大于我们设定的阈值Thickness,则需要返回上一步,并把我们的步长减半。

if (ScreenSpaceRayMarching(currPosSS, currInvW, dPosSS, dInvW, rayZ, isVertical, deltaZ, hitUV, endSS, dir, stepCount))
{
if (deltaZ < thickness) return true;

currPosSS -= dPosSS;
currInvW -= dInvW;
rayZ = - 1 / currInvW;

dPosSS *= 0.5;
dInvW *= 0.5;
}

参数:


效果:


Debug


效果


没有使用法线贴图


使用法线贴图

1. 对比

相同参数下,对比屏幕空间RayMarching。

步长Stride较大的情况下:



没有二分搜索的屏幕空间RayMarching

二分搜索的屏幕空间RayMarching。

步长Stride较小的情况下:



没有二分搜索的屏幕空间RayMarching


二分搜索的屏幕空间RayMarching

可以看到,当步长在一个很小的范围内的时候,二分搜索的优化是没有那么明显的。但是,二分搜索最关键的点在于准确,就比如说下面两张图:


没有二分搜索的屏幕空间RayMarching


二分搜索的屏幕空间RayMarching

因为屏幕没有储存其背后的信息,所以我们的墙壁上必然不应该有这个反射信息,如果没有二分搜索,就会因为跨步太大导致出现反射。

2. 问题解析

为什么相机在地面向上看的时候会有钳制范围?


原因就是RayOffset太大了,会导致这一部分的自反射和步进不协调。调整到0.01就能解决。但是RayOffset不能太小,太小会导致自反射。

3. 性能分析

参数:


静态基本上0.63ms~0.68ms,可以看出来,为了精准搜索,我们不得不增加一些开销。


那么我们有没有优化的手段呢?

Hierarchical Z-Buffer

1. 理论说明

这个Hierarchical Z-Buffer就是对深度图进行一次MipMap处理,不同的是,Hi-Z不再使用四个像素深度的平均值,而是最小值。整体思想是进行一次一次地保守估计,估计对了就迈进,估计不对就进行回溯。


来自Games 202

这里我自己总结了一下闫老师说的思路,如下图:


我在实践中发现,这个高层级被遮挡之后不是很方便对应子层级中的深度,所以我的思路是高层级被遮挡之后,会先进行一次回溯操作,之后再小步迈进,直到我们回溯到第0层。

2. 配置

首先,为了生成Hierarchical Z-Buffer,我们必须添加一个RenderFeature(RenderPass也写在这一个文件了):

using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Serialization;

namespaceScreenSpaceReflection.Render
{
publicclassHiZRenderFeature : ScriptableRendererFeature
{
[Serializable]
publicclassHiZSettings
{
[SerializeField] internal RenderPassEvent RenderPassEvent = RenderPassEvent.BeforeRenderingOpaques;
[SerializeField] [Range(2, 6)] internalint HiZMipCount = 6;
}

[SerializeField] private Shader m_HiZShader;
[SerializeField] private HiZSettings m_Settings = new();

private Material m_HiZMaterial;
private HiZRenderPass m_HiZRenderPass;

public override void Create()
{
m_HiZRenderPass ??= new HiZRenderPass();
m_HiZRenderPass.renderPassEvent = m_Settings.RenderPassEvent;

if(!m_HiZShader)
m_HiZShader = Shader.Find("Hidden/Universal Render Pipeline/Blit");
m_HiZMaterial = CoreUtils.CreateEngineMaterial(m_HiZShader);

m_HiZRenderPass.Create(m_HiZMaterial);
}

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(m_HiZRenderPass);
}

public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
{
m_HiZRenderPass.Setup(ref m_Settings);
}

protected override void Dispose(bool disposing)
{
m_HiZRenderPass?.Dispose();
m_HiZRenderPass?.ClearUp();
m_HiZRenderPass = null;
}
}

staticclassHiZShaderConstants
{
publicstaticreadonlystring HiZTexName = "_HiZTex";

publicstaticreadonlyint HiZMipLevelSizeID =
Shader.PropertyToID("_HiZMipLevelSize");

publicstaticreadonlyint HiZSourceMipLevelID =
Shader.PropertyToID("_HiZSourceMipLevel");

publicstaticreadonlyint HiZDestinationMipLevelID =
Shader.PropertyToID("_HiZDestinationMipLevel");

publicstaticreadonlyint MaxHiZMipLevelID =
Shader.PropertyToID("_MaxHiZMipLevel");

publicstaticreadonlyint HiZTexID =
Shader.PropertyToID("_HiZTex");

publicstaticint[] HiZTexsID;
}

classHiZRenderPass : ScriptableRenderPass
{
privateconststring m_SsrProfilingTag = "HiZRenderPass";
private ProfilingSampler m_ProfilingSampler = new(m_SsrProfilingTag + "_Sampler");
private RenderTextureDescriptor m_Descriptor;
private RenderTextureDescriptor m_HiZDesc;
private RenderTextureDescriptor[] m_HiZDescs;
private RTHandle[] m_HiZRTHandles;
private RTHandle m_HiZRTHandle;
private RTHandle m_CameraDepthTexture;

private Material m_HiZMaterial;
private HiZRenderFeature.HiZSettings m_Settings;
privateconstint m_MaxHiZMipCount = 6;

public void Create(Material material)
{
m_HiZMaterial = material;

HiZShaderConstants.HiZTexsID = newint[m_MaxHiZMipCount];
m_HiZDescs = new RenderTextureDescriptor[m_MaxHiZMipCount];
m_HiZRTHandles = new RTHandle[m_MaxHiZMipCount];

m_HiZRTHandle = RTHandles.Alloc(HiZShaderConstants.HiZTexID, name: HiZShaderConstants.HiZTexName);

for (int i = 0; i < m_MaxHiZMipCount; i++)
{
HiZShaderConstants.HiZTexsID[i] = Shader.PropertyToID(HiZShaderConstants.HiZTexName + i);
m_HiZRTHandles[i] = RTHandles.Alloc(HiZShaderConstants.HiZTexsID[i], name: HiZShaderConstants.HiZTexName + i);
}
}

public void Setup(ref HiZRenderFeature.HiZSettings settings)
{
m_Settings = settings;
}

public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
m_CameraDepthTexture = renderingData.cameraData.renderer.cameraDepthTargetHandle;

m_Descriptor = renderingData.cameraData.cameraTargetDescriptor;
m_Descriptor.useMipMap = false;
m_Descriptor.autoGenerateMips = false;

var width = Math.Max((int)Math.Ceiling(Mathf.Log(m_Descriptor.width, 2) - 1.0f), 1);
var height = Math.Max((int)Math.Ceiling(Mathf.Log(m_Descriptor.height, 2) - 1.0f), 1);
width = 1 << width;
height = 1 << height;

m_HiZDesc = GetCompatibleDescriptor(width, height, GraphicsFormat.R32_SFloat);
m_HiZDesc.useMipMap = true;
m_HiZDesc.sRGB = false; // linear
m_HiZDesc.mipCount = m_Settings.HiZMipCount;

RenderingUtils.ReAllocateIfNeeded(ref m_HiZRTHandle, m_HiZDesc, FilterMode.Bilinear,
TextureWrapMode.Clamp, name: HiZShaderConstants.HiZTexName);

for (int i = 0; i < m_Settings.HiZMipCount; i++)
{
m_HiZDescs[i] = GetCompatibleDescriptor(width, height, GraphicsFormat.R32_SFloat);
// m_HiZDescs[i] = new RenderTextureDescriptor(width, height, RenderTextureFormat.RFloat, 0, 1);
// m_HiZDescs[i].msaaSamples = 1;
m_HiZDescs[i].useMipMap = false;
m_HiZDescs[i].sRGB = false; // linear

RenderingUtils.ReAllocateIfNeeded(ref m_HiZRTHandles[i], m_HiZDescs[i],
FilterMode.Bilinear, TextureWrapMode.Clamp, name: HiZShaderConstants.HiZTexName);

// generate mipmap
width = Math.Max(width / 2, 1);
height = Math.Max(height / 2, 1);
}

ConfigureTarget(renderingData.cameraData.renderer.cameraColorTargetHandle);
ConfigureClear(ClearFlag.None, Color.white);
}

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get(m_SsrProfilingTag + "_CommandBuffer");

using (new ProfilingScope(cmd, m_ProfilingSampler))
{
// mip 0
Blitter.BlitCameraTexture(cmd, m_CameraDepthTexture, m_HiZRTHandles[0]);
cmd.CopyTexture(m_HiZRTHandles[0], 0, 0, m_HiZRTHandle, 0, 0);

// mip 1~max
for (int i = 1; i < m_Settings.HiZMipCount; i++)
{
cmd.SetGlobalFloat(HiZShaderConstants.HiZSourceMipLevelID, i - 1);
cmd.SetGlobalFloat(HiZShaderConstants.HiZDestinationMipLevelID, i);
cmd.SetGlobalVector(HiZShaderConstants.HiZMipLevelSizeID,
new Vector4(m_HiZDescs[i - 1].width, m_HiZDescs[i - 1].height,
1.0f / m_HiZDescs[i - 1].width, 1.0f / m_HiZDescs[i - 1].height));
Blitter.BlitCameraTexture(cmd, m_HiZRTHandles[i - 1], m_HiZRTHandles[i], m_HiZMaterial, 0);

cmd.CopyTexture(m_HiZRTHandles[i], 0, 0, m_HiZRTHandle, 0, i);

}

cmd.SetGlobalFloat(HiZShaderConstants.MaxHiZMipLevelID, m_Settings.HiZMipCount - 1);
cmd.SetGlobalTexture(HiZShaderConstants.HiZTexName, m_HiZRTHandle);
}

context.ExecuteCommandBuffer(cmd);
cmd.Clear();
CommandBufferPool.Release(cmd);
}

public override void OnCameraCleanup(CommandBuffer cmd)
{

}

public void Dispose()
{
foreach (var handle in m_HiZRTHandles)
handle?.Release();
m_HiZRTHandle?.Release();
}

public void ClearUp()
{
CoreUtils.Destroy(m_HiZMaterial);
}

RenderTextureDescriptor GetCompatibleDescriptor(int width, int height, GraphicsFormat format,
DepthBits depthBufferBits = DepthBits.None)
=> GetCompatibleDescriptor(m_Descriptor, width, height, format, depthBufferBits);

private static RenderTextureDescriptor GetCompatibleDescriptor(RenderTextureDescriptor desc, int width,
int height, GraphicsFormat format, DepthBits depthBufferBits = DepthBits.None)
{
desc.depthBufferBits = (int)depthBufferBits;
desc.msaaSamples = 1;
desc.width = width;
desc.height = height;
desc.graphicsFormat = format;
return desc;
}
}
}

我们HiZShader也是十分简单的:

Shader "Hidden/HiZShader"
{
SubShader
{
Tags { "RenderType" = "Opaque""RenderPipeline" = "UniversalPipeline"}
LOD 100

Pass
{
Name "HiZPass"
ZTest Always
ZWrite Off
Cull Off

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Fragment
#pragma multi_compile_fragment _ _LINEAR_TO_SRGB_CONVERSION
#pragma multi_compile_fragment _ DEBUG_DISPLAY

// Core.hlsl for XR dependencies
"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
"Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"

// --------- Uniform Variable ---------
SAMPLER(sampler_BlitTexture);
float _HiZSourceMipLevel;
float4 _HiZMipLevelSize;

half4 GetSource(half2 uv, float mipLevel = 0.0)
{
return SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearRepeat, uv, mipLevel);
}

// --------- Shading Stage ---------
half4 Fragment(Varyings input) : SV_Target
{
float2 uv = input.texcoord;

half4 nearest = half4(
GetSource(uv + float2(-1, -1) * _HiZMipLevelSize.zw, _HiZSourceMipLevel).r,
GetSource(uv + float2(-1, 1) * _HiZMipLevelSize.zw, _HiZSourceMipLevel).r,
GetSource(uv + float2( 1, -1) * _HiZMipLevelSize.zw, _HiZSourceMipLevel).r,
GetSource(uv + float2( 1, 1) * _HiZMipLevelSize.zw, _HiZSourceMipLevel).r);

// NDC 空间中, 深度从近到远, 由 1 到 0
return max(max(nearest.r, nearest.g), max(nearest.b, nearest.a));
}
ENDHLSL
}
}
}

值得注意的是,我们为了准确对齐屏幕信息,需要将深度图的Width和Height设置为2的整数次方,这样提高降采样的准确性,后续采样也较为精准地反映出区域的深度。

FrameDebug中看一下:


总共分6 Level


最高层级的Hierarchical Z Buffer


3. 核心实现

既然已经设置好了Hierarchical Z Buffer,那就开始我们的SSR Shader吧:

// HiZ RayMarching
bool HiZRayMarching(float3 posVS, float3 reflDirVS, float3 normalVS, inout float2 hitUV,
float stepCount, float thickness, float stride, float rayOffset, float maxDistance)
{
float3 startVS = posVS;

float endVSZ = posVS.z + reflDirVS.z * maxDistance;
if (endVSZ > -_ProjectionParams.y)
maxDistance = (-_ProjectionParams.y - startVS.z) / reflDirVS.z;
float3 endVS = startVS + reflDirVS * maxDistance;

float startInvW = 0;
float endInvW = 0;

float2 startSS = TransformViewToScreen(startVS, _ScreenSize.xy, startInvW);
float2 endSS = TransformViewToScreen(endVS, _ScreenSize.xy, endInvW);

float2 deltaSS = endSS - startSS;
bool isVertical = false;

if (abs(deltaSS.x) < abs(deltaSS.y))
{
isVertical = true;

deltaSS = deltaSS.yx;
startSS = startSS.yx;
endSS = endSS.yx;
}

float dir = sign(deltaSS.x);
float invdx = dir / deltaSS.x;
float2 dPosSS = float2(dir, invdx * deltaSS.y);
float dInvW = (endInvW - startInvW) * invdx;

dPosSS *= stride;
dInvW *= stride;

float3 rayVS = posVS + normalVS * rayOffset;

float2 currPosSS = startSS;
float currInvW = startInvW;

float preZ = rayVS.z;

float mipLevel = 0.0;
float end = endSS.x * dir;

UNITY_LOOP
for (int i = 0; i < stepCount && currPosSS.x * dir <= end; i++)
{
currPosSS += dPosSS * exp2(mipLevel);
currInvW += dInvW * exp2(mipLevel);

float rayNearZ = preZ;
float rayFarZ = -1 / (dInvW * exp2(mipLevel) * 0.5 + currInvW);
preZ = rayFarZ;
if (rayNearZ < rayFarZ) Swap(rayNearZ, rayFarZ);

hitUV = isVertical ? currPosSS.yx : currPosSS;
hitUV *= _ScreenSize.zw;

if (any(hitUV < 0.0) || any(hitUV > 1.0)) returnfalse;

float mipDepth = SAMPLE_TEXTURE2D_X_LOD(_HiZTex, sampler_HiZTex, hitUV, mipLevel);
float surfaceZ = -LinearEyeDepth(mipDepth, _ZBufferParams);

if (rayFarZ <= surfaceZ)
{
if (mipLevel == 0)
{
if (abs(surfaceZ - rayNearZ) < thickness) returntrue;
}
else
{
currPosSS -= dPosSS * exp2(mipLevel);
currInvW -= dInvW * exp2(mipLevel);
preZ = -1 / currInvW;

mipLevel--;
}
}
else
{
mipLevel = min(mipLevel + 1, _MaxHiZMipLevel);
}
}
returnfalse;
}

值得注意的是,我们步长是以2的指数形式增长,最多增长2^_MaxHiZMipCount倍,这样做虽然快,但是我们也要考虑准确性,从我们的理论说明部分可以得知,这个方法会在找到大体的点之后进行回溯,会逐步精确到1像素级别,这样我们就保证了我们的准确性。

参数:


与之前不同的是,我们的步长Stride和阈值Thickness都将使用更高的参数,这是我不断调参才出来的效果,因为如果使用原来的值会出现非常严重的断层,如果太大就会走样。

效果:


帧率一下就上来了

4. 性能分析

基本上在0.36ms~0.42ms之间,性能还是非常友好的。


注意:非全屏

结语

1. 后续可优化方向

1)使用Glossy效果进行Trick,遮挡缺失的信息。

2)使用动态切换分辨率的SSRTexture,优化性能。

3)使用Planar Reflection Probe(平面反射探针)实现全反射。

4)使用Temporal Filter(历史帧过滤)进行降噪处理。

5)法线比较高频时,转动镜头时容易闪烁,可以借助Motion Vector配合时间滤波解决闪烁问题。

6)使用TAA或MSAA等抗锯齿技术。

2. 未来展望

作为廉价的屏幕空间反射,效果上必然比不过光线追踪:


屏幕空间反射


光线追踪

但是,在实时渲染领域,光追一次耗费的性能实在是太大,即使有NVIDIA RTX的支持,我4060勉强能跑个五六十帧(GPU利用率爆到98%都是家常便饭,主要还时常卡顿),这SSR毕竟是类似于后处理的一种手段,跑个一二百帧没问题(大体估计了一下)。


参考:

1. Efficient GPU Screen-Space Ray Tracing

2. Unity URP实现屏幕空间反射(SSR)

https://zhuanlan.zhihu.com/p/650035462

3. 【论文复现】Efficient GPU Screen-Space Ray Tracing

https://zhuanlan.zhihu.com/p/386510829

文末,再次感谢毅毅的分享, 作者主页:https://www.zhihu.com/people/20-85-47-35, 如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群: 793972859 )。


近期精彩回顾

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
澡堂搓澡时勃起了,很尴尬,咋办?(女生勿入)

澡堂搓澡时勃起了,很尴尬,咋办?(女生勿入)

许超医生
2026-10-29 10:09:46
CBA5轮过后,男篮国家队郭士强就选这12人吧

CBA5轮过后,男篮国家队郭士强就选这12人吧

男足的小球童
2026-10-28 17:30:24
内塔尼亚胡输了,利库德集团声称选举被阿拉伯政党“窃取”

内塔尼亚胡输了,利库德集团声称选举被阿拉伯政党“窃取”

山河路口
2026-10-29 11:38:35
欧洲: 11 月 1 日起, 每个中国包裹收 2 欧元! 中国: 那我把小包

欧洲: 11 月 1 日起, 每个中国包裹收 2 欧元! 中国: 那我把小包

触摸史迹
2026-10-29 10:17:32
伉俪,不读kāng lì,别再错了,很丢人!

伉俪,不读kāng lì,别再错了,很丢人!

语丝纪
2026-10-29 14:12:31
东契奇缺阵!湖人103-87大胜快船!此战看到3个事实:湖人今夏的操作很成功

东契奇缺阵!湖人103-87大胜快船!此战看到3个事实:湖人今夏的操作很成功

篮球大视野
2026-10-29 13:28:46
11 月 1 日起,欧盟将对来自中国的包裹收2欧文,不分大小:中国商家的应对绝了!

11 月 1 日起,欧盟将对来自中国的包裹收2欧文,不分大小:中国商家的应对绝了!

怪味历史连连看
2026-10-29 13:25:14
今日金价:10月29日大家做好准备!接下来,黄金有可能会历史重演

今日金价:10月29日大家做好准备!接下来,黄金有可能会历史重演

牛锅巴小钒
2026-10-29 10:35:13
金价下跌,女子花5万元买的金手镯,还没戴就已亏1.3万元!“当时觉得还会涨,以为买到就是赚到”,专家提醒:保持冷静

金价下跌,女子花5万元买的金手镯,还没戴就已亏1.3万元!“当时觉得还会涨,以为买到就是赚到”,专家提醒:保持冷静

19楼
2026-10-29 15:48:11
北京郊区大批人马出没,疯狂挖掘神秘黑疙瘩,因滥采已岌岌可危

北京郊区大批人马出没,疯狂挖掘神秘黑疙瘩,因滥采已岌岌可危

阿莱美食汇
2026-10-29 13:00:24
反诈博主“微剑”家属再发声:彪形大汉上门施压,被迫签署谅解书

反诈博主“微剑”家属再发声:彪形大汉上门施压,被迫签署谅解书

民生故事会
2026-10-28 08:05:14
比红薯通便,比芋头便宜!秋天使劲吃,一降火、二润肺、三强筋骨

比红薯通便,比芋头便宜!秋天使劲吃,一降火、二润肺、三强筋骨

阿龙美食记
2026-10-27 14:35:21
服刑7年出狱查账崩溃:47万余利宝只剩6.43元,1.9万直接流进办案警官的微信

服刑7年出狱查账崩溃:47万余利宝只剩6.43元,1.9万直接流进办案警官的微信

文青大叔说
2026-10-27 09:03:14
退休6年的我,想劝告大家:如果身体还可以,能延退就不要早早退休

退休6年的我,想劝告大家:如果身体还可以,能延退就不要早早退休

小马达情感故事
2026-10-27 17:53:28
民政局朋友透露一个扎心现实:如今,十个离婚女性,九个都会后悔

民政局朋友透露一个扎心现实:如今,十个离婚女性,九个都会后悔

青史卷中人
2026-10-29 02:33:15
腰细屁股大的人偷着乐吧!这个被嫌弃“缺点”,竟是长寿体质

腰细屁股大的人偷着乐吧!这个被嫌弃“缺点”,竟是长寿体质

皓皓情感说
2026-10-27 08:42:28
妻子出轨,丈夫将15公分蜡烛塞进妻子的阴道内

妻子出轨,丈夫将15公分蜡烛塞进妻子的阴道内

胖胖侃咖
2025-04-13 08:00:08
美乌“领土妥协”方案露出轮廓 北欧两国领导人私下联系普京

美乌“领土妥协”方案露出轮廓 北欧两国领导人私下联系普京

西楼饮月
2026-10-28 22:24:50
13亿灭霸级肉签发行申购,股民中签较容易,中了注定吃大肉!

13亿灭霸级肉签发行申购,股民中签较容易,中了注定吃大肉!

数据挖掘分析
2026-10-29 07:06:21
西班牙列车事故华人亲历者讲述:前胸受到撞击,一度无法呼吸

西班牙列车事故华人亲历者讲述:前胸受到撞击,一度无法呼吸

封面新闻
2026-10-29 15:50:08
2026-10-29 16:23:00
侑虎科技UWA incentive-icons
侑虎科技UWA
游戏/VR性能优化平台
1637文章数 989关注度
往期回顾 全部

科技要闻

MacBook终于能触屏了:22999元起

头条要闻

小博索纳罗抵美 发公开信自称"巴西领导人"并感谢两人

头条要闻

小博索纳罗抵美 发公开信自称"巴西领导人"并感谢两人

体育要闻

普通人徐嘉余的入口与出口

娱乐要闻

李嘉格自曝离婚内情:过错方净身出户

财经要闻

两大娱乐巨头,谈崩了

汽车要闻

首销期权益价23.98万起 2026款理想i6上市

态度原创

数码
时尚
家居
亲子
房产

数码要闻

MausStudio项目亮相:玩家可自行设计并3D打印专属游戏鼠标外壳

今年秋冬最火的4双鞋,配风衣时髦又好看!

家居要闻

2026建博会(广州) 公装联探展交流活动

亲子要闻

吃了半个月免疫力营养包真的少感冒了

房产要闻

12.1亿!三亚挂出重磅宅地!

无障碍浏览 进入关怀版