├── 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 | 
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 |
10 | -
RMB and move mouse to rotate camera.
11 | -
Mouse Wheel to zoom in/out.
12 | -
1, 2, 3 to change between 3 shader varients.
13 | -
q, w to change between 2 particle system.
14 | -
a to change the speed of the particles between (0.5, 1, 2)
15 | -
s to stop the particle system.
16 | -
d to disable the noise effect of the particle system.
17 | -
z, x, c to change the background.
18 | -
v to stop the auto rotation of the camera
19 |
20 |
21 | ## Usage
22 |
23 | - Create a new Particle System and make sure it is set to Prewarm and the Max Particles are 10.
24 | - Create a new material with one of the provided shaders.
25 | - Add the material to the renderer component in the Particle System.
26 | - Add the script MetaBalls.cs to the Particle System.
27 | - Enjoy a mesmerizing effect.
28 |
29 |
30 | ## TO DO
31 |
32 | - Further optimise the raymarching on the particles.
33 | - Write a main cginclude file to allow reusability and extensibility.
34 | - Further integrate the shader it can take colours directly from the Particle System.
35 | - Add support to Blend Probes.
36 | - Support huge amounts of particles. (Currently only support max of 10 particles)
37 |
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 |
--------------------------------------------------------------------------------