001: /*
002: * $RCSfile: PhongShadingGLSL.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.6 $
041: * $Date: 2007/02/09 17:21:41 $
042: * $State: Exp $
043: */
044:
045: package org.jdesktop.j3d.examples.glsl_shader;
046:
047: import com.sun.j3d.utils.geometry.Sphere;
048: import com.sun.j3d.utils.shader.StringIO;
049: import com.sun.j3d.utils.universe.*;
050: import javax.media.j3d.*;
051: import javax.swing.JOptionPane;
052: import javax.vecmath.*;
053: import java.awt.GraphicsConfiguration;
054: import java.io.IOException;
055: import org.jdesktop.j3d.examples.Resources;
056:
057: /**
058: *
059: * @author kcr
060: */
061: public class PhongShadingGLSL extends javax.swing.JFrame {
062:
063: // Constants for type of light to use
064: private static final int DIRECTIONAL_LIGHT = 0;
065: private static final int POINT_LIGHT = 1;
066: private static final int SPOT_LIGHT = 2;
067:
068: // Flag indicates type of lights: directional, point, or spot lights.
069: private static int lightType = DIRECTIONAL_LIGHT;
070:
071: private SimpleUniverse univ = null;
072:
073: private ShaderAppearance sApp = null;
074: private ShaderProgram gouraudSP = null;
075: private ShaderProgram phongSP = null;
076:
077: public BranchGroup createSceneGraph() {
078: Color3f eColor = new Color3f(0.0f, 0.0f, 0.0f);
079: Color3f sColor = new Color3f(1.0f, 1.0f, 1.0f);
080: Color3f objColor = new Color3f(0.6f, 0.6f, 0.6f);
081: // Color3f lColor1 = new Color3f(1.0f, 0.0f, 0.0f);
082: // Color3f lColor2 = new Color3f(0.0f, 1.0f, 0.0f);
083: Color3f lColor1 = new Color3f(1.0f, 1.0f, 0.5f);
084: Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f);
085: Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
086:
087: Transform3D t;
088:
089: // Create the root of the branch graph
090: BranchGroup objRoot = new BranchGroup();
091:
092: // Create a Transformgroup to scale all objects so they
093: // appear in the scene.
094: TransformGroup objScale = new TransformGroup();
095: Transform3D t3d = new Transform3D();
096: t3d.setScale(0.5);
097: objScale.setTransform(t3d);
098: objRoot.addChild(objScale);
099:
100: // Create a bounds for the background and lights
101: BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,
102: 0.0, 0.0), 100.0);
103:
104: // Set up the background
105: Background bg = new Background(bgColor);
106: bg.setApplicationBounds(bounds);
107: objRoot.addChild(bg);
108:
109: // Create the TransformGroup node and initialize it to the
110: // identity. Enable the TRANSFORM_WRITE capability so that
111: // our behavior code can modify it at run time. Add it to
112: // the root of the subgraph.
113: TransformGroup objTrans = new TransformGroup();
114: objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
115: objScale.addChild(objTrans);
116:
117: // Create a Sphere object, generate one copy of the sphere,
118: // and add it into the scene graph.
119: sApp = new ShaderAppearance();
120: sApp.setCapability(ShaderAppearance.ALLOW_SHADER_PROGRAM_WRITE);
121: Material m = new Material(objColor, eColor, objColor, sColor,
122: 100.0f);
123: sApp.setMaterial(m);
124:
125: // Create Gouraud and Phong shader programs
126: String vertexProgram = null;
127: String fragmentProgram = null;
128: Shader[] shaders = new Shader[2];
129: String[] attrNames = { "numLights" };
130:
131: try {
132: vertexProgram = StringIO.readFully(Resources
133: .getResource("glsl_shader/gouraud.vert"));
134: fragmentProgram = StringIO.readFully(Resources
135: .getResource("glsl_shader/gouraud.frag"));
136: } catch (IOException e) {
137: throw new RuntimeException(e);
138: }
139: shaders[0] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL,
140: Shader.SHADER_TYPE_VERTEX, vertexProgram);
141: shaders[1] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL,
142: Shader.SHADER_TYPE_FRAGMENT, fragmentProgram);
143: gouraudSP = new GLSLShaderProgram();
144: gouraudSP.setShaders(shaders);
145:
146: try {
147: vertexProgram = StringIO.readFully(Resources
148: .getResource("glsl_shader/phong.vert"));
149: fragmentProgram = StringIO.readFully(Resources
150: .getResource("glsl_shader/phong.frag"));
151: } catch (IOException e) {
152: throw new RuntimeException(e);
153: }
154: shaders[0] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL,
155: Shader.SHADER_TYPE_VERTEX, vertexProgram);
156: shaders[1] = new SourceCodeShader(Shader.SHADING_LANGUAGE_GLSL,
157: Shader.SHADER_TYPE_FRAGMENT, fragmentProgram);
158: phongSP = new GLSLShaderProgram();
159: phongSP.setShaders(shaders);
160:
161: if (gouraudButton.isSelected()) {
162: sApp.setShaderProgram(gouraudSP);
163: } else if (phongButton.isSelected()) {
164: sApp.setShaderProgram(phongSP);
165: }
166: Sphere sph = new Sphere(1.0f, Sphere.GENERATE_NORMALS, 30, sApp);
167: objTrans.addChild(sph);
168:
169: // Create a new Behavior object that will perform the
170: // desired operation on the specified transform and add
171: // it into the scene graph.
172: Transform3D yAxis = new Transform3D();
173: yAxis.rotZ(Math.PI);
174: Alpha rotationAlpha = new Alpha(-1, 10000);
175:
176: RotationInterpolator rotator = new RotationInterpolator(
177: rotationAlpha, objTrans, yAxis, 0.0f,
178: (float) Math.PI * 2.0f);
179: rotator.setSchedulingBounds(bounds);
180: objRoot.addChild(rotator);
181:
182: // Create the transform group node for the each light and initialize
183: // it to the identity. Enable the TRANSFORM_WRITE capability so that
184: // our behavior code can modify it at runtime. Add them to the root
185: // of the subgraph.
186: TransformGroup l1RotTrans = new TransformGroup();
187: l1RotTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
188: objScale.addChild(l1RotTrans);
189:
190: TransformGroup l2RotTrans = new TransformGroup();
191: l2RotTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
192: objScale.addChild(l2RotTrans);
193:
194: // Create transformations for the positional lights
195: t = new Transform3D();
196: Vector3d lPos1 = new Vector3d(0.0, 0.0, 2.0);
197: t.set(lPos1);
198: TransformGroup l1Trans = new TransformGroup(t);
199: l1RotTrans.addChild(l1Trans);
200:
201: // t = new Transform3D();
202: // Vector3d lPos2 = new Vector3d(0.5, 0.8, 2.0);
203: // t.set(lPos2);
204: // TransformGroup l2Trans = new TransformGroup(t);
205: // l2RotTrans.addChild(l2Trans);
206:
207: // Create Geometry for point lights
208: ColoringAttributes caL1 = new ColoringAttributes();
209: // ColoringAttributes caL2 = new ColoringAttributes();
210: caL1.setColor(lColor1);
211: // caL2.setColor(lColor2);
212: Appearance appL1 = new Appearance();
213: // Appearance appL2 = new Appearance();
214: appL1.setColoringAttributes(caL1);
215: // appL2.setColoringAttributes(caL2);
216: l1Trans.addChild(new Sphere(0.05f, appL1));
217: // l2Trans.addChild(new Sphere(0.05f, appL2));
218:
219: // Create lights
220: AmbientLight aLgt = new AmbientLight(alColor);
221:
222: Light lgt1 = null;
223: // Light lgt2 = null;
224:
225: Point3f lPoint = new Point3f(0.0f, 0.0f, 0.0f);
226: Point3f atten = new Point3f(1.0f, 0.0f, 0.0f);
227: Vector3f lDirect1 = new Vector3f(lPos1);
228: // Vector3f lDirect2 = new Vector3f(lPos2);
229: lDirect1.negate();
230: // lDirect2.negate();
231:
232: switch (lightType) {
233: case DIRECTIONAL_LIGHT:
234: lgt1 = new DirectionalLight(lColor1, lDirect1);
235: // lgt2 = new DirectionalLight(lColor2, lDirect2);
236: break;
237: case POINT_LIGHT:
238: assert false : "can't get here";
239: lgt1 = new PointLight(lColor1, lPoint, atten);
240: // lgt2 = new PointLight(lColor2, lPoint, atten);
241: break;
242: case SPOT_LIGHT:
243: assert false : "can't get here";
244: lgt1 = new SpotLight(lColor1, lPoint, atten, lDirect1,
245: 25.0f * (float) Math.PI / 180.0f, 10.0f);
246: // lgt2 = new SpotLight(lColor2, lPoint, atten, lDirect2,
247: // 25.0f * (float)Math.PI / 180.0f, 10.0f);
248: break;
249: }
250:
251: // Set the influencing bounds
252: aLgt.setInfluencingBounds(bounds);
253: lgt1.setInfluencingBounds(bounds);
254: // lgt2.setInfluencingBounds(bounds);
255:
256: // Add the lights into the scene graph
257: objScale.addChild(aLgt);
258: l1Trans.addChild(lgt1);
259: // l2Trans.addChild(lgt2);
260:
261: // Create a new Behavior object that will perform the desired
262: // operation on the specified transform object and add it into the
263: // scene graph.
264: yAxis = new Transform3D();
265: Alpha rotor1Alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0,
266: 0, 4000, 0, 0, 0, 0, 0);
267: RotationInterpolator rotator1 = new RotationInterpolator(
268: rotor1Alpha, l1RotTrans, yAxis, 0.0f,
269: (float) Math.PI * 2.0f);
270: rotator1.setSchedulingBounds(bounds);
271: l1RotTrans.addChild(rotator1);
272:
273: // Create a new Behavior object that will perform the desired
274: // operation on the specified transform object and add it into the
275: // scene graph.
276: Alpha rotor2Alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0,
277: 0, 1000, 0, 0, 0, 0, 0);
278: RotationInterpolator rotator2 = new RotationInterpolator(
279: rotor2Alpha, l2RotTrans, yAxis, 0.0f, 0.0f);
280: bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
281: rotator2.setSchedulingBounds(bounds);
282: l2RotTrans.addChild(rotator2);
283:
284: return objRoot;
285: }
286:
287: private Canvas3D initScene() {
288: GraphicsConfiguration config = SimpleUniverse
289: .getPreferredConfiguration();
290:
291: Canvas3D c = new Canvas3D(config);
292:
293: univ = new SimpleUniverse(c);
294:
295: // Add a ShaderErrorListener
296: univ.addShaderErrorListener(new ShaderErrorListener() {
297: public void errorOccurred(ShaderError error) {
298: error.printVerbose();
299: JOptionPane.showMessageDialog(PhongShadingGLSL.this ,
300: error.toString(), "ShaderError",
301: JOptionPane.ERROR_MESSAGE);
302: }
303: });
304:
305: // This will move the ViewPlatform back a bit so the
306: // objects in the scene can be viewed.
307: univ.getViewingPlatform().setNominalViewingTransform();
308:
309: BranchGroup scene = createSceneGraph();
310: univ.addBranchGraph(scene);
311:
312: return c;
313: }
314:
315: /**
316: * Creates new form PhongShadingGLSL
317: */
318: public PhongShadingGLSL() {
319: // Initialize the GUI components
320: initComponents();
321:
322: // Create the scene and add the Canvas3D to the drawing panel
323: Canvas3D c = initScene();
324: drawingPanel.add(c, java.awt.BorderLayout.CENTER);
325: }
326:
327: // ----------------------------------------------------------------
328:
329: /** This method is called from within the constructor to
330: * initialize the form.
331: * WARNING: Do NOT modify this code. The content of this method is
332: * always regenerated by the Form Editor.
333: */
334: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
335: private void initComponents() {
336: java.awt.GridBagConstraints gridBagConstraints;
337:
338: shaderButtonGroup = new javax.swing.ButtonGroup();
339: guiPanel = new javax.swing.JPanel();
340: jPanel1 = new javax.swing.JPanel();
341: gouraudButton = new javax.swing.JRadioButton();
342: phongButton = new javax.swing.JRadioButton();
343: drawingPanel = new javax.swing.JPanel();
344: jMenuBar1 = new javax.swing.JMenuBar();
345: fileMenu = new javax.swing.JMenu();
346: exitMenuItem = new javax.swing.JMenuItem();
347:
348: setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
349: setTitle("Phong Shading Test");
350: guiPanel.setLayout(new java.awt.GridBagLayout());
351:
352: jPanel1.setLayout(new java.awt.GridBagLayout());
353:
354: jPanel1.setBorder(javax.swing.BorderFactory
355: .createTitledBorder("Shader"));
356: shaderButtonGroup.add(gouraudButton);
357: gouraudButton.setSelected(true);
358: gouraudButton.setText("Per-Vertex Lighting (Gouraud)");
359: gouraudButton.setBorder(javax.swing.BorderFactory
360: .createEmptyBorder(0, 0, 0, 0));
361: gouraudButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
362: gouraudButton
363: .addActionListener(new java.awt.event.ActionListener() {
364: public void actionPerformed(
365: java.awt.event.ActionEvent evt) {
366: gouraudButtonActionPerformed(evt);
367: }
368: });
369:
370: gridBagConstraints = new java.awt.GridBagConstraints();
371: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
372: gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
373: jPanel1.add(gouraudButton, gridBagConstraints);
374:
375: shaderButtonGroup.add(phongButton);
376: phongButton.setText("Per-Pixel Lighting (Phong)");
377: phongButton.setBorder(javax.swing.BorderFactory
378: .createEmptyBorder(0, 0, 0, 0));
379: phongButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
380: phongButton
381: .addActionListener(new java.awt.event.ActionListener() {
382: public void actionPerformed(
383: java.awt.event.ActionEvent evt) {
384: phongButtonActionPerformed(evt);
385: }
386: });
387:
388: gridBagConstraints = new java.awt.GridBagConstraints();
389: gridBagConstraints.gridx = 0;
390: gridBagConstraints.gridy = 1;
391: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
392: gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
393: jPanel1.add(phongButton, gridBagConstraints);
394:
395: gridBagConstraints = new java.awt.GridBagConstraints();
396: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
397: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
398: guiPanel.add(jPanel1, gridBagConstraints);
399:
400: getContentPane().add(guiPanel, java.awt.BorderLayout.NORTH);
401:
402: drawingPanel.setLayout(new java.awt.BorderLayout());
403:
404: drawingPanel.setPreferredSize(new java.awt.Dimension(500, 500));
405: getContentPane()
406: .add(drawingPanel, java.awt.BorderLayout.CENTER);
407:
408: fileMenu.setText("File");
409: exitMenuItem.setText("Exit");
410: exitMenuItem
411: .addActionListener(new java.awt.event.ActionListener() {
412: public void actionPerformed(
413: java.awt.event.ActionEvent evt) {
414: exitMenuItemActionPerformed(evt);
415: }
416: });
417:
418: fileMenu.add(exitMenuItem);
419:
420: jMenuBar1.add(fileMenu);
421:
422: setJMenuBar(jMenuBar1);
423:
424: pack();
425: }// </editor-fold>//GEN-END:initComponents
426:
427: private void phongButtonActionPerformed(
428: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_phongButtonActionPerformed
429: sApp.setShaderProgram(phongSP);
430: }//GEN-LAST:event_phongButtonActionPerformed
431:
432: private void gouraudButtonActionPerformed(
433: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gouraudButtonActionPerformed
434: sApp.setShaderProgram(gouraudSP);
435: }//GEN-LAST:event_gouraudButtonActionPerformed
436:
437: private void exitMenuItemActionPerformed(
438: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
439: System.exit(0);
440: }//GEN-LAST:event_exitMenuItemActionPerformed
441:
442: /**
443: * @param args the command line arguments
444: */
445: public static void main(String args[]) {
446: java.awt.EventQueue.invokeLater(new Runnable() {
447: public void run() {
448: new PhongShadingGLSL().setVisible(true);
449: }
450: });
451: }
452:
453: // Variables declaration - do not modify//GEN-BEGIN:variables
454: private javax.swing.JPanel drawingPanel;
455: private javax.swing.JMenuItem exitMenuItem;
456: private javax.swing.JMenu fileMenu;
457: private javax.swing.JRadioButton gouraudButton;
458: private javax.swing.JPanel guiPanel;
459: private javax.swing.JMenuBar jMenuBar1;
460: private javax.swing.JPanel jPanel1;
461: private javax.swing.JRadioButton phongButton;
462: private javax.swing.ButtonGroup shaderButtonGroup;
463: // End of variables declaration//GEN-END:variables
464:
465: }
|