热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenGLShader实例分析(2)绘制心脏跳动效果

本文将介绍怎么用Shader来绘制一个跳动的心脏。这里会涉及到一些数学知识。先看效果图:源代码如下:Createdbyinigoquilez-iq2013Lic

本文将介绍怎么用Shader来绘制一个跳动的心脏。这里会涉及到一些数学知识。先看效果图:

OpenGL Shader实例分析(2)绘制心脏跳动效果

源代码如下:

// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// changed by stalendp@gmail.com
Shader "shadertoy/Heart" { // see https://www.shadertoy.com/view/XsfGRn
 CGINCLUDE 
 
 #include "UnityCG.cginc"  
 #pragma target 3.0 
 struct vertOut { 
  float4 pos:SV_POSITION; 
  float4 srcPos; 
 }; 
 
 vertOut vert(appdata_base v) { 
  vertOut o; 
  o.pos = mul (UNITY_MATRIX_MVP, v.vertex); 
  return o; 
 } 
 
 fixed4 frag(float4 sp:WPOS) : COLOR0 { 
 float2 p = (2.0*sp.xy - _ScreenParams.xy) / min(_ScreenParams.y, _ScreenParams.x);
 p.y -= 0.25;
 
 //background color
 float3 bcol = float3(1.0,0.8,0.7-0.07*p.y) * (1.0 - 0.25*length(p));
 
 // animate
 float tt = fmod(_Time.y, 1.5)/1.5;
 float ss = pow(tt,.2) * 0.5 + 0.5;
 ss -= ss*0.2*sin(tt*6.2831*3.0)*exp(-tt*4.0);
 p *= float2(0.5, 1.5) + ss * float2(0.5, -0.5);
 
 // shape
 float a = atan2(p.x,p.y)/3.141593;
 float r = length(p);
 float h = abs(a);
 float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h);
 
 // color
 float s = 1.0-0.5*clamp(r/d,0.0,1.0);
 s = 0.75 + 0.75*p.x;
 s *= 1.0-0.25*r;
 s = 0.5 + 0.6*s;
 s *= 0.5+0.5*pow( 1.0-clamp(r/d, 0.0, 1.0 ), 0.1 );
 float3 hcol = float3(1.0,0.5*r,0.3)*s;
 
 float3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, d-r) );
 
 return float4(col,1.0);
 } 
 
 ENDCG 
 
 SubShader { 
 Pass { 
  CGPROGRAM 
 
  #pragma vertex vert 
  #pragma fragment frag 
  #pragma fragmentoption ARB_precision_hint_fastest 
 
  ENDCG 
 } 
 
 } 
 FallBack Off 
}

网上有很多关于心形的绘制方法,这里介绍一种。

1. 心形画法的原理

float a = atan2(p.y,p.x)/3.1415;

atan2(p.y,p.x)求的是向量(x,y)所对应的角度。求得的是弧度制的值,除以pi后得到的范围是[0,1];

所以上面的函数就是求得平面上的坐标点所对应向量的角度(被映射到[0,1]之间);

如下图,点p1和p2是屏幕上的不同的两点,但是他们对应的角度是(4/8)*pi(经过上面公式的映射,值为4/8);

下图是个单位圆,p1和p2中间标注的点4/8就是(atan2(p.y,p.x)/3.1415)的值。这个整个标注出来的点(除了p1和p2外)呈现一个心形。所以只要为心形内部和外部染成不同的颜色即可(如下图中,p1染成红色,p2染成背景色)。

方法是用step方法,这里用smoothstep,使得边缘不那么硬, 然后结合lerp方法,如下:

 float a = atan2(p.y,p.x)/3.141593; 
 float r = length(p);

 float3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, a-r) ); // 当p1时,smoothstep返回1;p2时,smoothstep返回0;

OpenGL Shader实例分析(2)绘制心脏跳动效果

这样就可以画半个倒着的心:

OpenGL Shader实例分析(2)绘制心脏跳动效果

翻转xy轴,并取绝对值,

float a = atan2(p.x,p.y)/3.141593;
float r = length(p);
float h = abs(a);
float3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, h-r) );

得到:

OpenGL Shader实例分析(2)绘制心脏跳动效果

心太肥了,用下面的函数来调节心形:

OpenGL Shader实例分析(2)绘制心脏跳动效果,对应的曲线如下:

OpenGL Shader实例分析(2)绘制心脏跳动效果

这样就得到比较ok的心形了,如下:

OpenGL Shader实例分析(2)绘制心脏跳动效果

2. 心形跳动的算法

接下来,结合时间和函数来获取一个跳动的心脏:

OpenGL Shader实例分析(2)绘制心脏跳动效果

对应的图像:

OpenGL Shader实例分析(2)绘制心脏跳动效果

正真的效果函数,如下:

OpenGL Shader实例分析(2)绘制心脏跳动效果

OpenGL Shader实例分析(2)绘制心脏跳动效果

对应的代码为:

// animate
float tt = fmod(_Time.y, 1.5)/1.5; // 周期为1.5秒
float ss = pow(tt,.2) * 0.5 + 0.5;
ss -= ss*0.2*sin(tt*6.2831*3.0)*exp(-tt*4.0);
p *= float2(0.5, 1.5) + ss * float2(0.5, -0.5); // 不同的轴影响不同,使得心在跳动时,纵向变矮,横向变宽

3. 颜色(待续)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程笔记。


推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了多因子选股模型在实际中的构建步骤,包括风险源分析、因子筛选和体系构建,并进行了模拟实证回测。在风险源分析中,从宏观、行业、公司和特殊因素四个角度分析了影响资产价格的因素。具体包括宏观经济运行和宏经济政策对证券市场的影响,以及行业类型、行业生命周期和行业政策对股票价格的影响。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
author-avatar
ENE的蓝白胖次
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有