Unity 社区
3
4

Shadertoy2Unity - 搬运工 - OceanWithJellyFish

郡墙
Programmer
阅读 728
2020年3月14日
纯shader实现海底水母世界 无贴图
老规矩 先看效果图
海底水母
Show me Code!
后续补充拆解步骤,感兴趣的小伙伴可以收藏文章~
Shader "Unlit/Ocean" { Properties { _BodyLight("Body Light",Color) = (1, 0.1, 0.5,1) _BodyLightting("Body Lightting",Color) = (1, 0.5, 0.1,1) _Water("Water",Color) = (0.1, 0.5, 1,1) _DepthWater("DepthWater",Color) = (0.1, 0.5, 0.6,1) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #define MAX_STEPS 100. #define VOLUME_STEPS 8 #define MIN_DISTANCE 0.1 #define MAX_DISTANCE 100. #define HIT_DISTANCE .01 #define S(x,y,z) smoothstep(x,y,z) #define B(x,y,z,w) S(x-z, x+z, w)*S(y+z, y-z, w) #define sat(x) clamp(x,0.,1.) #define SIN(x) sin(x)*.5+.5 #define mod(x,y) (x-y*floor(x/y)) float4 _BodyLight; float4 _Water; float4 _BodyLightting; float4 _DepthWater; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = ComputeScreenPos(o.vertex); return o; } static const float3 lf = float3(1., 0., 0.); static const float3 up = float3(0., 1., 0.); static const float3 fw = float3(0., 0., 1.); static const float pi = 3.141592653589793238; static const float twopi = 6.283185307179586; float3 bg; // global background color float3 accent; // color of the phosphorecence float N1(float x) { return frac(sin(x)*5346.1764); } float N2(float x, float y) { return N1(x + y*23414.324); } float N3(float3 p) { p = frac(p*0.3183099 + .1); p *= 17.0; return frac(p.x*p.y*p.z*(p.x + p.y + p.z)); } struct ray { float3 o; float3 d; }; struct camera { float3 p; // the position of the camera float3 forward; // the camera forward vector float3 left; // the camera left vector float3 up; // the camera up vector float3 center; // the center of the screen, in world coords float3 i; // where the current ray intersects the screen, in world coords ray ray; // the current ray: from cam pos, through current uv projected on screen float3 lookAt; // the lookat point float zoom; // the zoom factor }; struct de { // data type used to pass the various bits of information used to shade a de object float d; // final distance to field float m; // material float3 uv; float pump; float3 id; float3 pos; // the world-space coordinate of the fragment }; struct rc { // data type used to handle a repeated coordinate float3 id; // holds the floor'ed coordinate of each cell. Used to identify the cell. float3 h; // half of the size of the cell float3 p; // the repeated coordinate //float3 c; // the center of the cell, world coordinates }; rc Repeat(float3 pos, float3 size) { rc o; o.h = size*.5; o.id = floor(pos / size); // used to give a unique id to each cell o.p = mod(pos, size) - o.h; //o.c = o.id*size+o.h; return o; } camera cam; void CameraSetup(float2 uv, float3 position, float3 lookAt, float zoom) { cam.p = position; cam.lookAt = lookAt; cam.forward = normalize(cam.lookAt - cam.p); cam.left = cross(up, cam.forward); cam.up = cross(cam.forward, cam.left); cam.zoom = zoom; cam.center = cam.p + cam.forward*cam.zoom; cam.i = cam.center + cam.left*uv.x + cam.up*uv.y; cam.ray.o = cam.p; // ray origin = camera position cam.ray.d = normalize(cam.i - cam.p); // ray direction is the vector from the cam pos through the point on the imaginary screen } // ============== Functions I borrowed ;) // 3 out, 1 in... DAVE HOSKINS float3 N31(float p) { float3 p3 = frac((p) * float3(.1031, .11369, .13787)); p3 += dot(p3, p3.yzx + 19.19); return frac(float3((p3.x + p3.y)*p3.z, (p3.x + p3.z)*p3.y, (p3.y + p3.z)*p3.x)); } // DE functions from IQ float smin(float a, float b, float k) { float h = clamp(0.5 + 0.5*(b - a) / k, 0.0, 1.0); return lerp(b, a, h) - k*h*(1.0 - h); } float smax(float a, float b, float k) { float h = clamp(0.5 + 0.5*(b - a) / k, 0.0, 1.0); return lerp(a, b, h) + k*h*(1.0 - h); } float sdSphere(float3 p, float3 pos, float s) { return (length(p - pos) - s); } // From http://mercury.sexy/hg_sdf float2 pModPolar(inout float2 p, float repetitions, float fix) { float angle = twopi / repetitions; float a = atan2(p.y, p.x) + angle / 2.; float r = length(p); float c = floor(a / angle); a = mod(a, angle) - (angle / 2.)*fix; p = float2(cos(a), sin(a))*r; return p; } // ------------------------- float Dist(float2 P, float2 P0, float2 P1) { //2d point-line distance float2 v = P1 - P0; float2 w = P - P0; float c1 = dot(w, v); float c2 = dot(v, v); if (c1 <= 0.) // before P0 return length(P - P0); float b = c1 / c2; float2 Pb = P0 + b*v; return length(P - Pb); } float3 ClosestPoint(float3 ro, float3 rd, float3 p) { // returns the closest point on ray r to point p return ro + max(0., dot(p - ro, rd))*rd; } float2 RayRayTs(float3 ro1, float3 rd1, float3 ro2, float3 rd2) { // returns the two t's for the closest point between two rays // ro+rd*t1 = ro2+rd2*t2 float3 dO = ro2 - ro1; float3 cD = cross(rd1, rd2); float v = dot(cD, cD); float t1 = dot(cross(dO, rd2), cD) / v; float t2 = dot(cross(dO, rd1), cD) / v; return float2(t1, t2); } float DistRaySegment(float3 ro, float3 rd, float3 p1, float3 p2) { // returns the distance from ray r to line segment p1-p2 float3 rd2 = p2 - p1; float2 t = RayRayTs(ro, rd, p1, rd2); t.x = max(t.x, 0.); t.y = clamp(t.y, 0., length(rd2)); float3 rp = ro + rd*t.x; float3 sp = p1 + rd2*t.y; return length(rp - sp); } float2 sph(float3 ro, float3 rd, float3 pos, float radius) { // does a ray sphere intersection // returns a float2 with distance to both intersections // if both a and b are MAX_DISTANCE then there is no intersection float3 oc = pos - ro; float l = dot(rd, oc); float det = l*l - dot(oc, oc) + radius*radius; if (det < 0.0) return (MAX_DISTANCE); float d = sqrt(det); float a = l - d; float b = l + d; return float2(a, b); } float3 background(float3 r) { float x = atan2(r.x, r.z); // from -pi to pi float y = pi*0.5 - acos(r.y); // from -1/2pi to 1/2pi float3 col = bg*(1. + y); float t = _Time.y; // add god rays float a = sin(r.x); float beam = sat(sin(10.*x + a*y*5. + t)); beam *= sat(sin(7.*x + a*y*3.5 - t)); float beam2 = sat(sin(42.*x + a*y*21. - t)); beam2 *= sat(sin(34.*x + a*y*17. + t)); beam += beam2; col *= 1. + beam*.05; return col; } float remap(float a, float b, float c, float d, float t) { return ((t - a) / (b - a))*(d - c) + c; } de map(float3 p, float3 id) { float t = _Time.y*2.; float N = N3(id); de o; o.m = 0.; float x = (p.y + N*twopi)*1. + t; float r = 1.; float pump = cos(x + cos(x)) + sin(2.*x)*.2 + sin(4.*x)*.02; x = t + N*twopi; p.y -= (cos(x + cos(x)) + sin(2.*x)*.2)*.6; p.xz *= 1. + pump*.2; float d1 = sdSphere(p, float3(0., 0., 0.), r); float d2 = sdSphere(p, float3(0., -.5, 0.), r); o.d = smax(d1, -d2, .1); o.m = 1.; if (p.y<.5) { float sway = sin(t + p.y + N*twopi)*S(.5, -3., p.y)*N*.3; p.x += sway*N; // add some sway to the tentacles p.z += sway*(1. - N); float3 mp = p; mp.xz = pModPolar(mp.xz, 6., 0.); float d3 = length(mp.xz - float2(.2, .1)) - remap(.5, -3.5, .1, .01, mp.y); if (d3MAX_DISTANCE) break; d += min(s.d, dC); // move to distance to next cell or surface, whichever is closest } if (s.d0.) { float3 n = calcNormal(o); float lambert = sat(dot(n, L)); float3 R = reflect(camRay.d, n); float fresnel = sat(1. + dot(camRay.d, n)); float trans = (1. - fresnel)*.5; float3 ref = background(R); float fade = 0.; if (o.m == 1.) { // hood color float density = 0.; for (float i = 0.; i
发布于技术交流
4条评论

AI

全新AI功能上线

1. 基于Unity微调:专为Unity优化,提供精准高效的支持。

2. 深度集成:内置于团结引擎,随时查阅与学习。

3. 多功能支持:全面解决技术问题与学习需求。

AI