Vulkan_顶点着色器特效4(风吹树木等植被效果)

2023-11-02 21:50

本文主要是介绍Vulkan_顶点着色器特效4(风吹树木等植被效果),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本案例实现在风力作用下树木植被的弯曲旋转等效果。
在这里插入图片描述

一、基本原理

本案例中在上一小节间接绘制的场景基础上实现植被树干会随着风力的大小、方向产生对应的弯曲,下图给出了如何计算某一帧中树干上指定顶点弯曲后位置的策略。
在这里插入图片描述

从图中可以看出,为了简化计算,本案例中采用的风向是与 XOZ 平面平行的。设当前风向与 z 轴正方向的夹角为 α,树干原始状态下与 y 轴重合。点 A 为树干模型中的任一顶点,在风的吹动下偏转到 A’点。

顶点着色器需要计算的问题为:已知 A 点坐标(X0,Y0,Z0)、当前风向与 z 轴正方向的夹角 α以及弧 OA’所在圆的半径 OO’,求 A 点偏转到 A’点后的坐标。

  • 本案例采用的计算模型中,半径 OO’的大小与风力的大小成反比,风力越大,半径 OO’越小。这样就非常容易地实现了风越大,树干弯曲得越厉害。

下面给出具体的计算步骤。

1)由于 OA’为半径为 OO’的一段圆弧,那么可以得出 OA’=OA,且 O’O=O’A’。

2)根据弧长公式,可得出树干弯曲后的弧对应的圆心角θ 的弧度计算公式如下。
θ= OA’/ OO’= OA/ OO’

3)从图 2-9 以及根据三角函数的知识可以得出如下结论。
A’D= O’A’×sin(θ)= O’O’×sin(OA/ OO’)
OD=OO’- O’A’×cos(θ)= OO’- O’O’×cos(OA/ OO’)

4)接着可以得出如下结论。
OX’=OD×sin(α)=( OO’- O’O’×cos(OA/ OO’))×sin(α)
OZ’= OD×cos(α)= (OO’- O’O’×cos(OA/ OO’))×cos(α)

5)设顶点 A 的坐标为(X0,Y0,Z0),偏移 后 A’的坐标为(X1,Y1,Z1)。则可以用 Y0 替换上
面的 OA,那么有如下结论。
OX’=(OO’- OO’×cos(Y0/ OO’))×sin(α)
OZ’= (OO’- OO’×cos(Y0/ OO’))×cos(α)

6)最后可以得到 A’点的坐标。
X1= X0+ OX’= X0+(OO’- OO’×cos(Y0/ OO’))×sin(α)
Y1= A’D= OO’×sin(Y0/ OO’)
Z1= Z0+ OZ’= Z0+(OO’- OO’×cos(Y0/ OO’))×cos(α)

从上述得出的顶点位置变换公式中可以看出,只需要改变风向角度α ,就可以使椰子树向不同的方向摆动。同时,只需要根据风力大小改变弯曲半径 OO’的大小,就可以改变椰子树树干的弯曲程度。

二、开发步骤

我们首先新定义一个uniform数据用来在顶点着色器中控制风力及风向。

	struct {float bend_R=4;//风力(弯曲半径)float direction_degree=10;//风向(沿Z轴正方向逆时针旋转)} conVS;

具体的创建uniform缓冲区及绑定等不再赘述,我们可以通过设置不同数值来实现风力及风向。
接下来我们主要来看一下顶点着色器(基于上一文章的间接绘制):
顶点着色器:

#version 450// mesh数据
layout (location = 0) in vec4 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inUV;
layout (location = 3) in vec3 inColor;// 实例位置大小数据
layout (location = 4) in vec3 instancePos;
layout (location = 5) in vec3 instanceRot;
layout (location = 6) in float instanceScale;
layout (location = 7) in int instanceTexIndex;layout (binding = 0) uniform UBO 
{mat4 projection;mat4 modelview;
} ubo;layout (binding = 3) uniform CON
{float bend_R;//风力(弯曲半径)float direction_degree;//风向(沿Z轴正方向逆时针旋转)
} conVS;layout (location = 0) out vec3 outNormal;
layout (location = 1) out vec3 outColor;
layout (location = 2) out vec3 outUV;
layout (location = 3) out vec3 outViewVec;
layout (location = 4) out vec3 outLightVec;out gl_PerVertex
{vec4 gl_Position;
};void main() 
{outColor = inColor;outUV = vec3(inUV, instanceTexIndex);outUV.t = 1.0 - outUV.t;//角度变换矩阵mat4 mx, my, mz;// 围绕x轴旋转float s = sin(instanceRot.x);float c = cos(instanceRot.x);mx[0] = vec4(c, s, 0.0, 0.0);mx[1] = vec4(-s, c, 0.0, 0.0);mx[2] = vec4(0.0, 0.0, 1.0, 0.0);mx[3] = vec4(0.0, 0.0, 0.0, 1.0);	// 围绕y轴旋转s = sin(instanceRot.y);c = cos(instanceRot.y);my[0] = vec4(c, 0.0, s, 0.0);my[1] = vec4(0.0, 1.0, 0.0, 0.0);my[2] = vec4(-s, 0.0, c, 0.0);my[3] = vec4(0.0, 0.0, 0.0, 1.0);	// 围绕z轴旋转s = sin(instanceRot.z);c = cos(instanceRot.z);	mz[0] = vec4(1.0, 0.0, 0.0, 0.0);mz[1] = vec4(0.0, c, s, 0.0);mz[2] = vec4(0.0, -s, c, 0.0);mz[3] = vec4(0.0, 0.0, 0.0, 1.0);	mat4 rotMat = mz * my * mx;outNormal = inNormal * mat3(rotMat);vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0) * rotMat;float bend_R = conVS.bend_R+sin(gl_DrawIDARB*10);//这里指的是树的弯曲半径  sin(gl_DrawIDARB*10)差异作用float direction_degree=conVS.direction_degree;//用角度表示的风向,沿Z轴正方向逆时针旋转//计算当前的弧度float curr_radian=pos.y/bend_R;//计算当前点变换后的Y坐标float result_height=bend_R*sin(curr_radian);//计算当前点的增加的长度float increase=bend_R-bend_R*cos(curr_radian);//计算当前点最后的x坐标float result_X=pos.x+increase*sin(radians(direction_degree));//计算当前点最后的z坐标float result_Z=pos.z+increase*cos(radians(direction_degree));//最后结果顶点的坐标vec4 result_point=vec4(result_X,result_height,result_Z,1.0);gl_Position = ubo.projection * ubo.modelview * result_point;vec4 wPos = ubo.modelview * vec4(pos.xyz, 1.0); vec4 lPos = vec4(0.0, -5.0, 0.0, 1.0);outLightVec = lPos.xyz - pos.xyz;outViewVec = -pos.xyz;	
}

三、渲染效果

3.1 风向改变

我们可以通过控制conVS.direction_degree从0到360来实现风向不同变动,效果如下:
在这里插入图片描述

3.2 风力改变

我们可以通过控制conVS.bend_R来实现风力不同变动,效果如下:
在这里插入图片描述

3.3 风力+风向

我们最终可以通过控制conVS.bend_R和conVS.direction_degree来实现不同风向和风力来完成想要的效果,效果文章开头所展示。

这篇关于Vulkan_顶点着色器特效4(风吹树木等植被效果)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/333539

相关文章

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的

POJ3041 最小顶点覆盖

N*N的矩阵,有些格子有物体,每次消除一行或一列,最少要几次消灭完。 行i - >列j 连边,表示(i,j)处有物体,即 边表示 物体。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;impo

『功能项目』战士的平A特效【35】

我们打开上一篇34武器的切换实例的项目, 本章要做的事情是在战士的每次按A键时在指定位置生成一个平A特效 首先将之前下载的技能拖拽至场景中 完全解压缩后重命名为AEffect 拖拽至预制体文件夹 进入主角动画的战士动画层级 双击第一次攻击 选择Animation 创建事件 创建的动画事件帧放在攻击动画挥剑指定处 命名为PerpetualAtt

第49课 Scratch入门篇:骇客任务背景特效

骇客任务背景特效 故事背景:   骇客帝国特色背景在黑色中慢慢滚动着! 程序原理:  1 、 角色的设计技巧  2 、克隆体的应用及特效的使用 开始编程   1、使用 黑色的背景: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d74c872f06b4d9fbc88aecee634b074.png#pic_center)   2

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

【Godot4.3】多边形的斜线填充效果基础实现

概述 图案(Pattern)填充是一个非常常见的效果。其中又以斜线填充最为简单。本篇就探讨在Godot4.3中如何使用Geometry2D和CanvasItem的绘图函数实现斜线填充效果。 基础思路 Geometry2D类提供了多边形和多边形以及多边形与折线的布尔运算。按照自然的思路,多边形的斜线填充应该属于“多边形与折线的布尔运算”范畴。 第一个问题是如何获得斜线,这条斜线应该满足什么样

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。 <template><view class="audio-co

Nuxt3入门:过渡效果(第5节)

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果,以便对所有页面应用自动过渡效果。 nuxt.config.js export default defineNuxtConfig({app: {pageTransition: {name: 'fade',mode

【生日视频制作】酒吧一群美女车展模特大屏幕视频改字AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程酒吧一群美女车展模特大屏幕视频改字AE模板修改文字特效广软件告生成神器素材祝福玩法AE模板工程 怎么如何做的【生日视频制作】酒吧一群美女车展模特大屏幕视频改字AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤: 安装AE软件 下载AE模板 把AE模板导入AE软件 修改图片或文字 渲染出视频