1 /*
2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package shade.shaders;
26
27 import hat.Accelerator;
28 import hat.Accelerator.Compute;
29 import hat.ComputeContext;
30 import hat.ComputeContext.Kernel;
31 import hat.KernelContext;
32 import hat.NDRange;
33 import hat.backend.Backend;
34 import hat.buffer.F32Array;
35 import hat.types.F32;
36 import hat.types.vec2;
37 import hat.types.vec4;
38 import jdk.incubator.code.Reflect;
39 import optkl.ifacemapper.MappableIface;
40 import hat.buffer.Uniforms;
41 import shade.ShaderViewer;
42 import java.lang.invoke.MethodHandles;
43
44 import static hat.types.F32.abs;
45 import static hat.types.F32.floor;
46 import static hat.types.F32.log;
47 import static hat.types.F32.max;
48 import static hat.types.F32.mod;
49 import static hat.types.mat2.mat2;
50 import static hat.types.vec2.abs;
51 import static hat.types.vec2.add;
52 import static hat.types.vec2.div;
53 import static hat.types.vec2.dot;
54 import static hat.types.vec2.floor;
55 import static hat.types.vec2.fract;
56 import static hat.types.vec2.length;
57 import static hat.types.vec2.mul;
58 import static hat.types.vec2.sub;
59 import static hat.types.vec2.vec2;
60 import static hat.types.vec4.add;
61 import static hat.types.vec4.cos;
62 import static hat.types.vec4.div;
63 import static hat.types.vec4.mul;
64 import static hat.types.vec4.normalize;
65 import static hat.types.vec4.smoothstep;
66 import static hat.types.vec4.vec4;
67
68
69 //https://shadertoy.com/view/3llcDl
70 public class SpiralShader{
71
72 /*
73 // variant of https://shadertoy.com/view/3llcDl
74 // inspired by https://www.facebook.com/eric.wenger.547/videos/2727028317526304/
75
76 void mainImage(out vec4 fragColor, vec2 fragCoord ){
77
78 vec2 fResolution = iResolution.xy;
79
80 vec2 U = ((2.*fragCoord - fResolution)) / fResolution.y; // normalized coordinates
81 vec2 z = U - vec2(-1,0);
82 U.x = U.x-.5; // Moebius transform
83
84 U = U * mat2(z,-z.y,z.x) / dot(U,U);
85
86 U = U+.5;
87 // offset spiral, zoom phase // spiraling
88 U = log(length(U))*vec2(.5, -.5) + iTime/8. + atan(U.y, U.x)/6.2832 * vec2(6, 1);
89 // n
90 U = U * 3./vec2(2,1);
91 z = //vec2(1);
92 fwidth(U);
93 U = fract(U)*5.;
94
95 vec2 I = floor(U);
96 U = fract(U); // subdiv big square in 5x5
97 I.x = mod( I.x - 2.*I.y , 5.); // rearrange
98 U = vec2(U.x+ float(I.x==1.||I.x==3.),U.y+float(I.x<2.)); // recombine big tiles
99
100 float id = -1.;
101
102 if (I.x != 4.){
103 U =U/2.; // but small times
104 id = mod(floor(I.x/2.)+I.y,5.);
105 }
106 U = abs(fract(U)*2.-1.);
107 float v = max(U.x,U.y); // dist to border
108 fragColor = smoothstep(.7,-.7, (v-.95)/( abs(z.x-z.y)>1.?.1:z.y*8.)) // draw AA tiles
109 * (id<0.?vec4(1): .6 + .6 * cos( id + vec4(0,23,21,0) ) );// color
110 }
111 */
112
113
114 @Reflect
115 public static vec4 createPixel(vec2 fres, float ftime, vec2 fmouse, vec2 fragCoord){
116
117 // variant of https://shadertoy.com/view/3llcDl
118 // inspired by https://www.facebook.com/eric.wenger.547/videos/2727028317526304/
119
120
121 vec2 U = div(sub(mul(fragCoord, 2f), fres), fres.y());//.sub(fResolution).div(fResolution.y());
122 // normalized coordinates
123 var z = sub(U, vec2(-1f, 0f));
124
125 U = sub(U, vec2(.5f, 0f));
126 U = div(
127 mul(U, mat2(z.x(), z.y(), -z.y(), z.x())),
128 dot(U, U)
129 );
130 // offset spiral, zoom phase // spiraling
131 U = add(U, .5f);
132 //U = log(length(U))*vec2(.5, -.5) + iTime/8. + atan(U.y, U.x)/6.2832 * vec2(6, 1);
133 U = add(
134 add(
135 mul(log(length(U)), vec2(.5f, 0.5f)),
136 vec2(ftime / 8f)
137 ),
138 mul(
139 F32.atan(U.x(), U.y())/ 6.2832f,
140 vec2(6f, 1f)
141 )
142 );
143
144
145 U = div(mul(U, vec2(3f)), vec2(2f, 1f));
146 z = vec2(.001f);//fwidth(U); // this resamples the image. Not sure how we do this!
147 U = mul(fract(U), 5f);
148 vec2 I = floor(U);
149 U = fract(U); // subdiv big square in 5x5
150 I = vec2(mod(I.x() - 2.f * I.y(), 5f), I.y()); // rearrange
151 // U = vec2((I.x() == 1f || I.x() == 3f) ? 1f : 0f, I.x() < 2.0 ? 1f : 0f); // recombine big tiles
152 U = add(U, vec2((I.x() == 1f || I.x() == 3f) ? 1f : 0f, I.x() < 2.0 ? 1f : 0f)); // recombine big tiles
153 float id = -1f;
154 if (I.x() != 4f) {
155 U = div(U, 2f); // but small times
156 id = mod(floor(I.x() / 2f) + I.y(), 5f);
157 }
158 U = sub(abs(mul(fract(U), 2f)), 1f);
159 float v = max(U.x(), U.y()); // dist to border
160
161 return
162 //normalize(
163 smoothstep(
164 vec4(.7f),
165 vec4(-.7f),
166 mul(div(vec4(v - .95f), abs(z.x() - z.y()) > 1f
167 ? .1f
168 : z.y() * 8f
169 )
170 , id < 0f
171 ? vec4(1f)
172 : add(mul(vec4(.6f), .6f),
173 cos(add(vec4(id), vec4(0f, 23f, 21f, 0f)))
174 )
175 )
176 // )
177 );// color
178 }
179 @Reflect public static vec4 mainImage(Uniforms uniforms, vec4 fragColor, vec2 fragCoord){
180 return createPixel(vec2(uniforms.iResolution().x(),uniforms.iResolution().y()),uniforms.iTime(),vec2(uniforms.iMouse().x(),uniforms.iMouse().y()),fragCoord);
181 }
182
183 @Reflect
184 public static void penumbra(@MappableIface.RO KernelContext kc, @MappableIface.RO Uniforms uniforms, @MappableIface.RW F32Array f32Array) {
185 int width = (int) uniforms.iResolution().x();
186 int height = (int) uniforms.iResolution().y();
187 var fragColor = mainImage(uniforms, vec4.vec4(0f), vec2.vec2((float)(kc.gix % width), (float)(height-(kc.gix / width))));
188 f32Array.array(kc.gix * 3, fragColor.x());
189 f32Array.array(kc.gix * 3+1, fragColor.y());
190 f32Array.array(kc.gix * 3+2, fragColor.z());
191 }
192
193 @Reflect
194 static public void compute(final ComputeContext computeContext, @MappableIface.RO Uniforms uniforms, @MappableIface.RO F32Array image, int width, int height) {
195 computeContext.dispatchKernel(NDRange.of1D(width * height), (@Reflect Kernel) kc -> penumbra(kc, uniforms, image));
196 }
197
198 public static void update( Accelerator acc, Uniforms uniforms, F32Array f32Array, int width, int height) {
199 acc.compute((@Reflect Compute) cc -> compute(cc, uniforms, f32Array, width, height));
200 }
201
202 static void main(String[] args) {
203 var acc = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
204 var shader = ShaderViewer.of(acc, SpiralShader.class,1024, 1024);
205 shader.startLoop((uniforms, f32Array) -> update( acc, uniforms, f32Array, shader.view.getWidth(), shader.view.getHeight()));
206 }
207 }