[小明学Shader]7.环境映射和Cubemap

对于金属状、玻璃状物体,它们的表面能映射出周围环境。如果碰上这类的物体,用上我们本篇的 shader,就能让这种物体显得更加的逼真。

  • 制作Cubemap

写Shader之前呢,要用到一个Cubemap,可以用Unity的编辑器生成.代码如下:

using UnityEngine;
using UnityEditor;
using System.Collections;

public class GenerateCubeMap : ScriptableWizard {

    public Transform renderformPosition;
    public Cubemap cubeMap;

    void OnWizardUpdate(){
        helpString="Select transform to render from and cubemap to render int o";
        isValid = (renderformPosition != null) && (cubeMap != null);
    }

    void OnWizardCreate(){
        GameObject go = new GameObject ("CubeMap Camera", typeof(Camera));
        go.transform.position = renderformPosition.position;
        go.transform.rotation = renderformPosition.rotation;

        go.camera.RenderToCubemap (cubeMap);
        DestroyImmediate (go);
    }

    [MenuItem("Tool/Render to CubeMap")]
    static void RenderCubeMap(){
        ScriptableWizard.DisplayWizard("render cubemap",typeof(GenerateCubeMap),("Render"));
    }
}

这个脚本为菜单栏创建了一个Wizard,用来创建需要的Cubemap.在创建脚本的位置,可以右键创建一个Cubemap,然后通过对打开的Wizard窗口赋值,即可得到目标位置的Cubemap.

  • 创建环境映射Shader

环境映射的Shader需要在Properties中增加一个CUBE属性,然后在Input中增加类型为float3 的worldRefl.

Shader "Cutom/11.27/2"{
    Properties{
        _MainTex("Base(RGB)",2D)="white"{}
        _Cubemap("Cube Map",CUBE)=""{}
    }
    
    SubShader{
        Tags{"RenderType"="Opaque"}
        LOD 200
        
        CGPROGRAM
        #pragma surface surf Lambert
        
        sampler2D _MainTex;
        samplerCUBE _Cubemap;
        
        struct Input{
            float2 uv_MainTex;
            float3 worldRefl;
        };
        
        void surf(Input In,inout SurfaceOutput o){
            fixed4 c=tex2D(_MainTex,In.uv_MainTex);
            o.Albedo=c.rgb;
            
            fixed4 refcol=texCUBE(_Cubemap,In.worldRefl);
            refcol*=c.a;
            o.Emission=refcol.rgb;
            o.Alpha=refcol.a;
        }
        
        ENDCG
    }
}

将Cubemap上的点设定alpha值,然后将输出的Emission设定为Cubemap相应的值即可.这个 shader 代码,主要是用到了 texCUBE 这个 Unity 内置的方法,这个方法第1个参数是我们的 cubemap 文件,第2个参数是 unity 内置的基于世界坐标系的反射方向,在 Unity 渲染物体的时候,如果我们有 Input 结构需要这个东西,只要在 Input 结构中写上 worldRefl就可以, unity 会帮助把物体某个点的反射方向作为参数送如 shader,我们只要使用就可以。texCUBE 取出的值,我们把它放置到 SurfaceOutput 的 Emission 变量里面,出了 surf()这个方法后,光照方程会被运行, Emission 的值会在此过程保持,最后出了光照方程后( Unity在光照方程中主要计算某个点的光照颜色), Unity 会把 Emission 的颜色做加法加到顶点的颜色上,合成最后的输出到显卡缓存的色彩,也就是我们最后看到的颜色.

 

  • 效果图

虽然看起来很想透明的玻璃球,但这是一个镜子球的效果,我们看到的是反射的样子.

posted @ 2015-11-26 13:08  WongSiuming  阅读(594)  评论(0编辑  收藏  举报