Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
7935e4b
- separated rendering modes in functions, removed some commented out …
seuribe Jun 6, 2018
d26e9e8
- replaced multiplications with additions in the calculation of the (…
seuribe Jun 6, 2018
6a29d4f
- replaced multiplications with increments, additions and substractio…
seuribe Jun 6, 2018
1afa350
- prepared the code for using color buffer pooling
seuribe Jun 6, 2018
819456c
- created a new Color buffer pool class
seuribe Jun 6, 2018
a202b46
-added documentation
seuribe Jun 6, 2018
8db021b
- pushed down the synchronization to the bucket for a specific buffer…
seuribe Jun 6, 2018
be1e429
- cleanup: moved shading code to a different class
seuribe Jun 6, 2018
e43760a
- rename variables and made code slightly more readable
seuribe Jun 6, 2018
fae12e8
- remove unneeded for loop
seuribe Jun 6, 2018
8cec89a
Some changes in the shade function
seuribe Jun 6, 2018
5a51f0a
Separate concerns of rendering into different methods
seuribe Jun 6, 2018
3b7253a
Replace multiplications with additions
seuribe Jun 6, 2018
447a51c
Replace mutliplications with simpler operations
seuribe Jun 6, 2018
11c0e86
Prepare the code for using color buffer pooling
seuribe Jun 6, 2018
d4f34de
Implement Color buffer pooling
seuribe Jun 6, 2018
643c116
Improved documentation of the code
seuribe Jun 6, 2018
075ec24
Change the way color buffer pools are synchronized
seuribe Jun 6, 2018
f758442
Move shading code to its own class
seuribe Jun 6, 2018
39da69b
Make the code more readable
seuribe Jun 6, 2018
340eaa4
Remove unneeded for loop
seuribe Jun 6, 2018
7ede634
Avoid recalculating the view direction and improve readability
seuribe Jun 6, 2018
3b6f7d1
Merge branch 'rendering_task_updates' of https://github.com/IMAGINARY…
seuribe Jun 7, 2018
bf00999
Avoid recalculating internal width and height
seuribe Jun 8, 2018
3b834a8
Move pixel-stepping information to a new class
seuribe Jun 8, 2018
73a22aa
De-duplicate PixelStep creation
seuribe Jun 8, 2018
ba49dee
Move u and v variables inside the PixelStep instance
seuribe Jun 8, 2018
dbcf1bf
Move image dimensions into the PixelStep
seuribe Jun 8, 2018
fa674df
Make PixelStep an instance variable
seuribe Jun 8, 2018
28c0513
Restore correct pixel displacement when rendering without aliasing
seuribe Jun 8, 2018
d7c7b8a
Avoid re-setting the same ColumnSubstitutorPair in the hashmap
seuribe Jun 8, 2018
6aa5067
Make the CSP hashmap an instance variable
seuribe Jun 8, 2018
c2f30c9
Move logic of choosing which render method to use into call method
seuribe Jun 9, 2018
78f1339
Move inner classes to top of file
seuribe Jun 9, 2018
9ff7187
Move CSP creation to a new class
seuribe Jun 9, 2018
a156efc
Correct names of functions
seuribe Jun 9, 2018
3ff425c
Remove the internal color buffer index control from the rendering fun…
seuribe Jun 9, 2018
eb7efdf
Move pixel render strategy to new method(s)
seuribe Jun 9, 2018
35a6eec
Move pixel render strategies to its own class
seuribe Jun 9, 2018
b4287cb
Create new class for doing the Polynomial Tracing and returning the hit
seuribe Jun 9, 2018
0c5e8c5
Move remaining shading code into the Pixel rendering classes
seuribe Jun 9, 2018
f112b62
Move Pixel render strategy classes to their own files
seuribe Jun 9, 2018
ba1c889
Move ColumnSubstitutorPair and provider classes to their own files
seuribe Jun 9, 2018
ce0031f
Move PixelStep class to its own file
seuribe Jun 9, 2018
5f850fb
Clean up file
seuribe Jun 9, 2018
d3d4112
Move calculation of width and height into PixelStep
seuribe Jun 9, 2018
d662817
Remove dead code
seuribe Jun 9, 2018
61c9193
Replace method access with final public fields in SamplingPoint
seuribe Jun 9, 2018
1f5375e
Refactor threshold evaluating function
seuribe Jun 9, 2018
3a94181
Simplify super sampling code
seuribe Jun 9, 2018
c4c23c6
Avoid checking similarity of corner pixels when supersampling is forced
seuribe Jun 9, 2018
2e8b2f8
Move all corner point related calculation outside of the super sampli…
seuribe Jun 9, 2018
b377d72
Change CSP Provider to use an array instead of a hashmap
seuribe Jun 10, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package de.mfo.jsurf.rendering.cpu;

import javax.vecmath.Color3f;

import de.mfo.jsurf.rendering.RenderingInterruptedException;

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 )
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 ];

boolean doSuperSampling =
aap != AntiAliasingPattern.OG_2x2 &&
(thresholdSqr == 0 ||
areTooDifferent( ulColor, urColor ) ||
areTooDifferent( ulColor, llColor ) ||
areTooDifferent( ulColor, lrColor ) ||
areTooDifferent( urColor, llColor ) ||
areTooDifferent( urColor, lrColor ) ||
areTooDifferent( 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)
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 )
{
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 );
}
}

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;
}
}
47 changes: 31 additions & 16 deletions src/main/java/de/mfo/jsurf/rendering/cpu/AntiAliasingPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,36 @@

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;

public static class SamplingPoint
{
private float u, v, weight;
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);
}

public float getU() { return u;}
public float getV() { return v; }
public float getWeight() { return weight; }
}

private class SamplingPointIterator implements Iterator< SamplingPoint >
Expand Down Expand Up @@ -86,7 +89,19 @@ public void remove()
}
}

private AntiAliasingPattern( SamplingPoint[] points ) { this.points = points; }
private AntiAliasingPattern( SamplingPoint[] points, int vSteps ) {
this.points = points;
this.cornerWeight = findFirstCorner().weight;
this.vSteps = vSteps;
}

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 )
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/de/mfo/jsurf/rendering/cpu/BasicPixelRenderer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package de.mfo.jsurf.rendering.cpu;

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();
}
}
115 changes: 115 additions & 0 deletions src/main/java/de/mfo/jsurf/rendering/cpu/ColorBufferPool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package de.mfo.jsurf.rendering.cpu;

import java.util.ArrayList;
import java.util.List;

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.<br/>
* For example, if asked for a buffer for 457 colors, it will return one of size 512.<br/>
* <br/>
* 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<List<Color3f[]>> bufferPool;
private boolean dontPool = false;

// Usage statistics
private int createdBuffers = 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<List<Color3f[]>>(MAX_POWER_OF_TWO);
for (int i = 0 ; i < MAX_POWER_OF_TWO ; i++) {
bufferPool.add(new ArrayList<Color3f[]>());
}
}

public Color3f[] getBuffer(int size) {
size = powOf2Roundup(size);
int index = highestOneBit(size);
requestedBuffers++;

List<Color3f[]> bucket = bufferPool.get(index);
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 */
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
/** Minimum power of two bigger or equal to value */
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 void releaseBuffer(Color3f[] buffer) {
int size = buffer.length;
int index = highestOneBit(size);
List<Color3f[]> bucket = bufferPool.get(index);
synchronized (bucket) {
bucket.add(buffer);
}
}

public String getPoolStatistics() {
return "Requests / created: " + requestedBuffers + "/" + createdBuffers + ". Total size: " + totalBufferSize;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package de.mfo.jsurf.rendering.cpu;

import de.mfo.jsurf.algebra.RowSubstitutor;
import de.mfo.jsurf.algebra.RowSubstitutorForGradient;

class ColumnSubstitutorPairProvider {
private final RowSubstitutor surfaceRowSubstitutor;
private final RowSubstitutorForGradient gradientRowSubstitutor;

private final ColumnSubstitutorPair[] csps;
private final double vMult;
private final double vInc;

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) {
int index = (int)((v + vInc) * vMult);

if (csps[index] == null)
csps[index] = new ColumnSubstitutorPair(surfaceRowSubstitutor.setV( v ), gradientRowSubstitutor.setV( v ));

return csps[index];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import javax.vecmath.*;

class DrawcallStaticData
public class DrawcallStaticData
{
int[] colorBuffer;
int width;
Expand Down
Loading