永远不该为取悦别人, 而使自己失敬于人。 Man is born free, And everywhere he is in chains. 这里是我的平日工作和 side projects 代码片段记录. 其实就只是单纯想在 comments 里吐槽罢了 (bushi 2024.09.05 // Code is full of bugs, and so is life. // /\_/\ // ( o.o ) // 妈的,我是一只可爱的小猫该多好啊,人人都会喜欢我 // 王小兵写此段代码于上海 2024.09.01 #include <stdio.h> int main(int argc, char **argv) { printf("hello my friend, welcome.\n"); return 0; } 人生, 处处是苦涩的试炼, 短暂的欢愉。 Life is full of bitter trials and short pleasures. 希望我也能从 infj 变成 intj 不想内耗了 2024.09.08 // fwidth 函数是一个 GLSL 内置函数 // 用于计算函数在屏幕空间(或者其他坐标系)中 x 和 y 方向的变化率 // 也就是函数沿着 x 和 y 方向的梯度 // 对于输入坐标 p,fwidth(p)的计算公式如下 // fwidth(p) = abs(dFdx(p)) + abs(dFdy(p)) // abs函数表示取绝对值 // dFdx(p) 表示函数在 x 轴上的偏导数 // dFdy(p) 表示函数在 y 轴上的偏导数 // 下面是一个示例片元着色器 // 使用fwidth函数计算表面法线的偏导数,结果用于计算环境光的强度 // 来自 GLSL ES Shader 参考文档 http://www.bimant.com/docs/glsl-es/fwidth/ // 老夫我啊,一独立项目会用 fwdith 函数来实现 sdf 来做边缘检测和抗锯齿 uniform vec3 ambientColor; uniform vec3 lightColor; uniform vec3 lightDir; varying vec3 vNormal; void main() { vec3 n = normalize(vNormal); vec3 l = normalize(lightDir); float NdotL = dot(n, l); float intensity = max(0.0, NdotL); // 计算法线的偏导数 vec2 derivative = fwidth(gl_FragCoord.xy); // 加权环境光颜色 vec3 ambient = ambientColor * (1.0 - intensity * intensity); vec3 color = ambient + intensity * lightColor; // 应用边缘柔化 color *= exp(-(derivative.x + derivative.y)); gl_FragColor = vec4(color, 1.0); } 临江仙 - 绝影 加班调试无空调, 八戈解完心难解。 函数堆栈似深海。 错报如血若残阳, 回溯难寻源, 算法乱成线, 无尽循环乱引用, 编程人难眠。 // URP 自定义着色器的 Shadow Receieve // 自定义 shaderlab 添加 GPU instancing 支持需要在 pass 里添加 // #pragma multi_compile_instancing // 如果大量绘制的网格都一致,那么建议用 instancing // 如果用上 instancing,那么你的其他 pass 最好都同步添加上 instancing 的支持 // 如果网格不一致,但是相同 shader,且 shader 变体一致,那么建议用 SRP Batcher // 支持 SRP Batcher 主要是将 uniform 变量都划分到对应的 CBuffer // 这篇文章讲的不错 https://blog.csdn.net/linjf520/article/details/120757669 // 有些时候,老夫我真的尽力了 Shader "Custom/ShadowReceieve" { Properties { _MainTex ("Texture", 2D) = "white" {} _Color ("Color", Color) = (1, 1, 1, 1) [Toggle] _ALPHATEST ("Alpha Test On", Float) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" CBUFFER_START(UnityPerMaterial) half4 _Color; float4 _MainTex_ST; CBUFFER_END ENDHLSL Pass { HLSLPROGRAM #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _SHADOWS_SOFT #pragma multi_compile_instancing #pragma shader_feature _ALPHATEST_ON #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float4 shadowCoord : TEXCOORD1; float3 positionWS : TEXCOORD2; }; sampler2D _MainTex; v2f vert (appdata v) { v2f o; o.positionWS = TransformObjectToWorld(v.vertex.xyz); o.vertex = TransformWorldToHClip(o.positionWS); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.shadowCoord = TransformWorldToShadowCoord(o.positionWS); return o; } half4 frag(v2f i) : SV_Target { half3 ambient = half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); half shadow = MainLightRealtimeShadow(i.shadowCoord); half4 col = tex2D(_MainTex, i.uv); half4 finalCol = col * _Color; finalCol.rgb = lerp(finalCol.rgb * ambient.rgb, finalCol.rgb, shadow); return finalCol; } ENDHLSL } } } 人一旦丧失专注的能力, 稍微动一动,就觉得快累死了。 所以,千万别堕落。 So, don't fall into depravity. 2024.09.05 // 自定义着色器要想 SRP Batcher compatible // 材质自定义的属性要放在 UnityPerMaterial 的 CBuffer 中 // 逐材质的属性,需要定义在 cbuffer 中,才能在材质切换时直接绑定显存中的 cbuffer // 老夫是这屎山项目唯一的光,还会去考虑性能问题 CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _BaseColor; half4 _SpecColor; half4 _EmissionColor; half _Cutoff; half _Surface; CBUFFER_END // 公司的这脑洞突破天灵盖的项目 // 什么样的奇葩需求都能遇得到,比如这 Cesium 卫星图的 textures 导出 // 内存里创建的贴图无法修改 import settings isReadable // 要想读取 unreadable texture2d 可以先 blit 到一张 rt 里 // 草,是一种植物,狗是真的狗 private Texture2D ReadUnreadableTexture(Texture2D texture) { RenderTexture tmp = RenderTexture.GetTemporary( texture.width, texture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); Graphics.Blit(texture, tmp); RenderTexture previous = RenderTexture.active; RenderTexture.active = tmp; Texture2D retTexture2D = new Texture2D(texture.width, texture.height); retTexture2D.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0); retTexture2D.Apply(); RenderTexture.active = previous; RenderTexture.ReleaseTemporary(tmp); return retTexture2D; } // 使用重心坐标在三角形内随机点 // 点的稀疏程度和三角形面积成正比 // 这段代码是为了在草地上随机种树 // 输入是草地 mesh 的 triangles 对应的顶点序列 // 妈的,没错,反正都是些 2b 需求 List<Vector3> RandomPointsInTriangle(Vector3 v1, Vector3 v2, Vector3 v3, float density) { var points = new List<Vector3>(); var area = Vector3.Cross(v2 - v1, v3 - v1).magnitude * 0.5f; var pointCount = Mathf.CeilToInt(area * density); for (var i = 0; i < pointCount; ++i) { var randomPoint = GenerateRandomPointInTriangle(v1, v2, v3); points.Add(randomPoint); } return points; } Vector3 GenerateRandomPointInTriangle(Vector3 v1, Vector3 v2, Vector3 v3) { var r1 = Random.value; var r2 = Random.value; if (r1 + r2 > 1f) { r1 = 1f - r1; r2 = 1f - r2; } return v1 + r1 * (v2 - v1) + r2 * (v3 - v1); } 术之尽头,炁体源流 人能得志者,元炁充而有微,肌膚潤而光澤。 雲行雨施,萬物滋也;炁充百脉,萬神靈也。 僊經曰:無一毛不通於炁,無一節不住於神。