找回密码
 立即注册
查看: 314|回复: 0

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

[复制链接]
发表于 2022-11-6 15:10 | 显示全部楼层 |阅读模式
参考:
草地的顶点动画实现风吹草动
风格化草地制作过程
【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 {  [KeywordEnum(UseTex, UseColor)] _shaderEnum("ColorType", int) = 1  [Header(UseTex)]     [MainTexture]_DiffTex("Diffuse Texture", 2D) = "white"{}     [HDR][MainColor] _DiffColor("Diffuse Color", Color) = (1, 1, 1, 1)  [Space(40)]    [Header(UseColor)]  [HDR] _TopColor("top Color", Color) = (1, 1, 1, 1)  [HDR] _BottomColor("Bottom Color", Color) = (1, 1, 1, 1)  _ColorThresholed("Color Thresholed", range(0, 1.0)) = 0.5  [Space(40)]    [Header(Animation)]  _NoiseTex("Noise Tex", 2D) = "white"{}     [Tooltip(XSpeed YSpeed ZSpeed windMagnitude)]_WindControl("WindControl",vector) = (1,0,1,0.5)        //前面几个分量表示在各个轴向上自身摆动的速度, w表示摆动的强度        [Tooltip(XSpeed YSpeed ZSpeed worldSize)]_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 {  [KeywordEnum(UseTex, UseColor)] _shaderEnum("ColorType", int) = 1    [Header(UseTex)]     [MainTexture]_DiffTex("Diffuse Texture", 2D) = "white"{}     [HDR][MainColor] _DiffColor("Diffuse Color", Color) = (1, 1, 1, 1)  [Space(40)]    [Header(UseColor)]  [HDR] _TopColor("top Color", Color) = (1, 1, 1, 1)  [HDR] _BottomColor("Bottom Color", Color) = (1, 1, 1, 1)  _ColorThresholed("Color Thresholed", range(0, 1.0)) = 0.5  [Space(40)]    [Header(Animation)]  [NoScaleOffset]_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       }    }}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-21 21:50 , Processed in 0.093693 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表