xiaozongpeng 发表于 2022-11-6 15:10

风格化草地顶点动画与blender脚本初体验

参考:
草地的顶点动画实现风吹草动
风格化草地制作过程
【Blender观察】脚本学习笔记
建模与贴图

在blender中建立草模型

设置uv

其中草原点在底部顶点,uv最高达1

在ps中进行贴图绘制

其实进了ps,不带uv,也不知道该咋办就截图放下面图层当参考

blender中效果

有点丑……
bpy初体验

随机成一块草地,来下面研究blender中的python
在控制台输入
bpy.app.debug_wm = True
观察info面板,得到移动,缩放,复制的api
搜索官方api网站得到




python中这样的参数叫默认参数(学了个寂寞全还回去了),就是不一定要写,可以用等于的方式赋值。
布兰德里的bpy,很迷。
bpy.ops只能对当前激活(active)物体进行操作,以我一晚的研究来看没有办法对物体列表循环操作。
复制之后会激活新复制出来的物体,致使原来的for循环依据当前激活项复制,物体越跑越远。
使用info里view3d.select(deselect_all)的时候报错,poll() failed, context is incorrect,然后gotcha告诉我要根据上下文填参数,还是不行就去看c源码还有可能你是第一个尝试在脚本里用这个操作的人可能是个bug~

真的会谢……
研究了早上四节课,发现

这个参数里可以选择全不选,算是成功了,就是需要手动为五个颜色的叶片生成一下


ui界面的话,找不到如何在draw里,UI里调用函数和传入值。

脚本注释多行_【Blender】【0_基础篇】如何用Python脚本编写自己的插件

继承自bpy.types.panel的子类必须注册(registered)后使用。
UILayout

更新
运行一次后发现集合呈现这样的状态

选择了目标平面003但物体属性是激活状态的平面006,在残留的物体状态上直接运行就会出错。
解决不了,手动点一下吧。实在不理解这逻辑。。全取消选择后还残留着上次激活的物体属性,select_set起了作用又没完全起,选中了物体但不更新它的物体属性面板,还是没找到激活的api。凑合着用。

增加亿点细节后的叶片洗净备用

调参调到天荒地老

修改草的法线使其阴影平滑alt l

进入unity


关闭阴影投射

在rider创建urp shader模板(纯个人纪录)

定义属性

Properties { _shaderEnum("ColorType", int) = 1   _DiffTex("Diffuse Texture", 2D) = "white"{}    _DiffColor("Diffuse Color", Color) = (1, 1, 1, 1)    _TopColor("top Color", Color) = (1, 1, 1, 1) _BottomColor("Bottom Color", Color) = (1, 1, 1, 1)_ColorThresholed("Color Thresholed", range(0, 1.0)) = 0.5    _NoiseTex("Noise Tex", 2D) = "white"{}   _WindControl("WindControl",vector) = (1,0,1,0.5)      //前面几个分量表示在各个轴向上自身摆动的速度, w表示摆动的强度      _WaveControl("WaveControl",vector) = (1,0,1,1)      //前面几个分量表示在各个轴向上风浪的速度, w用来模拟地图的大小,值越小草摆动的越凌乱,越大摆动的越整体 }
此处使用两种着色方式,贴图与渐变色,定义两个关键字。
顶点着色器

v2f vert(a2v a)         {                v2f v = (v2f)0;                ZERO_INITIALIZE(v2f, v);                v.posWS = TransformObjectToWorld(a.vertex);       `      //顶点世界位置的xz加上随时间移动量作为噪声图uv                float2 sampleUV = v.posWS.xz /_WaveControl.w + _Time.x * _WaveControl.xz;                //顶点着色器不能使用标准的采样方法,需要使用SAMPLE_TEXTURE2D_LOD函数(URP下)。                //因为采样需要LOD,而顶点着色器中没有LOD信息,我们需要手动输入。       `      float waveSample = SAMPLE_TEXTURE2D_LOD(_NoiseTex, sampler_NoiseTex,sampleUV, 0).x;//让噪声纹理随时间移动                v.posWS.x += sin(waveSample * _WindControl.x) * _WaveControl.x * a.texcoord.y * _WindControl.w;v.posWS.z += sin(waveSample * _WindControl.z) * _WaveControl.z * a.texcoord.y * _WindControl.w;。                v.posCS = TransformWorldToHClip(v.posWS);                v.uv.xy = TRANSFORM_TEX(a.texcoord, _DiffTex).xy;                v.normWS = TransformObjectToWorldNormal(a.normalOS);//世界 法线                return v;         }
按照参考教程这么写,但效果完全不对,变成了一坨坨海草。群里大佬说是噪声图尺寸问题,我试了一张1024,两张512的与一张128的,都是这样。

经历一个月的摆烂与四小时的研究,关键在这里.


去除了无关紧要的control控制系数后,这个_WaveControl.w极其重要.别的文章里什么世界尺寸,愣是没看懂,调来调去都是海草.与噪声图当然也有关系.

首先与顶点的世界坐标的x,z有关,如果这片草的x在1000-1050,那么采到的无限repeat的噪声图在u方向有五十张,两点间采样出的值的差距特别大,会造成明明在差不多位置的顶点距离很远(变形得不像草了),若除以100,x在10-10.5间,采样到的噪声图在u方向只有半张,变化就会非常平缓.

改变噪声图尺寸当然也可以,但不是2倍3倍,可能是几百倍.得不偿失.

非常的水墨
Shader "Custom/GrassShader" { Properties { _shaderEnum("ColorType", int) = 1       _DiffTex("Diffuse Texture", 2D) = "white"{}    _DiffColor("Diffuse Color", Color) = (1, 1, 1, 1)    _TopColor("top Color", Color) = (1, 1, 1, 1) _BottomColor("Bottom Color", Color) = (1, 1, 1, 1)_ColorThresholed("Color Thresholed", range(0, 1.0)) = 0.5    _NoiseTex("Noise Tex", 2D) = "white"{}   _SampleSize("Sample Size", range(1, 100)) = 40_TimeControl("Time Control", range(1, 100)) = 15_WindIntensity("Wind Intensity", range(0, 10)) = 1 } SubShader    {      Tags {"RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}                HLSLINCLUDE      #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"#pragma shader_feature_local _SHADERENUM_USETEX#pragma shader_feature_local _SHADERENUM_USECOLOR                TEXTURE2D(_DiffTex);      SAMPLER(sampler_DiffTex);      TEXTURE2D(_NoiseTex);      SAMPLER(sampler_NoiseTex);      CBUFFER_START(UnityPerMaterial)                float4 _DiffTex_ST;      float4 _DiffColor;      float4 _TopColor;      float4 _BottomColor;                float _SampleSize;float _TimeControl;float _WindIntensity;      float _ColorThresholed;                CBUFFER_END                struct a2v      {            float4 vertex : POSITION;            float3 normalOS : NORMAL;            float2 texcoord : TEXCOORD;      };                   struct v2f      {            float4 posCS : SV_POSITION;            float4 uv : TEXCOORD;            float3 normWS : TEXCOORD1;            float3 posWS : TEXCOORD2;      };                ENDHLSL                Pass      {         Tags{"LightMode" = "UniversalForward"}         Cull off                      HLSLPROGRAM         #pragma vertex vert         #pragma fragment frag                     v2f vert(a2v a)         {            //结构体初始化                v2f v = (v2f)0;                ZERO_INITIALIZE(v2f, v);                v.posWS = TransformObjectToWorld(a.vertex);                        //顶点世界位置的xz加上随时间移动量作为噪声图uv                              float2 sampleUV = v.posWS.xz/_SampleSize + _Time.y / _TimeControl;               `                //                  bigger slower            bigger slower                              //顶点着色器不能使用标准的采样方法,需要使用SAMPLE_TEXTURE2D_LOD函数(URP下)。                //因为采样需要LOD,而顶点着色器中没有LOD信息,我们需要手动输入。                        float waveSample = SAMPLE_TEXTURE2D_LOD(_NoiseTex, sampler_NoiseTex,sampleUV, 0).x;//让噪声纹理随时间移动                v.posWS.x += waveSample * a.texcoord.y * _WindIntensity;//sin(waveSample)                //v.posWS.z += waveSample * a.texcoord.y * _WindIntensity;//用纹理坐标的y轴,由下至上变大控制世界顶点z方向的位移。                         v.posCS = TransformWorldToHClip(v.posWS);                v.uv.xy = TRANSFORM_TEX(a.texcoord, _DiffTex).xy;                v.normWS = TransformObjectToWorldNormal(a.normalOS);//世界 法线                return v;         }         half4 frag(v2f v) : SV_Target         {               //Light light = GetMainLight(TransformWorldToShadowCoord(v.posWS));               half3 normalWS = normalize(v.normWS);               half3 lightWS = normalize(_MainLightPosition.xyz - v.posWS);               half4 diffColor = SAMPLE_TEXTURE2D(_DiffTex, sampler_DiffTex, v.uv.xy) * _DiffColor;                                       #if _SHADERENUM_USECOLOR                      half4 albedo = lerp(_BottomColor, _TopColor, saturate(v.uv.y + _ColorThresholed));                      #else               half4 albedo = _MainLightColor * diffColor * (max(0, dot(normalWS, lightWS)) * 0.5 + 0.5);                      #endif               half4 finalColor = albedo;               return finalColor;         }         ENDHLSL       }    }}
页: [1]
查看完整版本: 风格化草地顶点动画与blender脚本初体验