66Unity-shader 如何采样立方体贴图(Cube Map采样)

目录

一、立方体贴图

1、基础理论

2、采样立方体贴图

3、渲染结果

4、完整代码

二、环境贴图生成工具

1、下载地址

2、软件简介


一、立方体贴图

        立方体贴图即 Cube Map

1、基础理论

        立方体纹理(Cubemap)是环境映射(Environment Mapping)一种实现方法。环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以模拟反射周围环境的效果。比如金属、瓷器、塑料等带有反射特征的材质。 立方体贴图一共包含了6张图,这些图像对应了立方体的6个面。立方体的每个面表示沿着世界空间下的轴向(上、下、左、右、前、后)观察所得的图像。

立方体贴图中包含的6张图(图1)       

        和其它二维纹理坐标不同,对立方体纹理采样需要一个三维的纹理坐标(就是说采样立方体纹理的uv是一个三维的向量)。这个三维纹理坐标表示了在世界空间下的一个3D方向。这个方向矢量从立方体的中心出发,让它向外延申时会与立方体的6个纹理之一发生相交,而采样得到的结果就是由该交点计算而来。如下图所示给出了使用方向矢量对立方体纹理采样的过程。

对立方体贴图的采样(图2)

        使用立方体贴图的优势是,实现简单快速,而得到的效果也比较好。它的缺点是当场景中引入了新的物体、光源、物体发生移动,我们就需要重新生成立方体贴图。它在实时渲染中有很多应用,最常见的就是用于天空盒子及环境映射。

        创建立方体贴图有三种方法:第一种方法是直接由一些特殊布局的纹理创建;第二种方法是手动创建一个Cubemap资源,再把6张图赋给它;第三种方法是由脚本生成。

        这篇文章主要介绍的就是第一种方法。第一种方法需要我们提供一张具有特殊布局的纹理,例如类似立方体展开图的交叉布局、全景布局等。

立方体贴图不同的排版形式(图3)

      

        Unity中的设置:把立方体纹理贴图的Texture Shape设置为cube即可。

cubemap纹理贴图在unity中的设置(图4)

光照框架:直接光漫反射+直接光镜面反射+间接光漫反射+间接光镜面反射

### Unity URP 中采样 CubeMap 的方法 在 Unity 的 Universal Render Pipeline (URP) 中,采样 CubeMap 是一种常见的操作,通常用于环境反射、天空盒渲染或其他基于方向的光照效果。以下是关于如何在 URP 中实现 CubeMap 采样的详细说明。 #### 使用 Shader 实现 CubeMap 采样 为了在 URP 中采样 CubeMap,可以编写自定义着色器并利用 HLSL 或 CG 语言中的 `texCUBE` 函数来完成这一任务。下面是一个简单的示例: ```hlsl Shader "Custom/CubeMapSample" { Properties { _CubeMap ("Environment Cubemap", CUBEMAP) = "" {} } SubShader { Tags { "RenderType"="Opaque" } Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag // Include necessary libraries #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; // Normal vector used for reflection calculation. }; struct v2f { float4 positionCS : SV_POSITION; float3 worldNormal : TEXCOORD0; // World space normal. float3 viewDirWS : TEXCOORD1; // View direction in world space. }; TEXTURECUBE(_CubeMap); SAMPLER(sampler_CubeMap); CBUFFER_START(UnityPerMaterial) float4 _CubeMap_ST; CBUFFER_END v2f vert(appdata input) { v2f output; // Transform vertex from object space to clip space. output.positionCS = TransformObjectToHClip(input.vertex.xyz); // Transform normal and calculate view direction in world space. output.worldNormal = TransformObjectToWorldNormal(input.normal); output.viewDirWS = GetWorldSpaceViewDir(input.vertex.xyz); return output; } half4 frag(v2f input) : SV_Target { // Calculate the reflection vector based on the view direction and surface normal. float3 reflectDir = normalize(reflect(-input.viewDirWS, input.worldNormal)); // Sample the cubemap using the reflection vector. half4 color = SAMPLE_TEXTURE_CUBE(_CubeMap, sampler_CubeMap, reflectDir); return color; } ENDHLSL } } } ``` 此代码片段展示了如何通过计算法线和视图方向之间的反射向量来采样 CubeMap[^2]。具体来说: - `_CubeMap` 定义了一个立方体贴图资源。 - 在顶点着色器中,将对象空间下的法线转换到世界空间下,并计算观察方向。 - 片段着色器中使用 `reflect()` 函数生成反射矢量,并将其传递给 `SAMPLE_TEXTURE_CUBE` 进行采样[^3]。 #### 配置材质与场景设置 创建一个新的材质并将上述着色器分配给它。随后,在该材质属性面板中加载所需的 CubeMap 资源。最后,将这个材质应用至目标模型或物体即可看到实时的效果。 另外需要注意的是,在某些情况下可能还需要调整摄像机或者灯光的相关参数以确保最终呈现出来的视觉效果符合预期[^4]。 #### 性能优化建议 当处理大量动态对象时可能会遇到性能瓶颈问题因此考虑以下几个方面来进行优化: - 尽量减少不必要的贴图切换次数; - 合理安排LOD(Level Of Detail),对于远离镜头的对象降低其细节程度从而减轻GPU负担; - 如果允许的话尝试预计算静态反射信息而不是每次运行时都重新计算一遍;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值