Harium / propan

3D engine based on Etyl and LibGDX
0 stars 1 forks source link

Add mirror routine #15

Open yuripourre opened 3 years ago

yuripourre commented 3 years ago
The effects of specular reflection can be approximated by a two-pass technique using the stencil buffer. During the first pass, we render the reflected image of the scene. During the second pass, we render the non-reflected view of the scene, using the stencil buffer to prevent the reflected image from being drawn over. 

https://www.opengl.org/archives/resources/code/samples/advanced/advanced97/notes/node90.html

It would be interesting to have a method mirror on camera

camera.mirror(plane); Position and direction would be reflected according to the mirror plane.

Cross product between up and plane may be useful.

LibGDX Snippet:

https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/Camera.java#L151

Point: Intersector#intersectRayPlane
Axis: 
Angle:

Example (JoGL Port) http://jerome.jouvie.free.fr/opengl-tutorials/Tutorial23.php

yuripourre commented 3 years ago

Another java example https://www.java-tips.org/other-api-tips-100035/112-jogl/1701-clipping-and-reflections-using-the-stencil-buffer-nehe-tutorial-jogl-port.html

http://forum.lwjgl.org/index.php?topic=1340.0

yuripourre commented 3 years ago
/*
         * We should clear the stencil buffer like we do with color and depth buffers
         */
        gl.glClear(IGL.GL_COLOR_BUFFER_BIT | IGL.GL_DEPTH_BUFFER_BIT | IGL.GL_STENCIL_BUFFER_BIT);  //Clear the buffers

        camera.update(getTimer().getTimePassedMillis());
        camera.lookAt(modelView);
        gl.glLoadMatrix(modelView);

        if(renderModeFilled) {
            gl.glPolygonMode(IGL.GL_FRONT_AND_BACK, IGL.GL_FILL);
        }
        else {
            gl.glPolygonMode(IGL.GL_FRONT_AND_BACK, IGL.GL_LINE);
        }

        if(camera.getMovable().equals(light)) {
            Vector3f pos = camera.getPosition(new Vector3f());
            lightPos[0] = pos.getX();
            lightPos[1] = pos.getY();
            lightPos[2] = pos.getZ();
        }

        /* Fill with one stencil buffer where the ground is */

        gl.glColorMask(false, false, false, false);             //Disable drawing of r, g, b & a
        gl.glDepthMask(false);
        gl.glEnable(IGL.GL_STENCIL_TEST);                       //Enable Stencil test
        gl.glStencilFunc(IGL.GL_ALWAYS, 1, 1);                  //Test always success, value stored in stencil buffer is 1 (second parameter)
        gl.glStencilOp(IGL.GL_KEEP, IGL.GL_KEEP, IGL.GL_REPLACE);   //Replace by 1 when test pass

        drawRectangle_YPlane_VtxUvNrm(gl, -10.0f, -10.0f, 20.0f, 20.0f, 1);

        gl.glDepthMask(true);
        gl.glColorMask(true, true, true, true);                 //Enable drawing of r, g, b & a

        /* Reflection */

        gl.glStencilFunc(IGL.GL_EQUAL, 1, 1);                   //Draw only where stencil buffer is 1
        gl.glStencilOp(IGL.GL_KEEP, IGL.GL_KEEP, IGL.GL_KEEP);      //Stencil buffer read only

        gl.glPushMatrix();
        gl.glScale(1.0f, -1.0f, 1.0f);                      //Mirror Y
        gl.glLight(IGL.GL_LIGHT0, IGL.GL_POSITION, BufferPool.wrap(lightPos));
        gl.glEnable(IGL.GL_LIGHTING);
        drawSpring(gl);
        gl.glDisable(IGL.GL_LIGHTING);
        gl.glPopMatrix();

        gl.glDisable(IGL.GL_STENCIL_TEST);

        /* Draw the ground */

        gl.glEnable(IGL.GL_TEXTURE_2D);
        gl.glBindTexture(IGL.GL_TEXTURE_2D,  texture.id);
        gl.glEnable(IGL.GL_BLEND);
        gl.glBlendFunc(IGL.GL_ONE, IGL.GL_ONE_MINUS_SRC_ALPHA);
        gl.glColor(1.0f, 1.0f, 1.0f, 0.8f);
        drawRectangle_YPlane_VtxUvNrm(gl, -10.0f, -10.0f, 20.0f, 20.0f, 10);
        gl.glColor(1.0f, 1.0f, 1.0f, 1.0f);
        gl.glDisable(IGL.GL_BLEND);
        gl.glDisable(IGL.GL_TEXTURE_2D);

        /* Draw the spring */

        gl.glLight(IGL.GL_LIGHT0, IGL.GL_POSITION, BufferPool.wrap(lightPos));
        gl.glEnable(IGL.GL_LIGHTING);
        drawSpring(gl);
        gl.glDisable(IGL.GL_LIGHTING);

        /* Draw the bulb */
        gl.glTranslate(lightPos[0], lightPos[1], lightPos[2]);
        Shapes.drawSphere(gl, 0.07f, 10, 10, true, null);
        gl.glTranslate(-lightPos[0], -lightPos[1], -lightPos[2]);