【OpenGL】Shader实例分析(七)- 雪花飘落效果

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40624603

研究了一个雪花飘落效果。感觉挺不错的。分享给大家,效果例如以下:

代码例如以下:

Shader "shadertoy/Flakes" {  // https://www.shadertoy.com/view/4d2Xzc
	Properties{
		iMouse ("Mouse Pos", Vector) = (100,100,0,0)
		iChannel0("iChannel0", 2D) = "white" {}
		iChannelResolution0 ("iChannelResolution0", Vector) = (100,100,0,0)
	}

	CGINCLUDE
	 	#include "UnityCG.cginc"
  		#pragma target 3.0
  		#pragma glsl

  		#define vec2 float2
  		#define vec3 float3
  		#define vec4 float4
  		#define mat2 float2x2
  		#define iGlobalTime _Time.y
  		#define mod fmod
  		#define mix lerp
  		#define atan atan2
  		#define fract frac
  		#define texture2D tex2D
  		// 屏幕的尺寸
  		#define iResolution _ScreenParams
  		// 屏幕中的坐标。以pixel为单位
  		#define gl_FragCoord ((_iParam.srcPos.xy/_iParam.srcPos.w)*_ScreenParams.xy) 

  		#define PI2 6.28318530718
  		#define pi 3.14159265358979
  		#define halfpi (pi * 0.5)
  		#define oneoverpi (1.0 / pi)

  		fixed4 iMouse;
  		sampler2D iChannel0;
  		fixed4 iChannelResolution0;

        struct v2f {
            float4 pos : SV_POSITION;
            float4 srcPos : TEXCOORD0;
        };              

       //   precision highp float;
        v2f vert(appdata_base v){
        	v2f o;
        	o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
            o.srcPos = ComputeScreenPos(o.pos);
            return o;
        }  

        vec4 main(v2f _iParam);

        fixed4 frag(v2f _iParam) : COLOR0 {
			return main(_iParam);
        }  

		vec4 main(v2f _iParam) {
		    vec2 p = gl_FragCoord.xy/iResolution.xy;
		    vec3  col = vec3(0,0,0);
		    float dd = 150;
		    for( int i=0; i<dd; i++ )
		    {
		        float an = 6.2831*float(i)/dd;
		        vec2  of = vec2( cos(an), sin(an) ) * (1.0+0.6*cos(7.0*an+iGlobalTime)) + vec2( 0.0, iGlobalTime );
		        col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );
		        col = max( col, texture2D( iChannel0, p +  5.0*of/iResolution.xy ).xyz );
		    }
		    col = pow( col, vec3(1.0,2.0,3.0) ) * pow( 4.0*p.y*(1.0-p.y), 0.2);

			return vec4( col, 1.0 );
		}

    ENDCG    

    SubShader {
        Pass {
            CGPROGRAM    

            #pragma vertex vert
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest     

            ENDCG
        }
    }
    FallBack Off
}

代码分析:

1)七边形雪花的绘制算法

详细代码例如以下:

float dd = 150;
for( int i=0; i<dd; i++ )
{
	float an = 6.2831*float(i)/dd;
	vec2  of = vec2( cos(an), sin(an) ) * (1.0+0.6*cos(7.0*an+iGlobalTime)) + vec2( 0.0, iGlobalTime );
	col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );
	col = max( col, texture2D( iChannel0, p +  5.0*of/iResolution.xy ).xyz );
}

在理解这段代码前。先理解怎么画一个圈,代码例如以下:

float dd = 30;
for( int i=0; i<dd; i++ )
{
	float an = 6.2831*float(i)/dd;
	vec2  of = vec2( cos(an), sin(an) );
	col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );
}

然后再准备一张贴图,图片中间是一个白色像素,周围都是黑色

效果例如以下:

这段代码处于fragment shader中,意味着屏幕上每个点都会进行上述的算法。详细例如以下,遍历贴图中该点周围的点(上面的代码中为距离该点为20单位的圆上的点)。把周围点中最亮的作为该点的颜色。 上面的贴图有点特殊。仅仅有一个点是白色,其余点都是黑色的。那么仅仅有距离该点正好为20单位的点才会变成亮色,其余的点都是黑色。如上图的结果。

一句话总结上面算法的效果:贴图中的每个“相对亮点”的周围都会产生“相对亮的特定图形”,图形的亮度取决于该点的亮度。越亮越明显。效果能够參考文末的图片。

接下来理解这段代码:

float dd = 150;
for( int i=0; i<dd; i++ )
{
	float an = 6.2831*float(i)/dd;
	vec2  of = vec2( cos(an), sin(an) ) * (1.0+0.7*cos(7.0*an));
	col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );
//	col = max( col, texture2D( iChannel0, p +  5.0*of/iResolution.xy ).xyz );
}

输出结果例如以下:

a)  1.0+0.7*cos(7.0*an)的图像例如以下:

b)算法中 of 向量的路径为:

结果就非常清晰了;事实上这里算法和《【OpenGL】Shader实例分析(二)- Heart》中绘制心形的算法非常类似。

最后加上时间就能够实现动画了:

vec2  of = vec2( cos(an), sin(an) ) * (1.0+0.6*cos(7.0*an+iGlobalTime)) + vec2( 0.0, iGlobalTime );

第一个iGlobalTime。用来控制雪花的旋转。第二个iGlobalTime使雪花下落。

2)后期颜色等处理

这里能够理解为一种postEffect处理。详细是例如以下的代码贡献的效果:

col = pow( col, vec3(1.0,2.0,3.0) ) * pow( 4.0*p.y*(1.0-p.y), 0.2);

a)  pow(col, vec3(1.0, 2.0, 3.0)) 这句话使得颜色变成暖色调。

col值的范围为[0,1],对小数继续pow运算,次数越高,该值越小。

比方:0.5的1次方是0.5。 2次方为0.25。 3次方为0.125等。所以这句话的作用非常明显:red成份不变,green变小一些,blue变的更小。达到的效果。使得总体颜色会偏向暖色调。

b)pow(4.0*p.y*(1.0-p.y), 0.2) 使得屏幕上下两边变暗。

最后附上shader中用到的贴图:

经过程序处理后,得到例如以下:

文章完成,欢迎讨论。

时间: 2024-12-26 06:35:03

【OpenGL】Shader实例分析(七)- 雪花飘落效果的相关文章

【OpenGL】Shader实例分析(六)- 卡牌特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/30989295 本文将介绍怎么通过alpha通道来隐藏信息,并实现卡牌特效.运行效果如下: 代码如下: Shader "stalendp/imageShine" { Properties { _MainTex ("image", 2D) = "white" {} _NoiseTex("noise", 2D) = &qu

JS制作的可控制风级的雪花飘落效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>JS制作的可控制风级的雪花飘落效果|kid

纯代码为网站站点添加雪花飘落效果

<script type="text/javascript"> (function($){ $.fn.snow = function(options){ var $flake = $('<div id="snowbox" />').css({'position': 'absolute','z-index':'9999', 'top': '-50px'}).html('?'), documentHeight = $(document).heig

Android实战简易教程-第六十九枪(自定义控件实现雪花飘落效果)

现在APP要求越来越高了,不只是要求实现功能,颜值的要求也越来越高,下面我们通过自定义控件来实现雪花飘落的效果,可以作为界面背景哦. 1.自定义控件: package com.test.a; import java.util.Random; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Can

原生js实现雪花飘落效果

雪花飘落的效果实现步骤:1.使用setInterval定时器每800毫秒创建一个雪花:2.把每一个雪花作为参数传进动态下落的方法中即可. <style> *{padding: 0;margin: 0;} body{ background:#000; width: 100%; height: 100%; overflow:hidden; } </style> <div id="flame"></div> js实现代码: <script

猫猫学IOS(三十三)UI之Quartz2D雪花飘落效果刷帧

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 效果: 可以加入随机数实现真的飘落效果哦. 代码: -(id)initWithCoder:(NSCoder *)aDecoder { //请注意这里一定要先初始化父类的构造方法 if (self=[super initWithCoder:aDecoder]) { NSLog(@"initWithCoder:"); /

【案例】雪花飘落效果

使用DOM节点操作1.周期性创建雪花setInterval()2.雪花出现的位置随机function rand(m,n){return Math.floor(Math.random() * (n-m+1)) + m}document.documentElement.clientWidth || document.body.clientWidth3.控制雪花向下飘(移动的步径)var step = 1;4.移除超出窗口高度的雪花元素document.documentElement.clientHe

【OpenGL】Shader实例分析(九)- AngryBots中的主角受伤特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40859441 AngryBots是Unity官方的一个非常棒的样例.非常有研究价值. 曾经研究的时候.因为其内容丰富,一时间不知道从哪入手写文章分析. 这一段时间研究shader技术比較多一些,就从shader的这一方面開始吧.首先分析当中的一个屏幕特效:当主角受到攻击时会出现的全屏效果(postScreenEffect).效果例如以下: 事实上这是一种的Bloom效果,相关文件有:M

Qt实现桌面动态背景雪花飘落程序

        曾经收到过一份礼物,一个雪花飘落的程序,觉得效果很炫,通过前几篇的学习,我们已经掌握了贴图的一些技巧了,那么现在就可以自己实现了(当然你必须先拥有qt信号与槽的基础知识),这里先看效果,然后再分析如何实现. 效果图:          这个程序实现很久了,也是当初学习qt的时候写的,因为工作的原因,当初的部分设想,并没有全部实现,现在分享,供大家一起学习.         当初的设想:                 1.雪花随机飘落                 2.地面的花