From 7935e4bdae198bf724e45960fc9ee20ed63edf3e Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:12:54 +0200 Subject: [PATCH 01/52] - separated rendering modes in functions, removed some commented out code --- .../jsurf/rendering/cpu/RenderingTask.java | 177 ++++++++---------- 1 file changed, 83 insertions(+), 94 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 46a4741..f5b78be 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -17,7 +17,6 @@ package de.mfo.jsurf.rendering.cpu; import de.mfo.jsurf.algebra.*; -import de.mfo.jsurf.debug.*; import de.mfo.jsurf.rendering.*; import javax.vecmath.*; @@ -42,27 +41,14 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, this.yEnd = yEnd; } - public Boolean call() - { - try - { + public Boolean call() { + try { render(); return true; - } - catch( RenderingInterruptedException rie ) - { - // rendering interrupted .. that's ok - //System.err.println( "... interrupted" ); - } - catch( Throwable t ) - { + } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok + } catch( Throwable t ) { t.printStackTrace(); } - finally - { - //Thread.interrupted(); // clear the interruption flag - } - return false; } @@ -78,88 +64,91 @@ private class ColumnSubstitutorPair ColumnSubstitutorForGradient gcs; } - protected void render() - throws RenderingInterruptedException - { - switch( dcsd.antiAliasingPattern ) - { - case OG_1x1: - { - // no antialising -> sample pixel center - int internal_width = xEnd - xStart + 1; - int internal_height = yEnd - yStart + 1; - double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); - double v_start = dcsd.rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); - double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); - double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - for( int y = 0; y < internal_height; y++ ) - { - double v = v_start + y * v_incr; - ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); - ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); - - for( int x = 0; x < internal_width; x++ ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - double u = u_start + x * u_incr; - dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, u, v ).get().getRGB(); - //dcsd.colorBuffer[ dcsd.width * y + x ] = traceRay( u, v ).get().getRGB(); - } - } + protected void render() throws RenderingInterruptedException { + switch( dcsd.antiAliasingPattern ) { + case OG_1x1: { + renderWithoutAliasing(); break; } - default: - { - // all other antialiasing modes - // first sample canvas at pixel corners and cast primary rays - int internal_width = xEnd - xStart + 2; - int internal_height = yEnd - yStart + 2; - Color3f[] internalColorBuffer = new Color3f[ internal_width * internal_height ]; - - ColumnSubstitutor scs = null; - ColumnSubstitutorForGradient gcs = null; - HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - double u_start = dcsd.rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); - double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); - double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); - double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - double v = 0.0; - for( int y = 0; y < internal_height; ++y ) - { - csp_hm.clear(); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); - - v = v_start + y * v_incr; - scs = dcsd.surfaceRowSubstitutor.setV( v ); - gcs = dcsd.gradientRowSubstitutor.setV( v ); - - csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); - - for( int x = 0; x < internal_width; ++x ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - - // current position on viewing plane - double u = u_start + x * u_incr; - // trace rays corresponding to (u,v)-coordinates on viewing plane - - internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); - if( x > 0 && y > 0 ) - { - Color3f ulColor = internalColorBuffer[ y * internal_width + x - 1 ]; - Color3f urColor = internalColorBuffer[ y * internal_width + x ]; - Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; - Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; - - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( u - u_incr, v - v_incr, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); - } - } - } + default: { + renderWithAliasing(); } } } + private void renderWithAliasing() { + // all other antialiasing modes + // first sample canvas at pixel corners and cast primary rays + int internal_width = xEnd - xStart + 2; + int internal_height = yEnd - yStart + 2; + Color3f[] internalColorBuffer = new Color3f[ internal_width * internal_height ]; + + ColumnSubstitutor scs = null; + ColumnSubstitutorForGradient gcs = null; + HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + double u_start = dcsd.rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); + double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); + double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); + double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); + double v = 0.0; + for( int y = 0; y < internal_height; ++y ) + { + csp_hm.clear(); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + + v = v_start + y * v_incr; + scs = dcsd.surfaceRowSubstitutor.setV( v ); + gcs = dcsd.gradientRowSubstitutor.setV( v ); + + csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + + for( int x = 0; x < internal_width; ++x ) + { + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); + + // current position on viewing plane + double u = u_start + x * u_incr; + // trace rays corresponding to (u,v)-coordinates on viewing plane + + internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); + if( x > 0 && y > 0 ) + { + Color3f ulColor = internalColorBuffer[ y * internal_width + x - 1 ]; + Color3f urColor = internalColorBuffer[ y * internal_width + x ]; + Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; + Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; + + dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( u - u_incr, v - v_incr, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + } + } + } + } + + private void renderWithoutAliasing() { + // no antialising -> sample pixel center + int internal_width = xEnd - xStart + 1; + int internal_height = yEnd - yStart + 1; + double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); + double v_start = dcsd.rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); + double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); + double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); + for( int y = 0; y < internal_height; y++ ) + { + double v = v_start + y * v_incr; + ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); + ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); + + for( int x = 0; x < internal_width; x++ ) + { + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); + double u = u_start + x * u_incr; + dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, u, v ).get().getRGB(); + //dcsd.colorBuffer[ dcsd.width * y + x ] = traceRay( u, v ).get().getRGB(); + } + } + } + private Color3f antiAliasPixel( double ll_u, double ll_v, double u_incr, double v_incr, AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor, HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm ) { // first average pixel-corner colors From d26e9e86242cf5499990d2ea5b7626e7031b36eb Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:26:22 +0200 Subject: [PATCH 02/52] - replaced multiplications with additions in the calculation of the (u,v) position in the viewing plane --- .../jsurf/rendering/cpu/RenderingTask.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index f5b78be..2f2e4e7 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -90,26 +90,28 @@ private void renderWithAliasing() { double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - double v = 0.0; + + double vOld = 0; + double v = v_start; + for( int y = 0; y < internal_height; ++y ) { - csp_hm.clear(); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + csp_hm.clear(); + csp_hm.put( vOld, new ColumnSubstitutorPair( scs, gcs ) ); - v = v_start + y * v_incr; scs = dcsd.surfaceRowSubstitutor.setV( v ); gcs = dcsd.gradientRowSubstitutor.setV( v ); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + double uOld = 0; + double u = u_start; for( int x = 0; x < internal_width; ++x ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - // current position on viewing plane - double u = u_start + x * u_incr; // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); if( x > 0 && y > 0 ) { @@ -118,9 +120,13 @@ private void renderWithAliasing() { Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( u - u_incr, v - v_incr, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } + uOld = u; + u += u_incr; } + vOld = v; + v += v_incr; } } From 6a29d4f29c68700ec6faf7efb5738a83303e6b56 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:35:15 +0200 Subject: [PATCH 03/52] - replaced multiplications with increments, additions and substractions for the internal color buffer index --- .../de/mfo/jsurf/rendering/cpu/RenderingTask.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 2f2e4e7..583cbbb 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -93,7 +93,7 @@ private void renderWithAliasing() { double vOld = 0; double v = v_start; - + int internalBufferIndex = 0; for( int y = 0; y < internal_height; ++y ) { csp_hm.clear(); @@ -112,18 +112,19 @@ private void renderWithAliasing() { throw new RenderingInterruptedException(); // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); + internalColorBuffer[ internalBufferIndex ] = tracePolynomial( scs, gcs, u, v ); if( x > 0 && y > 0 ) { - Color3f ulColor = internalColorBuffer[ y * internal_width + x - 1 ]; - Color3f urColor = internalColorBuffer[ y * internal_width + x ]; - Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; - Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; + Color3f urColor = internalColorBuffer[ internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ internalBufferIndex - internal_width ]; + Color3f llColor = internalColorBuffer[ internalBufferIndex - internal_width - 1 ]; dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } uOld = u; u += u_incr; + internalBufferIndex++; } vOld = v; v += v_incr; From 1afa3503c48641b0626e65c2a0f0283596ecbd85 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:43:29 +0200 Subject: [PATCH 04/52] - prepared the code for using color buffer pooling --- .../jsurf/rendering/cpu/RenderingTask.java | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 583cbbb..6280a28 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -42,12 +42,17 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, } public Boolean call() { + int width = xEnd - xStart + 2; + int height = yEnd - yStart + 2; + Color3f[] colorBuffer = getBuffer(width * height); try { - render(); + render(colorBuffer, width, height); return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok } catch( Throwable t ) { t.printStackTrace(); + } finally { + releaseBuffer(colorBuffer); } return false; } @@ -64,24 +69,29 @@ private class ColumnSubstitutorPair ColumnSubstitutorForGradient gcs; } - protected void render() throws RenderingInterruptedException { + protected void render(Color3f[] colorBuffer, int width, int height) throws RenderingInterruptedException { switch( dcsd.antiAliasingPattern ) { case OG_1x1: { renderWithoutAliasing(); break; } default: { - renderWithAliasing(); + renderWithAliasing(colorBuffer, width, height); } } + } + + private Color3f[] getBuffer(int size) { + return new Color3f[size]; + } + + private void releaseBuffer(Color3f[] buffer) { + } - private void renderWithAliasing() { + private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { // all other antialiasing modes // first sample canvas at pixel corners and cast primary rays - int internal_width = xEnd - xStart + 2; - int internal_height = yEnd - yStart + 2; - Color3f[] internalColorBuffer = new Color3f[ internal_width * internal_height ]; ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; @@ -94,7 +104,7 @@ private void renderWithAliasing() { double vOld = 0; double v = v_start; int internalBufferIndex = 0; - for( int y = 0; y < internal_height; ++y ) + for( int y = 0; y < height; ++y ) { csp_hm.clear(); csp_hm.put( vOld, new ColumnSubstitutorPair( scs, gcs ) ); @@ -106,7 +116,7 @@ private void renderWithAliasing() { double uOld = 0; double u = u_start; - for( int x = 0; x < internal_width; ++x ) + for( int x = 0; x < width; ++x ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); @@ -117,8 +127,8 @@ private void renderWithAliasing() { { Color3f urColor = internalColorBuffer[ internalBufferIndex ]; Color3f ulColor = internalColorBuffer[ internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ internalBufferIndex - internal_width ]; - Color3f llColor = internalColorBuffer[ internalBufferIndex - internal_width - 1 ]; + Color3f lrColor = internalColorBuffer[ internalBufferIndex - width ]; + Color3f llColor = internalColorBuffer[ internalBufferIndex - width - 1 ]; dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } From 819456ca2283afbbf89050fbd8fe8426b881dc78 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 10:46:24 +0200 Subject: [PATCH 05/52] - created a new Color buffer pool class - moved color buffer creation & pooling to the new class --- .../jsurf/rendering/cpu/ColorBufferPool.java | 87 +++++++++++++++++++ .../jsurf/rendering/cpu/RenderingTask.java | 14 ++- 2 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java new file mode 100644 index 0000000..c1f06ad --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java @@ -0,0 +1,87 @@ +package de.mfo.jsurf.rendering.cpu; + +import java.util.ArrayList; +import java.util.List; + +import javax.vecmath.Color3f; + +public class ColorBufferPool { + + private List> bufferPool; + private int createdBuffers = 0; + private int getBufferCalls = 0; + private int totalBufferSize = 0; + + public ColorBufferPool() { + bufferPool = new ArrayList>(32); + for (int i = 0 ; i < 32 ; i++) { + bufferPool.add(new ArrayList()); + } + } + + public synchronized Color3f[] getBuffer(int size) { + size = powOf2Roundup(size); + int index = highestOneBit(size); + getBufferCalls++; + + List bucket = bufferPool.get(index); + if (bucket.isEmpty()) { + createdBuffers++; + totalBufferSize += size; + System.out.println("Created color buffers size " + size + ". Call / created: " + getBufferCalls + "/" + createdBuffers + ". Total size: " + totalBufferSize); + return new Color3f[size]; + } else + return bucket.remove(0); + } + + public static int highestOneBit(int x) { + int index = 0; + if ((x & 0xFFFF0000) != 0) { + index += 16; + x >>= 16; + } + if ((x & 0xFF00) != 0) { + index += 8; + x >>= 8; + } + if ((x & 0xF0) != 0) { + index += 4; + x >>= 4; + } + if ((x & 0x0C) != 0) { + index += 2; + x >>= 2; + } + if ((x & 2) != 0) + index++; + + return index; + } + + // https://stackoverflow.com/questions/364985/algorithm-for-finding-the-smallest-power-of-two-thats-greater-or-equal-to-a-giv + private int powOf2Roundup(int x) { + if (x < 0) + return 0; + + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x+1; + } + + public synchronized void releaseBuffer(Color3f[] buffer) { + int size = buffer.length; + int index = highestOneBit(size); +// clearBuffer(buffer); + bufferPool.get(index).add(buffer); + } + + private void clearBuffer(Color3f[] buffer) { + for (int i = 0 ; i < buffer.length ; i++) + buffer[i].set(0f, 0f, 0f); + } + +} diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 6280a28..b36397b 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -25,6 +25,8 @@ public class RenderingTask implements Callable { + static ColorBufferPool bufferPool = new ColorBufferPool(); + // initialized by the constructor private int xStart; private int yStart; @@ -44,7 +46,7 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, public Boolean call() { int width = xEnd - xStart + 2; int height = yEnd - yStart + 2; - Color3f[] colorBuffer = getBuffer(width * height); + Color3f[] colorBuffer = bufferPool.getBuffer(width * height); try { render(colorBuffer, width, height); return true; @@ -52,7 +54,7 @@ public Boolean call() { } catch( Throwable t ) { t.printStackTrace(); } finally { - releaseBuffer(colorBuffer); + bufferPool.releaseBuffer(colorBuffer); } return false; } @@ -81,13 +83,7 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende } } - private Color3f[] getBuffer(int size) { - return new Color3f[size]; - } - - private void releaseBuffer(Color3f[] buffer) { - - } + private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { // all other antialiasing modes From a202b46a7df0c1ddcf33727fe73704817681a831 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 11:59:29 +0200 Subject: [PATCH 06/52] -added documentation - moved the statistics printing to a separate method --- .../jsurf/rendering/cpu/ColorBufferPool.java | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java index c1f06ad..096f31d 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java @@ -5,16 +5,41 @@ import javax.vecmath.Color3f; +/** + * The buffers returned from this class will not have the exact size requested, but the + * size of the minimum power of two higher (or equal) to it.
+ * For example, if asked for a buffer for 457 colors, it will return one of size 512.
+ *
+ * This will waste memory, but allows to reuse the buffers for different parts, and also + * when the rendering size changes. It also keeps them nicely aligned in memory, which + * could produce more speed improvements. + * + * @author Sebastian + * + */ public class ColorBufferPool { + // Should be an array of lists, but Java does not allow arrays of generic types private List> bufferPool; + private boolean dontPool = false; + + // Usage statistics private int createdBuffers = 0; - private int getBufferCalls = 0; + private int requestedBuffers = 0; private int totalBufferSize = 0; + + // the biggest buffer it can hold is of size 2^32 == 2^16 x 2^16, an area of 65536 x 65536 + private static final int MAX_POWER_OF_TWO = 32; + public static ColorBufferPool createDummyPool() { + ColorBufferPool pool = new ColorBufferPool(); + pool.dontPool = true; + return pool; + } + public ColorBufferPool() { - bufferPool = new ArrayList>(32); - for (int i = 0 ; i < 32 ; i++) { + bufferPool = new ArrayList>(MAX_POWER_OF_TWO); + for (int i = 0 ; i < MAX_POWER_OF_TWO ; i++) { bufferPool.add(new ArrayList()); } } @@ -22,18 +47,18 @@ public ColorBufferPool() { public synchronized Color3f[] getBuffer(int size) { size = powOf2Roundup(size); int index = highestOneBit(size); - getBufferCalls++; + requestedBuffers++; List bucket = bufferPool.get(index); - if (bucket.isEmpty()) { + if (dontPool || bucket.isEmpty()) { createdBuffers++; totalBufferSize += size; - System.out.println("Created color buffers size " + size + ". Call / created: " + getBufferCalls + "/" + createdBuffers + ". Total size: " + totalBufferSize); return new Color3f[size]; } else - return bucket.remove(0); + return bucket.remove(bucket.size() - 1); } + /** Index of the highest bit set in the binary representation of an integer */ public static int highestOneBit(int x) { int index = 0; if ((x & 0xFFFF0000) != 0) { @@ -59,6 +84,7 @@ public static int highestOneBit(int x) { } // https://stackoverflow.com/questions/364985/algorithm-for-finding-the-smallest-power-of-two-thats-greater-or-equal-to-a-giv + /** Minimum power of two bigger or equal to value */ private int powOf2Roundup(int x) { if (x < 0) return 0; @@ -75,13 +101,10 @@ private int powOf2Roundup(int x) { public synchronized void releaseBuffer(Color3f[] buffer) { int size = buffer.length; int index = highestOneBit(size); -// clearBuffer(buffer); bufferPool.get(index).add(buffer); } - private void clearBuffer(Color3f[] buffer) { - for (int i = 0 ; i < buffer.length ; i++) - buffer[i].set(0f, 0f, 0f); + public String getPoolStatistics() { + return "Requests / created: " + requestedBuffers + "/" + createdBuffers + ". Total size: " + totalBufferSize; } - } From 8db021bb4d47dba885e44b96455cb40e650503e6 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 12:07:40 +0200 Subject: [PATCH 07/52] - pushed down the synchronization to the bucket for a specific buffer size, instead of the pool instance --- .../jsurf/rendering/cpu/ColorBufferPool.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java index 096f31d..4b52a94 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java @@ -44,18 +44,20 @@ public ColorBufferPool() { } } - public synchronized Color3f[] getBuffer(int size) { + public Color3f[] getBuffer(int size) { size = powOf2Roundup(size); int index = highestOneBit(size); requestedBuffers++; List bucket = bufferPool.get(index); - if (dontPool || bucket.isEmpty()) { - createdBuffers++; - totalBufferSize += size; - return new Color3f[size]; - } else - return bucket.remove(bucket.size() - 1); + synchronized (bucket) { + if (dontPool || bucket.isEmpty()) { + createdBuffers++; + totalBufferSize += size; + return new Color3f[size]; + } else + return bucket.remove(bucket.size() - 1); + } } /** Index of the highest bit set in the binary representation of an integer */ @@ -98,10 +100,13 @@ private int powOf2Roundup(int x) { return x+1; } - public synchronized void releaseBuffer(Color3f[] buffer) { + public void releaseBuffer(Color3f[] buffer) { int size = buffer.length; int index = highestOneBit(size); - bufferPool.get(index).add(buffer); + List bucket = bufferPool.get(index); + synchronized (bucket) { + bucket.add(buffer); + } } public String getPoolStatistics() { From be1e429c8d6e154a49111b99d7a8faf221c24d8f Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 12:29:40 +0200 Subject: [PATCH 08/52] - cleanup: moved shading code to a different class --- .../jsurf/rendering/cpu/RenderingTask.java | 129 +++++------------- .../de/mfo/jsurf/rendering/cpu/Shader.java | 63 +++++++++ 2 files changed, 100 insertions(+), 92 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index b36397b..43c252a 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -32,7 +32,9 @@ public class RenderingTask implements Callable private int yStart; private int xEnd; private int yEnd; - private DrawcallStaticData dcsd; + private final DrawcallStaticData dcsd; + private final Shader frontShader; + private final Shader backShader; public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { @@ -41,6 +43,8 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, this.yStart = yStart; this.xEnd = xEnd; this.yEnd = yEnd; + this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); + this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); } public Boolean call() { @@ -77,18 +81,14 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende renderWithoutAliasing(); break; } - default: { + // all other antialiasing modes + default: renderWithAliasing(colorBuffer, width, height); - } } } - - private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { - // all other antialiasing modes // first sample canvas at pixel corners and cast primary rays - ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); @@ -137,8 +137,8 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he } } + /** no antialising -> sample pixel center */ private void renderWithoutAliasing() { - // no antialising -> sample pixel center int internal_width = xEnd - xStart + 1; int internal_height = yEnd - yStart + 1; double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); @@ -271,6 +271,35 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad } return dcsd.backgroundColor; } + + /** + * Calculates the shading in camera space + * @param p The hit point on the surface in camera space. + * @param n The surface normal at the hit point in camera space. + * @param eye The eye point in camera space. + * @return + */ + protected Color3f shade( Point3d p, Vector3d n, Point3d eye ) + { + // normalize only if point is not singular + float nLength = (float) n.length(); + if( nLength != 0.0f ) + n.scale( 1.0f / nLength ); + + // compute view vector + Vector3d v = new Vector3d( eye ); + v.sub( p ); + v.normalize(); + + // compute, which material to use + Shader shader = frontShader; + if( n.dot( v ) <= 0.0f ) { + shader = backShader; + n.negate(); + } + + return shader.shade(p, v, n); + } // private Color3f traceRay( double u, double v ) // { @@ -358,90 +387,6 @@ boolean blowUpChooseMaterial( Point3d p ) return ( 3.0 * dist ) % 2.0 < 1.0; } - /** - * Calculates the shading in camera space - * @param p The hit point on the surface in camera space. - * @param n The surface normal at the hit point in camera space. - * @param eye The eye point in camera space. - * @return - */ - protected Color3f shade( Point3d p, Vector3d n, Point3d eye ) - { - // normalize only if point is not singular - float nLength = (float) n.length(); - if( nLength != 0.0f ) - n.scale( 1.0f / nLength ); - - // compute view vector - Vector3d v = new Vector3d( eye ); - v.sub( p ); - v.normalize(); -/* - // special coloring for blowup-visualization - if( n.dot( v ) < 0.0f ) - n.negate(); - if( blowUpChooseMaterial( dcsd.rayCreator.cameraSpaceToSurfaceSpace( p ) ) ) - { - return shadeWithMaterial( p, v, n, dcsd.frontAmbientColor, dcsd.frontLightProducts ); - } - else - { - return shadeWithMaterial( p, v, n, dcsd.backAmbientColor, dcsd.backLightProducts ); - } -*/ - // compute, which material to use - if( n.dot( v ) > 0.0f ) - { - return shadeWithMaterial( p, v, n, dcsd.frontAmbientColor, dcsd.frontLightProducts ); - } - else - { - n.negate(); - return shadeWithMaterial( p, v, n, dcsd.backAmbientColor, dcsd.backLightProducts ); - } - } - - /** - * Shades a point with the same algorithm used by the - * {@link surf raytracer}. - * @param hitPoint Intersection point. - * @param v View vector (from intersection point to eye). - * @param n Surface normal. - * @param material Surface material. - * @return - */ - protected Color3f shadeWithMaterial( Point3d hitPoint, Vector3d v, Vector3d n, Color3f ambientColor, LightProducts[] lightProducts ) - { - Vector3d l = new Vector3d(); - Vector3d h = new Vector3d(); - - Color3f color = new Color3f( ambientColor ); - - for( int i = 0; i < dcsd.lightSources.length; i++ ) - { - LightSource lightSource = dcsd.lightSources[i]; - - l.sub( lightSource.getPosition(), hitPoint ); - l.normalize(); - - float lambertTerm = (float) n.dot( l ); - if( lambertTerm > 0.0f ) - { - // compute diffuse color component - color.scaleAdd( lambertTerm, lightProducts[i].getDiffuseProduct(), color ); - - // compute specular color component - h.add( l, v ); - h.normalize(); - - color.scaleAdd( ( float ) Math.pow( Math.max( 0.0f, n.dot( h ) ), lightProducts[i].getMaterial().getShininess() ), lightProducts[i].getSpecularProduct(), color ); - } - } - - color.clampMax( 1.0f ); - - return color; - } } diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java new file mode 100644 index 0000000..d77ab66 --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java @@ -0,0 +1,63 @@ +package de.mfo.jsurf.rendering.cpu; + +import javax.vecmath.Color3f; +import javax.vecmath.Point3d; +import javax.vecmath.Vector3d; + +import de.mfo.jsurf.rendering.LightProducts; +import de.mfo.jsurf.rendering.LightSource; + +public class Shader { + + private final Color3f ambientColor; + private final LightSource[] lightSources; + private final LightProducts[] lightProducts; + + public Shader(Color3f ambientColor, LightSource[] lightSources, LightProducts[] lightProducts) { + this.ambientColor = ambientColor; + this.lightSources = lightSources; + this.lightProducts = lightProducts; + } + + /** + * Shades a point with the same algorithm used by the + * {@link surf raytracer}. + * @param hitPoint Intersection point. + * @param v View vector (from intersection point to eye). + * @param n Surface normal. + * @param material Surface material. + * @return + */ + protected Color3f shade( Point3d hitPoint, Vector3d v, Vector3d n) + { + Vector3d l = new Vector3d(); + Vector3d h = new Vector3d(); + + Color3f color = new Color3f( ambientColor ); + + for( int i = 0; i < lightSources.length; i++ ) + { + LightSource lightSource = lightSources[i]; + + l.sub( lightSource.getPosition(), hitPoint ); + l.normalize(); + + float lambertTerm = (float) n.dot( l ); + if( lambertTerm > 0.0f ) + { + // compute diffuse color component + color.scaleAdd( lambertTerm, lightProducts[i].getDiffuseProduct(), color ); + + // compute specular color component + h.add( l, v ); + h.normalize(); + + color.scaleAdd( ( float ) Math.pow( Math.max( 0.0f, n.dot( h ) ), lightProducts[i].getMaterial().getShininess() ), lightProducts[i].getSpecularProduct(), color ); + } + } + + color.clampMax( 1.0f ); + + return color; + } +} From e43760a8ffc4286483f491b3df22e31d69198eb0 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 13:06:31 +0200 Subject: [PATCH 09/52] - rename variables and made code slightly more readable --- .../de/mfo/jsurf/rendering/cpu/Shader.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java index d77ab66..d37f4cb 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java @@ -8,7 +8,6 @@ import de.mfo.jsurf.rendering.LightSource; public class Shader { - private final Color3f ambientColor; private final LightSource[] lightSources; private final LightProducts[] lightProducts; @@ -23,14 +22,13 @@ public Shader(Color3f ambientColor, LightSource[] lightSources, LightProducts[] * Shades a point with the same algorithm used by the * {@link surf raytracer}. * @param hitPoint Intersection point. - * @param v View vector (from intersection point to eye). - * @param n Surface normal. - * @param material Surface material. + * @param view View vector (from intersection point to eye). + * @param normal Surface normal. * @return */ - protected Color3f shade( Point3d hitPoint, Vector3d v, Vector3d n) + protected Color3f shade( Point3d hitPoint, Vector3d view, Vector3d normal) { - Vector3d l = new Vector3d(); + Vector3d lightDirection = new Vector3d(); Vector3d h = new Vector3d(); Color3f color = new Color3f( ambientColor ); @@ -38,21 +36,22 @@ protected Color3f shade( Point3d hitPoint, Vector3d v, Vector3d n) for( int i = 0; i < lightSources.length; i++ ) { LightSource lightSource = lightSources[i]; + LightProducts lightProducts = this.lightProducts[i]; - l.sub( lightSource.getPosition(), hitPoint ); - l.normalize(); + lightDirection.sub( lightSource.getPosition(), hitPoint ); + lightDirection.normalize(); - float lambertTerm = (float) n.dot( l ); + float lambertTerm = (float) normal.dot( lightDirection ); if( lambertTerm > 0.0f ) { // compute diffuse color component - color.scaleAdd( lambertTerm, lightProducts[i].getDiffuseProduct(), color ); + color.scaleAdd( lambertTerm, lightProducts.getDiffuseProduct(), color ); // compute specular color component - h.add( l, v ); + h.add( lightDirection, view ); h.normalize(); - - color.scaleAdd( ( float ) Math.pow( Math.max( 0.0f, n.dot( h ) ), lightProducts[i].getMaterial().getShininess() ), lightProducts[i].getSpecularProduct(), color ); + double specularTerm = Math.pow( Math.max( 0.0f, normal.dot(h) ), lightProducts.getMaterial().getShininess() ); + color.scaleAdd( (float)specularTerm, lightProducts.getSpecularProduct(), color ); } } From fae12e8f5858dd7e04d6dc7bfc7d2bec5b8a14f1 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 13:10:07 +0200 Subject: [PATCH 10/52] - remove unneeded for loop --- .../jsurf/rendering/cpu/RenderingTask.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 43c252a..82d70e3 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -251,21 +251,16 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad interval.x = Math.max( interval.x, eyeLocation ); // intersect ray with surface and shade pixel - //double[] hits = hits = dcsd.realRootFinder.findAllRootsIn( surfacePoly, interval.x, interval.y ); - double[] hits = { dcsd.realRootFinder.findFirstRootIn( surfacePoly, interval.x, interval.y ) }; - if( java.lang.Double.isNaN( hits[ 0 ] )) - hits = new double[ 0 ]; - for( double hit : hits ) + double hit = dcsd.realRootFinder.findFirstRootIn( surfacePoly, interval.x, interval.y ); + if( !java.lang.Double.isNaN( hit ) && dcsd.rayClipper.clipPoint( surfaceRay.at( hit ), true ) ) { - if( dcsd.rayClipper.clipPoint( surfaceRay.at( hit ), true ) ) - { - if( gradientPolys == null ) - gradientPolys = gcs.setU( u ); - Vector3d n_surfaceSpace = gradientPolys.setT( hit ); - Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); + if( gradientPolys == null ) + gradientPolys = gcs.setU( u ); - return shade( ray.at( hit ), n_cameraSpace, eye ); - } + Vector3d n_surfaceSpace = gradientPolys.setT( hit ); + Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); + + return shade( ray.at( hit ), n_cameraSpace, eye ); } } } From 8cec89a263c606d3d12b3111d4994e51def6360b Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 14:14:28 +0200 Subject: [PATCH 11/52] Some changes in the shade function - rename variables - calculate the square root of the normal length only if needed - avoid recalculating view direction, take instead the negated ray direction --- .../jsurf/rendering/cpu/RenderingTask.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 82d70e3..11a1934 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -232,7 +232,6 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad Ray clippingRay = dcsd.rayCreator.createClippingSpaceRay( u, v ); Ray surfaceRay = dcsd.rayCreator.createSurfaceSpaceRay( u, v ); - Point3d eye = ray.at( dcsd.rayCreator.getEyeLocationOnRay() ); UnivariatePolynomialVector3d gradientPolys = null; // optimize rays and root-finder parameters @@ -260,7 +259,7 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad Vector3d n_surfaceSpace = gradientPolys.setT( hit ); Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); - return shade( ray.at( hit ), n_cameraSpace, eye ); + return shade( ray, hit, n_cameraSpace ); } } } @@ -269,31 +268,25 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad /** * Calculates the shading in camera space - * @param p The hit point on the surface in camera space. - * @param n The surface normal at the hit point in camera space. - * @param eye The eye point in camera space. - * @return */ - protected Color3f shade( Point3d p, Vector3d n, Point3d eye ) - { + protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) + { // normalize only if point is not singular - float nLength = (float) n.length(); + float nLength = (float) cameraSpaceNormal.length(); if( nLength != 0.0f ) - n.scale( 1.0f / nLength ); + cameraSpaceNormal.scale( 1.0f / nLength ); - // compute view vector - Vector3d v = new Vector3d( eye ); - v.sub( p ); - v.normalize(); + Vector3d view = new Vector3d(-ray.d.x, -ray.d.y, -ray.d.z); + // TODO: not normalizing the view does not seem to affect the rendered result, maybe it can be avoided + view.normalize(); - // compute, which material to use Shader shader = frontShader; - if( n.dot( v ) <= 0.0f ) { + if( cameraSpaceNormal.dot( view ) <= 0.0f ) { shader = backShader; - n.negate(); + cameraSpaceNormal.negate(); } - return shader.shade(p, v, n); + return shader.shade(ray.at(hit), view, cameraSpaceNormal); } // private Color3f traceRay( double u, double v ) From 5a51f0a2a9344c0ea972858305e2d488c8659bda Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:12:54 +0200 Subject: [PATCH 12/52] Separate concerns of rendering into different methods --- .../jsurf/rendering/cpu/RenderingTask.java | 177 ++++++++---------- 1 file changed, 83 insertions(+), 94 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 46a4741..f5b78be 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -17,7 +17,6 @@ package de.mfo.jsurf.rendering.cpu; import de.mfo.jsurf.algebra.*; -import de.mfo.jsurf.debug.*; import de.mfo.jsurf.rendering.*; import javax.vecmath.*; @@ -42,27 +41,14 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, this.yEnd = yEnd; } - public Boolean call() - { - try - { + public Boolean call() { + try { render(); return true; - } - catch( RenderingInterruptedException rie ) - { - // rendering interrupted .. that's ok - //System.err.println( "... interrupted" ); - } - catch( Throwable t ) - { + } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok + } catch( Throwable t ) { t.printStackTrace(); } - finally - { - //Thread.interrupted(); // clear the interruption flag - } - return false; } @@ -78,88 +64,91 @@ private class ColumnSubstitutorPair ColumnSubstitutorForGradient gcs; } - protected void render() - throws RenderingInterruptedException - { - switch( dcsd.antiAliasingPattern ) - { - case OG_1x1: - { - // no antialising -> sample pixel center - int internal_width = xEnd - xStart + 1; - int internal_height = yEnd - yStart + 1; - double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); - double v_start = dcsd.rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); - double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); - double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - for( int y = 0; y < internal_height; y++ ) - { - double v = v_start + y * v_incr; - ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); - ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); - - for( int x = 0; x < internal_width; x++ ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - double u = u_start + x * u_incr; - dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, u, v ).get().getRGB(); - //dcsd.colorBuffer[ dcsd.width * y + x ] = traceRay( u, v ).get().getRGB(); - } - } + protected void render() throws RenderingInterruptedException { + switch( dcsd.antiAliasingPattern ) { + case OG_1x1: { + renderWithoutAliasing(); break; } - default: - { - // all other antialiasing modes - // first sample canvas at pixel corners and cast primary rays - int internal_width = xEnd - xStart + 2; - int internal_height = yEnd - yStart + 2; - Color3f[] internalColorBuffer = new Color3f[ internal_width * internal_height ]; - - ColumnSubstitutor scs = null; - ColumnSubstitutorForGradient gcs = null; - HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - double u_start = dcsd.rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); - double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); - double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); - double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - double v = 0.0; - for( int y = 0; y < internal_height; ++y ) - { - csp_hm.clear(); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); - - v = v_start + y * v_incr; - scs = dcsd.surfaceRowSubstitutor.setV( v ); - gcs = dcsd.gradientRowSubstitutor.setV( v ); - - csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); - - for( int x = 0; x < internal_width; ++x ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - - // current position on viewing plane - double u = u_start + x * u_incr; - // trace rays corresponding to (u,v)-coordinates on viewing plane - - internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); - if( x > 0 && y > 0 ) - { - Color3f ulColor = internalColorBuffer[ y * internal_width + x - 1 ]; - Color3f urColor = internalColorBuffer[ y * internal_width + x ]; - Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; - Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; - - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( u - u_incr, v - v_incr, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); - } - } - } + default: { + renderWithAliasing(); } } } + private void renderWithAliasing() { + // all other antialiasing modes + // first sample canvas at pixel corners and cast primary rays + int internal_width = xEnd - xStart + 2; + int internal_height = yEnd - yStart + 2; + Color3f[] internalColorBuffer = new Color3f[ internal_width * internal_height ]; + + ColumnSubstitutor scs = null; + ColumnSubstitutorForGradient gcs = null; + HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + double u_start = dcsd.rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); + double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); + double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); + double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); + double v = 0.0; + for( int y = 0; y < internal_height; ++y ) + { + csp_hm.clear(); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + + v = v_start + y * v_incr; + scs = dcsd.surfaceRowSubstitutor.setV( v ); + gcs = dcsd.gradientRowSubstitutor.setV( v ); + + csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + + for( int x = 0; x < internal_width; ++x ) + { + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); + + // current position on viewing plane + double u = u_start + x * u_incr; + // trace rays corresponding to (u,v)-coordinates on viewing plane + + internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); + if( x > 0 && y > 0 ) + { + Color3f ulColor = internalColorBuffer[ y * internal_width + x - 1 ]; + Color3f urColor = internalColorBuffer[ y * internal_width + x ]; + Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; + Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; + + dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( u - u_incr, v - v_incr, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + } + } + } + } + + private void renderWithoutAliasing() { + // no antialising -> sample pixel center + int internal_width = xEnd - xStart + 1; + int internal_height = yEnd - yStart + 1; + double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); + double v_start = dcsd.rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); + double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); + double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); + for( int y = 0; y < internal_height; y++ ) + { + double v = v_start + y * v_incr; + ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); + ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); + + for( int x = 0; x < internal_width; x++ ) + { + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); + double u = u_start + x * u_incr; + dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, u, v ).get().getRGB(); + //dcsd.colorBuffer[ dcsd.width * y + x ] = traceRay( u, v ).get().getRGB(); + } + } + } + private Color3f antiAliasPixel( double ll_u, double ll_v, double u_incr, double v_incr, AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor, HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm ) { // first average pixel-corner colors From 3b7253a2c82d56a1bab23c78f3372179f4e3a7a7 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:26:22 +0200 Subject: [PATCH 13/52] Replace multiplications with additions --- .../jsurf/rendering/cpu/RenderingTask.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index f5b78be..2f2e4e7 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -90,26 +90,28 @@ private void renderWithAliasing() { double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - double v = 0.0; + + double vOld = 0; + double v = v_start; + for( int y = 0; y < internal_height; ++y ) { - csp_hm.clear(); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + csp_hm.clear(); + csp_hm.put( vOld, new ColumnSubstitutorPair( scs, gcs ) ); - v = v_start + y * v_incr; scs = dcsd.surfaceRowSubstitutor.setV( v ); gcs = dcsd.gradientRowSubstitutor.setV( v ); csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + double uOld = 0; + double u = u_start; for( int x = 0; x < internal_width; ++x ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - // current position on viewing plane - double u = u_start + x * u_incr; // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); if( x > 0 && y > 0 ) { @@ -118,9 +120,13 @@ private void renderWithAliasing() { Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( u - u_incr, v - v_incr, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } + uOld = u; + u += u_incr; } + vOld = v; + v += v_incr; } } From 447a51c28d12358b0bb9034f348022f89b312489 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:35:15 +0200 Subject: [PATCH 14/52] Replace mutliplications with simpler operations --- .../de/mfo/jsurf/rendering/cpu/RenderingTask.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 2f2e4e7..583cbbb 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -93,7 +93,7 @@ private void renderWithAliasing() { double vOld = 0; double v = v_start; - + int internalBufferIndex = 0; for( int y = 0; y < internal_height; ++y ) { csp_hm.clear(); @@ -112,18 +112,19 @@ private void renderWithAliasing() { throw new RenderingInterruptedException(); // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ y * internal_width + x ] = tracePolynomial( scs, gcs, u, v ); + internalColorBuffer[ internalBufferIndex ] = tracePolynomial( scs, gcs, u, v ); if( x > 0 && y > 0 ) { - Color3f ulColor = internalColorBuffer[ y * internal_width + x - 1 ]; - Color3f urColor = internalColorBuffer[ y * internal_width + x ]; - Color3f llColor = internalColorBuffer[ ( y - 1 ) * internal_width + x - 1]; - Color3f lrColor = internalColorBuffer[ ( y - 1 ) * internal_width + x ]; + Color3f urColor = internalColorBuffer[ internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ internalBufferIndex - internal_width ]; + Color3f llColor = internalColorBuffer[ internalBufferIndex - internal_width - 1 ]; dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } uOld = u; u += u_incr; + internalBufferIndex++; } vOld = v; v += v_incr; From 11c0e86ed3870dba263cbb5985a7df0bef236374 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 09:43:29 +0200 Subject: [PATCH 15/52] Prepare the code for using color buffer pooling --- .../jsurf/rendering/cpu/RenderingTask.java | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 583cbbb..6280a28 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -42,12 +42,17 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, } public Boolean call() { + int width = xEnd - xStart + 2; + int height = yEnd - yStart + 2; + Color3f[] colorBuffer = getBuffer(width * height); try { - render(); + render(colorBuffer, width, height); return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok } catch( Throwable t ) { t.printStackTrace(); + } finally { + releaseBuffer(colorBuffer); } return false; } @@ -64,24 +69,29 @@ private class ColumnSubstitutorPair ColumnSubstitutorForGradient gcs; } - protected void render() throws RenderingInterruptedException { + protected void render(Color3f[] colorBuffer, int width, int height) throws RenderingInterruptedException { switch( dcsd.antiAliasingPattern ) { case OG_1x1: { renderWithoutAliasing(); break; } default: { - renderWithAliasing(); + renderWithAliasing(colorBuffer, width, height); } } + } + + private Color3f[] getBuffer(int size) { + return new Color3f[size]; + } + + private void releaseBuffer(Color3f[] buffer) { + } - private void renderWithAliasing() { + private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { // all other antialiasing modes // first sample canvas at pixel corners and cast primary rays - int internal_width = xEnd - xStart + 2; - int internal_height = yEnd - yStart + 2; - Color3f[] internalColorBuffer = new Color3f[ internal_width * internal_height ]; ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; @@ -94,7 +104,7 @@ private void renderWithAliasing() { double vOld = 0; double v = v_start; int internalBufferIndex = 0; - for( int y = 0; y < internal_height; ++y ) + for( int y = 0; y < height; ++y ) { csp_hm.clear(); csp_hm.put( vOld, new ColumnSubstitutorPair( scs, gcs ) ); @@ -106,7 +116,7 @@ private void renderWithAliasing() { double uOld = 0; double u = u_start; - for( int x = 0; x < internal_width; ++x ) + for( int x = 0; x < width; ++x ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); @@ -117,8 +127,8 @@ private void renderWithAliasing() { { Color3f urColor = internalColorBuffer[ internalBufferIndex ]; Color3f ulColor = internalColorBuffer[ internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ internalBufferIndex - internal_width ]; - Color3f llColor = internalColorBuffer[ internalBufferIndex - internal_width - 1 ]; + Color3f lrColor = internalColorBuffer[ internalBufferIndex - width ]; + Color3f llColor = internalColorBuffer[ internalBufferIndex - width - 1 ]; dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } From d4f34de96a79b8bc14b80d123f30393662496910 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 10:46:24 +0200 Subject: [PATCH 16/52] Implement Color buffer pooling --- .../jsurf/rendering/cpu/ColorBufferPool.java | 87 +++++++++++++++++++ .../jsurf/rendering/cpu/RenderingTask.java | 14 ++- 2 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java new file mode 100644 index 0000000..c1f06ad --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java @@ -0,0 +1,87 @@ +package de.mfo.jsurf.rendering.cpu; + +import java.util.ArrayList; +import java.util.List; + +import javax.vecmath.Color3f; + +public class ColorBufferPool { + + private List> bufferPool; + private int createdBuffers = 0; + private int getBufferCalls = 0; + private int totalBufferSize = 0; + + public ColorBufferPool() { + bufferPool = new ArrayList>(32); + for (int i = 0 ; i < 32 ; i++) { + bufferPool.add(new ArrayList()); + } + } + + public synchronized Color3f[] getBuffer(int size) { + size = powOf2Roundup(size); + int index = highestOneBit(size); + getBufferCalls++; + + List bucket = bufferPool.get(index); + if (bucket.isEmpty()) { + createdBuffers++; + totalBufferSize += size; + System.out.println("Created color buffers size " + size + ". Call / created: " + getBufferCalls + "/" + createdBuffers + ". Total size: " + totalBufferSize); + return new Color3f[size]; + } else + return bucket.remove(0); + } + + public static int highestOneBit(int x) { + int index = 0; + if ((x & 0xFFFF0000) != 0) { + index += 16; + x >>= 16; + } + if ((x & 0xFF00) != 0) { + index += 8; + x >>= 8; + } + if ((x & 0xF0) != 0) { + index += 4; + x >>= 4; + } + if ((x & 0x0C) != 0) { + index += 2; + x >>= 2; + } + if ((x & 2) != 0) + index++; + + return index; + } + + // https://stackoverflow.com/questions/364985/algorithm-for-finding-the-smallest-power-of-two-thats-greater-or-equal-to-a-giv + private int powOf2Roundup(int x) { + if (x < 0) + return 0; + + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x+1; + } + + public synchronized void releaseBuffer(Color3f[] buffer) { + int size = buffer.length; + int index = highestOneBit(size); +// clearBuffer(buffer); + bufferPool.get(index).add(buffer); + } + + private void clearBuffer(Color3f[] buffer) { + for (int i = 0 ; i < buffer.length ; i++) + buffer[i].set(0f, 0f, 0f); + } + +} diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 6280a28..b36397b 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -25,6 +25,8 @@ public class RenderingTask implements Callable { + static ColorBufferPool bufferPool = new ColorBufferPool(); + // initialized by the constructor private int xStart; private int yStart; @@ -44,7 +46,7 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, public Boolean call() { int width = xEnd - xStart + 2; int height = yEnd - yStart + 2; - Color3f[] colorBuffer = getBuffer(width * height); + Color3f[] colorBuffer = bufferPool.getBuffer(width * height); try { render(colorBuffer, width, height); return true; @@ -52,7 +54,7 @@ public Boolean call() { } catch( Throwable t ) { t.printStackTrace(); } finally { - releaseBuffer(colorBuffer); + bufferPool.releaseBuffer(colorBuffer); } return false; } @@ -81,13 +83,7 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende } } - private Color3f[] getBuffer(int size) { - return new Color3f[size]; - } - - private void releaseBuffer(Color3f[] buffer) { - - } + private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { // all other antialiasing modes From 643c116c463e792d7c697a41e7db82fd9f90af86 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 11:59:29 +0200 Subject: [PATCH 17/52] Improved documentation of the code --- .../jsurf/rendering/cpu/ColorBufferPool.java | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java index c1f06ad..096f31d 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java @@ -5,16 +5,41 @@ import javax.vecmath.Color3f; +/** + * The buffers returned from this class will not have the exact size requested, but the + * size of the minimum power of two higher (or equal) to it.
+ * For example, if asked for a buffer for 457 colors, it will return one of size 512.
+ *
+ * This will waste memory, but allows to reuse the buffers for different parts, and also + * when the rendering size changes. It also keeps them nicely aligned in memory, which + * could produce more speed improvements. + * + * @author Sebastian + * + */ public class ColorBufferPool { + // Should be an array of lists, but Java does not allow arrays of generic types private List> bufferPool; + private boolean dontPool = false; + + // Usage statistics private int createdBuffers = 0; - private int getBufferCalls = 0; + private int requestedBuffers = 0; private int totalBufferSize = 0; + + // the biggest buffer it can hold is of size 2^32 == 2^16 x 2^16, an area of 65536 x 65536 + private static final int MAX_POWER_OF_TWO = 32; + public static ColorBufferPool createDummyPool() { + ColorBufferPool pool = new ColorBufferPool(); + pool.dontPool = true; + return pool; + } + public ColorBufferPool() { - bufferPool = new ArrayList>(32); - for (int i = 0 ; i < 32 ; i++) { + bufferPool = new ArrayList>(MAX_POWER_OF_TWO); + for (int i = 0 ; i < MAX_POWER_OF_TWO ; i++) { bufferPool.add(new ArrayList()); } } @@ -22,18 +47,18 @@ public ColorBufferPool() { public synchronized Color3f[] getBuffer(int size) { size = powOf2Roundup(size); int index = highestOneBit(size); - getBufferCalls++; + requestedBuffers++; List bucket = bufferPool.get(index); - if (bucket.isEmpty()) { + if (dontPool || bucket.isEmpty()) { createdBuffers++; totalBufferSize += size; - System.out.println("Created color buffers size " + size + ". Call / created: " + getBufferCalls + "/" + createdBuffers + ". Total size: " + totalBufferSize); return new Color3f[size]; } else - return bucket.remove(0); + return bucket.remove(bucket.size() - 1); } + /** Index of the highest bit set in the binary representation of an integer */ public static int highestOneBit(int x) { int index = 0; if ((x & 0xFFFF0000) != 0) { @@ -59,6 +84,7 @@ public static int highestOneBit(int x) { } // https://stackoverflow.com/questions/364985/algorithm-for-finding-the-smallest-power-of-two-thats-greater-or-equal-to-a-giv + /** Minimum power of two bigger or equal to value */ private int powOf2Roundup(int x) { if (x < 0) return 0; @@ -75,13 +101,10 @@ private int powOf2Roundup(int x) { public synchronized void releaseBuffer(Color3f[] buffer) { int size = buffer.length; int index = highestOneBit(size); -// clearBuffer(buffer); bufferPool.get(index).add(buffer); } - private void clearBuffer(Color3f[] buffer) { - for (int i = 0 ; i < buffer.length ; i++) - buffer[i].set(0f, 0f, 0f); + public String getPoolStatistics() { + return "Requests / created: " + requestedBuffers + "/" + createdBuffers + ". Total size: " + totalBufferSize; } - } From 075ec24d2b8f9d649897b492c3a8251dfb81af0a Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 12:07:40 +0200 Subject: [PATCH 18/52] Change the way color buffer pools are synchronized By pushing synchronization down to each individual bucket instad of the pool class, the granularity of locking should be increased, reducing the chances of threads being blocked. --- .../jsurf/rendering/cpu/ColorBufferPool.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java index 096f31d..4b52a94 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java @@ -44,18 +44,20 @@ public ColorBufferPool() { } } - public synchronized Color3f[] getBuffer(int size) { + public Color3f[] getBuffer(int size) { size = powOf2Roundup(size); int index = highestOneBit(size); requestedBuffers++; List bucket = bufferPool.get(index); - if (dontPool || bucket.isEmpty()) { - createdBuffers++; - totalBufferSize += size; - return new Color3f[size]; - } else - return bucket.remove(bucket.size() - 1); + synchronized (bucket) { + if (dontPool || bucket.isEmpty()) { + createdBuffers++; + totalBufferSize += size; + return new Color3f[size]; + } else + return bucket.remove(bucket.size() - 1); + } } /** Index of the highest bit set in the binary representation of an integer */ @@ -98,10 +100,13 @@ private int powOf2Roundup(int x) { return x+1; } - public synchronized void releaseBuffer(Color3f[] buffer) { + public void releaseBuffer(Color3f[] buffer) { int size = buffer.length; int index = highestOneBit(size); - bufferPool.get(index).add(buffer); + List bucket = bufferPool.get(index); + synchronized (bucket) { + bucket.add(buffer); + } } public String getPoolStatistics() { From f75844281ae92b44c3c8d69359271c401bb55cb8 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 12:29:40 +0200 Subject: [PATCH 19/52] Move shading code to its own class Separating shading logic makes de code more readable, and opens the doors to later implementing multiple shading algorithms. --- .../jsurf/rendering/cpu/RenderingTask.java | 129 +++++------------- .../de/mfo/jsurf/rendering/cpu/Shader.java | 63 +++++++++ 2 files changed, 100 insertions(+), 92 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index b36397b..43c252a 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -32,7 +32,9 @@ public class RenderingTask implements Callable private int yStart; private int xEnd; private int yEnd; - private DrawcallStaticData dcsd; + private final DrawcallStaticData dcsd; + private final Shader frontShader; + private final Shader backShader; public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { @@ -41,6 +43,8 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, this.yStart = yStart; this.xEnd = xEnd; this.yEnd = yEnd; + this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); + this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); } public Boolean call() { @@ -77,18 +81,14 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende renderWithoutAliasing(); break; } - default: { + // all other antialiasing modes + default: renderWithAliasing(colorBuffer, width, height); - } } } - - private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { - // all other antialiasing modes // first sample canvas at pixel corners and cast primary rays - ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); @@ -137,8 +137,8 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he } } + /** no antialising -> sample pixel center */ private void renderWithoutAliasing() { - // no antialising -> sample pixel center int internal_width = xEnd - xStart + 1; int internal_height = yEnd - yStart + 1; double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); @@ -271,6 +271,35 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad } return dcsd.backgroundColor; } + + /** + * Calculates the shading in camera space + * @param p The hit point on the surface in camera space. + * @param n The surface normal at the hit point in camera space. + * @param eye The eye point in camera space. + * @return + */ + protected Color3f shade( Point3d p, Vector3d n, Point3d eye ) + { + // normalize only if point is not singular + float nLength = (float) n.length(); + if( nLength != 0.0f ) + n.scale( 1.0f / nLength ); + + // compute view vector + Vector3d v = new Vector3d( eye ); + v.sub( p ); + v.normalize(); + + // compute, which material to use + Shader shader = frontShader; + if( n.dot( v ) <= 0.0f ) { + shader = backShader; + n.negate(); + } + + return shader.shade(p, v, n); + } // private Color3f traceRay( double u, double v ) // { @@ -358,90 +387,6 @@ boolean blowUpChooseMaterial( Point3d p ) return ( 3.0 * dist ) % 2.0 < 1.0; } - /** - * Calculates the shading in camera space - * @param p The hit point on the surface in camera space. - * @param n The surface normal at the hit point in camera space. - * @param eye The eye point in camera space. - * @return - */ - protected Color3f shade( Point3d p, Vector3d n, Point3d eye ) - { - // normalize only if point is not singular - float nLength = (float) n.length(); - if( nLength != 0.0f ) - n.scale( 1.0f / nLength ); - - // compute view vector - Vector3d v = new Vector3d( eye ); - v.sub( p ); - v.normalize(); -/* - // special coloring for blowup-visualization - if( n.dot( v ) < 0.0f ) - n.negate(); - if( blowUpChooseMaterial( dcsd.rayCreator.cameraSpaceToSurfaceSpace( p ) ) ) - { - return shadeWithMaterial( p, v, n, dcsd.frontAmbientColor, dcsd.frontLightProducts ); - } - else - { - return shadeWithMaterial( p, v, n, dcsd.backAmbientColor, dcsd.backLightProducts ); - } -*/ - // compute, which material to use - if( n.dot( v ) > 0.0f ) - { - return shadeWithMaterial( p, v, n, dcsd.frontAmbientColor, dcsd.frontLightProducts ); - } - else - { - n.negate(); - return shadeWithMaterial( p, v, n, dcsd.backAmbientColor, dcsd.backLightProducts ); - } - } - - /** - * Shades a point with the same algorithm used by the - * {@link surf raytracer}. - * @param hitPoint Intersection point. - * @param v View vector (from intersection point to eye). - * @param n Surface normal. - * @param material Surface material. - * @return - */ - protected Color3f shadeWithMaterial( Point3d hitPoint, Vector3d v, Vector3d n, Color3f ambientColor, LightProducts[] lightProducts ) - { - Vector3d l = new Vector3d(); - Vector3d h = new Vector3d(); - - Color3f color = new Color3f( ambientColor ); - - for( int i = 0; i < dcsd.lightSources.length; i++ ) - { - LightSource lightSource = dcsd.lightSources[i]; - - l.sub( lightSource.getPosition(), hitPoint ); - l.normalize(); - - float lambertTerm = (float) n.dot( l ); - if( lambertTerm > 0.0f ) - { - // compute diffuse color component - color.scaleAdd( lambertTerm, lightProducts[i].getDiffuseProduct(), color ); - - // compute specular color component - h.add( l, v ); - h.normalize(); - - color.scaleAdd( ( float ) Math.pow( Math.max( 0.0f, n.dot( h ) ), lightProducts[i].getMaterial().getShininess() ), lightProducts[i].getSpecularProduct(), color ); - } - } - - color.clampMax( 1.0f ); - - return color; - } } diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java new file mode 100644 index 0000000..d77ab66 --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java @@ -0,0 +1,63 @@ +package de.mfo.jsurf.rendering.cpu; + +import javax.vecmath.Color3f; +import javax.vecmath.Point3d; +import javax.vecmath.Vector3d; + +import de.mfo.jsurf.rendering.LightProducts; +import de.mfo.jsurf.rendering.LightSource; + +public class Shader { + + private final Color3f ambientColor; + private final LightSource[] lightSources; + private final LightProducts[] lightProducts; + + public Shader(Color3f ambientColor, LightSource[] lightSources, LightProducts[] lightProducts) { + this.ambientColor = ambientColor; + this.lightSources = lightSources; + this.lightProducts = lightProducts; + } + + /** + * Shades a point with the same algorithm used by the + * {@link surf raytracer}. + * @param hitPoint Intersection point. + * @param v View vector (from intersection point to eye). + * @param n Surface normal. + * @param material Surface material. + * @return + */ + protected Color3f shade( Point3d hitPoint, Vector3d v, Vector3d n) + { + Vector3d l = new Vector3d(); + Vector3d h = new Vector3d(); + + Color3f color = new Color3f( ambientColor ); + + for( int i = 0; i < lightSources.length; i++ ) + { + LightSource lightSource = lightSources[i]; + + l.sub( lightSource.getPosition(), hitPoint ); + l.normalize(); + + float lambertTerm = (float) n.dot( l ); + if( lambertTerm > 0.0f ) + { + // compute diffuse color component + color.scaleAdd( lambertTerm, lightProducts[i].getDiffuseProduct(), color ); + + // compute specular color component + h.add( l, v ); + h.normalize(); + + color.scaleAdd( ( float ) Math.pow( Math.max( 0.0f, n.dot( h ) ), lightProducts[i].getMaterial().getShininess() ), lightProducts[i].getSpecularProduct(), color ); + } + } + + color.clampMax( 1.0f ); + + return color; + } +} From 39da69b95c6e9d6e3f53b043e094b8111d93b5a7 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 13:06:31 +0200 Subject: [PATCH 20/52] Make the code more readable --- .../de/mfo/jsurf/rendering/cpu/Shader.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java index d77ab66..d37f4cb 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/Shader.java @@ -8,7 +8,6 @@ import de.mfo.jsurf.rendering.LightSource; public class Shader { - private final Color3f ambientColor; private final LightSource[] lightSources; private final LightProducts[] lightProducts; @@ -23,14 +22,13 @@ public Shader(Color3f ambientColor, LightSource[] lightSources, LightProducts[] * Shades a point with the same algorithm used by the * {@link surf raytracer}. * @param hitPoint Intersection point. - * @param v View vector (from intersection point to eye). - * @param n Surface normal. - * @param material Surface material. + * @param view View vector (from intersection point to eye). + * @param normal Surface normal. * @return */ - protected Color3f shade( Point3d hitPoint, Vector3d v, Vector3d n) + protected Color3f shade( Point3d hitPoint, Vector3d view, Vector3d normal) { - Vector3d l = new Vector3d(); + Vector3d lightDirection = new Vector3d(); Vector3d h = new Vector3d(); Color3f color = new Color3f( ambientColor ); @@ -38,21 +36,22 @@ protected Color3f shade( Point3d hitPoint, Vector3d v, Vector3d n) for( int i = 0; i < lightSources.length; i++ ) { LightSource lightSource = lightSources[i]; + LightProducts lightProducts = this.lightProducts[i]; - l.sub( lightSource.getPosition(), hitPoint ); - l.normalize(); + lightDirection.sub( lightSource.getPosition(), hitPoint ); + lightDirection.normalize(); - float lambertTerm = (float) n.dot( l ); + float lambertTerm = (float) normal.dot( lightDirection ); if( lambertTerm > 0.0f ) { // compute diffuse color component - color.scaleAdd( lambertTerm, lightProducts[i].getDiffuseProduct(), color ); + color.scaleAdd( lambertTerm, lightProducts.getDiffuseProduct(), color ); // compute specular color component - h.add( l, v ); + h.add( lightDirection, view ); h.normalize(); - - color.scaleAdd( ( float ) Math.pow( Math.max( 0.0f, n.dot( h ) ), lightProducts[i].getMaterial().getShininess() ), lightProducts[i].getSpecularProduct(), color ); + double specularTerm = Math.pow( Math.max( 0.0f, normal.dot(h) ), lightProducts.getMaterial().getShininess() ); + color.scaleAdd( (float)specularTerm, lightProducts.getSpecularProduct(), color ); } } From 340eaa4e412c6a7da47695859a089e3dedb9cccb Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 13:10:07 +0200 Subject: [PATCH 21/52] Remove unneeded for loop --- .../jsurf/rendering/cpu/RenderingTask.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 43c252a..82d70e3 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -251,21 +251,16 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad interval.x = Math.max( interval.x, eyeLocation ); // intersect ray with surface and shade pixel - //double[] hits = hits = dcsd.realRootFinder.findAllRootsIn( surfacePoly, interval.x, interval.y ); - double[] hits = { dcsd.realRootFinder.findFirstRootIn( surfacePoly, interval.x, interval.y ) }; - if( java.lang.Double.isNaN( hits[ 0 ] )) - hits = new double[ 0 ]; - for( double hit : hits ) + double hit = dcsd.realRootFinder.findFirstRootIn( surfacePoly, interval.x, interval.y ); + if( !java.lang.Double.isNaN( hit ) && dcsd.rayClipper.clipPoint( surfaceRay.at( hit ), true ) ) { - if( dcsd.rayClipper.clipPoint( surfaceRay.at( hit ), true ) ) - { - if( gradientPolys == null ) - gradientPolys = gcs.setU( u ); - Vector3d n_surfaceSpace = gradientPolys.setT( hit ); - Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); + if( gradientPolys == null ) + gradientPolys = gcs.setU( u ); - return shade( ray.at( hit ), n_cameraSpace, eye ); - } + Vector3d n_surfaceSpace = gradientPolys.setT( hit ); + Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); + + return shade( ray.at( hit ), n_cameraSpace, eye ); } } } From 7ede63443f2c09313cd55379b133ccc7e0819f2f Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Wed, 6 Jun 2018 14:14:28 +0200 Subject: [PATCH 22/52] Avoid recalculating the view direction and improve readability The ray already contains the viewing direction, so it does not need to be recalculated. By changing which parameters are passed to the shade function, it's possible to avoid some vector operations. --- .../jsurf/rendering/cpu/RenderingTask.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 82d70e3..11a1934 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -232,7 +232,6 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad Ray clippingRay = dcsd.rayCreator.createClippingSpaceRay( u, v ); Ray surfaceRay = dcsd.rayCreator.createSurfaceSpaceRay( u, v ); - Point3d eye = ray.at( dcsd.rayCreator.getEyeLocationOnRay() ); UnivariatePolynomialVector3d gradientPolys = null; // optimize rays and root-finder parameters @@ -260,7 +259,7 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad Vector3d n_surfaceSpace = gradientPolys.setT( hit ); Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); - return shade( ray.at( hit ), n_cameraSpace, eye ); + return shade( ray, hit, n_cameraSpace ); } } } @@ -269,31 +268,25 @@ private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGrad /** * Calculates the shading in camera space - * @param p The hit point on the surface in camera space. - * @param n The surface normal at the hit point in camera space. - * @param eye The eye point in camera space. - * @return */ - protected Color3f shade( Point3d p, Vector3d n, Point3d eye ) - { + protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) + { // normalize only if point is not singular - float nLength = (float) n.length(); + float nLength = (float) cameraSpaceNormal.length(); if( nLength != 0.0f ) - n.scale( 1.0f / nLength ); + cameraSpaceNormal.scale( 1.0f / nLength ); - // compute view vector - Vector3d v = new Vector3d( eye ); - v.sub( p ); - v.normalize(); + Vector3d view = new Vector3d(-ray.d.x, -ray.d.y, -ray.d.z); + // TODO: not normalizing the view does not seem to affect the rendered result, maybe it can be avoided + view.normalize(); - // compute, which material to use Shader shader = frontShader; - if( n.dot( v ) <= 0.0f ) { + if( cameraSpaceNormal.dot( view ) <= 0.0f ) { shader = backShader; - n.negate(); + cameraSpaceNormal.negate(); } - return shader.shade(p, v, n); + return shader.shade(ray.at(hit), view, cameraSpaceNormal); } // private Color3f traceRay( double u, double v ) From bf0099995307f87248984990b5dc07708473a38a Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 18:32:35 +0200 Subject: [PATCH 23/52] Avoid recalculating internal width and height --- .../java/de/mfo/jsurf/rendering/cpu/RenderingTask.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 11a1934..5d83c21 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -78,7 +78,7 @@ private class ColumnSubstitutorPair protected void render(Color3f[] colorBuffer, int width, int height) throws RenderingInterruptedException { switch( dcsd.antiAliasingPattern ) { case OG_1x1: { - renderWithoutAliasing(); + renderWithoutAliasing(width, height); break; } // all other antialiasing modes @@ -138,20 +138,18 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he } /** no antialising -> sample pixel center */ - private void renderWithoutAliasing() { - int internal_width = xEnd - xStart + 1; - int internal_height = yEnd - yStart + 1; + private void renderWithoutAliasing(int width, int height) { double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); double v_start = dcsd.rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); - for( int y = 0; y < internal_height; y++ ) + for( int y = 0; y < height; y++ ) { double v = v_start + y * v_incr; ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); - for( int x = 0; x < internal_width; x++ ) + for( int x = 0; x < width; x++ ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); From 3b834a8fc57f3f9bd5bd7daf031488a39de3412c Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 20:17:38 +0200 Subject: [PATCH 24/52] Move pixel-stepping information to a new class --- .../jsurf/rendering/cpu/RenderingTask.java | 63 ++++++++++++++----- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 5d83c21..05e6605 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -87,18 +87,51 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende } } + private class PixelStep { + public final double u_start; + public final double v_start; + public final double u_incr; + public final double v_incr; + + private PixelStep(double u_start, double v_start, double u_incr, double v_incr) { + this.u_start = u_start; + this.v_start = v_start; + this.u_incr = u_incr; + this.v_incr = v_incr; + } + } + + private PixelStep stepsWithAliasing() { + RayCreator rayCreator = dcsd.rayCreator; + Vector2d uInterval = rayCreator.getUInterval(); + Vector2d vInterval = rayCreator.getVInterval(); + double u_start = rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); + double v_start = rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); + double u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); + double v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); + return new PixelStep(u_start, v_start, u_incr, v_incr); + } + + private PixelStep stepsWithoutAliasing() { + RayCreator rayCreator = dcsd.rayCreator; + Vector2d uInterval = rayCreator.getUInterval(); + Vector2d vInterval = rayCreator.getVInterval(); + double u_start = rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); + double v_start = rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); + double u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); + double v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); + return new PixelStep(u_start, v_start, u_incr, v_incr); + } + private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { // first sample canvas at pixel corners and cast primary rays ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - double u_start = dcsd.rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); - double v_start = dcsd.rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); - double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); - double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); + PixelStep step = stepsWithAliasing(); double vOld = 0; - double v = v_start; + double v = step.v_start; int internalBufferIndex = 0; for( int y = 0; y < height; ++y ) { @@ -111,7 +144,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); double uOld = 0; - double u = u_start; + double u = step.u_start; for( int x = 0; x < width; ++x ) { if( Thread.currentThread().isInterrupted() ) @@ -126,26 +159,24 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he Color3f lrColor = internalColorBuffer[ internalBufferIndex - width ]; Color3f llColor = internalColorBuffer[ internalBufferIndex - width - 1 ]; - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, u_incr, v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, step.u_incr, step.v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } uOld = u; - u += u_incr; + u += step.u_incr; internalBufferIndex++; } vOld = v; - v += v_incr; + v += step.v_incr; } } /** no antialising -> sample pixel center */ private void renderWithoutAliasing(int width, int height) { - double u_start = dcsd.rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); - double v_start = dcsd.rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); - double u_incr = ( dcsd.rayCreator.getUInterval().y - dcsd.rayCreator.getUInterval().x ) / ( dcsd.width - 1.0 ); - double v_incr = ( dcsd.rayCreator.getVInterval().y - dcsd.rayCreator.getVInterval().x ) / ( dcsd.height - 1.0 ); + PixelStep step = stepsWithoutAliasing(); + for( int y = 0; y < height; y++ ) { - double v = v_start + y * v_incr; + double v = step.v_start + y * step.v_incr; ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); @@ -153,13 +184,13 @@ private void renderWithoutAliasing(int width, int height) { { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - double u = u_start + x * u_incr; + double u = step.u_start + x * step.u_incr; dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, u, v ).get().getRGB(); //dcsd.colorBuffer[ dcsd.width * y + x ] = traceRay( u, v ).get().getRGB(); } } } - + private Color3f antiAliasPixel( double ll_u, double ll_v, double u_incr, double v_incr, AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor, HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm ) { // first average pixel-corner colors From 73a22aa090769b39fe37646dc8bd99b292876c3d Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 20:32:15 +0200 Subject: [PATCH 25/52] De-duplicate PixelStep creation --- .../jsurf/rendering/cpu/RenderingTask.java | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 05e6605..4ed904f 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -87,7 +87,7 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende } } - private class PixelStep { + private static class PixelStep { public final double u_start; public final double v_start; public final double u_incr; @@ -99,28 +99,16 @@ private PixelStep(double u_start, double v_start, double u_incr, double v_incr) this.u_incr = u_incr; this.v_incr = v_incr; } - } - - private PixelStep stepsWithAliasing() { - RayCreator rayCreator = dcsd.rayCreator; - Vector2d uInterval = rayCreator.getUInterval(); - Vector2d vInterval = rayCreator.getVInterval(); - double u_start = rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); - double v_start = rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); - double u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); - double v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); - return new PixelStep(u_start, v_start, u_incr, v_incr); - } - - private PixelStep stepsWithoutAliasing() { - RayCreator rayCreator = dcsd.rayCreator; - Vector2d uInterval = rayCreator.getUInterval(); - Vector2d vInterval = rayCreator.getVInterval(); - double u_start = rayCreator.transformU( xStart / ( dcsd.width - 1.0 ) ); - double v_start = rayCreator.transformV( yStart / ( dcsd.height - 1.0 ) ); - double u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); - double v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); - return new PixelStep(u_start, v_start, u_incr, v_incr); + + private PixelStep(DrawcallStaticData dcsd, int xStart, int yStart) { + RayCreator rayCreator = dcsd.rayCreator; + Vector2d uInterval = rayCreator.getUInterval(); + Vector2d vInterval = rayCreator.getVInterval(); + this.u_start = rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); + this.v_start = rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); + this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); + this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); + } } private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { @@ -128,7 +116,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - PixelStep step = stepsWithAliasing(); + PixelStep step = new PixelStep(dcsd, xStart, yStart); double vOld = 0; double v = step.v_start; @@ -172,7 +160,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he /** no antialising -> sample pixel center */ private void renderWithoutAliasing(int width, int height) { - PixelStep step = stepsWithoutAliasing(); + PixelStep step = new PixelStep(dcsd, xStart, yStart); for( int y = 0; y < height; y++ ) { From ba49dee9adb76160abf54e7e5e918fc93b083f0e Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 20:54:34 +0200 Subject: [PATCH 26/52] Move u and v variables inside the PixelStep instance --- .../jsurf/rendering/cpu/RenderingTask.java | 73 ++++++++++++------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 4ed904f..8722946 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -87,20 +87,22 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende } } + /** + * Holds information needed for stepping through the pixels in the image + * + */ private static class PixelStep { public final double u_start; public final double v_start; public final double u_incr; public final double v_incr; - private PixelStep(double u_start, double v_start, double u_incr, double v_incr) { - this.u_start = u_start; - this.v_start = v_start; - this.u_incr = u_incr; - this.v_incr = v_incr; - } + public double v; + public double u; + public double vOld; + public double uOld; - private PixelStep(DrawcallStaticData dcsd, int xStart, int yStart) { + public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart) { RayCreator rayCreator = dcsd.rayCreator; Vector2d uInterval = rayCreator.getUInterval(); Vector2d vInterval = rayCreator.getVInterval(); @@ -108,6 +110,29 @@ private PixelStep(DrawcallStaticData dcsd, int xStart, int yStart) { this.v_start = rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); + + reset(); + } + + private void reset() { + vOld = 0; + v = v_start; + + uOld = 0; + u = u_start; + } + + public void stepU() { + uOld = u; + u += u_incr; + } + + public void stepV() { + vOld = v; + v += v_incr; + + uOld = 0; + u = u_start; } } @@ -118,28 +143,24 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); PixelStep step = new PixelStep(dcsd, xStart, yStart); - double vOld = 0; - double v = step.v_start; int internalBufferIndex = 0; for( int y = 0; y < height; ++y ) { csp_hm.clear(); - csp_hm.put( vOld, new ColumnSubstitutorPair( scs, gcs ) ); + csp_hm.put( step.vOld, new ColumnSubstitutorPair( scs, gcs ) ); - scs = dcsd.surfaceRowSubstitutor.setV( v ); - gcs = dcsd.gradientRowSubstitutor.setV( v ); + scs = dcsd.surfaceRowSubstitutor.setV( step.v ); + gcs = dcsd.gradientRowSubstitutor.setV( step.v ); - csp_hm.put( v, new ColumnSubstitutorPair( scs, gcs ) ); + csp_hm.put( step.v, new ColumnSubstitutorPair( scs, gcs ) ); - double uOld = 0; - double u = step.u_start; for( int x = 0; x < width; ++x ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ internalBufferIndex ] = tracePolynomial( scs, gcs, u, v ); + internalColorBuffer[ internalBufferIndex ] = tracePolynomial( scs, gcs, step.u, step.v ); if( x > 0 && y > 0 ) { Color3f urColor = internalColorBuffer[ internalBufferIndex ]; @@ -147,14 +168,12 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he Color3f lrColor = internalColorBuffer[ internalBufferIndex - width ]; Color3f llColor = internalColorBuffer[ internalBufferIndex - width - 1 ]; - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( uOld, vOld, step.u_incr, step.v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( step.uOld, step.vOld, step.u_incr, step.v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } - uOld = u; - u += step.u_incr; + step.stepU(); internalBufferIndex++; } - vOld = v; - v += step.v_incr; + step.stepV(); } } @@ -164,18 +183,18 @@ private void renderWithoutAliasing(int width, int height) { for( int y = 0; y < height; y++ ) { - double v = step.v_start + y * step.v_incr; - ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( v ); - ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( v ); + ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( step.v ); + ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( step.v ); for( int x = 0; x < width; x++ ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - double u = step.u_start + x * step.u_incr; - dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, u, v ).get().getRGB(); - //dcsd.colorBuffer[ dcsd.width * y + x ] = traceRay( u, v ).get().getRGB(); + + dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, step.u, step.v ).get().getRGB(); + step.stepU(); } + step.stepV(); } } From dbcf1bf7ec9757e89f83b62b1fa42affe67ef521 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 21:07:53 +0200 Subject: [PATCH 27/52] Move image dimensions into the PixelStep --- .../jsurf/rendering/cpu/RenderingTask.java | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 8722946..3b9bb77 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -52,7 +52,8 @@ public Boolean call() { int height = yEnd - yStart + 2; Color3f[] colorBuffer = bufferPool.getBuffer(width * height); try { - render(colorBuffer, width, height); + PixelStep step = new PixelStep(dcsd, xStart, yStart, width, height); + render(colorBuffer, step); return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok } catch( Throwable t ) { @@ -75,15 +76,15 @@ private class ColumnSubstitutorPair ColumnSubstitutorForGradient gcs; } - protected void render(Color3f[] colorBuffer, int width, int height) throws RenderingInterruptedException { + protected void render(Color3f[] colorBuffer, PixelStep step) throws RenderingInterruptedException { switch( dcsd.antiAliasingPattern ) { case OG_1x1: { - renderWithoutAliasing(width, height); + renderWithoutAliasing(step); break; } // all other antialiasing modes default: - renderWithAliasing(colorBuffer, width, height); + renderWithAliasing(colorBuffer, step); } } @@ -92,17 +93,23 @@ protected void render(Color3f[] colorBuffer, int width, int height) throws Rende * */ private static class PixelStep { - public final double u_start; - public final double v_start; - public final double u_incr; - public final double v_incr; + private final double u_start; + private final double v_start; + private final double u_incr; + private final double v_incr; + + public final int width; + public final int height; public double v; public double u; public double vOld; public double uOld; + + public int colorBufferIndex; + private final int colorBufferVStep; - public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart) { + public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int width, int height) { RayCreator rayCreator = dcsd.rayCreator; Vector2d uInterval = rayCreator.getUInterval(); Vector2d vInterval = rayCreator.getVInterval(); @@ -111,6 +118,10 @@ public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart) { this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); + this.width = width; + this.height = height; + this.colorBufferIndex = (yStart - 1) * dcsd.width + xStart - 1; + this.colorBufferVStep = dcsd.width - width; reset(); } @@ -125,6 +136,7 @@ private void reset() { public void stepU() { uOld = u; u += u_incr; + colorBufferIndex++; } public void stepV() { @@ -133,18 +145,18 @@ public void stepV() { uOld = 0; u = u_start; + colorBufferIndex += colorBufferVStep; } } - private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int height) { + private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { // first sample canvas at pixel corners and cast primary rays ColumnSubstitutor scs = null; ColumnSubstitutorForGradient gcs = null; HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - PixelStep step = new PixelStep(dcsd, xStart, yStart); int internalBufferIndex = 0; - for( int y = 0; y < height; ++y ) + for( int y = 0; y < step.height; ++y ) { csp_hm.clear(); csp_hm.put( step.vOld, new ColumnSubstitutorPair( scs, gcs ) ); @@ -154,7 +166,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he csp_hm.put( step.v, new ColumnSubstitutorPair( scs, gcs ) ); - for( int x = 0; x < width; ++x ) + for( int x = 0; x < step.width; ++x ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); @@ -165,10 +177,10 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he { Color3f urColor = internalColorBuffer[ internalBufferIndex ]; Color3f ulColor = internalColorBuffer[ internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ internalBufferIndex - width ]; - Color3f llColor = internalColorBuffer[ internalBufferIndex - width - 1 ]; + Color3f lrColor = internalColorBuffer[ internalBufferIndex - step.width ]; + Color3f llColor = internalColorBuffer[ internalBufferIndex - step.width - 1 ]; - dcsd.colorBuffer[ ( yStart + y - 1 ) * dcsd.width + ( xStart + x - 1 ) ] = antiAliasPixel( step.uOld, step.vOld, step.u_incr, step.v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( step.uOld, step.vOld, step.u_incr, step.v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } step.stepU(); internalBufferIndex++; @@ -178,20 +190,19 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, int width, int he } /** no antialising -> sample pixel center */ - private void renderWithoutAliasing(int width, int height) { - PixelStep step = new PixelStep(dcsd, xStart, yStart); + private void renderWithoutAliasing(PixelStep step) { - for( int y = 0; y < height; y++ ) + for( int y = 0; y < step.height; y++ ) { ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( step.v ); ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( step.v ); - for( int x = 0; x < width; x++ ) + for( int x = 0; x < step.width; x++ ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - dcsd.colorBuffer[ dcsd.width * ( yStart + y ) + xStart + x ] = tracePolynomial( scs, gcs, step.u, step.v ).get().getRGB(); + dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial( scs, gcs, step.u, step.v ).get().getRGB(); step.stepU(); } step.stepV(); From fa674df032f9c1512cfeca2278cffa1d497d86f1 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 21:13:39 +0200 Subject: [PATCH 28/52] Make PixelStep an instance variable This will remove the need for most other instance variables, and allow to remove parameters from some functions --- .../jsurf/rendering/cpu/RenderingTask.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 3b9bb77..b2073be 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -28,31 +28,22 @@ public class RenderingTask implements Callable static ColorBufferPool bufferPool = new ColorBufferPool(); // initialized by the constructor - private int xStart; - private int yStart; - private int xEnd; - private int yEnd; private final DrawcallStaticData dcsd; private final Shader frontShader; private final Shader backShader; + private final PixelStep step; public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { this.dcsd = dcsd; - this.xStart = xStart; - this.yStart = yStart; - this.xEnd = xEnd; - this.yEnd = yEnd; + this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); } public Boolean call() { - int width = xEnd - xStart + 2; - int height = yEnd - yStart + 2; - Color3f[] colorBuffer = bufferPool.getBuffer(width * height); + Color3f[] colorBuffer = bufferPool.getBuffer(step.width * step.height); try { - PixelStep step = new PixelStep(dcsd, xStart, yStart, width, height); render(colorBuffer, step); return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok @@ -180,7 +171,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { Color3f lrColor = internalColorBuffer[ internalBufferIndex - step.width ]; Color3f llColor = internalColorBuffer[ internalBufferIndex - step.width - 1 ]; - dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( step.uOld, step.vOld, step.u_incr, step.v_incr, dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); } step.stepU(); internalBufferIndex++; @@ -209,7 +200,7 @@ private void renderWithoutAliasing(PixelStep step) { } } - private Color3f antiAliasPixel( double ll_u, double ll_v, double u_incr, double v_incr, AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor, HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm ) + private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor, HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm ) { // first average pixel-corner colors Color3f finalColor; @@ -242,8 +233,8 @@ else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) else { // color of this sample point is not known -> calculate - double v = ll_v + sp.getV() * v_incr; - double u = ll_u + sp.getU() * u_incr; + double v = step.v + sp.getV() * step.v_incr; + double u = step.u + sp.getU() * step.u_incr; ColumnSubstitutorPair csp = csp_hm.get( v ); if( csp == null ) { From 28c05138e6e6fc1b30f25416589e2c9a216d68ef Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 22:57:58 +0200 Subject: [PATCH 29/52] Restore correct pixel displacement when rendering without aliasing --- .../java/de/mfo/jsurf/rendering/cpu/RenderingTask.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index b2073be..7f1e8fb 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -104,8 +104,9 @@ public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int width, int RayCreator rayCreator = dcsd.rayCreator; Vector2d uInterval = rayCreator.getUInterval(); Vector2d vInterval = rayCreator.getVInterval(); - this.u_start = rayCreator.transformU( ( xStart - 0.5 ) / ( dcsd.width - 1.0 ) ); - this.v_start = rayCreator.transformV( ( yStart - 0.5 ) / ( dcsd.height - 1.0 ) ); + double displace = (dcsd.antiAliasingPattern == AntiAliasingPattern.OG_1x1) ? 0 : 0.5; + this.u_start = rayCreator.transformU( ( xStart - displace ) / ( dcsd.width - 1.0 ) ); + this.v_start = rayCreator.transformV( ( yStart - displace ) / ( dcsd.height - 1.0 ) ); this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); @@ -233,8 +234,8 @@ else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) else { // color of this sample point is not known -> calculate - double v = step.v + sp.getV() * step.v_incr; - double u = step.u + sp.getU() * step.u_incr; + double v = step.vOld + sp.getV() * step.v_incr; + double u = step.uOld + sp.getU() * step.u_incr; ColumnSubstitutorPair csp = csp_hm.get( v ); if( csp == null ) { From d7c7b8a00538a29775f0ad9af86e2416eec615a4 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Fri, 8 Jun 2018 23:37:54 +0200 Subject: [PATCH 30/52] Avoid re-setting the same ColumnSubstitutorPair in the hashmap When vOld == 0, the CSP will have only null pointers, which are never used. When vOld == the old v, then it will just overwrite the previous CSP set for v. This does not happen when the hashmap is cleared, but doing so prevents the reuse of the CS and CSG for different pixels in the same column. --- .../java/de/mfo/jsurf/rendering/cpu/RenderingTask.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 7f1e8fb..fad95a7 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -143,18 +143,13 @@ public void stepV() { private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { // first sample canvas at pixel corners and cast primary rays - ColumnSubstitutor scs = null; - ColumnSubstitutorForGradient gcs = null; HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); int internalBufferIndex = 0; for( int y = 0; y < step.height; ++y ) { - csp_hm.clear(); - csp_hm.put( step.vOld, new ColumnSubstitutorPair( scs, gcs ) ); - - scs = dcsd.surfaceRowSubstitutor.setV( step.v ); - gcs = dcsd.gradientRowSubstitutor.setV( step.v ); + ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( step.v ); + ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( step.v ); csp_hm.put( step.v, new ColumnSubstitutorPair( scs, gcs ) ); From 6aa50674946b4f22e6a9602e45b13b4f61846e70 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 00:10:53 +0200 Subject: [PATCH 31/52] Make the CSP hashmap an instance variable --- .../java/de/mfo/jsurf/rendering/cpu/RenderingTask.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index fad95a7..8bf051b 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -32,6 +32,7 @@ public class RenderingTask implements Callable private final Shader frontShader; private final Shader backShader; private final PixelStep step; + private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { @@ -39,6 +40,7 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); + this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); } public Boolean call() { @@ -143,7 +145,6 @@ public void stepV() { private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { // first sample canvas at pixel corners and cast primary rays - HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); int internalBufferIndex = 0; for( int y = 0; y < step.height; ++y ) @@ -167,7 +168,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { Color3f lrColor = internalColorBuffer[ internalBufferIndex - step.width ]; Color3f llColor = internalColorBuffer[ internalBufferIndex - step.width - 1 ]; - dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor, csp_hm ).get().getRGB(); + dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); } step.stepU(); internalBufferIndex++; @@ -196,7 +197,7 @@ private void renderWithoutAliasing(PixelStep step) { } } - private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor, HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm ) + private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) { // first average pixel-corner colors Color3f finalColor; From c2f30c941d1fd07cedd83fab4cdc566a51d4866a Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 09:31:32 +0200 Subject: [PATCH 32/52] Move logic of choosing which render method to use into call method --- .../jsurf/rendering/cpu/RenderingTask.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 8bf051b..4b1ebf8 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -44,19 +44,29 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, } public Boolean call() { - Color3f[] colorBuffer = bufferPool.getBuffer(step.width * step.height); + Color3f[] colorBuffer = null; try { - render(colorBuffer, step); + if (useAliasing()) { + colorBuffer = bufferPool.getBuffer(step.width * step.height); + renderWithAliasing(colorBuffer, step); + } else { + renderWithoutAliasing(step); + } return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok } catch( Throwable t ) { t.printStackTrace(); } finally { - bufferPool.releaseBuffer(colorBuffer); + if (colorBuffer != null) + bufferPool.releaseBuffer(colorBuffer); } return false; } + private boolean useAliasing() { + return dcsd.antiAliasingPattern != AntiAliasingPattern.OG_1x1; + } + private class ColumnSubstitutorPair { ColumnSubstitutorPair( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs ) @@ -69,18 +79,6 @@ private class ColumnSubstitutorPair ColumnSubstitutorForGradient gcs; } - protected void render(Color3f[] colorBuffer, PixelStep step) throws RenderingInterruptedException { - switch( dcsd.antiAliasingPattern ) { - case OG_1x1: { - renderWithoutAliasing(step); - break; - } - // all other antialiasing modes - default: - renderWithAliasing(colorBuffer, step); - } - } - /** * Holds information needed for stepping through the pixels in the image * From 78f13398695d91b8f784117a4d690561471613bd Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 09:33:39 +0200 Subject: [PATCH 33/52] Move inner classes to top of file --- .../jsurf/rendering/cpu/RenderingTask.java | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 4b1ebf8..70d37b1 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -25,63 +25,8 @@ public class RenderingTask implements Callable { - static ColorBufferPool bufferPool = new ColorBufferPool(); - - // initialized by the constructor - private final DrawcallStaticData dcsd; - private final Shader frontShader; - private final Shader backShader; - private final PixelStep step; - private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; - - public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) - { - this.dcsd = dcsd; - this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); - this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); - this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); - this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - } - - public Boolean call() { - Color3f[] colorBuffer = null; - try { - if (useAliasing()) { - colorBuffer = bufferPool.getBuffer(step.width * step.height); - renderWithAliasing(colorBuffer, step); - } else { - renderWithoutAliasing(step); - } - return true; - } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok - } catch( Throwable t ) { - t.printStackTrace(); - } finally { - if (colorBuffer != null) - bufferPool.releaseBuffer(colorBuffer); - } - return false; - } - - private boolean useAliasing() { - return dcsd.antiAliasingPattern != AntiAliasingPattern.OG_1x1; - } - - private class ColumnSubstitutorPair - { - ColumnSubstitutorPair( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs ) - { - this.scs = scs; - this.gcs = gcs; - } - - ColumnSubstitutor scs; - ColumnSubstitutorForGradient gcs; - } - /** * Holds information needed for stepping through the pixels in the image - * */ private static class PixelStep { private final double u_start; @@ -141,6 +86,60 @@ public void stepV() { } } + private class ColumnSubstitutorPair + { + ColumnSubstitutorPair( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs ) + { + this.scs = scs; + this.gcs = gcs; + } + + ColumnSubstitutor scs; + ColumnSubstitutorForGradient gcs; + } + + static ColorBufferPool bufferPool = new ColorBufferPool(); + + // initialized by the constructor + private final DrawcallStaticData dcsd; + private final Shader frontShader; + private final Shader backShader; + private final PixelStep step; + private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; + + public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) + { + this.dcsd = dcsd; + this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); + this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); + this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); + this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + } + + public Boolean call() { + Color3f[] colorBuffer = null; + try { + if (useAliasing()) { + colorBuffer = bufferPool.getBuffer(step.width * step.height); + renderWithAliasing(colorBuffer, step); + } else { + renderWithoutAliasing(step); + } + return true; + } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok + } catch( Throwable t ) { + t.printStackTrace(); + } finally { + if (colorBuffer != null) + bufferPool.releaseBuffer(colorBuffer); + } + return false; + } + + private boolean useAliasing() { + return dcsd.antiAliasingPattern != AntiAliasingPattern.OG_1x1; + } + private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { // first sample canvas at pixel corners and cast primary rays From 9ff7187f097a31714156370af87455e7b4a2f941 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 10:59:05 +0200 Subject: [PATCH 34/52] Move CSP creation to a new class This removes the responsibilities of the rendering methods, as how the CSP is stored can be considered a different concern. Also, this change opens the doors to changing how the CSPs are cached, as a hashmap might not be the most efficient solution. --- .../jsurf/rendering/cpu/RenderingTask.java | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 70d37b1..46ef85a 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -86,16 +86,37 @@ public void stepV() { } } - private class ColumnSubstitutorPair + private static class ColumnSubstitutorPair { + public final ColumnSubstitutor scs; + public final ColumnSubstitutorForGradient gcs; + ColumnSubstitutorPair( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs ) { this.scs = scs; this.gcs = gcs; } + } - ColumnSubstitutor scs; - ColumnSubstitutorForGradient gcs; + private static class ColumnSubstitutorPairProvider { + private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; + private final RowSubstitutor surfaceRowSubstitutor; + private final RowSubstitutorForGradient gradientRowSubstitutor; + + public ColumnSubstitutorPairProvider(DrawcallStaticData dcsd) { + this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + this.surfaceRowSubstitutor = dcsd.surfaceRowSubstitutor; + this.gradientRowSubstitutor = dcsd.gradientRowSubstitutor; + } + + public ColumnSubstitutorPair get(double v) { + ColumnSubstitutorPair csp = csp_hm.get(v); + if (csp == null) { + csp = new ColumnSubstitutorPair(surfaceRowSubstitutor.setV( v ), gradientRowSubstitutor.setV( v )); + csp_hm.put(v, csp); + } + return csp; + } } static ColorBufferPool bufferPool = new ColorBufferPool(); @@ -105,7 +126,7 @@ private class ColumnSubstitutorPair private final Shader frontShader; private final Shader backShader; private final PixelStep step; - private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; + private final ColumnSubstitutorPairProvider cspProvider; public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { @@ -113,7 +134,7 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); - this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + this.cspProvider = new ColumnSubstitutorPairProvider(dcsd); } public Boolean call() { @@ -146,10 +167,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { int internalBufferIndex = 0; for( int y = 0; y < step.height; ++y ) { - ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( step.v ); - ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( step.v ); - - csp_hm.put( step.v, new ColumnSubstitutorPair( scs, gcs ) ); + ColumnSubstitutorPair csp = cspProvider.get(step.v); for( int x = 0; x < step.width; ++x ) { @@ -157,7 +175,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { throw new RenderingInterruptedException(); // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ internalBufferIndex ] = tracePolynomial( scs, gcs, step.u, step.v ); + internalColorBuffer[ internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); if( x > 0 && y > 0 ) { Color3f urColor = internalColorBuffer[ internalBufferIndex ]; @@ -179,15 +197,14 @@ private void renderWithoutAliasing(PixelStep step) { for( int y = 0; y < step.height; y++ ) { - ColumnSubstitutor scs = dcsd.surfaceRowSubstitutor.setV( step.v ); - ColumnSubstitutorForGradient gcs = dcsd.gradientRowSubstitutor.setV( step.v ); - + ColumnSubstitutorPair csp = cspProvider.get(step.v); + for( int x = 0; x < step.width; x++ ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial( scs, gcs, step.u, step.v ).get().getRGB(); + dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); step.stepU(); } step.stepV(); @@ -229,12 +246,7 @@ else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) // color of this sample point is not known -> calculate double v = step.vOld + sp.getV() * step.v_incr; double u = step.uOld + sp.getU() * step.u_incr; - ColumnSubstitutorPair csp = csp_hm.get( v ); - if( csp == null ) - { - csp = new ColumnSubstitutorPair( dcsd.surfaceRowSubstitutor.setV( v ), dcsd.gradientRowSubstitutor.setV( v ) ); - csp_hm.put( v, csp ); - } + ColumnSubstitutorPair csp = cspProvider.get( v ); ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); } finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); From a156efcbb588657e6991d7cf4167146c6a7efc5c Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 10:59:30 +0200 Subject: [PATCH 35/52] Correct names of functions --- .../de/mfo/jsurf/rendering/cpu/RenderingTask.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 46ef85a..392a1d7 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -140,11 +140,11 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, public Boolean call() { Color3f[] colorBuffer = null; try { - if (useAliasing()) { + if (useAntiAliasing()) { colorBuffer = bufferPool.getBuffer(step.width * step.height); - renderWithAliasing(colorBuffer, step); + renderWithAntiAliasing(colorBuffer, step); } else { - renderWithoutAliasing(step); + renderWithoutAntiAliasing(step); } return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok @@ -157,11 +157,11 @@ public Boolean call() { return false; } - private boolean useAliasing() { + private boolean useAntiAliasing() { return dcsd.antiAliasingPattern != AntiAliasingPattern.OG_1x1; } - private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { + private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep step) { // first sample canvas at pixel corners and cast primary rays int internalBufferIndex = 0; @@ -193,7 +193,7 @@ private void renderWithAliasing(Color3f[] internalColorBuffer, PixelStep step) { } /** no antialising -> sample pixel center */ - private void renderWithoutAliasing(PixelStep step) { + private void renderWithoutAntiAliasing(PixelStep step) { for( int y = 0; y < step.height; y++ ) { From 3ff425cfa739b72b068ea7e9f35246ec5c96b3f2 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 12:22:57 +0200 Subject: [PATCH 36/52] Remove the internal color buffer index control from the rendering function --- .../de/mfo/jsurf/rendering/cpu/RenderingTask.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 392a1d7..00f7c47 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -42,6 +42,7 @@ private static class PixelStep { public double vOld; public double uOld; + public int internalBufferIndex; public int colorBufferIndex; private final int colorBufferVStep; @@ -74,6 +75,7 @@ public void stepU() { uOld = u; u += u_incr; colorBufferIndex++; + internalBufferIndex++; } public void stepV() { @@ -164,7 +166,6 @@ private boolean useAntiAliasing() { private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep step) { // first sample canvas at pixel corners and cast primary rays - int internalBufferIndex = 0; for( int y = 0; y < step.height; ++y ) { ColumnSubstitutorPair csp = cspProvider.get(step.v); @@ -175,18 +176,17 @@ private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep ste throw new RenderingInterruptedException(); // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); + internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); if( x > 0 && y > 0 ) { - Color3f urColor = internalColorBuffer[ internalBufferIndex ]; - Color3f ulColor = internalColorBuffer[ internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ internalBufferIndex - step.width ]; - Color3f llColor = internalColorBuffer[ internalBufferIndex - step.width - 1 ]; + Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; + Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); } step.stepU(); - internalBufferIndex++; } step.stepV(); } From eb7efdf0b3de6284186f80f41235bbb4ea8d97dc Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 12:41:52 +0200 Subject: [PATCH 37/52] Move pixel render strategy to new method(s) --- .../jsurf/rendering/cpu/RenderingTask.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 00f7c47..205d1a6 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -164,8 +164,6 @@ private boolean useAntiAliasing() { } private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep step) { - // first sample canvas at pixel corners and cast primary rays - for( int y = 0; y < step.height; ++y ) { ColumnSubstitutorPair csp = cspProvider.get(step.v); @@ -175,17 +173,7 @@ private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep ste if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - // trace rays corresponding to (u,v)-coordinates on viewing plane - internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); - if( x > 0 && y > 0 ) - { - Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; - Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; - Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; - - dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); - } + renderPixelWithAntiAliasing(x, y, step, csp, internalColorBuffer); step.stepU(); } step.stepV(); @@ -204,12 +192,30 @@ private void renderWithoutAntiAliasing(PixelStep step) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); + renderPixelWithoutAntiAliasing(step, csp); step.stepU(); } step.stepV(); } } + + private void renderPixelWithAntiAliasing(int x, int y, PixelStep step, ColumnSubstitutorPair csp, Color3f[] internalColorBuffer) { + internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); + if( x > 0 && y > 0 ) + { + Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; + Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; + + dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); + } + } + + + private void renderPixelWithoutAntiAliasing(PixelStep step, ColumnSubstitutorPair csp) { + dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); + } private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) { From 35a6eec237e740af98efcac0c95a54b3d3a2e58d Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 13:12:02 +0200 Subject: [PATCH 38/52] Move pixel render strategies to its own class --- .../jsurf/rendering/cpu/RenderingTask.java | 213 +++++++++--------- 1 file changed, 105 insertions(+), 108 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 205d1a6..d9b250f 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -121,6 +121,105 @@ public ColumnSubstitutorPair get(double v) { } } + private abstract class PixelRenderStrategy { + public abstract void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp); + } + + private class AntiAliasedPixelRenderer extends PixelRenderStrategy { + + private final Color3f[] internalColorBuffer; + private final float thresholdSqr; + + public AntiAliasedPixelRenderer(DrawcallStaticData cdsd, Color3f[] internalColorBuffer) { + this.internalColorBuffer = internalColorBuffer; + this.thresholdSqr = dcsd.antiAliasingThreshold * dcsd.antiAliasingThreshold; + } + + @Override + public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { + internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); + if( x > 0 && y > 0 ) + { + Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; + Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; + + dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); + } + } + + private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) + { + // first average pixel-corner colors + Color3f finalColor; + + // adaptive supersampling + if( aap != AntiAliasingPattern.OG_2x2 && ( colorDiffSqr( ulColor, urColor ) >= thresholdSqr || + colorDiffSqr( ulColor, llColor ) >= thresholdSqr || + colorDiffSqr( ulColor, lrColor ) >= thresholdSqr || + colorDiffSqr( urColor, llColor ) >= thresholdSqr || + colorDiffSqr( urColor, lrColor ) >= thresholdSqr || + colorDiffSqr( llColor, lrColor ) >= thresholdSqr ) ) + { + // anti-alias pixel with advanced sampling pattern + finalColor = new Color3f(); + for( AntiAliasingPattern.SamplingPoint sp : aap ) + { + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); + + Color3f ss_color; + if( sp.getU() == 0.0 && sp.getV() == 0.0 ) + ss_color = llColor; + else if( sp.getU() == 0.0 && sp.getV() == 1.0 ) + ss_color = ulColor; + else if( sp.getU() == 1.0 && sp.getV() == 1.0 ) + ss_color = urColor; + else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) + ss_color = lrColor; + else + { + // color of this sample point is not known -> calculate + double v = step.vOld + sp.getV() * step.v_incr; + double u = step.uOld + sp.getU() * step.u_incr; + ColumnSubstitutorPair csp = cspProvider.get( v ); + ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); + } + finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); + + if( false ) + return new Color3f( 0, 0, 0 ); // paint pixels, that are supposed to be anti-aliased in black + } + } + else + { + finalColor = new Color3f( ulColor ); + finalColor.add( urColor ); + finalColor.add( llColor ); + finalColor.add( lrColor ); + finalColor.scale( 0.25f ); + } + + // clamp color, because floating point operations may yield values outside [0,1] + finalColor.clamp( 0f, 1f ); + return finalColor; + } + + private float colorDiffSqr( Color3f c1, Color3f c2 ) + { + Vector3f diff = new Vector3f( c1 ); + diff.sub( c2 ); + return diff.dot( diff ); + } + } + + private class BasicPixelRenderer extends PixelRenderStrategy { + @Override public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { + dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); + } + } + static ColorBufferPool bufferPool = new ColorBufferPool(); // initialized by the constructor @@ -142,12 +241,14 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, public Boolean call() { Color3f[] colorBuffer = null; try { + PixelRenderStrategy pixelRenderer; if (useAntiAliasing()) { colorBuffer = bufferPool.getBuffer(step.width * step.height); - renderWithAntiAliasing(colorBuffer, step); + pixelRenderer = new AntiAliasedPixelRenderer(dcsd, colorBuffer); } else { - renderWithoutAntiAliasing(step); + pixelRenderer = new BasicPixelRenderer(); } + renderImage(pixelRenderer); return true; } catch( RenderingInterruptedException rie ) { // rendering interrupted .. that's ok } catch( Throwable t ) { @@ -163,7 +264,7 @@ private boolean useAntiAliasing() { return dcsd.antiAliasingPattern != AntiAliasingPattern.OG_1x1; } - private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep step) { + private void renderImage(PixelRenderStrategy pixelRenderer) { for( int y = 0; y < step.height; ++y ) { ColumnSubstitutorPair csp = cspProvider.get(step.v); @@ -173,108 +274,13 @@ private void renderWithAntiAliasing(Color3f[] internalColorBuffer, PixelStep ste if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - renderPixelWithAntiAliasing(x, y, step, csp, internalColorBuffer); + pixelRenderer.renderPixel(x, y, step, csp); step.stepU(); } step.stepV(); } } - /** no antialising -> sample pixel center */ - private void renderWithoutAntiAliasing(PixelStep step) { - - for( int y = 0; y < step.height; y++ ) - { - ColumnSubstitutorPair csp = cspProvider.get(step.v); - - for( int x = 0; x < step.width; x++ ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - - renderPixelWithoutAntiAliasing(step, csp); - step.stepU(); - } - step.stepV(); - } - } - - private void renderPixelWithAntiAliasing(int x, int y, PixelStep step, ColumnSubstitutorPair csp, Color3f[] internalColorBuffer) { - internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); - if( x > 0 && y > 0 ) - { - Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; - Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; - Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; - - dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); - } - } - - - private void renderPixelWithoutAntiAliasing(PixelStep step, ColumnSubstitutorPair csp) { - dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); - } - - private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) - { - // first average pixel-corner colors - Color3f finalColor; - - // adaptive supersampling - float thresholdSqr = dcsd.antiAliasingThreshold * dcsd.antiAliasingThreshold; - if( aap != AntiAliasingPattern.OG_2x2 && ( colorDiffSqr( ulColor, urColor ) >= thresholdSqr || - colorDiffSqr( ulColor, llColor ) >= thresholdSqr || - colorDiffSqr( ulColor, lrColor ) >= thresholdSqr || - colorDiffSqr( urColor, llColor ) >= thresholdSqr || - colorDiffSqr( urColor, lrColor ) >= thresholdSqr || - colorDiffSqr( llColor, lrColor ) >= thresholdSqr ) ) - { - // anti-alias pixel with advanced sampling pattern - finalColor = new Color3f(); - for( AntiAliasingPattern.SamplingPoint sp : aap ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - - Color3f ss_color; - if( sp.getU() == 0.0 && sp.getV() == 0.0 ) - ss_color = llColor; - else if( sp.getU() == 0.0 && sp.getV() == 1.0 ) - ss_color = ulColor; - else if( sp.getU() == 1.0 && sp.getV() == 1.0 ) - ss_color = urColor; - else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) - ss_color = lrColor; - else - { - // color of this sample point is not known -> calculate - double v = step.vOld + sp.getV() * step.v_incr; - double u = step.uOld + sp.getU() * step.u_incr; - ColumnSubstitutorPair csp = cspProvider.get( v ); - ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); - } - finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); - - if( false ) - return new Color3f( 0, 0, 0 ); // paint pixels, that are supposed to be anti-aliased in black - } - } - else - { - finalColor = new Color3f( ulColor ); - finalColor.add( urColor ); - finalColor.add( llColor ); - finalColor.add( lrColor ); - finalColor.scale( 0.25f ); - } - - // clamp color, because floating point operations may yield values outside [0,1] - finalColor.clamp( 0f, 1f ); - return finalColor; - } - private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs, double u, double v ) { // create rays @@ -381,13 +387,6 @@ protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) // return dcsd.backgroundColor; // } - private float colorDiffSqr( Color3f c1, Color3f c2 ) - { - Vector3f diff = new Vector3f( c1 ); - diff.sub( c2 ); - return diff.dot( diff ); - } - protected boolean intersectPolynomial( UnivariatePolynomial p, double rayStart, double rayEnd, double[] hit ) { //System.out.println( p ); @@ -426,5 +425,3 @@ boolean blowUpChooseMaterial( Point3d p ) } } - - From b4287cbc0b2d8b537e2c5581a3d3b959e412e82b Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:16:50 +0200 Subject: [PATCH 39/52] Create new class for doing the Polynomial Tracing and returning the hit --- .../jsurf/rendering/cpu/PolynomialTracer.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/PolynomialTracer.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PolynomialTracer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PolynomialTracer.java new file mode 100644 index 0000000..bd8da7d --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PolynomialTracer.java @@ -0,0 +1,54 @@ +package de.mfo.jsurf.rendering.cpu; + +import java.util.List; + +import javax.vecmath.Vector2d; + +import de.mfo.jsurf.algebra.ColumnSubstitutor; +import de.mfo.jsurf.algebra.ColumnSubstitutorForGradient; +import de.mfo.jsurf.algebra.RealRootFinder; +import de.mfo.jsurf.algebra.UnivariatePolynomial; +import de.mfo.jsurf.rendering.cpu.clipping.Clipper; + +public class PolynomialTracer { + private final RealRootFinder realRootFinder; + private final RayCreator rayCreator; + private final Clipper rayClipper; + + public PolynomialTracer(DrawcallStaticData dcds) { + this.rayClipper = dcds.rayClipper; + this.rayCreator = dcds.rayCreator; + this.realRootFinder = dcds.realRootFinder; + } + + /** + * Returns the closest valid distance at which there was a hit. Double.NaN if no hit. + */ + public double findClosestHit( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs, double u, double v ) + { + Ray clippingRay = rayCreator.createClippingSpaceRay( u, v ); + + List< Vector2d > intervals = rayClipper.clipRay( clippingRay ); + if( !intervals.isEmpty() ) + { + UnivariatePolynomial surfacePoly = scs.setU( u ); + for( Vector2d interval : intervals ) + { + // adjust interval, so that it does not start before the eye point + double eyeLocation = rayCreator.getEyeLocationOnRay(); + if( interval.x < eyeLocation && eyeLocation < interval.y ) + interval.x = Math.max( interval.x, eyeLocation ); + + // intersect ray with surface and shade pixel + double hit = realRootFinder.findFirstRootIn( surfacePoly, interval.x, interval.y ); + Ray surfaceRay = rayCreator.createSurfaceSpaceRay( u, v ); + if( !java.lang.Double.isNaN( hit ) && rayClipper.clipPoint( surfaceRay.at( hit ), true ) ) + { + return hit; + } + } + } + return Double.NaN; + } + +} From 0c5e8c5bce57dd0d4a19b514b2b8e536587339b0 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:17:16 +0200 Subject: [PATCH 40/52] Move remaining shading code into the Pixel rendering classes --- .../jsurf/rendering/cpu/RenderingTask.java | 147 +++++++++--------- 1 file changed, 72 insertions(+), 75 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index d9b250f..3d1f014 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -122,17 +122,76 @@ public ColumnSubstitutorPair get(double v) { } private abstract class PixelRenderStrategy { + private final PolynomialTracer polyTracer; + private final RayCreator rayCreator; + private final Shader frontShader; + private final Shader backShader; + private final Color3f backgroundColor; + + protected final int[] colorBuffer; + + public PixelRenderStrategy(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { + this.polyTracer = polyTracer; + this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); + this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); + this.backgroundColor = dcsd.backgroundColor; + this.rayCreator = dcsd.rayCreator; + this.colorBuffer = dcsd.colorBuffer; + } + public abstract void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp); + + protected Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs, double u, double v ) + { + double hit = polyTracer.findClosestHit(scs, gcs, u, v); + + if (Double.isNaN(hit)) + return backgroundColor; + + UnivariatePolynomialVector3d gradientPolys = gcs.setU( u ); + Vector3d n_surfaceSpace = gradientPolys.setT( hit ); + Vector3d n_cameraSpace = rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); + + Ray ray = rayCreator.createCameraSpaceRay( u, v ); + return shade( ray, hit, n_cameraSpace ); + } + + /** + * Calculates the shading in camera space + */ + protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) + { + // normalize only if point is not singular + float nLength = (float) cameraSpaceNormal.length(); + if( nLength != 0.0f ) + cameraSpaceNormal.scale( 1.0f / nLength ); + + Vector3d view = new Vector3d(-ray.d.x, -ray.d.y, -ray.d.z); + // TODO: not normalizing the view does not seem to affect the rendered result, maybe it can be avoided + view.normalize(); + + Shader shader = frontShader; + if( cameraSpaceNormal.dot( view ) <= 0.0f ) { + shader = backShader; + cameraSpaceNormal.negate(); + } + + return shader.shade(ray.at(hit), view, cameraSpaceNormal); + } } private class AntiAliasedPixelRenderer extends PixelRenderStrategy { - private final Color3f[] internalColorBuffer; private final float thresholdSqr; + private final AntiAliasingPattern aap; + private final ColumnSubstitutorPairProvider cspProvider; - public AntiAliasedPixelRenderer(DrawcallStaticData cdsd, Color3f[] internalColorBuffer) { + public AntiAliasedPixelRenderer(DrawcallStaticData dcsd, Color3f[] internalColorBuffer, PolynomialTracer polyTracer, ColumnSubstitutorPairProvider cspProvider) { + super(dcsd, polyTracer); this.internalColorBuffer = internalColorBuffer; this.thresholdSqr = dcsd.antiAliasingThreshold * dcsd.antiAliasingThreshold; + this.aap = dcsd.antiAliasingPattern; + this.cspProvider = cspProvider; } @Override @@ -145,11 +204,11 @@ public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; - dcsd.colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( dcsd.antiAliasingPattern, ulColor, urColor, llColor, lrColor ).get().getRGB(); + colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( step, ulColor, urColor, llColor, lrColor ).get().getRGB(); } } - private Color3f antiAliasPixel( AntiAliasingPattern aap, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) + private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) { // first average pixel-corner colors Color3f finalColor; @@ -215,8 +274,12 @@ private float colorDiffSqr( Color3f c1, Color3f c2 ) } private class BasicPixelRenderer extends PixelRenderStrategy { + public BasicPixelRenderer(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { + super(dcsd, polyTracer); + } + @Override public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { - dcsd.colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); + colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); } } @@ -224,18 +287,16 @@ private class BasicPixelRenderer extends PixelRenderStrategy { // initialized by the constructor private final DrawcallStaticData dcsd; - private final Shader frontShader; - private final Shader backShader; private final PixelStep step; private final ColumnSubstitutorPairProvider cspProvider; + private final PolynomialTracer polyTracer; public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { this.dcsd = dcsd; this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); - this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); - this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); this.cspProvider = new ColumnSubstitutorPairProvider(dcsd); + this.polyTracer = new PolynomialTracer(dcsd); } public Boolean call() { @@ -244,9 +305,9 @@ public Boolean call() { PixelRenderStrategy pixelRenderer; if (useAntiAliasing()) { colorBuffer = bufferPool.getBuffer(step.width * step.height); - pixelRenderer = new AntiAliasedPixelRenderer(dcsd, colorBuffer); + pixelRenderer = new AntiAliasedPixelRenderer(dcsd, colorBuffer, polyTracer, cspProvider); } else { - pixelRenderer = new BasicPixelRenderer(); + pixelRenderer = new BasicPixelRenderer(dcsd, polyTracer); } renderImage(pixelRenderer); return true; @@ -280,70 +341,6 @@ private void renderImage(PixelRenderStrategy pixelRenderer) { step.stepV(); } } - - private Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs, double u, double v ) - { - // create rays - Ray ray = dcsd.rayCreator.createCameraSpaceRay( u, v ); - Ray clippingRay = dcsd.rayCreator.createClippingSpaceRay( u, v ); - Ray surfaceRay = dcsd.rayCreator.createSurfaceSpaceRay( u, v ); - - UnivariatePolynomialVector3d gradientPolys = null; - - // optimize rays and root-finder parameters - //optimizeRays( ray, clippingRay, surfaceRay ); - - // clip ray - List< Vector2d > intervals = dcsd.rayClipper.clipRay( clippingRay ); - if( !intervals.isEmpty() ) - { - UnivariatePolynomial surfacePoly = scs.setU( u ); - for( Vector2d interval : intervals ) - { - // adjust interval, so that it does not start before the eye point - double eyeLocation = dcsd.rayCreator.getEyeLocationOnRay(); - if( interval.x < eyeLocation && eyeLocation < interval.y ) - interval.x = Math.max( interval.x, eyeLocation ); - - // intersect ray with surface and shade pixel - double hit = dcsd.realRootFinder.findFirstRootIn( surfacePoly, interval.x, interval.y ); - if( !java.lang.Double.isNaN( hit ) && dcsd.rayClipper.clipPoint( surfaceRay.at( hit ), true ) ) - { - if( gradientPolys == null ) - gradientPolys = gcs.setU( u ); - - Vector3d n_surfaceSpace = gradientPolys.setT( hit ); - Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); - - return shade( ray, hit, n_cameraSpace ); - } - } - } - return dcsd.backgroundColor; - } - - /** - * Calculates the shading in camera space - */ - protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) - { - // normalize only if point is not singular - float nLength = (float) cameraSpaceNormal.length(); - if( nLength != 0.0f ) - cameraSpaceNormal.scale( 1.0f / nLength ); - - Vector3d view = new Vector3d(-ray.d.x, -ray.d.y, -ray.d.z); - // TODO: not normalizing the view does not seem to affect the rendered result, maybe it can be avoided - view.normalize(); - - Shader shader = frontShader; - if( cameraSpaceNormal.dot( view ) <= 0.0f ) { - shader = backShader; - cameraSpaceNormal.negate(); - } - - return shader.shade(ray.at(hit), view, cameraSpaceNormal); - } // private Color3f traceRay( double u, double v ) // { From f112b628f0acb2c27a3eb65a6279828c234b633a Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:24:40 +0200 Subject: [PATCH 41/52] Move Pixel render strategy classes to their own files --- .../cpu/AntiAliasedPixelRenderer.java | 102 ++++++++++ .../rendering/cpu/BasicPixelRenderer.java | 14 ++ .../rendering/cpu/DrawcallStaticData.java | 2 +- .../rendering/cpu/PixelRenderStrategy.java | 69 +++++++ .../jsurf/rendering/cpu/RenderingTask.java | 174 +----------------- 5 files changed, 192 insertions(+), 169 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java new file mode 100644 index 0000000..809a4bf --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -0,0 +1,102 @@ +package de.mfo.jsurf.rendering.cpu; + +import javax.vecmath.Color3f; +import javax.vecmath.Vector3f; + +import de.mfo.jsurf.rendering.RenderingInterruptedException; +import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPair; +import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPairProvider; +import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; + +class AntiAliasedPixelRenderer extends PixelRenderStrategy { + private final Color3f[] internalColorBuffer; + private final float thresholdSqr; + private final AntiAliasingPattern aap; + private final ColumnSubstitutorPairProvider cspProvider; + + public AntiAliasedPixelRenderer(DrawcallStaticData dcsd, Color3f[] internalColorBuffer, PolynomialTracer polyTracer, ColumnSubstitutorPairProvider cspProvider) { + super(dcsd, polyTracer); + this.internalColorBuffer = internalColorBuffer; + this.thresholdSqr = dcsd.antiAliasingThreshold * dcsd.antiAliasingThreshold; + this.aap = dcsd.antiAliasingPattern; + this.cspProvider = cspProvider; + } + + @Override + public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { + internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); + if( x > 0 && y > 0 ) + { + Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; + Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; + + colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( step, ulColor, urColor, llColor, lrColor ).get().getRGB(); + } + } + + private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) + { + // first average pixel-corner colors + Color3f finalColor; + + // adaptive supersampling + if( aap != AntiAliasingPattern.OG_2x2 && ( colorDiffSqr( ulColor, urColor ) >= thresholdSqr || + colorDiffSqr( ulColor, llColor ) >= thresholdSqr || + colorDiffSqr( ulColor, lrColor ) >= thresholdSqr || + colorDiffSqr( urColor, llColor ) >= thresholdSqr || + colorDiffSqr( urColor, lrColor ) >= thresholdSqr || + colorDiffSqr( llColor, lrColor ) >= thresholdSqr ) ) + { + // anti-alias pixel with advanced sampling pattern + finalColor = new Color3f(); + for( AntiAliasingPattern.SamplingPoint sp : aap ) + { + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); + + Color3f ss_color; + if( sp.getU() == 0.0 && sp.getV() == 0.0 ) + ss_color = llColor; + else if( sp.getU() == 0.0 && sp.getV() == 1.0 ) + ss_color = ulColor; + else if( sp.getU() == 1.0 && sp.getV() == 1.0 ) + ss_color = urColor; + else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) + ss_color = lrColor; + else + { + // color of this sample point is not known -> calculate + double v = step.vOld + sp.getV() * step.v_incr; + double u = step.uOld + sp.getU() * step.u_incr; + ColumnSubstitutorPair csp = cspProvider.get( v ); + ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); + } + finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); + + if( false ) + return new Color3f( 0, 0, 0 ); // paint pixels, that are supposed to be anti-aliased in black + } + } + else + { + finalColor = new Color3f( ulColor ); + finalColor.add( urColor ); + finalColor.add( llColor ); + finalColor.add( lrColor ); + finalColor.scale( 0.25f ); + } + + // clamp color, because floating point operations may yield values outside [0,1] + finalColor.clamp( 0f, 1f ); + return finalColor; + } + + private float colorDiffSqr( Color3f c1, Color3f c2 ) + { + Vector3f diff = new Vector3f( c1 ); + diff.sub( c2 ); + return diff.dot( diff ); + } +} \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java new file mode 100644 index 0000000..d93f00f --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java @@ -0,0 +1,14 @@ +package de.mfo.jsurf.rendering.cpu; + +import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPair; +import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; + +class BasicPixelRenderer extends PixelRenderStrategy { + public BasicPixelRenderer(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { + super(dcsd, polyTracer); + } + + @Override public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { + colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); + } +} \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/DrawcallStaticData.java b/src/main/java/de/mfo/jsurf/rendering/cpu/DrawcallStaticData.java index 18d7eb9..a3d6995 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/DrawcallStaticData.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/DrawcallStaticData.java @@ -22,7 +22,7 @@ import javax.vecmath.*; -class DrawcallStaticData +public class DrawcallStaticData { int[] colorBuffer; int width; diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java new file mode 100644 index 0000000..1343ae7 --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java @@ -0,0 +1,69 @@ +package de.mfo.jsurf.rendering.cpu; + +import javax.vecmath.Color3f; +import javax.vecmath.Vector3d; + +import de.mfo.jsurf.algebra.ColumnSubstitutor; +import de.mfo.jsurf.algebra.ColumnSubstitutorForGradient; +import de.mfo.jsurf.algebra.UnivariatePolynomialVector3d; +import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPair; +import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; + +public abstract class PixelRenderStrategy { + private final PolynomialTracer polyTracer; + private final RayCreator rayCreator; + private final Shader frontShader; + private final Shader backShader; + private final Color3f backgroundColor; + + protected final int[] colorBuffer; + + public PixelRenderStrategy(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { + this.polyTracer = polyTracer; + this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); + this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); + this.backgroundColor = dcsd.backgroundColor; + this.rayCreator = dcsd.rayCreator; + this.colorBuffer = dcsd.colorBuffer; + } + + public abstract void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp); + + protected Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs, double u, double v ) + { + double hit = polyTracer.findClosestHit(scs, gcs, u, v); + + if (Double.isNaN(hit)) + return backgroundColor; + + UnivariatePolynomialVector3d gradientPolys = gcs.setU( u ); + Vector3d n_surfaceSpace = gradientPolys.setT( hit ); + Vector3d n_cameraSpace = rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); + + Ray ray = rayCreator.createCameraSpaceRay( u, v ); + return shade( ray, hit, n_cameraSpace ); + } + + /** + * Calculates the shading in camera space + */ + protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) + { + // normalize only if point is not singular + float nLength = (float) cameraSpaceNormal.length(); + if( nLength != 0.0f ) + cameraSpaceNormal.scale( 1.0f / nLength ); + + Vector3d view = new Vector3d(-ray.d.x, -ray.d.y, -ray.d.z); + // TODO: not normalizing the view does not seem to affect the rendered result, maybe it can be avoided + view.normalize(); + + Shader shader = frontShader; + if( cameraSpaceNormal.dot( view ) <= 0.0f ) { + shader = backShader; + cameraSpaceNormal.negate(); + } + + return shader.shade(ray.at(hit), view, cameraSpaceNormal); + } +} \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 3d1f014..43b7585 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -28,11 +28,11 @@ public class RenderingTask implements Callable /** * Holds information needed for stepping through the pixels in the image */ - private static class PixelStep { + static class PixelStep { private final double u_start; private final double v_start; - private final double u_incr; - private final double v_incr; + final double u_incr; + final double v_incr; public final int width; public final int height; @@ -88,7 +88,7 @@ public void stepV() { } } - private static class ColumnSubstitutorPair + static class ColumnSubstitutorPair { public final ColumnSubstitutor scs; public final ColumnSubstitutorForGradient gcs; @@ -100,7 +100,7 @@ private static class ColumnSubstitutorPair } } - private static class ColumnSubstitutorPairProvider { + static class ColumnSubstitutorPairProvider { private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; private final RowSubstitutor surfaceRowSubstitutor; private final RowSubstitutorForGradient gradientRowSubstitutor; @@ -121,169 +121,7 @@ public ColumnSubstitutorPair get(double v) { } } - private abstract class PixelRenderStrategy { - private final PolynomialTracer polyTracer; - private final RayCreator rayCreator; - private final Shader frontShader; - private final Shader backShader; - private final Color3f backgroundColor; - - protected final int[] colorBuffer; - - public PixelRenderStrategy(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { - this.polyTracer = polyTracer; - this.frontShader = new Shader(dcsd.frontAmbientColor, dcsd.lightSources, dcsd.frontLightProducts); - this.backShader = new Shader(dcsd.backAmbientColor, dcsd.lightSources, dcsd.backLightProducts); - this.backgroundColor = dcsd.backgroundColor; - this.rayCreator = dcsd.rayCreator; - this.colorBuffer = dcsd.colorBuffer; - } - - public abstract void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp); - - protected Color3f tracePolynomial( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs, double u, double v ) - { - double hit = polyTracer.findClosestHit(scs, gcs, u, v); - - if (Double.isNaN(hit)) - return backgroundColor; - - UnivariatePolynomialVector3d gradientPolys = gcs.setU( u ); - Vector3d n_surfaceSpace = gradientPolys.setT( hit ); - Vector3d n_cameraSpace = rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); - - Ray ray = rayCreator.createCameraSpaceRay( u, v ); - return shade( ray, hit, n_cameraSpace ); - } - - /** - * Calculates the shading in camera space - */ - protected Color3f shade( Ray ray, double hit, Vector3d cameraSpaceNormal ) - { - // normalize only if point is not singular - float nLength = (float) cameraSpaceNormal.length(); - if( nLength != 0.0f ) - cameraSpaceNormal.scale( 1.0f / nLength ); - - Vector3d view = new Vector3d(-ray.d.x, -ray.d.y, -ray.d.z); - // TODO: not normalizing the view does not seem to affect the rendered result, maybe it can be avoided - view.normalize(); - - Shader shader = frontShader; - if( cameraSpaceNormal.dot( view ) <= 0.0f ) { - shader = backShader; - cameraSpaceNormal.negate(); - } - - return shader.shade(ray.at(hit), view, cameraSpaceNormal); - } - } - - private class AntiAliasedPixelRenderer extends PixelRenderStrategy { - private final Color3f[] internalColorBuffer; - private final float thresholdSqr; - private final AntiAliasingPattern aap; - private final ColumnSubstitutorPairProvider cspProvider; - - public AntiAliasedPixelRenderer(DrawcallStaticData dcsd, Color3f[] internalColorBuffer, PolynomialTracer polyTracer, ColumnSubstitutorPairProvider cspProvider) { - super(dcsd, polyTracer); - this.internalColorBuffer = internalColorBuffer; - this.thresholdSqr = dcsd.antiAliasingThreshold * dcsd.antiAliasingThreshold; - this.aap = dcsd.antiAliasingPattern; - this.cspProvider = cspProvider; - } - - @Override - public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { - internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); - if( x > 0 && y > 0 ) - { - Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; - Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; - Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; - - colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( step, ulColor, urColor, llColor, lrColor ).get().getRGB(); - } - } - - private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) - { - // first average pixel-corner colors - Color3f finalColor; - - // adaptive supersampling - if( aap != AntiAliasingPattern.OG_2x2 && ( colorDiffSqr( ulColor, urColor ) >= thresholdSqr || - colorDiffSqr( ulColor, llColor ) >= thresholdSqr || - colorDiffSqr( ulColor, lrColor ) >= thresholdSqr || - colorDiffSqr( urColor, llColor ) >= thresholdSqr || - colorDiffSqr( urColor, lrColor ) >= thresholdSqr || - colorDiffSqr( llColor, lrColor ) >= thresholdSqr ) ) - { - // anti-alias pixel with advanced sampling pattern - finalColor = new Color3f(); - for( AntiAliasingPattern.SamplingPoint sp : aap ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); - - Color3f ss_color; - if( sp.getU() == 0.0 && sp.getV() == 0.0 ) - ss_color = llColor; - else if( sp.getU() == 0.0 && sp.getV() == 1.0 ) - ss_color = ulColor; - else if( sp.getU() == 1.0 && sp.getV() == 1.0 ) - ss_color = urColor; - else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) - ss_color = lrColor; - else - { - // color of this sample point is not known -> calculate - double v = step.vOld + sp.getV() * step.v_incr; - double u = step.uOld + sp.getU() * step.u_incr; - ColumnSubstitutorPair csp = cspProvider.get( v ); - ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); - } - finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); - - if( false ) - return new Color3f( 0, 0, 0 ); // paint pixels, that are supposed to be anti-aliased in black - } - } - else - { - finalColor = new Color3f( ulColor ); - finalColor.add( urColor ); - finalColor.add( llColor ); - finalColor.add( lrColor ); - finalColor.scale( 0.25f ); - } - - // clamp color, because floating point operations may yield values outside [0,1] - finalColor.clamp( 0f, 1f ); - return finalColor; - } - - private float colorDiffSqr( Color3f c1, Color3f c2 ) - { - Vector3f diff = new Vector3f( c1 ); - diff.sub( c2 ); - return diff.dot( diff ); - } - } - - private class BasicPixelRenderer extends PixelRenderStrategy { - public BasicPixelRenderer(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { - super(dcsd, polyTracer); - } - - @Override public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { - colorBuffer[ step.colorBufferIndex ] = tracePolynomial(csp.scs, csp.gcs, step.u, step.v ).get().getRGB(); - } - } - - static ColorBufferPool bufferPool = new ColorBufferPool(); + static ColorBufferPool bufferPool = new ColorBufferPool(); // initialized by the constructor private final DrawcallStaticData dcsd; From ba1c8891a0392e88fcc45f33634b2ba991cd2c1f Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:26:55 +0200 Subject: [PATCH 42/52] Move ColumnSubstitutorPair and provider classes to their own files --- .../cpu/AntiAliasedPixelRenderer.java | 2 -- .../rendering/cpu/BasicPixelRenderer.java | 1 - .../rendering/cpu/ColumnSubstitutorPair.java | 16 +++++++++ .../cpu/ColumnSubstitutorPairProvider.java | 27 +++++++++++++++ .../rendering/cpu/PixelRenderStrategy.java | 1 - .../jsurf/rendering/cpu/RenderingTask.java | 34 ------------------- 6 files changed, 43 insertions(+), 38 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPair.java create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 809a4bf..36c8195 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -4,8 +4,6 @@ import javax.vecmath.Vector3f; import de.mfo.jsurf.rendering.RenderingInterruptedException; -import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPair; -import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPairProvider; import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; class AntiAliasedPixelRenderer extends PixelRenderStrategy { diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java index d93f00f..aa63db3 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java @@ -1,6 +1,5 @@ package de.mfo.jsurf.rendering.cpu; -import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPair; import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; class BasicPixelRenderer extends PixelRenderStrategy { diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPair.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPair.java new file mode 100644 index 0000000..f96524d --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPair.java @@ -0,0 +1,16 @@ +package de.mfo.jsurf.rendering.cpu; + +import de.mfo.jsurf.algebra.ColumnSubstitutor; +import de.mfo.jsurf.algebra.ColumnSubstitutorForGradient; + +class ColumnSubstitutorPair +{ + public final ColumnSubstitutor scs; + public final ColumnSubstitutorForGradient gcs; + + ColumnSubstitutorPair( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs ) + { + this.scs = scs; + this.gcs = gcs; + } +} \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java new file mode 100644 index 0000000..28d51b2 --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java @@ -0,0 +1,27 @@ +package de.mfo.jsurf.rendering.cpu; + +import java.util.HashMap; + +import de.mfo.jsurf.algebra.RowSubstitutor; +import de.mfo.jsurf.algebra.RowSubstitutorForGradient; + +class ColumnSubstitutorPairProvider { + private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; + private final RowSubstitutor surfaceRowSubstitutor; + private final RowSubstitutorForGradient gradientRowSubstitutor; + + public ColumnSubstitutorPairProvider(DrawcallStaticData dcsd) { + this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + this.surfaceRowSubstitutor = dcsd.surfaceRowSubstitutor; + this.gradientRowSubstitutor = dcsd.gradientRowSubstitutor; + } + + public ColumnSubstitutorPair get(double v) { + ColumnSubstitutorPair csp = csp_hm.get(v); + if (csp == null) { + csp = new ColumnSubstitutorPair(surfaceRowSubstitutor.setV( v ), gradientRowSubstitutor.setV( v )); + csp_hm.put(v, csp); + } + return csp; + } +} \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java index 1343ae7..9eba918 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java @@ -6,7 +6,6 @@ import de.mfo.jsurf.algebra.ColumnSubstitutor; import de.mfo.jsurf.algebra.ColumnSubstitutorForGradient; import de.mfo.jsurf.algebra.UnivariatePolynomialVector3d; -import de.mfo.jsurf.rendering.cpu.RenderingTask.ColumnSubstitutorPair; import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; public abstract class PixelRenderStrategy { diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 43b7585..17c9f5d 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -21,7 +21,6 @@ import javax.vecmath.*; import java.util.concurrent.*; -import java.util.*; public class RenderingTask implements Callable { @@ -88,39 +87,6 @@ public void stepV() { } } - static class ColumnSubstitutorPair - { - public final ColumnSubstitutor scs; - public final ColumnSubstitutorForGradient gcs; - - ColumnSubstitutorPair( ColumnSubstitutor scs, ColumnSubstitutorForGradient gcs ) - { - this.scs = scs; - this.gcs = gcs; - } - } - - static class ColumnSubstitutorPairProvider { - private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; - private final RowSubstitutor surfaceRowSubstitutor; - private final RowSubstitutorForGradient gradientRowSubstitutor; - - public ColumnSubstitutorPairProvider(DrawcallStaticData dcsd) { - this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); - this.surfaceRowSubstitutor = dcsd.surfaceRowSubstitutor; - this.gradientRowSubstitutor = dcsd.gradientRowSubstitutor; - } - - public ColumnSubstitutorPair get(double v) { - ColumnSubstitutorPair csp = csp_hm.get(v); - if (csp == null) { - csp = new ColumnSubstitutorPair(surfaceRowSubstitutor.setV( v ), gradientRowSubstitutor.setV( v )); - csp_hm.put(v, csp); - } - return csp; - } - } - static ColorBufferPool bufferPool = new ColorBufferPool(); // initialized by the constructor From ce0031f4aa07f9ae742e63c8e8a9d5a99904dac4 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:28:13 +0200 Subject: [PATCH 43/52] Move PixelStep class to its own file --- .../cpu/AntiAliasedPixelRenderer.java | 1 - .../rendering/cpu/BasicPixelRenderer.java | 2 - .../rendering/cpu/PixelRenderStrategy.java | 1 - .../de/mfo/jsurf/rendering/cpu/PixelStep.java | 66 +++++++++++++++++++ .../jsurf/rendering/cpu/RenderingTask.java | 63 ------------------ 5 files changed, 66 insertions(+), 67 deletions(-) create mode 100644 src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 36c8195..23abab4 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -4,7 +4,6 @@ import javax.vecmath.Vector3f; import de.mfo.jsurf.rendering.RenderingInterruptedException; -import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; class AntiAliasedPixelRenderer extends PixelRenderStrategy { private final Color3f[] internalColorBuffer; diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java index aa63db3..c5ce6bc 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java @@ -1,7 +1,5 @@ package de.mfo.jsurf.rendering.cpu; -import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; - class BasicPixelRenderer extends PixelRenderStrategy { public BasicPixelRenderer(DrawcallStaticData dcsd, PolynomialTracer polyTracer) { super(dcsd, polyTracer); diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java index 9eba918..60e43fe 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelRenderStrategy.java @@ -6,7 +6,6 @@ import de.mfo.jsurf.algebra.ColumnSubstitutor; import de.mfo.jsurf.algebra.ColumnSubstitutorForGradient; import de.mfo.jsurf.algebra.UnivariatePolynomialVector3d; -import de.mfo.jsurf.rendering.cpu.RenderingTask.PixelStep; public abstract class PixelRenderStrategy { private final PolynomialTracer polyTracer; diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java new file mode 100644 index 0000000..219353b --- /dev/null +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java @@ -0,0 +1,66 @@ +package de.mfo.jsurf.rendering.cpu; + +import javax.vecmath.Vector2d; + +/** + * Holds information needed for stepping through the pixels in the image + */ +class PixelStep { + private final double u_start; + private final double v_start; + final double u_incr; + final double v_incr; + + public final int width; + public final int height; + + public double v; + public double u; + public double vOld; + public double uOld; + + public int internalBufferIndex; + public int colorBufferIndex; + private final int colorBufferVStep; + + public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int width, int height) { + RayCreator rayCreator = dcsd.rayCreator; + Vector2d uInterval = rayCreator.getUInterval(); + Vector2d vInterval = rayCreator.getVInterval(); + double displace = (dcsd.antiAliasingPattern == AntiAliasingPattern.OG_1x1) ? 0 : 0.5; + this.u_start = rayCreator.transformU( ( xStart - displace ) / ( dcsd.width - 1.0 ) ); + this.v_start = rayCreator.transformV( ( yStart - displace ) / ( dcsd.height - 1.0 ) ); + this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); + this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); + + this.width = width; + this.height = height; + this.colorBufferIndex = (yStart - 1) * dcsd.width + xStart - 1; + this.colorBufferVStep = dcsd.width - width; + reset(); + } + + private void reset() { + vOld = 0; + v = v_start; + + uOld = 0; + u = u_start; + } + + public void stepU() { + uOld = u; + u += u_incr; + colorBufferIndex++; + internalBufferIndex++; + } + + public void stepV() { + vOld = v; + v += v_incr; + + uOld = 0; + u = u_start; + colorBufferIndex += colorBufferVStep; + } +} \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 17c9f5d..80e6bc9 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -24,69 +24,6 @@ public class RenderingTask implements Callable { - /** - * Holds information needed for stepping through the pixels in the image - */ - static class PixelStep { - private final double u_start; - private final double v_start; - final double u_incr; - final double v_incr; - - public final int width; - public final int height; - - public double v; - public double u; - public double vOld; - public double uOld; - - public int internalBufferIndex; - public int colorBufferIndex; - private final int colorBufferVStep; - - public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int width, int height) { - RayCreator rayCreator = dcsd.rayCreator; - Vector2d uInterval = rayCreator.getUInterval(); - Vector2d vInterval = rayCreator.getVInterval(); - double displace = (dcsd.antiAliasingPattern == AntiAliasingPattern.OG_1x1) ? 0 : 0.5; - this.u_start = rayCreator.transformU( ( xStart - displace ) / ( dcsd.width - 1.0 ) ); - this.v_start = rayCreator.transformV( ( yStart - displace ) / ( dcsd.height - 1.0 ) ); - this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); - this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); - - this.width = width; - this.height = height; - this.colorBufferIndex = (yStart - 1) * dcsd.width + xStart - 1; - this.colorBufferVStep = dcsd.width - width; - reset(); - } - - private void reset() { - vOld = 0; - v = v_start; - - uOld = 0; - u = u_start; - } - - public void stepU() { - uOld = u; - u += u_incr; - colorBufferIndex++; - internalBufferIndex++; - } - - public void stepV() { - vOld = v; - v += v_incr; - - uOld = 0; - u = u_start; - colorBufferIndex += colorBufferVStep; - } - } - static ColorBufferPool bufferPool = new ColorBufferPool(); // initialized by the constructor From 5f850fbc634bde5cf3eb856a67220925ada3fb7f Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:31:11 +0200 Subject: [PATCH 44/52] Clean up file Remove unused and commented out code, replace .* imports with just the needed ones. --- .../jsurf/rendering/cpu/RenderingTask.java | 87 +------------------ 1 file changed, 3 insertions(+), 84 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 80e6bc9..241f616 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -16,11 +16,10 @@ package de.mfo.jsurf.rendering.cpu; -import de.mfo.jsurf.algebra.*; -import de.mfo.jsurf.rendering.*; +import java.util.concurrent.Callable; +import javax.vecmath.Color3f; -import javax.vecmath.*; -import java.util.concurrent.*; +import de.mfo.jsurf.rendering.RenderingInterruptedException; public class RenderingTask implements Callable { @@ -82,84 +81,4 @@ private void renderImage(PixelRenderStrategy pixelRenderer) { step.stepV(); } } - -// private Color3f traceRay( double u, double v ) -// { -// // create rays -// Ray ray = dcsd.rayCreator.createCameraSpaceRay( u, v ); -// Ray clippingRay = dcsd.rayCreator.createClippingSpaceRay( u, v ); -// Ray surfaceRay = dcsd.rayCreator.createSurfaceSpaceRay( u, v ); -// -// Point3d eye = Helper.interpolate1D( ray.o, ray.d, dcsd.rayCreator.getEyeLocationOnRay() ); -// UnivariatePolynomialVector3d gradientPolys = null; -// -// // optimize rays and root-finder parameters -// //optimizeRays( ray, clippingRay, surfaceRay ); -// -// //System.out.println( u + "," + v + ":("+surfaceRay.o.x+","+surfaceRay.o.y+","+surfaceRay.o.z+")"+"("+surfaceRay.d.x+","+surfaceRay.d.y+","+surfaceRay.d.z+")t" ); -// -// // clip ray -// List< Vector2d > intervals = dcsd.rayClipper.clipRay( clippingRay ); -// for( Vector2d interval : intervals ) -// { -// // adjust interval, so that it does not start before the eye point -// double eyeLocation = dcsd.rayCreator.getEyeLocationOnRay(); -// -// if( interval.x < eyeLocation && eyeLocation < interval.y ) -// interval.x = Math.max( interval.x, eyeLocation ); -// -// // intersect ray with surface and shade pixel -// double[] hit = new double[ 1 ]; -// if( intersect( surfaceRay, interval.x, interval.y, hit ) ) -// if( dcsd.rayClipper.clipPoint( surfaceRay.at( hit[ 0 ] ), true ) ) -// { -// if( gradientPolys == null ) -// gradientPolys = gcs.setU( u ); -// Vector3d n_surfaceSpace = gradientPolys.setT( hit ); -// Vector3d n_cameraSpace = dcsd.rayCreator.surfaceSpaceNormalToCameraSpaceNormal( n_surfaceSpace ); -// -// return shade( ray.at( hit ), n_cameraSpace, eye ); -// } -// return shade( ray, surfaceRay, hit[ 0 ], eye ); -// } -// return dcsd.backgroundColor; -// } - - protected boolean intersectPolynomial( UnivariatePolynomial p, double rayStart, double rayEnd, double[] hit ) - { - //System.out.println( p ); - hit[ 0 ] = dcsd.realRootFinder.findFirstRootIn( p, rayStart, rayEnd ); - return !java.lang.Double.isNaN( hit[ 0 ] ); - } - - protected boolean intersect( Ray r, double rayStart, double rayEnd, double[] hit ) - { - UnivariatePolynomial x = new UnivariatePolynomial( r.o.x, r.d.x ); - UnivariatePolynomial y = new UnivariatePolynomial( r.o.y, r.d.y ); - UnivariatePolynomial z = new UnivariatePolynomial( r.o.z, r.d.z ); - - UnivariatePolynomial p = dcsd.coefficientCalculator.calculateCoefficients( x, y, z ); - p = p.shrink(); - - hit[ 0 ] = ( float ) dcsd.realRootFinder.findFirstRootIn( p, rayStart, rayEnd ); - return !java.lang.Double.isNaN( hit[ 0 ] ); - } - - boolean blowUpChooseMaterial( Point3d p ) - { - double R; - if( dcsd.rayClipper instanceof de.mfo.jsurf.rendering.cpu.clipping.ClipBlowUpSurface ) - R = ( ( de.mfo.jsurf.rendering.cpu.clipping.ClipBlowUpSurface ) dcsd.rayClipper ).get_R(); - else - R = 1.0; - - double u = p.x; - double tmp = Math.sqrt( p.y*p.y + p.z*p.z ); - double v = R + tmp; - double dist = u * u + v * v; - if( dist > 1.0 ) - v = R - tmp; // choose the solution inside the disc - return ( 3.0 * dist ) % 2.0 < 1.0; - } - } From d3d41129ad1559eca63c93fa25fa16769ce73bdf Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:45:45 +0200 Subject: [PATCH 45/52] Move calculation of width and height into PixelStep --- src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java | 6 +++--- src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java index 219353b..47827c0 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java @@ -23,7 +23,7 @@ class PixelStep { public int colorBufferIndex; private final int colorBufferVStep; - public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int width, int height) { + public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd) { RayCreator rayCreator = dcsd.rayCreator; Vector2d uInterval = rayCreator.getUInterval(); Vector2d vInterval = rayCreator.getVInterval(); @@ -33,8 +33,8 @@ public PixelStep(DrawcallStaticData dcsd, int xStart, int yStart, int width, int this.u_incr = ( uInterval.y - uInterval.x ) / ( dcsd.width - 1.0 ); this.v_incr = ( vInterval.y - vInterval.x ) / ( dcsd.height - 1.0 ); - this.width = width; - this.height = height; + this.width = xEnd - xStart + 2; + this.height = yEnd - yStart + 2; this.colorBufferIndex = (yStart - 1) * dcsd.width + xStart - 1; this.colorBufferVStep = dcsd.width - width; reset(); diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index 241f616..c2d6676 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -34,7 +34,7 @@ public class RenderingTask implements Callable public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, int yEnd ) { this.dcsd = dcsd; - this.step = new PixelStep(dcsd, xStart, yStart, xEnd - xStart + 2, yEnd - yStart + 2); + this.step = new PixelStep(dcsd, xStart, yStart, xEnd, yEnd); this.cspProvider = new ColumnSubstitutorPairProvider(dcsd); this.polyTracer = new PolynomialTracer(dcsd); } From d6628176fa91451e2cd87578a65336c71ca52bc9 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:46:22 +0200 Subject: [PATCH 46/52] Remove dead code --- .../de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 23abab4..734d0d3 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -71,9 +71,6 @@ else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); } finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); - - if( false ) - return new Color3f( 0, 0, 0 ); // paint pixels, that are supposed to be anti-aliased in black } } else From 61c91937784fac58744f2b70686c0bb975d111f0 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:48:50 +0200 Subject: [PATCH 47/52] Replace method access with final public fields in SamplingPoint --- .../rendering/cpu/AntiAliasedPixelRenderer.java | 14 +++++++------- .../jsurf/rendering/cpu/AntiAliasingPattern.java | 8 +++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 734d0d3..ea6240f 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -54,23 +54,23 @@ private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor throw new RenderingInterruptedException(); Color3f ss_color; - if( sp.getU() == 0.0 && sp.getV() == 0.0 ) + if( sp.u == 0.0 && sp.v == 0.0 ) ss_color = llColor; - else if( sp.getU() == 0.0 && sp.getV() == 1.0 ) + else if( sp.u == 0.0 && sp.v == 1.0 ) ss_color = ulColor; - else if( sp.getU() == 1.0 && sp.getV() == 1.0 ) + else if( sp.u == 1.0 && sp.v == 1.0 ) ss_color = urColor; - else if( sp.getU() == 1.0 && sp.getV() == 0.0 ) + else if( sp.u == 1.0 && sp.v == 0.0 ) ss_color = lrColor; else { // color of this sample point is not known -> calculate - double v = step.vOld + sp.getV() * step.v_incr; - double u = step.uOld + sp.getU() * step.u_incr; + double v = step.vOld + sp.v * step.v_incr; + double u = step.uOld + sp.u * step.u_incr; ColumnSubstitutorPair csp = cspProvider.get( v ); ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); } - finalColor.scaleAdd( sp.getWeight(), ss_color, finalColor ); + finalColor.scaleAdd( sp.weight, ss_color, finalColor ); } } else diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java index 21a47e8..288888e 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java @@ -36,7 +36,9 @@ public enum AntiAliasingPattern implements Iterable< AntiAliasingPattern.Samplin public static class SamplingPoint { - private float u, v, weight; + public final float u; + public final float v; + public final float weight; private SamplingPoint( float u, float v, float weight ) { @@ -44,10 +46,6 @@ private SamplingPoint( float u, float v, float weight ) this.v = v; this.weight = weight; } - - public float getU() { return u;} - public float getV() { return v; } - public float getWeight() { return weight; } } private class SamplingPointIterator implements Iterator< SamplingPoint > From 1f5375eefb694489ba1cf29d10a1d7bf44b37d86 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 14:57:06 +0200 Subject: [PATCH 48/52] Refactor threshold evaluating function A small optimization to avoid creating a new vector and two vector class function calls every time the similarity of colors is evaluated. --- .../cpu/AntiAliasedPixelRenderer.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index ea6240f..4c4c896 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -1,7 +1,6 @@ package de.mfo.jsurf.rendering.cpu; import javax.vecmath.Color3f; -import javax.vecmath.Vector3f; import de.mfo.jsurf.rendering.RenderingInterruptedException; @@ -39,12 +38,13 @@ private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor Color3f finalColor; // adaptive supersampling - if( aap != AntiAliasingPattern.OG_2x2 && ( colorDiffSqr( ulColor, urColor ) >= thresholdSqr || - colorDiffSqr( ulColor, llColor ) >= thresholdSqr || - colorDiffSqr( ulColor, lrColor ) >= thresholdSqr || - colorDiffSqr( urColor, llColor ) >= thresholdSqr || - colorDiffSqr( urColor, lrColor ) >= thresholdSqr || - colorDiffSqr( llColor, lrColor ) >= thresholdSqr ) ) + if( aap != AntiAliasingPattern.OG_2x2 && + ( !areWithinThreshold( ulColor, urColor ) || + !areWithinThreshold( ulColor, llColor ) || + !areWithinThreshold( ulColor, lrColor ) || + !areWithinThreshold( urColor, llColor ) || + !areWithinThreshold( urColor, lrColor ) || + !areWithinThreshold( llColor, lrColor ) ) ) { // anti-alias pixel with advanced sampling pattern finalColor = new Color3f(); @@ -86,11 +86,11 @@ else if( sp.u == 1.0 && sp.v == 0.0 ) finalColor.clamp( 0f, 1f ); return finalColor; } - - private float colorDiffSqr( Color3f c1, Color3f c2 ) - { - Vector3f diff = new Vector3f( c1 ); - diff.sub( c2 ); - return diff.dot( diff ); + + private boolean areWithinThreshold(Color3f c1, Color3f c2) { + float x = c1.x - c2.x; + float y = c1.y - c2.y; + float z = c1.z - c2.z; + return (x * x) + (y * y) + (z * z) < thresholdSqr; } } \ No newline at end of file From 3a941814414f628121def38f02e4b5af74c0784c Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 15:57:02 +0200 Subject: [PATCH 49/52] Simplify super sampling code Avoid doing too many conditions inside the tightest loop. Instead, pre-calculate always the corner rays and then skip them when iterating over the SamplingPoints. --- .../cpu/AntiAliasedPixelRenderer.java | 71 ++++++++----------- .../rendering/cpu/AntiAliasingPattern.java | 17 ++++- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 4c4c896..8577760 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -34,63 +34,50 @@ public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) { - // first average pixel-corner colors - Color3f finalColor; + boolean doSuperSampling = + aap != AntiAliasingPattern.OG_2x2 && + (areTooDifferent( ulColor, urColor ) || + areTooDifferent( ulColor, llColor ) || + areTooDifferent( ulColor, lrColor ) || + areTooDifferent( urColor, llColor ) || + areTooDifferent( urColor, lrColor ) || + areTooDifferent( llColor, lrColor )); - // adaptive supersampling - if( aap != AntiAliasingPattern.OG_2x2 && - ( !areWithinThreshold( ulColor, urColor ) || - !areWithinThreshold( ulColor, llColor ) || - !areWithinThreshold( ulColor, lrColor ) || - !areWithinThreshold( urColor, llColor ) || - !areWithinThreshold( urColor, lrColor ) || - !areWithinThreshold( llColor, lrColor ) ) ) + // first average pixel-corner colors. Weight depends on whether more samples will be taken + Color3f accumulator = new Color3f( ulColor ); + accumulator.add( urColor ); + accumulator.add( llColor ); + accumulator.add( lrColor ); + accumulator.scale( doSuperSampling ? aap.cornerWeight : 0.25f); + + if (doSuperSampling) { - // anti-alias pixel with advanced sampling pattern - finalColor = new Color3f(); for( AntiAliasingPattern.SamplingPoint sp : aap ) { if( Thread.currentThread().isInterrupted() ) throw new RenderingInterruptedException(); - Color3f ss_color; - if( sp.u == 0.0 && sp.v == 0.0 ) - ss_color = llColor; - else if( sp.u == 0.0 && sp.v == 1.0 ) - ss_color = ulColor; - else if( sp.u == 1.0 && sp.v == 1.0 ) - ss_color = urColor; - else if( sp.u == 1.0 && sp.v == 0.0 ) - ss_color = lrColor; - else - { - // color of this sample point is not known -> calculate - double v = step.vOld + sp.v * step.v_incr; - double u = step.uOld + sp.u * step.u_incr; - ColumnSubstitutorPair csp = cspProvider.get( v ); - ss_color = tracePolynomial( csp.scs, csp.gcs, u, v ); - } - finalColor.scaleAdd( sp.weight, ss_color, finalColor ); + // corners already accumulated above + if (sp.isCorner) + continue; + + double v = step.vOld + sp.v * step.v_incr; + double u = step.uOld + sp.u * step.u_incr; + ColumnSubstitutorPair csp = cspProvider.get( v ); + Color3f sample = tracePolynomial( csp.scs, csp.gcs, u, v ); + accumulator.scaleAdd( sp.weight, sample, accumulator ); } } - else - { - finalColor = new Color3f( ulColor ); - finalColor.add( urColor ); - finalColor.add( llColor ); - finalColor.add( lrColor ); - finalColor.scale( 0.25f ); - } // clamp color, because floating point operations may yield values outside [0,1] - finalColor.clamp( 0f, 1f ); - return finalColor; + accumulator.clamp( 0f, 1f ); + return accumulator; } - private boolean areWithinThreshold(Color3f c1, Color3f c2) { + private boolean areTooDifferent(Color3f c1, Color3f c2) { float x = c1.x - c2.x; float y = c1.y - c2.y; float z = c1.z - c2.z; - return (x * x) + (y * y) + (z * z) < thresholdSqr; + return (x * x) + (y * y) + (z * z) >= thresholdSqr; } } \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java index 288888e..1148f14 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java @@ -33,18 +33,22 @@ public enum AntiAliasingPattern implements Iterable< AntiAliasingPattern.Samplin QUINCUNX( getQuincunxPattern() ); private final SamplingPoint[] points; + + public final float cornerWeight; public static class SamplingPoint { public final float u; public final float v; public final float weight; + public final boolean isCorner; private SamplingPoint( float u, float v, float weight ) { this.u = u; this.v = v; this.weight = weight; + this.isCorner = (u == 0.0 || u == 1.0) && (v == 0.0 || v == 1.0); } } @@ -84,7 +88,18 @@ public void remove() } } - private AntiAliasingPattern( SamplingPoint[] points ) { this.points = points; } + private AntiAliasingPattern( SamplingPoint[] points ) { + this.points = points; + this.cornerWeight = findFirstCorner().weight; + } + + SamplingPoint findFirstCorner() { + for (SamplingPoint sp : points) + if (sp.isCorner) + return sp; + return points[0]; + } + public Iterator< SamplingPoint > iterator() { return new SamplingPointIterator( this.points ); } private static SamplingPoint[] getOGSSPattern( int size ) From c4c23c6381e4d11ddc72463843489a9b6fda27e9 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 16:01:50 +0200 Subject: [PATCH 50/52] Avoid checking similarity of corner pixels when supersampling is forced --- .../de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 8577760..42c8810 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -36,7 +36,8 @@ private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor { boolean doSuperSampling = aap != AntiAliasingPattern.OG_2x2 && - (areTooDifferent( ulColor, urColor ) || + (thresholdSqr == 0 || + areTooDifferent( ulColor, urColor ) || areTooDifferent( ulColor, llColor ) || areTooDifferent( ulColor, lrColor ) || areTooDifferent( urColor, llColor ) || From 2e8b2f832935fd37841917efa7c73d41c86d8937 Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sat, 9 Jun 2018 16:16:02 +0200 Subject: [PATCH 51/52] Move all corner point related calculation outside of the super sampling function --- .../cpu/AntiAliasedPixelRenderer.java | 60 +++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java index 42c8810..7eec5da 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasedPixelRenderer.java @@ -21,19 +21,14 @@ public AntiAliasedPixelRenderer(DrawcallStaticData dcsd, Color3f[] internalColor @Override public void renderPixel(int x, int y, PixelStep step, ColumnSubstitutorPair csp) { internalColorBuffer[ step.internalBufferIndex ] = tracePolynomial( csp.scs, csp.gcs, step.u, step.v ); - if( x > 0 && y > 0 ) - { - Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; - Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; - Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; - Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; + if( x == 0 || y == 0 ) + return; + + Color3f urColor = internalColorBuffer[ step.internalBufferIndex ]; + Color3f ulColor = internalColorBuffer[ step.internalBufferIndex - 1 ]; + Color3f lrColor = internalColorBuffer[ step.internalBufferIndex - step.width ]; + Color3f llColor = internalColorBuffer[ step.internalBufferIndex - step.width - 1 ]; - colorBuffer[ step.colorBufferIndex ] = antiAliasPixel( step, ulColor, urColor, llColor, lrColor ).get().getRGB(); - } - } - - private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor, Color3f llColor, Color3f lrColor ) - { boolean doSuperSampling = aap != AntiAliasingPattern.OG_2x2 && (thresholdSqr == 0 || @@ -50,29 +45,32 @@ private Color3f antiAliasPixel( PixelStep step, Color3f ulColor, Color3f urColor accumulator.add( llColor ); accumulator.add( lrColor ); accumulator.scale( doSuperSampling ? aap.cornerWeight : 0.25f); - + if (doSuperSampling) + sampleExceptCorners(step, accumulator); + + accumulator.clamp( 0f, 1f ); + + colorBuffer[ step.colorBufferIndex ] = accumulator.get().getRGB(); + } + + private void sampleExceptCorners( PixelStep step, Color3f accumulator ) + { + for( AntiAliasingPattern.SamplingPoint sp : aap ) { - for( AntiAliasingPattern.SamplingPoint sp : aap ) - { - if( Thread.currentThread().isInterrupted() ) - throw new RenderingInterruptedException(); + if( Thread.currentThread().isInterrupted() ) + throw new RenderingInterruptedException(); - // corners already accumulated above - if (sp.isCorner) - continue; - - double v = step.vOld + sp.v * step.v_incr; - double u = step.uOld + sp.u * step.u_incr; - ColumnSubstitutorPair csp = cspProvider.get( v ); - Color3f sample = tracePolynomial( csp.scs, csp.gcs, u, v ); - accumulator.scaleAdd( sp.weight, sample, accumulator ); - } + // corners already accumulated above + if (sp.isCorner) + continue; + + double v = step.vOld + sp.v * step.v_incr; + double u = step.uOld + sp.u * step.u_incr; + ColumnSubstitutorPair csp = cspProvider.get( v ); + Color3f sample = tracePolynomial( csp.scs, csp.gcs, u, v ); + accumulator.scaleAdd( sp.weight, sample, accumulator ); } - - // clamp color, because floating point operations may yield values outside [0,1] - accumulator.clamp( 0f, 1f ); - return accumulator; } private boolean areTooDifferent(Color3f c1, Color3f c2) { From b377d72986f10f9aac00d241a29b987b1148246e Mon Sep 17 00:00:00 2001 From: Sebastian Uribe Date: Sun, 10 Jun 2018 14:57:42 +0200 Subject: [PATCH 52/52] Change CSP Provider to use an array instead of a hashmap --- .../rendering/cpu/AntiAliasingPattern.java | 24 ++++++++++-------- .../cpu/ColumnSubstitutorPairProvider.java | 25 +++++++++++-------- .../de/mfo/jsurf/rendering/cpu/PixelStep.java | 2 +- .../jsurf/rendering/cpu/RenderingTask.java | 2 +- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java index 1148f14..60f09ff 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java @@ -21,18 +21,19 @@ public enum AntiAliasingPattern implements Iterable< AntiAliasingPattern.SamplingPoint > { - OG_1x1( getOGSSPattern( 1 ) ), - OG_2x2( getOGSSPattern( 2 ) ), - OG_3x3( getOGSSPattern( 3 ) ), - OG_4x4( getOGSSPattern( 4 ) ), - OG_5x5( getOGSSPattern( 5 ) ), - OG_6x6( getOGSSPattern( 6 ) ), - OG_7x7( getOGSSPattern( 7 ) ), - OG_8x8( getOGSSPattern( 8 ) ), - RG_2x2( getRGSSPattern() ), - QUINCUNX( getQuincunxPattern() ); + OG_1x1( getOGSSPattern( 1 ), 1 ), + OG_2x2( getOGSSPattern( 2 ), 2 ), + OG_3x3( getOGSSPattern( 3 ), 3 ), + OG_4x4( getOGSSPattern( 4 ), 4 ), + OG_5x5( getOGSSPattern( 5 ), 5 ), + OG_6x6( getOGSSPattern( 6 ), 6 ), + OG_7x7( getOGSSPattern( 7 ), 7 ), + OG_8x8( getOGSSPattern( 8 ), 8 ), + RG_2x2( getRGSSPattern(), 2 ), + QUINCUNX( getQuincunxPattern(), 3 ); private final SamplingPoint[] points; + public final int vSteps; public final float cornerWeight; @@ -88,9 +89,10 @@ public void remove() } } - private AntiAliasingPattern( SamplingPoint[] points ) { + private AntiAliasingPattern( SamplingPoint[] points, int vSteps ) { this.points = points; this.cornerWeight = findFirstCorner().weight; + this.vSteps = vSteps; } SamplingPoint findFirstCorner() { diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java b/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java index 28d51b2..df39029 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/ColumnSubstitutorPairProvider.java @@ -1,27 +1,30 @@ package de.mfo.jsurf.rendering.cpu; -import java.util.HashMap; - import de.mfo.jsurf.algebra.RowSubstitutor; import de.mfo.jsurf.algebra.RowSubstitutorForGradient; class ColumnSubstitutorPairProvider { - private final HashMap< java.lang.Double, ColumnSubstitutorPair > csp_hm; private final RowSubstitutor surfaceRowSubstitutor; private final RowSubstitutorForGradient gradientRowSubstitutor; + + private final ColumnSubstitutorPair[] csps; + private final double vMult; + private final double vInc; - public ColumnSubstitutorPairProvider(DrawcallStaticData dcsd) { - this.csp_hm = new HashMap< java.lang.Double, ColumnSubstitutorPair >(); + public ColumnSubstitutorPairProvider(DrawcallStaticData dcsd, PixelStep step) { this.surfaceRowSubstitutor = dcsd.surfaceRowSubstitutor; this.gradientRowSubstitutor = dcsd.gradientRowSubstitutor; + this.vInc = -step.v_start; + this.vMult = (double)dcsd.antiAliasingPattern.vSteps / step.v_incr; + this.csps = new ColumnSubstitutorPair[(dcsd.antiAliasingPattern.vSteps + 1) * (step.height + 1)]; } public ColumnSubstitutorPair get(double v) { - ColumnSubstitutorPair csp = csp_hm.get(v); - if (csp == null) { - csp = new ColumnSubstitutorPair(surfaceRowSubstitutor.setV( v ), gradientRowSubstitutor.setV( v )); - csp_hm.put(v, csp); - } - return csp; + int index = (int)((v + vInc) * vMult); + + if (csps[index] == null) + csps[index] = new ColumnSubstitutorPair(surfaceRowSubstitutor.setV( v ), gradientRowSubstitutor.setV( v )); + + return csps[index]; } } \ No newline at end of file diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java index 47827c0..bee3480 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/PixelStep.java @@ -7,7 +7,7 @@ */ class PixelStep { private final double u_start; - private final double v_start; + final double v_start; final double u_incr; final double v_incr; diff --git a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java index c2d6676..9aff7e0 100644 --- a/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java +++ b/src/main/java/de/mfo/jsurf/rendering/cpu/RenderingTask.java @@ -35,7 +35,7 @@ public RenderingTask( DrawcallStaticData dcsd, int xStart, int yStart, int xEnd, { this.dcsd = dcsd; this.step = new PixelStep(dcsd, xStart, yStart, xEnd, yEnd); - this.cspProvider = new ColumnSubstitutorPairProvider(dcsd); + this.cspProvider = new ColumnSubstitutorPairProvider(dcsd, step); this.polyTracer = new PolynomialTracer(dcsd); }