Realtime raytracing experiments in pure Java

Just a Question: How does your topmost code look like?
I mean the Code that is shooting the rays and puts the rgb-values into the picture.
And what do you use to display the image?

I’m just curious.

  • Longor1996

I’m writing the data to a BufferedImage and draw that through a g.drawImage() call. It’s surprisingly fast, because I can use images without alpha channel.

The code looks like this - the real tracing code is in the object.hit() and object.trace() methods. I’ve tried to keep the framework expandable to have more object types but planes and spheres. TracerDataSet is kept in one instance per thread. linepix is an int [] which will take the pixels of one line. Ray, p, lineV and the like are instances of a 3D vector type. Look is the looking vector of the viewer into the scene.

    void calculateScene(int yStart, int yEnd, TracerDataSet data)
    {
        int width = data.linepix.length;
        int height = displayPanel.getHeight();
        
        final int hw = width >> 1;
        final int hh = height >> 1;
        
        for(int y=yEnd; y>yStart; y--)
        {
            data.lineV.set(look);
            data.lineV.add(vert, y);
            
            for(int x=-hw; x<hw; x++)
            {
                data.ray.set(data.lineV);
                data.ray.add(horz, x);
                
                data.p.set(camera);
                
                final int rgb = traceObjects(data);

                data.linepix[hw+x] = rgb;
            }          
            displayPanel.setline(hh-y, data.linepix);
        }                
    }
    

    private int traceObjects(TracerDataSet data)
    {
        boolean go;
        int brightness = 255;
        
        long objectRgb = -1;
        
        do
        {
            go = false;
            
            final double t = findIntersection(data);

            if(data.bestObject != null)
            {
                final long color = data.bestObject.hit(data.p, data.ray, light, t);
                
                if(color == -1L)
                {
                    // mirror, p and v are set up by hit().
                    go = true;
                    brightness = brightness * 230 >> 8;
                }
                else
                {
                    objectRgb = color;
                }
            }
        }
        while(go && brightness > 16);

        if(objectRgb == -1)
        {
            // Nothing hit

            data.ray.norm();
            final int tx = (int)(Textures.clouds.getWidth() * (data.ray.x+1.0) * 0.5);
            final int ty = (int)(Textures.clouds.getHeight() * (data.ray.y+1.0) * 0.5);

            objectRgb = RGB.spread(Textures.clouds.getRGB(tx, ty));
        }
        else
        {
            // shadows
            // need to calculate ray from data.p to light source
            
            data.ray.set(light);
            data.ray.sub(data.p);
            
            findIntersection(data);
            if(data.bestObject != null)
            {
                // shadow
                // brightness = brightness * 10 >> 8;
                brightness = 32;
            }
        }
        
        return RGB.shadeAndCompact(objectRgb, brightness);
    }

    private double findIntersection(TracerDataSet data)
    {
        final double raylen2 = data.ray.length2();

        double bestT = Double.MAX_VALUE;
        data.bestObject = null;
        
        for(int i=0; i<objects.size(); i++)
        {
            final SceneObject object = objects.get(i);
            final double t = object.trace(data.p, data.ray, raylen2);

            if(t >= 0 && t < bestT)
            {
                data.bestObject = object;
                bestT = t;
            }
        }
        
        return bestT;
    }


I’ll clean up the code a bit and publish it under the GPL as part of this project:

http://sourceforge.net/p/freemapper/code/26/tree/gardenlife/trunk/

Give me some hours …

Edit:

The code is there now. It’s a bit farther evolved than the one used for the demo in this thread, but it didn’t cut into performance too badly. The SimpleRay class has a main method which you can run and which will show the demo scene:

http://sourceforge.net/p/freemapper/code/27/tree/gardenlife/trunk/src/tracer/

I want to use the tracer for this project eventually:

Nice!
I get a quite steady 40fps with shadows, which is really impressive :slight_smile:

People can now begin to stop saying “Java is slow” ;D

I’m also positively impressed. I didn’t expect this when I started, although I knew that the Java runtime got much better during the past years.

That was really cool.

40-45fps with the shadows, not bad :slight_smile: