diff options
3 files changed, 965 insertions, 631 deletions
diff --git a/src/main/java/org/jogamp/java3d/utils/geometry/Box.java b/src/main/java/org/jogamp/java3d/utils/geometry/Box.java index 4061412..3444d5c 100644 --- a/src/main/java/org/jogamp/java3d/utils/geometry/Box.java +++ b/src/main/java/org/jogamp/java3d/utils/geometry/Box.java @@ -56,7 +56,7 @@ import org.jogamp.vecmath.Vector3f; * front facing when the faces are rotated 90 toward the viewer. * <p> * By default all primitives with the same parameters share their - * geometry (e.g., you can have 50 shperes in your scene, but the + * geometry (e.g., you can have 50 spheres in your scene, but the * geometry is stored only once). A change to one primitive will * effect all shared nodes. Another implication of this * implementation is that the capabilities of the geometry are shared, diff --git a/src/main/java/org/jogamp/java3d/utils/shader/Cube.java b/src/main/java/org/jogamp/java3d/utils/shader/Cube.java index 7f387b8..8ef1098 100644 --- a/src/main/java/org/jogamp/java3d/utils/shader/Cube.java +++ b/src/main/java/org/jogamp/java3d/utils/shader/Cube.java @@ -1,312 +1,322 @@ -/*
- * Copyright (c) 2016 JogAmp Community. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-package org.jogamp.java3d.utils.shader;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-import org.jogamp.java3d.GeometryArray;
-import org.jogamp.java3d.J3DBuffer;
-import org.jogamp.java3d.Shape3D;
-import org.jogamp.java3d.TriangleArray;
-import org.jogamp.java3d.utils.shader.SimpleShaderAppearance;
-
-/**
- * @author Administrator
- *
- */
-public class Cube extends Shape3D
-{
-
- private static final float[] verts = {
- // front face
- 1.0f, -1.0f, 1.0f, //1
- 1.0f, 1.0f, 1.0f, //2
- -1.0f, 1.0f, 1.0f, //3
- 1.0f, -1.0f, 1.0f, //1
- -1.0f, 1.0f, 1.0f, //3
- -1.0f, -1.0f, 1.0f, //4
- // back face
- -1.0f, -1.0f, -1.0f, //1
- -1.0f, 1.0f, -1.0f, //2
- 1.0f, 1.0f, -1.0f, //3
- -1.0f, -1.0f, -1.0f, //1
- 1.0f, 1.0f, -1.0f, //3
- 1.0f, -1.0f, -1.0f, //4
- // right face
- 1.0f, -1.0f, -1.0f, //1
- 1.0f, 1.0f, -1.0f, //2
- 1.0f, 1.0f, 1.0f, //3
- 1.0f, -1.0f, -1.0f, //1
- 1.0f, 1.0f, 1.0f, //3
- 1.0f, -1.0f, 1.0f, //4
- // left face
- -1.0f, -1.0f, 1.0f, //1
- -1.0f, 1.0f, 1.0f, //2
- -1.0f, 1.0f, -1.0f, //3
- -1.0f, -1.0f, 1.0f, //1
- -1.0f, 1.0f, -1.0f, //3
- -1.0f, -1.0f, -1.0f, //4
- // top face
- 1.0f, 1.0f, 1.0f, //1
- 1.0f, 1.0f, -1.0f, //2
- -1.0f, 1.0f, -1.0f, //3
- 1.0f, 1.0f, 1.0f, //1
- -1.0f, 1.0f, -1.0f, //3
- -1.0f, 1.0f, 1.0f, //4
- // bottom face
- -1.0f, -1.0f, 1.0f, //1
- -1.0f, -1.0f, -1.0f, //2
- 1.0f, -1.0f, -1.0f, //3
- -1.0f, -1.0f, 1.0f, //1
- 1.0f, -1.0f, -1.0f, //3
- 1.0f, -1.0f, 1.0f, };//4
-
- private static final float[] colors = {
- // front face (red)
- 1.0f, 0.0f, 0.0f, //1
- 1.0f, 0.0f, 0.0f, //2
- 1.0f, 0.0f, 0.0f, //3
- 1.0f, 0.0f, 0.0f, //1
- 1.0f, 0.0f, 0.0f, //3
- 1.0f, 0.0f, 0.0f, //4
- // back face (green)
- 0.0f, 1.0f, 0.0f, //1
- 0.0f, 1.0f, 0.0f, //2
- 0.0f, 1.0f, 0.0f, //3
- 0.0f, 1.0f, 0.0f, //1
- 0.0f, 1.0f, 0.0f, //3
- 0.0f, 1.0f, 0.0f, //4
- // right face (blue)
- 0.0f, 0.0f, 1.0f, //1
- 0.0f, 0.0f, 1.0f, //2
- 0.0f, 0.0f, 1.0f, //3
- 0.0f, 0.0f, 1.0f, //1
- 0.0f, 0.0f, 1.0f, //3
- 0.0f, 0.0f, 1.0f, //4
- // left face (yellow)
- 1.0f, 1.0f, 0.0f, //1
- 1.0f, 1.0f, 0.0f, //2
- 1.0f, 1.0f, 0.0f, //3
- 1.0f, 1.0f, 0.0f, //1
- 1.0f, 1.0f, 0.0f, //3
- 1.0f, 1.0f, 0.0f, //4
- // top face (magenta)
- 1.0f, 0.0f, 1.0f, //1
- 1.0f, 0.0f, 1.0f, //2
- 1.0f, 0.0f, 1.0f, //3
- 1.0f, 0.0f, 1.0f, //1
- 1.0f, 0.0f, 1.0f, //3
- 1.0f, 0.0f, 1.0f, //4
- // bottom face (cyan)
- 0.0f, 1.0f, 1.0f, //1
- 0.0f, 1.0f, 1.0f, //2
- 0.0f, 1.0f, 1.0f, //3
- 0.0f, 1.0f, 1.0f, //1
- 0.0f, 1.0f, 1.0f, //3
- 0.0f, 1.0f, 1.0f, };//4
-
- /**
- * Constructs a color cube with unit scale. The corners of the
- * color cube are [-1,-1,-1] and [1,1,1].
- */
- public Cube()
- {
- TriangleArray cube = new TriangleArray(36,
- GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE);
-
- cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(verts)));
- cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors)));
-
- this.setGeometry(cube);
- this.setAppearance(new SimpleShaderAppearance(null,false,false));
- }
-
- /**
- * Constructs a color cube with the specified scale. The corners of the
- * color cube are [-scale,-scale,-scale] and [scale,scale,scale].
- * @param scale the scale of the cube
- */
- public Cube(double scale)
- {
- TriangleArray cube = new TriangleArray(36,
- GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE);
-
- float scaledVerts[] = new float[verts.length];
- for (int i = 0; i < verts.length; i++)
- scaledVerts[i] = verts[i] * (float) scale;
-
- cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts)));
- cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors)));
-
- this.setGeometry(cube);
-
- this.setAppearance(new SimpleShaderAppearance(null,false,false));
- }
-
- public Cube(double scale, float r, float g, float b)
- {
- TriangleArray cube = new TriangleArray(36,
- GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE);
-
- float scaledVerts[] = new float[verts.length];
- for (int i = 0; i < verts.length; i++)
- scaledVerts[i] = verts[i] * (float) scale;
-
- cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts)));
-
- float colorsSet[] = new float[36 * 3];
- for (int i = 0; i < 36; i++)
- {
- colorsSet[i * 3 + 0] = r;
- colorsSet[i * 3 + 1] = g;
- colorsSet[i * 3 + 2] = b;
- }
-
- cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colorsSet)));
-
- this.setGeometry(cube);
- this.setAppearance(new SimpleShaderAppearance(null,false,false));
- }
-
- /**
- * Constructs a color cube with the specified scale. The corners of the
- * color cube are [-scale,-scale,-scale] and [scale,scale,scale].
- * @param scale the scale of the cube
- */
- public Cube(double xScale, double yScale, double zScale)
- {
- TriangleArray cube = new TriangleArray(36,
- GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE);
-
- float scaledVerts[] = new float[verts.length];
- for (int i = 0; i < verts.length; i += 3)
- {
- scaledVerts[i + 0] = verts[i + 0] * (float) xScale;
- scaledVerts[i + 1] = verts[i + 1] * (float) yScale;
- scaledVerts[i + 2] = verts[i + 2] * (float) zScale;
- }
-
- cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts)));
- cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors)));
-
- this.setGeometry(cube);
- this.setAppearance(new SimpleShaderAppearance(null,false,false));
- }
-
- public Cube(double xScale, double yScale, double zScale, float r, float g, float b)
- {
- TriangleArray cube = new TriangleArray(36,
- GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE);
-
- float scaledVerts[] = new float[verts.length];
- for (int i = 0; i < verts.length; i += 3)
- {
- scaledVerts[i + 0] = verts[i + 0] * (float) xScale;
- scaledVerts[i + 1] = verts[i + 1] * (float) yScale;
- scaledVerts[i + 2] = verts[i + 2] * (float) zScale;
- }
-
- cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts)));
-
- float colorsSet[] = new float[36 * 3];
- for (int i = 0; i < 36; i++)
- {
- colorsSet[i * 3 + 0] = r;
- colorsSet[i * 3 + 1] = g;
- colorsSet[i * 3 + 2] = b;
- }
-
- cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colorsSet)));
-
- this.setGeometry(cube);
- this.setAppearance(new SimpleShaderAppearance(null,false,false));
- }
-
- public Cube(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax)
- {
- TriangleArray cube = new TriangleArray(36,
- GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE);
-
- float scaledVerts[] = new float[] {
- // front face
- xMax, yMin, zMax, //1
- xMax, yMax, zMax, //2
- xMin, yMax, zMax, //3
- xMax, yMin, zMax, //1
- xMin, yMax, zMax, //3
- xMin, yMin, zMax, //4
- // back face
- xMin, yMin, zMin, //1
- xMin, yMax, zMin, //2
- xMax, yMax, zMin, //3
- xMin, yMin, zMin, //1
- xMax, yMax, zMin, //3
- xMax, yMin, zMin, //4
- // right face
- xMax, yMin, zMin, //1
- xMax, yMax, zMin, //2
- xMax, yMax, zMax, //3
- xMax, yMin, zMin, //1
- xMax, yMax, zMax, //3
- xMax, yMin, zMax, //4
- // left face
- xMin, yMin, zMax, //1
- xMin, yMax, zMax, //2
- xMin, yMax, zMin, //3
- xMin, yMin, zMax, //1
- xMin, yMax, zMin, //3
- xMin, yMin, zMin, //4
- // top face
- xMax, yMax, zMax, //1
- xMax, yMax, zMin, //2
- xMin, yMax, zMin, //3
- xMax, yMax, zMax, //1
- xMin, yMax, zMin, //3
- xMin, yMax, zMax, //4
- // bottom face
- xMin, yMin, zMax, //1
- xMin, yMin, zMin, //2
- xMax, yMin, zMin, //3
- xMin, yMin, zMax, //1
- xMax, yMin, zMin, //3
- xMax, yMin, zMax, };//4
-
- cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts)));
- cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors)));
-
- this.setGeometry(cube);
- this.setAppearance(new SimpleShaderAppearance(null,false,false));
- }
-
- public static FloatBuffer makeFloatBuffer(float[] arr)
- {
- ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);
- bb.order(ByteOrder.nativeOrder());
- FloatBuffer fb = bb.asFloatBuffer();
- fb.put(arr);
- fb.position(0);
- return fb;
- }
-
-}
+/* + * Copyright (c) 2016 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those + * of the authors and should not be interpreted as representing official policies, + * either expressed or implied, of the JogAmp Community. + * + */ + +package org.jogamp.java3d.utils.shader; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import org.jogamp.java3d.GeometryArray; +import org.jogamp.java3d.J3DBuffer; +import org.jogamp.java3d.Shape3D; +import org.jogamp.java3d.TriangleArray; +import org.jogamp.java3d.utils.shader.SimpleShaderAppearance; + +/** + * Note Cube does not have normals and so cannot be used for lit geometries + * It is designed as a general debug position indicator + * If you want to add a Material and have lighting enabled please use a org.jogamp.java3d.utils.geometry.Box + * + */ +public class Cube extends Shape3D +{ + + private static final float[] verts = { + // front face + 1.0f, -1.0f, 1.0f, //1 + 1.0f, 1.0f, 1.0f, //2 + -1.0f, 1.0f, 1.0f, //3 + 1.0f, -1.0f, 1.0f, //1 + -1.0f, 1.0f, 1.0f, //3 + -1.0f, -1.0f, 1.0f, //4 + // back face + -1.0f, -1.0f, -1.0f, //1 + -1.0f, 1.0f, -1.0f, //2 + 1.0f, 1.0f, -1.0f, //3 + -1.0f, -1.0f, -1.0f, //1 + 1.0f, 1.0f, -1.0f, //3 + 1.0f, -1.0f, -1.0f, //4 + // right face + 1.0f, -1.0f, -1.0f, //1 + 1.0f, 1.0f, -1.0f, //2 + 1.0f, 1.0f, 1.0f, //3 + 1.0f, -1.0f, -1.0f, //1 + 1.0f, 1.0f, 1.0f, //3 + 1.0f, -1.0f, 1.0f, //4 + // left face + -1.0f, -1.0f, 1.0f, //1 + -1.0f, 1.0f, 1.0f, //2 + -1.0f, 1.0f, -1.0f, //3 + -1.0f, -1.0f, 1.0f, //1 + -1.0f, 1.0f, -1.0f, //3 + -1.0f, -1.0f, -1.0f, //4 + // top face + 1.0f, 1.0f, 1.0f, //1 + 1.0f, 1.0f, -1.0f, //2 + -1.0f, 1.0f, -1.0f, //3 + 1.0f, 1.0f, 1.0f, //1 + -1.0f, 1.0f, -1.0f, //3 + -1.0f, 1.0f, 1.0f, //4 + // bottom face + -1.0f, -1.0f, 1.0f, //1 + -1.0f, -1.0f, -1.0f, //2 + 1.0f, -1.0f, -1.0f, //3 + -1.0f, -1.0f, 1.0f, //1 + 1.0f, -1.0f, -1.0f, //3 + 1.0f, -1.0f, 1.0f, };//4 + + private static final float[] colors = { + // front face (red) + 1.0f, 0.0f, 0.0f, //1 + 1.0f, 0.0f, 0.0f, //2 + 1.0f, 0.0f, 0.0f, //3 + 1.0f, 0.0f, 0.0f, //1 + 1.0f, 0.0f, 0.0f, //3 + 1.0f, 0.0f, 0.0f, //4 + // back face (green) + 0.0f, 1.0f, 0.0f, //1 + 0.0f, 1.0f, 0.0f, //2 + 0.0f, 1.0f, 0.0f, //3 + 0.0f, 1.0f, 0.0f, //1 + 0.0f, 1.0f, 0.0f, //3 + 0.0f, 1.0f, 0.0f, //4 + // right face (blue) + 0.0f, 0.0f, 1.0f, //1 + 0.0f, 0.0f, 1.0f, //2 + 0.0f, 0.0f, 1.0f, //3 + 0.0f, 0.0f, 1.0f, //1 + 0.0f, 0.0f, 1.0f, //3 + 0.0f, 0.0f, 1.0f, //4 + // left face (yellow) + 1.0f, 1.0f, 0.0f, //1 + 1.0f, 1.0f, 0.0f, //2 + 1.0f, 1.0f, 0.0f, //3 + 1.0f, 1.0f, 0.0f, //1 + 1.0f, 1.0f, 0.0f, //3 + 1.0f, 1.0f, 0.0f, //4 + // top face (magenta) + 1.0f, 0.0f, 1.0f, //1 + 1.0f, 0.0f, 1.0f, //2 + 1.0f, 0.0f, 1.0f, //3 + 1.0f, 0.0f, 1.0f, //1 + 1.0f, 0.0f, 1.0f, //3 + 1.0f, 0.0f, 1.0f, //4 + // bottom face (cyan) + 0.0f, 1.0f, 1.0f, //1 + 0.0f, 1.0f, 1.0f, //2 + 0.0f, 1.0f, 1.0f, //3 + 0.0f, 1.0f, 1.0f, //1 + 0.0f, 1.0f, 1.0f, //3 + 0.0f, 1.0f, 1.0f, };//4 + + /** + * Constructs a color cube with unit scale. The corners of the + * color cube are [-1,-1,-1] and [1,1,1]. + */ + public Cube() + { + TriangleArray cube = new TriangleArray(36, + GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE); + + cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(verts))); + cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors))); + + this.setGeometry(cube); + this.setAppearance(new SimpleShaderAppearance()); + } + + /** + * Constructs a color cube with the specified scale. The corners of the + * color cube are [-scale,-scale,-scale] and [scale,scale,scale]. + * @param scale the scale of the cube + */ + public Cube(double scale) + { + TriangleArray cube = new TriangleArray(36, + GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE); + + float scaledVerts[] = new float[verts.length]; + for (int i = 0; i < verts.length; i++) + scaledVerts[i] = verts[i] * (float) scale; + + cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts))); + cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors))); + + this.setGeometry(cube); + + this.setAppearance(new SimpleShaderAppearance()); + } + + public Cube(double scale, float r, float g, float b) + { + TriangleArray cube = new TriangleArray(36, + GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE); + + float scaledVerts[] = new float[verts.length]; + for (int i = 0; i < verts.length; i++) + scaledVerts[i] = verts[i] * (float) scale; + + cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts))); + + float colorsSet[] = new float[36 * 3]; + for (int i = 0; i < 36; i++) + { + colorsSet[i * 3 + 0] = r; + colorsSet[i * 3 + 1] = g; + colorsSet[i * 3 + 2] = b; + } + + cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colorsSet))); + + this.setGeometry(cube); + this.setAppearance(new SimpleShaderAppearance()); + } + + /** + * Constructs a color cube with the specified scale. The corners of the + * color cube are [-scale,-scale,-scale] and [scale,scale,scale]. + * @param scale the scale of the cube + */ + public Cube(double xScale, double yScale, double zScale) + { + TriangleArray cube = new TriangleArray(36, + GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE); + + float scaledVerts[] = new float[verts.length]; + for (int i = 0; i < verts.length; i += 3) + { + scaledVerts[i + 0] = verts[i + 0] * (float) xScale; + scaledVerts[i + 1] = verts[i + 1] * (float) yScale; + scaledVerts[i + 2] = verts[i + 2] * (float) zScale; + } + + cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts))); + cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors))); + + this.setGeometry(cube); + this.setAppearance(new SimpleShaderAppearance()); + } + + public Cube(double xScale, double yScale, double zScale, float r, float g, float b) + { + TriangleArray cube = new TriangleArray(36, + GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE); + + float scaledVerts[] = new float[verts.length]; + for (int i = 0; i < verts.length; i += 3) + { + scaledVerts[i + 0] = verts[i + 0] * (float) xScale; + scaledVerts[i + 1] = verts[i + 1] * (float) yScale; + scaledVerts[i + 2] = verts[i + 2] * (float) zScale; + } + + cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts))); + + float colorsSet[] = new float[36 * 3]; + for (int i = 0; i < 36; i++) + { + colorsSet[i * 3 + 0] = r; + colorsSet[i * 3 + 1] = g; + colorsSet[i * 3 + 2] = b; + } + + cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colorsSet))); + + this.setGeometry(cube); + this.setAppearance(new SimpleShaderAppearance()); + } + + public Cube(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax) + { + TriangleArray cube = new TriangleArray(36, + GeometryArray.COORDINATES | GeometryArray.COLOR_3 | GeometryArray.USE_NIO_BUFFER | GeometryArray.BY_REFERENCE); + + float scaledVerts[] = new float[] { + // front face + xMax, yMin, zMax, //1 + xMax, yMax, zMax, //2 + xMin, yMax, zMax, //3 + xMax, yMin, zMax, //1 + xMin, yMax, zMax, //3 + xMin, yMin, zMax, //4 + // back face + xMin, yMin, zMin, //1 + xMin, yMax, zMin, //2 + xMax, yMax, zMin, //3 + xMin, yMin, zMin, //1 + xMax, yMax, zMin, //3 + xMax, yMin, zMin, //4 + // right face + xMax, yMin, zMin, //1 + xMax, yMax, zMin, //2 + xMax, yMax, zMax, //3 + xMax, yMin, zMin, //1 + xMax, yMax, zMax, //3 + xMax, yMin, zMax, //4 + // left face + xMin, yMin, zMax, //1 + xMin, yMax, zMax, //2 + xMin, yMax, zMin, //3 + xMin, yMin, zMax, //1 + xMin, yMax, zMin, //3 + xMin, yMin, zMin, //4 + // top face + xMax, yMax, zMax, //1 + xMax, yMax, zMin, //2 + xMin, yMax, zMin, //3 + xMax, yMax, zMax, //1 + xMin, yMax, zMin, //3 + xMin, yMax, zMax, //4 + // bottom face + xMin, yMin, zMax, //1 + xMin, yMin, zMin, //2 + xMax, yMin, zMin, //3 + xMin, yMin, zMax, //1 + xMax, yMin, zMin, //3 + xMax, yMin, zMax, };//4 + + cube.setCoordRefBuffer(new J3DBuffer(makeFloatBuffer(scaledVerts))); + cube.setColorRefBuffer(new J3DBuffer(makeFloatBuffer(colors))); + + this.setGeometry(cube); + this.setAppearance(new SimpleShaderAppearance()); + } + + public static FloatBuffer makeFloatBuffer(float[] arr) + { + ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4); + bb.order(ByteOrder.nativeOrder()); + FloatBuffer fb = bb.asFloatBuffer(); + fb.put(arr); + fb.position(0); + return fb; + } + +} diff --git a/src/main/java/org/jogamp/java3d/utils/shader/SimpleShaderAppearance.java b/src/main/java/org/jogamp/java3d/utils/shader/SimpleShaderAppearance.java index ab48fac..8ef0bd1 100644 --- a/src/main/java/org/jogamp/java3d/utils/shader/SimpleShaderAppearance.java +++ b/src/main/java/org/jogamp/java3d/utils/shader/SimpleShaderAppearance.java @@ -1,30 +1,41 @@ /* * Copyright (c) 2016 JogAmp Community. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those + * of the authors and should not be interpreted as representing official policies, + * either expressed or implied, of the JogAmp Community. * */ package org.jogamp.java3d.utils.shader; +import java.util.HashMap; + import org.jogamp.java3d.ColoringAttributes; import org.jogamp.java3d.GLSLShaderProgram; import org.jogamp.java3d.LineAttributes; import org.jogamp.java3d.Material; +import org.jogamp.java3d.NodeComponent; +import org.jogamp.java3d.PointAttributes; import org.jogamp.java3d.PolygonAttributes; import org.jogamp.java3d.RenderingAttributes; import org.jogamp.java3d.Shader; @@ -32,21 +43,81 @@ import org.jogamp.java3d.ShaderAppearance; import org.jogamp.java3d.ShaderAttributeSet; import org.jogamp.java3d.ShaderAttributeValue; import org.jogamp.java3d.SourceCodeShader; +import org.jogamp.java3d.TexCoordGeneration; +import org.jogamp.java3d.Texture; +import org.jogamp.java3d.TextureAttributes; +import org.jogamp.java3d.TextureUnitState; +import org.jogamp.java3d.TransparencyAttributes; import org.jogamp.vecmath.Color3f; +import org.jogamp.vecmath.Vector4f; /** + * SimpleShaderAppearance is a mechanism to quickly build shaders compatible with Java3D 1.7.0 Jogl2es2Pipeline. + * It will use the set components to determine the shader to use, for example if you set a material + * then it will add the lighting uniforms values and do the calculations + * Similarly if you set a texture it will sample from it. + * + * Sharing SimpleShaderAppearances (such as appears to be done by Box) will almost certainly cause problems, however the shader programs + * that are identical are automatically shared internally. + * + * If you want to see examples of the shader source use getVertexShaderSource and getFragmentShaderSource after setting up + * a SimpleShaderAppearance as you would have done for a regular Appearance + * + * Some pipeline data such as FogData are not used by this class and must be manually setup if desired. + * + * To use the auto builder simply construct using SimpleShaderAppearance() + * To force a flat shader use SimpleShaderAppearance(false, false) + * To force a colored line shader use SimpleShaderAppearance(new Color4f(1,0,1,1,)) + * + * Note, this defaults to the values for desktop, on ES hardware you must call + * SimpleShaderAppearance.setVersionES300(); + * or SimpleShaderAppearance.setVersionES100(); * @author phil * */ public class SimpleShaderAppearance extends ShaderAppearance { - - public static String versionString = "#version 120\n"; - private static GLSLShaderProgram flatShaderProgram; - private static GLSLShaderProgram textureShaderProgram; - private static GLSLShaderProgram colorLineShaderProgram; - private static GLSLShaderProgram litFlatShaderProgram; - private static GLSLShaderProgram litTextureShaderProgram; + + private static String versionString = "#version 120\n"; + private static String outString = "varying"; + private static String inString = "varying"; + private static String fragColorDec = ""; + private static String fragColorVar = "gl_FragColor"; + private static String vertexAttributeInString = "attribute"; + private static String texture2D = "texture2D"; + + public static void setVersionES100() + { + versionString = "#version 100\n"; + outString = "varying"; + inString = "varying"; + fragColorDec = ""; + fragColorVar = "gl_FragColor"; + vertexAttributeInString = "attribute"; + texture2D = "texture2D"; + } + + public static void setVersionES300() + { + versionString = "#version 300 es\n"; + outString = "out"; + inString = "in"; + fragColorDec = "out vec4 glFragColor;\n"; + fragColorVar = "glFragColor"; + vertexAttributeInString = "in"; + texture2D = "texture"; + } + + public static void setVersion120() + { + versionString = "#version 120\n"; + outString = "varying"; + inString = "varying"; + fragColorDec = ""; + fragColorVar = "gl_FragColor"; + vertexAttributeInString = "attribute"; + texture2D = "texture2D"; + } public static String alphaTestUniforms = "uniform int alphaTestEnabled;\n" + // "uniform int alphaTestFunction;\n" + // @@ -70,12 +141,56 @@ public class SimpleShaderAppearance extends ShaderAppearance " discard; \n" + // "}\n"; + public static String glFrontMaterial = "struct material\n" + // + " {\n" + // + " int lightEnabled;\n" + // + " vec4 ambient;\n" + // + " vec4 diffuse;\n" + // + " vec4 emission; \n" + // + " vec3 specular;\n" + // + " float shininess;\n" + // + " };\n" + // + "uniform material glFrontMaterial;\n"; // + + public static String glLightSource = "struct lightSource\n" + // + " {\n" + // + " vec4 position;\n" + // + " vec4 diffuse;\n" + // + " vec4 specular;\n" + // + " float constantAttenuation, linearAttenuation, quadraticAttenuation;\n" + // + " float spotCutoff, spotExponent;\n" + // + " vec3 spotDirection;\n" + // + " };\n" + // + "\n" + // + " uniform int numberOfLights;\n" + // + " const int maxLights = 3;\n" + // + " uniform lightSource glLightSource[maxLights];\n"; // + + private static HashMap<Integer, GLSLShaderProgram> shaderPrograms = new HashMap<Integer, GLSLShaderProgram>(); + + private static GLSLShaderProgram flatShaderProgram; + private static GLSLShaderProgram colorLineShaderProgram; + + private static HashMap<GLSLShaderProgram, String> vertexShaderSources = new HashMap<GLSLShaderProgram, String>(); + private static HashMap<GLSLShaderProgram, String> fragmentShaderSources = new HashMap<GLSLShaderProgram, String>(); + + private boolean buildBasedOnAttributes = false; + + // we can't set it in the super class as tex coord gen is not supported in the pipeline + // so we record it in this class when set + private TexCoordGeneration texCoordGeneration = null; + + private String vertexShaderSource = null; + + private String fragmentShaderSource = null; + /** - * Polygons no texture, no single color, must have color vertex attribute + * This will define the shader code based on the attributes set */ public SimpleShaderAppearance() { - this(null, false, false); + buildBasedOnAttributes = true; + rebuildShaders(); } /** @@ -87,14 +202,6 @@ public class SimpleShaderAppearance extends ShaderAppearance this(color, false, false); } - /** - * Polygons if hasTexture is true a texture otherwise vertex attribute colors for face color - */ - public SimpleShaderAppearance(boolean hasTexture) - { - this(null, false, hasTexture); - } - public SimpleShaderAppearance(boolean lit, boolean hasTexture) { this(null, lit, hasTexture); @@ -104,372 +211,589 @@ public class SimpleShaderAppearance extends ShaderAppearance * otherwise simple poly appearance * @param color */ - public SimpleShaderAppearance(Color3f color, boolean lit, boolean hasTexture) + private SimpleShaderAppearance(Color3f color, boolean lit, boolean hasTexture) { - if (lit) + if (lit || hasTexture) { - String vertexProgram = versionString; - vertexProgram += "attribute vec4 glVertex;\n"; - vertexProgram += "attribute vec4 glColor;\n"; - vertexProgram += "attribute vec3 glNormal; \n"; - if (hasTexture) - { - vertexProgram += "attribute vec2 glMultiTexCoord0;\n"; - } - vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; - vertexProgram += "uniform mat4 glModelViewMatrix;\n"; - vertexProgram += "uniform mat3 glNormalMatrix;\n"; - vertexProgram += "uniform int ignoreVertexColors;\n"; - vertexProgram += "uniform vec4 glLightModelambient;\n"; - vertexProgram += "struct material\n"; - vertexProgram += "{\n"; - vertexProgram += " int lightEnabled;\n"; - vertexProgram += " vec4 ambient;\n"; - vertexProgram += " vec4 diffuse;\n"; - vertexProgram += " vec4 emission; \n"; - vertexProgram += " vec3 specular;\n"; - vertexProgram += " float shininess;\n"; - vertexProgram += "};\n"; - vertexProgram += "uniform material glFrontMaterial;\n"; - vertexProgram += "struct lightSource\n"; - vertexProgram += " {\n"; - vertexProgram += " vec4 position;\n"; - vertexProgram += " vec4 diffuse;\n"; - vertexProgram += " vec4 specular;\n"; - vertexProgram += " float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"; - vertexProgram += " float spotCutoff, spotExponent;\n"; - vertexProgram += " vec3 spotDirection;\n"; - vertexProgram += " };\n"; - vertexProgram += "\n"; - vertexProgram += " uniform int numberOfLights;\n"; - vertexProgram += " const int maxLights = 1;\n"; - vertexProgram += " uniform lightSource glLightSource[maxLights];\n"; - if (hasTexture) - { - vertexProgram += "varying vec2 glTexCoord0;\n"; - } - vertexProgram += "varying vec3 LightDir;\n"; - vertexProgram += "varying vec3 ViewDir;\n"; - vertexProgram += "varying vec3 N;\n"; - vertexProgram += "varying vec4 A;\n"; - vertexProgram += "varying vec4 C;\n"; - vertexProgram += "varying vec4 D;\n"; - vertexProgram += "varying vec3 emissive;\n"; - vertexProgram += "varying vec3 specular;\n"; - vertexProgram += "varying float shininess;\n"; - vertexProgram += "void main( void ){\n"; - vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; - if (hasTexture) + boolean hasTextureCoordGen = false; + boolean texCoordGenModeObjLinear = false; + build(hasTexture, lit, hasTextureCoordGen, texCoordGenModeObjLinear); + } + else + { + if (color != null) { - vertexProgram += "glTexCoord0 = glMultiTexCoord0.st;\n"; - } + PolygonAttributes polyAtt = new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0.0f); + polyAtt.setPolygonOffset(0.1f); + setPolygonAttributes(polyAtt); + LineAttributes lineAtt = new LineAttributes(1, LineAttributes.PATTERN_SOLID, false); + setLineAttributes(lineAtt); + + ColoringAttributes colorAtt = new ColoringAttributes(color, ColoringAttributes.FASTEST); + setColoringAttributes(colorAtt); - vertexProgram += "N = normalize(glNormalMatrix * glNormal);\n"; + RenderingAttributes ra = new RenderingAttributes(); + ra.setIgnoreVertexColors(true); + setRenderingAttributes(ra); - vertexProgram += "vec3 v = vec3(glModelViewMatrix * glVertex);\n"; + Material mat = new Material(); + setMaterial(mat); + + if (colorLineShaderProgram == null) + { + colorLineShaderProgram = new GLSLShaderProgram() { + @Override + public String toString() + { + return "SimpleShaderAppearance colorLineShaderProgram"; + } + }; + String vertexProgram = versionString; + vertexProgram += vertexAttributeInString + " vec4 glVertex;\n"; + vertexProgram += vertexAttributeInString + " vec4 glColor;\n"; + vertexProgram += "uniform int ignoreVertexColors;\n"; + vertexProgram += "uniform vec4 objectColor;\n"; + vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; + vertexProgram += outString + " vec4 glFrontColor;\n"; + vertexProgram += "void main( void ){\n"; + vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; + vertexProgram += "if( ignoreVertexColors != 0 )\n"; + vertexProgram += " glFrontColor = objectColor;\n"; + vertexProgram += "else\n"; + vertexProgram += " glFrontColor = glColor;\n"; + vertexProgram += "}"; - vertexProgram += "ViewDir = -v.xyz;\n"; - vertexProgram += "LightDir = glLightSource[0].position.xyz;\n"; + String fragmentProgram = versionString; + fragmentProgram += "precision mediump float;\n"; + fragmentProgram += inString + " vec4 glFrontColor;\n"; + fragmentProgram += fragColorDec; + fragmentProgram += "void main( void ){\n"; + fragmentProgram += fragColorVar + " = glFrontColor;\n"; + fragmentProgram += "}"; - vertexProgram += "A = glLightModelambient * glFrontMaterial.ambient;\n"; - vertexProgram += "if( ignoreVertexColors != 0) \n"; - // objectColor should be used if it is no lighting, and reusing material diffuse appears wrong - vertexProgram += " C = vec4(1,1,1,1);//glFrontMaterial.diffuse; \n"; - vertexProgram += "else \n"; - vertexProgram += " C = glColor; \n"; + colorLineShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); - vertexProgram += "D = glLightSource[0].diffuse * glFrontMaterial.diffuse;\n"; + vertexShaderSources.put(colorLineShaderProgram, vertexProgram); + fragmentShaderSources.put(colorLineShaderProgram, fragmentProgram); + } - vertexProgram += "emissive = glFrontMaterial.emission.rgb;\n"; - vertexProgram += "specular = glFrontMaterial.specular;\n"; - vertexProgram += "shininess = glFrontMaterial.shininess;\n"; - vertexProgram += "}"; + setShaderProgram(colorLineShaderProgram); + vertexShaderSource = vertexShaderSources.get(colorLineShaderProgram); + fragmentShaderSource = fragmentShaderSources.get(colorLineShaderProgram); - String fragmentProgram = versionString; - fragmentProgram += "precision mediump float;\n"; - if (hasTexture) + } + else { - fragmentProgram += alphaTestUniforms; - fragmentProgram += "varying vec2 glTexCoord0;\n"; - fragmentProgram += "uniform sampler2D BaseMap;\n"; - } + if (flatShaderProgram == null) + { + flatShaderProgram = new GLSLShaderProgram() { + @Override + public String toString() + { + return "SimpleShaderAppearance flatShaderProgram"; + } + }; + String vertexProgram = versionString; + vertexProgram += vertexAttributeInString + " vec4 glVertex;\n"; + vertexProgram += vertexAttributeInString + " vec4 glColor;\n"; + vertexProgram += "uniform int ignoreVertexColors;\n"; + vertexProgram += "uniform vec4 objectColor;\n"; + vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; + vertexProgram += outString + " vec4 glFrontColor;\n"; + vertexProgram += "void main( void ){\n"; + vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; + vertexProgram += "if( ignoreVertexColors != 0 )\n"; + vertexProgram += " glFrontColor = objectColor;\n"; + vertexProgram += "else\n"; + vertexProgram += " glFrontColor = glColor;\n"; + vertexProgram += "}"; - fragmentProgram += "in vec3 LightDir;\n"; - fragmentProgram += "in vec3 ViewDir;\n"; + String fragmentProgram = versionString; + fragmentProgram += "precision mediump float;\n"; + fragmentProgram += "uniform float transparencyAlpha;\n"; + fragmentProgram += inString + " vec4 glFrontColor;\n"; + fragmentProgram += fragColorDec; + fragmentProgram += "void main( void ){\n"; + fragmentProgram += fragColorVar + " = glFrontColor;\n"; + fragmentProgram += fragColorVar + ".a *= transparencyAlpha;\n"; + fragmentProgram += "}"; - fragmentProgram += "in vec3 N;\n"; + flatShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); + vertexShaderSources.put(flatShaderProgram, vertexProgram); + fragmentShaderSources.put(flatShaderProgram, fragmentProgram); + //System.out.println("vertexProgram " +vertexProgram); + //System.out.println("fragmentProgram " +fragmentProgram); - fragmentProgram += "in vec4 A;\n"; - fragmentProgram += "in vec4 C;\n"; - fragmentProgram += "in vec4 D;\n"; + } - fragmentProgram += "in vec3 emissive;\n"; - fragmentProgram += "in vec3 specular;\n"; - fragmentProgram += "in float shininess;\n"; - fragmentProgram += "void main( void ){\n "; - if (hasTexture) - { - fragmentProgram += "vec4 baseMap = texture2D( BaseMap, glTexCoord0.st );\n"; + setShaderProgram(flatShaderProgram); + vertexShaderSource = vertexShaderSources.get(flatShaderProgram); + fragmentShaderSource = fragmentShaderSources.get(flatShaderProgram); } - if (hasTexture) - { - fragmentProgram += alphaTestMethod; - } - fragmentProgram += "vec3 normal = N;\n"; - fragmentProgram += "vec3 L = normalize(LightDir);\n"; - fragmentProgram += "vec3 E = normalize(ViewDir);\n"; - fragmentProgram += "vec3 R = reflect(-L, normal);\n"; - fragmentProgram += "vec3 H = normalize( L + E );\n"; + } + + } - fragmentProgram += "float NdotL = max( dot(normal, L), 0.0 );\n"; - fragmentProgram += "float NdotH = max( dot(normal, H), 0.0 );\n"; - fragmentProgram += "float EdotN = max( dot(normal, E), 0.0 );\n"; - fragmentProgram += "float NdotNegL = max( dot(normal, -L), 0.0 );\n"; + public String getVertexShaderSource() + { + return vertexShaderSource; + } - fragmentProgram += "vec4 color;\n"; - if (hasTexture) + public String getFragmentShaderSource() + { + return fragmentShaderSource; + } + + private static Shader[] makeShaders(String vertexProgram, String fragmentProgram) + { + Shader[] shaders = new Shader[2]; + shaders[0] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL, Shader.SHADER_TYPE_VERTEX, vertexProgram) { + @Override + public String toString() { - fragmentProgram += "vec3 albedo = baseMap.rgb * C.rgb;\n"; + return "vertexProgram"; } - else + }; + shaders[1] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL, Shader.SHADER_TYPE_FRAGMENT, fragmentProgram) { + @Override + public String toString() { - fragmentProgram += "vec3 albedo = C.rgb;\n"; + return "fragmentProgram"; } - fragmentProgram += "vec3 diffuse = A.rgb + (D.rgb * NdotL);\n"; - - // 0.3 is just what the calc is - fragmentProgram += "vec3 spec = specular * pow(NdotH, 0.3*shininess);\n"; - // D is not right it should be the light source spec color, probably just 1,1,1 but java3d has no spec on lights - //fragmentProgram += "spec *= D.rgb;\n"; + }; + return shaders; + } - fragmentProgram += "color.rgb = albedo * (diffuse + emissive) + spec;\n"; - if (hasTexture) + private void rebuildShaders() + { + if (buildBasedOnAttributes) + { + // we only rebuild if we are not yet live or the right capabilities have been set + if ((!this.isLive() && !this.isCompiled()) || (this.getCapability(ALLOW_MATERIAL_READ) + && this.getCapability(ALLOW_TEXTURE_UNIT_STATE_READ) && this.getCapability(ALLOW_TEXTURE_READ))) { - fragmentProgram += "color.a = C.a * baseMap.a;\n"; + boolean hasTexture = this.getTexture() != null || this.getTextureUnitCount() > 0; + if (this.getTextureUnitCount() > 0) + System.out.println("this.getTextureUnitCount() " + this.getTextureUnitCount()); + boolean lit = this.getMaterial() != null; // having material== lit geometry + + //POLYGON_LINE and POLYGON_POINT are not lit + lit = lit && (this.getPolygonAttributes() == null + || this.getPolygonAttributes().getPolygonMode() == PolygonAttributes.POLYGON_FILL); + + boolean hasTextureCoordGen = hasTexture && texCoordGeneration != null; + + boolean texCoordGenModeObjLinear = hasTextureCoordGen + && (texCoordGeneration.getGenMode() == TexCoordGeneration.OBJECT_LINEAR); + build(hasTexture, lit, hasTextureCoordGen, texCoordGenModeObjLinear); } - else + } + } + + private void build(boolean hasTexture, boolean lit, boolean hasTextureCoordGen, boolean texCoordGenModeObjLinear) + { + int shaderKey = (hasTexture ? 1 : 0) + (lit ? 2 : 0) + (hasTextureCoordGen ? 4 : 0) + (texCoordGenModeObjLinear ? 8 : 0); + + GLSLShaderProgram shaderProgram = shaderPrograms.get(new Integer(shaderKey)); + if (shaderProgram == null) + { + String vertexProgram = versionString; + String fragmentProgram = versionString; + if (hasTextureCoordGen) { - fragmentProgram += "color.a = C.a;\n"; + if (texCoordGeneration.getFormat() != 0) + System.out.println("texCoordGeneration.getFormat() must be 0"); + /** + * Generates texture coordinates as a linear function in object coordinates. + public static final int OBJECT_LINEAR = 0; + * Generates texture coordinates as a linear function in eye coordinates. + public static final int EYE_LINEAR = 1; + * Generates texture coordinates using a spherical reflection mapping in eye coordinates. + public static final int SPHERE_MAP = 2; + * Generates texture coordinates that match vertices' normals in eye coordinates. + public static final int NORMAL_MAP = 3; + * Generates texture coordinates that match vertices' reflection vectors in eye coordinates. + public static final int REFLECTION_MAP = 4; + see multitex.vert in examples for sphere map and cube map and google for the others + */ } - fragmentProgram += "gl_FragColor = color;\n"; - - fragmentProgram += "}"; - if (hasTexture) + if (lit) { - if (litTextureShaderProgram == null) + + vertexProgram += vertexAttributeInString + " vec4 glVertex;\n"; + vertexProgram += vertexAttributeInString + " vec4 glColor;\n"; + vertexProgram += vertexAttributeInString + " vec3 glNormal; \n"; + if (hasTexture && !hasTextureCoordGen) { - litTextureShaderProgram = new GLSLShaderProgram() { - @Override - public String toString() + vertexProgram += vertexAttributeInString + " vec2 glMultiTexCoord0;\n"; + } + vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; + vertexProgram += "uniform mat4 glModelViewMatrix;\n"; + vertexProgram += "uniform mat3 glNormalMatrix;\n"; + vertexProgram += "uniform int ignoreVertexColors;\n"; + vertexProgram += "uniform vec4 glLightModelambient;\n"; + vertexProgram += glFrontMaterial; + vertexProgram += glLightSource; + if (hasTextureCoordGen && texCoordGenModeObjLinear) + { + vertexProgram += "uniform vec4 texCoordGenPlaneS;\n"; + vertexProgram += "uniform vec4 texCoordGenPlaneT;\n"; + } + if (hasTexture) + { + vertexProgram += outString + " vec2 glTexCoord0;\n"; + } + + vertexProgram += outString + " vec3 ViewVec;\n"; + vertexProgram += outString + " vec3 N;\n"; + vertexProgram += outString + " vec4 A;\n"; + vertexProgram += outString + " vec4 C;\n"; + vertexProgram += outString + " vec3 emissive;\n"; + vertexProgram += outString + " vec4 lightsD[maxLights];\n"; + vertexProgram += outString + " vec3 lightsS[maxLights];\n"; + vertexProgram += outString + " vec3 lightsLightDir[maxLights];\n"; + vertexProgram += outString + " float shininess;\n"; + if (hasTextureCoordGen) + { + vertexProgram += "vec2 object_linear(vec4 pos, vec4 planeOS, vec4 planeOT)\n"; + vertexProgram += "{\n"; + vertexProgram += " return vec2(pos.x*planeOS.x+pos.y*planeOS.y+pos.z*planeOS.z+pos.w*planeOS.w,pos.x*planeOT.x+pos.y*planeOT.y+pos.z*planeOT.z+pos.w*planeOT.w);\n"; + vertexProgram += "}\n"; + } + + vertexProgram += "void main( void ){\n"; + vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; + vertexProgram += "N = normalize(glNormalMatrix * glNormal);\n"; + if (hasTexture) + { + if (!hasTextureCoordGen) + { + vertexProgram += "glTexCoord0 = glMultiTexCoord0.st;\n"; + } + else + { + if (texCoordGenModeObjLinear) { - return "SimpleShaderAppearance litTextureShaderProgram"; + vertexProgram += "glTexCoord0 = object_linear(glVertex, texCoordGenPlaneS, texCoordGenPlaneT);\n"; } - }; - litTextureShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); - litTextureShaderProgram.setShaderAttrNames(new String[] { "BaseMap" }); + else + { + System.err.println("texCoordGeneration.getGenMode() not supported " + texCoordGeneration.getGenMode()); + } + } + } + + vertexProgram += "vec3 v = vec3(glModelViewMatrix * glVertex);\n"; + + vertexProgram += "ViewVec = -v.xyz;\n"; + + vertexProgram += "A = glLightModelambient * glFrontMaterial.ambient;\n"; + vertexProgram += "if( ignoreVertexColors != 0) \n"; + // objectColor should be used if it is no lighting, and reusing material diffuse appears wrong + vertexProgram += " C = vec4(1,1,1,1);//glFrontMaterial.diffuse; \n"; + vertexProgram += "else \n"; + vertexProgram += " C = glColor; \n"; + + vertexProgram += "emissive = glFrontMaterial.emission.rgb;\n"; + vertexProgram += "shininess = glFrontMaterial.shininess;\n"; + + vertexProgram += "for (int index = 0; index < numberOfLights && index < maxLights; index++) // for all light sources\n"; + vertexProgram += "{ \n"; + vertexProgram += " lightsD[index] = glLightSource[index].diffuse * glFrontMaterial.diffuse; \n"; + vertexProgram += " lightsS[index] = glLightSource[index].specular.rgb * glFrontMaterial.specular;\n"; + vertexProgram += " lightsLightDir[index] = glLightSource[index].position.xyz; \n"; + vertexProgram += "}\n"; + vertexProgram += "}"; + + fragmentProgram += "precision mediump float;\n"; + fragmentProgram += "precision highp int;\n"; + fragmentProgram += "uniform float transparencyAlpha;\n"; + if (hasTexture) + { + fragmentProgram += alphaTestUniforms; + fragmentProgram += inString + " vec2 glTexCoord0;\n"; + fragmentProgram += "uniform sampler2D BaseMap;\n"; } + fragmentProgram += "uniform int numberOfLights;\n"; + fragmentProgram += inString + " vec3 ViewVec;\n"; - setShaderProgram(litTextureShaderProgram); + fragmentProgram += inString + " vec3 N;\n"; - ShaderAttributeSet shaderAttributeSet = new ShaderAttributeSet(); - shaderAttributeSet.put(new ShaderAttributeValue("BaseMap", new Integer(0))); - setShaderAttributeSet(shaderAttributeSet); - } - else - { - if (litFlatShaderProgram == null) + fragmentProgram += inString + " vec4 A;\n"; + fragmentProgram += inString + " vec4 C;\n"; + + fragmentProgram += inString + " vec3 emissive;\n"; + fragmentProgram += inString + " float shininess;\n"; + fragmentProgram += " const int maxLights = 3;\n"; + fragmentProgram += inString + " vec4 lightsD[maxLights]; \n"; + fragmentProgram += inString + " vec3 lightsS[maxLights]; \n"; + fragmentProgram += inString + " vec3 lightsLightDir[maxLights]; \n"; + + fragmentProgram += fragColorDec; + fragmentProgram += "void main( void ){\n "; + if (hasTexture) { - litFlatShaderProgram = new GLSLShaderProgram() { - @Override - public String toString() - { - return "SimpleShaderAppearance litFlatShaderProgram"; - } - }; - litFlatShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); + fragmentProgram += "vec4 baseMap = " + texture2D + "( BaseMap, glTexCoord0.st );\n"; + } + if (hasTexture) + { + fragmentProgram += alphaTestMethod; + } + + fragmentProgram += "vec4 color;\n"; + fragmentProgram += "vec3 albedo = " + (hasTexture ? "baseMap.rgb *" : "") + " C.rgb;\n"; + + fragmentProgram += "vec3 diffuse = A.rgb;\n"; + fragmentProgram += "vec3 spec;\n"; - //System.out.println("vertexProgram " + vertexProgram); - //System.out.println("fragmentProgram " + fragmentProgram); + fragmentProgram += "vec3 normal = N;\n"; + fragmentProgram += "vec3 E = normalize(ViewVec);\n"; + fragmentProgram += "float EdotN = max( dot(normal, E), 0.0 );\n"; + fragmentProgram += "for (int index = 0; index < numberOfLights && index < maxLights; index++) // for all light sources\n"; + fragmentProgram += "{ \n"; + fragmentProgram += " vec3 L = normalize( lightsLightDir[index] );\n"; + fragmentProgram += " //vec3 R = reflect(-L, normal);\n"; + fragmentProgram += " vec3 H = normalize( L + E ); \n"; + fragmentProgram += " float NdotL = max( dot(normal, L), 0.0 );\n"; + fragmentProgram += " float NdotH = max( dot(normal, H), 0.0 ); \n"; + fragmentProgram += " float NdotNegL = max( dot(normal, -L), 0.0 ); \n"; + + fragmentProgram += " diffuse = diffuse + (lightsD[index].rgb * NdotL);\n"; + fragmentProgram += " spec = spec + (lightsS[index] * pow(NdotH, 0.3*shininess));\n"; + fragmentProgram += "}\n"; + + fragmentProgram += "color.rgb = albedo * (diffuse + emissive) + spec;\n"; + if (hasTexture) + { + fragmentProgram += "color.a = C.a * baseMap.a;\n"; } + else + { + fragmentProgram += "color.a = C.a;\n"; + } + + fragmentProgram += "color.a *= transparencyAlpha;\n"; + fragmentProgram += fragColorVar + " = color;\n"; - setShaderProgram(litFlatShaderProgram); + //for debug of the incorrect looking tex coord gen values + //if (hasTexture) + //fragmentProgram += fragColorVar + " = vec4(mod(glTexCoord0.s,1.0),mod(glTexCoord0.t,1.0),0,1);\n"; + + fragmentProgram += "}"; } - } - else - { - if (hasTexture) + else { - if (textureShaderProgram == null) + // not lit + if (hasTexture) { - textureShaderProgram = new GLSLShaderProgram() { - @Override - public String toString() - { - return "SimpleShaderAppearance textureShaderProgram"; - } - }; - String vertexProgram = versionString; - vertexProgram += "attribute vec4 glVertex;\n"; - vertexProgram += "attribute vec2 glMultiTexCoord0;\n"; + vertexProgram += vertexAttributeInString + " vec4 glVertex;\n"; + vertexProgram += vertexAttributeInString + " vec2 glMultiTexCoord0;\n"; vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; - vertexProgram += "varying vec2 glTexCoord0;\n"; + vertexProgram += outString + " vec2 glTexCoord0;\n"; vertexProgram += "void main( void ){\n"; vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; vertexProgram += "glTexCoord0 = glMultiTexCoord0.st;\n"; vertexProgram += "}"; - String fragmentProgram = versionString; fragmentProgram += "precision mediump float;\n"; + fragmentProgram += "uniform float transparencyAlpha;\n"; fragmentProgram += alphaTestUniforms; - fragmentProgram += "varying vec2 glTexCoord0;\n"; + fragmentProgram += inString + " vec2 glTexCoord0;\n"; fragmentProgram += "uniform sampler2D BaseMap;\n"; + fragmentProgram += fragColorDec; fragmentProgram += "void main( void ){\n "; - fragmentProgram += "vec4 baseMap = texture2D( BaseMap, glTexCoord0.st );\n"; + fragmentProgram += "vec4 baseMap = " + texture2D + "( BaseMap, glTexCoord0.st );\n"; fragmentProgram += alphaTestMethod; - fragmentProgram += "gl_FragColor = baseMap;\n"; + fragmentProgram += "baseMap.a *= transparencyAlpha;\n"; + fragmentProgram += fragColorVar + " = baseMap;\n"; fragmentProgram += "}"; - textureShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); - textureShaderProgram.setShaderAttrNames(new String[] { "BaseMap" }); } + else + { + //no lit no texture + vertexProgram += vertexAttributeInString + " vec4 glVertex;\n"; + vertexProgram += vertexAttributeInString + " vec4 glColor;\n"; + vertexProgram += "uniform int ignoreVertexColors;\n"; + vertexProgram += "uniform vec4 objectColor;\n"; + vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; + vertexProgram += outString + " vec4 glFrontColor;\n"; + vertexProgram += "void main( void ){\n"; + vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; + vertexProgram += "if( ignoreVertexColors != 0 )\n"; + vertexProgram += " glFrontColor = objectColor;\n"; + vertexProgram += "else\n"; + vertexProgram += " glFrontColor = glColor;\n"; + vertexProgram += "}"; - setShaderProgram(textureShaderProgram); + fragmentProgram += "precision mediump float;\n"; + fragmentProgram += "uniform float transparencyAlpha;\n"; + fragmentProgram += inString + " vec4 glFrontColor;\n"; + fragmentProgram += fragColorDec; + fragmentProgram += "void main( void ){\n"; + fragmentProgram += fragColorVar + " = glFrontColor;\n"; + fragmentProgram += fragColorVar + ".a *= transparencyAlpha;\n"; + fragmentProgram += "}"; - ShaderAttributeSet shaderAttributeSet = new ShaderAttributeSet(); - shaderAttributeSet.put(new ShaderAttributeValue("BaseMap", new Integer(0))); - setShaderAttributeSet(shaderAttributeSet); + } } - else + // build the shader program and cache it + shaderProgram = new GLSLShaderProgram() { + @Override + public String toString() + { + return "SimpleShaderAppearance " + getName(); + } + }; + shaderProgram.setName("shaderkey = " + shaderKey); + shaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); + vertexShaderSources.put(shaderProgram, vertexProgram); + fragmentShaderSources.put(shaderProgram, fragmentProgram); + + if (hasTexture) { - if (color != null) + if (texCoordGenModeObjLinear) { - PolygonAttributes polyAtt = new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0.0f); - polyAtt.setPolygonOffset(0.1f); - setPolygonAttributes(polyAtt); - LineAttributes lineAtt = new LineAttributes(1, LineAttributes.PATTERN_SOLID, false); - setLineAttributes(lineAtt); + shaderProgram.setShaderAttrNames(new String[] { "BaseMap", "texCoordGenPlaneS", "texCoordGenPlaneT" }); + } + else + { + shaderProgram.setShaderAttrNames(new String[] { "BaseMap" }); + } + } + shaderPrograms.put(new Integer(shaderKey), shaderProgram); - ColoringAttributes colorAtt = new ColoringAttributes(color, ColoringAttributes.FASTEST); - setColoringAttributes(colorAtt); + } - RenderingAttributes ra = new RenderingAttributes(); - ra.setIgnoreVertexColors(true); - setRenderingAttributes(ra); + setShaderProgram(shaderProgram); + vertexShaderSource = vertexShaderSources.get(shaderProgram); + fragmentShaderSource = fragmentShaderSources.get(shaderProgram); - Material mat = new Material(); - setMaterial(mat); + if (hasTexture) + { + ShaderAttributeSet shaderAttributeSet = new ShaderAttributeSet(); + shaderAttributeSet.put(new ShaderAttributeValue("BaseMap", new Integer(0))); + if (texCoordGenModeObjLinear) + { + Vector4f planeS = new Vector4f(); + texCoordGeneration.getPlaneS(planeS); + Vector4f planeT = new Vector4f(); + texCoordGeneration.getPlaneT(planeT); - if (colorLineShaderProgram == null) - { - colorLineShaderProgram = new GLSLShaderProgram() { - @Override - public String toString() - { - return "SimpleShaderAppearance colorLineShaderProgram"; - } - }; - String vertexProgram = versionString; - vertexProgram += "attribute vec4 glVertex;\n"; - vertexProgram += "attribute vec4 glColor;\n"; - vertexProgram += "uniform int ignoreVertexColors;\n"; - vertexProgram += "uniform vec4 objectColor;\n"; - vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; - vertexProgram += "varying vec4 glFrontColor;\n"; - vertexProgram += "void main( void ){\n"; - vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; - vertexProgram += "if( ignoreVertexColors != 0 )\n"; - vertexProgram += " glFrontColor = objectColor;\n"; - vertexProgram += "else\n"; - vertexProgram += " glFrontColor = glColor;\n"; - vertexProgram += "}"; - - String fragmentProgram = versionString; - fragmentProgram += "precision mediump float;\n"; - fragmentProgram += "varying vec4 glFrontColor;\n"; - fragmentProgram += "void main( void ){\n"; - fragmentProgram += "gl_FragColor = glFrontColor;\n"; - fragmentProgram += "}"; - - colorLineShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); - } + shaderAttributeSet.put(new ShaderAttributeValue("texCoordGenPlaneS", planeS)); + shaderAttributeSet.put(new ShaderAttributeValue("texCoordGenPlaneT", planeT)); + } - setShaderProgram(colorLineShaderProgram); + setShaderAttributeSet(shaderAttributeSet); + } - } - else - { - RenderingAttributes ra = new RenderingAttributes(); - setRenderingAttributes(ra); + } - if (flatShaderProgram == null) - { - flatShaderProgram = new GLSLShaderProgram() { - @Override - public String toString() - { - return "SimpleShaderAppearance flatShaderProgram"; - } - }; - String vertexProgram = versionString; - vertexProgram += "attribute vec4 glVertex;\n"; - vertexProgram += "attribute vec4 glColor;\n"; - vertexProgram += "uniform int ignoreVertexColors;\n"; - vertexProgram += "uniform vec4 objectColor;\n"; - vertexProgram += "uniform mat4 glModelViewProjectionMatrix;\n"; - vertexProgram += "varying vec4 glFrontColor;\n"; - vertexProgram += "void main( void ){\n"; - vertexProgram += "gl_Position = glModelViewProjectionMatrix * glVertex;\n"; - vertexProgram += "if( ignoreVertexColors != 0 )\n"; - vertexProgram += " glFrontColor = objectColor;\n"; - vertexProgram += "else\n"; - vertexProgram += " glFrontColor = glColor;\n"; - vertexProgram += "}"; - - String fragmentProgram = versionString; - fragmentProgram += "precision mediump float;\n"; - fragmentProgram += "varying vec4 glFrontColor;\n"; - fragmentProgram += "void main( void ){\n"; - fragmentProgram += "gl_FragColor = glFrontColor;\n"; - fragmentProgram += "}"; - - flatShaderProgram.setShaders(makeShaders(vertexProgram, fragmentProgram)); + @Override + public void setMaterial(Material material) + { + super.setMaterial(material); + rebuildShaders(); + } - } + @Override + public void setColoringAttributes(ColoringAttributes coloringAttributes) + { + super.setColoringAttributes(coloringAttributes); + rebuildShaders(); + } - setShaderProgram(flatShaderProgram); + @Override + public void setTransparencyAttributes(TransparencyAttributes transparencyAttributes) + { + super.setTransparencyAttributes(transparencyAttributes); + rebuildShaders(); + } - } - } + @Override + public void setRenderingAttributes(RenderingAttributes renderingAttributes) + { + super.setRenderingAttributes(renderingAttributes); + rebuildShaders(); + } - } + @Override + public void setPolygonAttributes(PolygonAttributes polygonAttributes) + { + super.setPolygonAttributes(polygonAttributes); + rebuildShaders(); + } + @Override + public void setLineAttributes(LineAttributes lineAttributes) + { + super.setLineAttributes(lineAttributes); + rebuildShaders(); } - private static Shader[] makeShaders(String vertexProgram, String fragmentProgram) + @Override + public void setPointAttributes(PointAttributes pointAttributes) { - Shader[] shaders = new Shader[2]; - shaders[0] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL, Shader.SHADER_TYPE_VERTEX, vertexProgram) { - @Override - public String toString() - { - return "vertexProgram"; - } - }; - shaders[1] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL, Shader.SHADER_TYPE_FRAGMENT, fragmentProgram) { - @Override - public String toString() - { - return "fragmentProgram"; - } - }; - return shaders; + super.setPointAttributes(pointAttributes); + rebuildShaders(); + } + + @Override + public void setTexture(Texture texture) + { + super.setTexture(texture); + rebuildShaders(); + } + + @Override + public void setTextureAttributes(TextureAttributes textureAttributes) + { + super.setTextureAttributes(textureAttributes); + rebuildShaders(); + } + + @Override + public void setTexCoordGeneration(TexCoordGeneration texCoordGeneration) + { + // can't use the super version as it's not supported + //super.setTexCoordGeneration(texCoordGeneration); + this.texCoordGeneration = texCoordGeneration; + rebuildShaders(); + } + + @Override + public void setTextureUnitState(TextureUnitState[] stateArray) + { + System.out.println("SimpleShaderAppearance with textureunitstates in use"); + super.setTextureUnitState(stateArray); + rebuildShaders(); + } + + @Override + public void setTextureUnitState(int index, TextureUnitState state) + { + System.out.println("SimpleShaderAppearance with textureunitstates in use"); + super.setTextureUnitState(index, state); + rebuildShaders(); + } + + /** + * Must implement or clones turn out to be ShaderAppearance + */ + @SuppressWarnings("deprecation") + @Override + public NodeComponent cloneNodeComponent() + { + SimpleShaderAppearance a = new SimpleShaderAppearance(); + a.duplicateNodeComponent(this); + return a; } } |