关于Godot,GLSL和WebGL,迷你游戏中使用的着色器

本文主要介绍GLSL着色器,以及如何在此迷你演示游戏中使用它们。



本文分为以下顺序:


  • 链接和简要说明。
  • 对游戏逻辑和Godot使用功能的非常简短的描述。
  • 关于使用的着色器。
  • 有关Godot及其功能的更多信息。
  • WebGL2有效
  • 多人游戏



1.链接和描述


您可以itch.io链接 下载Win / Linux版本


整个游戏的源代码可在githubgitlab找到


游戏玩法:


最少,这不是一个完整的游戏。 (游戏中没有声音)


游戏的目的是保持最大回合数。 当HP球数为零且游戏中没有机器人时,回合开始。


销毁人物时,会出现奖金, 每回合一次 ,以蓝色,红色/绿色,黄色表示射击动画的速度,损坏(仅在主球体中)和跳跃的高度。 机器人也会随机给予奖励。 玩家角色每回合恢复+ 1HP。




2.游戏的逻辑以及所使用的资源


使用的资源:


Blender仅用于减少模型上的多边形数量,并创建破碎的模型块。


使用了futari-addon模块。 (我会在下面写)


在游戏中,两个模型具有动画。
我在原始模型 Godot中所做的玩家角色动作
第二种模型是具有高质量动画的Sphere-bot


此处列出了所有使用过的现成的第三方对象模型


游戏逻辑和Godot功能:


游戏逻辑不是最佳方式,我将列出正常完成的要点。


3D场景仅使用一个视口,在几个视口(低分辨率)中,有用于处理多通道/反馈着色器的2D视口(也是低分辨率)的正交相机,下面将详细介绍。


所有纹理都有mipmap ,甚至可以在浏览器中使用。 还有其他图形设置(Esc-设置) 。 例如,您可以为游戏设置任何分辨率 ,最高为32x32像素,例如,我在设置中设置了320x240分辨率,在浏览器中运行游戏,然后打开了最大的抗锯齿MSAA功能


所有光源都是实时工作的,总共有16个。


地板和围栏是多次复制一个模型的最简单的粒子, 代码微不足道


我的着色器中的粒子旋转矩阵(几块地板)只是该公式的一小部分:


 mat4 rotationAxisAngle( vec3 v, float angle ) { float s = sin( angle ); float c = cos( angle ); float ic = 1.0 - c; return mat4( vx*vx*ic + c, vy*vx*ic - s*vz, vz*vx*ic + s*vy, 0.0, vx*vy*ic + s*vz, vy*vy*ic + c, vz*vy*ic - s*vx, 0.0, vx*vz*ic - s*vy, vy*vz*ic + s*vx, vz*vz*ic + c, 0.0, 0.0, 0.0, 0.0, 1.0 ); } 

例如, v=vec3(0.0,0.0,1.0)是沿z轴的旋转, angle=PI/2. 替换他们并获得所需的转弯。


可破坏块的动画被认为是实时物理引擎



Godot中的物理非常有限,即使有十二个活动对象,它也开始显着降低FPS ,因此禁用了被破坏的碎片之间的所有碰撞,并且设置了其他碰撞,设置了物理级别,同时破坏的数量也受到限制,并且同时具有最大数量的机器人(六)。


惯性物理原理以及玩家角色与动态物体的相互作用。 默认情况下,它在Godot中处于关闭状态,我编写了一个最小的交互文件中的代码:


bot_hit.gd _integrate_forces函数,所调用的只是对手机器人运动
player_l.gd首先, move_and_slide函数关闭无限惯性,而process_collision函数排斥对象。


游戏开始时的预加载(预加载)用于避免在对象首次出现时出现滞后,这很有帮助,但是当您打开“ 阴影” (和其他一些选项)时,滞后将再次出现在对象的首次出现时。 同样在浏览器中,由于使用着色器的浏览器的特殊性,所以这无济于事。


一个光源中的几个重复对象以及几个GIProbe,光源的形状和参数均旨在避免OpenGL的限制或Godot中的限制。




3.二手着色器


环境全景图:


该游戏使用静态全景,图片是从此着色器获取的 (c1 c2颜色,ldir位置)


 vec3 sky(vec3 d, vec3 c1, vec3 c2) { vec3 ldir = normalize(vec3(0.,0.,-1.)); vec3 col = mix(c1*100., c2*100., min(abs(dy)*2. + .5, 1.)) / 255.*.5; col *= (1. + vec3(1., .7, .3) / sqrt(length(d - ldir))*2.); //sun return clamp(col,vec3(0.),vec3(1.)); } 

要获取全景图,请从第57行panorama_uv(fragCoord,ro,rd);删除注释panorama_uv(fragCoord,ro,rd); 并在第58行添加评论


过去的演示中的Godot的动态全景(YouTube和代码链接) 云的全景
在此演示中使用了昼夜循环与云层运动的全景图:



例如另一个白天/夜晚的全景图,在shadertoy上我没有在任何地方使用它


如果您需要将CubeMap转换为Godot环境的全景图 ,我做了一个简单的Web转换器


非常简单的着色器:


粒子着色器是否静态确定其动画位置 。 例如spawn.shader)



为了使物体 (不仅是球) 周围发光 ,这是gglow.shader的一行 (可以根据需要更改数字)


 float intensity = pow(0.122 + max(dot(NORMAL, normalize(VIEW)),0.), 010.85); 


以3D格式显示文本数字 ,正如我在Godot中所了解的那样,这是没有办法的(不创建其他FBO(视口)),因此简单的着色器可以从纹理中打印数字(以便进行mipmapping ), 着色器代码


用户界面元素:


在着色器上使UI面板的自定义形式最容易实现,也许这根本不对此处显示正确的方法作为示例 (在UI部分)。
在此游戏中, 最简单的动画是菜单的背景, 指示器是HP 。 在上方的白天/夜晚全景视频的链接中,该操作也完成了,侧面有条纹,着色器上有所有动画。


关于futari-addon模块:


对于视频中的 2D粒子,它的工作原理几乎与此着色器相同(请参见1:41)。


在开始时,一次在视频上构建所有多边形的2D-SDF贴图,然后将生成的纹理简单地发送到粒子,粒子本身在当前位置构建法线并更改运动。


futari-addon的功能几乎相同,只是传输3D球体和平面的坐标,而不是2D纹理贴图,它们是在粒子着色器中根据条件进行处理的,因此您可以自由更改其位置和其他参数。


另外,还有风(在我的2D示例中,添加风非常简单,因为另一个纹理的速度带有+-值,并且粒子只是将此贴图的速度值添加到其位置中)。


futari-addon模块非常好 ,使用它而不是创建自己的粒子系统。


屏蔽效果:


使用转换反馈缓冲区将影响球体的坐标和播放器的位置以及消光的粒子传输到该粒子。 en_m.shader文件中的着色器代码



机器人盾牌:



着色器作为三维噪声遮挡物。基本上, 这里flow函数都可以使着色器正常工作
背景由gl_FrontFacing确定, gl_FrontFacing涂成越来越深而不是蓝色。
对打卡的响应-只需简单地发送电击事件计时器。





着色器读取其最后一帧,或“反馈/多遍”着色器:


几乎所有效果都是使用此逻辑产生的。
游戏中的着色器之一
作为源,我设置了一个正交相机 ,可以在短距离内拍摄特定组中的对象(而不处理整个场景)


冰场效应:


着色器如上所示,在项目文件中是ice_feedback.shader ,以及用于平面的片段着色器,该着色器使用简单的深度循环创建地板深度的错觉:


 while(current_depth < depth){ ofs -= delta; depth = textureLod(texture_depth, ofs,0.0).r; current_depth += layer_depth; } 


粒子场效应:


着色器相同 ,根据着色器中帧缓冲区颜色的亮度,粒子的y坐标(高度),颜色也根据颜色亮度( 我没有单独保存粒子着色器,它在项目中的对象 floor/visible_/floor3/grass/grass )。



动态标志动画:


Godot拥有用于动画化布料的SoftBody,但是它是CPU,所以我没有使用过。 我使用了到原始代码的现成代码链接 。 该标志从侧面的三个球上推下,角色的头部是第四个球。
如上例所示, 通道着色器的逻辑只有三个轴,即着色器(1) flag.shader多遍代码,绘制该标志的着色器仅显示纹理并更改平面(2) flag.shader的几何形状。



数字外观:


形状没有UV,因此cchess.shader中的所有代码都没有三边 纹理贴图,用于纹理映射和三角顶点



击打盒 (红色框)的动画会损坏玩家的角色,并从该帧中留下痕迹(颗粒很明显):



它仅使用已经指定的着色器gglow.shader
PS 在一个着色器中制作了相同的动画链接到shadertoy


对于粒子,仅使用两个纹理,即圆形和正方形。




4.关于Godot及其功能


Godot非常好且简单(不适用于初学者)。 我真的很喜欢Godot的功能。


有很多错误,Godot文档不完整,有时会由于错误而引起误导,并且没有指出关键点(对我而言并不明显),以便了解必须多次重读哪个Godot源代码(代码不大且编写得很好)。
这只是我的印象,可能是错误的,我不想误导任何人。


我强调,即使是Godot中非常重要的错误,也可以通过GDScript以最少的努力在Godot本身中加以解决。 无疑是一大优势


我还注意到,Godot 绝不受外部因素的特殊性的保护 ,例如浏览器中的WASM,ANGLE限制,浏览器本身的强大限制,当然还有视频卡驱动程序中的数十个错误,所有这些都必须手动绕过。


时滞 -管理存在大问题, 戈多方面是100%,我没有解决。 (在FPS着色器的编译过程中控制楔块和滞后(例如,在浏览器中),还有与Godot中3D渲染功能有关的其他滞后,我绕开了其中的一些,但它们仍然存在/可能存在。




5. WebGL2的工作原理 仅Linux


如果您使用的是Windows,请不要从链接中启动游戏。 链接到WebGL2 / WASM版本。


信息更新 :WebGL版本是在Windows10(仅在Firefox中,在关闭了ANGLE的情况下)在功能强大的PC(i9 / 16gb ram / 8gb视频)上启动的,尽管地板无法再渲染(由于某种原因),并且Firefox正在泄漏内存(> 16GB) )在五分钟之内...最好不要自担风险,只能冒险


仅适用于Chrome 76+和Firefox (Linux)。


已发送有关Windows的错误报告(链接) ,如果这是浏览器错误,则Google在2个月后做出反应。 但这显然是ANGLE中的错误,几乎可以肯定不会解决。
错误报告已关闭,并且也不会编辑ANGLE。 因此,在Windows上,浏览器将无法运行。


在此项目的过程中,修复了Chrome中的一个错误,这是因为该转换反馈和我以前没有用过的上一个演示(上有昼/夜全景图的视频)开始工作了。




6.多人游戏


添加了多人游戏,仅用于测试目的(以及Godot中的示例多人游戏)。 github和itch上主要版本旁边的源代码和二进制版本(开头的链接)。



随着Godot 3.2的发布,我还将为测试添加WebRTC。

Source: https://habr.com/ru/post/zh-CN467779/


All Articles