Disable shading?

Started by jasef, December 07, 2012, 05:40:34 PM

Previous topic - Next topic

jasef

I'm using the software renderer only.

Is it possible to completely turn off shading? For example, here's a shot from my (modified) "Hello World" example:



(created image using buffer.getOutputBuffer() and ImageIO.write())

I want the only colors in the image to be blue and green, without any blending or anti-aliasing.

Is this possible with jPCT?

Thanks!

EgonOlsen

If you assign no additional light sources and no or a unified texture, there should be no shading.

jasef

What I really want is flat shading, like GL_FLAT back in the day. I tried making my own IRenderHook and did this:

public void beforeRendering(int polyID) {
            GL11.glShadeModel(GL11.GL_FLAT);
        }


but no luck.

Are there any examples of using flat shading using the GLSLShader or IRenderHook classes?

Thanks.


EgonOlsen

BTW: The documentation for that method isn't quite complete. When using compiled objects (Object3D.compile()), you'll get real flat shading, not just faked one.

jasef

Tried it, doesn't work. I'm trying a GLSLShader next.

EgonOlsen

"Doesn't work" is a bit vague. There's actually not much that can't work if you enable flat shading that way. It might not give you what you expect though. Judging from your screen shot, i actually don't see any gouraud shading but some weird artifacts at the edges. Can you post the modified code?

jasef

Here's my code (background is now black):


import com.threed.jpct.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

public class JPCTTest {

    private World world;
    private FrameBuffer buffer;
    private Object3D box;

    public JPCTTest() throws Exception {

        world = new World();
        world.setAmbientLight(255, 255, 255);

        Texture green = new Texture(8, 8, Color.GREEN);
        TextureManager.getInstance().addTexture("green", green);

        box = Primitives.getBox(16f, 2f);

        box.setTexture("green");
        box.setEnvmapped(Object3D.ENVMAP_ENABLED);
        box.setShadingMode(Object3D.SHADING_FAKED_FLAT);

        box.build();
        world.addObject(box);

        world.getCamera().setPosition(50, -50, -5);
        world.getCamera().lookAt(box.getTransformedCenter());

        buffer = new FrameBuffer(100, 100, FrameBuffer.SAMPLINGMODE_NORMAL);

        buffer.enableRenderer(IRenderer.RENDERER_SOFTWARE);
        buffer.disableRenderer(IRenderer.RENDERER_OPENGL);

        buffer.clear(java.awt.Color.BLACK);

        world.renderScene(buffer);
        world.draw(buffer);
        buffer.update();

        BufferedImage image = (BufferedImage)(buffer.getOutputBuffer());

        DataBufferInt buf = (DataBufferInt) image.getRaster().getDataBuffer();
        int[] colors = buf.getData();

        HashMap<String, Boolean> colorsMap = new HashMap<String, Boolean>();

        for(int i = 0; i < colors.length; i++) {
            Color c = new Color(colors[i]);

            String rgb = Integer.toHexString(c.getRGB());
            rgb = rgb.substring(2, rgb.length());

            //System.out.print(rgb+",");

            if(!colorsMap.containsKey(rgb)) {
                colorsMap.put(rgb, true);
            }
        }

        System.out.println("num colors = "+colorsMap.size());

        try {
            File outputfile = new File("saved.png");
            ImageIO.write(image, "png", outputfile);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws Exception {
        new JPCTTest();
    }
}


Here's the image that's saved:



As you can see, I count the number of colors and the result is 26.

If it was true "flat" shading, I'd expect two colors in the whole file: pure green (0, 255, 0) and black. But there is some blending/dithering going on.

Any advice appreciated, thanks!

EgonOlsen

I gave your test case a try and you are right...there are these color banding artifacts when using the software renderer. They are caused by the interpolation across the scanlines of the polygons. One might think that there's no problem to interpolate between 255 and 255, but that's not quite what happens. To make the shading perspective correct, you actually interpolate between 255/z1 and 255/z2. To get the actual color at a point, this value is multiplied by z which itself is being calculated based on a linear interpolation from 1/z1 to 1/z2. All these interpolations happen in integer arithmetic and they do have some accuracy issues, which leads to colors of a scanline being slightly off at the right edges in some case. You can improve this, by rendering into a larger frame buffer, which increases the accuracy.

If you really need completely uniform results, you have two options:

  • do some post-processing on your own
  • abuse the fact that the software renderer supports overbright lighting, i.e. you can use lighting values for ambient larger than 255. Try 500,500,500 for example, and add box.setLighting(Object3D.LIGHTING_NO_LIGHTS); (and remove box.setEnvmapped(..) and box.setShadingMode(...)) and you'll get the desired result. However, this only works for colors with either 0 or 255 in their rgb-components.

jasef