关闭

Shader学习历程(四)——Unity官方Image effect__Fisheye

标签: unitygpushader屏幕特效ImageEffec
2568人阅读 评论(0) 收藏 举报
分类:

前面

有时很想自己做一些很酷炫的image effect,但又不知道要从何开始,不妨先学习学习官方的Image effect是怎么实现的。这一篇主要探究鱼眼效果是如何实现的。下附两幅图看看效果是啥样的:
这里写图片描述这里写图片描述

主要

我们现在正式看看它是怎么实现的,一个完整的屏幕特效分为两部分,一是cpu部分,它负责决定何时执行,并把rendertexture和相关参数传递给gpu,二是gpu部分,也就是处理rendertexture的shader,它负责处理当前rendertexture并输出。
先附上C#代码:

using System;
using UnityEngine;

namespace UnityStandardAssets.ImageEffects
{
    [ExecuteInEditMode]
    [RequireComponent (typeof(Camera))]
    [AddComponentMenu ("Image Effects/Displacement/Fisheye")]
    class Fisheye : PostEffectsBase
    {
        public float strengthX = 0.05f;
        public float strengthY = 0.05f;

        public Shader fishEyeShader = null;
        private Material fisheyeMaterial = null;


        public override bool CheckResources ()
        {
            CheckSupport (false);
            fisheyeMaterial = CheckShaderAndCreateMaterial(fishEyeShader,fisheyeMaterial);

            if (!isSupported)
                ReportAutoDisable ();
            return isSupported;
        }

        void OnRenderImage (RenderTexture source, RenderTexture destination)
        {
            if (CheckResources()==false)
            {
                Graphics.Blit (source, destination);
                return;
            }

            float oneOverBaseSize = 80.0f / 512.0f; // to keep values more like in the old version of fisheye

            float ar = (source.width * 1.0f) / (source.height * 1.0f);

            fisheyeMaterial.SetVector ("intensity", new Vector4 (strengthX * ar * oneOverBaseSize, strengthY * oneOverBaseSize, strengthX * ar * oneOverBaseSize, strengthY * oneOverBaseSize));
            Graphics.Blit (source, destination, fisheyeMaterial);
        }
    }
}

解释:

  • [ExecuteInEditMode]的作用是使其直接在编辑窗口中运行,这样我们就不用点Play了。

  • Fisheye类继承的是PostEffectsBase,PostEffectsBase这个类也是导入effect包自带的,我们可以看到它重载了CheckResources()方法,这个方法用来初始化,初始化分为两部分,一是创建一个隐藏的material(用来使用FisheyeShader),二是检测设备是否支持此屏幕特效。然后调用它的是在PostEffectsBase中的如下代码:

 protected void Start ()
        {
            CheckResources ();
        }
  • OnRenderImage(RenderTexture source, RenderTexture destination)可以在挂在Camera上的所有脚本中使用,它有两个参数,sourse是当前屏幕所要显示的RenderTexture,destination是目标RenderTexture ,函数作用用通俗的话来说就是本来正常渲染出的画面现在不直接放到屏幕上了,我们把它传递给shader,然后把处理过后的画面再显示在屏幕上,如果一个摄像机上有多个屏幕特效的话,那么上一个的输出将作为下一个的输入。

  • Graphics.Blit (source, destination); 当初始化不通过的时候,使用此函数将source直接作为destination输出

  • Graphics.Blit (source, destination, fisheyeMaterial); 此函数将把source作为material的_MainTex,把shader的输出作为destination。

接下来是shader代码:

Shader "Hidden/FisheyeShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "" {}
    }

    // Shader code pasted into all further CGPROGRAM blocks
    CGINCLUDE

    #include "UnityCG.cginc"

    struct v2f {
        float4 pos : SV_POSITION;
        float2 uv : TEXCOORD0;
    };

    sampler2D _MainTex;

    float2 intensity;

    v2f vert( appdata_img v ) 
    {
        v2f o;
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = v.texcoord.xy;
        return o;
    } 

    half4 frag(v2f i) : Color 
    {
        half2 coords = i.uv;
        coords = (coords - 0.5) * 2.0;      

        half2 realCoordOffs;
        realCoordOffs.x = (1-coords.y * coords.y) * intensity.y * (coords.x); 
        realCoordOffs.y = (1-coords.x * coords.x) * intensity.x * (coords.y);

        half4 color = tex2D (_MainTex, i.uv - realCoordOffs);    

        return color;
    }

    ENDCG 

Subshader {
 Pass {
      ZTest Always Cull Off ZWrite Off

      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
      ENDCG
  }

}

Fallback off

} // shader

解释:shader部分基础内容太多,我们只关注主体计算部分,如有疑问或纠错,欢迎在下面评论,我将迅速回复。
首先需要提醒的是,脚本暴露的两个参数strengthX和strengthY分别控制着屏幕纵向和横向的拉伸。。。。具体我也不知道为什么。因此在前面的C#代码中,strengthX*(宽长比)的作用是:若是屏幕比较扁,那么纵向的strengthX增长速率将加快,这样纵横变化速率将显得一致。

coords = (coords - 0.5) * 2.0;

这一句我们得到了一个该像素与中心点相关的值,下面将要用到。

half2 realCoordOffs;
        realCoordOffs.x = (1-coords.y * coords.y) * intensity.y * (coords.x); 
        realCoordOffs.y = (1-coords.x * coords.x) * intensity.x * (coords.y);

这两句定义并计算了偏移量,可能我们不太知道它为什么要这样计算,但我们可以从中看出偏移量与像素点到中心点的距离成正比,与像素点到轴的距离成正比。
还有一个需要注意的地方就是如下这一句
half4 color = tex2D (_MainTex, i.uv - realCoordOffs);
你会发现这一句使最终的纹理始终向中心点靠近,这会让人疑惑,其实这就是所谓的拉伸,即相同数目的像素点对应更少数目的纹理像素点,这也就造成了当你拉伸较大将导致视野变小的现象。这也意味着可能有两个像素点对应着相同的纹理像素 。

最后

就这样了,希望大家能够指出错误,相互交流。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Unity3D图像后处理特效——Glow image effect

Glow (sometimes called "Bloom") can dramatically enhance the rendered image by making overbright par...
  • Amazonzx
  • Amazonzx
  • 2012-07-15 21:22
  • 7778

Unity3D for VR 学习(11): 后期屏幕渲染特效(Image Effect)

在Unite ShangHai 2016 Keynote中,《Adam》的图形技术介绍,令人印象深刻:可以与电影效果相媲美、近乎次时代大作、好莱坞大片效果的3分钟实时渲染的短片,淋漓尽致的展现了uni...
  • Alasa_TT
  • Alasa_TT
  • 2016-09-02 11:53
  • 1826

【Unity3D Shader编程】之八 Unity5新版Shader模板源码解析&径向模糊屏幕特效的实现

概要:本文对Unity5中全新的三种Shader模板的源码进行了解析,然后还讲解了运动模糊屏幕特效的实现方法。 Unity5和之前的书写模式有了一定的改变。Unity5时代的Shader Refere...
  • zhmxy555
  • zhmxy555
  • 2015-10-25 20:26
  • 28757

【Unity ImageEffect】一个用于角色遮挡透视轮廓的效果

前言         有些游戏项目需要在角色被遮挡后仍然显示出来,让玩家不会迷失自我的感觉,但一般不会用原颜色渲染出来,一般会用另外的颜色表示。本文介绍一种当角色被遮挡后,用另外一种颜色并有轮廓渐变效...
  • herox25000
  • herox25000
  • 2016-01-12 10:15
  • 5213

Unity Image Effect

Antialiasing 抗锯齿 SSAA 模式最快,但是效果最差, 随后是 NFAA, FXAAII, FXAA II, DLAA,FXAAs. 速度随之降低,效果增强Bloom and Lens...
  • u010893023
  • u010893023
  • 2015-10-30 09:38
  • 2104

Unity中的image effect总结

这些效果是可以叠加的,部分一起用画面超赞 1.Vignetting 光晕效果 :可以实现场景中的聚焦,以及对中心之外的物体做模糊处理 2.vortexEffect  漩涡状的扭曲效果,可以...
  • yukoxiaowangzi
  • yukoxiaowangzi
  • 2014-12-22 14:03
  • 1331

Unity3D图像后处理特效——Grayscale image effect

Grayscale is a simple image effect that changes colors to grayscale by default. It can also use a Te...
  • Amazonzx
  • Amazonzx
  • 2012-07-16 09:54
  • 7412

【Unity ImageEffect】一个用于角色外边缘发光的效果

前言         现在很多游戏都有选中角色后高亮显示选中目标的需求,但是Unity是没有提供这样的功能(很不爽)。虽然在Unity Store上有几款很不错的插件能满足需求,但是往往别人的东西过...
  • herox25000
  • herox25000
  • 2016-01-14 10:17
  • 4595

《ImageEffects(屏幕特效)官方文档翻译》——编写屏幕特效【Writing Image Effects】

译注:鉴于翻译的混乱情况,将Texture译为纹理(实际上也应该如此),因为纹理和贴图还是有一些区别的。Image Effects是Unity3D中一种进行图像后期渲染的方式。
  • kevlis
  • kevlis
  • 2016-11-01 11:27
  • 701

Unity3D图像后处理特效——Fisheye image effect

The Fisheye image effect creates distorts the image as if viewed through a fisheye lens (although ...
  • Amazonzx
  • Amazonzx
  • 2012-07-15 20:41
  • 3252
    个人资料
    • 访问:53561次
    • 积分:957
    • 等级:
    • 排名:千里之外
    • 原创:44篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    个人博客
    最新评论