现在还没用到cubemap(除了天空盒子),只是初步的学了一下最简单的cubemap的shader
找一幅图
ShaderLab学习小结(十八)cubemap_第1张图片
好吧,有点大,在unity里把它设置成cubemap
ShaderLab学习小结(十八)cubemap_第2张图片
OK,图有了,看shader,代码挺简单的,其实和普通的2D贴图shader挺像

Shader "Custom/Cubemap" {
    Properties {
        _Cube ("Cubemap", cube) = "" {}             //1.
    }
    SubShader {
        pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            #include "Lighting.cginc"

            samplerCUBE _Cube;             //2.

            struct v2f {
                float4 pos:POSITION;
                float3 R:TEXCOORD0;
            };
            v2f vert(appdata_base v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                float3 L= -_WorldSpaceLightPos0.xyz;                       //3.
                float3 N = UnityObjectToWorldNormal(v.normal);
                o.R = reflect(L, N);            //4.
                return o;
            }
            fixed4 frag(v2f IN):COLOR
            {
                fixed4 col = texCUBE(_Cube, IN.R);            //5.
                return col;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

注意,以上这段代码是有问题的,后面会指出问题并改正,先以这段代码来说明
按照注释位置

1、2

_Cube ("Cubemap", cube) = "" {}             //1.
samplerCUBE _Cube;             //2.

2D贴图时,Properties里定义的是2d,而变量声明时用的是sampler2D
而对于cubemap来说则是cube和samplerCUBE
注意:samplerCUBE的CUBE大写,就像sampler2D的D大写一样

3、4、5

先看5

fixed4 col = texCUBE(_Cube, IN.R);            //5.

因为按照所学,最后的纹理采样要用到texCUBE这个CG函数,其实看形式和tex2D很像
第一个参数就是我们的cubemap那张图
第二个参数则是在vert程序中计算的一个世界坐标系下的反射向量,float3的
再看4是如何计算这个反射的

o.R = reflect(L, N);            //4.

反射吗,当然是光和法线,而这个L,是光的入射,即从光源指向顶点
reflect函数是计算反射向量的
所以看3

float3 L= -_WorldSpaceLightPos0.xyz;                       //3.

以前用到这个世界坐标空间下的光方向_WorldSpaceLightPos0.xyz,这个是从顶点指向光源的方向,现在正好相反,所以取负

貌似OK了,我们看看结果,在场景中建一个球体,把这个材质赋给它,并转动视角

其实也不能说错了,如果就是要这个效果的话
用光与法线算出来的反射,因为光是平行光固定的,顶点法线也是固定的,反射也是固定的
所以算出来的颜色是固定,就有了这个效果
但如果想实现的是像镜面那种效果的话,随着视角的不同,看到的东西并不相同,代码就要做些修改了
既然是随视角变化,那是不是认为不要用光的方向而是用视方向
我们把注释的3和4改一下

float3 V = -WorldSpaceViewDir(v.vertex);    //3.
o.R = reflect(V, N);    //4.

这里用了视方向,同样是从眼睛指向顶点,所以也取负
再用reflect函数
看下效果