zoukankan      html  css  js  c++  java
  • shader实例(二十二)TexGen-球面贴图SphereMap

    http://blog.sina.com.cn/s/blog_89d90b7c0102vfqz.html

    球面贴图一般用于环境反射,如下图(左边为球面贴图,右边为正常贴图),一个镜面水晶球在这只猫的前方,而这只猫也正看着这个水晶球,效果是这只大头猫的头变的更大了。shader实例(二十二)TexGen-球面贴图SphereMap


    原理:

    1.将顶点转换到摄像机空间

    2.根据该顶点的摄像机【入射向量 I 】和【法线向量N】计算【反射向量R】

    3.将【反射向量R】与【摄像机向量(0,0,1)】相加,计算出【过渡向量m】

    4.求【过渡向量m】单位向量,再将值映射为uv的值域上,求得纹理坐标

    如图:


    基础知识:

    求反射向量 http://www.cnblogs.com/graphics/archive/2013/02/21/2920627.html

     

    代码和详细分析如下:


    }

    <span style="background-color: rgb(255, 255, 255);">Shader "Custom/球面贴图" {
       Properties {
            _Reflectivity ("Reflectivity", Range (0,1)) = 0.5
            _MainTex("Base", 2D) = "white"
            _Environment ("Environment", 2D) = "white"
        }
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                sampler2D _MainTex;
                sampler2D _Environment;
                float4 _MainTex_ST;
                float _Reflectivity;
                struct v2f {
                    float4  pos : SV_POSITION; // 输出的坐标信息
                    float2  uv : TEXCOORD0; // 输出的主材质纹理信息
                    float2  uv2:TEXCOORD1; // 输出的球面纹理信息
                } ;
                
                // 求反射向量。这个底层有封装,拆开就是这样的
                float3 reflect(float3 I,float3 N)
                {
                    return I - 2.0*N *dot(N,I);
                }
                
                float2 GetUV(float3 r)
                {
                    // 开根号对过渡向量m求模(反射向量r+摄像机向量(0,0,1)为过渡向量m)
                    float m = sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0)); 
                    // 求过渡向量m的单位向量
                    float3 n = float3(r.x / m, r.y / m, r.z / m);
                    // 顶点值域为[-1,1],转为UV的值域[0,1]
                    // 在边缘处UV信息也是更靠近图片里面,才形成镜面水晶球的效果吧
                    return float2(0.5 * n.x + 0.5,0.5 * n.y + 0.5);
                }
      
                v2f vert (appdata_base v)
                {
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
                    
                    // 将顶点信息转换到摄像机坐标
                    float3 posEyeSpace = mul(UNITY_MATRIX_MV,v.vertex).xyz;
                    // 获取摄像机的入射向量
                    float3 I = posEyeSpace - float3(0,0,0);
                    // 将顶点的法线向量转换到摄像机坐标
                    float3 N = mul((float3x3)UNITY_MATRIX_MV,v.normal);
                    // 求法线单位向量
                    N = normalize(N);
                    // 根据入射向量和法线向量求反射向量
                    float3 R = reflect(I,N);
                    // 根据反射向量获取最终的UV信息
                    o.uv2 = GetUV(R);
                    return o;
                }
                float4 frag (v2f i) : COLOR
                {
                    float4 reflectiveColor = tex2D(_Environment,i.uv2);
                    float4 decalColor = tex2D(_MainTex,i.uv);
                    float4 outp = lerp(decalColor,reflectiveColor,_Reflectivity);
                    return outp;
                }
                ENDCG
            }
        }</span>

  • 相关阅读:
    GCD (hdu 5726)
    1092
    D. Puzzles(Codeforces Round #362 (Div. 2))
    A. Lorenzo Von Matterhorn
    Polyomino Composer(UVA12291)
    Optimal Symmetric Paths(UVA12295)
    菜鸟物流的运输网络(计蒜客复赛F)
    1193
    1119
    1374
  • 原文地址:https://www.cnblogs.com/nafio/p/9137319.html
Copyright © 2011-2022 走看看