- /
-
Refraction
on 30 Oct 2024
- 74
- 522
- 1
- 6
- 2000
Cite your audio source here (if applicable): The Tortise and the Hare (Flook)
drawframe(1);
Write your drawframe function below
function drawframe(f)
persistent S Q
% Shorteners & convenience functions
l=@linspace;
v=@(x)x./vecnorm(x);
C=@circshift;
cc=@(x)C(x,[-f,-f]*4);
r=@(x)x/2+fftshift(x)/2;
F=@ifft2;
R=@reshape;
B=@erf;
Y=@sqrt;
P=@randn;
J=@meshgrid;
% Make sand and rocks
rng(2,'v4');
N=768; % Multiple of 96 for smooth transition
q=l(-1,1,N+1);
q=q(1:N);
[q1,q2]=J(q);
k=exp(6i*P(N))./(q.^2+q'.^2+2e-6); % Complex spatial noise
k1=B(abs(F(k))*.5)*0.6-.36; % Rocks
n=hann(N)*hann(N)'; % K-space smoother
k2=abs(F(k.*n.^300))*3+P(N)/200; % Sand
k2=C(k2+sin(q*30*pi)/20,[-1,-1]*30*-1)/20-.2; % Adding ripples & offsets to sand
[k,ki]=max(cc(cat(3,r(k1),r(k2))),[],3); % Combining & indices for coloration
% Sky function: image will be refracted through interface
[x,y,z]=sphere(100);
s=v([1;1;1]);
g=.5-B((Y(sum(((cat(3,x,y,z)-permute(s,[3,2,1])).^2),3))-.5)*5)/2; % Sky & sun
g=g+B(l(-1.5,1,101)'*3)/2+.5; % Adding horizon
[A,E]=J(l(-pi,pi,101),l(-pi/2,pi/2,101)); % Associated grid for interpolation
% Angle span
ags=l(0,2*pi,97);
% Camera positions, targets & up-vectors
p=sin(ags(1:end-1))/40;
cy=[p-.8;-p-.8;-cos(2*ags(1:end-1))/15+.05];
cu=C([-p;p;ones(1,96)],[0,5])*1.3;
ct=C(cy.*[1;1;1.4],[0,-5])+[.2;.2;0];
c=cy(:,f); % Current camera position
% Water surface spectrum generation function
d=@(a,b,c,h)ifftshift(n.^10.*exp(6i*P(N)+h*1i)./((q+a).^2+(q+b)'.^2+c));
wt=cc(r(real(F(d(.01,.01,5e-5,ags(f)*3)*.3+d(.02,.06,1e-3,9*ags(f))/3))/5+.4)); % Water surface
% % % Now start computing refractions
% Surf normals of water -> used for refraction
[x,y,z]=surfnorm(q1,q2,wt);
M=[x(:),y(:),z(:)]; % Normals
X=[q1(:),q2(:),wt(:)]; % Face centers
% Refraction: Camera to surface
ry=v(X'-c)'; % Camera to surface vectors
I=dot(M,ry,2);
I(I<0)=0; % Values <0 would be pointing wrong way
t=Y(1-1.1.^2*(1-I.^2)).*M+1.1*(ry-I.*M); % Refracted ray vectors
G=imag(t(:,3))~=0; % Beyond total reflection
t=real(t);
[Z,L,~]=cart2sph(t(:,1),t(:,2),t(:,3)); % Az & El. of vectors on water surface
L=R(interp2(A,E,g,Z,L,'cubic',0),[N,N]); % Interpolation into sky map
L(G)=0;
% Refraction: Sun to sand
I=M(:,3); % Sediment normal is ostensibly normal so this is a shortcut
t=real(v((Y(1-0.95.^2*(1-I.^2)).*M+0.95*([0,0,1]-I.*M))')'); % Refracted ray vectors
dxy=t(:,1:2).*(-.2-X(:,3))./t(:,3); % Ray intersection offsets
qp=[q1(:),q2(:)];
% More than 10 neighbors is preferable but times out in online execution
[~,D]=knnsearch(qp+dxy,qp,'K',10); % Search for 10 closest intersections
V=sum(exp(-1e5*(D.^2)),2)*1.3; % Exponential distance gives caustic value.
% Avoid lighting objects: lambertian scattering approx. for sediment
% surface
[sx,sy,sz]=surfnorm(q1,q2,k);
vc=sx*s(1)+sy*s(2)+sz*s(3);
% Lambertian scattering for surface in non-refracted regions
cwv=v(X'-c)';
[sx,sy,sz]=surfnorm(q1,q2,wt);
wc=R(sx(:).*cwv(:,1)+sy(:).*cwv(:,2)+sz(:).*cwv(:,3),[N,N]);
% Now create coloring for sediment
o=ones(N,N);
c1=cat(3,1,.9,.8).*o; % Sand
c2=flip(c1,3)/3; % rock
cA=o.*cat(3,0,.6,1)/2; % Ambient color;
m=ki-1; % mask
cl=(c1.*m+(1-m).*c2).*vc*1.5.*B(R(V,[N,N])/10)*2; % Color-map
% Create coloring for watersased on refraction of sunlight & ambient
mp=flipud(sky);
mp(1,:)=[0,.6,1]/2;
L(L<.5)=1.5*wc(L<.5);
L(L<.5)=.5;
L(L>1.5)=1.5;
W=ind2rgb(round(255*rescale(L)),mp);
% Need to fade to blue so get distances...
w=B(R(Y(sum((c-[q1(:),q2(:),k(:)]').^2)),[N,N])*2-2)/2+.5;
cl=w.*cA+(1-w).*cl;
W=w.*cA+(1-w).*W;
qn=-((q+1)'.^2+(q+1).^2).^2/50;
% Plotting
if f==1
S=surf(q,q',k,cl);
hold;
Q=surf(q,q',wt+qn,W);
shading flat;
=axis equal off
set(gcf,'color',[0,.6,1]/2);
camproj p
camva(65);
else
S.CData=cl;
Q.CData=W;
S.ZData=k;
Q.ZData=wt+qn;
end
campos(c);
camtarget(ct(:,f));
camup(cu(:,f));
end