├── .gitignore ├── LICENSE ├── LICENSE.meta ├── Million Dust.meta ├── Million Dust ├── Compute Shaders.meta ├── Compute Shaders │ ├── DustCompute.compute │ ├── DustCompute.compute.meta │ ├── Math Functions.cginc │ ├── Math Functions.cginc.meta │ ├── Physics Functions.cginc │ ├── Physics Functions.cginc.meta │ ├── Random Functions.cginc │ ├── Random Functions.cginc.meta │ ├── Type Definitions.cginc │ └── Type Definitions.cginc.meta ├── Materials.meta ├── Materials │ ├── Box Collider.mat │ ├── Box Collider.mat.meta │ ├── Cannon Ball.mat │ ├── Cannon Ball.mat.meta │ ├── Cone - Blower.mat │ ├── Cone - Blower.mat.meta │ ├── Cone - Cannon.mat │ ├── Cone - Cannon.mat.meta │ ├── Cone - Cleaner.mat │ ├── Cone - Cleaner.mat.meta │ ├── Cone - Emitter.mat │ ├── Cone - Emitter.mat.meta │ ├── Dust.mat │ ├── Dust.mat.meta │ ├── Explosion.mat │ ├── Explosion.mat.meta │ ├── Player.mat │ ├── Player.mat.meta │ ├── Sphere Collider.mat │ ├── Sphere Collider.mat.meta │ ├── World Bounds.mat │ └── World Bounds.mat.meta ├── Million Dust.unity ├── Million Dust.unity.meta ├── Prefabs.meta ├── Prefabs │ ├── Cannon Ball.prefab │ ├── Cannon Ball.prefab.meta │ ├── Explosion.prefab │ └── Explosion.prefab.meta ├── Scripts.meta ├── Scripts │ ├── CannonBall.cs │ ├── CannonBall.cs.meta │ ├── Colliders.meta │ ├── Colliders │ │ ├── DustBoxCollider.cs │ │ ├── DustBoxCollider.cs.meta │ │ ├── DustCollider.cs │ │ ├── DustCollider.cs.meta │ │ ├── DustSphereCollider.cs │ │ └── DustSphereCollider.cs.meta │ ├── Cones.meta │ ├── Cones │ │ ├── Cannon.cs │ │ ├── Cannon.cs.meta │ │ ├── Cone.cs │ │ ├── Cone.cs.meta │ │ ├── DustEmitter.cs │ │ ├── DustEmitter.cs.meta │ │ ├── VacuumCleaner.cs │ │ └── VacuumCleaner.cs.meta │ ├── DustManager.cs │ ├── DustManager.cs.meta │ ├── DustManager_Colliders.cs │ ├── DustManager_Colliders.cs.meta │ ├── DustManager_Methods.cs │ ├── DustManager_Methods.cs.meta │ ├── Editor Scripts.meta │ ├── Editor Scripts │ │ ├── EditorHierarchyIconHelper.cs │ │ ├── EditorHierarchyIconHelper.cs.meta │ │ ├── EditorTagHelper.cs │ │ └── EditorTagHelper.cs.meta │ ├── MeshMaker.cs │ ├── MeshMaker.cs.meta │ ├── MinMaxBounds.cs │ ├── MinMaxBounds.cs.meta │ ├── PlayerController.cs │ └── PlayerController.cs.meta ├── Shaders.meta ├── Shaders │ ├── Box Collider.shader │ ├── Box Collider.shader.meta │ ├── Cannon Ball.shader │ ├── Cannon Ball.shader.meta │ ├── Depth Intersection.shader │ ├── Depth Intersection.shader.meta │ ├── Dust.shader │ ├── Dust.shader.meta │ ├── Explosion.shader │ ├── Explosion.shader.meta │ ├── Sphere Collider.shader │ ├── Sphere Collider.shader.meta │ ├── World Bounds.shader │ └── World Bounds.shader.meta ├── Textures.meta └── Textures │ ├── Point_Dust.png │ └── Point_Dust.png.meta ├── README.md └── README.md.meta /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | # Unity3D generated file on crash reports 52 | sysinfo.txt 53 | 54 | # Builds 55 | *.apk 56 | *.unitypackage 57 | 58 | # Crashlytics generated file 59 | crashlytics-build.properties 60 | 61 | 62 | # Additions by Rito 63 | *.cmd 64 | *.cmd.meta 65 | _* 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Rito15 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 85f1484f6448a23438da2f32d045a086 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Million Dust.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2cec59debffc520469b764e731e08138 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Compute Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 530aac007f14aca42882e58d945a98e6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/DustCompute.compute: -------------------------------------------------------------------------------- 1 |  2 | #pragma kernel Populate 3 | #pragma kernel SetDustColors 4 | #pragma kernel Update 5 | #pragma kernel VacuumUp 6 | #pragma kernel Emit 7 | #pragma kernel BlowWind 8 | #pragma kernel Explode 9 | 10 | #include "Type Definitions.cginc" 11 | #include "Math Functions.cginc" 12 | #include "Random Functions.cginc" 13 | #include "Physics Functions.cginc" 14 | 15 | /******************************************************************* 16 | * Naming Conventions 17 | /******************************************************************* 18 | - AToB : B - A 19 | - ~Dir : 방향 벡터(크기 1) 20 | - ~Dist : 두 위치 벡터 사이의 거리(스칼라) 21 | - ~Len : 한 벡터의 길이 22 | /*******************************************************************/ 23 | 24 | /******************************************************************* 25 | /* Definitions 26 | /*******************************************************************/ 27 | #define NUM_THREADS_HEADER numthreads(64,1,1) 28 | #define TRUE 1 29 | #define FALSE 0 30 | #define TAU 6.28318530 31 | 32 | // 순간적 충격에 의한 속도 계산 시 사용 - 타임스케일 변경에도 일관적 동작 유지 33 | #define CONSTANT_DELTA_TIME 0.02 34 | 35 | #define DEFAULT_BOX_COLLIDER { float3(-0.5, -0.5, -0.5), float3(0.5, 0.5, 0.5) } 36 | 37 | /******************************************************************* 38 | /* Variables 39 | /*******************************************************************/ 40 | /* Buffers */ 41 | RWStructuredBuffer dustBuffer; // 먼지 위치, 생존 여부 42 | RWStructuredBuffer dustColorBuffer; // 먼지 색상 RGB 43 | RWStructuredBuffer velocityBuffer; // 먼지 속도 44 | RWStructuredBuffer aliveNumberBuffer; // 생존한 먼지 개수 45 | RWStructuredBuffer collisionFlagBuffer; // 이번 프레임 충돌 처리 여부 46 | 47 | /* Colliders */ 48 | RWStructuredBuffer sphereColliderBuffer; 49 | uint sphereColliderCount; 50 | 51 | RWStructuredBuffer boxColliderBuffer; 52 | uint boxColliderCount; 53 | 54 | /* Init On Load */ 55 | uint dustCount; // 먼지 개수 56 | 57 | /* Common */ 58 | float3 spawnBoundsMin; // 먼지 생성 영역 - 최소 지점 59 | float3 spawnBoundsMax; // 먼지 생성 영역 - 최대 지점 60 | float3 worldBoundsMin; // 월드 제한 영역 - 최소 지점 61 | float3 worldBoundsMax; // 월드 제한 영역 - 최대 지점 62 | float deltaTime; // delta t 63 | 64 | /* Populate */ 65 | half3 dustColorA; // 무작위 색상 A 66 | half3 dustColorB; // 무작위 색상 B 67 | 68 | /* Controller */ 69 | float3 controllerPos; // 월드 위치 70 | float3 controllerForward; // 전방 벡터 71 | 72 | /* Physics(Update) */ 73 | float3 gravity; // 중력 가속도 74 | float radius; // 먼지 반지름 75 | float mass; // 질량 76 | float drag; // (공기) 저항력 77 | float bounciness; // 탄성력 78 | 79 | /* Vacuum Cleaner */ 80 | float cleanerSqrDist; // 먼지 흡입 범위(반지름) - 제곱 81 | float cleanerSqrDeathRange; // 먼지 소멸 범위(반지름) - 제곱 82 | float cleanerSqrForce; // 빨아들이는 힘 - 제곱 83 | float cleanerDotThreshold; // 진공 청소기 원뿔 영역 내적 범위 84 | bool cleanerKillOn; // 흡수하여 먼지 제거할지 여부 85 | 86 | /* Emitter */ 87 | float time; // Time.time 88 | float emitterForce; // 방출 강도 89 | float emitterDist; // 방출 거리 90 | float emitterAngleRad; // 방출 각도 91 | uint emissionPerSec; // 초당 먼지 발사 개수 92 | float4x4 controllerMatrix; // localToWorld 93 | 94 | /* Blower */ 95 | float blowerSqrDist; // 영향 범위(반지름) - 제곱 96 | float blowerSqrForce; // 미는 힘 - 제곱 97 | float blowerDotThreshold; // 원뿔 영역 내적 범위 98 | 99 | /* Explode */ 100 | float3 explosionPosition; // 폭발 중심 위치 101 | float explosionSqrRange; // 폭발 반지름 - 제곱 102 | float explosionForce; // 폭발 힘 103 | 104 | /******************************************************************* 105 | /* Functions 106 | /*******************************************************************/ 107 | // 먼지 파괴 108 | void DestroyDust(uint i) 109 | { 110 | dustBuffer[i].isAlive = FALSE; 111 | InterlockedAdd(aliveNumberBuffer[0], -1); 112 | } 113 | 114 | /******************************************************************* 115 | /* Kernels 116 | /*******************************************************************/ 117 | // 초기 생성 118 | [NUM_THREADS_HEADER] 119 | void Populate (uint3 id : SV_DispatchThreadID) 120 | { 121 | uint i = id.x; 122 | 123 | // 무작위 요소 추가 : XZ평면 반지름 1 크기의 원 좌표 가산 124 | uint deg = i % 360; 125 | float3 ranDir = float3(cos(deg), 0, sin(deg)); 126 | float3 ranPos = Random11(i) * ranDir; 127 | 128 | float width = SqrMagnitude(spawnBoundsMax - spawnBoundsMin); 129 | float seed = i * 100000 / (width * dustCount); 130 | dustBuffer[i].position = RandomRange13(seed, spawnBoundsMin, spawnBoundsMax) + ranPos; 131 | dustBuffer[i].isAlive = TRUE; 132 | } 133 | 134 | // 먼지 색상 설정(2가지 중 랜덤) 135 | [NUM_THREADS_HEADER] 136 | void SetDustColors (uint3 id : SV_DispatchThreadID) 137 | { 138 | uint i = id.x; 139 | 140 | float2 seed2d = float2(i % dustCount, i / dustCount); 141 | float t = Random21(seed2d); 142 | dustColorBuffer[i] = lerp(dustColorA, dustColorB, t); 143 | } 144 | 145 | // 실시간 업데이트(물리) 146 | [NUM_THREADS_HEADER] 147 | void Update (uint3 id : SV_DispatchThreadID) 148 | { 149 | uint i = id.x; 150 | if(dustBuffer[i].isAlive == FALSE) return; 151 | if(i >= dustCount) return; 152 | 153 | float3 A = 0; // 가속도 합 벡터 154 | 155 | // F = m * a 156 | // dv = a * dt 157 | 158 | // =================================================== 159 | // 속도 계산 160 | // =================================================== 161 | 162 | // [1] 중력 163 | A += gravity; 164 | 165 | // [2] 저항력 166 | A -= velocityBuffer[i] * drag; 167 | 168 | // 속도 적용 : dv = a * dt, v = v0 + dv 169 | velocityBuffer[i] += A * deltaTime; 170 | 171 | // =================================================== 172 | // 이동 시뮬레이션, 충돌 검사 173 | // =================================================== 174 | // 다음 프레임 위치 계산 : S = S0 + V * t 175 | float3 currPos = dustBuffer[i].position; 176 | float3 nextPos = currPos + velocityBuffer[i] * deltaTime; 177 | 178 | // 이번 프레임 충돌 처리 완료 여부 초기화 179 | collisionFlagBuffer[i] = false; 180 | 181 | // [1] Sphere Colliders 182 | for(uint scIndex = 0; scIndex < sphereColliderCount; scIndex++) 183 | { 184 | if(collisionFlagBuffer[i] == true) continue; 185 | 186 | float4 sphere; 187 | sphere.xyz = mul(sphereColliderBuffer[scIndex].localToWorld, float4(0, 0, 0, 1)).xyz; 188 | sphere.w = sphereColliderBuffer[scIndex].scale.x * 0.5; 189 | 190 | if(SphereToSphereIntersection(float4(nextPos, radius), sphere)) 191 | { 192 | DustToSphereCollision(currPos, nextPos, velocityBuffer[i], radius, sphere, bounciness, collisionFlagBuffer[i]); 193 | } 194 | } 195 | 196 | // [2] Box Colliders(OBB) 197 | for(uint bcIndex = 0; bcIndex < boxColliderCount; bcIndex++) 198 | { 199 | if(collisionFlagBuffer[i] == true) continue; 200 | 201 | Bounds box = DEFAULT_BOX_COLLIDER; 202 | float4x4 WtL = boxColliderBuffer[bcIndex].worldToLocal; 203 | 204 | float3 localNextPos = mul(WtL, float4(nextPos, 1)).xyz; 205 | 206 | // 박스 로컬 스페이스에서의 먼지 스케일 계산 207 | float3 localDustRadius = radius.xxx / boxColliderBuffer[bcIndex].scale; 208 | 209 | // 박스 콜라이더의 로컬 스페이스에서 먼지 교차 검사(AABB-AABB) 210 | if(DustToDefaultAABBIntersection(localNextPos, localDustRadius)) 211 | { 212 | float3 localCurrPos = mul(WtL, float4(currPos, 1)).xyz; 213 | float3 localVelocity = mul(WtL, float4(velocityBuffer[i], 0)).xyz; 214 | 215 | // 박스 콜라이더의 로컬 스페이스에서 충돌 처리 216 | DustToAABBCollision(localCurrPos, localNextPos, localVelocity, localDustRadius, box, bounciness, collisionFlagBuffer[i]); 217 | 218 | float4x4 LtW = boxColliderBuffer[bcIndex].localToWorld; 219 | nextPos = mul(LtW, float4(localNextPos, 1)).xyz; 220 | velocityBuffer[i] = mul(LtW, float4(localVelocity, 0)).xyz; 221 | } 222 | } 223 | 224 | // [Last] 월드 영역 제한(Box) 225 | Bounds bounds; 226 | bounds.min = worldBoundsMin; 227 | bounds.max = worldBoundsMax; 228 | ConfineWithinWorldBounds(currPos, nextPos, velocityBuffer[i], radius, bounciness, bounds); 229 | 230 | // 다음 위치 적용 231 | dustBuffer[i].position = nextPos; 232 | } 233 | 234 | // 진공 청소기로 빨아들이기 235 | [NUM_THREADS_HEADER] 236 | void VacuumUp (uint3 id : SV_DispatchThreadID) 237 | { 238 | uint i = id.x; 239 | if(dustBuffer[i].isAlive == FALSE) return; 240 | if(i >= dustCount) return; 241 | 242 | float3 F = 0; // 힘 합 벡터 243 | bool flag = false; 244 | 245 | float3 currPos = dustBuffer[i].position; // 현재 프레임 먼지 위치 246 | float3 currToHead = (controllerPos - currPos); // 먼지 -> 청소기 입구 247 | float sqrDist = SqrMagnitude(currToHead); // 청소기 입구 <-> 먼지 사이 거리 제곱 248 | 249 | // 원뿔 범위 및 힘 계산 250 | if (sqrDist < cleanerSqrDist) 251 | { 252 | float3 dustToHeadDir = normalize(currToHead); // 먼지 -> 청소기 입구 방향 253 | float dotValue = dot(controllerForward, -dustToHeadDir); 254 | 255 | // 원뿔 범위 내에 있을 경우 빨아들이기 256 | if(dotValue > cleanerDotThreshold) 257 | { 258 | float force = cleanerSqrForce / sqrDist; 259 | 260 | // 빨아들이는 힘 261 | F += dustToHeadDir * force * dotValue; 262 | 263 | flag = true; 264 | } 265 | } 266 | 267 | // 속도 계산 268 | if(flag) 269 | { 270 | // 가속도 271 | float3 A = F / mass; 272 | 273 | // 속도 274 | velocityBuffer[i] += A * deltaTime; 275 | 276 | // 제거 모드 확인 277 | if(cleanerKillOn == false) 278 | return; 279 | 280 | // 다음 프레임 위치 예측 : S = S0 + V * t 281 | float3 nextPos = currPos + velocityBuffer[i] * deltaTime; 282 | 283 | float3 headToNext = nextPos - controllerPos; 284 | float3 headToCurrDir = normalize(-currToHead); 285 | float3 headToNextDir = normalize(headToNext); 286 | 287 | // 현재 프레임에 먼지가 원뿔 범위 내에 있었다면 288 | if(dot(controllerForward, headToCurrDir) > cleanerDotThreshold) 289 | { 290 | // 다음 프레임에 원뿔 밖으로 나가거나 입구에 근접하면 파괴 291 | if(dot(controllerForward, headToNextDir) < cleanerDotThreshold || 292 | SqrMagnitude(headToNext) < cleanerSqrDeathRange) 293 | { 294 | DestroyDust(i); 295 | } 296 | } 297 | } 298 | } 299 | 300 | // 죽었던 먼지들 살려서 발사 301 | [NUM_THREADS_HEADER] 302 | void Emit (uint3 id : SV_DispatchThreadID) 303 | { 304 | uint i = id.x; 305 | if(dustBuffer[i].isAlive == TRUE) return; 306 | if(i >= dustCount) return; 307 | 308 | /* 발사 확률 계산*/ 309 | // emissionPerSec = 프레임당 발사되는 개수 / deltaTime 310 | // 발사 확률 = 프레임당 발사되는 개수 / 현재 개수 311 | 312 | float aliveCount = dustCount - aliveNumberBuffer[0]; // 죽은(발사 가능한) 먼지 개수 313 | float emissionCount = emissionPerSec * deltaTime; // 발사할 먼지 개수 314 | float emissionRatio = emissionCount / aliveCount; // 발사 확률 315 | 316 | float seed = (i + time) / 79238.288; 317 | float r = Random11(seed); 318 | if(r > emissionRatio) return; 319 | 320 | // Note : localDir의 z를 1로 고정하고, xy를 tan(emitterAngleRad)로 지정함으로써 321 | // 발사되는 먼지들이 형성하는 원뿔의 각도를 suctionAngle로 설정하는 효과를 얻는다. 322 | 323 | // r2.x : 각 먼지의 각도 (-360 ~ 360), r2.y : 원의 반지름(원뿔의 각도 결정) 324 | float seed2 = i / 82801.277; 325 | float2 r2 = RandomRange12(seed2, float2(-TAU, 0), float2(TAU, 1)); 326 | float2 randomCircle = float2(cos(r2.x), sin(r2.x)) * r2.y * tan(emitterAngleRad); 327 | 328 | // 발사 방향 벡터 공간 변환 329 | // Note - localDir.z : 기본 값 1 => Z축 볼륨을 주기 위해 연산 추가 330 | float3 localDir = float3(randomCircle.x, randomCircle.y, (1 + r * r2.y * TAU)); 331 | float3 worldDir = mul(controllerMatrix, float4(localDir, 0)).xyz; 332 | 333 | float3 F = worldDir * emitterForce * emitterDist; 334 | float3 A = F / mass; 335 | float3 V = A * CONSTANT_DELTA_TIME; 336 | 337 | dustBuffer[i].position = controllerPos; 338 | velocityBuffer[i] = V; 339 | 340 | // 먼지 되살리기 341 | dustBuffer[i].isAlive = TRUE; 342 | InterlockedAdd(aliveNumberBuffer[0], 1); 343 | } 344 | 345 | // 바람 불기 346 | [NUM_THREADS_HEADER] 347 | void BlowWind (uint3 id : SV_DispatchThreadID) 348 | { 349 | uint i = id.x; 350 | if(dustBuffer[i].isAlive == FALSE) return; 351 | if(i >= dustCount) return; 352 | 353 | float3 dustPos = dustBuffer[i].position; // 현재 프레임 먼지 위치 354 | float3 headToDust = (dustPos - controllerPos); // 입구 -> 먼지 355 | float sqrDist = SqrMagnitude(headToDust); // 입구<-> 먼지 사이 거리 제곱 356 | 357 | // 구형 범위 내에 포함되는 경우 358 | if (sqrDist < blowerSqrDist) 359 | { 360 | float3 headToDustDir = normalize(headToDust); // 입구 -> 먼지 방향 361 | float dotValue = dot(controllerForward, headToDustDir); 362 | 363 | // 원뿔 범위 내에 포함되는 경우, 밀쳐내기 364 | if(dotValue > blowerDotThreshold) 365 | { 366 | float force = blowerSqrForce / sqrt(sqrDist); 367 | 368 | float3 F = headToDustDir * force * dotValue; 369 | float3 A = F / mass; 370 | velocityBuffer[i] += A * CONSTANT_DELTA_TIME; 371 | } 372 | } 373 | } 374 | 375 | // 지점 폭발 376 | [NUM_THREADS_HEADER] 377 | void Explode (uint3 id : SV_DispatchThreadID) 378 | { 379 | uint i = id.x; 380 | if(dustBuffer[i].isAlive == FALSE) return; 381 | if(i >= dustCount) return; 382 | 383 | float3 dustPos = dustBuffer[i].position; // 현재 프레임 먼지 위치 384 | float3 centerToDust = (dustPos - explosionPosition); // 폭발 중심 -> 먼지 385 | float sqrDist = SqrMagnitude(centerToDust); // 폭발 중심<-> 먼지 사이 거리 제곱 386 | 387 | // 구형 범위 내에 포함되는 경우 388 | if (sqrDist < explosionSqrRange) 389 | { 390 | float t = 1 - (sqrDist / explosionSqrRange); 391 | float f = t * explosionForce; 392 | float3 dir = normalize(centerToDust); 393 | 394 | float3 F = dir * f; 395 | float3 A = F / mass; 396 | velocityBuffer[i] += A * deltaTime; 397 | } 398 | } -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/DustCompute.compute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a725fe981ed6cbf45a47ee3e356c76dc 3 | ComputeShaderImporter: 4 | externalObjects: {} 5 | currentAPIMask: 4 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Math Functions.cginc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rito15/Unity-Million-Dust/9f997480ccb636ab20d633921cd8361acba004f0/Million Dust/Compute Shaders/Math Functions.cginc -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Math Functions.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 31cb0e6c96647c744b8bdf289dff9a16 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Physics Functions.cginc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rito15/Unity-Million-Dust/9f997480ccb636ab20d633921cd8361acba004f0/Million Dust/Compute Shaders/Physics Functions.cginc -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Physics Functions.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 977d2084d576c9e4fb490b8f59538345 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Random Functions.cginc: -------------------------------------------------------------------------------- 1 | 2 | #define RM 39482.17593 3 | #define RD1 7.8671 4 | #define RD2 3.3419 5 | #define RD3 5.8912 6 | #define RP1 2.1759 7 | #define RP2 4.7921 8 | 9 | float Random11(float seed) 10 | { 11 | return frac(sin(dot(float2(RD1, seed), float2(seed, RD2))) * RM); 12 | } 13 | float2 Random12(float seed) 14 | { 15 | return float2( 16 | frac(sin(dot(float2(RD1, seed), float2(seed, RD2))) * RM), 17 | frac(sin(dot(float2(seed, RD2), float2(RD3, seed))) * RM) 18 | ); 19 | } 20 | float3 Random13(float seed) 21 | { 22 | return float3( 23 | frac(sin(dot(float2(seed, RD1), float2(RD2, seed))) * RM), 24 | frac(sin(dot(float2(seed, RD2), float2(RD3, seed))) * RM), 25 | frac(sin(dot(float2(seed, RD3), float2(RD1, seed))) * RM) 26 | ); 27 | } 28 | 29 | float RandomRange11(float seed, float min, float max) 30 | { 31 | return lerp(min, max, Random11(seed)); 32 | } 33 | float2 RandomRange12(float seed, float2 min, float2 max) 34 | { 35 | float2 vec; 36 | vec.x = RandomRange11(seed, min.x, max.x); 37 | vec.y = RandomRange11(seed + RP1, min.y, max.y); 38 | return vec; 39 | } 40 | float3 RandomRange13(float seed, float3 min, float3 max) 41 | { 42 | float3 vec; 43 | vec.x = RandomRange11(seed, min.x, max.x); 44 | vec.y = RandomRange11(seed + RP1, min.y, max.y); 45 | vec.z = RandomRange11(seed + RP2, min.z, max.z); 46 | return vec; 47 | } 48 | 49 | float Random21(float2 seed) 50 | { 51 | return frac(sin(dot(seed, float2(RD1, RD2))) * RM); 52 | } 53 | float2 Random22(float2 seed) 54 | { 55 | return float2( 56 | frac(sin(dot(seed, float2(RD1, RD2))) * RM), 57 | frac(sin(dot(seed + float2(RP1, RP2), float2(RD2, RD3))) * RM) 58 | ); 59 | } 60 | float3 Random23(float2 seed) 61 | { 62 | return float3( 63 | frac(sin(dot(seed, float2(RD1, RD2))) * RM), 64 | frac(sin(dot(seed + float2(RP1, RP2), float2(RD2, RD3))) * RM), 65 | frac(sin(dot(seed + float2(RP2, RP1), float2(RD3, RD1))) * RM) 66 | ); 67 | } 68 | 69 | float RandomRange21(float2 seed, float min, float max) 70 | { 71 | return lerp(min, max, Random21(seed)); 72 | } 73 | float2 RandomRange22(float2 seed, float2 min, float2 max) 74 | { 75 | float2 vec; 76 | vec.x = RandomRange21(seed, min.x, max.x); 77 | vec.y = RandomRange21(seed + float2(RP1, RP2), min.y, max.y); 78 | return vec; 79 | } 80 | float3 RandomRange23(float2 seed, float3 min, float3 max) 81 | { 82 | float3 vec; 83 | vec.x = RandomRange21(seed, min.x, max.x); 84 | vec.y = RandomRange21(seed + float2(RP1, RP2), min.y, max.y); 85 | vec.z = RandomRange21(seed + float2(RP2, RP1), min.z, max.z); 86 | return vec; 87 | } -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Random Functions.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1385b94c2dfeb5942a00349fcbf526e8 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Type Definitions.cginc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rito15/Unity-Million-Dust/9f997480ccb636ab20d633921cd8361acba004f0/Million Dust/Compute Shaders/Type Definitions.cginc -------------------------------------------------------------------------------- /Million Dust/Compute Shaders/Type Definitions.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 376d9d8522d575f4291f008a3b837623 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 368c82b4c4db8bc47b6954af767025b3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Box Collider.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Box Collider 11 | m_Shader: {fileID: 4800000, guid: 261c33ee91f9f5a4dac3a2603b4e447f, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _texcoord: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | m_Floats: 27 | - _Intersection1: 1 28 | - _IntersectionIntensity: 0.3 29 | - _Power: 1 30 | - _Smoothness: 0.2 31 | - _Width: 0.2 32 | - __dirty: 0 33 | m_Colors: 34 | - _Color: {r: 1, g: 1, b: 1, a: 0} 35 | -------------------------------------------------------------------------------- /Million Dust/Materials/Box Collider.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e2c7c28a39f6134ba27daa04e4e684b 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cannon Ball.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Cannon Ball 11 | m_Shader: {fileID: 4800000, guid: e44e42bb0dbf9184790ada4fec8f4729, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 3002 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0 24 | - _FresnelIntensity: 3 25 | - _FresnelPower: 1 26 | - _Intersection: 0.6 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 0, g: 0.9817288, b: 1, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cannon Ball.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e42df576914d28f428459e783ecec98f 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Blower.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Cone - Blower 11 | m_Shader: {fileID: 4800000, guid: 36c962b1c4493cd4e91d1f87bdfee72d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 3001 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0.2 24 | - _FresnelIntensity: 2 25 | - _FresnelPower: 3.06 26 | - _Intersection: 0.8 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 1, g: 0.33490568, b: 0.39750278, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Blower.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49a1c47b697e4ac4e9e81697a3e42568 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Cannon.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Cone - Cannon 11 | m_Shader: {fileID: 4800000, guid: 36c962b1c4493cd4e91d1f87bdfee72d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 3001 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0.2 24 | - _FresnelIntensity: 2 25 | - _FresnelPower: 1.5 26 | - _Intersection: 1 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 0, g: 0.8396226, b: 0.05505435, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Cannon.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5455babacd950e3458f9474ee073dcd8 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Cleaner.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Cone - Cleaner 11 | m_Shader: {fileID: 4800000, guid: 36c962b1c4493cd4e91d1f87bdfee72d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 3001 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0.1 24 | - _FresnelIntensity: 3 25 | - _FresnelPower: 4 26 | - _Intersection: 1 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 0, g: 1, b: 0.8239019, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Cleaner.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 367b14cad09159d42aaa2db0961281b5 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Emitter.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Cone - Emitter 11 | m_Shader: {fileID: 4800000, guid: 36c962b1c4493cd4e91d1f87bdfee72d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 3001 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0.1 24 | - _FresnelIntensity: 2 25 | - _FresnelPower: 5 26 | - _Intersection: 1 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 0.8150126, g: 1, b: 0, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Cone - Emitter.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 012fb628776ba904392ebf8ebf896c5d 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Dust.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Dust 11 | m_Shader: {fileID: 4800000, guid: 91a0d60d54a827d4db33e781eb519d9d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _MainTex: 23 | m_Texture: {fileID: 2800000, guid: e3933a5af5354e243a44512e5de3776c, type: 3} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | m_Floats: 27 | - _CutOff: 0.5 28 | m_Colors: 29 | - _Color: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Dust.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 580e99519544d7049bc9d6a36bb4e96b 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Explosion.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Explosion 11 | m_Shader: {fileID: 4800000, guid: ca07cfe48c7bdd9429ee3628e95443be, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 3002 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0.265 24 | - _FresnelIntensity: 0.8 25 | - _FresnelPower: 1 26 | - _Intersection: 0.6 27 | - _Power: 3 28 | - __dirty: 0 29 | m_Colors: 30 | - _Color: {r: 1, g: 1, b: 1, a: 1} 31 | -------------------------------------------------------------------------------- /Million Dust/Materials/Explosion.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cbaaeeacfecf5be45ab63bfe938f6cbf 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Player.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Player 11 | m_Shader: {fileID: 4800000, guid: 36c962b1c4493cd4e91d1f87bdfee72d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0.7 24 | - _FresnelIntensity: 1 25 | - _FresnelPower: 5 26 | - _Intersection: 0.5 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 0.8301887, g: 0.8301887, b: 0.8301887, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Player.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6ef5095705bc274099cf9480a069bcd 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/Sphere Collider.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: Sphere Collider 11 | m_Shader: {fileID: 4800000, guid: 99c406b1b155ea14294103fc27b2b20d, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 0 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - _Ambient: 0 24 | - _FresnelIntensity: 0.75 25 | - _FresnelPower: 0.5 26 | - _Intersection: 0.4 27 | - __dirty: 0 28 | m_Colors: 29 | - _Color: {r: 1, g: 1, b: 1, a: 1} 30 | -------------------------------------------------------------------------------- /Million Dust/Materials/Sphere Collider.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a938fd553ec81e44f9a40ecbb2a24abd 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Materials/World Bounds.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: World Bounds 11 | m_Shader: {fileID: 4800000, guid: fc893f8dec30aa74fb38dffa80b56c05, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: [] 22 | m_Floats: 23 | - __dirty: 0 24 | m_Colors: [] 25 | -------------------------------------------------------------------------------- /Million Dust/Materials/World Bounds.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a7c357410e3263149ad9025f4ffac9a1 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Million Dust.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 911aaa7eb252def40a3d25995f1e877d 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Million Dust/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 474ef042fdcf6de40bc321446f26d751 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Prefabs/Cannon Ball.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &8121042753049998215 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 2420836496645141817} 12 | - component: {fileID: 6692805609753369901} 13 | - component: {fileID: 2100266121893881353} 14 | - component: {fileID: 5876574552656517186} 15 | - component: {fileID: 2523111049047731110} 16 | - component: {fileID: 3468666402742456569} 17 | m_Layer: 0 18 | m_Name: Cannon Ball 19 | m_TagString: Untagged 20 | m_Icon: {fileID: 0} 21 | m_NavMeshLayer: 0 22 | m_StaticEditorFlags: 0 23 | m_IsActive: 1 24 | --- !u!4 &2420836496645141817 25 | Transform: 26 | m_ObjectHideFlags: 0 27 | m_CorrespondingSourceObject: {fileID: 0} 28 | m_PrefabInstance: {fileID: 0} 29 | m_PrefabAsset: {fileID: 0} 30 | m_GameObject: {fileID: 8121042753049998215} 31 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 32 | m_LocalPosition: {x: 0, y: 0, z: 0} 33 | m_LocalScale: {x: 2, y: 2, z: 2} 34 | m_Children: [] 35 | m_Father: {fileID: 0} 36 | m_RootOrder: 0 37 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 38 | --- !u!33 &6692805609753369901 39 | MeshFilter: 40 | m_ObjectHideFlags: 0 41 | m_CorrespondingSourceObject: {fileID: 0} 42 | m_PrefabInstance: {fileID: 0} 43 | m_PrefabAsset: {fileID: 0} 44 | m_GameObject: {fileID: 8121042753049998215} 45 | m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} 46 | --- !u!23 &2100266121893881353 47 | MeshRenderer: 48 | m_ObjectHideFlags: 0 49 | m_CorrespondingSourceObject: {fileID: 0} 50 | m_PrefabInstance: {fileID: 0} 51 | m_PrefabAsset: {fileID: 0} 52 | m_GameObject: {fileID: 8121042753049998215} 53 | m_Enabled: 1 54 | m_CastShadows: 1 55 | m_ReceiveShadows: 1 56 | m_DynamicOccludee: 1 57 | m_MotionVectors: 1 58 | m_LightProbeUsage: 1 59 | m_ReflectionProbeUsage: 1 60 | m_RayTracingMode: 2 61 | m_RenderingLayerMask: 1 62 | m_RendererPriority: 0 63 | m_Materials: 64 | - {fileID: 2100000, guid: e42df576914d28f428459e783ecec98f, type: 2} 65 | m_StaticBatchInfo: 66 | firstSubMesh: 0 67 | subMeshCount: 0 68 | m_StaticBatchRoot: {fileID: 0} 69 | m_ProbeAnchor: {fileID: 0} 70 | m_LightProbeVolumeOverride: {fileID: 0} 71 | m_ScaleInLightmap: 1 72 | m_ReceiveGI: 1 73 | m_PreserveUVs: 0 74 | m_IgnoreNormalsForChartDetection: 0 75 | m_ImportantGI: 0 76 | m_StitchLightmapSeams: 1 77 | m_SelectedEditorRenderState: 3 78 | m_MinimumChartSize: 4 79 | m_AutoUVMaxDistance: 0.5 80 | m_AutoUVMaxAngle: 89 81 | m_LightmapParameters: {fileID: 0} 82 | m_SortingLayerID: 0 83 | m_SortingLayer: 0 84 | m_SortingOrder: 0 85 | --- !u!135 &5876574552656517186 86 | SphereCollider: 87 | m_ObjectHideFlags: 0 88 | m_CorrespondingSourceObject: {fileID: 0} 89 | m_PrefabInstance: {fileID: 0} 90 | m_PrefabAsset: {fileID: 0} 91 | m_GameObject: {fileID: 8121042753049998215} 92 | m_Material: {fileID: 0} 93 | m_IsTrigger: 1 94 | m_Enabled: 1 95 | serializedVersion: 2 96 | m_Radius: 0.5 97 | m_Center: {x: 0, y: 0, z: 0} 98 | --- !u!54 &2523111049047731110 99 | Rigidbody: 100 | m_ObjectHideFlags: 0 101 | m_CorrespondingSourceObject: {fileID: 0} 102 | m_PrefabInstance: {fileID: 0} 103 | m_PrefabAsset: {fileID: 0} 104 | m_GameObject: {fileID: 8121042753049998215} 105 | serializedVersion: 2 106 | m_Mass: 1 107 | m_Drag: 0 108 | m_AngularDrag: 0.05 109 | m_UseGravity: 1 110 | m_IsKinematic: 0 111 | m_Interpolate: 0 112 | m_Constraints: 0 113 | m_CollisionDetection: 0 114 | --- !u!114 &3468666402742456569 115 | MonoBehaviour: 116 | m_ObjectHideFlags: 0 117 | m_CorrespondingSourceObject: {fileID: 0} 118 | m_PrefabInstance: {fileID: 0} 119 | m_PrefabAsset: {fileID: 0} 120 | m_GameObject: {fileID: 8121042753049998215} 121 | m_Enabled: 1 122 | m_EditorHideFlags: 0 123 | m_Script: {fileID: 11500000, guid: 25ef65d4b8c0c334a8bc482123204e1d, type: 3} 124 | m_Name: 125 | m_EditorClassIdentifier: 126 | rBody: {fileID: 2523111049047731110} 127 | -------------------------------------------------------------------------------- /Million Dust/Prefabs/Cannon Ball.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8ae78a68ac0fd1f4c87ce4d529526384 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Million Dust/Prefabs/Explosion.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 071687ae9ba46e34a94abae928fe03c2 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Million Dust/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82956598b8cb5e94ca0045154a641ddd 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Scripts/CannonBall.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-13 PM 8:58:15 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// 투사체 13 | /// 14 | public class CannonBall : MonoBehaviour 15 | { 16 | [SerializeField] private Rigidbody rBody; 17 | 18 | private GameObject explosionPrefab; 19 | private float explosionParticleSize; 20 | 21 | private float explosionSqrRange; 22 | private float explosionForce; 23 | 24 | private void Init() 25 | { 26 | if (rBody == null) 27 | rBody = GetComponent(); 28 | 29 | if (rBody == null) 30 | rBody = gameObject.AddComponent(); 31 | 32 | TryGetComponent(out Collider col); 33 | col.isTrigger = true; 34 | } 35 | 36 | /// 폭발 프리팹 등록 37 | public void SetExplosionPrefab(GameObject prefab, float size) 38 | { 39 | this.explosionPrefab = prefab; 40 | this.explosionParticleSize = size; 41 | } 42 | 43 | /// 포탄 발사 44 | public void Shoot(in Vector3 movement, in float explosionRange, in float explosionForce, in float lifespan = 5f) 45 | { 46 | Init(); 47 | Destroy(gameObject, lifespan); 48 | rBody.AddForce(movement, ForceMode.Impulse); 49 | 50 | this.explosionSqrRange = explosionRange * explosionRange; 51 | this.explosionForce = explosionForce; 52 | } 53 | 54 | private void OnTriggerEnter(Collider other) 55 | { 56 | if (other.CompareTag(DustCollider.ColliderTag) == false) return; 57 | 58 | // 1. Explode 커널 실행 59 | DustManager.Instance.Explode(transform.position, explosionSqrRange, explosionForce); 60 | 61 | // 2. 폭발 프리팹 생성 62 | if (explosionPrefab != null) 63 | { 64 | GameObject clone = Instantiate(explosionPrefab, transform.position, Quaternion.identity); 65 | clone.SetActive(true); 66 | 67 | ParticleSystem ps = clone.GetComponent(); 68 | if (ps != null) 69 | { 70 | var mainModule = ps.main; 71 | mainModule.startSize = explosionParticleSize; 72 | } 73 | 74 | Destroy(clone, 2f); 75 | } 76 | 77 | Destroy(gameObject); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/CannonBall.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 25ef65d4b8c0c334a8bc482123204e1d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9a2886f952e8ecc469cff0fba7665367 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders/DustBoxCollider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-17 PM 5:33:04 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | public class DustBoxCollider : DustCollider 12 | { 13 | protected override void OnEnable() 14 | { 15 | base.OnEnable(); 16 | 17 | if (!TryGetComponent(out BoxCollider _)) 18 | gameObject.AddComponent(); 19 | 20 | dustManager.AddBoxCollider(this); 21 | } 22 | 23 | protected override void OnDisable() 24 | { 25 | base.OnDisable(); 26 | dustManager.RemoveBoxCollider(this); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders/DustBoxCollider.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0075c2057eb32ed4fa9a93f390352bc1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders/DustCollider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-13 PM 8:59:37 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// 먼지 월드와 동기화되는 충돌체 13 | /// 14 | public abstract class DustCollider : MonoBehaviour 15 | { 16 | public const string ColliderTag = "DustCollider"; 17 | protected DustManager dustManager; 18 | 19 | protected void Awake() 20 | { 21 | tag = ColliderTag; 22 | } 23 | 24 | protected virtual void OnEnable() 25 | { 26 | if (dustManager == null) 27 | dustManager = FindObjectOfType(); 28 | #if UNITY_EDITOR 29 | StartCoroutine(UpdateColliderDataRoutine()); 30 | #endif 31 | } 32 | 33 | protected virtual void OnDisable() 34 | { 35 | #if UNITY_EDITOR 36 | StopAllCoroutines(); 37 | #endif 38 | } 39 | 40 | #if UNITY_EDITOR 41 | private IEnumerator UpdateColliderDataRoutine() 42 | { 43 | yield return new WaitForEndOfFrame(); 44 | 45 | Vector3 prevPosition = transform.position; 46 | Vector3 prevScale = transform.lossyScale; 47 | Vector3 prevAngles = transform.eulerAngles; 48 | Vector3 position, eulerAngles, lossyScale; 49 | WaitForSeconds wfs = new WaitForSeconds(0.2f); 50 | 51 | while (true) 52 | { 53 | position = transform.position; 54 | eulerAngles = transform.eulerAngles; 55 | lossyScale = transform.lossyScale; 56 | 57 | // 위치나 크기에 변화가 생기면 정보 업데이트 58 | if (position != prevPosition || lossyScale != prevScale || eulerAngles != prevAngles) 59 | { 60 | dustManager.UpdateBoxCollider(); 61 | } 62 | 63 | prevPosition = position; 64 | prevAngles = eulerAngles; 65 | prevScale = lossyScale; 66 | yield return wfs; 67 | } 68 | } 69 | #endif 70 | } 71 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders/DustCollider.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e4858cc380d1b946bb8771503bd482b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders/DustSphereCollider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-12 AM 2:17:05 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// 컴퓨트 쉐이더 내에서 사용될 구체 콜라이더 13 | /// 14 | [DisallowMultipleComponent] 15 | public class DustSphereCollider : DustCollider 16 | { 17 | protected override void OnEnable() 18 | { 19 | base.OnEnable(); 20 | 21 | if (!TryGetComponent(out SphereCollider _)) 22 | gameObject.AddComponent(); 23 | 24 | dustManager.AddSphereCollider(this); 25 | } 26 | 27 | protected override void OnDisable() 28 | { 29 | base.OnDisable(); 30 | dustManager.RemoveSphereCollider(this); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Colliders/DustSphereCollider.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56ebc8caedfe125478818ba45e30d38c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b76a69c95aed79e428d85c5e877bf87b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/Cannon.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-13 PM 8:51:40 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// 대포 발사대 13 | /// 14 | public class Cannon : Cone 15 | { 16 | [Header("Cannon Options")] 17 | [SerializeField] private GameObject cannonBallPrefab; 18 | [SerializeField] private GameObject explosionPrefab; 19 | 20 | [Range(1, 200f)] 21 | [SerializeField] private float explosionRange = 25f; 22 | 23 | [Range(100f, 10000f)] 24 | [SerializeField] private float explosionForce = 3000f; 25 | 26 | [Range(0.1f, 2f)] 27 | [SerializeField] private float shootingInterval = 1f; 28 | 29 | private float currentCooldown = 0f; 30 | 31 | private void Update() 32 | { 33 | if (currentCooldown > 0f) 34 | currentCooldown -= Time.deltaTime; 35 | 36 | // 발사 37 | if (isRunning && currentCooldown <= 0f) 38 | { 39 | currentCooldown = shootingInterval; 40 | Shoot(); 41 | } 42 | } 43 | 44 | public void Shoot() 45 | { 46 | GameObject clone = Instantiate(cannonBallPrefab, transform.position, Quaternion.identity); 47 | CannonBall ball = clone.GetComponent(); 48 | 49 | ball.SetExplosionPrefab(explosionPrefab, explosionRange * 2f); 50 | ball.Shoot(transform.forward * force, explosionRange, explosionForce); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/Cannon.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 85aab8a7d46bbc34aadaf5459c2bd6fa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/Cone.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-05 PM 4:49:41 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | [DisallowMultipleComponent] 12 | public class Cone : MonoBehaviour 13 | { 14 | [SerializeField] protected Material coneMaterial; 15 | 16 | [Space] 17 | [SerializeField] protected bool isRunning = false; 18 | 19 | [Range(0f, 200f)] 20 | [SerializeField] protected float force = 50f; 21 | 22 | [Range(1f, 50f)] 23 | [SerializeField] protected float distance = 5f; 24 | 25 | [Range(0.01f, 89.9f)] 26 | [SerializeField] protected float angle = 45f; 27 | 28 | protected Transform coneTransform; 29 | protected GameObject coneGO; 30 | 31 | 32 | public bool IsRunning { get => isRunning; set => isRunning = value; } 33 | public float SqrDistance => distance * distance; 34 | public float Distance => distance; 35 | public float SqrForce => force * force; 36 | public float Force => force; 37 | public float AngleRad => angle * Mathf.Deg2Rad; 38 | 39 | 40 | protected virtual void Awake() 41 | { 42 | CreateCone(coneMaterial); 43 | } 44 | 45 | private void Update() 46 | { 47 | ChangeConeScale(); 48 | } 49 | 50 | public void ShowCone() => coneGO.SetActive(true); 51 | public void HideCone() => coneGO.SetActive(false); 52 | 53 | 54 | /// 옵션 변경에 따라 자식 스케일 변경 55 | private void ChangeConeScale() 56 | { 57 | float r = Mathf.Tan(angle * Mathf.Deg2Rad) * distance * 0.5f; 58 | float z = distance * 0.5f; 59 | 60 | coneTransform.localScale = new Vector3(r, r, z); 61 | } 62 | 63 | /// 자식 원뿔 생성 64 | protected void CreateCone(Material material) 65 | { 66 | coneGO = new GameObject("Cone Mesh"); 67 | coneTransform = coneGO.transform; 68 | coneTransform.SetParent(transform, false); 69 | 70 | MeshRenderer mr = coneGO.AddComponent(); 71 | mr.material = material; 72 | mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; 73 | mr.receiveShadows = false; 74 | 75 | MeshFilter mf = coneGO.AddComponent(); 76 | mf.sharedMesh = MeshMaker.CreateConeMesh(); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/Cone.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f47513ac57555b34dad2567e39593175 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/DustEmitter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-05 PM 4:33:25 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | public class DustEmitter : Cone 12 | { 13 | // 초당 발사되는 먼지 개수 14 | [SerializeField, Range(1000, 100000)] 15 | private int emissionPerSec = 1000; 16 | 17 | public int EmissionPerSec => emissionPerSec; 18 | } 19 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/DustEmitter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e644367b112d2f54486e9f468a25208f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/VacuumCleaner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-09-27 PM 3:13:42 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | public class VacuumCleaner : Cone 12 | { 13 | [Range(0.01f, 5f), Tooltip("먼지가 사망하는 영역 반지름")] 14 | [SerializeField] private float deathRange = 0.2f; 15 | 16 | [Space, Tooltip("먼지 제거 모드")] 17 | [SerializeField] private bool killMode = true; 18 | 19 | public float SqrDeathRange => deathRange * deathRange; 20 | public bool KillMode => killMode; 21 | } 22 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/Cones/VacuumCleaner.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8420e3c9cbe815242b4cf82600e6776c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/DustManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-09-26 PM 9:47:41 7 | // 작성자 : Rito 8 | // https://www.youtube.com/watch?v=PGk0rnyTa1U 9 | 10 | namespace Rito.MillionDust 11 | { 12 | using SF = UnityEngine.SerializeField; 13 | 14 | /*======================================================================*/ 15 | /* */ 16 | /* Fields & Unitey Events */ 17 | /* */ 18 | /*======================================================================*/ 19 | 20 | [DisallowMultipleComponent] 21 | public partial class DustManager : MonoBehaviour 22 | { 23 | // Singleton 24 | public static DustManager Instance => _instance; 25 | private static DustManager _instance; 26 | 27 | private struct Dust 28 | { 29 | public Vector3 position; 30 | public int isAlive; 31 | } 32 | 33 | [Header("Compute Shader")] 34 | [SF] private ComputeShader dustCompute; 35 | 36 | [Header("Dust")] 37 | [SF] private Mesh dustMesh; 38 | [SF] private Material dustMaterial; 39 | 40 | [Space(4f)] 41 | [SF] private int dustCount = 100000; // 생성할 먼지 개수 42 | [Range(0.01f, 2f)] 43 | [SF] private float dustScale = 1f; 44 | [Range(0.01f, 1f)] 45 | [SF] private float dustRadius = 1f; 46 | 47 | [Space(4f)] 48 | [SF] private Color dustColorA = Color.black; 49 | [SF] private Color dustColorB = Color.gray; 50 | 51 | [Header("Spawn")] 52 | [SF] private Vector3 spawnBottomCenter = new Vector3(0, 0, 0); // 분포 중심 하단 위치(피벗) 53 | [SF] private Vector3 spawnSize = new Vector3(100, 25, 100); // 분포 너비(XYZ) 54 | 55 | // 월드 큐브 콜라이더 56 | [Header("World")] 57 | [SF] private Vector3 worldBottomCenter = new Vector3(0, 0, 0); 58 | [SF] private Vector3 worldSize = new Vector3(100, 25, 100); 59 | [SF] private Material worldMaterial; 60 | 61 | [Header("Player")] 62 | [SF] private PlayerController controller; 63 | [SF] private VacuumCleaner cleaner; 64 | [SF] private Cone blower; 65 | [SF] private DustEmitter emitter; 66 | [SF] private Cannon cannon; 67 | 68 | [Header("Physics")] 69 | [Range(-20f, 20f)] 70 | [SF] private float gravityX = 0; 71 | 72 | [Range(-20f, 20f)] 73 | [SF] private float gravityY = -9.8f; 74 | 75 | [Range(-20f, 20f)] 76 | [SF] private float gravityZ = 0; 77 | 78 | [Space] 79 | [Range(0.01f, 20f)] 80 | [SF] private float mass = 1f; // 먼지 질량 81 | 82 | [Range(0f, 10f)] 83 | [SF] private float drag = 1f; // (공기) 저항력 84 | 85 | [Range(0f, 1f)] 86 | [SF] private float bounciness = 0.6f; // 충돌 탄성력 87 | 88 | [Header("Game")] 89 | [Range(0, 1f)] 90 | [SF] private float timescale = 1f; 91 | 92 | private ComputeBuffer dustBuffer; // 먼지 데이터 버퍼(위치, ...) 93 | private ComputeBuffer dustVelocityBuffer; // 먼지 현재 속도 버퍼 94 | private ComputeBuffer argsBuffer; // 먼지 렌더링 데이터 버퍼 95 | private ComputeBuffer aliveNumberBuffer; // 생존 먼지 개수 버퍼 96 | private ComputeBuffer dustColorBuffer; // 먼지 색상 버퍼 97 | private ComputeBuffer collisionFlagBuffer;// 충돌 처리 완료 여부 버퍼 98 | 99 | // Private Variables 100 | private uint[] aliveNumberArray; 101 | private int aliveNumber; 102 | private float deltaTime; 103 | private Bounds worldBounds; 104 | 105 | private GameObject worldGO; 106 | private MeshFilter worldMF; 107 | private MeshRenderer worldMR; 108 | 109 | // Inputs & Mode 110 | private KeyCode cleanerKey = KeyCode.Alpha1; 111 | private KeyCode blowerKey = KeyCode.Alpha2; 112 | private KeyCode emitterKey = KeyCode.Alpha3; 113 | private KeyCode cannonKey = KeyCode.Alpha4; 114 | 115 | private KeyCode operationKey = KeyCode.Mouse0; 116 | private KeyCode showCursorKey = KeyCode.Mouse1; 117 | private Cone currentCone; 118 | 119 | // Compute Shader Data 120 | private int kernelPopulate; 121 | private int kernelSetDustColors; 122 | private int kernelUpdate; 123 | private int kernelVacuumUp; 124 | private int kernelEmit; 125 | private int kernelBlow; 126 | private int kernelExplode; 127 | private int kernelGroupSizeX; 128 | 129 | // 게임 시작 시 초기화 작업 완료 후 처리 130 | private Queue afterInitJobQueue = new Queue(); 131 | 132 | private ColliderSet sphereColliderSet; 133 | private ColliderSet boxColliderSet; 134 | 135 | /*********************************************************************** 136 | * Unity Events 137 | ***********************************************************************/ 138 | #region . 139 | private void Awake() 140 | { 141 | _instance = this; 142 | } 143 | 144 | private void Start() 145 | { 146 | ClampDustCount(); 147 | InitCones(); 148 | 149 | InitKernels(); 150 | InitComputeShader(); 151 | InitComputeBuffers(); 152 | SetBuffersToShaders(); 153 | 154 | PopulateDusts(); 155 | SetDustColors(); 156 | InitWorldBounds(); 157 | InitColliders(); 158 | 159 | ProcessInitialJobs(); 160 | 161 | StartCoroutine(DetectDataChangesRoutine()); 162 | } 163 | 164 | /// 초기화 이전에 쌓인 작업들 처리 165 | private void ProcessInitialJobs() 166 | { 167 | while (afterInitJobQueue.Count > 0) 168 | afterInitJobQueue.Dequeue()?.Invoke(); 169 | afterInitJobQueue = null; 170 | } 171 | 172 | private void Update() 173 | { 174 | Time.timeScale = timescale; 175 | deltaTime = Time.deltaTime; 176 | 177 | HandlePlayerInputs(); 178 | UpdateCommonVariables(); 179 | UpdateVacuumCleaner(); 180 | UpdateEmitter(); 181 | UpdateBlower(); 182 | UpdatePhysics(); 183 | 184 | dustMaterial.SetFloat("_Scale", dustScale); 185 | Graphics.DrawMeshInstancedIndirect(dustMesh, 0, dustMaterial, worldBounds, argsBuffer); 186 | } 187 | 188 | private void OnDestroy() 189 | { 190 | if (dustBuffer != null) dustBuffer.Release(); 191 | if (argsBuffer != null) argsBuffer.Release(); 192 | if (aliveNumberBuffer != null) aliveNumberBuffer.Release(); 193 | if (dustVelocityBuffer != null) dustVelocityBuffer.Release(); 194 | if (dustColorBuffer != null) dustColorBuffer.Release(); 195 | if (collisionFlagBuffer != null) collisionFlagBuffer.Release(); 196 | } 197 | 198 | private GUIStyle boxStyle; 199 | private void OnGUI() 200 | { 201 | if (boxStyle == null) 202 | { 203 | boxStyle = new GUIStyle(GUI.skin.box); 204 | boxStyle.fontSize = 205 | #if UNITY_EDITOR 206 | 48; 207 | #else 208 | 24; 209 | #endif 210 | } 211 | 212 | float scWidth = Screen.width; 213 | float scHeight = Screen.height; 214 | Rect r = new Rect(scWidth * 0.04f, scHeight * 0.04f, scWidth * 0.25f, scHeight * 0.05f); 215 | 216 | GUI.Box(r, $"{aliveNumber:#,###,##0} / {dustCount:#,###,##0}", boxStyle); 217 | } 218 | 219 | private void OnDrawGizmos() 220 | { 221 | if (Application.isPlaying) return; 222 | 223 | CalculateWorldBounds(ref worldBounds); 224 | 225 | Gizmos.color = Color.cyan; 226 | Gizmos.DrawWireCube(worldBounds.center, worldBounds.size); 227 | } 228 | #endregion 229 | } 230 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/DustManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 64442c8b355ce0b42ad92d7b3c802e81 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/DustManager_Colliders.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-17 PM 4:20:57 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /*======================================================================*/ 12 | /* */ 13 | /* Colliders */ 14 | /* */ 15 | /*======================================================================*/ 16 | public partial class DustManager : MonoBehaviour 17 | { 18 | /*********************************************************************** 19 | * Class Definitions 20 | ***********************************************************************/ 21 | #region . 22 | private class ColliderSet 23 | { 24 | private struct ColliderData 25 | { 26 | public Matrix4x4 localToWorld; 27 | public Matrix4x4 worldToLocal; 28 | public Vector3 scale; 29 | 30 | public ColliderData(DustCollider collider) 31 | { 32 | localToWorld = collider.transform.localToWorldMatrix; 33 | worldToLocal = collider.transform.worldToLocalMatrix; 34 | scale = collider.transform.lossyScale; 35 | } 36 | } 37 | 38 | /* Collider */ 39 | private ComputeBuffer colliderBuffer; 40 | private List colliders; 41 | 42 | /* Data */ 43 | private ColliderData[] dataArray; 44 | private int dataCount; 45 | 46 | /* Compute Shader, Compute Buffer */ 47 | private ComputeShader computeShader; 48 | private int shaderKernel; // Update Kernel 49 | private string bufferName; 50 | private string countVariableName; 51 | 52 | public ColliderSet(ComputeShader computeShader, int shaderKernel, string bufferName, string countVariableName) 53 | { 54 | this.colliders = new List(4); 55 | this.dataArray = new ColliderData[4]; 56 | this.computeShader = computeShader; 57 | this.shaderKernel = shaderKernel; 58 | this.bufferName = bufferName; 59 | this.countVariableName = countVariableName; 60 | this.dataCount = 0; 61 | 62 | colliderBuffer = new ComputeBuffer(1, 4); // 기본 값 63 | computeShader.SetBuffer(shaderKernel, bufferName, colliderBuffer); 64 | computeShader.SetInt(countVariableName, 0); 65 | } 66 | 67 | ~ColliderSet() 68 | { 69 | ReleaseBuffer(); 70 | } 71 | 72 | private void ReleaseBuffer() 73 | { 74 | if (colliderBuffer != null) 75 | colliderBuffer.Release(); 76 | } 77 | 78 | private void ExpandDataArray() 79 | { 80 | ColliderData[] newArray = new ColliderData[this.dataArray.Length * 2]; 81 | Array.Copy(this.dataArray, newArray, this.dataArray.Length); 82 | this.dataArray = newArray; 83 | } 84 | 85 | /// 컴퓨트 버퍼의 데이터를 새롭게 갱신하고 컴퓨트 쉐이더에 전달 86 | private void ReallocateBuffer() 87 | { 88 | ReleaseBuffer(); 89 | if (dataCount == 0) return; 90 | 91 | colliderBuffer = new ComputeBuffer(dataCount, sizeof(float) * 35); 92 | computeShader.SetInt(countVariableName, dataCount); 93 | UpdateColliderData(); 94 | } 95 | 96 | /// 배열 내부의 콜라이더 데이터만 갱신하여 컴퓨트 쉐이더에 전달 97 | public void UpdateColliderData() 98 | { 99 | if (dataArray.Length < dataCount) 100 | ExpandDataArray(); 101 | 102 | for (int i = 0; i < dataCount; i++) 103 | { 104 | dataArray[i] = new ColliderData(colliders[i]); 105 | } 106 | 107 | colliderBuffer.SetData(dataArray, 0, 0, dataCount); 108 | computeShader.SetBuffer(shaderKernel, bufferName, colliderBuffer); 109 | } 110 | 111 | public void AddCollider(DustCollider collider) 112 | { 113 | if (colliders.Contains(collider)) return; 114 | 115 | dataCount++; 116 | colliders.Add(collider); 117 | ReallocateBuffer(); 118 | } 119 | 120 | public void RemoveCollider(DustCollider collider) 121 | { 122 | if (!colliders.Contains(collider)) return; 123 | 124 | dataCount--; 125 | colliders.Remove(collider); 126 | ReallocateBuffer(); 127 | } 128 | } 129 | #endregion 130 | /*********************************************************************** 131 | * Private Generic Methods 132 | ***********************************************************************/ 133 | #region . 134 | /// ColliderSet에 새로운 Collider 추가 135 | private void AddCollider(Func getter, DustCollider collider) 136 | { 137 | var colSet = getter(); 138 | 139 | if (colSet == null) 140 | { 141 | afterInitJobQueue.Enqueue(() => getter().AddCollider(collider)); 142 | } 143 | else 144 | { 145 | colSet.AddCollider(collider); 146 | } 147 | } 148 | 149 | /// ColliderSet의 내부 컴퓨트 버퍼 갱신 150 | private void UpdateCollider(ColliderSet set) 151 | { 152 | if (set != null) 153 | set.UpdateColliderData(); 154 | } 155 | 156 | /// ColliderSet에서 Collider 제거 157 | private void RemoveCollider(ColliderSet set, DustCollider collider) 158 | { 159 | if (set != null) 160 | set.RemoveCollider(collider); 161 | } 162 | #endregion 163 | /*********************************************************************** 164 | * Public Methods 165 | ***********************************************************************/ 166 | #region . 167 | public void AddSphereCollider(DustSphereCollider collider) 168 | { 169 | AddCollider(() => sphereColliderSet, collider); 170 | } 171 | public void UpdateSphereCollider() 172 | { 173 | UpdateCollider(sphereColliderSet); 174 | } 175 | public void RemoveSphereCollider(DustSphereCollider collider) 176 | { 177 | RemoveCollider(sphereColliderSet, collider); 178 | } 179 | 180 | public void AddBoxCollider(DustBoxCollider collider) 181 | { 182 | AddCollider(() => boxColliderSet, collider); 183 | } 184 | public void UpdateBoxCollider() 185 | { 186 | UpdateCollider(boxColliderSet); 187 | } 188 | public void RemoveBoxCollider(DustBoxCollider collider) 189 | { 190 | RemoveCollider(boxColliderSet, collider); 191 | } 192 | #endregion 193 | } 194 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/DustManager_Colliders.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 57ab279739bb13f44981dea3f063221f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/DustManager_Methods.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-17 PM 4:23:05 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /*======================================================================*/ 12 | /* */ 13 | /* Methods */ 14 | /* */ 15 | /*======================================================================*/ 16 | public partial class DustManager : MonoBehaviour 17 | { 18 | /*********************************************************************** 19 | * Private Methods 20 | ***********************************************************************/ 21 | #region . 22 | private void CalculateWorldBounds(ref Bounds worldBounds) 23 | { 24 | Vector3 boundsCenter = worldBottomCenter + Vector3.up * worldSize.y * 0.5f; 25 | worldBounds = new Bounds( 26 | boundsCenter, 27 | worldSize 28 | ); 29 | } 30 | private void ChangeCone(Cone next) 31 | { 32 | currentCone.HideCone(); 33 | currentCone = next; 34 | currentCone.ShowCone(); 35 | } 36 | 37 | /// 필드 변경사항 감지하여 적용 38 | private IEnumerator DetectDataChangesRoutine() 39 | { 40 | int oldDustCount = this.dustCount; 41 | Color oldDustColorA = this.dustColorA; 42 | Color oldDustColorB = this.dustColorB; 43 | Vector3 oldWorldPivot = this.worldBottomCenter; 44 | Vector3 oldWorldSize = this.worldSize; 45 | 46 | WaitForSeconds wfs = new WaitForSeconds(0.5f); 47 | while (true) 48 | { 49 | // 1. 먼지 개수 50 | if (oldDustCount != this.dustCount) 51 | { 52 | ClampDustCount(); 53 | InitComputeShader(); 54 | InitComputeBuffers(); 55 | SetBuffersToShaders(); 56 | PopulateDusts(); 57 | SetDustColors(); 58 | } 59 | // 2. 먼지 색상 60 | if (oldDustColorA != this.dustColorA || 61 | oldDustColorB != this.dustColorB) 62 | { 63 | SetDustColors(); 64 | } 65 | // 3. 월드 영역 66 | if (oldWorldPivot != this.worldBottomCenter || 67 | oldWorldSize != this.worldSize) 68 | { 69 | InitWorldBounds(); 70 | } 71 | 72 | // 이전 값 저장 73 | oldDustCount = this.dustCount; 74 | oldDustColorA = this.dustColorA; 75 | oldDustColorB = this.dustColorB; 76 | oldWorldPivot = this.worldBottomCenter; 77 | oldWorldSize = this.worldSize; 78 | yield return wfs; 79 | } 80 | } 81 | 82 | #endregion 83 | /*********************************************************************** 84 | * Init Methods 85 | ***********************************************************************/ 86 | #region . 87 | private void ClampDustCount() 88 | { 89 | dustCount = Mathf.Clamp(dustCount, 1, 1_000_000); 90 | } 91 | 92 | private void InitCones() 93 | { 94 | cleaner.HideCone(); 95 | emitter.HideCone(); 96 | blower.HideCone(); 97 | cannon.HideCone(); 98 | 99 | currentCone = cleaner; 100 | currentCone.ShowCone(); 101 | } 102 | 103 | private void InitKernels() 104 | { 105 | kernelPopulate = dustCompute.FindKernel("Populate"); 106 | kernelSetDustColors = dustCompute.FindKernel("SetDustColors"); 107 | kernelUpdate = dustCompute.FindKernel("Update"); 108 | kernelVacuumUp = dustCompute.FindKernel("VacuumUp"); 109 | kernelEmit = dustCompute.FindKernel("Emit"); 110 | kernelBlow = dustCompute.FindKernel("BlowWind"); 111 | kernelExplode = dustCompute.FindKernel("Explode"); 112 | } 113 | 114 | private void InitComputeShader() 115 | { 116 | dustCompute.GetKernelThreadGroupSizes(kernelUpdate, out uint tx, out _, out _); 117 | kernelGroupSizeX = Mathf.CeilToInt((float)dustCount / tx); 118 | 119 | dustCompute.SetInt("dustCount", dustCount); 120 | } 121 | 122 | /// 먼지 개수에 영향 받는 컴퓨트 버퍼들 생성 123 | private void InitComputeBuffers() 124 | { 125 | if (argsBuffer != null) argsBuffer.Release(); 126 | if (dustBuffer != null) dustBuffer.Release(); 127 | if (dustColorBuffer != null) dustColorBuffer.Release(); 128 | if (dustVelocityBuffer != null) dustVelocityBuffer.Release(); 129 | if (aliveNumberBuffer != null) aliveNumberBuffer.Release(); 130 | if (collisionFlagBuffer != null) collisionFlagBuffer.Release(); 131 | 132 | // Args Buffer 133 | int subMeshIndex = 0; 134 | uint[] argsData = new uint[] 135 | { 136 | (uint)dustMesh.GetIndexCount(subMeshIndex), 137 | (uint)dustCount, 138 | (uint)dustMesh.GetIndexStart(subMeshIndex), 139 | (uint)dustMesh.GetBaseVertex(subMeshIndex), 140 | 0 141 | }; 142 | 143 | argsBuffer = new ComputeBuffer(1, 5 * sizeof(uint), ComputeBufferType.IndirectArguments); 144 | argsBuffer.SetData(argsData); 145 | 146 | // Dust Buffer 147 | dustBuffer = new ComputeBuffer(dustCount, sizeof(float) * 3 + sizeof(int)); 148 | 149 | // Color Buffer 150 | dustColorBuffer = new ComputeBuffer(dustCount, sizeof(float) * 3); 151 | 152 | // Dust Velocity Buffer 153 | dustVelocityBuffer = new ComputeBuffer(dustCount, sizeof(float) * 3); 154 | 155 | // Alive Number Buffer 156 | aliveNumberBuffer = new ComputeBuffer(1, sizeof(uint)); 157 | aliveNumberArray = new uint[] { (uint)dustCount }; 158 | aliveNumberBuffer.SetData(aliveNumberArray); 159 | 160 | // Collision Flag Buffer 161 | collisionFlagBuffer = new ComputeBuffer(dustCount, 4); 162 | } 163 | 164 | /// 컴퓨트 버퍼들을 쉐이더에 할당 165 | private void SetBuffersToShaders() 166 | { 167 | dustMaterial.SetBuffer("_DustBuffer", dustBuffer); 168 | dustMaterial.SetBuffer("_DustColorBuffer", dustColorBuffer); 169 | 170 | dustCompute.SetBuffer(kernelPopulate, "dustBuffer", dustBuffer); 171 | 172 | dustCompute.SetBuffer(kernelSetDustColors, "dustColorBuffer", dustColorBuffer); 173 | //dustCompute.SetBuffer(kernelUpdate, "dustColorBuffer", dustColorBuffer); // For Debug 174 | 175 | dustCompute.SetBuffer(kernelUpdate, "dustBuffer", dustBuffer); 176 | dustCompute.SetBuffer(kernelUpdate, "velocityBuffer", dustVelocityBuffer); 177 | dustCompute.SetBuffer(kernelUpdate, "aliveNumberBuffer", aliveNumberBuffer); 178 | dustCompute.SetBuffer(kernelUpdate, "collisionFlagBuffer", collisionFlagBuffer); 179 | 180 | dustCompute.SetBuffer(kernelVacuumUp, "dustBuffer", dustBuffer); 181 | dustCompute.SetBuffer(kernelVacuumUp, "velocityBuffer", dustVelocityBuffer); 182 | dustCompute.SetBuffer(kernelVacuumUp, "aliveNumberBuffer", aliveNumberBuffer); 183 | 184 | dustCompute.SetBuffer(kernelEmit, "dustBuffer", dustBuffer); 185 | dustCompute.SetBuffer(kernelEmit, "velocityBuffer", dustVelocityBuffer); 186 | dustCompute.SetBuffer(kernelEmit, "aliveNumberBuffer", aliveNumberBuffer); 187 | 188 | dustCompute.SetBuffer(kernelBlow, "dustBuffer", dustBuffer); 189 | dustCompute.SetBuffer(kernelBlow, "velocityBuffer", dustVelocityBuffer); 190 | 191 | dustCompute.SetBuffer(kernelExplode, "dustBuffer", dustBuffer); 192 | dustCompute.SetBuffer(kernelExplode, "velocityBuffer", dustVelocityBuffer); 193 | } 194 | 195 | /// 먼지들을 영역 내의 무작위 위치에 생성 196 | private void PopulateDusts() 197 | { 198 | Vector3 spawnCenter = spawnBottomCenter + Vector3.up * spawnSize.y * 0.5f; 199 | Bounds spawnBounds = new Bounds(spawnCenter, spawnSize); 200 | 201 | dustCompute.SetVector("spawnBoundsMin", spawnBounds.min); 202 | dustCompute.SetVector("spawnBoundsMax", spawnBounds.max); 203 | dustCompute.Dispatch(kernelPopulate, kernelGroupSizeX, 1, 1); 204 | } 205 | 206 | /// 2가지 색상 사이의 무작위 색상을 먼지마다 설정 207 | private void SetDustColors() 208 | { 209 | dustCompute.SetVector("dustColorA", dustColorA); 210 | dustCompute.SetVector("dustColorB", dustColorB); 211 | dustCompute.Dispatch(kernelSetDustColors, kernelGroupSizeX, 1, 1); 212 | } 213 | 214 | /// 월드 영역 큐브 메시 생성 및 컴퓨트 쉐이더에 값 전달 215 | private void InitWorldBounds() 216 | { 217 | if (worldGO == null) worldGO = new GameObject("World"); 218 | if (worldMF == null) worldMF = worldGO.AddComponent(); 219 | if (worldMR == null) worldMR = worldGO.AddComponent(); 220 | 221 | worldGO.tag = DustCollider.ColliderTag; 222 | 223 | CalculateWorldBounds(ref worldBounds); 224 | 225 | worldMF.sharedMesh = MeshMaker.CreateWorldBoundsMesh(worldBounds); 226 | worldMR.sharedMaterial = worldMaterial; 227 | 228 | if (!worldGO.TryGetComponent(out MeshCollider col)) 229 | col = worldGO.AddComponent(); 230 | col.sharedMesh = worldMF.sharedMesh; 231 | 232 | dustCompute.SetVector("worldBoundsMin", worldBounds.min); 233 | dustCompute.SetVector("worldBoundsMax", worldBounds.max); 234 | } 235 | 236 | private void InitColliders() 237 | { 238 | sphereColliderSet = new ColliderSet( 239 | this.dustCompute, 240 | kernelUpdate, 241 | "sphereColliderBuffer", 242 | "sphereColliderCount" 243 | ); 244 | boxColliderSet = new ColliderSet( 245 | this.dustCompute, 246 | kernelUpdate, 247 | "boxColliderBuffer", 248 | "boxColliderCount" 249 | ); 250 | } 251 | 252 | #endregion 253 | /*********************************************************************** 254 | * Update Methods 255 | ***********************************************************************/ 256 | #region . 257 | /// 사용자 입력 처리 258 | private void HandlePlayerInputs() 259 | { 260 | // 모드 변경 261 | if (Input.GetKeyDown(cleanerKey)) ChangeCone(cleaner); 262 | else if (Input.GetKeyDown(blowerKey)) ChangeCone(blower); 263 | else if (Input.GetKeyDown(emitterKey)) ChangeCone(emitter); 264 | else if (Input.GetKeyDown(cannonKey)) ChangeCone(cannon); 265 | 266 | // 마우스 보이기 & 숨기기 267 | if (Input.GetKeyDown(showCursorKey)) 268 | controller.ShowCursorToggle(); 269 | 270 | // 동작 수행 271 | bool run = controller.MouseLocked && Input.GetKey(operationKey); 272 | cleaner.IsRunning = run && currentCone == cleaner; 273 | blower.IsRunning = run && currentCone == blower; 274 | emitter.IsRunning = run && currentCone == emitter; 275 | cannon.IsRunning = run && currentCone == cannon; 276 | } 277 | 278 | /// 컴퓨트 쉐이더 공통 변수들 업데이트 279 | private void UpdateCommonVariables() 280 | { 281 | dustCompute.SetFloat("deltaTime", deltaTime); 282 | 283 | // 컨트롤러 284 | dustCompute.SetVector("controllerPos", controller.Position); 285 | dustCompute.SetVector("controllerForward", controller.Forward); 286 | 287 | // 물리 288 | dustCompute.SetVector("gravity", new Vector3(gravityX, gravityY, gravityZ)); 289 | dustCompute.SetFloat("radius", dustRadius); 290 | dustCompute.SetFloat("mass", mass); 291 | dustCompute.SetFloat("drag", drag); 292 | dustCompute.SetFloat("bounciness", bounciness); 293 | } 294 | 295 | /// 청소기 커널 실행 296 | private void UpdateVacuumCleaner() 297 | { 298 | if (!cleaner.IsRunning) return; 299 | 300 | dustCompute.SetFloat("cleanerSqrForce", cleaner.SqrForce); 301 | dustCompute.SetFloat("cleanerSqrDist", cleaner.SqrDistance); 302 | dustCompute.SetFloat("cleanerSqrDeathRange", cleaner.SqrDeathRange); 303 | dustCompute.SetFloat("cleanerDotThreshold", Mathf.Cos(cleaner.AngleRad)); 304 | dustCompute.SetBool("cleanerKillOn", cleaner.KillMode); 305 | 306 | dustCompute.Dispatch(kernelVacuumUp, kernelGroupSizeX, 1, 1); 307 | } 308 | 309 | /// 방출기 커널 실행 310 | private void UpdateEmitter() 311 | { 312 | if (!emitter.IsRunning) return; 313 | 314 | dustCompute.SetFloat("time", Time.time); 315 | dustCompute.SetMatrix("controllerMatrix", controller.LocalToWorld); 316 | dustCompute.SetFloat("emitterForce", emitter.Force); 317 | dustCompute.SetFloat("emitterDist", emitter.Distance); 318 | dustCompute.SetFloat("emitterAngleRad", emitter.AngleRad); 319 | dustCompute.SetInt("emissionPerSec", emitter.EmissionPerSec); 320 | 321 | dustCompute.Dispatch(kernelEmit, kernelGroupSizeX, 1, 1); 322 | } 323 | 324 | /// 송풍기 커널 실행 325 | private void UpdateBlower() 326 | { 327 | if (!blower.IsRunning) return; 328 | 329 | dustCompute.SetFloat("blowerSqrForce", blower.SqrForce); 330 | dustCompute.SetFloat("blowerSqrDist", blower.SqrDistance); 331 | dustCompute.SetFloat("blowerDotThreshold", Mathf.Cos(blower.AngleRad)); 332 | 333 | dustCompute.Dispatch(kernelBlow, kernelGroupSizeX, 1, 1); 334 | } 335 | 336 | /// 물리 업데이트 337 | private void UpdatePhysics() 338 | { 339 | dustCompute.Dispatch(kernelUpdate, kernelGroupSizeX, 1, 1); 340 | 341 | aliveNumberBuffer.GetData(aliveNumberArray); 342 | aliveNumber = (int)aliveNumberArray[0]; 343 | } 344 | #endregion 345 | /*********************************************************************** 346 | * Public Methods 347 | ***********************************************************************/ 348 | #region . 349 | 350 | /// Explode(폭발) 커널 실행 351 | public void Explode(in Vector3 position, in float sqrRange, in float force) 352 | { 353 | dustCompute.SetVector("explosionPosition", position); 354 | dustCompute.SetFloat("explosionSqrRange", sqrRange); 355 | dustCompute.SetFloat("explosionForce", force); 356 | dustCompute.Dispatch(kernelExplode, kernelGroupSizeX, 1, 1); 357 | } 358 | 359 | #endregion 360 | } 361 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/DustManager_Methods.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6fbd8356dfe16d144a0682c3388d2c87 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Editor Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 24efb6bdfdbd7084a9706a9c7c5d67af 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Editor Scripts/EditorHierarchyIconHelper.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | using UnityEditor; 7 | using System; 8 | 9 | // 날짜 : 2021-10-25 AM 2:27:00 10 | // 작성자 : Rito 11 | 12 | namespace Rito.MillionDust 13 | { 14 | /// 15 | /// 16 | /// 17 | public static class EditorHierarchyIconHelper 18 | { 19 | [UnityEditor.InitializeOnLoadMethod] 20 | private static void ApplyHierarchyIcon() 21 | { 22 | if (GameObject.FindObjectOfType() == null) 23 | return; 24 | 25 | if (iconData == null || iconData.Length == 0) 26 | InitIconData(); 27 | 28 | UnityEditor.EditorApplication.hierarchyWindowItemOnGUI += DrawHierarchyIcon; 29 | } 30 | 31 | private static (Type type, Texture icon, Color color)[] iconData; 32 | 33 | private static void InitIconData() 34 | { 35 | Texture boxCollider = EditorGUIUtility.IconContent("d_BoxCollider Icon").image; 36 | Texture sphereCollider = EditorGUIUtility.IconContent("d_SphereCollider Icon").image; 37 | 38 | iconData = new (Type, Texture, Color)[] 39 | { 40 | (typeof(DustManager), EditorGUIUtility.FindTexture("GameManager Icon"), Color.magenta), 41 | (typeof(Cone), EditorGUIUtility.FindTexture("d_Favorite On Icon"), Color.yellow), 42 | (typeof(Camera), EditorGUIUtility.FindTexture("Camera Gizmo"), Color.cyan), 43 | (typeof(DustBoxCollider), boxCollider, Color.white), 44 | (typeof(DustSphereCollider), sphereCollider, Color.white), 45 | }; 46 | } 47 | 48 | private static void DrawHierarchyIcon(int instanceID, Rect selectionRect) 49 | { 50 | Rect iconRect = new Rect(selectionRect); 51 | iconRect.x = 32f; // 하이라키 좌측 끝 52 | iconRect.width = 16f; 53 | 54 | GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject; 55 | if (go == null) 56 | return; 57 | 58 | Color c = GUI.color; 59 | 60 | for (int i = 0; i < iconData.Length; i++) 61 | { 62 | ref var current = ref iconData[i]; 63 | if (current.icon != null && go.GetComponent(current.type) != null) 64 | { 65 | GUI.color = go.activeInHierarchy ? current.color : Color.white * 0.5f; 66 | GUI.DrawTexture(iconRect, current.icon); 67 | break; 68 | } 69 | } 70 | 71 | GUI.color = c; 72 | } 73 | } 74 | } 75 | 76 | #endif -------------------------------------------------------------------------------- /Million Dust/Scripts/Editor Scripts/EditorHierarchyIconHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ef95bcb3cc2b5a4abab7a3ea9232fd9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/Editor Scripts/EditorTagHelper.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | using UnityEditor; 7 | using System; 8 | 9 | // 날짜 : 2021-10-15 PM 6:28:21 10 | // 작성자 : Rito 11 | 12 | namespace Rito.MillionDust 13 | { 14 | public static class EditorTagHelper 15 | { 16 | private static bool isPlaymode = false; 17 | 18 | [InitializeOnEnterPlayMode] 19 | private static void OnEnterPlayMode() 20 | { 21 | isPlaymode = true; 22 | } 23 | 24 | [InitializeOnLoadMethod] 25 | private static void OnLoadMethod() 26 | { 27 | if (isPlaymode) return; 28 | 29 | AddNewTag(DustCollider.ColliderTag); 30 | } 31 | 32 | /// 태그 중복 확인 및 추가 33 | public static void AddNewTag(string tagName) 34 | { 35 | SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]); 36 | SerializedProperty tagsProp = tagManager.FindProperty("tags"); 37 | 38 | int tagCount = tagsProp.arraySize; 39 | 40 | // [1] 해당 태그가 존재하는지 확인 41 | bool found = false; 42 | for (int i = 0; i < tagCount; i++) 43 | { 44 | SerializedProperty t = tagsProp.GetArrayElementAtIndex(i); 45 | 46 | if (t.stringValue.Equals(tagName)) 47 | { 48 | found = true; 49 | break; 50 | } 51 | } 52 | 53 | // [2] 배열 마지막에 태그 추가 54 | if (!found) 55 | { 56 | tagsProp.InsertArrayElementAtIndex(tagCount); 57 | SerializedProperty n = tagsProp.GetArrayElementAtIndex(tagCount); 58 | n.stringValue = tagName; 59 | tagManager.ApplyModifiedProperties(); 60 | } 61 | } 62 | } 63 | } 64 | #endif -------------------------------------------------------------------------------- /Million Dust/Scripts/Editor Scripts/EditorTagHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3f33d227afaba64399e87fa473f6532 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/MeshMaker.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-07 PM 4:41:16 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// 메시 생성 담당 정적 클래스 13 | /// 14 | public static class MeshMaker 15 | { 16 | /// 원뿔 모양 메시 생성 17 | public static Mesh CreateConeMesh(int sample = 24) 18 | { 19 | Mesh mesh = new Mesh(); 20 | Vector3[] verts = new Vector3[sample + 1]; 21 | int[] tris = new int[sample * 3]; 22 | 23 | verts[0] = Vector3.zero; // 꼭짓점 24 | float deltaRad = Mathf.PI * 2f / sample; 25 | for (int i = 1; i <= sample; i++) 26 | { 27 | float r = i * deltaRad; 28 | verts[i] = new Vector3(Mathf.Cos(r), Mathf.Sin(r), 1f); 29 | } 30 | 31 | int t = 0; 32 | for (int i = 1; i < sample; i++) 33 | { 34 | tris[t] = 0; 35 | tris[t + 1] = i + 1; 36 | tris[t + 2] = i; 37 | t += 3; 38 | } 39 | tris[t] = 0; 40 | tris[t + 1] = 1; 41 | tris[t + 2] = sample; 42 | 43 | mesh.vertices = verts; 44 | mesh.triangles = tris; 45 | mesh.RecalculateNormals(); 46 | mesh.RecalculateBounds(); 47 | 48 | return mesh; 49 | } 50 | 51 | /// 면이 내부를 향하는 큐브 생성 52 | public static Mesh CreateWorldBoundsMesh(in Bounds bounds) 53 | { 54 | Vector3 m = bounds.min; 55 | Vector3 M = bounds.max; 56 | 57 | // Top 58 | Vector3 _0 = m.X_Z() + M._Y_(); 59 | Vector3 _1 = m.X__() + M._YZ(); 60 | Vector3 _2 = M; 61 | Vector3 _3 = m.__Z() + M.XY_(); 62 | // Bottom 63 | Vector3 _4 = m; 64 | Vector3 _5 = m.XY_() + M.__Z(); 65 | Vector3 _6 = m._Y_() + M.X_Z(); 66 | Vector3 _7 = m._YZ() + M.X__(); 67 | 68 | /* Vertices */ 69 | const int SizeV = 8 * 3; 70 | Vector3[] V = new Vector3[SizeV]; 71 | int i = 0; 72 | V[i++] = _0; V[i++] = _5; V[i++] = _4; V[i++] = _1; // Left 73 | V[i++] = _1; V[i++] = _6; V[i++] = _5; V[i++] = _2; // Forward 74 | V[i++] = _2; V[i++] = _7; V[i++] = _6; V[i++] = _3; // Right 75 | V[i++] = _3; V[i++] = _4; V[i++] = _7; V[i++] = _0; // Back 76 | V[i++] = _0; V[i++] = _2; V[i++] = _1; V[i++] = _3; // Top 77 | V[i++] = _5; V[i++] = _7; V[i++] = _4; V[i++] = _6; // Bottom 78 | 79 | /* Triangles */ 80 | const int SizeT = 6 * 2 * 3; 81 | int[] T = new int[SizeT]; 82 | for (i = 0; i < 6; i++) 83 | { 84 | int t = i * 6; 85 | int v = i * 4; 86 | T[t + 0] = v + 0; 87 | T[t + 1] = v + 1; 88 | T[t + 2] = v + 2; 89 | T[t + 3] = v + 0; 90 | T[t + 4] = v + 3; 91 | T[t + 5] = v + 1; 92 | } 93 | 94 | /* Colors */ 95 | Color[] C = new Color[SizeV]; 96 | Color gray = new Color(0.5f, 0.5f, 0.5f, 1f); 97 | Color grayDelta = new Color(0.05f, 0.05f, 0.05f, 0f); 98 | int[] D = { 0, 1, 0, 1, 2, 2 }; // Left, Forward, Right, Back, Top, Bot 99 | 100 | for (i = 0; i < 6; i++) 101 | { 102 | for(int j = 0; j < 4; j++) 103 | C[i * 4 + j] = gray + grayDelta * D[i]; 104 | } 105 | 106 | Mesh mesh = new Mesh(); 107 | mesh.vertices = V; 108 | mesh.triangles = T; 109 | mesh.colors = C; 110 | 111 | mesh.RecalculateBounds(); 112 | mesh.RecalculateNormals(); 113 | 114 | return mesh; 115 | } 116 | 117 | private static Vector3 X__(in this Vector3 vec) => new Vector3(vec.x, 0f, 0f); 118 | private static Vector3 _Y_(in this Vector3 vec) => new Vector3(0f, vec.y, 0f); 119 | private static Vector3 __Z(in this Vector3 vec) => new Vector3(0, 0f, vec.z); 120 | private static Vector3 XY_(in this Vector3 vec) => new Vector3(vec.x, vec.y, 0f); 121 | private static Vector3 _YZ(in this Vector3 vec) => new Vector3(0f, vec.y, vec.z); 122 | private static Vector3 X_Z(in this Vector3 vec) => new Vector3(vec.x, 0f, vec.z); 123 | } 124 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/MeshMaker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e09447d45d3df4409dae530aa65f873 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/MinMaxBounds.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-17 PM 7:29:16 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// Box Collider를 위한 Min-Max 데이터 13 | /// 14 | public struct MinMaxBounds 15 | { 16 | public Vector3 min; 17 | public Vector3 max; 18 | 19 | public static MinMaxBounds FromBounds(in Bounds bounds) 20 | { 21 | MinMaxBounds mmb = default; 22 | mmb.min = bounds.min; 23 | mmb.max = bounds.max; 24 | return mmb; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/MinMaxBounds.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d76dcd945e7c11048b498cab85ad3d2b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Scripts/PlayerController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | // 날짜 : 2021-10-05 PM 4:33:57 7 | // 작성자 : Rito 8 | 9 | namespace Rito.MillionDust 10 | { 11 | /// 12 | /// 13 | /// 14 | public class PlayerController : MonoBehaviour 15 | { 16 | [Range(0.01f, 100f)] 17 | [SerializeField] private float moveSpeed = 25f; 18 | 19 | private Transform parent; 20 | private float deltaTime; 21 | private bool mouseLocked = false; 22 | 23 | public bool MouseLocked => mouseLocked; 24 | public Vector3 Position => transform.position; 25 | public Vector3 Forward => transform.forward; 26 | public Matrix4x4 LocalToWorld => transform.localToWorldMatrix; 27 | 28 | private void Awake() 29 | { 30 | parent = transform.parent; 31 | } 32 | 33 | private void Update() 34 | { 35 | deltaTime = Time.unscaledDeltaTime; 36 | 37 | if (mouseLocked) 38 | { 39 | Move(); 40 | Rotate(); 41 | } 42 | } 43 | 44 | // 마우스 보이기/숨기기 45 | public void ShowCursorToggle() 46 | { 47 | mouseLocked ^= true; 48 | Cursor.lockState = mouseLocked ? CursorLockMode.Locked : CursorLockMode.None; 49 | Cursor.visible = !mouseLocked; 50 | } 51 | 52 | private void Move() 53 | { 54 | float x = Input.GetAxisRaw("Horizontal"); 55 | float z = Input.GetAxisRaw("Vertical"); 56 | float y = 0f; 57 | if (Input.GetKey(KeyCode.Space)) y += .5f; 58 | else if (Input.GetKey(KeyCode.LeftControl)) y -= .5f; 59 | 60 | Vector3 moveVec = new Vector3(x, y, z).normalized * moveSpeed; 61 | 62 | if (Input.GetKey(KeyCode.LeftShift)) 63 | moveVec *= 2f; 64 | 65 | parent.Translate(moveVec * deltaTime, Space.Self); 66 | } 67 | 68 | private void Rotate() 69 | { 70 | float v = Input.GetAxisRaw("Mouse X") * deltaTime * 100f; 71 | float h = Input.GetAxisRaw("Mouse Y") * deltaTime * 100f; 72 | 73 | // 부모 : 좌우 회전 74 | parent.localRotation *= Quaternion.Euler(0, v, 0); 75 | 76 | // 상하 회전 77 | Vector3 eRot = transform.localEulerAngles; 78 | float nextX = eRot.x - h; 79 | if (nextX > 180f) nextX -= 360f; 80 | if (-90f < nextX && nextX < 90f) 81 | { 82 | eRot.x = nextX; 83 | } 84 | transform.localEulerAngles = eRot; 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Million Dust/Scripts/PlayerController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2f964c94709560498e70c4db562fa43 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Million Dust/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f64dc2a5c497dd841bcab759a1279c85 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Box Collider.shader: -------------------------------------------------------------------------------- 1 | // Made with Amplify Shader Editor 2 | // Available at the Unity Asset Store - http://u3d.as/y3X 3 | Shader "Rito/Box Collider" 4 | { 5 | Properties 6 | { 7 | _Width("Width", Range( 0 , 1)) = 0.2 8 | _Power("Power", Range( 0 , 8)) = 1 9 | _Smoothness("Smoothness", Range( 0 , 1)) = 0.2 10 | [HDR]_Color("Color", Color) = (1,1,1,0) 11 | [Space(6)]_Intersection1("Intersection", Range( 0 , 1)) = 0.1 12 | _IntersectionIntensity("Intersection Intensity", Range( 0 , 1)) = 1 13 | [HideInInspector] _texcoord( "", 2D ) = "white" {} 14 | [HideInInspector] __dirty( "", Int ) = 1 15 | } 16 | 17 | SubShader 18 | { 19 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+0" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" "IsEmissive" = "true" } 20 | Cull Back 21 | CGPROGRAM 22 | #include "UnityCG.cginc" 23 | #pragma target 3.0 24 | #pragma multi_compile_instancing 25 | #pragma surface surf Unlit alpha:fade keepalpha noshadow noambient novertexlights nolightmap nodynlightmap nodirlightmap nofog nometa noforwardadd 26 | struct Input 27 | { 28 | float2 uv_texcoord; 29 | float4 screenPos; 30 | }; 31 | 32 | uniform float4 _Color; 33 | uniform float _Width; 34 | uniform float _Smoothness; 35 | uniform float _Power; 36 | uniform float _Intersection1; 37 | UNITY_DECLARE_DEPTH_TEXTURE( _CameraDepthTexture ); 38 | uniform float4 _CameraDepthTexture_TexelSize; 39 | uniform float _IntersectionIntensity; 40 | 41 | inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten ) 42 | { 43 | return half4 ( 0, 0, 0, s.Alpha ); 44 | } 45 | 46 | void surf( Input i , inout SurfaceOutput o ) 47 | { 48 | o.Emission = _Color.rgb; 49 | float temp_output_14_0 = ( 0.5 * ( 1.0 - _Width ) ); 50 | float2 temp_cast_1 = (temp_output_14_0).xx; 51 | float2 temp_cast_2 = (( temp_output_14_0 + _Smoothness )).xx; 52 | float2 temp_cast_3 = (0.5).xx; 53 | float2 smoothstepResult10 = smoothstep( temp_cast_1 , temp_cast_2 , abs( ( i.uv_texcoord - temp_cast_3 ) )); 54 | float2 break9 = smoothstepResult10; 55 | float4 ase_screenPos = float4( i.screenPos.xyz , i.screenPos.w + 0.00000000001 ); 56 | float4 ase_screenPosNorm = ase_screenPos / ase_screenPos.w; 57 | ase_screenPosNorm.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? ase_screenPosNorm.z : ase_screenPosNorm.z * 0.5 + 0.5; 58 | float eyeDepth22 = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE( _CameraDepthTexture, ase_screenPosNorm.xy )); 59 | o.Alpha = ( pow( saturate( ( break9.x + break9.y ) ) , _Power ) + ( saturate( ( ( _Intersection1 + ase_screenPos.w ) - eyeDepth22 ) ) * _IntersectionIntensity ) ); 60 | } 61 | 62 | ENDCG 63 | } 64 | CustomEditor "ASEMaterialInspector" 65 | } 66 | /*ASEBEGIN 67 | Version=18900 68 | 332;127;1468;851;1597.098;359.562;1.388757;True;False 69 | Node;AmplifyShaderEditor.RangedFloatNode;7;-1603.588,235.9653;Inherit;False;Property;_Width;Width;0;0;Create;True;0;0;0;False;0;False;0.2;0.2900154;0;1;0;1;FLOAT;0 70 | Node;AmplifyShaderEditor.RangedFloatNode;4;-1340.788,133.4654;Inherit;False;Constant;_05;0.5;0;0;Create;True;0;0;0;False;0;False;0.5;0;0;0;0;1;FLOAT;0 71 | Node;AmplifyShaderEditor.TexCoordVertexDataNode;2;-1388.187,4.165368;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 72 | Node;AmplifyShaderEditor.OneMinusNode;16;-1341.011,240.7824;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0 73 | Node;AmplifyShaderEditor.RangedFloatNode;12;-1324.388,317.1655;Inherit;False;Property;_Smoothness;Smoothness;2;0;Create;True;0;0;0;False;0;False;0.2;0.263312;0;1;0;1;FLOAT;0 74 | Node;AmplifyShaderEditor.SimpleSubtractOpNode;3;-1187.788,34.46539;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0 75 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;14;-1188.41,215.4825;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 76 | Node;AmplifyShaderEditor.AbsOpNode;5;-1057.788,34.46539;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0 77 | Node;AmplifyShaderEditor.SimpleAddOpNode;11;-1033.088,250.7654;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 78 | Node;AmplifyShaderEditor.SmoothstepOpNode;10;-869.7918,35.4654;Inherit;True;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;1,0;False;1;FLOAT2;0 79 | Node;AmplifyShaderEditor.RangedFloatNode;21;-828.5166,333.6688;Inherit;False;Property;_Intersection1;Intersection;4;0;Create;True;0;0;0;False;1;Space(6);False;0.1;0;0;1;0;1;FLOAT;0 80 | Node;AmplifyShaderEditor.ScreenPosInputsNode;20;-756.5873,437.3288;Float;False;1;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 81 | Node;AmplifyShaderEditor.BreakToComponentsNode;9;-654.7916,34.46542;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15 82 | Node;AmplifyShaderEditor.ScreenDepthNode;22;-761.5873,604.3288;Inherit;False;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0 83 | Node;AmplifyShaderEditor.SimpleAddOpNode;23;-554.5874,431.3288;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 84 | Node;AmplifyShaderEditor.SimpleAddOpNode;8;-544.0532,37.29102;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 85 | Node;AmplifyShaderEditor.SimpleSubtractOpNode;24;-431.5877,473.3288;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 86 | Node;AmplifyShaderEditor.SaturateNode;25;-306.5878,473.3288;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0 87 | Node;AmplifyShaderEditor.SaturateNode;13;-433.9412,37.94273;Inherit;True;1;0;FLOAT;0;False;1;FLOAT;0 88 | Node;AmplifyShaderEditor.RangedFloatNode;18;-524.7607,262.4853;Inherit;False;Property;_Power;Power;1;0;Create;True;0;0;0;False;0;False;1;0;0;8;0;1;FLOAT;0 89 | Node;AmplifyShaderEditor.RangedFloatNode;28;-444.4302,580.6263;Inherit;False;Property;_IntersectionIntensity;Intersection Intensity;5;0;Create;True;0;0;0;False;0;False;1;0;0;1;0;1;FLOAT;0 90 | Node;AmplifyShaderEditor.PowerNode;17;-212.1318,99.91827;Inherit;True;False;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0 91 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;27;-125.0159,476.4697;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 92 | Node;AmplifyShaderEditor.SimpleAddOpNode;26;31.91321,191.7743;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 93 | Node;AmplifyShaderEditor.ColorNode;19;-187.8065,-78.10121;Inherit;False;Property;_Color;Color;3;1;[HDR];Create;True;0;0;0;False;0;False;1,1,1,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 94 | Node;AmplifyShaderEditor.StandardSurfaceOutputNode;0;157.6002,-95.39728;Float;False;True;-1;2;ASEMaterialInspector;0;0;Unlit;Rito/Box Collider;False;False;False;False;True;True;True;True;True;True;True;True;False;False;True;True;True;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Transparent;0.5;True;False;0;False;Transparent;;Transparent;All;14;all;True;True;True;True;0;False;-1;False;1;False;-1;255;False;-1;255;False;-1;6;False;-1;3;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;False;2;5;False;-1;10;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;-1;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 95 | WireConnection;16;0;7;0 96 | WireConnection;3;0;2;0 97 | WireConnection;3;1;4;0 98 | WireConnection;14;0;4;0 99 | WireConnection;14;1;16;0 100 | WireConnection;5;0;3;0 101 | WireConnection;11;0;14;0 102 | WireConnection;11;1;12;0 103 | WireConnection;10;0;5;0 104 | WireConnection;10;1;14;0 105 | WireConnection;10;2;11;0 106 | WireConnection;9;0;10;0 107 | WireConnection;23;0;21;0 108 | WireConnection;23;1;20;4 109 | WireConnection;8;0;9;0 110 | WireConnection;8;1;9;1 111 | WireConnection;24;0;23;0 112 | WireConnection;24;1;22;0 113 | WireConnection;25;0;24;0 114 | WireConnection;13;0;8;0 115 | WireConnection;17;0;13;0 116 | WireConnection;17;1;18;0 117 | WireConnection;27;0;25;0 118 | WireConnection;27;1;28;0 119 | WireConnection;26;0;17;0 120 | WireConnection;26;1;27;0 121 | WireConnection;0;2;19;0 122 | WireConnection;0;9;26;0 123 | ASEEND*/ 124 | //CHKSM=84897BC7FEAF1D2D26BA6119F44AAEFE6DBB43C7 -------------------------------------------------------------------------------- /Million Dust/Shaders/Box Collider.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 261c33ee91f9f5a4dac3a2603b4e447f 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Cannon Ball.shader: -------------------------------------------------------------------------------- 1 | // Made with Amplify Shader Editor 2 | // Available at the Unity Asset Store - http://u3d.as/y3X 3 | Shader "Rito/Cannon Ball" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,0) 8 | _FresnelPower("Fresnel Power", Range( 0 , 10)) = 5 9 | _FresnelIntensity("Fresnel Intensity", Range( 0 , 10)) = 1 10 | [HideInInspector] __dirty( "", Int ) = 1 11 | } 12 | 13 | SubShader 14 | { 15 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+0" "IgnoreProjector" = "True" "IsEmissive" = "true" } 16 | Cull Back 17 | CGINCLUDE 18 | #include "UnityPBSLighting.cginc" 19 | #include "Lighting.cginc" 20 | #pragma target 3.0 21 | struct Input 22 | { 23 | float3 worldPos; 24 | float3 worldNormal; 25 | }; 26 | 27 | uniform float4 _Color; 28 | uniform float _FresnelIntensity; 29 | uniform float _FresnelPower; 30 | 31 | inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten ) 32 | { 33 | return half4 ( 0, 0, 0, s.Alpha ); 34 | } 35 | 36 | void surf( Input i , inout SurfaceOutput o ) 37 | { 38 | o.Emission = _Color.rgb; 39 | float3 ase_worldPos = i.worldPos; 40 | float3 ase_worldViewDir = normalize( UnityWorldSpaceViewDir( ase_worldPos ) ); 41 | float3 ase_worldNormal = i.worldNormal; 42 | float fresnelNdotV1 = dot( ase_worldNormal, ase_worldViewDir ); 43 | float fresnelNode1 = ( 0.0 + _FresnelIntensity * pow( 1.0 - fresnelNdotV1, _FresnelPower ) ); 44 | o.Alpha = fresnelNode1; 45 | } 46 | 47 | ENDCG 48 | CGPROGRAM 49 | #pragma surface surf Unlit alpha:fade keepalpha fullforwardshadows 50 | 51 | ENDCG 52 | Pass 53 | { 54 | Name "ShadowCaster" 55 | Tags{ "LightMode" = "ShadowCaster" } 56 | ZWrite On 57 | CGPROGRAM 58 | #pragma vertex vert 59 | #pragma fragment frag 60 | #pragma target 3.0 61 | #pragma multi_compile_shadowcaster 62 | #pragma multi_compile UNITY_PASS_SHADOWCASTER 63 | #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2 64 | #include "HLSLSupport.cginc" 65 | #if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN ) 66 | #define CAN_SKIP_VPOS 67 | #endif 68 | #include "UnityCG.cginc" 69 | #include "Lighting.cginc" 70 | #include "UnityPBSLighting.cginc" 71 | sampler3D _DitherMaskLOD; 72 | struct v2f 73 | { 74 | V2F_SHADOW_CASTER; 75 | float3 worldPos : TEXCOORD1; 76 | float3 worldNormal : TEXCOORD2; 77 | UNITY_VERTEX_INPUT_INSTANCE_ID 78 | UNITY_VERTEX_OUTPUT_STEREO 79 | }; 80 | v2f vert( appdata_full v ) 81 | { 82 | v2f o; 83 | UNITY_SETUP_INSTANCE_ID( v ); 84 | UNITY_INITIALIZE_OUTPUT( v2f, o ); 85 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO( o ); 86 | UNITY_TRANSFER_INSTANCE_ID( v, o ); 87 | float3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz; 88 | half3 worldNormal = UnityObjectToWorldNormal( v.normal ); 89 | o.worldNormal = worldNormal; 90 | o.worldPos = worldPos; 91 | TRANSFER_SHADOW_CASTER_NORMALOFFSET( o ) 92 | return o; 93 | } 94 | half4 frag( v2f IN 95 | #if !defined( CAN_SKIP_VPOS ) 96 | , UNITY_VPOS_TYPE vpos : VPOS 97 | #endif 98 | ) : SV_Target 99 | { 100 | UNITY_SETUP_INSTANCE_ID( IN ); 101 | Input surfIN; 102 | UNITY_INITIALIZE_OUTPUT( Input, surfIN ); 103 | float3 worldPos = IN.worldPos; 104 | half3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) ); 105 | surfIN.worldPos = worldPos; 106 | surfIN.worldNormal = IN.worldNormal; 107 | SurfaceOutput o; 108 | UNITY_INITIALIZE_OUTPUT( SurfaceOutput, o ) 109 | surf( surfIN, o ); 110 | #if defined( CAN_SKIP_VPOS ) 111 | float2 vpos = IN.pos; 112 | #endif 113 | half alphaRef = tex3D( _DitherMaskLOD, float3( vpos.xy * 0.25, o.Alpha * 0.9375 ) ).a; 114 | clip( alphaRef - 0.01 ); 115 | SHADOW_CASTER_FRAGMENT( IN ) 116 | } 117 | ENDCG 118 | } 119 | } 120 | Fallback "Diffuse" 121 | CustomEditor "ASEMaterialInspector" 122 | } 123 | /*ASEBEGIN 124 | Version=18900 125 | 375;156;1468;863;1193;225.5;1;True;False 126 | Node;AmplifyShaderEditor.RangedFloatNode;2;-597,311.5;Inherit;False;Property;_FresnelPower;Fresnel Power;1;0;Create;True;0;0;0;False;0;False;5;0;0;10;0;1;FLOAT;0 127 | Node;AmplifyShaderEditor.RangedFloatNode;4;-595,227.5;Inherit;False;Property;_FresnelIntensity;Fresnel Intensity;2;0;Create;True;0;0;0;False;0;False;1;0;0;10;0;1;FLOAT;0 128 | Node;AmplifyShaderEditor.ColorNode;3;-247,-15.5;Inherit;False;Property;_Color;Color;0;0;Create;True;0;0;0;False;0;False;1,1,1,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 129 | Node;AmplifyShaderEditor.FresnelNode;1;-283,192.5;Inherit;False;Standard;WorldNormal;ViewDir;False;False;5;0;FLOAT3;0,0,1;False;4;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;1;False;3;FLOAT;5;False;1;FLOAT;0 130 | Node;AmplifyShaderEditor.StandardSurfaceOutputNode;0;0,0;Float;False;True;-1;2;ASEMaterialInspector;0;0;Unlit;Rito/Cannon Ball;False;False;False;False;False;False;False;False;False;False;False;False;False;False;True;False;False;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Transparent;0.5;True;True;0;False;Transparent;;Transparent;All;14;all;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;True;2;5;False;-1;10;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;-1;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 131 | WireConnection;1;2;4;0 132 | WireConnection;1;3;2;0 133 | WireConnection;0;2;3;0 134 | WireConnection;0;9;1;0 135 | ASEEND*/ 136 | //CHKSM=128F74D78E3496027A3987B3B557ABD37E0DF45E -------------------------------------------------------------------------------- /Million Dust/Shaders/Cannon Ball.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e44e42bb0dbf9184790ada4fec8f4729 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Depth Intersection.shader: -------------------------------------------------------------------------------- 1 | // Made with Amplify Shader Editor 2 | // Available at the Unity Asset Store - http://u3d.as/y3X 3 | Shader "Rito/Depth Intersection" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,0) 8 | _Intersection("Intersection", Range( 0 , 1)) = 0.1 9 | _Ambient("Ambient", Range( 0 , 1)) = 0.1 10 | _FresnelPower("Fresnel Power", Range( 0 , 20)) = 5 11 | _FresnelIntensity("Fresnel Intensity", Range( 0 , 20)) = 1 12 | [HideInInspector] __dirty( "", Int ) = 1 13 | } 14 | 15 | SubShader 16 | { 17 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+0" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" "IsEmissive" = "true" } 18 | Cull Back 19 | CGPROGRAM 20 | #include "UnityCG.cginc" 21 | #pragma target 3.0 22 | #pragma surface surf Unlit alpha:fade keepalpha noshadow noambient novertexlights nolightmap nodynlightmap nodirlightmap nofog nometa noforwardadd 23 | struct Input 24 | { 25 | float4 screenPos; 26 | float3 worldPos; 27 | float3 worldNormal; 28 | }; 29 | 30 | uniform float4 _Color; 31 | uniform float _Ambient; 32 | uniform float _Intersection; 33 | UNITY_DECLARE_DEPTH_TEXTURE( _CameraDepthTexture ); 34 | uniform float4 _CameraDepthTexture_TexelSize; 35 | uniform float _FresnelIntensity; 36 | uniform float _FresnelPower; 37 | 38 | inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten ) 39 | { 40 | return half4 ( 0, 0, 0, s.Alpha ); 41 | } 42 | 43 | void surf( Input i , inout SurfaceOutput o ) 44 | { 45 | float4 ase_screenPos = float4( i.screenPos.xyz , i.screenPos.w + 0.00000000001 ); 46 | float4 ase_screenPosNorm = ase_screenPos / ase_screenPos.w; 47 | ase_screenPosNorm.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? ase_screenPosNorm.z : ase_screenPosNorm.z * 0.5 + 0.5; 48 | float eyeDepth5 = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE( _CameraDepthTexture, ase_screenPosNorm.xy )); 49 | float3 ase_worldPos = i.worldPos; 50 | float3 ase_worldViewDir = normalize( UnityWorldSpaceViewDir( ase_worldPos ) ); 51 | float3 ase_worldNormal = i.worldNormal; 52 | float fresnelNdotV11 = dot( ase_worldNormal, ase_worldViewDir ); 53 | float fresnelNode11 = ( 0.0 + _FresnelIntensity * pow( 1.0 - fresnelNdotV11, _FresnelPower ) ); 54 | float temp_output_14_0 = ( ( _Color.a * _Ambient ) + ( _Color.a * ( saturate( ( ( _Intersection + ase_screenPos.w ) - eyeDepth5 ) ) + fresnelNode11 ) ) ); 55 | o.Emission = ( _Color * temp_output_14_0 ).rgb; 56 | o.Alpha = temp_output_14_0; 57 | } 58 | 59 | ENDCG 60 | } 61 | CustomEditor "ASEMaterialInspector" 62 | } 63 | /*ASEBEGIN 64 | Version=18900 65 | 359;138;1468;881;1386.146;299.6286;1.3;True;False 66 | Node;AmplifyShaderEditor.ScreenPosInputsNode;3;-905.3029,227.2883;Float;False;1;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 67 | Node;AmplifyShaderEditor.RangedFloatNode;4;-995.2861,156.9584;Inherit;False;Property;_Intersection;Intersection;1;0;Create;True;0;0;0;False;0;False;0.1;0;0;1;0;1;FLOAT;0 68 | Node;AmplifyShaderEditor.ScreenDepthNode;5;-910.3029,394.2883;Inherit;False;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0 69 | Node;AmplifyShaderEditor.SimpleAddOpNode;6;-703.3029,221.2883;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 70 | Node;AmplifyShaderEditor.SimpleSubtractOpNode;7;-580.3029,263.2883;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 71 | Node;AmplifyShaderEditor.RangedFloatNode;19;-925.9464,494.6714;Inherit;False;Property;_FresnelIntensity;Fresnel Intensity;4;0;Create;True;0;0;0;False;0;False;1;2;0;20;0;1;FLOAT;0 72 | Node;AmplifyShaderEditor.RangedFloatNode;18;-927.2462,573.9714;Inherit;False;Property;_FresnelPower;Fresnel Power;3;0;Create;True;0;0;0;False;0;False;5;0;0;20;0;1;FLOAT;0 73 | Node;AmplifyShaderEditor.FresnelNode;11;-625.3026,405.9923;Inherit;True;Standard;WorldNormal;ViewDir;False;False;5;0;FLOAT3;0,0,1;False;4;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;1;False;3;FLOAT;5;False;1;FLOAT;0 74 | Node;AmplifyShaderEditor.SaturateNode;8;-455.3028,263.2883;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0 75 | Node;AmplifyShaderEditor.SimpleAddOpNode;12;-312.9026,322.6923;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 76 | Node;AmplifyShaderEditor.ColorNode;2;-399,-7.5;Inherit;False;Property;_Color;Color;0;0;Create;True;0;0;0;False;0;False;1,1,1,0;1,1,1,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 77 | Node;AmplifyShaderEditor.RangedFloatNode;16;-474.456,163.6108;Inherit;False;Property;_Ambient;Ambient;2;0;Create;True;0;0;0;False;0;False;0.1;0;0;1;0;1;FLOAT;0 78 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-185.2026,266.2922;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 79 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-174.1556,105.1108;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0.1;False;1;FLOAT;0 80 | Node;AmplifyShaderEditor.SimpleAddOpNode;14;-40.25552,155.8106;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 81 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;17;72.84542,41.41061;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0 82 | Node;AmplifyShaderEditor.StandardSurfaceOutputNode;24;256.1002,-7.799996;Float;False;True;-1;2;ASEMaterialInspector;0;0;Unlit;Rito/Depth Intersection;False;False;False;False;True;True;True;True;True;True;True;True;False;False;True;True;False;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Transparent;0.5;True;False;0;False;Transparent;;Transparent;All;14;all;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;False;2;5;False;-1;10;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;-1;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 83 | WireConnection;6;0;4;0 84 | WireConnection;6;1;3;4 85 | WireConnection;7;0;6;0 86 | WireConnection;7;1;5;0 87 | WireConnection;11;2;19;0 88 | WireConnection;11;3;18;0 89 | WireConnection;8;0;7;0 90 | WireConnection;12;0;8;0 91 | WireConnection;12;1;11;0 92 | WireConnection;13;0;2;4 93 | WireConnection;13;1;12;0 94 | WireConnection;15;0;2;4 95 | WireConnection;15;1;16;0 96 | WireConnection;14;0;15;0 97 | WireConnection;14;1;13;0 98 | WireConnection;17;0;2;0 99 | WireConnection;17;1;14;0 100 | WireConnection;24;2;17;0 101 | WireConnection;24;9;14;0 102 | ASEEND*/ 103 | //CHKSM=9726A82141D3C1A580C8256D651FC1DBAD5728E3 -------------------------------------------------------------------------------- /Million Dust/Shaders/Depth Intersection.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36c962b1c4493cd4e91d1f87bdfee72d 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Dust.shader: -------------------------------------------------------------------------------- 1 | Shader "Rito/Dust" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Texture", 2D) = "white" {} 6 | _CutOff("Alphatest Cutoff", Range(0, 1)) = 0.5 7 | } 8 | SubShader 9 | { 10 | //Tags { "Queue"="Transparent+1" "RenderType"="Transparent" "IgnoreProjector"="True" } 11 | Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" "IgnoreProjector"="True"} 12 | //ZWrite Off 13 | Lighting Off 14 | Fog { Mode Off } 15 | Blend SrcAlpha OneMinusSrcAlpha 16 | 17 | Pass 18 | { 19 | CGPROGRAM 20 | #pragma vertex vert 21 | #pragma fragment frag 22 | 23 | #include "UnityCG.cginc" 24 | #define TRUE 1 25 | #define FALSE 0 26 | 27 | struct v2f 28 | { 29 | float4 pos : SV_POSITION; 30 | float3 uv : TEXCOORD0; 31 | int isAlive : TEXCOORD1; 32 | half3 dustColor : COLOR0; 33 | }; 34 | 35 | struct Dust 36 | { 37 | float3 position; 38 | int isAlive; 39 | }; 40 | 41 | // ======================================================================================== 42 | // Vertex Shader 43 | // ======================================================================================== 44 | uniform float _Scale; 45 | StructuredBuffer _DustBuffer; 46 | StructuredBuffer _DustColorBuffer; 47 | 48 | float4 CalculateVertex(float4 vertex, float3 worldPos) 49 | { 50 | float3 camUpVec = normalize( UNITY_MATRIX_V._m10_m11_m12 ); 51 | float3 camForwardVec = -normalize( UNITY_MATRIX_V._m20_m21_m22 ); 52 | float3 camRightVec = normalize( UNITY_MATRIX_V._m00_m01_m02 ); 53 | float4x4 camRotMat = float4x4( camRightVec, 0, camUpVec, 0, camForwardVec, 0, 0, 0, 0, 1 ); 54 | 55 | vertex = mul(vertex, camRotMat); // Billboard 56 | vertex.xyz *= _Scale; // Scale 57 | vertex.xyz += worldPos; // Instance Position 58 | 59 | // World => VP => Clip 60 | return mul(UNITY_MATRIX_VP, vertex); 61 | } 62 | 63 | v2f vert (appdata_full v, uint instanceID : SV_InstanceID) 64 | { 65 | v2f o; 66 | 67 | o.isAlive = _DustBuffer[instanceID].isAlive; 68 | o.pos = CalculateVertex(v.vertex, _DustBuffer[instanceID].position); 69 | o.uv = v.texcoord; 70 | o.dustColor = _DustColorBuffer[instanceID]; 71 | 72 | return o; 73 | } 74 | 75 | // ======================================================================================== 76 | // Fragment Shader 77 | // ======================================================================================== 78 | sampler2D _MainTex; 79 | fixed _CutOff; 80 | 81 | fixed4 frag (v2f i) : SV_Target 82 | { 83 | // 죽은 먼지는 렌더링 X 84 | if(i.isAlive == FALSE) 85 | { 86 | discard; 87 | } 88 | 89 | fixed4 col = tex2D(_MainTex, i.uv); 90 | col.rgb = i.dustColor * col.a; 91 | 92 | clip(col.a - _CutOff); 93 | 94 | return col; 95 | } 96 | ENDCG 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Dust.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 91a0d60d54a827d4db33e781eb519d9d 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Explosion.shader: -------------------------------------------------------------------------------- 1 | // Made with Amplify Shader Editor 2 | // Available at the Unity Asset Store - http://u3d.as/y3X 3 | Shader "Rito/Explosion" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,0) 8 | _Power("Power", Range( 0 , 20)) = 6 9 | [HideInInspector] __dirty( "", Int ) = 1 10 | } 11 | 12 | SubShader 13 | { 14 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+0" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" "IsEmissive" = "true" } 15 | Cull Back 16 | CGPROGRAM 17 | #pragma target 3.0 18 | #pragma multi_compile_instancing 19 | #pragma surface surf Unlit alpha:fade keepalpha noshadow noambient novertexlights nolightmap nodynlightmap nodirlightmap nofog nometa noforwardadd 20 | struct Input 21 | { 22 | float3 worldNormal; 23 | float3 viewDir; 24 | float4 vertexColor : COLOR; 25 | }; 26 | 27 | uniform float4 _Color; 28 | uniform float _Power; 29 | 30 | inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten ) 31 | { 32 | return half4 ( 0, 0, 0, s.Alpha ); 33 | } 34 | 35 | void surf( Input i , inout SurfaceOutput o ) 36 | { 37 | o.Emission = _Color.rgb; 38 | float3 ase_worldNormal = i.worldNormal; 39 | float3 ase_normWorldNormal = normalize( ase_worldNormal ); 40 | float dotResult3 = dot( ase_normWorldNormal , i.viewDir ); 41 | o.Alpha = ( _Color.a * pow( saturate( dotResult3 ) , _Power ) * i.vertexColor.a ); 42 | } 43 | 44 | ENDCG 45 | } 46 | CustomEditor "ASEMaterialInspector" 47 | } 48 | /*ASEBEGIN 49 | Version=18900 50 | 442;129;1468;857;1420.332;368.5823;1.3;True;False 51 | Node;AmplifyShaderEditor.WorldNormalVector;1;-1014.9,-3.5;Inherit;False;True;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3 52 | Node;AmplifyShaderEditor.ViewDirInputsCoordNode;4;-997.9,136.5;Inherit;False;World;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3 53 | Node;AmplifyShaderEditor.DotProductOpNode;3;-804.9,46.5;Inherit;True;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0 54 | Node;AmplifyShaderEditor.RangedFloatNode;6;-737,307.5;Inherit;False;Property;_Power;Power;1;0;Create;True;0;0;0;False;0;False;6;0;0;20;0;1;FLOAT;0 55 | Node;AmplifyShaderEditor.SaturateNode;9;-572.732,83.81767;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0 56 | Node;AmplifyShaderEditor.PowerNode;5;-423,93.5;Inherit;True;False;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0 57 | Node;AmplifyShaderEditor.ColorNode;7;-393.3325,-107.2823;Inherit;False;Property;_Color;Color;0;0;Create;True;0;0;0;False;0;False;1,1,1,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 58 | Node;AmplifyShaderEditor.VertexColorNode;10;-359.5322,311.3178;Inherit;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 59 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;8;-151.5326,53.91765;Inherit;False;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0 60 | Node;AmplifyShaderEditor.StandardSurfaceOutputNode;0;72.8,-6.5;Float;False;True;-1;2;ASEMaterialInspector;0;0;Unlit;Rito/Explosion;False;False;False;False;True;True;True;True;True;True;True;True;False;False;True;True;True;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Transparent;0.5;True;False;0;False;Transparent;;Transparent;All;14;all;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;False;2;5;False;-1;10;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;-1;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 61 | WireConnection;3;0;1;0 62 | WireConnection;3;1;4;0 63 | WireConnection;9;0;3;0 64 | WireConnection;5;0;9;0 65 | WireConnection;5;1;6;0 66 | WireConnection;8;0;7;4 67 | WireConnection;8;1;5;0 68 | WireConnection;8;2;10;4 69 | WireConnection;0;2;7;0 70 | WireConnection;0;9;8;0 71 | ASEEND*/ 72 | //CHKSM=97B5D7726B1F4DEAD96B85AF575BD232BC758F3C -------------------------------------------------------------------------------- /Million Dust/Shaders/Explosion.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca07cfe48c7bdd9429ee3628e95443be 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Shaders/Sphere Collider.shader: -------------------------------------------------------------------------------- 1 | // Made with Amplify Shader Editor 2 | // Available at the Unity Asset Store - http://u3d.as/y3X 3 | Shader "Rito/Sphere Collider" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,0) 8 | _Intersection("Intersection", Range( 0 , 1)) = 0.1 9 | _Ambient("Ambient", Range( 0 , 1)) = 0.1 10 | _FresnelPower("Fresnel Power", Range( 0 , 20)) = 5 11 | _FresnelIntensity("Fresnel Intensity", Range( 0 , 20)) = 1 12 | [HideInInspector] __dirty( "", Int ) = 1 13 | } 14 | 15 | SubShader 16 | { 17 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+0" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" "IsEmissive" = "true" } 18 | Cull Back 19 | Blend SrcAlpha OneMinusSrcAlpha 20 | 21 | CGPROGRAM 22 | #include "UnityCG.cginc" 23 | #pragma target 3.0 24 | #pragma surface surf Unlit keepalpha noshadow noambient novertexlights nolightmap nodynlightmap nodirlightmap nofog nometa noforwardadd 25 | struct Input 26 | { 27 | float4 screenPos; 28 | float3 worldPos; 29 | float3 worldNormal; 30 | }; 31 | 32 | uniform float4 _Color; 33 | uniform float _Ambient; 34 | uniform float _Intersection; 35 | UNITY_DECLARE_DEPTH_TEXTURE( _CameraDepthTexture ); 36 | uniform float4 _CameraDepthTexture_TexelSize; 37 | uniform float _FresnelIntensity; 38 | uniform float _FresnelPower; 39 | 40 | inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten ) 41 | { 42 | return half4 ( 0, 0, 0, s.Alpha ); 43 | } 44 | 45 | void surf( Input i , inout SurfaceOutput o ) 46 | { 47 | float4 ase_screenPos = float4( i.screenPos.xyz , i.screenPos.w + 0.00000000001 ); 48 | float4 ase_screenPosNorm = ase_screenPos / ase_screenPos.w; 49 | ase_screenPosNorm.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? ase_screenPosNorm.z : ase_screenPosNorm.z * 0.5 + 0.5; 50 | float eyeDepth5 = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE( _CameraDepthTexture, ase_screenPosNorm.xy )); 51 | float3 ase_worldPos = i.worldPos; 52 | float3 ase_worldViewDir = normalize( UnityWorldSpaceViewDir( ase_worldPos ) ); 53 | float3 ase_worldNormal = i.worldNormal; 54 | float fresnelNdotV11 = dot( ase_worldNormal, ase_worldViewDir ); 55 | float fresnelNode11 = ( 0.0 + _FresnelIntensity * pow( 1.0 - fresnelNdotV11, _FresnelPower ) ); 56 | float temp_output_14_0 = ( ( _Color.a * _Ambient ) + ( _Color.a * ( saturate( ( ( _Intersection + ase_screenPos.w ) - eyeDepth5 ) ) + fresnelNode11 ) ) ); 57 | o.Emission = ( _Color * temp_output_14_0 ).rgb; 58 | o.Alpha = temp_output_14_0; 59 | } 60 | 61 | ENDCG 62 | } 63 | CustomEditor "ASEMaterialInspector" 64 | } 65 | /*ASEBEGIN 66 | Version=18900 67 | 229;149;1468;851;1386.146;260.6286;1.3;True;False 68 | Node;AmplifyShaderEditor.ScreenPosInputsNode;3;-905.3029,227.2883;Float;False;1;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 69 | Node;AmplifyShaderEditor.RangedFloatNode;4;-995.2861,145.2584;Inherit;False;Property;_Intersection;Intersection;2;0;Create;True;0;0;0;False;0;False;0.1;0;0;1;0;1;FLOAT;0 70 | Node;AmplifyShaderEditor.SimpleAddOpNode;6;-703.3029,221.2883;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 71 | Node;AmplifyShaderEditor.ScreenDepthNode;5;-910.3029,394.2883;Inherit;False;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0 72 | Node;AmplifyShaderEditor.SimpleSubtractOpNode;7;-580.3029,263.2883;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 73 | Node;AmplifyShaderEditor.RangedFloatNode;19;-925.9464,494.6714;Inherit;False;Property;_FresnelIntensity;Fresnel Intensity;5;0;Create;True;0;0;0;False;0;False;1;2;0;20;0;1;FLOAT;0 74 | Node;AmplifyShaderEditor.RangedFloatNode;18;-927.2462,573.9714;Inherit;False;Property;_FresnelPower;Fresnel Power;4;0;Create;True;0;0;0;False;0;False;5;0;0;20;0;1;FLOAT;0 75 | Node;AmplifyShaderEditor.FresnelNode;11;-624.0026,413.7923;Inherit;True;Standard;WorldNormal;ViewDir;False;False;5;0;FLOAT3;0,0,1;False;4;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;1;False;3;FLOAT;5;False;1;FLOAT;0 76 | Node;AmplifyShaderEditor.SaturateNode;8;-455.3028,263.2883;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0 77 | Node;AmplifyShaderEditor.SimpleAddOpNode;12;-312.9026,322.6923;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 78 | Node;AmplifyShaderEditor.RangedFloatNode;16;-474.456,163.6108;Inherit;False;Property;_Ambient;Ambient;3;0;Create;True;0;0;0;False;0;False;0.1;0;0;1;0;1;FLOAT;0 79 | Node;AmplifyShaderEditor.ColorNode;2;-399,-7.5;Inherit;False;Property;_Color;Color;1;0;Create;True;0;0;0;False;0;False;1,1,1,0;1,1,1,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 80 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-185.2026,266.2922;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 81 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-174.1556,105.1108;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0.1;False;1;FLOAT;0 82 | Node;AmplifyShaderEditor.SimpleAddOpNode;14;-40.25552,155.8106;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 83 | Node;AmplifyShaderEditor.SimpleMultiplyOpNode;17;72.84542,41.41061;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0 84 | Node;AmplifyShaderEditor.StandardSurfaceOutputNode;24;256.1002,-7.799996;Float;False;True;-1;2;ASEMaterialInspector;0;0;Unlit;Rito/Sphere Collider;False;False;False;False;True;True;True;True;True;True;True;True;False;False;True;True;False;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Custom;0.5;True;False;0;True;Transparent;;Transparent;All;14;all;True;True;True;True;0;False;-1;False;1;False;-1;255;False;-1;255;False;-1;6;False;-1;0;False;-1;0;False;-1;3;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;False;2;5;False;-1;10;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;0;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 85 | WireConnection;6;0;4;0 86 | WireConnection;6;1;3;4 87 | WireConnection;7;0;6;0 88 | WireConnection;7;1;5;0 89 | WireConnection;11;2;19;0 90 | WireConnection;11;3;18;0 91 | WireConnection;8;0;7;0 92 | WireConnection;12;0;8;0 93 | WireConnection;12;1;11;0 94 | WireConnection;13;0;2;4 95 | WireConnection;13;1;12;0 96 | WireConnection;15;0;2;4 97 | WireConnection;15;1;16;0 98 | WireConnection;14;0;15;0 99 | WireConnection;14;1;13;0 100 | WireConnection;17;0;2;0 101 | WireConnection;17;1;14;0 102 | WireConnection;24;2;17;0 103 | WireConnection;24;9;14;0 104 | ASEEND*/ 105 | //CHKSM=B7D83AF573B9C71D1A81C0A040B4C1D172548072 -------------------------------------------------------------------------------- /Million Dust/Shaders/Sphere Collider.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 99c406b1b155ea14294103fc27b2b20d 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Shaders/World Bounds.shader: -------------------------------------------------------------------------------- 1 | // Made with Amplify Shader Editor 2 | // Available at the Unity Asset Store - http://u3d.as/y3X 3 | Shader "Rito/World Bounds" 4 | { 5 | Properties 6 | { 7 | [HideInInspector] __dirty( "", Int ) = 1 8 | } 9 | 10 | SubShader 11 | { 12 | Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+0" "IgnoreProjector" = "True" "IsEmissive" = "true" } 13 | Cull Back 14 | CGPROGRAM 15 | #pragma target 3.0 16 | #pragma surface surf Unlit keepalpha addshadow fullforwardshadows noambient novertexlights nolightmap nodynlightmap nodirlightmap nofog nometa noforwardadd 17 | struct Input 18 | { 19 | float4 vertexColor : COLOR; 20 | }; 21 | 22 | inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten ) 23 | { 24 | return half4 ( 0, 0, 0, s.Alpha ); 25 | } 26 | 27 | void surf( Input i , inout SurfaceOutput o ) 28 | { 29 | o.Emission = i.vertexColor.rgb; 30 | o.Alpha = 1; 31 | } 32 | 33 | ENDCG 34 | } 35 | Fallback "Diffuse" 36 | CustomEditor "ASEMaterialInspector" 37 | } 38 | /*ASEBEGIN 39 | Version=18900 40 | 375;156;1468;863;1127;227.5;1;True;False 41 | Node;AmplifyShaderEditor.VertexColorNode;4;-341,34.5;Inherit;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 42 | Node;AmplifyShaderEditor.StandardSurfaceOutputNode;0;0,0;Float;False;True;-1;2;ASEMaterialInspector;0;0;Unlit;Rito/World Bounds;False;False;False;False;True;True;True;True;True;True;True;True;False;False;True;False;False;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Opaque;0.5;True;True;0;False;Opaque;;Geometry;All;14;all;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;True;0;0;False;-1;0;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;-1;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 43 | WireConnection;0;2;4;0 44 | ASEEND*/ 45 | //CHKSM=DD6B8FD17DD89651038272ED1D4B676180C8C535 -------------------------------------------------------------------------------- /Million Dust/Shaders/World Bounds.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fc893f8dec30aa74fb38dffa80b56c05 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Million Dust/Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9bc8f04a806799842ae492d7635ac8d3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Million Dust/Textures/Point_Dust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rito15/Unity-Million-Dust/9f997480ccb636ab20d633921cd8361acba004f0/Million Dust/Textures/Point_Dust.png -------------------------------------------------------------------------------- /Million Dust/Textures/Point_Dust.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3933a5af5354e243a44512e5de3776c 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 128 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | - serializedVersion: 3 75 | buildTarget: Standalone 76 | maxTextureSize: 128 77 | resizeAlgorithm: 0 78 | textureFormat: -1 79 | textureCompression: 1 80 | compressionQuality: 50 81 | crunchedCompression: 0 82 | allowsAlphaSplitting: 0 83 | overridden: 0 84 | androidETC2FallbackOverride: 0 85 | forceMaximumCompressionQuality_BC6H_BC7: 0 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | bones: [] 92 | spriteID: 93 | internalID: 0 94 | vertices: [] 95 | indices: 96 | edges: [] 97 | weights: [] 98 | secondaryTextures: [] 99 | spritePackingTag: 100 | pSDRemoveMatte: 0 101 | pSDShowRemoveMatteOption: 0 102 | userData: 103 | assetBundleName: 104 | assetBundleVariant: 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Million Dust 2 | 3 | - Physics-based Dust Simulation 4 | 5 | - Unity Engine (2019.4.9f1) 6 | 7 | - GPU Instancing 8 | 9 | - Compute Shader 10 | 11 | - (KR) 12 | 13 | # 14 | 15 |
16 | 17 | ## Controls 18 | ### [1] Mouse 19 | - `Move` : Rotate Camera 20 | - `Left Click` : Use Current Tool 21 | - `Right Click` : Show/Hide Cursor 22 | 23 | ### [2] Keyboard 24 | - `WASD` : Move Player 25 | - `LShift` : Accelerate 26 | - `LCtrl` : Descend 27 | - `Space` : Ascend 28 | - `1, 2, 3, 4` : Change Tools 29 | 30 |
31 | 32 | ## Generate 1 million dust in random positions 33 | 34 | 35 |
36 | 37 | 38 | ## Vacuum Up 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 | 48 | ## Emit 49 | 50 | 51 | 52 |
53 | 54 | ## Plane Collision, Bounciness 55 | 56 | 57 | 58 | 59 | 60 |
61 | 62 | ## Inner Wall Collision(Cube) 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | ## Blow 71 | 72 | 73 | 74 | 75 | 76 |
77 | 78 | ## Sphere Collision 79 | 80 | 81 | 82 | 83 | 84 | 85 |
86 | 87 | ## Box(AABB) Collision 88 | 89 | 90 | 91 | 92 |
93 | 94 | ## Box(OBB) Collision 95 | 96 | 97 | 98 | 99 |
100 | 101 | ## Projectile Launch & Explosion 102 | 103 | 104 | 105 | 106 | 107 | 108 | 111 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9fec924dbd36bc4c8c906c2d76142d3 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------