├── ProjectSettings ├── ProjectVersion.txt ├── AudioManager.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── TagManager.asset ├── TimeManager.asset ├── EditorSettings.asset ├── NetworkManager.asset ├── DynamicsManager.asset ├── GraphicsSettings.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── QualitySettings.asset ├── UnityAdsSettings.asset ├── ClusterInputManager.asset ├── EditorBuildSettings.asset └── UnityConnectSettings.asset ├── Assets ├── scene.unity ├── Materials │ ├── SkyMap.mat │ ├── MeatBall_Toon.mat │ ├── MeatBall_Glass.mat │ ├── MeatBall_BlinnPhong.mat │ ├── SkyMap.mat.meta │ ├── MeatBall_Glass.mat.meta │ ├── MeatBall_Toon.mat.meta │ └── MeatBall_BlinnPhong.mat.meta ├── Textures │ ├── uffizi_probe.hdr │ └── uffizi_probe.hdr.meta ├── scene.unity.meta ├── Scripts.meta ├── Shaders.meta ├── Textures.meta ├── Materials.meta ├── Shaders │ ├── MetaBall_Toon.shader.meta │ ├── MetaBall_BlinnPhong.shader.meta │ ├── MetaBall_RefractionGlass.shader.meta │ ├── MetaBall_BlinnPhong.shader │ ├── MetaBall_Toon.shader │ └── MetaBall_RefractionGlass.shader └── Scripts │ ├── FPSDisplay.cs.meta │ ├── MenuManger.cs.meta │ ├── MetaBalls.cs.meta │ ├── CameraBehaviour.cs.meta │ ├── FPSDisplay.cs │ ├── CameraBehaviour.cs │ ├── MetaBalls.cs │ └── MenuManger.cs ├── .gitignore └── README.md /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.5.1f1 2 | -------------------------------------------------------------------------------- /Assets/scene.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/Assets/scene.unity -------------------------------------------------------------------------------- /Assets/Materials/SkyMap.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/Assets/Materials/SkyMap.mat -------------------------------------------------------------------------------- /Assets/Materials/MeatBall_Toon.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/Assets/Materials/MeatBall_Toon.mat -------------------------------------------------------------------------------- /Assets/Textures/uffizi_probe.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/Assets/Textures/uffizi_probe.hdr -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /Assets/Materials/MeatBall_Glass.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/Assets/Materials/MeatBall_Glass.mat -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityAdsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/UnityAdsSettings.asset -------------------------------------------------------------------------------- /Assets/Materials/MeatBall_BlinnPhong.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/Assets/Materials/MeatBall_BlinnPhong.mat -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudyEMS/MetaBalls/HEAD/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /Assets/scene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ae71f420bad914a1bb454a41b086483c 3 | timeCreated: 1486325134 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/SkyMap.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02b770a75a50f48e79a9d226c66cd74b 3 | timeCreated: 1486914611 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/MeatBall_Glass.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 986820bd04524429f8cc138dca638a43 3 | timeCreated: 1486541857 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/MeatBall_Toon.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c147a329bb93f46d094d62f8e2a7230f 3 | timeCreated: 1486541857 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/MeatBall_BlinnPhong.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6ab96c8d8b604ff59ad42bcef0d4e14 3 | timeCreated: 1486541857 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a95f7df1d44f643c3beea191e243615c 3 | folderAsset: yes 4 | timeCreated: 1486888458 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 841186224937641fdba2d2bc249b1a84 3 | folderAsset: yes 4 | timeCreated: 1486888464 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b61f0574c62d4a2088f4e1de9ce1ede 3 | folderAsset: yes 4 | timeCreated: 1486991384 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0fa7efa708d9e453aaa743da134ff712 3 | folderAsset: yes 4 | timeCreated: 1486888482 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Shaders/MetaBall_Toon.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f91d0902d800486aaa32491308733d1 3 | timeCreated: 1486541835 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Shaders/MetaBall_BlinnPhong.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 132eaa34695254bd9ac4898c5d8a1829 3 | timeCreated: 1486541835 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Shaders/MetaBall_RefractionGlass.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 688587b1d436b4d9abcc2b77f71dc443 3 | timeCreated: 1486541835 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scripts/FPSDisplay.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aec54dd2f55e7487681c836093902aef 3 | timeCreated: 1486997715 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Scripts/MenuManger.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd630b0b5a9794afb9a61b3768cfcf5d 3 | timeCreated: 1486988152 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Scripts/MetaBalls.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d11bf02d03f6e4b79a61e419df063db2 3 | timeCreated: 1486378332 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Scripts/CameraBehaviour.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9658c4284a36342dfbdeaa49812ad2b1 3 | timeCreated: 1486805521 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # =============== # 2 | # Unity generated # 3 | # =============== # 4 | [Tt]emp/ 5 | [Oo]bj/ 6 | [Bb]uild/ 7 | [Ll]ibrary/ 8 | sysinfo.txt 9 | *.stackdump 10 | 11 | # ===================================== # 12 | # Visual Studio / MonoDevelop generated # 13 | # ===================================== # 14 | [Ee]xported[Oo]bj/ 15 | .vs/ 16 | /*.userprefs 17 | /*.csproj 18 | /*.pidb 19 | /*.suo 20 | /*.sln* 21 | /*.user 22 | /*.unityproj 23 | /*.booproj 24 | 25 | # ============ # 26 | # OS generated # 27 | # ============ # 28 | .DS_Store* 29 | ._* 30 | .Spotlight-V100 31 | .Trashes 32 | Icon? 33 | ehthumbs.db 34 | [Tt]humbs.db 35 | -------------------------------------------------------------------------------- /Assets/Scripts/FPSDisplay.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class FPSDisplay : MonoBehaviour 5 | { 6 | float deltaTime = 0.0f; 7 | 8 | void Update() 9 | { 10 | deltaTime += (Time.deltaTime - deltaTime) * 0.1f; 11 | } 12 | 13 | void OnGUI() 14 | { 15 | int w = Screen.width, h = Screen.height; 16 | 17 | GUIStyle style = new GUIStyle(); 18 | 19 | Rect rect = new Rect(0, 0, w, h * 2 / 100); 20 | style.alignment = TextAnchor.UpperLeft; 21 | style.fontSize = h * 2 / 100; 22 | style.normal.textColor = new Color (0.0f, 0.0f, 0.5f, 1.0f); 23 | float msec = deltaTime * 1000.0f; 24 | float fps = 1.0f / deltaTime; 25 | string text = string.Format("{0:0.0} ms ({1:0.} fps)", msec, fps); 26 | GUI.Label(rect, text, style); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Assets/Scripts/CameraBehaviour.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class CameraBehaviour : MonoBehaviour { 6 | 7 | public float rotationSpeed = 5f; 8 | public float minDistance = -2f, maxDistance = -10f; 9 | [Range(0,1)]public float zoomSensitivity = 0.2f; 10 | public bool shouldRotate = true; 11 | 12 | private Transform cam; 13 | private bool autoRotate = true; 14 | private float currentDistance = 1f; 15 | private int autoRotateDir = 1; 16 | 17 | void Start(){ 18 | cam = Camera.main.transform; 19 | } 20 | 21 | // Update is called once per frame 22 | void Update () { 23 | float h = Input.GetAxis("Mouse X"); 24 | 25 | if(Input.GetMouseButtonDown(1)){ 26 | autoRotate = false; 27 | } 28 | 29 | if (Input.GetMouseButton(1)){ 30 | transform.Rotate(0, rotationSpeed * h * 2, 0); 31 | } 32 | if (Input.GetMouseButtonUp(1)){ 33 | autoRotateDir = h > 0 ? 1 : -1; 34 | autoRotate = true; 35 | } 36 | 37 | if(shouldRotate && autoRotate) 38 | transform.Rotate(0, autoRotateDir * rotationSpeed * Time.deltaTime, 0); 39 | 40 | float d = Input.GetAxis("Mouse ScrollWheel") * zoomSensitivity; 41 | if(d != 0){ 42 | currentDistance = Mathf.Clamp01(currentDistance + d); 43 | float distance = Mathf.Lerp(maxDistance, minDistance, currentDistance); 44 | cam.localPosition = new Vector3(0,0,distance); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MetaBalls 2 | An implementation Metaballs (a.k.a Blobs) inside Unity3D. Written as a shader for the Particle System to allow formore control and fun ;-) 3 | 4 | ![Demo Glass Metaball](http://i.giphy.com/l3q2CEBxrQABnRhaE.gif) 5 | 6 | ## Demo 7 | Demo scene included. As I didn't have time to make GUI, I included the following commands to interact with the demo. 8 | #### Commands 9 | 20 | 21 | ## Usage 22 |
    23 |
  1. Create a new Particle System and make sure it is set to Prewarm and the Max Particles are 10.
  2. 24 |
  3. Create a new material with one of the provided shaders.
  4. 25 |
  5. Add the material to the renderer component in the Particle System.
  6. 26 |
  7. Add the script MetaBalls.cs to the Particle System.
  8. 27 |
  9. Enjoy a mesmerizing effect.
  10. 28 |
29 | 30 | ## TO DO 31 | 38 | 39 | ## Disclaimer 40 | Skybox from http://pauldebevec.com/Probes/ 41 | -------------------------------------------------------------------------------- /Assets/Scripts/MetaBalls.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | //[ExecuteInEditMode] 6 | public class MetaBalls : MonoBehaviour { 7 | 8 | public Material CurrentMaterial { 9 | get { 10 | return mat; 11 | } 12 | set { 13 | if(value == mat) 14 | return; 15 | mat = pSystem.GetComponent().sharedMaterial = value; 16 | } 17 | } 18 | 19 | private Material mat; 20 | private ParticleSystem pSystem; 21 | private ParticleSystem.Particle[] particles; 22 | private List particlesPos; 23 | private float speed = 0.0f; 24 | 25 | // Use this for initialization 26 | void Awake () { 27 | pSystem = GetComponent(); 28 | particles = new ParticleSystem.Particle[pSystem.main.maxParticles]; 29 | particlesPos = new List(10); 30 | mat = pSystem.GetComponent().sharedMaterial; 31 | speed = pSystem.main.startSpeedMultiplier; 32 | } 33 | 34 | // Update is called once per frame 35 | void Update () { 36 | // Clear the position of particles. 37 | particlesPos.Clear(); 38 | 39 | // Get a list of the current alive particles in this frame. 40 | int aliveParticles = pSystem.GetParticles(particles); 41 | 42 | // Get the position of all alive particles in this frame. 43 | for(int i = 0; i < aliveParticles; i++){ 44 | particlesPos.Add(particles[i].position); 45 | } 46 | 47 | // Update the position array in the shader. 48 | mat.SetVectorArray("_ParticlesPos", particlesPos); 49 | 50 | } 51 | 52 | public bool TogglePlay(){ 53 | if(pSystem.isPlaying) 54 | pSystem.Pause(); 55 | else 56 | pSystem.Play(); 57 | 58 | return pSystem.isPlaying; 59 | } 60 | 61 | public void TogglePlay(bool b){ 62 | if(b) 63 | pSystem.Play(); 64 | else 65 | pSystem.Pause(); 66 | } 67 | 68 | public bool ToggleNoise(){ 69 | ParticleSystem.NoiseModule n = pSystem.noise; 70 | if(n.enabled) 71 | n.enabled = false; 72 | else 73 | n.enabled = true; 74 | return n.enabled; 75 | } 76 | 77 | public void ToggleNoise(bool b){ 78 | ParticleSystem.NoiseModule n = pSystem.noise; 79 | n.enabled = b; 80 | } 81 | 82 | public void ChangeSpeed(float newSpeed){ 83 | ParticleSystem.MainModule pmain = pSystem.main; 84 | pmain.startSpeedMultiplier = speed * newSpeed; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /Assets/Textures/uffizi_probe.hdr.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1511b6f5a6fc0470c8fa4c95add96319 3 | timeCreated: 1486914701 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: 7 | 8900000: generatedCubemap 8 | serializedVersion: 4 9 | mipmaps: 10 | mipMapMode: 0 11 | enableMipMap: 1 12 | sRGBTexture: 0 13 | linearTexture: 0 14 | fadeOut: 0 15 | borderMipMap: 0 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 | grayScaleToAlpha: 0 25 | generateCubemap: 1 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | filterMode: -1 32 | aniso: -1 33 | mipBias: -1 34 | wrapMode: -1 35 | nPOTScale: 1 36 | lightmap: 0 37 | compressionQuality: 50 38 | spriteMode: 0 39 | spriteExtrude: 1 40 | spriteMeshType: 1 41 | alignment: 0 42 | spritePivot: {x: 0.5, y: 0.5} 43 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 44 | spritePixelsToUnits: 100 45 | alphaUsage: 1 46 | alphaIsTransparency: 0 47 | spriteTessellationDetail: -1 48 | textureType: 0 49 | textureShape: 2 50 | maxTextureSizeSet: 0 51 | compressionQualitySet: 0 52 | textureFormatSet: 0 53 | platformSettings: 54 | - buildTarget: DefaultTexturePlatform 55 | maxTextureSize: 2048 56 | textureFormat: -1 57 | textureCompression: 1 58 | compressionQuality: 50 59 | crunchedCompression: 0 60 | allowsAlphaSplitting: 0 61 | overridden: 0 62 | - buildTarget: Standalone 63 | maxTextureSize: 2048 64 | textureFormat: -1 65 | textureCompression: 1 66 | compressionQuality: 50 67 | crunchedCompression: 0 68 | allowsAlphaSplitting: 0 69 | overridden: 0 70 | - buildTarget: iPhone 71 | maxTextureSize: 2048 72 | textureFormat: -1 73 | textureCompression: 1 74 | compressionQuality: 50 75 | crunchedCompression: 0 76 | allowsAlphaSplitting: 0 77 | overridden: 0 78 | - buildTarget: Android 79 | maxTextureSize: 2048 80 | textureFormat: -1 81 | textureCompression: 1 82 | compressionQuality: 50 83 | crunchedCompression: 0 84 | allowsAlphaSplitting: 0 85 | overridden: 0 86 | - buildTarget: WebGL 87 | maxTextureSize: 2048 88 | textureFormat: -1 89 | textureCompression: 1 90 | compressionQuality: 50 91 | crunchedCompression: 0 92 | allowsAlphaSplitting: 0 93 | overridden: 0 94 | spriteSheet: 95 | serializedVersion: 2 96 | sprites: [] 97 | outline: [] 98 | spritePackingTag: 99 | userData: 100 | assetBundleName: 101 | assetBundleVariant: 102 | -------------------------------------------------------------------------------- /Assets/Scripts/MenuManger.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class MenuManger : MonoBehaviour { 6 | 7 | public CameraBehaviour camRig; 8 | public GameObject fallingParticle, sphereParticle; 9 | public Material[] mats; 10 | 11 | private MetaBalls currentMetaBallScript; 12 | private bool isNoiseEnabled = false, isPlaying = true; 13 | private float currentSpeed = 1.0f; 14 | // Use this for initialization 15 | void Start () { 16 | if(fallingParticle == null || sphereParticle == null){ 17 | Debug.LogError("Make sure there is a reference to the particle systems in the scene."); 18 | return; 19 | } 20 | // Only one should be active, spherical is by default. 21 | fallingParticle.SetActive(false); 22 | sphereParticle.SetActive(true); 23 | currentMetaBallScript = sphereParticle.GetComponent(); 24 | } 25 | 26 | // Update is called once per frame 27 | void Update () { 28 | // Particle System. 29 | if(Input.GetKeyDown(KeyCode.Q)){ 30 | fallingParticle.SetActive(false); 31 | sphereParticle.SetActive(true); 32 | InitParticleSystem(sphereParticle); 33 | } 34 | if(Input.GetKeyDown(KeyCode.W)){ 35 | fallingParticle.SetActive(true); 36 | sphereParticle.SetActive(false); 37 | InitParticleSystem(fallingParticle); 38 | } 39 | 40 | 41 | // Material. 42 | if(Input.GetKeyDown(KeyCode.Alpha1)){ 43 | currentMetaBallScript.CurrentMaterial = mats[0]; 44 | } 45 | if(Input.GetKeyDown(KeyCode.Alpha2)){ 46 | currentMetaBallScript.CurrentMaterial = mats[1]; 47 | } 48 | if(Input.GetKeyDown(KeyCode.Alpha3)){ 49 | currentMetaBallScript.CurrentMaterial = mats[2]; 50 | } 51 | 52 | // Particle speed/movement. 53 | if(Input.GetKeyDown(KeyCode.A)){ 54 | if(currentSpeed == 1.0f){ 55 | currentSpeed = 2.0f; 56 | } else if (currentSpeed == 2.0f){ 57 | currentSpeed = 0.5f; 58 | } else { 59 | currentSpeed = 1.0f; 60 | } 61 | currentMetaBallScript.ChangeSpeed(currentSpeed); 62 | } 63 | if(Input.GetKeyDown(KeyCode.S)){ 64 | isPlaying = currentMetaBallScript.TogglePlay(); 65 | } 66 | if(Input.GetKeyDown(KeyCode.D)){ 67 | isNoiseEnabled = currentMetaBallScript.ToggleNoise(); 68 | } 69 | 70 | // Camera background. 71 | if(Input.GetKeyDown(KeyCode.Z)){ 72 | Camera.main.clearFlags = CameraClearFlags.Color; 73 | Camera.main.backgroundColor = Color.white; 74 | } 75 | if(Input.GetKeyDown(KeyCode.X)){ 76 | Camera.main.clearFlags = CameraClearFlags.Color; 77 | Camera.main.backgroundColor = Color.black; 78 | } 79 | if(Input.GetKeyDown(KeyCode.C)){ 80 | Camera.main.clearFlags = CameraClearFlags.Skybox; 81 | } 82 | if(Input.GetKeyDown(KeyCode.V)){ 83 | camRig.shouldRotate = !camRig.shouldRotate; 84 | // Camera.main.clearFlags = CameraClearFlags.Skybox; 85 | } 86 | } 87 | 88 | private void InitParticleSystem(GameObject ps){ 89 | Material m = currentMetaBallScript.CurrentMaterial; 90 | currentMetaBallScript = ps.GetComponent(); 91 | currentMetaBallScript.CurrentMaterial = m; 92 | currentMetaBallScript.ChangeSpeed(currentSpeed); 93 | currentMetaBallScript.TogglePlay(isNoiseEnabled); 94 | currentMetaBallScript.TogglePlay(isPlaying); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Assets/Shaders/MetaBall_BlinnPhong.shader: -------------------------------------------------------------------------------- 1 | Shader "MetaBall/BlinnPhong" 2 | { 3 | Properties 4 | { 5 | // ******************************************************************************************** // 6 | // VARIABLE NAME NAME IN PROPERTY WINDOW EDITOR BOX DEFAULT VALUE // 7 | // ******************************************************************************************** // 8 | 9 | // Diffuse 10 | _Color ("Tint", Color) = (0.2, 0.3, 0.4, 1) 11 | _DiffusePower ("Diffuse Power", Float) = 3 12 | // Specular 13 | _SpecColor ("Specular", Color) = (0.4, 0.5, 0.6, 1) 14 | _SpecPower ("Specular Power", Float) = 3 15 | _SpecAtten ("Specular Attenuation", Range(0,1)) = 1 16 | // Fresnel 17 | _FresnelBias ("Fresnel Bias", Range(0,1)) = 1 18 | _FresnelScale ("Fresnel Scale", Range(0,2)) = 1 19 | _FresnelPower ("Fresnel Power", Range(1,10)) = 3 20 | // Radial Basis Function 21 | _K ("RadialBasis Constant", Float) = 7 22 | _Threshold ("Isosurface Threshold", Range(0,1)) = 0.5 23 | _Epsilon ("Normal Epsilon", Range(0,1)) = 0.1 24 | } 25 | SubShader 26 | { 27 | Tags { "Queue"="Transparent" "RenderType"="Transparent" } 28 | Blend SrcAlpha OneMinusSrcAlpha 29 | Cull Off // Draw all faces 30 | ZWrite Off // Don't write on the Zbuffer 31 | Lighting Off // Don't let unity do lighting calculations. 32 | 33 | Pass 34 | { 35 | CGPROGRAM 36 | #pragma vertex vert 37 | #pragma fragment frag 38 | 39 | #include "UnityCG.cginc" 40 | 41 | struct appdata 42 | { 43 | float4 vertex : POSITION; 44 | }; 45 | 46 | struct v2f 47 | { 48 | float4 vertex : SV_POSITION; 49 | float4 worldPosition : TEXCOORD0; 50 | }; 51 | 52 | uniform float3 _ParticlesPos[10]; // The world position of all particles, feeded with c# script. 53 | 54 | float4 _Color; // Diffuse Color. 55 | float _DiffusePower; // Diffuse Power. 56 | 57 | float4 _SpecColor; // Specular Color. 58 | float _SpecPower; // Specular Power. 59 | fixed _SpecAtten; // Specular Scale. 60 | 61 | fixed _FresnelBias; // Fresnel Bias (shift). 62 | fixed _FresnelScale; // Fresnel Scale. 63 | float _FresnelPower; // Fresnel Power. 64 | 65 | float _K; // Radial basis function constant. 66 | fixed _Threshold; // Isosurface threshold. 67 | fixed _Epsilon; // Epsilon to approximate normal on isosurface. 68 | 69 | float scalarField(float3 pos){ 70 | float density = 0; 71 | for(int i = 0; i < 10; i++){ 72 | float dis = distance(pos, _ParticlesPos[i].xyz); 73 | density += exp(-_K * (dis)); 74 | } 75 | return density; 76 | } 77 | 78 | float scalarField(float x, float y, float z){ 79 | float3 pos = float3(x,y,z); 80 | return scalarField(pos); 81 | } 82 | 83 | float3 calcNormal(float3 p){ 84 | float3 N; 85 | N.x = scalarField(p.x + _Epsilon, p.y, p.z) - scalarField(p.x - _Epsilon, p.y, p.z); 86 | N.y = scalarField(p.x, p.y + _Epsilon, p.z) - scalarField(p.x, p.y - _Epsilon, p.z); 87 | N.z = scalarField(p.x, p.y, p.z + _Epsilon) - scalarField(p.x, p.y, p.z - _Epsilon); 88 | // N /= 2 * _Epsilon; 89 | return -N; 90 | } 91 | 92 | float3 blinnPhong(float3 V, float3 N, float3 L){ 93 | float3 H = normalize(V + L); 94 | float NdotH = saturate(dot(N, H)); // for specular. 95 | float NdotV = saturate(dot(N, V)); // for fresnel. 96 | float LdotN = saturate(dot(L, N)); // for diffuse. 97 | 98 | float fresnel = _FresnelBias + _FresnelScale * pow(1 - NdotV, _FresnelPower); 99 | float3 diffuseTerm = _Color * clamp(LdotN, 0.5, 1); 100 | float3 specularTerm = pow(NdotH, _SpecPower) * _SpecAtten * _SpecColor ; 101 | 102 | return diffuseTerm + (specularTerm * fresnel); 103 | } 104 | 105 | v2f vert (appdata v) 106 | { 107 | v2f o; 108 | o.worldPosition = mul(unity_ObjectToWorld, v.vertex); 109 | o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 110 | return o; 111 | } 112 | 113 | 114 | float4 frag (v2f i) : SV_Target 115 | { 116 | // initial color of the fragment. 117 | float4 col = _Color; 118 | col.a = 0; 119 | 120 | // prepare to raycast. 121 | float3 viewDir = normalize(i.worldPosition - _WorldSpaceCameraPos.xyz); // World space direction from cam to fragment. 122 | float3 start = i.worldPosition - 2.0 * viewDir; // Start sampling two unit before the fragment along the viewDir. 123 | float3 p; // The sample point. 124 | 125 | // We now start sampling on the ray. We will be sampling each 0.2 points along the ray for a maximum length of 3 units. 126 | // And once we find an intersection with the isosurface, we sample again with a smaller step till we can pinpoint the 127 | // exact point of intersection. 128 | for(float i = 0; i < 3.0; i+=0.2){ 129 | p = start + i * viewDir; 130 | 131 | if(scalarField(p) > _Threshold){ 132 | // now, sample each 0.05 from (p - 0.2, p + 0.2) 133 | float3 start2 = p - 0.2 * viewDir; 134 | for(float i = 0.05; i < 0.4; i+=0.05){ 135 | p = start2 + i * viewDir; 136 | 137 | if(scalarField(p) > _Threshold){ 138 | // finally, sample each 0.01 from (p - 0.05, p + 0.05) 139 | float3 start3 = p - 0.05 * viewDir; 140 | for(float i = 0.01; i < 0.1; i+=0.01){ 141 | p = start3 + i * viewDir; 142 | if(scalarField(p) > _Threshold){ 143 | break; 144 | } 145 | } 146 | break; 147 | } 148 | } 149 | 150 | // ... calculate its normal. 151 | float3 N = normalize(calcNormal(p)); 152 | // ... calculate the lightDir. 153 | float3 L = normalize(UnityWorldSpaceLightDir(p.xyz)); // the same as normalize(_WorldSpaceLightPos0 - p.xyz); 154 | // ... illuminate with blinnPhong 155 | col.xyz = blinnPhong(-viewDir, N, L); 156 | // ... make it visible. 157 | col.a = 1; 158 | break; 159 | } 160 | } 161 | 162 | return col; 163 | } 164 | 165 | ENDCG 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Assets/Shaders/MetaBall_Toon.shader: -------------------------------------------------------------------------------- 1 | Shader "MetaBall/Toon" 2 | { 3 | Properties 4 | { 5 | // ******************************************************************************************** // 6 | // VARIABLE NAME NAME IN PROPERTY WINDOW EDITOR BOX DEFAULT VALUE // 7 | // ******************************************************************************************** // 8 | 9 | // Diffuse 10 | _Color ("Tint", Color) = (0.2, 0.3, 0.4, 1) 11 | _DiffusePower ("Diffuse Power", Float) = 3 12 | _DiffuseLevels ("DiffuseLevels", int) = 3 13 | // Specular 14 | _SpecColor ("Specular", Color) = (0.4, 0.5, 0.6, 1) 15 | _SpecPower ("Specular Power", Float) = 3 16 | _SpecAtten ("Specular Attenuation", Range(0,1)) = 1 17 | _SpecThreshold ("Specular Threshold", Range(0,1)) = 0.4 18 | // Edge 19 | _EdgeColor ("Edge Color", Color) = (0, 0, 0, 1) 20 | _EdgeThreshold ("Edge Threshold", Range(0,1)) = 0.2 21 | // Radial Basis Function 22 | _K ("RadialBasis Constant", Float) = 7 23 | _Threshold ("Isosurface Threshold", Range(0,1)) = 0.5 24 | _Epsilon ("Normal Epsilon", Range(0,1)) = 0.1 25 | } 26 | SubShader 27 | { 28 | Tags { "Queue"="Transparent" "RenderType"="Transparent" } 29 | Blend SrcAlpha OneMinusSrcAlpha 30 | Cull Off 31 | ZWrite Off // Don't write on the ZBuffer. 32 | Lighting Off // Don't let unity do lighting calculations. 33 | 34 | Pass 35 | { 36 | CGPROGRAM 37 | #pragma vertex vert 38 | #pragma fragment frag 39 | 40 | #include "UnityCG.cginc" 41 | 42 | struct appdata 43 | { 44 | float4 vertex : POSITION; 45 | }; 46 | 47 | struct v2f 48 | { 49 | float4 vertex : SV_POSITION; 50 | float4 worldPosition : TEXCOORD0; 51 | }; 52 | 53 | uniform float3 _ParticlesPos[10]; // The world position of all particles, feeded with c# script. 54 | 55 | float4 _Color; // Diffuse Color. 56 | float _DiffusePower; // Diffuse Power. 57 | int _DiffuseLevels; 58 | 59 | float4 _SpecColor; // Specular Color. 60 | float _SpecPower; // Specular Power. 61 | fixed _SpecAtten; // Specular Scale. 62 | fixed _SpecThreshold; // Specular threshold. 63 | 64 | float4 _EdgeColor; // Edge Color. 65 | fixed _EdgeThreshold; // Edge threshold. 66 | 67 | float _K; // Radial basis function constant. 68 | fixed _Threshold; // Isosurface threshold. 69 | fixed _Epsilon; // Epsilon to approximate normal on isosurface. 70 | 71 | float scalarField(float3 pos){ 72 | float density = 0; 73 | for(int i = 0; i < 10; i++){ 74 | float dis = distance(pos, _ParticlesPos[i].xyz); 75 | density += exp(-_K * (dis)); 76 | } 77 | return density; 78 | } 79 | 80 | float scalarField(float x, float y, float z){ 81 | float3 pos = float3(x,y,z); 82 | return scalarField(pos); 83 | } 84 | 85 | float3 calcNormal(float3 p){ 86 | float3 N; 87 | N.x = scalarField(p.x + _Epsilon, p.y, p.z) - scalarField(p.x - _Epsilon, p.y, p.z); 88 | N.y = scalarField(p.x, p.y + _Epsilon, p.z) - scalarField(p.x, p.y - _Epsilon, p.z); 89 | N.z = scalarField(p.x, p.y, p.z + _Epsilon) - scalarField(p.x, p.y, p.z - _Epsilon); 90 | return -N; 91 | } 92 | 93 | float3 blinnPhongToon(float3 V, float3 N, float3 L){ 94 | float3 H = normalize(V + L); 95 | float NdotH = saturate(dot(N, H)); // for specular. 96 | float NdotV = saturate(dot(N, V)); // for fresnel. 97 | float LdotN = saturate(dot(L, N)); // for diffuse. 98 | 99 | float3 diffuseTerm = _Color * floor(LdotN * _DiffuseLevels) / _DiffuseLevels; 100 | float spec = pow(NdotH, _SpecPower); 101 | float3 specularTerm = spec * _SpecAtten * _SpecColor * (spec > _SpecThreshold ? 1 : 0); 102 | float3 edge = NdotV > _EdgeThreshold ? 1 : _EdgeColor; 103 | return edge * (_Color + diffuseTerm + (specularTerm)); 104 | } 105 | 106 | v2f vert (appdata v) 107 | { 108 | v2f o; 109 | o.worldPosition = mul(unity_ObjectToWorld, v.vertex); 110 | o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 111 | return o; 112 | } 113 | 114 | float4 frag (v2f i) : SV_Target 115 | { 116 | // initial color of the fragment. 117 | float4 col = _Color; 118 | col.a = 0; 119 | 120 | // prepare to raycast. 121 | float3 viewDir = normalize(i.worldPosition - _WorldSpaceCameraPos.xyz); // World space direction from cam to fragment. 122 | float3 start = i.worldPosition - 2.0 * viewDir; // Start sampling two units before the fragment along the viewDir. 123 | float3 p; // The sampled point. 124 | 125 | // We now start sampling on the ray. We will be sampling each 0.2 points along the ray for a maximum length of 3 units. 126 | // And once we find an intersection with the isosurface, we sample again with a smaller step till we can pinpoint the 127 | // exact point of intersection. 128 | for(float i = 0; i < 3.0; i+=0.2){ 129 | p = start + i * viewDir; 130 | 131 | if(scalarField(p) > _Threshold){ 132 | // now, sample each 0.05 from (p - 0.2, p + 0.2) 133 | float3 start2 = p - 0.2 * viewDir; 134 | for(float i = 0.05; i < 0.4; i+=0.05){ 135 | p = start2 + i * viewDir; 136 | 137 | if(scalarField(p) > _Threshold){ 138 | // finally, sample each 0.01 from (p - 0.05, p + 0.05) 139 | float3 start3 = p - 0.05 * viewDir; 140 | for(float i = 0.01; i < 0.1; i+=0.01){ 141 | p = start3 + i * viewDir; 142 | if(scalarField(p) > _Threshold){ 143 | break; 144 | } 145 | } 146 | break; 147 | } 148 | } 149 | 150 | // ... calculate its normal. 151 | float3 N = normalize(calcNormal(p)); 152 | // ... calculate the lightDir. 153 | float3 L = normalize(UnityWorldSpaceLightDir(p.xyz)); // the same as normalize(_WorldSpaceLightPos0 - p.xyz); 154 | // ... illuminate with blinnPhong 155 | col.xyz = blinnPhongToon(-viewDir, N, L); 156 | // ... make it visible. 157 | col.a = 1; 158 | break; 159 | } 160 | } 161 | 162 | return col; 163 | } 164 | 165 | ENDCG 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Assets/Shaders/MetaBall_RefractionGlass.shader: -------------------------------------------------------------------------------- 1 | Shader "MetaBall/RefractionGlass" 2 | { 3 | Properties 4 | { 5 | // ******************************************************************************************** // 6 | // VARIABLE NAME NAME IN PROPERTY WINDOW EDITOR BOX DEFAULT VALUE // 7 | // ******************************************************************************************** // 8 | 9 | // Diffuse 10 | _Color ("Tint", Color) = (0.2, 0.3, 0.4, 1) 11 | _DiffusePower ("Diffuse Power", Float) = 3 12 | // Specular 13 | _SpecColor ("Specular", Color) = (0.4, 0.5, 0.6, 1) 14 | _SpecPower ("Specular Power", Float) = 3 15 | _SpecAtten ("Specular Attenuation", Range(0,1)) = 1 16 | // Fresnel 17 | _FresnelBias ("Fresnel Bias", Range(0,1)) = 1 18 | _FresnelScale ("Fresnel Scale", Range(0,2)) = 1 19 | _FresnelPower ("Fresnel Power", Range(1,10)) = 3 20 | // Reflection 21 | [NoScaleOffset] 22 | _EnvCUBE ("Environment Map", CUBE) = "cube" {} 23 | _EtaRatio ("Refraction Ratio", Range(0,1)) = 0.8 24 | // Radial Basis Function 25 | _K ("RadialBasis Constant", Float) = 7 26 | _Threshold ("Isosurface Threshold", Range(0,1)) = 0.5 27 | _Epsilon ("Normal Epsilon", Range(0,1)) = 0.1 28 | } 29 | SubShader 30 | { 31 | Tags { "Queue"="Transparent" "RenderType"="Transparent" } 32 | Blend SrcAlpha OneMinusSrcAlpha 33 | Cull Off 34 | ZWrite Off // Don't write on the ZBuffer. 35 | Lighting Off // Don't let unity do lighting calculations. 36 | 37 | Pass 38 | { 39 | CGPROGRAM 40 | #pragma vertex vert 41 | #pragma fragment frag 42 | 43 | #include "UnityCG.cginc" 44 | 45 | struct appdata 46 | { 47 | float4 vertex : POSITION; 48 | }; 49 | 50 | struct v2f 51 | { 52 | float4 vertex : SV_POSITION; 53 | float4 worldPosition : TEXCOORD0; 54 | }; 55 | 56 | uniform float3 _ParticlesPos[10]; // The world position of all particles, feeded with c# script. 57 | 58 | float4 _Color; // Diffuse Color. 59 | float _DiffusePower; // Diffuse Power. 60 | 61 | float4 _SpecColor; // Specular Color. 62 | float _SpecPower; // Specular Power. 63 | fixed _SpecAtten; // Specular Scale. 64 | 65 | fixed _FresnelBias; // Fresnel Bias (shift). 66 | fixed _FresnelScale; // Fresnel Scale. 67 | float _FresnelPower; // Fresnel Power. 68 | 69 | float _K; // Radial basis function constant. 70 | fixed _Threshold; // Isosurface threshold. 71 | fixed _Epsilon; // Epsilon to approximate normal on isosurface. 72 | 73 | samplerCUBE _EnvCUBE; 74 | fixed _EtaRatio; 75 | 76 | float scalarField(float3 pos){ 77 | float density = 0; 78 | for(int i = 0; i < 10; i++){ 79 | float dis = distance(pos, _ParticlesPos[i].xyz); 80 | density += exp(-_K * (dis)); 81 | } 82 | return density; 83 | } 84 | 85 | float scalarField(float x, float y, float z){ 86 | float3 pos = float3(x,y,z); 87 | return scalarField(pos); 88 | } 89 | 90 | float3 calcNormal(float3 p){ 91 | float3 N; 92 | N.x = scalarField(p.x + _Epsilon, p.y, p.z) - scalarField(p.x - _Epsilon, p.y, p.z); 93 | N.y = scalarField(p.x, p.y + _Epsilon, p.z) - scalarField(p.x, p.y - _Epsilon, p.z); 94 | N.z = scalarField(p.x, p.y, p.z + _Epsilon) - scalarField(p.x, p.y, p.z - _Epsilon); 95 | return -N; 96 | } 97 | 98 | float3 blinnPhongRefraction(float3 V, float3 N, float3 L){ 99 | float3 H = normalize(V + L); 100 | float3 R = reflect(-V, N); 101 | float3 T = refract(-V, N, _EtaRatio); 102 | T = reflect(-T, -V); 103 | 104 | float NdotH = saturate(dot(N, H)); // for specular. 105 | float NdotV = saturate(dot(N, V)); // for fresnel. 106 | float LdotN = saturate(dot(L, N)); // for diffuse. 107 | 108 | // Compute reflected color 109 | float3 rc0 = texCUBE(_EnvCUBE, R); 110 | float3 rc1 = texCUBElod(_EnvCUBE, float4(R, 6.0)); 111 | float3 reflectedColor = 0.8 * rc0 + 0.2 * rc1; 112 | 113 | // Compute refracted color. 114 | rc0 = texCUBE(_EnvCUBE, T); 115 | rc1 = texCUBElod(_EnvCUBE, float4(T, 5.0)); 116 | float3 refractedColor = 0.2 * rc0 + 0.8 * rc1; 117 | 118 | float fresnel = _FresnelBias + _FresnelScale * pow(1 - NdotV, _FresnelPower); 119 | float3 col = lerp(refractedColor, reflectedColor, fresnel); 120 | 121 | 122 | float3 diffuseTerm = col * clamp(LdotN, 0.2, 1); 123 | float3 specularTerm = pow(NdotH, _SpecPower) * _SpecAtten * _SpecColor ; 124 | 125 | return _DiffusePower * _Color * (diffuseTerm + specularTerm); 126 | } 127 | 128 | v2f vert (appdata v) 129 | { 130 | v2f o; 131 | o.worldPosition = mul(unity_ObjectToWorld, v.vertex); 132 | o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 133 | return o; 134 | } 135 | 136 | float4 frag (v2f i) : SV_Target 137 | { 138 | // initial color of the fragment. 139 | float4 col = _Color; 140 | col.a = 0; 141 | 142 | // prepare to raycast. 143 | float3 viewDir = normalize(i.worldPosition - _WorldSpaceCameraPos.xyz); // World space direction from cam to fragment. 144 | float3 start = i.worldPosition - 2.0 * viewDir; // Start sampling two units before the fragment along the viewDir. 145 | float3 p; // The sampled point. 146 | 147 | // We now start sampling on the ray. We will be sampling each 0.2 points along the ray for a maximum length of 3 units. 148 | // And once we find an intersection with the isosurface, we sample again with a smaller step till we can pinpoint the 149 | // exact point of intersection. 150 | for(float i = 0; i < 3.0; i+=0.2){ 151 | p = start + i * viewDir; 152 | 153 | if(scalarField(p) > _Threshold){ 154 | // now, sample each 0.05 from (p - 0.2, p + 0.2) 155 | float3 start2 = p - 0.2 * viewDir; 156 | for(float i = 0.05; i < 0.4; i+=0.05){ 157 | p = start2 + i * viewDir; 158 | 159 | if(scalarField(p) > _Threshold){ 160 | // finally, sample each 0.01 from (p - 0.05, p + 0.05) 161 | float3 start3 = p - 0.05 * viewDir; 162 | for(float i = 0.01; i < 0.1; i+=0.01){ 163 | p = start3 + i * viewDir; 164 | if(scalarField(p) > _Threshold){ 165 | break; 166 | } 167 | } 168 | break; 169 | } 170 | } 171 | 172 | // ... calculate its normal. 173 | float3 N = normalize(calcNormal(p)); 174 | // ... calculate the lightDir. 175 | float3 L = normalize(UnityWorldSpaceLightDir(p.xyz)); // the same as normalize(_WorldSpaceLightPos0 - p.xyz); 176 | // ... illuminate with blinnPhong 177 | col.xyz = blinnPhongRefraction(-viewDir, N, L); 178 | // ... make it visible. 179 | col.a = 1; 180 | break; 181 | } 182 | } 183 | 184 | return col; 185 | } 186 | 187 | ENDCG 188 | } 189 | } 190 | } 191 | --------------------------------------------------------------------------------