立方体贴图shade计算

正常的平面贴图是根据mesh顶点找到对应的uv坐标,然后根据重心坐标插值计算三角面内每个点的uv坐标值。最后根据uv坐标值查找平面贴图上的颜色值。
立方体贴图的6个面分别为6张图片,我们怎么根据mesh面上的坐标值来计算对应平面上的uv坐标值。
基本算法是根据原点与mesh面上点坐标(x,y,z)的射线和立方体贴图的交点作为uv坐标。

这里介绍一下uv坐标计算的数学推导过程
直线的表示方程为 p ⃗ = o ⃗ + t d ⃗ \vec{p}=\vec{o}+t\vec{d} p =o +td ,这里 o ⃗ \vec{o} o d ⃗ \vec{d} d 为向量, o ⃗ \vec{o} o 表示起始点,这里为原点; d ⃗ \vec{d} d 表示直线的方向,这里为mesh面上的3维点坐标与原点的方向 n o r m ( ( x , y , z ) − ( 0 , 0 , 0 ) ) = n o r m ( x , y , z ) norm((x,y,z)-(0,0,0))=norm(x,y,z) norm((x,y,z)(0,0,0))=norm(x,y,z);t为需要计算的值。 代入后直线表示方程为 p ⃗ = t ∗ n o r m ( x , y , z ) \vec{p}=t*norm(x,y,z) p =tnorm(x,y,z)
平面的表示方程为 ( p ⃗ − p 0 ⃗ ) ⋅ n ⃗ = 0 (\vec{p}-\vec{p0})\cdot \vec{n}=0 (p p0 )n =0,其中 p ⃗ \vec{p} p 为需要求的点坐标, p 0 ⃗ \vec{p0} p0 为已知的平面上任一点; n ⃗ \vec{n} n 为平面的法向量。 以立方体贴图的右平面举例,其法向量 n ⃗ \vec{n} n 为x轴的方向(1,0,0), p 0 ⃗ \vec{p0} p0 取(1,0,0),代入后平面表示方程为 ( p ⃗ − ( 1 , 0 , 0 ) ) ⋅ ( 1 , 0 , 0 ) = 0 (\vec{p}-(1,0,0))\cdot(1,0,0)=0 (p (1,0,0))(1,0,0)=0
直线与平面的交点表示该点同时满足直线和平面表示方程,将上述两个方程联立,得到
( t ∗ n o r m ( x , y , z ) − ( 1 , 0 , 0 ) ) ⋅ ( 1 , 0 , 0 ) = 0 (t*norm(x,y,z)-(1,0,0))\cdot(1,0,0)=0 (tnorm(x,y,z)(1,0,0))(1,0,0)=0,简化后得 t ∗ x n o r m − 1 = 0 t*xnorm-1=0 txnorm1=0 t = 1 / x n o r m t=1/xnorm t=1/xnorm,其中xnorm表示(x,y,z)归一化后x分量的值。
将t代入直线方程可以得到y,z的坐标为 ynorm/xnorm、znorm/xnorm。因为在右平面上x值都为1,最后的uv坐标值为 ( y n o r m / x n o r m , z n o r m / x n o r m ) (ynorm/xnorm, znorm/xnorm) ynorm/xnorm,znorm/xnorm)
然后再以左平面为例,左平面的法向量 n ⃗ \vec{n} n 为(-1,0,0), p 0 ⃗ \vec{p0} p0 取(-1,0,0),联立方程为 ( t ∗ n o r m ( x , y , z ) − ( − 1 , 0 , 0 ) ) ⋅ ( − 1 , 0 , 0 ) = 0 (t*norm(x,y,z)-(-1,0,0))\cdot(-1,0,0)=0 (tnorm(x,y,z)(1,0,0))(1,0,0)=0,可得 t = − 1 / x n o r m t=-1/xnorm t=1/xnorm,uv坐标值为 ( − y n o r m / x n o r m , − z n o r m / x n o r m ) (-ynorm/xnorm, -znorm/xnorm) (ynorm/xnorm,znorm/xnorm)

综上可得简化后的计算过程如下:
设mesh上坐标点为(x,y,z),取这3个分量中绝对值最大的分量表示位于哪个平面上,然后分别用其他两个分量除以该分量绝对值表示uv坐标。如点(3,-8,-5),表示位于立方体的下方平面上,uv坐标为(3/8,-5/8)
在opengl中我们要根据上述计算过程来实现uv坐标的计算。在unity中有samplerCUBE,可以调用texCUBE用mesh坐标直接从立方体贴图中获取颜色值。代码如下所示,注意mesh的坐标值都是用的物体局部坐标系,不是世界坐标系。

Shader "CubemapSampler"
{
    Properties
    {
        _CubeMap("CubeMap", CUBE) = ""{}
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;   
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 vertexLocal : TEXCOORD1;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertexLocal = v.vertex;
                o.vertex = UnityObjectToClipPos(v.vertex);

                return o;
            }

            samplerCUBE _CubeMap;
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = texCUBE(_CubeMap, normalize(i.vertexLocal.xyz));
                return col;
            }
            ENDCG
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值