(转)溶解shader

游戏中物体腐化消失,燃烧消失时,会有从局部慢慢消失的效果,然后配合一些粒子特效,就能达到非常好的美术效果。
类似效果如下:

注:
_DissColor为溶解主色,_AddColor为叠加色,按照溶解的移动方向来看开始色为DissColor+AddColor
上图中DissColor为红色,AddColor为绿色
所以燃烧时
开始色为DissColor + AddColor = 黄色
默认色为DissColor 红色
然后配上火的粒子特效,这样就能模拟比较真实的燃烧效果。
我们也可以设置其他的颜色,比如被各种魔法,化学物品击中.....算了,不敢想象了,好残忍

代码和原理如下:
表面着色器:

Shader "Dissolve/Dissolve_TexturCoords" {
    Properties {
        _Color ("主颜色", Color) = (1,1,1,1)                       // 主色
_MainTex ("模型贴图", 2D) = "white" {}                      // 主材质
_DissolveText ("溶解贴图", 2D) = "white" {}                 // 溶解贴图
_Tile("溶解贴图的平铺大小", Range (0, 1)) = 1                // 平铺值,设置溶解贴图大小  

_Amount ("溶解值", Range (0, 1)) = 0.5                     // 溶解度
_DissSize("溶解大小", Range (0, 1)) = 0.1                   // 溶解范围大小  

_DissColor ("溶解主色", Color) = (1,1,1,1)                  // 溶解颜色
_AddColor ("叠加色,与主色叠加为开始色[R|G|B>0表示启用]", Color) = (1,1,1,1) // 改色与溶解色融合形成开始色
}
SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        Cull off  

        CGPROGRAM
        #pragma target 3.0
        #pragma surface surf BlinnPhong  

        sampler2D _MainTex;
        sampler2D _DissolveText;
        fixed4 _Color;          // 主色
half _Tile;             // 平铺值
half _Amount;           // 溶解度
half _DissSize;         // 溶解范围
half4 _DissColor;       // 溶解颜色
half4 _AddColor;        // 叠加色
// 最终色
static half3 finalColor = float3(1,1,1);  

        struct Input {
            float2 uv_MainTex;  // 只需要主材质的UV信息
};  

void surf (Input IN, inout SurfaceOutput o) {
            // 对主材质进行采样
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
            // 设置主材质和颜色
o.Albedo = tex.rgb * _Color.rgb;
            // 对裁剪材质进行采样,取R色值
float ClipTex = tex2D (_DissolveText, IN.uv_MainTex/_Tile).r;  

            // 裁剪量 = 裁剪材质R - 外部设置量
float ClipAmount = ClipTex - _Amount;
            if(_Amount > 0)
            {
                // 如果裁剪材质的R色值 < 设置的裁剪值  那么此点将被裁剪
if(ClipAmount < 0)
                {
                    clip(-0.1);
                }
                // 然后处理没有被裁剪的值
else
                {
                    // 针对没有被裁剪的点,【裁剪量】小于【裁剪大小】的做处理
// 如果设置了叠加色,那么该色为ClipAmount/_DissSize(这样会形成渐变效果)
if(ClipAmount < _DissSize)
                    {
                        if(_AddColor.x == 0)
                            finalColor.x = _DissColor.x;
                        else
                            finalColor.x = ClipAmount/_DissSize;  

                        if (_AddColor.y == 0)
                            finalColor.y = _DissColor.y;
                        else
                            finalColor.y = ClipAmount/_DissSize;  

                        if (_AddColor.z == 0)
                            finalColor.z = _DissColor.z;
                        else
                            finalColor.z = ClipAmount/_DissSize;
                        // 融合
o.Albedo  = o.Albedo * finalColor * 2;
                    }
                }
            }
            o.Alpha = tex.a * _Color.a;
        }
        ENDCG
    }//endsubshader
}

CG:

//溶解
Shader "Dissolve" {
    Properties
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _DissolorTex ("DissolorTex (RGB)", 2D) = "white" {}
        _RAmount ("RAmount", Range (0, 1)) = 0.5

        _DissolorWith("DissolorWith", float) = 0.1//溶解过度宽度
        _DissColor ("DissColor", Color) = (1,1,1,1)//溶解颜色
        _Illuminate ("Illuminate", Range (0, 4)) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        Pass
        {
        CGPROGRAM
        #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float2 texcoord1 : TEXCOORD1;
            };
            struct v2f
            {
                float4 pos : POSITION;
                half2 texcoord : TEXCOORD0;
                half2 texcoord1 : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _DissolorTex;
            float4 _DissolorTex_ST;
            half _RAmount;

            half _DissolorWith;
            half4 _DissColor;
            half _Illuminate;

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.texcoord1 = TRANSFORM_TEX(v.texcoord1, _DissolorTex);
                return o;
            }

            half4 frag(v2f i) :COLOR
            {
                half4 mainCol = tex2D(_MainTex,i.texcoord);
                half4 DissolorTexCol = tex2D(_DissolorTex,i.texcoord1);
                half clipVauleR = DissolorTexCol.r - _RAmount;
                if(clipVauleR <= 0)
                {
                    if(clipVauleR > -_DissolorWith)
                    {
                        if(_RAmount != 1)
                        {
                            //插值颜色过度
                            float t = clipVauleR / -_DissolorWith;
                            mainCol = lerp(mainCol, _DissColor, t);
                        }
                        else
                        {
                            discard;
                        }
                    }
                    else
                    {
                        discard;
                    }

                }

                return mainCol * _Illuminate;
            }
        #pragma vertex vert
        #pragma fragment frag

        ENDCG
        }

    } 

}
时间: 2024-12-11 04:12:15

(转)溶解shader的相关文章

[Unity] Simple Shaderlab 1 // UI用的简单shader 1 - 流光

最近经常要给2D游戏写一些新的shader来做特效.比起粒子特效,着色器特效可能更适合UI和2D元素上的表现. 先看一下效果: 关于在shaderlab种实现流光的文章很多,但很少有给UI实现的,并且常常只是Add一层颜色,并没有去表现“光”的效果. 以下是shader全文,后面会介绍一些细节: 1 Shader "UI/Unlit/Flowlight" 2 { 3 Properties 4 { 5 [PerRendererData] _MainTex ("Sprite Te

Esfog_UnityShader教程_溶解效果Dissolve

溶解效果在游戏中是很常见的,比如在一些神话或者魔法世界中,一些NPC角色在剧情需要时候会身体会渐渐的消失掉.甚至有一些更炫的,比如用火焰喷射器把目标燃尽.这些都可以用到溶解效果.这篇文章主要是讲解一下比较基础的溶解效果如何实现,实现的方法并不唯一,本篇只是其中一种思路. 原理 既然想让角色的身体一块块渐渐消失,不妨就让角色身体上相应的部位不进行渲染(或者改成透明,我们这里选择前者).那根据什么来判断身体的哪一部分需要被溶解呢,这时候就需要一张额外的贴图或者利用角色纹理贴图的Alpha通道(本篇选

[Unity] Simple Shaderlab 1 || uGui用简单shader - 流光

最近经常要给2D游戏写一些新的shader来做特效.比起粒子特效,着色器特效可能更适合UI和2D元素上的表现. 先看一下效果: 关于在shaderlab种实现流光的文章很多,但很少有给UI实现的,并且常常只是Add一层颜色,并没有去表现“光”的效果. 以下是shader全文,后面会介绍一些细节: 1 Shader "Sprites/Default_Flowlight" 2 { 3 Properties 4 { 5 [PerRendererData] _MainTex ("Sp

Shader Forge学习

最近学习了一下shader forge,一个屌屌哒插件用来生成shader.尽管其降低了制作shader的难度,但是真的想做出满意的shader的话还是得有一定的CG基础.但是仅仅是做出一些简单的效果的话,这个攻击还是绰绰有余,挺好上手的.只要按下键盘按钮,它就可以换出快捷命令,单击鼠标便可以选取相应的命令,滚动滚轮则可以滚动命令.鼠标拖动拖动柄可以连接,Alt+右键拖过连线便可切断连接. 一.两个简单的效果:uv流动溶解,uv扭曲高光 流动溶解或遮罩 流动扭曲高光

[UnityShader]溶解与重现效果

参考链接:http://www.cnblogs.com/Esfog/p/DissolveShader.html 效果图: 从颜色变化来说,有三种,一种是纹理颜色,一种是纹理与黑边的混合颜色,一种是透明(用discard处理,不绘制像素).还需要一张纹理(任意),根据它的任意一个通道来控制哪部分先消失.例如上面的效果图用的就是这张纹理的r通道: 如果用的是这张纹理(也就是模型自身的纹理)的r通道,会更加酷: 溶解效果代码如下: Shader "Esfog/Dissolve" { Prop

unity shader笔记

clip函数可以用来切割mesh clip(var); var 的值小于0时就会被切割 表面着色器 其实就是生成了定点片元着色器,相当于一种包装和简化吧 标准的填充结构 struct SurfaceOutput { fixed3 Albedo; // diffuse color fixed3 Normal; // tangent space normal, if written fixed3 Emission; half Specular; // specular power in 0..1 r

火云开发课堂 - 《Shader从入门到精通》系列 第一节:Shader介绍与工程搭建

<Shader从入门到精通>系列在线课程 第一节:Shader介绍与工程搭建 视频地址:http://edu.csdn.net/course/detail/1441/22665?auto_start=1 交流论坛:http://www.firestonegames.com/bbs/forum.php 工程下载地址:请成为正式学员获取工程 课程截图: 项目实例: 版权声明:本文为博主原创文章,未经博主允许不得转载.

Qt 3D的研究(五):Gooch Shader

Qt 3D的研究(五):Gooch Shader Qt 3D的一个很大的优势就是采用数据驱动的方式,将C++和GLSL使用QML来表示,动态语言的优势尽显.在上一次的研究中,我实现了一个非常简单的着色器,接下来,我们可以在此基础上,通过设定着色器的数据,制作出更加绚丽的着色效果.作为开始,我们先从几个非真实渲染(Non-Photorealistic Rendering,NPR)开始吧. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/deta

游戏框架其九:网和着色器( Mesh and Shader )

网的重要作用可以导入3DMAX等创建的模型,到游戏中:着色器可以实现特定绚丽的效果.它们的实现如下 1. 网 Mesh的实现: #pragma once //======================================================================== // File: Mesh.h - classes to render meshes in D3D9 and D3D11 // 主要是导入3DMAX等软件生成的模型文件 基于Windows Dir