在我学习入门精要的时候,经常遇到不解释api,甚至是关键代码的实现原理。

11.3.1流动的河流中的offset.x的sin函数查了一下好像大家也都是书上原话直接复制,现在好不容易想明白了希望能帮到和我一样一脸懵逼的人。

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 11/Water" {
Properties {
_MainTex ("Main Tex", 2D) = "white" {}
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_Magnitude ("Distortion Magnitude", Float) = 1
_Frequency ("Distortion Frequency", Float) = 1
_InvWaveLength ("Distortion Inverse Wave Length", Float) = 10
_Speed ("Speed", Float) = 0.5
}
SubShader {
// Need to disable batching because of the vertex animation
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"} Pass {
Tags { "LightMode"="ForwardBase" } ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
float _Magnitude;
float _Frequency;
float _InvWaveLength;
float _Speed; struct a2v {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
}; struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
}; v2f vert(a2v v) {
v2f o; float4 offset;
offset.yzw = float3(0.0, 0.0, 0.0);
//最重要却没讲清楚的一句
offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
o.pos = UnityObjectToClipPos(v.vertex + offset);
//这里只对uv偏移,对模型顶点没有影响
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv += float2(0.0, _Time.y * _Speed); return o;
} fixed4 frag(v2f i) : SV_Target {
fixed4 c = tex2D(_MainTex, i.uv);
c.rgb *= _Color.rgb; return c;
} ENDCG
}
}
FallBack "Transparent/VertexLit"
}

这个offset.x是个啥?而且其中的v.vertex的xyz分量都乘了波长更让人摸不着头脑,我们先看一个标准版本。

下面这个版本能够实现一个标准的行波河流

offset.x = _Magnitude * sin(_Frequency * _Time.y + v.vertex.z * _InvWaveLength);

效果(上下边缘对称)

然后逐一解释

这个首先是坐标,我们需要知道模型空间下左右(横轴)是z,而上下是x。

然后再用行波的表达式

y = Asin(kx - ωt + φ)+ b

可以知道x对应v.vertex.z;_Time.y对应t

并且周期是2π/ω,波长是2π/k。

那么我们就能知道书上原话“利用_Frequency属性和内置的_Time变量来控制正弦函数的频率,....乘以_InvWaveLength来控制波长”是啥意思了

_Magnitude 控制波动幅度大家学过三角函数肯定都知道。

然后再来看书上为什么是

offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;

这里多出来的是

v.vertex.y * _InvWaveLength + v.vertex.x * _InvWaveLengt

实际上y没有意义----因为我们这个河流的顶点的y在模型空间上都是0

所以考虑x就是在纵方向上形成偏移,竖直方向来看,同一z轴的x往下不断变化,也就是同一z上的不同x的初项不同,从上往下的波初项不同,形成偏移

放在图片上面就是上下边缘的波形相同,但是时刻不同。

这里可能有人想的比较复杂,觉得顶点坐标已经偏移了之后计算会变化,但其实v.vertex一直都是原本的顶点坐标,只是pos来负责计算之后输出到SV_POSITION之中。



希望能帮到大家

《Shader入门精要》第11章-11.3.1流动的河流中的offset.x的解释的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第11章 让画面动起来

    转自 冯乐乐的 <Unity Shader入门精要> Unity Shader 中的内置变量 动画效果往往都是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化.Unity ...

  2. Unity Shader入门精要读书笔记(一)序章

    本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数 ...

  3. Unity Shader入门精要学习笔记 - 第4章 学习 Shader 所需的数学基础

    摘录自 冯乐乐的<Unity Shader入门精要> 笛卡尔坐标系 1)二维笛卡尔坐标系 在游戏制作中,我们使用的数学绝大部分都是计算位置.距离.角度等变量.而这些计算大部分都是在笛卡尔坐 ...

  4. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

  5. Unity Shader入门精要学习笔记 - 第17章 Unity的表面着色器探秘

    转自 冯乐乐的<Unity Shader 入门精要> 2010年的Unity 3 中,Surface Shader 出现了. 表面着色器的一个例子. 我们先做如下准备工作. 1)新建一个场 ...

  6. Unity Shader入门精要学习笔记 - 第16章 Unity中的渲染优化技术

    转自冯乐乐的 <Unity Shader 入门精要> 移动平台的特点 为了尽可能一处那些隐藏的表面,减少overdraw(即一个像素被绘制多次),PowerVR芯片(通常用于ios设备和某 ...

  7. Unity Shader入门精要学习笔记 - 第15章 使用噪声

    转载自 冯乐乐的 <Unity Shader 入门精要> 消融效果 消融效果常见于游戏中的角色死亡.地图烧毁等效果.这这些效果中,消融往往从不同的区域开始,并向看似随机的方向扩张,最后整个 ...

  8. Unity Shader入门精要学习笔记 - 第14章非真实感渲染

    转载自 冯乐乐的 <Unity Shader 入门精要> 尽管游戏渲染一般都是以照相写实主义作为主要目标,但也有许多游戏使用了非真实感渲染(NPR)的方法来渲染游戏画面.非真实感渲染的一个 ...

  9. Unity Shader入门精要学习笔记 - 第10章 高级纹理

    转载自 冯乐乐的 <Unity Shader入门精要> 立方体纹理 在图形学中,立方体纹理是环境映射的一种实现方法.环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层 ...

随机推荐

  1. uniapp 小程序全屏的实现

    通过设置navigationStyle, 即自定义导航实现背景全屏 参考文章:  微信小程序 自定义头部导航栏 navigationStyle 代码部分 在page.json中, 加入 "n ...

  2. 连接docker里面的mysql失败解决

    场景:在虚拟机的docker容器中安装latest版本的mysql之后,在宿主机中使用navicat连接虚拟机中的mysql出现下图报错: 解决方法: 1.首先docker ps命令查看正在运行的容器 ...

  3. mysql入门基础增删查改

    数据查询语法(DQL) DQL就是数据查询语言,数据库执行DQL语句不会对数据进行改变,而是让数据库发送结果集给客户端. 语法: SELECT selection_list /*要查询的列名称*/ F ...

  4. Docker consul的容器服务更新与发现

    Docker consul的容器服务更新与发现 目录 Docker consul的容器服务更新与发现 一.Consul简介 1. 服务注册与发现 2. consul概述 3. consul的两种模式 ...

  5. 洛谷P1563 [NOIP2016 提高组] 玩具谜题

    题目链接:https://www.luogu.com.cn/problem/P1563 哈哈哈,这个题拿来一读是不是很吃惊hahaha,我刚开始读的时候吓了我一跳,这么长的题干,这么绕的题意,还有下面 ...

  6. java 监听redis事件

    第一步:利用RDM等redis连接工具查看相应事件,然后去网上搜索 一下,会有redis各种事件的说明,选择契合业务的事件: 第二步:创建监听处理类: 1 package com.lechuang.a ...

  7. Nodejs允许跨域访问

    状况:本地的前端项目(uni-app)以及后台管理(vue-mongo-node)和本地mongo数据库 前台项目端口是8082,后台数据接口是8081. 跨域解决,直接上代码: uni-app的ma ...

  8. 有手就行7——*项目构建细节2-钩子(webhook) 配置

    有手就行7--*项目构建细节2-钩子(webhook) 配置 钩子服务  1)开启webhook功能 使用root账户登录到后台,点击Admin Area -> Settings -> N ...

  9. 初见Redis

    Redis是什么,有什么特点和优势 Redis是一个开源用C语言编写的,基于内存,可以持久化,高性能的key-value数据库,并提供多种语言的API. 它也被称为数据结构服务器,因为值(value) ...

  10. ESXI系统从0搭建流程

    ESXI系统从0搭建流程 简单介绍 简单介绍:项目中使用到了这个系统,我自己不会搭建,但是请教别人之后自己成功搭建出来了此系统.所以在此记录一下搭建流程,希望能够帮助"零"小白. ...