风格化草地顶点动画与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]