diff --git a/README.md b/README.md new file mode 100644 index 0000000..0706b79 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Simple ray tracer +## Build and run +`mvn clean package`\ +`java -jar ray-tracer.jar` + +### 4K rendered scene +![4K rendered scene](pictures/image-4k.png) \ No newline at end of file diff --git a/pictures/image-1.png b/pictures/image-1.png new file mode 100644 index 0000000..8bb6948 Binary files /dev/null and b/pictures/image-1.png differ diff --git a/pictures/image-2.png b/pictures/image-2.png new file mode 100644 index 0000000..abcfd52 Binary files /dev/null and b/pictures/image-2.png differ diff --git a/pictures/image-3.png b/pictures/image-3.png new file mode 100644 index 0000000..93e5fec Binary files /dev/null and b/pictures/image-3.png differ diff --git a/pictures/image-4.png b/pictures/image-4.png new file mode 100644 index 0000000..701d46b Binary files /dev/null and b/pictures/image-4.png differ diff --git a/pictures/image-4k.png b/pictures/image-4k.png new file mode 100644 index 0000000..e9add8c Binary files /dev/null and b/pictures/image-4k.png differ diff --git a/pictures/image-5.png b/pictures/image-5.png new file mode 100644 index 0000000..0f8c5f4 Binary files /dev/null and b/pictures/image-5.png differ diff --git a/pom.xml b/pom.xml index d4b35c3..baa0354 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,11 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + org.apache.maven.plugins maven-compiler-plugin diff --git a/src/main/java/Convertor.java b/src/main/java/Convertor.java new file mode 100644 index 0000000..5e3aaa9 --- /dev/null +++ b/src/main/java/Convertor.java @@ -0,0 +1,86 @@ +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +public class Convertor { + public static void main(String[] args) { + + final String sourceFilename = "image.ppm"; + final String destFilename = "image.png"; + + // try to get hold of the file. + try(BufferedReader reader = new BufferedReader(new FileReader(sourceFilename))) { + // validate file header + final String FileHeader = "P3"; + String line = reader.readLine(); + if (!FileHeader.equals(line)) { + System.err.printf("Failed to read %s, bad header\n", sourceFilename); + System.exit(1); + } + + int width = 0; + int height = 0; + + line = reader.readLine(); + if (line != null) { + String[] values = line.split(" "); + width = Integer.parseInt(values[0]); + height = Integer.parseInt(values[1]); + } else { + System.err.printf("Failed to read %s, bad dimensions\n", sourceFilename); + System.exit(1); + } + + + // just validate the bpp value, even though it isn't being used + line = reader.readLine(); + if (line != null) { + int bpp = Integer.parseInt(line); + if (bpp < 0 || bpp > 255) { + System.err.printf("Failed to read %s, bad colour size\n", sourceFilename); + System.exit(1); + } + } else { + System.err.printf("Failed to read %s, bad colour size\n", sourceFilename); + System.exit(1); + } + + // prepare the data buffer + final int BPP = 3; + int imageSize = width * height; + System.out.println(width + "x" + height); + var imageData = new int[imageSize]; + + int row = 0; + while ((line = reader.readLine()) != null) { + String[] values = line.split(" "); + if (values.length != BPP) { + System.err.printf("Failed to read %s at line %d, bad colour size", sourceFilename, row); + System.exit(1); + } + + int r = Integer.parseInt(values[0]); + int g = Integer.parseInt(values[1]); + int b = Integer.parseInt(values[2]); + + int pixelValue = (r << 16) | (g << 8) | b; + imageData[row++] = pixelValue; + } + + var bufferImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + bufferImg.setRGB(0, 0, width, height, imageData, 0, width); + + var outputfile = new File(destFilename); + ImageIO.write(bufferImg, "png", outputfile); + } catch (IOException ex) { + System.out.println(ex.getMessage()); + ex.printStackTrace(); + System.exit(1); + } + + System.out.printf("Processed %s into %s\n", sourceFilename, destFilename); + } +} diff --git a/src/main/java/Main.java b/src/main/java/Main.java index ae018d9..1d7e4da 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -36,9 +36,9 @@ public static void main(String[] args) throws Exception{ public Main(BufferedWriter writer) throws IOException { //Image double aspectRatio = 16.0/9.0; - int width = 3840; + int width = 400; int height = (int)(width / aspectRatio); - int samplesPerPixel = 500; + int samplesPerPixel = 100; int depth = 50; //World HittableList world = new HittableArrayList(); @@ -46,22 +46,21 @@ public Main(BufferedWriter writer) throws IOException { Material ground = new Lambertian(new Color(0.5, 0.5, 0.5)); Material left = new Lambertian(new Color(0, 0, 1)); Material center = new Metal(new Color(0.8, 0.6, 0.2)); - Material right = new Dielectric(2.4); + Material right = new Dielectric(1.5); world.add(new Sphere(new Point(0, -1000, 0), 1000, ground)); - world.add(new Sphere(new Point(-1.5, 1, 0), 1, left)); + world.add(new Sphere(new Point(-2, 1, 0), 1, left)); world.add(new Sphere(new Point(0, 1, 0), 1, center)); - world.add(new Sphere(new Point(1.5, 1, 0), 1, right)); - Util.fillScene(world); + world.add(new Sphere(new Point(2, 1, 0), 1, right)); +// Util.fillScene(world); //Camera - Point lookFrom = new Point(13, 3, 13); - Point lookAt = new Point(); + Point lookFrom = new Point(5, 5, 13); + Point lookAt = new Point(0, 1, 0); Vector worldNormal = new Vector(0, 1, 0); double fov = 20; double aperture = 0.1; - double focusDist = new Vector(lookAt, lookAt).length(); - + double focusDist = new Vector(lookAt, lookFrom).length(); Camera camera = new ClearCamera(lookFrom, lookAt, worldNormal, fov, aspectRatio); // Camera camera = new BlurCamera(lookFrom, lookAt, worldNormal, fov, aspectRatio, aperture, focusDist); @@ -78,10 +77,10 @@ public Main(BufferedWriter writer) throws IOException { double v = ((double) j + random.nextDouble())/(height - 1); Ray ray = camera.getRay(u, v); Color color = rayColor(ray, world, depth).scale(1d/samplesPerPixel); +// Color color = Util.normalColor(ray, world).scale(1d/samplesPerPixel); pixelColor.setRed(pixelColor.getRed() + color.getRed()) .setGreen(pixelColor.getGreen() + color.getGreen()) .setBlue(pixelColor.getBlue() + color.getBlue()); - } writeColor(writer, pixelColor, Math::sqrt); } @@ -118,7 +117,6 @@ private void writeColor(BufferedWriter writer, Color color, Function