Slide 1

Slide 1 text

6OJUZºϨΠϚʔνϯά
 ʹΑΔө૾੍࡞ͷ࣮ફख๏ 2019/06/19 KLab TECH Meetup #4 @gam0022 / Sho HOSODA

Slide 2

Slide 2 text

ࣗݾ঺հ • @gam0022 / Sho HOSODA • KLabגࣜձࣾ ৽ଔ5೥໨ • UnityΤϯδχΞ • γΣʔμʔ͕޷͖ 2

Slide 3

Slide 3 text

WORMHOLE by gam0022 & sadakkey ʢൃදͷ୊ࡐʣ 2ͭͷੈքΛʮϫʔϜϗʔϧͰۭؒҠಈʯ͢ΔUnityʹΑΔө૾࡞඼ 3 ඇݱ࣮ͳσδλϧۭؒ ਫฏઢͷ޿͕Δࣗવۭؒ Tokyo Demo Fest 2018 ͷ Combined Demo Compo ༏উ࡞඼

Slide 4

Slide 4 text

ϨΠϚʔνϯάͱσϞγʔϯ • ڑ཭ؔ਺ʢdistance functionʣͱ͍͏਺ࣜͰܗঢ়Λఆٛ ‣ 3DϞσϧΛ༻ҙ͢Δඞཁ͕ͳ͍ ‣ ݫ͍͠༰ྔͷ੍໿ͷ͋ΔσϞγʔϯͷ෦໳ʢ4k intro౳ʣͱ૬ੑ͕ྑ͍ • TDFʢTokyo Demo Festʣͷ্Ґ࡞඼΋ϨΠϚʔνϯάΛར༻ 4 WORMHOLE by gam0022 & sadakkey 1st place@Combined Demo Compo, TDF2018 2nd stage BOSS by 0x4015&YET11 1st place@Combined Demo Compo, TDF2016 Shift by FMS_Cat 1st place@Combined Demo Compo, TDF2017

Slide 5

Slide 5 text

ڑ཭ؔ਺ͷ͓͞Β͍ ڑ཭ؔ਺ = ఺p͔Β෺ମද໘΁ͷ࠷୹ڑ཭Λฦؔ͢਺ 5 float sdSphere( vec3 p, float s ) { return length(p)-s; } float udBox( vec3 p, vec3 b ) { return length(max(abs(p)-b,0.0)); } http://iquilezles.org/www/articles/distfunctions/distfunctions.htm

Slide 6

Slide 6 text

ϨΠϚʔνϯάΛ׬શʹཧղͰ͖Δࢿྉ • σϞγʔϯ΁Α͏ͦ͜ʢCEDEC 2017ʣ • γΣʔμ͚ͩͰੈքΛ૑Δʂthree.jsʹΑΔϨΠϚʔνϯά 6

Slide 7

Slide 7 text

ܗঢ়ɹ࣭ײɹԋग़ 7 ө૾Λߏ੒͢Δ3ཁૉ

Slide 8

Slide 8 text

ܗঢ় 8

Slide 9

Slide 9 text

ܗঢ়ϞσϦϯά 9

Slide 10

Slide 10 text

τϯωϧʢඇݱ࣮ͳσδλϧۭؒʣ͸ڑ཭ؔ਺ʹΑΔϞσϦϯά 10

Slide 11

Slide 11 text

τϯωϧͷڑ཭ؔ਺ͷઃܭΞϓϩʔν طଘͷϑϥΫλϧਤܗΛΞϨϯδ 11 MengerSponge IFSͷύϥϝʔλΛௐ੔ foldRotateΛద༻

Slide 12

Slide 12 text

IFSʢIterated function systemʣͱ͸ • ࣗ਎ͷॖখίϐʔΛॏͶ߹ΘͤΔ͜ͱ ͰϑϥΫλϧਤܗΛͭ͘ΔςΫχοΫ • forϧʔϓ ͷதͰૢ࡞Λ܁Γฦ͢ ‣ fold ‣ ֦େॖখ ‣ ฏߦҠಈ 12 // IFSʹΑΔMengerSpongeͷڑ཭ؔ਺ float dMenger(float3 z0, float3 offset, float scale) { float4 z = float4(z0, 1.0); for (int n = 0; n < 4; n++) { z = abs(z); if (z.x < z.y) z.xy = z.yx; if (z.x < z.z) z.xz = z.zx; if (z.y < z.z) z.yz = z.zy; z *= scale; z.xyz -= offset * (scale - 1.0); if (z.z < -0.5 * offset.z * (scale - 1.0)) z.z += offset.z * (scale - 1.0); } return (length(max(abs(z.xyz) - float3(1.0, 1.0, 1.0), 0.0)) - 0.05) / z.w; } sdBox ➞ fold ➞ ֦େॖখ ฏߦҠಈ ➞

Slide 13

Slide 13 text

IFSʢIterated function systemʣͷΞϨϯδ • OffsetʢฏߦҠಈʣͱ Scaleʢ֦େॖখʣ
 ͷύϥϝʔλʹΑͬͯܗঢ়΋มԽ͢Δ 13 // IFSʹΑΔMengerSpongeͷڑ཭ؔ਺ float dMenger(float3 z0, float3 offset, float scale) { float4 z = float4(z0, 1.0); for (int n = 0; n < 4; n++) { z = abs(z); if (z.x < z.y) z.xy = z.yx; if (z.x < z.z) z.xz = z.zx; if (z.y < z.z) z.yz = z.zy; z *= scale; z.xyz -= offset * (scale - 1.0); if (z.z < -0.5 * offset.z * (scale - 1.0)) z.z += offset.z * (scale - 1.0); } return (length(max(abs(z.xyz) - float3(1.0, 1.0, 1.0), 0.0)) - 0.05) / z.w; } Offset = (1, 1, 1) Scale = 3 Offset = (0.79, 1.1, 0.47) Scale = 2.31

Slide 14

Slide 14 text

foldRotateͱ͸ ͋Δ࣠Λத৺ͱͯ͠Ұఆͷ֯౓Ͱճస͠ͳ͕ΒۭؒΛંΓͨͨΉૢ࡞ 14 n = 3 θ = 120° n = 4 θ = 90° n = 6 θ = 60° n = 8 θ = 45°

Slide 15

Slide 15 text

alias foldRotate = polarMod ಉ͡ૢ࡞͕ͩɺݺͼํʢղऍʣʹ೿ൊʢफڭʣ͕͋Δ 15 GPME3PUBUFʢճసͷંΓͨͨΈʣ QPMBS.PEʢۃ࠲ඪͷ.PEʣ @gam0022 @kanetaaaaa

Slide 16

Slide 16 text

foldRotateͷ࣮૷ • 2Dͷճసߦྻ 16 // 2Dͷճసߦྻͷੜ੒ float2x2 rotate(in float a) { float s = sin(a), c = cos(a); return float2x2(c, s, -s, c); } // ճస fold // https://www.shadertoy.com/view/Mlf3Wj float2 foldRotate(in float2 p, in float s) { float a = PI / s - atan2(p.x, p.y); float n = PI2 / s; a = floor(a / n) * n; p = mul(rotate(a), p); return p; } • foldRotate ‣ ۃ࠲ඪͷ֯౓ΛٻΊΔ ‣ ଐ͍ͯ͠ΔྖҬʹԠͯ͡ճస

Slide 17

Slide 17 text

foldRotateͷৄࡉ͸ϒϩάͰ ڑ཭ؔ਺ͷfoldʢંΓͨͨΈʣʹΑΔܗঢ়ઃܭ | gam0022.net 17

Slide 18

Slide 18 text

τϯωϧͷڑ཭ؔ਺ͷ׬੒ʂ 18 // IFSʹΑΔMengerSpongeͷڑ཭ؔ਺ float dMenger(float3 z0, float3 offset, float scale) { float4 z = float4(z0, 1.0); for (int n = 0; n < 4; n++) { z = abs(z); if (z.x < z.y) z.xy = z.yx; if (z.x < z.z) z.xz = z.zx; if (z.y < z.z) z.yz = z.zy; z *= scale; z.xyz -= offset * (scale - 1.0); if (z.z < -0.5 * offset.z * (scale - 1.0)) z.z += offset.z * (scale - 1.0); } return (length(max(abs(z.xyz) - float3(1.0, 1.0, 1.0), 0.0)) - 0.05) / z.w; } // 2Dͷճసߦྻͷੜ੒ float2x2 rotate(in float a) { float s = sin(a), c = cos(a); return float2x2(c, s, -s, c); } // ճస fold // https://www.shadertoy.com/view/Mlf3Wj float2 foldRotate(in float2 p, in float s) { float a = PI / s - atan2(p.x, p.y); float n = PI2 / s; a = floor(a / n) * n; p = mul(rotate(a), p); return p; } inline float DistanceFunction(float3 pos) { // ճసfoldͷద༻ pos.yx = foldRotate(pos.yx, _MengerFold); return dMenger(pos, _MengerOffset, _MengerScale); } Θ͔ͣߦͷίʔυͰෳࡶͳܗঢ়ΛఆٛͰ͖ͨʂ .FOHFS4QPOHF GPME3PUBUF

Slide 19

Slide 19 text

࣭ײ 19

Slide 20

Slide 20 text

࣭ײϥΠςΟϯάॲཧ 20

Slide 21

Slide 21 text

σΟϑΝʔυϨϯμϦϯάΛ࠾༻ σΟϑΝʔυϨϯμϦϯά͸2ͭͷύεͰγʔϯΛඳը 21 G-Bufferύε ϥΠςΟϯάʹඞཁͳ৘ใʢGόοϑΝʣΛੜ੒ RT0: Diffuse color (RGB), occlusion (A). RT1: Specular color (RGB), roughness (A). ɹRT3: Emission + lighting + lightmaps + reflection probes buffer. RT2: World space normal (RGB), unused (A). Depth + Stencil Lightingύε GόοϑΝΛݩʹ
 ϥΠςΟϯάΛܭࢉ

Slide 22

Slide 22 text

σΟϑΝʔυϨϯμϦϯάΛ࠾༻ͨ͠3ͭͷཧ༝ ᶃ ڑ཭ؔ਺ͱϙϦΰϯ͕ࠞࡏͨ͠γʔϯͷҰ؏ͨ͠ϥΠςΟϯάॲཧ͕Մೳ ‣ ϨΠϚʔνϯάͷ݁ՌΛG-Bufferʹॻ͖ࠐΉ
 G-BufferύεͷγΣʔμʔΛ࣮૷͢Ε͹OK ‣ @hecomi ͞Μͷ uRaymarching Λར༻͢Δͱָ ᶄ 6OJUZඪ४ͷ-JHIUJOHύεΛར༻Ͱ͖Δ ‣ ࣗ෼ͰϥΠςΟϯάॲཧΛ࣮૷͠ͳͯ͘΋
 Unityͷશछྨͷޫݯ΍ReflectionProbeʹରԠͰ͖Δ ᶅ େྔͷޫݯͳͲϦονͳϥΠςΟϯάʹڧ͍ 22 @hecomi

Slide 23

Slide 23 text

σΟϑΝʔυϨϯμϦϯάͷϥΠςΟϯάΛΧελϚΠζ σΟϑΝʔυϨϯμϦϯάͷऑ఺ ‣ γʔϯશମΛಉ͡ॲཧͰϥΠςΟϯά͢ΔͨΊɺ
 ϚςϦΞϧ͝ͱʹϥΠςΟϯάΛΧελϚΠζ͠ʹ͍͘ ‣ LightingύεʹखΛՃ͑Δͷ͸Өڹൣғ͕େ͖͍ɾख͕͔͔ؒΔ ղܾࡦɿ&NJTTJWFΛ׆༻ ‣ EmissiveҎ֎ͷύϥϝʔλΛ0ʹ͢Δͱɺ
 Emissiveͷ৭͕ͦͷ··࠷ऴ݁ՌʹͳΔ ‣ ಠࣗͷϥΠςΟϯά݁ՌΛEmissiveʹ֨ೲ 23

Slide 24

Slide 24 text

EmissiveʹΑΔσΟϑΝʔυϨϯμϦϯάͷϥΠςΟϯάͷௐ੔ ϑϨωϧ൓ࣹͷޮՌΛ Emissive ʹॻ͖ࠐΉ͜ͱͰɺϥΠςΟϯάΛௐ੔ 24 ϑϨωϧͳ͠ ϑϨωϧ͋Γ

Slide 25

Slide 25 text

ԋग़ 25

Slide 26

Slide 26 text

ԋग़㱩Ξχϝʔγϣϯ 26

Slide 27

Slide 27 text

ςΩετͷΞχϝʔγϣϯ 27

Slide 28

Slide 28 text

TextMeshProͱ͸ʁ • SDF(Signed Distance Field)Λ࢖ͬͯߴ඼࣭ʹϑΥϯτΛϨϯμϦϯά ‣ จࣈͷྠֲ·Ͱͷڑ཭Λըૉ஋ʹͨ͠ը૾ ‣ ֦େͯ͠΋δϟΪ͕໨ཱͨͳ͍ ‣ ϨΠϚʔνϯάͷڑ཭ؔ਺ͱಉ֓͡೦ʢ2Dͱ3Dͷҧ͍ʣ 28 SDFςΫενϟ TextMeshProͷϨϯμϦϯά݁Ռ

Slide 29

Slide 29 text

TextMeshProͷඳըͷ࢓૊Έ • CPUͰ1จࣈͣͭMeshΛੜ੒ʢSDFςΫενϟ༻ͷUV͸௖఺σʔλʹʣ • ϑϥάϝϯτγΣʔμʔͰSDFͷςΫενϟ͔Β
 ϑΥϯτͷ಺֎ͷ൑ఆͯ͠ϨϯμϦϯά 29 TextMeshProͷϫΠϠʔϑϨʔϜදࣔ

Slide 30

Slide 30 text

γΣʔμʔΛॻ͚͹ɺ 5FYU.FTI1SPͷϨϯμϦϯάΛ ࣗ༝ʹΧελϚΠζͰ͖Δ 30

Slide 31

Slide 31 text

TextMeshProͷγΣʔμʔͷΧελϚΠζํ๏ 1. TextMeshProͷγΣʔμʔΛίϐʔ ‣ TMP_SDF-Mobile.shader 
 ͕࣮૷͕γϯϓϧͳͷͰΦεεϝ 2. γΣʔμʔΛվ଄ ‣ ৭Λܾఆ͢Δ෦෼ ‣ SDFͷϑΣον෦෼ 3. TextMeshProͷΠϯεϖΫλ͔Β
 վ଄ͨ͠γΣʔμʔΛઃఆ 31

Slide 32

Slide 32 text

TextMeshProͷγΣʔμʔͷΧελϚΠζྫ 32 ϒϥ΢ϯ؅෩ sinؔ਺Ͱ໛༷ͱಈ͖Λ͚ͭΔ ϞʔϑΟϯά 2छྨͷSDFΛϒϨϯυ

Slide 33

Slide 33 text

TextMeshProͷγΣʔμʔͷΧελϚΠζྫ จࣈΛύϥύϥͱग़ݱɾফࣦͤ͞ΔΤϑΣΫτ 33 // PIXEL SHADER fixed4 PixShader(pixel_t input) : SV_Target { - half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half2 uv = input.texcoord0.xy; + uv.y = clamp(uv.y, 0.0, 0.5 + 0.5 * sin(_Time.y)); + half d = tex2D(_MainTex, uv).a * input.param.x; half4 c = input.faceColor * saturate(d - input.param.w); SDFςΫενϟΛϑΣον͢Δ UVΛ࣌ؒͰ clamp ϑΥϯτΛҾ͖৳͹͢ޮՌ͕ੜ·ΕΔ

Slide 34

Slide 34 text

ৄࡉ͸QiitaͰ [Unity] ΧελϜγΣʔμʔͰTextMeshProʹಠ૑తͳԋग़ΛՃ͑Δ 34

Slide 35

Slide 35 text

͜͜·Ͱͷ·ͱΊ γΣʔμʔΛ࢖͏ͱɺ୹͍ίʔυͰଟ࠼ͳදݱ͕Ͱ͖Δ 35 ෳࡶͳܗঢ় ϦΞϧͳ࣭ײ Χοί͍͍ԋग़

Slide 36

Slide 36 text

Unity Timeline Λ ׆༻ͨ͠ԋग़ 36

Slide 37

Slide 37 text

ԋग़ͷࢼߦࡨޡͷΠςϨʔγϣϯʹUnity TimelineΛ׆༻ Unity Timelineͷ׆༻ 37 Timeline Window

Slide 38

Slide 38 text

Animation Track • ϨΠϚʔνϯά༻ͷϚςϦΞϧͷύϥϝʔλ੍ޚ • ϙετΤϑΣΫτ༻ͷϚςϦΞϧͷύϥϝʔλ੍ޚ 38

Slide 39

Slide 39 text

Custom Track for TextMeshPro TextMeshProͷςΩετΛॻ͖׵͑ΔTrackΛࣗ࡞ ‣ ඪ४TrackͰ͸࣮ݱͰ͖ͳ͔ͬͨ 39

Slide 40

Slide 40 text

Chinemachine Track ΧϝϥϫʔΫʹ͸ChinemachineΛར༻ 40

Slide 41

Slide 41 text

ԋग़ͷ·ͱΊ • نଇతͳಈ͖͸γΣʔμʔ͕ಘҙ ‣ نଇత = ਺ࣜͰදݱ͕Ͱ͖Δ ‣ ྫ: ԻָͷBPMʹ߹ΘͤͯνΧνΧ఺໓ͤ͞Δ • ෆنଇͳಈ͖͸Unity Timeline͕ಘҙ ‣ ྫ: ΧϝϥϫʔΫ 41 ෳ਺ͷಓ۩Λ࢖͍෼͚Δ͜ͱͰɺ ࡞ۀޮ཰ΛUP͠Α͏✌

Slide 42

Slide 42 text

WORMHOLEͷؔ࿈৘ใ • UnityϓϩδΣΫτΛGitHubʹެ։த ‣ https://github.com/gam0022/unity-demoscene ‣ Assets/Demoscene/Projects/2018-10-28-TDF2018/ • ϒϩά ‣ Tokyo Demo Fest 2018ͷDemo Compo༏উ࡞඼ͷղઆʢάϥϑΟοΫฤʣ • KLab Tech Book Vol.4 ‣ ٕज़ॻయ6ͰಉਓࢽΛ൦෍͠·͢&ిࢠ൛μ΢ϯϩʔυϖʔδ 42

Slide 43

Slide 43 text

γΣʔμʔ͸ຐ๏ͷಓ۩✨ ԿͰ΋Ͱ͖Δɹ࠷ڧ ΈΜͳγΣʔμʔΛ΍Ζ͏☺ 43