Posted by
Ralph Martin on
Feb 24, 2011; 10:19am
URL: https://forum.jogamp.org/Textures-program-works-on-one-machine-but-not-on-another-tp2566528.html
I've tried to port ToyShader ( see
http://projects.autonomy.net.au/ai/browser/POC/OpenGL/TimLambertsToys/ToyShader.java?rev=) to JOGL2. It all seems to work except as follows:
- MacBook Pro - works perfectly
- Mac Pro - textures displayed incorrectly
The main difference between these two is that the MacBook has an Nvidia graphics card, the Mac Pro has ATI. Otherwise,
- the exact same JOGL2 library files are used on each
- the exact same Netbeans project is used on each to compile and run
I'm reluctant to report this as a bug, as I may have done something wrong in my porting. I'd like someone to have a look at the code first, and see if there's an obvious mistake, before I report a bug. Also, the issue probably needs stripping down to essentials for a bug report.
Here's the code for the main class, which is the one dealing with textures.
package org.yourorghere;
/**
* Toy plaything for me to learn JOGL/OpenGL
* See effects of different OpneGL settings and shaders
*/
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.GL2;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.texture.*;
import java.io.*;
import java.nio.*;
public class ToyShader2 extends JFrame
implements GLEventListener, KeyListener {
ShapeManager shapeManager;
FPSAnimator animator;
trackball ball = new trackball();
int aWidth = 1000;
int aHeight = 1000;
JCheckBoxMenuItem wireframe;
JCheckBoxMenuItem specular;
JCheckBoxMenuItem headLight;
JCheckBoxMenuItem directionalLight;
JCheckBoxMenuItem smooth;
JCheckBoxMenuItem backFaceCull;
JCheckBoxMenuItem zBuffer;
JCheckBoxMenuItem twoSided;
JCheckBoxMenuItem useShader;
JCheckBoxMenuItem useTexture;
JRadioButtonMenuItem[] levelItems, shaderItems, textureItems;
//associates shader names with programs
Map<String, Integer> programs = new HashMap<String, Integer>();
String shader; //name of current shader
static final String shaderDir = "shaders";
//associates texture names with Textures
Map<String, Texture> textures = new HashMap<String, Texture>();
String texture; //name of current texture
static final String textureDir = "textures";
private float time = 0.0f; // keeps track of time -- passed to shaders
private int timeLoc; // location of time variable
public static void main(String[] args) {
ToyShader2 t = new ToyShader2();
//exit if frame's close box is clicked
t.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.exit(0);
}
public void windowClosing(WindowEvent e) {
windowClosed(e);
}
});
}
int level;
/* These functions are "callbacks" for events we are
not interested in
*/
public void keyTyped(KeyEvent evt) {
}
public void keyReleased(KeyEvent evt) {
}
public ToyShader2() {
super("ToyShader");
GLProfile glp = GLProfile.getDefault();
// Specifies a set of OpenGL capabilities, based on your profile.
GLCapabilities caps = new GLCapabilities(glp);
GLCanvas glc = new GLCanvas(caps);
add("Center", glc);
glc.setSize(aWidth, aHeight);
JPopupMenu.setDefaultLightWeightPopupEnabled(false); //so menus appear above GLCanvas
JMenuBar menubar = new JMenuBar();
setJMenuBar(menubar);
shapeManager = new ShapeManager();
menubar.add(shapeManager.getMenu());
JMenu options = new JMenu("Options");
menubar.add(options);
wireframe = new JCheckBoxMenuItem("Wireframe");
options.add(wireframe);
headLight = new JCheckBoxMenuItem("Head Light");
options.add(headLight);
headLight.setSelected(true);
directionalLight = new JCheckBoxMenuItem("Directional Light");
options.add(directionalLight);
specular = new JCheckBoxMenuItem("Specular Lighting");
options.add(specular);
twoSided = new JCheckBoxMenuItem("Two-sided Lighting");
options.add(twoSided);
backFaceCull = new JCheckBoxMenuItem("Back-face Cull");
options.add(backFaceCull);
zBuffer = new JCheckBoxMenuItem("Use Z Buffer");
options.add(zBuffer);
zBuffer.setSelected(true);
smooth = new JCheckBoxMenuItem("Smooth Shading");
options.add(smooth);
useShader = new JCheckBoxMenuItem("Use Shader");
options.add(useShader);
useTexture = new JCheckBoxMenuItem("Use Texture");
options.add(useTexture);
JMenu levels = new JMenu("Level");
ButtonGroup lbg = new ButtonGroup();
levelItems = new JRadioButtonMenuItem[7];
for (int i = 0; i < levelItems.length; i++) {
levelItems[i] = new JRadioButtonMenuItem(i + "");
levels.add(levelItems[i]);
lbg.add(levelItems[i]);
levelItems[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
level = Integer.parseInt(e.getActionCommand());
}
});
}
level = 2;
levelItems[level].setSelected(true);
menubar.add(levels);
String[] names = ShaderUtil.listShaders(shaderDir);
JMenu shaders = new JMenu("Shader");
ButtonGroup sbg = new ButtonGroup();
shaderItems = new JRadioButtonMenuItem[names.length];
if (names != null) {
for (int i = 0; i < names.length; i++) {
// strip off ".vert" suffix
String thisname = names[i].substring(0, names[i].length() - 5);
shaderItems[i] = new JRadioButtonMenuItem(thisname);
shaders.add(shaderItems[i]);
sbg.add(shaderItems[i]);
shaderItems[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
shader = e.getActionCommand();
}
});
}
}
shaderItems[0].setSelected(true);
shader = shaderItems[0].getActionCommand();
menubar.add(shaders);
//texture menu -- we look for .png files in the texture directory.
File dir = new File(textureDir);
names = dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
String lowname = name.toLowerCase();
return lowname.endsWith(".png") || lowname.endsWith(".jpg");
}
});
JMenu textures = new JMenu("Texture");
ButtonGroup tbg = new ButtonGroup();
textureItems = new JRadioButtonMenuItem[names.length];
if (names != null) {
for (int i = 0; i < names.length; i++) {
textureItems[i] = new JRadioButtonMenuItem(names[i]);
textures.add(textureItems[i]);
tbg.add(textureItems[i]);
textureItems[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
texture = e.getActionCommand();
}
});
}
}
textureItems[0].setSelected(true);
texture = textureItems[0].getActionCommand();
menubar.add(textures);
ball.listen(glc);
glc.addGLEventListener(this);
glc.addKeyListener(this);
addKeyListener(this);
animator = new FPSAnimator(glc, 100); //animate at 30 fps
animator.start();
pack(); //work out sizes of all Components
setVisible(true);
}
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(0.2f, 0.3f, 0.2f, 1.0f);
}
public void keyPressed(KeyEvent evt) {
if (evt.getKeyChar() == 'q') {
animator.stop();
System.exit(0);
}
if (evt.getKeyChar() == 's') {
specular.setSelected(!specular.isSelected()); //toggle
}
if (evt.getKeyChar() == 'r') {
smooth.setSelected(!smooth.isSelected()); //toggle
}
if (evt.getKeyChar() == 'l') {
twoSided.setSelected(!twoSided.isSelected()); //toggle
}
if (evt.getKeyChar() == '+' && level < levelItems.length - 1) {
levelItems[++level].setSelected(true);
}
if (evt.getKeyChar() == '-' && level > 0) {
levelItems[--level].setSelected(true);
}
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL2 gl = drawable.getGL().getGL2();
gl.glViewport(x, y, width, height);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-2, 2, -2, 2, -5, 10);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glEnable(GL2.GL_AUTO_NORMAL);
aWidth = width;
aHeight = height;
}
public void display(GLAutoDrawable drawable) {
float[] teapotMat = {0.6f, 0.6f, 0.6f, 1.0f};
float[] teapotSpec = {0.8f, 0.8f, 0.8f, 1.0f};
float[] zero = {0.0f, 0.0f, 0.0f, 1.0f};
GL2 gl = drawable.getGL().getGL2();
gl.glShadeModel(smooth.isSelected() ? GL2.GL_SMOOTH : GL2.GL_FLAT);
gl.glLightModeli(GL2.GL_LIGHT_MODEL_TWO_SIDE, twoSided.isSelected() ? 1 : 0);
if (zBuffer.isSelected()) {
gl.glEnable(GL2.GL_DEPTH_TEST);
} else {
gl.glDisable(GL2.GL_DEPTH_TEST);
}
if (backFaceCull.isSelected()) {
gl.glEnable(GL2.GL_CULL_FACE);
} else {
gl.glDisable(GL2.GL_CULL_FACE);
}
gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT);
// gl.glColor3f(1.0f, 1.0f, 1.0f);
float[] hlightpos = {0.0f, 0.0f, 1.0f, 0.0f};
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, hlightpos, 0);
gl.glEnable(GL2.GL_LIGHTING);
if (headLight.isSelected()) {
gl.glEnable(GL2.GL_LIGHT0);
} else {
gl.glDisable(GL2.GL_LIGHT0);
}
gl.glEnable(GL2.GL_NORMALIZE); //scale normals to have length 1
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
gl.glMultMatrixf(ball.getRotMatrix(), 0);
float[] dlightpos = {1.0f, 1.0f, 1.0f, 0.0f};
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, dlightpos, 0);
float[] dcolour = {0.6f, 0.6f, 0.6f, 0.0f};
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, dcolour, 0);
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_SPECULAR, dcolour, 0);
if (directionalLight.isSelected()) {
gl.glEnable(GL2.GL_LIGHT1);
} else {
gl.glDisable(GL2.GL_LIGHT1);
}
gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE, teapotMat, 0);
if (specular.isSelected()) {
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, teapotSpec, 0);
gl.glMateriali(GL2.GL_FRONT, GL2.GL_SHININESS, 80);
} else {
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, zero, 0);
gl.glMateriali(GL2.GL_FRONT, GL2.GL_SHININESS, 0);
}
if (wireframe.isSelected()) {
gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
} else {
gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
}
if (useShader.isSelected()) {
//use vertex and fragment shaders
Integer programObject = programs.get(shader);
if (programObject == null) { //need to load shaders into opengl
int program = ShaderUtil.makeShaders(gl, shaderDir, shader);
timeLoc = gl.glGetUniformLocation(program, "time");
programObject = new Integer(program);
programs.put(shader, programObject);
}
gl.glUseProgram(programObject.intValue());
//tell shaders the time
gl.glUniform1f(timeLoc, time);
time += 1;
} else {
if (gl.isFunctionAvailable("glUseProgram")) {
gl.glUseProgram(0);
}
}
if (useTexture.isSelected()) {
//apply specular lighting after texturing
gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SEPARATE_SPECULAR_COLOR);
//enable texturing
gl.glEnable(GL2.GL_TEXTURE_2D);
Texture tex = textures.get(texture);
if (tex == null) { //need to load texture
tex = loadTexture(textureDir + File.separator + texture);
textures.put(texture, tex);
}
tex.enable();
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_REPEAT);
gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE,
GL2.GL_MODULATE);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER,
GL2.GL_LINEAR);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER,
GL2.GL_LINEAR_MIPMAP_LINEAR);
tex.bind();
} else {
gl.glDisable(GL2.GL_TEXTURE_2D);
}
shapeManager.display(gl, level, wireframe.isSelected());
gl.glPopMatrix();
}
/** This method handles things if display depth changes */
public void displayChanged(GLAutoDrawable drawable,
boolean modeChanged,
boolean deviceChanged) {
}
public void dispose(GLAutoDrawable drawable) {
}
/** Load a texture from a file */
Texture loadTexture(String filename) {
Texture texture = null;
try {
texture = TextureIO.newTexture(new File(filename), true);
} catch (Exception e) {
e.printStackTrace();
}
return (texture);
}
}