zoukankan      html  css  js  c++  java
  • Unity论坛问答-Spherize(球面化)效果

    原贴地址: https://forum.unity.com/threads/spherize-alternative.907757/

    题主问道:
    我想做一个Gimp中的Spherize(球面化)滤镜效果, 然后使用了ShaderGraph中的Spherize节点, 但是效果不对.

    bgolus回答:
    你想要的效果叫做stereographic projection(球极投影, 立体投影), 在PhotoShop/Gimp中被叫做Spherize.
    ShaderLab

    Shader "Unlit/StereographicProjectionBubble"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            _PanSpeed ("Pan Speed", Float) = 0.1
            _Spherify ("Spherify", Range(0,1)) = 1
        }
        SubShader
        {
            Tags { "Queue"="Transparent" "RenderType"="Transparent" "PreviewType"="Plane" }
            LOD 100
    
            Blend SrcAlpha OneMinusSrcAlpha
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
    
                float _PanSpeed;
                float _Spherify;
    
                v2f vert (appdata_base v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = v.texcoord.xy;
                    return o;
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    float2 centered_uv = i.uv * 2.0 - 1.0;
                    float z = sqrt(1.0 - saturate(dot(centered_uv.xy, centered_uv.xy)));
                    float2 spherified_uv = centered_uv / (z + 1.0);
                    float2 uv = spherified_uv * 0.5 + 0.5;
    
                    uv = lerp(i.uv, uv, _Spherify);
                    uv = TRANSFORM_TEX(uv, _MainTex);
                    uv.x += frac(_Time.y * _PanSpeed);
                    fixed4 col = tex2D(_MainTex, uv);
    
                    half sqrDist = dot(centered_uv.xy, centered_uv.xy);
                    half mask = 1.0 - sqrDist;
                    mask = saturate(mask / fwidth(mask));
    
                    col.a *= mask;
    
                    return col;
                }
                ENDCG
            }
        }
    }

    ShaderGraph

    一些说明:
        1. ShaderGraph中的Spherize在文档中介绍如下:
        Applies a spherical warping effect similar to a fisheye camera lens

        也就是鱼眼效果
        
        算法大约如下:
            a. 计算点P到圆心的距离d
            b. P' = P * d^4
        当P点在圆周上时, P'与P重合
        P点在圆内时, d<1, P' < P, 并且越接近圆心, P'相比于P越小
        P点在圆外时则相反, d >1, P'>P, 越远离圆心, P'相比于P越大
        
        2. 关于球极投影
        一个半径为1的球体, 从北极点N出发, 过下半球的点P做一条射线, 较赤道平面于P', 参考下图
       
       
        其中P点的坐标为(x, y, z), P'的坐标为(X, Y, 0), 它们之间的关系为:
        
        
        ShaderLab的代码首先将UV转换到(-1, 1), 然后投射到下半球, 计算出z, 注意这里计算得到的z是正数, 而下半球的z应该是负数, 所以1-z变成了1+z.
        再计算出P'坐标, 最后在映射回(0, 1), 从图易知, 越靠近圆心部分, 图形放大的越厉害, 反之缩小的越厉害.
        当UV的值超出圆的范围, 此时z = 0, P' = (x, y), 也就是保持不变.

  • 相关阅读:
    关于lockkeyword
    关于多层for循环迭代的效率优化问题
    Android 面试精华题目总结
    Linux基础回想(1)——Linux系统概述
    linux源代码编译安装OpenCV
    校赛热身 Problem C. Sometimes Naive (状压dp)
    校赛热身 Problem C. Sometimes Naive (状压dp)
    校赛热身 Problem B. Matrix Fast Power
    校赛热身 Problem B. Matrix Fast Power
    集合的划分(递推)
  • 原文地址:https://www.cnblogs.com/yusjoel/p/13260354.html
Copyright © 2011-2022 走看看