• Unity3D-Shader-实现X光效果


    【旧博客转移 - 2016年1月3日 16:40 

    最近学习了一些Shader效果,打算把学到的知识总结一下,这篇讲一下这种轮廓发光的效果(如下图所示),也有一些地方管这个叫X光

     
     

    1.原理

    可以看到图上的蓝色人物,边缘颜色比较深,而中间的比较浅,这是利用法线跟视线向量的点乘值计算出颜色浓度来实现的
     

    2.代码

    Shader "lijia/Xray"
    {
        Properties
        {
            _RimColor("RimColor", Color) = (0, 0, 1, 1)
            _RimIntensity("Intensity", Range(0, 2)) = 1
        }
        SubShader
        {
            Tags {"Queue"="Transparent" "RenderType"="Opaque" }
    
            LOD 200
            Pass
            {
                Blend SrcAlpha One//打开混合模式
                ZWrite off
                Lighting off
    
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float3 normal:Normal;
                };
    
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    fixed4 color:COLOR;
                };
    
                fixed4 _RimColor;
                float _RimIntensity;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                    float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));//计算出顶点到相机的向量
                    float val = 1 - saturate(dot(v.normal, viewDir));//计算点乘值
                    o.color = _RimColor * val * (1 + _RimIntensity);//计算强度
                    return o;
                }
    
                fixed4 frag (v2f i) : COLOR
                {
                    return i.color;
                }
                ENDCG
            }
        }
    }

    float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));//计算出顶点到相机的向量
    这一句是调用了UnityCG.cginc库中的ObjSpaceViewDir方法,获得viewDir

    inline float3 ObjSpaceViewDir( in float4 v )
    {
        float3 objSpaceCameraPos = mul(_World2Object, float4(_WorldSpaceCameraPos.xyz, 1)).xyz;
        return objSpaceCameraPos - v.xyz;
    }

    翻看UnityCG中ObjSpaceViewDir方法的源码,发现它是拿到_WorldSpaceCameraPos(世界坐标相机的位置),左乘World2Object矩阵,转成模型坐标系
    最后objSpaceCameraPos - v.xyz (向量相减),得到viewDir向量

    viewDir跟normal的点乘值,就表示两个向量的夹角大小

    1. 夹角 < 90°时,点乘>0
    2. 夹角 = 90°时,点乘=0
    3. 夹角 > 90°时,点乘<0

    边缘的顶点,点乘值接近90度,也就是值接近0,所以这里用1减去点乘值( saturate函数:返回0-1之间的数 )

    float val = 1 - saturate(dot(v.normal, viewDir));
    
    计算出颜色强度后,把颜色传给fragment着色器去输出渲染,就可以看到效果了
    
  • 相关阅读:
    人脸识别算法初次了解
    白话经典算法系列之二 直接插入排序的三种实现
    常见浏览器兼容性问题与解决方式
    MP3的频率、比特率、码率与音质的关系
    程序猿接私活经验总结,来自csdn论坛语录
    Java虚拟机工作原理具体解释
    簡單SQL存儲過程實例
    全栈JavaScript之路(七)学习 Comment 类型节点.
    strdup函数的使用方法
    POJ 2823 Sliding Window 【单调队列】
  • 原文地址:https://www.cnblogs.com/lijiajia/p/6861432.html
Copyright © 2020-2023  润新知