Cg Programming/Unity/Nonlinear Deformations非线性变形

2024-03-11 09:08

本文主要是介绍Cg Programming/Unity/Nonlinear Deformations非线性变形,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本教程介绍顶点混合作为非线性变形的一个例子。主要的应用实际就是蒙皮网格的绘制。

虽然本教程不是基于其它任何指定的教程上的,对章节“顶点变换”的理解还是非常有用的。

在两个模型变换之间混合

这里写图片描述

大多数网格的变形不能用章节“顶点变换”中讨论的4×4矩阵的仿射变换来建模。虚构的变形场对空间的变形只是其中的一个例子。计算机图形中最重要的例子就是当连接点弯曲时网格的变形,比如肘或膝盖。

本教程介绍了实现其中一些变形的顶点混合。基本的想法是在顶点着色器中应用多重模型变换(在本教程中我们只使用两个模型变换)以及混合这些变换过的顶点,即用必须为每个顶点指定的权重计算它们的加权平均值。举例来说,在骨骼连接点附近处皮肤的变形主要是受两根骨骼交接处的位置和方向的影响。于是,这两根骨骼的位置和方向定义了两个仿射变换。皮肤上不同的点会受到这两根骨骼不同的影响:连接点处的点可能受到两根骨骼同样的影响,而在一根骨骼周围远离连接处的点会更多地受到这根骨骼的影响。通过使用这两个变换的加权平均值中的不同权重可以实现两根骨骼影响的不同强度。

为了本教程的目的,我们使用两个uniform变换float4x4 _Trafo0float4x4 _Trafo1,它们由用户指定。最后一个小型Java脚本(它应该被挂载到应该被变形有网格上去,比如默认的球体)允许我们指定其它两个游戏对象并且把它们的模型变换复制到着色器的uniform中。

@script ExecuteInEditMode()public var bone0 : GameObject;
public var bone1 : GameObject;function Update () 
{if (null != bone0){GetComponent(Renderer).sharedMaterial.SetMatrix("_Trafo0", bone0.GetComponent(Renderer).localToWorldMatrix);}if (null != bone1){GetComponent(Renderer).sharedMaterial.SetMatrix("_Trafo1", bone1.GetComponent(Renderer).localToWorldMatrix);}if (null != bone0 && null != bone1){transform.position = 0.5 * (bone0.transform.position + bone1.transform.position);transform.rotation = bone0.transform.rotation;}
}

在C#中,脚本(名字为”MyClass”)看起来是这样的:

using UnityEngine;
using System.Collections;[ExecuteInEditMode]
public class MyClass : MonoBehaviour
{public GameObject bone0;public GameObject bone1;void Update () {if (null != bone0){GetComponent<Renderer>().sharedMaterial.SetMatrix("_Trafo0", bone0.GetComponent<Renderer>().localToWorldMatrix);}if (null != bone1){GetComponent<Renderer>().sharedMaterial.SetMatrix("_Trafo1", bone1.GetComponent<Renderer>().localToWorldMatrix);} if (null != bone0 && null != bone1){transform.position = 0.5f * (bone0.transform.position + bone1.transform.position);transform.rotation = bone0.transform.rotation;}}
}

其它两个游戏对象可以是任何对象–我喜欢有一个内置半透明着色器的立方体,这样它们的位置和方向就是可见的但它们不会遮挡变形的网格。

在本教程中,用变换_Trafo0混合的权重被设置为input.vertex.z + 0.5

float weight0 = input.vertex.z + 0.5;

另一个权重就是1.0 - weight0。于是,input.vertex.z坐标正向的部分被_Trafo0影响,以及其它的部分被_Trafo1影响。一般来说,权重是依赖于应用的并且用户应该允许为每个顶点指定权重。

这两个变换的应用程序以及加权平均值可以这样写:

float4 blendedVertex = weight0 * mul(_Trafo0, input.vertex) + (1.0 - weight0) * mul(_Trafo1, input.vertex);

然后这个混合顶点必须被乘以观察矩阵和投影矩阵。这两个矩阵的乘积可以用UNITY_MATRIX_VP来表示:

output.pos = mul(UNITY_MATRIX_VP, blendedVertex);

为了说明这些不同的权重,我们用红色分量把weight0可视化,用绿色分量把1.0 - weight0可视化(它在片元着色器中设置):

output.col = float4(weight0, 1.0 - weight0, 0.0, 1.0);

对于一个实际的应用,我们应该通过这两个对应的逆转置模型变换对法向量进行变换,并且在片元着色器中执行逐像素光照。

完整的着色器代码

Shader "Cg shader for vertex blending" {SubShader {Pass {   CGPROGRAM#pragma vertex vert  #pragma fragment frag #include "UnityCG.cginc"// Uniforms set by a scriptuniform float4x4 _Trafo0; // model transformation of bone0uniform float4x4 _Trafo1; // model transformation of bone1struct vertexInput {float4 vertex : POSITION;};struct vertexOutput {float4 pos : SV_POSITION;float4 col : COLOR;};vertexOutput vert(vertexInput input) {vertexOutput output;float weight0 = input.vertex.z + 0.5; // depends on the meshfloat4 blendedVertex = weight0 * mul(_Trafo0, input.vertex) + (1.0 - weight0) * mul(_Trafo1, input.vertex);output.pos = mul(UNITY_MATRIX_VP, blendedVertex);output.col = float4(weight0, 1.0 - weight0, 0.0, 1.0); // visualize weight0 as red and weight1 as greenreturn output;}float4 frag(vertexOutput input) : COLOR{return input.col;}ENDCG}}
}

当然,这个只是这个概念的一个说明,但是它已经可以被用在一些有趣的非线性变形中了,比如围绕着z轴的扭动。

对于骨骼动画中的蒙皮网格,更多的骨骼(即模型变换)是必须的,每个顶点必须指定哪一根骨骼(例如使用索引)对加权平均值的哪个权重有贡献。但是,Unity会在软件中计算顶点的混合;这样,这个话题就跟Unity程序员无关了。

总结

恭喜,你又完成了一章的学习。我们看到了:

  • 如何混合被两个模型矩阵变换的顶点。
  • 该技术是如何被应用到非线性变换和蒙皮网格上的。

这篇关于Cg Programming/Unity/Nonlinear Deformations非线性变形的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

【Unity Shader】片段着色器(Fragment Shader)的概念及其使用方法

在Unity和图形编程中,片段着色器(Fragment Shader)是渲染管线中的一个阶段,负责计算屏幕上每个像素(片段)的颜色和特性。片段着色器通常在顶点着色器和任何几何处理之后运行,是决定最终像素颜色的关键步骤。 Fragment Shader的概念: 像素处理:片段着色器处理经过顶点着色器和几何着色器处理后,映射到屏幕空间的像素。颜色计算:它计算每个像素的颜色值,这可能包括纹理采样、光

【Unity Shader】Alpha Blend(Alpha混合)的概念及其使用示例

在Unity和图形编程中,Alpha Blend(也称为Alpha混合)是一种用于处理像素透明度的技术。它允许像素与背景像素融合,从而实现透明或半透明的效果。Alpha Blend在渲染具有透明度的物体(如窗户、玻璃、水、雾等)时非常重要。 Alpha Blend的概念: Alpha值:Alpha值是一个介于0(完全透明)和1(完全不透明)的数值,用于表示像素的透明度。混合模式:Alpha B

Apple - Media Playback Programming Guide

本文翻译整理自:Media Playback Programming Guide(Updated: 2018-01-16 https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/Introduction

Unity Meta Quest 开发:关闭 MR 应用的安全边界

社区链接: SpatialXR社区:完整课程、项目下载、项目孵化宣发、答疑、投融资、专属圈子 📕教程说明 这期教程我将介绍如何在应用中关闭 Quest 系统的安全边界。 视频讲解: https://www.bilibili.com/video/BV1Gm42157Zi 在 Unity 中导入 Meta XR SDK,进行环境配置后,打开 Assets > Plugins > An

机器学习算法(二):1 逻辑回归的从零实现(普通实现+多项式特征实现非线性分类+正则化实现三个版本)

文章目录 前言一、普通实现1 数据集准备2 逻辑回归模型3 损失函数4 计算损失函数的梯度5 梯度下降算法6 训练模型 二、多项式特征实现非线性分类1 数据准备与多项式特征构造2 逻辑回归模型 三、逻辑回归 --- 正则化实现1 数据准备2 逻辑回归模型3 正则化损失函数4 计算损失函数的梯度5 梯度下降6 训练模型 总结 前言 今天我们开始介绍逻辑回归的从零开始实现代码了,

Unity 字体创建时候容易导致字体文件不正确的一种情况

上面得到了两种字体格式,一种是TextMeshPro的,另一种是Unity UI系统中默认使用的字体资源。其原因是创建的位置不同导致的。 1.下面是TextMeshPro字体创建的位置 2:下面是Unity UI系统中默认使用的字体资源

摄像头画面显示于unity场景

🐾 个人主页 🐾 🪧阿松爱睡觉,横竖醒不来 🏅你可以不屠龙,但不能不磨剑🗡 目录 一、前言二、UI画面三、显示于场景四、结语 一、前言 由于标题限制,这篇文章主要是讲在unity中调用摄像头,然后将摄像头捕捉到的画面显示到场景中,无论是UI画面还是场景中的某个物体上;至于应用的场景可以用于AR增强现实。 那么话不多说,直接开始今

unity开发 --------- NGUI (UITable)

unity开发 --------- NGUI UITable与UIGrid相似,都是实现自动排序的。但UIGrid的元素大小是由我们来指定的,而Table中的元素的大小是根据元素本身计算出来的。 UITable还保存了元素的顺序List<Transform>。每次重排序,都会更新此List。除了要计算元素的Bound和保存List外,其他基本与UIGrid一致。 unity开发 ---

unity开发 --------- NGUI (UIGrid)

unity开发 --------- NGUI  UIGrid可以实现多个gameobject自动排序。可以设定其排序方向、每个元素的宽度,高度等。 public Arrangement arrangement = Arrangement.Horizontal;public int maxPerLine = 0;public float cellWi

unity开发 --------- NGUI(Localization、UILocalize)

unity开发 --------- NGUI NGUI支持动态加载资源功能。比如语言选择:假如当前语言为中文,当将语言更改为英文时,所有UI上的文字也立即变成了英文。此功能是用Localization和UILocalize两个脚本配合完成的。 Localization中记录多种配置方案,当更改配置方案时,由Localization发送通知,通知各UILocalize更新。 NGU