美文网首页
Kingdom-water

Kingdom-water

作者: Foo_d488 | 来源:发表于2018-04-29 14:25 被阅读0次

    基本思路:根据环境(风,光,基础运动)动态生成一张置换贴图用于倒影变化

    Flash版本关键代码如下:
    声明置换滤镜

    //mapBitmap 基于这个对象扭曲目标图像
    //mapPoint 一个值,它包含目标显示对象的左上角相对于映射图像左上角的偏移量。
    //componentX 通过这个参数将mapBitmap中的颜色或alpha通道设置为映射图像,并基于这个映射图像在x轴方向置换像素。
    //componentY 通过这个参数将mapBitmap中的颜色或alpha通道设置为映射图像,并基于这个映射图像在y轴方向置换像素。
    //scaleX 这个参数定义了应用置换后在x轴上的偏移量,数值越大,置换效果越明显
    //scaleY 这个参数定义了应用置换后在y轴上的偏移量,数值越大,置换效果越明显
    //mode 定义滤镜效果超出图像大小时,该部分像素的处理方式。它的可能值为DisplacementMapFilterMode常量。
    //     WRAP表示置换值折返到图像的另一侧;
    //     CLAMP的意义和ConvolutionFilter一样,表示置换值重复图像边缘的像素;
    //     IGNORE表示忽略置换并使用源像素;
    //     COLOR同样和ConvolutionFilter类似,用指定的颜色和透明度替换置换值。
    //color 指定对于超出范围的替换应用什么颜色。置换的有效范围是 0.0 到 1.0。如果 mode 设置为 DisplacementMapFilterMode.COLOR,则使用此参数。
    //alpha 指定对于超出范围的替换应用什么 Alpha 值。它被指定为 0.0 到 1.0 之间的标准值。例如,0.25 设置透明度值为 25%。如果 mode 设置为 DisplacementMapFilterMode.COLOR,则使用此参数。
    //ex: Offx = (mapBitmap[componentX][x,y]-128)/128*scaleX;
    displacementFilter = new DisplacementMapFilter(displacementBitmap, zeroPoint, 1, 2, 256, 256, DisplacementMapFilterMode.COLOR, baseColor, 0.5);
    

    每帧逻辑,加入了风和夜色的影响:

      override public function update():void
     {
        timer += FlxG.elapsed;
        if (weather.changed > weatherChanged)
        {
          //interpolateColor 插值运算 baseColor*(1- weather.darkness)+ weather.darknessColor*weather.darkness
          currentBase = 0xFF000000 | Utils.interpolateColor(baseColor, weather.darknessColor, weather.darkness)
                    
          //涟漪幅度    WIND_RIPPLE_MULTIPLIER:Number = 25;
          var rippleScale:int = int(weather.wind*WIND_RIPPLE_MULTIPLIER);
          var xscale:int = rippleScale/2;
          var yscale:int = rippleScale;
          if(xscale != 2)
              xscale = xscale;
          //噪声矩阵   rMul, gMul, bMul, aMul, rOff, gOff, bOff, aOff NOISE_BIAS:int = 100;
          noiseRange = new ColorTransform(xscale/128,yscale/128,1,1,(128-xscale+(NOISE_BIAS*xscale/128)),(128-yscale+(NOISE_BIAS*yscale/128)),1,1)
          weatherChanged = weather.t
         }
    }
    

    渲染部分:
    BitmapData.perlinNoise(baseX:Number, baseY:Number, numOctaves:uint, randomSeed:int, stitch:Boolean, fractalNoise:Boolean, channelOptions:uint=7, grayScale:Boolean=false, offsets:Array=null):void
    是FLASH自带的生成柏林噪声的方法。生成多张噪点图叠加得到最终的结果。
    baseX, baseY分别是沿X,Y轴生成的杂点频率。
    numOctaves 噪点图的张数。
    randomSeed 要使用的随机种子数。如果您保持使所有其他参数不变,可以通过改变随机种子值来生成不同的伪随机结果。
    stitch 一个布尔值。如果该值为 true,则该方法将尝试平滑图像的转变边缘以创建无缝的纹理,用于作为位图填充进行平铺。
    fractalNoise 一个布尔值。如果该值为 true,则该方法将生成碎片杂点;否则,它将生成湍流。带有湍流的图像具有可见的不连续性渐变,可以使其具有更接近锐化的视觉效果,例如火焰或海浪。
    channelOptions 一个数字,可以是四个颜色通道值(BitmapDataChannel.RED、BitmapDataChannel.BLUE、BitmapDataChannel.GREEN 和 BitmapDataChannel.ALPHA)的任意组合。您可以使用 logical OR (|) 运算符来组合通道值。
    grayScale 一个布尔值。如果该值为 true,则通过将红色、绿色和蓝色通道的每一个值都设置为相同的值来创建一个灰度图像。如果此值设置为 true,则 Alpha 通道值将不会受到影响。
    offsets 与每个 octave 的 x 和 y 偏移量相对应的点数组。通过操作这些偏移量值,您可以平滑滚动 perlinNoise 图像的图层。偏移数组中的每个点将影响一个特定的 octave 杂点函数。

      override public function draw():void
            {
                if (timer > 0.1)
                { // Update the water ripple
                    perlinOffset.y += 1/5;
                    perlinOffset.x = FlxG.camera.scroll.x*1.5;
                    displacementBitmap.perlinNoise(32, 4, 1, 12312, false, false, 1|2, true, [perlinOffset]);
                    displacementBitmap.colorTransform(rect,noiseRange);
                    // Adjust the base color according to the weather.
                    displacementFilter.color = currentBase;
                    timer = 0;
                }
                var px:BitmapData = pixels;
                matrix.identity();
                matrix.scale(1, -1);
                getScreenXY(_point);
                matrix.translate(-_point.x, _point.y);
                // Clear the reflection
                px.fillRect(rect, currentBase);
                Utils.gradientOverlay(px, [0x00000000,0x66000000], 90, 4);
                // Flip the screen and copy it to the reflection
                px.draw(FlxG.camera.buffer, matrix, transform);
                
                // Draw the lights
                var l:Light;
                for (var i:int = 0; i < lights.length; i++){
                    l = lights.members[i] as Light;
                    l.getScreenXY(_point);
                    if(l.visible && -64 < _point.x && _point.x < FlxG.width + 64){
                        l.reflected.alpha = weather.darkness * 0.8;
                        l.reflected.alpha *= Math.min(1.0, (weather.wind * 10));
                        l.reflected.drawFrame();
                        stamp(l.reflected, _point.x - l.reflected.width/2 + 4, (y - l.y) * 0.3);
                    }
                }
                
                // Apply the ripple filter
                px.applyFilter(px, rect, zeroPoint, displacementFilter); 
                dirty = true;
                super.draw()
            }
    

    unity中的水实现思路:
    1.在每个像素点上用Mathf.Perlin(float x, float y)产生随机值,生成柏林噪声贴图
    2.通过shader取贴图通道值作变换

    
        void CalcNoise(float dx, float dy)
        {
            float y = 0.0F;
            while(y < noiseTex.height)
            {
                float x = 0.0F;
                float sample = 0;
                while(x < noiseTex.width)
                {
                    
                    float xCoord = x / noiseTex.width * scale;
                    float yCoord = y / noiseTex.height * scale;
                    sample = Mathf.PerlinNoise(xCoord + dx, yCoord + dy);//*_force;
                    pix[(int)(y * noiseTex.width + x)] = new Color(sample, sample, sample);
                    x++;
                }
                y++;
            }
            noiseTex.SetPixels(pix);
            noiseTex.Apply();
        }
    
        float n = 0;
        void Update()
        {
            n += deltaY;
            CalcNoise(0, n);
            rend.material.SetTexture("_NoiseTex", noiseTex);
        }
    

    比较特殊的一点是因为游戏是像素风的,在取坐标的时候取了下整,保证同一个像素格内的偏移是gg

    
    Shader "ProjZombie/WaterSprite"
    {
        Properties
        {
            [PerRendererData] _MainTex ("Texture", 2D) = "white" {}
            _NoiseTex ("Noise Texture (RG)", 2D) = "white" {}
            _Color ("Tint", Color) = (1,1,1,1)
            _HeatForce  ("Heat Force", range (0,0.1)) = 0.1
            _width  ("Heat Force", range (1.0,1024.0)) = 256.0
            _height  ("Heat Force", range (1.0,1024.0)) = 256.0
    
        }
        SubShader
        {
            Tags
                { 
                    "Queue"="Transparent" 
                    "IgnoreProjector"="True" 
                    "RenderType"="Transparent" 
                    "PreviewType"="Plane"
                    "CanUseSpriteAtlas"="True"
                }
            // No culling or depth
        ZWrite Off
        Cull Off
        Blend Off
    
            Pass
            {
            
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                    float4 color    : COLOR;
                };
                
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                    fixed4 color    : COLOR;
                };
                
                fixed4 _Color;
                sampler2D _NoiseTex;
                            float _HeatForce;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = v.uv;
                    o.color = v.color * _Color;
                    #ifdef PIXELSNAP_ON
                    o.vertex = UnityPixelSnap (OUT.vertex);
                    #endif
                    return o;
                }
                
                sampler2D _MainTex;
                float _width;
                float _height;
                //It is executed for each pixel and the output is the color info of the pixel.
                fixed4 frag (v2f i) : SV_Target
                {
    
                    half4 offsetColor1 = tex2D(_NoiseTex, i.uv);
                    i.uv.x = ceil(i.uv.x*_width)/_width;
                    i.uv.y = ceil(i.uv.y*_height)/_height;
                    i.uv.x += offsetColor1.r  * _HeatForce;
                    i.uv.y += offsetColor1.g * _HeatForce;
                    fixed4 col = tex2D( _MainTex, i.uv);
                    col.rgb *= col.a;
                    return col;
                }
                ENDCG
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Kingdom-water

          本文链接:https://www.haomeiwen.com/subject/dkbolftx.html