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

相关文章

Kotlin Compose Button 实现长按监听并实现动画效果(完整代码)

《KotlinComposeButton实现长按监听并实现动画效果(完整代码)》想要实现长按按钮开始录音,松开发送的功能,因此为了实现这些功能就需要自己写一个Button来解决问题,下面小编给大... 目录Button 实现原理1. Surface 的作用(关键)2. InteractionSource3.

使用WPF实现窗口抖动动画效果

《使用WPF实现窗口抖动动画效果》在用户界面设计中,适当的动画反馈可以提升用户体验,尤其是在错误提示、操作失败等场景下,窗口抖动作为一种常见且直观的视觉反馈方式,常用于提醒用户注意当前状态,本文将详细... 目录前言实现思路概述核心代码实现1、 获取目标窗口2、初始化基础位置值3、创建抖动动画4、动画完成后

uniapp小程序中实现无缝衔接滚动效果代码示例

《uniapp小程序中实现无缝衔接滚动效果代码示例》:本文主要介绍uniapp小程序中实现无缝衔接滚动效果的相关资料,该方法可以实现滚动内容中字的不同的颜色更改,并且可以根据需要进行艺术化更改和自... 组件滚动通知只能实现简单的滚动效果,不能实现滚动内容中的字进行不同颜色的更改,下面实现一个无缝衔接的滚动

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

Flutter实现文字镂空效果的详细步骤

《Flutter实现文字镂空效果的详细步骤》:本文主要介绍如何使用Flutter实现文字镂空效果,包括创建基础应用结构、实现自定义绘制器、构建UI界面以及实现颜色选择按钮等步骤,并详细解析了混合模... 目录引言实现原理开始实现步骤1:创建基础应用结构步骤2:创建主屏幕步骤3:实现自定义绘制器步骤4:构建U

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用