Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.event.ComponentAdapter;
- import java.awt.event.ComponentEvent;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.awt.image.BufferedImage;
- import java.awt.image.DataBufferInt;
- import java.util.concurrent.CountDownLatch;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- import javax.swing.SwingUtilities;
- public class CpuShader {
- public static float clamp (float value, float min, float max) {
- if (value < min) { return min; }
- if (value > max) { return max; }
- return value;
- }
- public static void main (String[] args) throws Exception {
- ShaderRunner runner = run( (ctx, in, out) -> {
- // "mango"
- out.r = in.xN;
- out.g = in.yN;
- });
- runner.execution.await();
- SwingUtilities.invokeLater(runner.frame::dispose);
- }
- public static float ratio (int a, int b) {
- return (float) a / (float) b;
- }
- public static ShaderRunner run (Shader shader) {
- ShaderRunner result = new ShaderRunner(shader);
- SwingUtilities.invokeLater( () -> {
- result.ui();
- result.clock.start();
- });
- return result;
- }
- public static interface Shader {
- public void apply (Context ctx, Input in, Output out);
- public static class Context {
- public int width, height; // target dimensions
- public float aspectWH; // aspect-ratio = width / height
- public float aspectHW; // aspect-ratio = height / width
- }
- public static class Input {
- public int x, y;
- public float xN, yN; // normalized to [0, 1]
- public float time;
- }
- public static class Output {
- public float r, g, b, a;
- }
- }
- public static class ShaderPanel extends JPanel {
- public Dimension targetDim;
- public BufferedImage target;
- public int[] targetBuffer;
- public final ShaderRunner runner;
- public final Shader.Context shaderCtx = new Shader.Context();
- public final Shader.Input shaderIn = new Shader.Input();
- public final Shader.Output shaderOut = new Shader.Output();
- public ShaderPanel (ShaderRunner runner) {
- {
- this.runner = runner;
- }
- {
- Dimension initialDim = new Dimension(640, 480);
- setPreferredSize(initialDim);
- setSize(initialDim);
- }
- {
- rebuildTarget();
- }
- {
- addComponentListener(new ComponentAdapter() {
- @Override public void componentResized (ComponentEvent e) {
- rebuildTarget();
- }
- });
- }
- }
- @Override public void paintComponent (Graphics graphics) {
- {
- shaderCtx.width = targetDim.width;
- shaderCtx.height = targetDim.height;
- shaderCtx.aspectWH = ratio(shaderCtx.width, shaderCtx.height);
- shaderCtx.aspectHW = ratio(shaderCtx.height, shaderCtx.width);
- }
- {
- long t0 = System.nanoTime();
- for (int y = 0; y < targetDim.height; y++) {
- for (int x = 0; x < targetDim.width; x++) {
- {
- shaderIn.x = x;
- shaderIn.y = y;
- shaderIn.xN = ratio(x, targetDim.width);
- shaderIn.yN = ratio(y, targetDim.height);
- shaderIn.time = runner.time;
- }
- {
- shaderOut.r = 0f;
- shaderOut.g = 0f;
- shaderOut.b = 0f;
- shaderOut.a = 1f;
- }
- {
- runner.shader.apply(shaderCtx, shaderIn, shaderOut);
- }
- {
- shaderOut.r = clamp(shaderOut.r, 0f, 1f);
- shaderOut.g = clamp(shaderOut.g, 0f, 1f);
- shaderOut.b = clamp(shaderOut.b, 0f, 1f);
- shaderOut.a = clamp(shaderOut.a, 0f, 1f);
- int r = (int) (255 * shaderOut.r);
- int g = (int) (255 * shaderOut.g);
- int b = (int) (255 * shaderOut.b);
- int a = (int) (255 * shaderOut.a);
- int i = y * targetDim.width + x;
- targetBuffer[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
- }
- }
- }
- long t1 = System.nanoTime();
- long dt = t1 - t0;
- long dtMS = dt / 1_000_000L;
- long fps = 1_000_000_000L / dt;
- if (false) { System.out.println("frame: " + dtMS + "ms (" + fps + "fps)"); }
- }
- {
- graphics.drawImage(target, 0, 0, null);
- }
- }
- public void rebuildTarget () {
- targetDim = new Dimension(getWidth(), getHeight());
- target = new BufferedImage(targetDim.width, targetDim.height, BufferedImage.TYPE_INT_ARGB);
- targetBuffer = ((DataBufferInt) target.getRaster().getDataBuffer()).getData();
- }
- }
- public static class ShaderRunner {
- public final Shader shader;
- public final CountDownLatch execution = new CountDownLatch(1);
- public final Thread clock = new Thread(this::clock, "shader-runner-clock");
- public final JFrame frame;
- public final ShaderPanel panel;
- public float time;
- public ShaderRunner (Shader shader) {
- this.shader = shader;
- frame = new JFrame("ShaderRunner");
- panel = new ShaderPanel(this);
- }
- public void clock () {
- while (true) {
- time += ratio(1, 60);
- SwingUtilities.invokeLater(panel::repaint);
- try {
- Thread.sleep(16);
- } catch (InterruptedException e) {
- break;
- }
- }
- }
- public void ui () {
- frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
- frame.addWindowListener(new WindowAdapter() {
- @Override public void windowClosing (WindowEvent e) {
- clock.interrupt();
- execution.countDown();
- }
- });
- frame.add(panel);
- frame.pack();
- frame.setLocationRelativeTo(null);
- frame.setVisible(true);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement