Basic GLSL shaders not working - java
So I've tried to follow some tutorials on OpenGL and GLSL. I'm writing them in Java, using JOGL2, Original is in C++ though. All code compiles without any problems, shader preview in Shader designer even shows right effect, but when I run my app, it only draws blank white triangle. I can't find where am I making a mistake at all-.- btw my graphics card is Geforce GT330M, supports OpenGL 3.3, GLSL 3.30. newest drivers installed, so that shouldnt be a problem I guess.
My code for loading and creating a shader:
package OpenGL33.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import javax.media.opengl.GL3;
public class ShaderUtils {
public int createProgram(GL3 gl, String vertexSource, String fragmentSource) throws IOException{
int v = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
int f = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
String[] strings;
/*
* vertex shader
*/
strings = loadResource(vertexSource);
gl.glShaderSource(v, strings.length, strings, (int[]) null, 0);
gl.glCompileShader(v);
/*
* fragment shader
*/
strings = loadResource(fragmentSource);
gl.glShaderSource(f, strings.length, strings, (int[]) null, 0);
gl.glCompileShader(f);
/*
* Create shader program and attach shaders
*/
int program = gl.glCreateProgram();
gl.glAttachShader(program, v);
gl.glAttachShader(program, f);
gl.glLinkProgram(program);
gl.glValidateProgram(program);
return program;
}
private String[] loadResource(String resource) throws IOException{
BufferedReader reader;
ArrayList<String> input = new ArrayList<String>();
String line;
reader = new BufferedReader(new InputStreamReader(getClass().getResource(resource).openStream()));
while ((line = reader.readLine()) != null) {
input.add(line);
}
String[] strings = new String[input.size()];
input.toArray(strings);
return strings;
}
}
Vertex shader:
#version 330
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
Fragment shader:
#version 330
out vec4 outputColor;
void main()
{
float lerpValue = gl_FragCoord.y / 500.0f;
outputColor = mix(vec4(1.0f, 1.0f, 1.0f, 1.0f),
vec4(0.0f, 0.0f, 0.0f, 1.0f), lerpValue);
}
and OpenGlListener class:
package OpenGL33;
import OpenGL33.Utils.ShaderUtils;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.gl2.GLUT;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.opengl.GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
class OpenGlListener implements GLEventListener{
private GLU glu = new GLU();
private GLUT glut = new GLUT();
// vertex buffer
private FloatBuffer vertices;
private int[] verticesBuffer = new int[1];
private int shaderProgram;
private ShaderUtils sUtils;
// triangle coords
public static final float[] vertexPositions = {
0.0f, 0.5f, 0.0f, 1.0f,
0.5f, -0.366f, 0.0f, 1.0f,
-0.5f, -0.366f, 0.0f, 1.0f};
public OpenGlListener(){
sUtils = new ShaderUtils();
}
public void initializeVertexBuffer(GLAutoDrawable drawable){
GL3 gl = drawable.getGL().getGL3bc();
vertices = Buffers.newDirectFloatBuffer(vertexPositions.length);
vertices.put(vertexPositions);
vertices.position(0);
gl.glGenBuffers(1, verticesBuffer, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, verticesBuffer[0]);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertexPositions.length * 4 * Buffers.SIZEOF_FLOAT, vertices, GL3.GL_STATIC_DRAW);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
}
#Override
public void init(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
// check VBO support
if(!gl.isExtensionAvailable("GL_ARB_vertex_buffer_object")){
System.err.println("Error - missing VBO support");
}
// load shaders
try{
//tutorial 1
shaderProgram = sUtils.createProgram(gl, "/resources/shaders/FragPosition.vert", "/resources/shaders/FragPosition.frag");
//tutorial 2
//shaderProgram = sUtils.createProgram(gl, "/resources/shaders/MultiInput.vert", "/resources/shaders/MultiInput.frag");
}
catch (IOException ex) {
Logger.getLogger(OpenGlListener.class.getName()).log(Level.SEVERE, null, ex);
}
initializeVertexBuffer(drawable);
}
#Override
public void dispose(GLAutoDrawable drawable) {
//To change body of generated methods, choose Tools | Templates.
}
#Override
public void display(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
gl.glUseProgram(shaderProgram);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, verticesBuffer[0]);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 4, GL3.GL_FLOAT, false, 0, 0);
gl.glDrawArrays(GL3.GL_TRIANGLES, 0, 3);
gl.glDisableVertexAttribArray(0);
gl.glUseProgram(0);
drawable.swapBuffers();
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL3 gl = drawable.getGL().getGL3bc();
gl.glViewport(0, 0, width, height);
}
}
App runs in swing window, drawing in GLJPanel.
Related
GP/GPU : ping pong technique with JOGL
I've tried to implement an reaction-diffusion model on GPU with JOGL and GLSL. I use a ping pong technique with 2 FramebufferObject ( I've tried too with one FBO and 2 Colors attachements without success). Shader seems correct since I've tried it in unity (with some adaptations) and it works. After one week of trying many things, i'm completely out of idea to make this code works. I'm really not specialist of JOGL, so maybe i miss something evident. The result is an image which becomes white with time : no reaction-diffusion behaviors and I don't understand why ! Thanks in advance for helps. Here is my code : package gpu2; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.nio.IntBuffer; import java.nio.FloatBuffer; import java.io.File; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.util.FPSAnimator; import com.jogamp.opengl.GLFBODrawable; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Colorbuffer; import com.jogamp.opengl.FBObject.ColorAttachment; import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderUtil; import com.jogamp.opengl.util.GLBuffers; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLOffscreenAutoDrawable; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import com.jogamp.opengl.GLDrawableFactory; import static com.jogamp.opengl.GL.*; // GL constants import static com.jogamp.opengl.GL2.*; // GL2 constants import gpu2.ModelParam; /** * JOGL 2.0 Program Template (GLCanvas) * This is a "Component" which can be added into a top-level "Container". * It also handles the OpenGL events to render graphics. */ #SuppressWarnings("serial") public class JOGL2Setup_GLCanvas extends GLCanvas implements GLEventListener { // Define constants for the top-level container private static String TITLE = "JOGL 2.0 Setup (GLCanvas)"; // window's title private static final int CANVAS_WIDTH = 512; // width of the drawable private static final int CANVAS_HEIGHT = 512; // height of the drawable private static final int FPS = 30; // animator's target frames per second private final float[] canvasVertices = { -1f, -1f, 0.0f, -1f, 1f, 0.0f, 1f, -1f, 0.0f, 1f, 1f, 0.0f, }; private final float[] canvasTexCoords = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; /** The entry main() method to setup the top-level container and animator */ public static void main(String[] args) { // Run the GUI codes in the event-dispatching thread for thread safety SwingUtilities.invokeLater(new Runnable() { #Override public void run() { // Create the OpenGL rendering canvas GLCanvas canvas = new JOGL2Setup_GLCanvas(); canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT)); // Create a animator that drives canvas' display() at the specified FPS. final FPSAnimator animator = new FPSAnimator(canvas, FPS, true); // Create the top-level container final JFrame frame = new JFrame(); // Swing's JFrame or AWT's Frame frame.getContentPane().add(canvas); frame.addWindowListener(new WindowAdapter() { #Override public void windowClosing(WindowEvent e) { // Use a dedicate thread to run the stop() to ensure that the // animator stops before program exits. new Thread() { #Override public void run() { if (animator.isStarted()) animator.stop(); System.exit(0); } }.start(); } }); frame.setTitle(TITLE); frame.pack(); frame.setVisible(true); animator.start(); // start the animation loop } }); } // Setup OpenGL Graphics Renderer private GLU glu; // for the GL Utility private GL2 gl; //OpenGl data private int vboVertices; private int vboTextCoord; private Texture textureFile; private FBObject fbo[]; private ShaderProgram shaderCompute; private ShaderProgram shaderVisu; private ShaderProgram shaderComputeInit; private int currentSourceBuffer = 0; private int currentDestBuffer = 1; private int currentFrame = 0; private int maxFrameCount = 5000000; private float clearUniform = 0; ModelParam params = new ModelParam(); public JOGL2Setup_GLCanvas() { this.addGLEventListener(this); } #Override public void init(GLAutoDrawable drawable) { gl = drawable.getGL().getGL2(); // get the OpenGL graphics context glu = new GLU(); // get GL Utilities gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set background (clear) color gl.glEnable(GL_TEXTURE_2D); gl.glEnable( GL_COLOR_MATERIAL ); gl.glEnable( GL_FRAMEBUFFER ); gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NEAREST); // best perspective correction viewOrtho(gl); gl.glViewport(0,0,CANVAS_WIDTH,CANVAS_HEIGHT); int[] buffers = new int[2]; gl.glGenBuffers(2, buffers, 0); vboVertices = buffers[0]; vboTextCoord = buffers[1]; gl.glBindBuffer(GL_ARRAY_BUFFER, vboVertices); gl.glBufferData(GL_ARRAY_BUFFER, canvasVertices.length*(Float.SIZE/Byte.SIZE)*3, FloatBuffer.wrap(canvasVertices), GL_STATIC_DRAW); gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord); gl.glBufferData(GL_ARRAY_BUFFER, canvasTexCoords.length*(Float.SIZE/Byte.SIZE)*2, FloatBuffer.wrap(canvasTexCoords), GL_STATIC_DRAW); gl.glBindBuffer( GL_ARRAY_BUFFER, 0 ); // ------------ create Texture Source------------------------ textureFile = initializeTexture(); if (textureFile==null) { System.out.println("cannot load texture from disk"); } // ------------ load shaders ------------------------ shaderCompute = loadShader(gl, "compute.vsh", "compute.fsh"); shaderComputeInit = loadShader(gl, "compute.vsh", "computeInit.fsh"); shaderVisu = loadShader(gl, "visu.vsh", "visu.fsh"); // ------------ create FBO ------------------------ initFBO(); } /** * Called back by the animator to perform rendering. */ #Override public void display(GLAutoDrawable drawable) { if (currentFrame < maxFrameCount) { prepareNextStep(); renderToFBO(); currentFrame++; } renderFBOToScreen(); } private void prepareNextStep() { currentSourceBuffer = 1 - currentSourceBuffer; currentDestBuffer = 1 - currentDestBuffer; } private void renderToFBO() { fbo[currentDestBuffer].bind(gl); //gl.glClear(GL_COLOR_BUFFER_BIT); viewOrtho(gl); shaderCompute.useProgram(gl, true); setShaderUniformFloat(gl, shaderCompute.program(), "diffuseU", 0.211f); setShaderUniformFloat(gl, shaderCompute.program(), "diffuseV", 0.088f); setShaderUniformFloat(gl, shaderCompute.program(), "feed", 0.007f); setShaderUniformFloat(gl, shaderCompute.program(), "kill", 0.08f); setShaderUniformFloat(gl, shaderCompute.program(), "Tech", 1f); setShaderUniformFloat(gl, shaderCompute.program(), "currentFrame", currentFrame); setShaderUniformFloat2(gl, shaderCompute.program(), "resolution", CANVAS_WIDTH, CANVAS_HEIGHT); drawDataBuffer(shaderCompute, true); shaderCompute.useProgram(gl, false); fbo[currentDestBuffer].unbind(gl); } void drawDataBuffer(ShaderProgram currentShader, boolean sencondImage) { // --- draw vbo gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); //textcoords gl.glBindBuffer(GL_ARRAY_BUFFER,vboTextCoord); gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); //vertices gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices ); gl.glVertexPointer(3, GL_FLOAT, 0, 0); //activate texture data from last fbo final FBObject.Colorbuffer texSource = (FBObject.Colorbuffer) fbo[currentSourceBuffer].getColorbuffer(0); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D, texSource.getName()); setShaderUniform1i(gl, currentShader.program(), "textureData", 0); if (sencondImage) { //activate texture with image from file gl.glActiveTexture(GL_TEXTURE1); gl.glBindTexture(GL_TEXTURE_2D, textureFile.getTextureObject()); textureFile.bind(gl); setShaderUniform1i(gl, currentShader.program(), "textureImage", 1); } //draw buffer on screens gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3); //disable texture image if (sencondImage) { gl.glActiveTexture(GL_TEXTURE1); textureFile.disable(gl); } //disable texture data gl.glActiveTexture(GL_TEXTURE0); gl.glDisable(texSource.getName()); gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL_VERTEX_ARRAY); } public void renderFBOToScreen() { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear color and depth buffers gl.glLoadIdentity(); // reset the model-view matrix viewOrtho(gl); gl.glEnable(GL_TEXTURE_2D); final FBObject.Colorbuffer tex0 = (FBObject.Colorbuffer) fbo[currentDestBuffer].getColorbuffer(0); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D, tex0.getName()); //activate shader shaderVisu.useProgram(gl, true); // --- draw vbo gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); //textcoords gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord); gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); //vertices gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices ); gl.glVertexPointer(3, GL_FLOAT, 0, 0); //draw buffer on screens gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3); gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL_VERTEX_ARRAY); gl.glBindBuffer( GL_ARRAY_BUFFER, 0 ); //desactivate shader shaderVisu.useProgram(gl, false); } private void initFBO() { try { gl.glEnable(GL_TEXTURE_2D); fbo = new FBObject[2]; //first fbo fbo[currentSourceBuffer] = new FBObject(); // Create FrameBuffer fbo[currentSourceBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); fbo[currentSourceBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call fbo[currentSourceBuffer].bind(gl); int tex = genTexture(gl); gl.glBindTexture(GL_TEXTURE_2D, tex); gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null); fbo[currentSourceBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); //gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); int DrawBuffers[] = {GL_COLOR_ATTACHMENT0}; gl.glDrawBuffers(1, DrawBuffers, 0); // "1" is the size of DrawBuffers fbo[currentSourceBuffer].unbind(gl); //second fbo fbo[currentDestBuffer] = new FBObject(); // Create FrameBuffer fbo[currentDestBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); fbo[currentDestBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call fbo[currentDestBuffer].bind(gl); tex = genTexture(gl); gl.glBindTexture(GL_TEXTURE_2D, tex); gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null); fbo[currentDestBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); //ogl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); gl.glDrawBuffers(1, DrawBuffers, 1); // "1" is the size of DrawBuffers fbo[currentDestBuffer].unbind(gl); } catch (Exception e) { System.out.println("Problem with fbo init " + e); e.printStackTrace(); } } private Texture initializeTexture() { Texture t = null; try { t = TextureIO.newTexture(new File("e:/shaders/wiki.jpg"), false); t.setTexParameteri(gl, GL_TEXTURE_MIN_FILTER, GL_LINEAR); t.setTexParameteri(gl, GL_TEXTURE_MAG_FILTER, GL_LINEAR); t.setTexParameteri(gl, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); t.setTexParameteri(gl, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } catch (Exception e) { System.out.println("Unable to read texture file: " + e); e.printStackTrace(); } return t; } private ShaderProgram loadShader(GL2 gl, String vertexShader, String fragmentShader) { ShaderCode vertShader = ShaderCode.create(gl, GL2.GL_VERTEX_SHADER, 1, getClass(), new String[]{"e:/shaders/"+vertexShader},false); vertShader.compile(gl); ShaderCode fragShader = ShaderCode.create(gl, GL2.GL_FRAGMENT_SHADER, 1, getClass(), new String[]{"e:/shaders/"+fragmentShader},false); fragShader.compile(gl); ShaderProgram newShader = new ShaderProgram(); newShader.init(gl); newShader.add(vertShader); newShader.add(fragShader); newShader.link(gl, System.out); vertShader.destroy(gl); fragShader.destroy(gl); return newShader; } public static void setShaderUniform1i(GL2 inGL,int inProgramID,String inName,int inValue) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform1i(tUniformLocation, inValue); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } public static void setShaderUniformFloat(GL2 inGL,int inProgramID,String inName,float inValue) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform1f(tUniformLocation, inValue); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } public static void setShaderUniformFloat2(GL2 inGL,int inProgramID,String inName,float inValue1 ,float inValue2) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform2f(tUniformLocation, inValue1, inValue2); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } private void viewOrtho(GL2 gl) // Set Up An Ortho View { gl.glMatrixMode(GL_PROJECTION); // Select Projection gl.glPushMatrix(); // Push The Matrix gl.glLoadIdentity(); // Reset The Matrix gl.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); gl.glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix gl.glPushMatrix(); // Push The Matrix gl.glLoadIdentity(); // Reset The Matrix } private int genTexture(GL2 gl) { final int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); return tmp[0]; } /** * Called back before the OpenGL context is destroyed. Release resource such as buffers. */ #Override public void dispose(GLAutoDrawable drawable) { } } And the corresponding GLSL Shader : #version 120 uniform sampler2D textureData; uniform sampler2D textureImage; uniform vec2 resolution; uniform float diffuseU; uniform float diffuseV; uniform float feed; uniform float kill; uniform float Tech = 1.0; uniform float currentFrame = 0.0; void main() { //coords vec2 position = ( gl_FragCoord.xy / resolution.xy ); vec2 pixel = 1./resolution; //get data from texture vec4 imgSource = texture2D(textureImage, gl_TexCoord[0].st); vec2 oldUV = texture2D(textureData, gl_TexCoord[0].st).rg; if(currentFrame<10){ if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.2f) oldUV = vec2(0.0,0.2); else if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.3f) oldUV = vec2(0.5,0.1); else oldUV = vec2(0.1,0.0); gl_FragColor = vec4(oldUV.rg, 0.0, 1.0); return; } //get neightboors vec2 dataUp = texture2D(textureData, position + pixel * vec2(0., 1.)).rg; vec2 dataDown = texture2D(textureData, position + pixel * vec2(0., -1.)).rg; vec2 dataLeft = texture2D(textureData, position + pixel * vec2(-1., 0.)).rg; vec2 dataRight = texture2D(textureData, position + pixel * vec2(1., 0.)).rg; //adapt parameters vec2 imgParam = imgSource.rg; float dU = diffuseU ;//+ 0.01 * (imgParam - 0.5); float dV = diffuseV ;//+ 0.01 * (imgParam - 0.5); float F = feed ;//+ 0.01 * (imgParam - 0.5); float K = kill ;//+ 0.01 * (imgParam - 0.5); //compute new values vec2 laplace = (dataUp+dataDown+dataLeft+dataRight) - 4.0 * oldUV; float uvv = oldUV.r * oldUV.g * oldUV.g; // calculate delta quantities float du = dU * laplace.r - uvv + F*(1.0 - oldUV.r); float dv = dV * laplace.g + uvv - (F+K)*oldUV.g; vec2 newUV = oldUV + vec2(du, dv)* Tech; gl_FragColor = vec4(newUV.rg, 0.0, 1.0); }
Few considerations: avoid deprecated OpenGL (and GLU), use GL4 (or GL3) unless you need awt/swt/swing, prefer newt, more here prefer Animator instead of FPSAnimator, more here prefer direct buffers instead of arrays, since otherwise jogl has to create them underneath and you can't keep trace (= deallocate when done) of those native allocations GL4 will allow you also to avoid all those uniform overhead (and also potential bugs) you have to deal with (especially during runtime), thanks to explicit locations prefer direct buffer management instead of FBObject for the moment unless you really know what FBObject is doing. Once you get it working, you can move on using that class. This may be (one of the) cause your code is not working, because something is not getting setup up as you need. Moreover, the lines of codes needed to replace FBObject are essentially the same (if you can't use explicit location for any reason) prefer some literal way to define the texture uniform location, it is usually another tricky part causing bugs, something like this prefer also a sampler for the textures, gives you more flexibility don't wait one week next time, let us know earlier! :) Frustation can be a nasty thing that put you down easily. Together we can help you getting it working ;)
JavaVM crashing when drawing using OpenGL
I've got the folowing code: package test.opengl; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL30; import com.badlogic.gdx.utils.BufferUtils; import java.io.IOException; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.file.Files; import java.nio.file.Paths; import static com.badlogic.gdx.graphics.GL20.*; public class GLClass extends ApplicationAdapter { private int shaderProgram; private GL30 gl; FloatBuffer vertices; IntBuffer vao = BufferUtils.newIntBuffer(1); IntBuffer vbo = BufferUtils.newIntBuffer(1); #Override public void create() { gl = Gdx.gl30; compileShaders(); vertices = BufferUtils.newFloatBuffer(9); vertices.put(new float[] { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }); gl.glEnable(GL_DEPTH_TEST); gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); gl.glGenVertexArrays(1, vao); gl.glGenBuffers(1, vbo); gl.glBindVertexArray(vao.get(0)); gl.glBindBuffer(GL_ARRAY_BUFFER, vbo.get(0)); gl.glBufferData(GL_ARRAY_BUFFER, 9, vertices, GL_STATIC_DRAW); gl.glVertexAttribPointer(0, 3, GL_FLOAT, false, 3, 0); gl.glEnableVertexAttribArray(0); gl.glBindVertexArray(0); } #Override public void render() { gl.glClearColor(0.2f, 0.2f, 0.2f, 1); gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gl.glUseProgram(shaderProgram); gl.glBindVertexArray(vao.get(0)); gl.glDrawArrays(GL_TRIANGLES, 0, 3); gl.glBindVertexArray(0); int err = gl.glGetError(); if (err != 0) System.err.println("ERROR: " + err); } #Override public void resize(int width, int height) { gl.glViewport(0, 0, width, height); } private void compileShaders() { String vsSource; String fsSource; try { vsSource = new String(Files.readAllBytes(Paths.get("shaders/shader.vert"))); fsSource = new String(Files.readAllBytes(Paths.get("shaders/shader.frag"))); } catch (IOException e) { throw new RuntimeException(e); } shaderProgram = gl.glCreateProgram(); int vertexShader = gl.glCreateShader(GL_VERTEX_SHADER); gl.glShaderSource(vertexShader, vsSource); gl.glCompileShader(vertexShader); System.err.println(gl.glGetShaderInfoLog(vertexShader)); gl.glAttachShader(shaderProgram, vertexShader); int fragmentShader = gl.glCreateShader(GL_FRAGMENT_SHADER); gl.glShaderSource(fragmentShader, fsSource); gl.glCompileShader(fragmentShader); System.err.println(gl.glGetShaderInfoLog(fragmentShader)); gl.glAttachShader(shaderProgram, fragmentShader); gl.glLinkProgram(shaderProgram); gl.glDeleteShader(vertexShader); gl.glDeleteShader(fragmentShader); } } The code for shader.vert: #version 330 core layout (location = 0) in vec3 position; void main() { gl_Position = vec4(position.x, position.y, position.z, 1.0); } The code for shader.frag: #version 330 out vec4 out_Color; void main() { out_Color = vec4(1.0f, 0.5f, 0.2f, 1.0f); } It is running on desktop and the program crashes as soon as the first call of render() is completed, without a stacktrace and a segfault log. config.useGL30 is set to true. Why is it crashing? Am I doing anything wrong?
VAO does't render in color with shaders
I recently started learning OpenGL and I have been trying to write a program that displays a diamond on the screen using VAOs and VBOs with shaders. My code is mostly based on this tutorial: https://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29 and I also used the shaders from the tutorial. The diamond is supposed to be drawn using the color information from the vertex array object but instead it is just drawn in white. The shaders seem to be loading fine so I think it is a problem with my vertex and buffer array objects. Can someone please explain why my code is not working how I expected or show a clear example of how to render VAOs using colors from an array of color attributes. package windows; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.nio.FloatBuffer; import java.nio.IntBuffer; import javax.media.opengl.GL2; 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.glu.GLU; import shaders.ShaderControl2; import com.jogamp.common.nio.Buffers; public class Test4 implements GLEventListener{ ShaderControl2 sc; FloatBuffer vertexPos, vertexCol; IntBuffer vao, vbo; GLU glu = new GLU(); public static void main(String[] args){ GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); GLCanvas canvas = new GLCanvas(caps); Test4 t = new Test4(); canvas.addGLEventListener(t); Frame f = new Frame("TEST #4"); f.setSize(400,400); f.add(canvas); f.setVisible(true); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); } #Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); gl.glClearColor(0, 0, 0, 1f); gl.glClear(GL2.GL_COLOR_BUFFER_BIT); sc.useShader(gl); gl.glBindVertexArray(vao.get(0)); gl.glEnableVertexAttribArray(0); gl.glEnableVertexAttribArray(1); gl.glDrawArrays(GL2.GL_LINE_LOOP, 0 , 4); sc.dontUseShader(gl); } #Override public void dispose(GLAutoDrawable drawable) { // TODO Auto-generated method stub } #Override public void init(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); System.out.println(gl.glGetString(GL2.GL_VERSION)); vertexPos = Buffers.newDirectFloatBuffer(8); vertexPos.put(new float[]{0f, 1f}); vertexPos.put(new float[]{1f, 0f}); vertexPos.put(new float[]{0f, -1f}); vertexPos.put(new float[]{-1f, 0}); vertexPos.flip(); vertexCol = Buffers.newDirectFloatBuffer(12); vertexCol.put(new float[]{1f, 0f, 0f}); vertexCol.put(new float[]{0f, 1f, 0f}); vertexCol.put(new float[]{0f, 0f, 1f}); vertexCol.put(new float[]{1f, 1f, 1f}); vertexCol.flip(); vao = IntBuffer.allocate(1); vbo = IntBuffer.allocate(2); gl.glGenVertexArrays(1, vao); gl.glGenBuffers(2, vbo); int bytesPerFloat = Float.SIZE/Byte.SIZE; gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(0)); gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertexPos.capacity() * bytesPerFloat, vertexPos, GL2.GL_STATIC_DRAW); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(1)); gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertexCol.capacity() * bytesPerFloat, vertexCol, GL2.GL_STATIC_DRAW); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); gl.glBindVertexArray(vao.get()); gl.glEnableVertexAttribArray(0); gl.glEnableVertexAttribArray(1); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(0)); gl.glVertexAttribPointer(0, 2, GL2.GL_FLOAT, false, 0, 0); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(1)); gl.glVertexAttribPointer(1, 3, GL2.GL_FLOAT, false, 0, 0); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); sc = new ShaderControl2(); sc.vSrc = sc.loadShader("v.txt"); sc.fSrc = sc.loadShader("f.txt"); } #Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } } ShaderControl2 code: package shaders; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.IntBuffer; import javax.media.opengl.*; public class ShaderControl2 { private int vertexShaderProg, fragmentShaderProg, shaderProg; public String[] vSrc, fSrc; public String[] loadShader(String sFile){ String line = new String(); StringBuilder fileContent = new StringBuilder(); try{ InputStream is = getClass().getResourceAsStream(sFile); BufferedReader br = new BufferedReader(new InputStreamReader(is)); while((line = br.readLine()) != null){ fileContent.append(line + "\n"); } is.close(); } catch(Exception e){ e.printStackTrace(); } System.out.println("Shader file content:\n" + fileContent); return new String[]{fileContent.toString()}; } public void attachShader(GL2 gl){ IntBuffer isCompiledVS = IntBuffer.allocate(1), isCompiledFS = IntBuffer.allocate(1), isLinked = IntBuffer.allocate(1); IntBuffer vLogLength = IntBuffer.allocate(1), fLogLength = IntBuffer.allocate(1), linkLogLength = IntBuffer.allocate(1); ByteBuffer vertexInfoLog, fragmentInfoLog, linkInfoLog; int size; vertexShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); gl.glShaderSource(vertexShaderProg, 1, vSrc, null); gl.glCompileShader(vertexShaderProg); gl.glGetShaderiv(vertexShaderProg, GL2.GL_COMPILE_STATUS, isCompiledVS); if(isCompiledVS.get(0) == 0){ System.out.println("Failed to compile vertexShaderProg"); gl.glGetShaderiv(vertexShaderProg, GL2.GL_INFO_LOG_LENGTH, vLogLength); size = vLogLength.get(0); vertexInfoLog = ByteBuffer.allocate(size); gl.glGetShaderInfoLog(vertexShaderProg, size, vLogLength, vertexInfoLog); for(byte b : vertexInfoLog.array()){ System.err.print((char)b); } } fragmentShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); gl.glShaderSource(fragmentShaderProg, 1, vSrc, null); gl.glCompileShader(fragmentShaderProg); gl.glGetShaderiv(fragmentShaderProg, GL2.GL_COMPILE_STATUS, isCompiledFS); if(isCompiledFS.get(0) == 0){ System.out.println("Failed to compile fragmentShaderProg"); gl.glGetShaderiv(fragmentShaderProg, GL2.GL_INFO_LOG_LENGTH, fLogLength); size = fLogLength.get(0); fragmentInfoLog = ByteBuffer.allocate(size); gl.glGetShaderInfoLog(fragmentShaderProg, size, fLogLength, fragmentInfoLog); for(byte b : fragmentInfoLog.array()){ System.err.print((char)b); } } shaderProg = gl.glCreateProgram(); gl.glAttachShader(shaderProg, vertexShaderProg); gl.glAttachShader(shaderProg, fragmentShaderProg); gl.glBindAttribLocation(shaderProg, 0, "in_Position"); gl.glBindAttribLocation(shaderProg, 1, "in_Color"); gl.glLinkProgram(shaderProg); gl.glGetProgramiv(shaderProg, GL2.GL_LINK_STATUS, isLinked); if(isLinked.get(0) == 0){ System.out.println("Failed to link shaderProg"); gl.glGetShaderiv(shaderProg, GL2.GL_INFO_LOG_LENGTH, linkLogLength); size = linkLogLength.get(0); linkInfoLog = ByteBuffer.allocate(size); gl.glGetProgramInfoLog(shaderProg, size, linkLogLength, linkInfoLog); for(byte b : linkInfoLog.array()){ System.err.print((char)b); } } } public int useShader(GL2 gl){ gl.glUseProgram(shaderProg); return shaderProg; } public void dontUseShader(GL2 gl){ gl.glUseProgram(0); } } Shader Code f.txt: #version 210 // It was expressed that some drivers required this next line to function properly precision highp float; in vec3 ex_Color; out vec4 gl_FragColor; void main(void) { // Pass through our original color with full opacity. gl_FragColor = vec4(ex_Color,1.0); } v.txt: #version 210 // in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1 in vec2 in_Position; in vec3 in_Color; // We output the ex_Color variable to the next shader in the chain out vec3 ex_Color; void main(void) { // Since we are using flat lines, our input only had two points: x and y. // Set the Z coordinate to 0 and W coordinate to 1 gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0); // GLSL allows shorthand use of vectors too, the following is also valid: // gl_Position = vec4(in_Position, 0.0, 1.0); // We're simply passing the color through unmodified ex_Color = in_Color; }
The reason you see just white lines is because the shader program is not being used at all. I can't see where you call attach shaders (you never call sc.attachShader(gl), I added sc.attachShader(gl) at the end of the init method. Now a lot of errors will appear. In attachshader, when you create fragmentShaderProg you create it as a GL_VERTEX_SHADER, it should be GL_FRAGMENT_SHADER, and just below that you are sending the source of the vertex shader in place of the fragment shader. version 210 of the GLSL language doesn't exist, change it to version 130. The thing with the GLSL version is that it is independent from the OpenGL version, https://github.com/mattdesl/lwjgl-basics/wiki/GLSL-Versions #version 130 Now add to the end of the init method sc.attachShader(gl) and change fragmentShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); gl.glShaderSource(fragmentShaderProg, 1, vSrc, null); for fragmentShaderProg = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER); gl.glShaderSource(fragmentShaderProg, 1, fSrc, null); now it works.
Testing out some LWJGL OpenGL, won't make box. What should I do?
Had this working on OpenGL ES 1.0 & 2.0. Goal: Make a box, then display it Won't work with LWJGL on Win 7. Loads a green box (as it should), and then starts to display a bunch of really thick white lines that won't stay as a box. There is a lot of flickering. Here is a picture. Here is the code for windows. Main.java package play.box; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; public class Main { public static final boolean VSYNC = true; public static final int WIDTH = 800; public static final int HEIGHT = 600; public static final boolean FULLSCREEN = false; protected boolean running = false; public static void main(String[] args) { try { start(); } catch (LWJGLException e) { e.printStackTrace(); } } public static void start() throws LWJGLException { Display.setTitle("Display example"); Display.setResizable(false); Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT)); Display.setVSyncEnabled(VSYNC); Display.setFullscreen(FULLSCREEN); Display.create(); // Setup OpenGL GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(-3, 3, -2, 2, -1, 1); GL11.glMatrixMode(GL11.GL_MODELVIEW); new Renderer().run(); } } Renderer.java package play.box; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.GL11; public class Renderer implements Runnable { public Renderer() { } #Override public void run() { while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT); GL11.glClearColor(0.0f, 0.5f, 0.0f, 1.0f); // Rendering // /*GL11.glBegin(GL11.GL_TRIANGLES); GL11.glColor3f(1.0f, 0.0f, 0.0f); GL11.glVertex2f(0.0f, 1.0f); GL11.glColor3f(1.0f, 0.0f, 0.0f); GL11.glVertex2f(1.0f, 1.0f); GL11.glColor3f(1.0f, 0.0f, 0.0f); GL11.glVertex2f(1.0f, -1.0f); GL11.glEnd();*/ Box box = new Box(); box.draw(); // End of Rendering // Display.update(); try { Thread.sleep(1000); } catch(Exception e) { e.printStackTrace(); } } } } Box.java package play.box; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import org.lwjgl.opengl.GL11; public class Box { private float verticies[] = { -1.0f, 1.0f, // Left Top (0) -1.0f, -1.0f, // Left Bottom (1) 1.0f, -1.0f, // Right Bottom (2) 1.0f, 1.0f // Right Top (4) }; private short indicies[] = { 0, 1, 2, 2, 3, 0 }; private FloatBuffer vertBuff; private ShortBuffer indexBuff; public Box() { this.setupBuffers(); } private void setupBuffers() { ByteBuffer bBuff = ByteBuffer.allocateDirect(this.verticies.length * 4); bBuff.order(ByteOrder.nativeOrder()); this.vertBuff = bBuff.asFloatBuffer(); this.vertBuff.put(this.verticies); this.vertBuff.position(0); ByteBuffer pbBuff = ByteBuffer.allocateDirect(this.indicies.length * 2); pbBuff.order(ByteOrder.nativeOrder()); this.indexBuff = pbBuff.asShortBuffer(); this.indexBuff.put(this.indicies); this.indexBuff.position(0); } public void draw() { GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); GL11.glVertexPointer(2, GL11.GL_FLOAT, this.vertBuff); GL11.glDrawElements(GL11.GL_TRIANGLES, this.indexBuff); GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY); } } Updated Code: package play.box; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; public class Box { private float verticies[] = { -1.0f, 1.0f, // Left Top (0) -1.0f, -1.0f, // Left Bottom (1) 1.0f, -1.0f, // Right Bottom (2) 1.0f, 1.0f // Right Top (4) }; private short indicies[] = { 0, 1, 2, 2, 3, 0 }; private FloatBuffer vertBuff; private ShortBuffer indexBuff; private int vbo_handle; private int ibo_handle; private int vao_handle; private String vShaderStr = "attribute vec4 vPosition; \n" + "void main() { \n" + " gl_Position = vPosition;\n" + "} \n"; private String fShaderStr = "precision mediump float; \n" + "void main() { \n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" + "} \n"; private int vertexShader; private int fragmentShader; private int programObject; public Box() { } public void create() { ByteBuffer bBuff = ByteBuffer.allocateDirect(this.verticies.length * 4); bBuff.order(ByteOrder.nativeOrder()); this.vertBuff = bBuff.asFloatBuffer(); this.vertBuff.put(this.verticies); //this.vertBuff.flip(); this.vertBuff.position(0); ByteBuffer pbBuff = ByteBuffer.allocateDirect(this.indicies.length * 2); pbBuff.order(ByteOrder.nativeOrder()); this.indexBuff = pbBuff.asShortBuffer(); this.indexBuff.put(this.indicies); //this.indexBuff.flip(); this.indexBuff.position(0); // Create VBO this.vbo_handle = GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbo_handle); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.vertBuff, GL15.GL_DYNAMIC_DRAW); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); // Create IBO this.ibo_handle = GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.ibo_handle); GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, this.indexBuff, GL15.GL_DYNAMIC_DRAW); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); // Create VAO this.vao_handle = GL30.glGenVertexArrays(); GL30.glBindVertexArray(vao_handle); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_handle); GL20.glEnableVertexAttribArray(0); GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo_handle); GL30.glBindVertexArray(0); // Setup Shaders this.vertexShader = this.loadShader(GL20.GL_VERTEX_SHADER, this.vShaderStr); this.fragmentShader = this.loadShader(GL20.GL_FRAGMENT_SHADER, this.fShaderStr); // Setup Program int program = GL20.glCreateProgram(); if(program == 0) { return; } GL20.glAttachShader(program, this.vertexShader); GL20.glAttachShader(program, this.fragmentShader); GL20.glBindAttribLocation(program, 0, "vPosition"); GL20.glLinkProgram(program); if(GL20.glGetProgrami(program, GL20.GL_LINK_STATUS) == 0) { System.out.println("Error Creating Program: " + GL20.glGetProgramInfoLog(program, Integer.MAX_VALUE)); GL20.glDeleteProgram(program); return; } this.programObject = program; } public void draw() { this.create(); GL20.glUseProgram(this.programObject); GL30.glBindVertexArray(vao_handle); GL11.glDrawElements(GL11.GL_TRIANGLES, 2, GL11.GL_FLOAT, 0); GL30.glBindVertexArray(0); this.dispose(); } public void draw(boolean useVAO) { if(useVAO) { this.draw(); } else { this.create(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbo_handle); GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0L); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.ibo_handle); GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); GL11.glDrawElements(GL11.GL_TRIANGLES, this.indicies.length, GL11.GL_UNSIGNED_SHORT, 0L); GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY); this.dispose(); } } public void dispose() { GL30.glDeleteVertexArrays(vao_handle); GL30.glDeleteVertexArrays(vbo_handle); GL30.glDeleteVertexArrays(ibo_handle); this.vao_handle = -1; this.vbo_handle = -1; this.ibo_handle = -1; } private int loadShader(int type, String shaderSrc) { int shader; shader = GL20.glCreateShader(type); if(shader == 0) { return 0; } GL20.glShaderSource(shader, shaderSrc); GL20.glCompileShader(shader); if(GL20.glGetShaderi(shader, GL20.GL_COMPILE_STATUS) == 0) { System.out.println("Error Loading Shader: " + GL20.glGetShaderInfoLog(shader, Integer.MAX_VALUE)); GL20.glDeleteShader(shader); return 0; } return shader; } }
Instead of just showing you what you asked for in the comments, I will demonstrate how you create, render and dispose a VAO using a VBO and IBO. VAO <=> Vertex Array Object VBO <=> Vertex Buffer Object IBO <=> Index Buffer Object Creating VAO, VBO & IBO The vao_handle, vbo_handle and ibo_handle is 3 integers containing the id/handle, these 3 variables are used in the whole following code. vbo_data <=> FloatBuffer containing the vertices ibo_data <=> IntBuffer containing the indices The two above variables are used in the following code. // Creating the VBO vbo_handle = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, vbo_handle); glBufferData(GL_ARRAY_BUFFER, vbo_data, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // Creating the IBO ibo_handle = glGenBuffers(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_handle ); glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_data, GL_DYNAMIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Creating the VAO vao_handle = glGenVertexArrays(); glBindVertexArray(vao_handle); glBindBuffer(GL_ARRAY_BUFFER, vbo_handle); glEnableVertexAttribArray(INDEX); // Place your own INDEX value in the parenthesis glVertexAttribPointer(INDEX, SIZE, TYPE, NORMALIZED, STRIDE, OFFSET); // Replace all the VARIABLES with the values which fit to your VAO, VBO and IBO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_handle); glBindVertexArray(0); /* * Remember that the INDEX given in the * glEnableVertexAttribArray() and in * glVertexAttribPointer() is the same * INDEX used in Shaders (GLSL) * * If the INDEX is 0 then in GLSL it * should look like this * GLSL: layout(location = 0) in vec3 position; * * ^ we can ignore this if you aren't * using Shaders, though keep it in mind * since we might need it in the future */ Rendering VAO glBindVertexArray(vao_handle); glDrawElements(MODE, SIZE, TYPE, OFFSET); // Again replace the variables, so it fits to your VAO, VBO and IBO glBindVertexArray(0); Dispose VAO, VBO & IBO This is how you delete the different buffers, which is a good thing to do, when you close the program or if at some point you don't need them anymore. glDeleteVertexArrays(vao_handle); // Deletes the VAO glDeleteBuffers(vbo_handle); // Deletes the VBO glDeleteBuffers(ibo_handle); // Deletes the IBO vao_handle = -1; vbo_handle = -1; ibo_handle = -1;
OpenGL ES Object is Displaying Strangely / Distorted - Android
EDIT OK - I grabbed a device and..guess what...it displays correctly ? Does anyone know why this would be happening on the simulator only ? Thank you. I am trying to draw an object using glDrawElements on Android. I am using the code below to read in my vertice and indice data and then draw the object in my render method. I am testing this on the simulator rather than a real device. This is my scene object code : import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; public class SceneObject { public FloatBuffer mVertexBuffer; public FloatBuffer mTextureBuffer; public ShortBuffer indexBuffer; public FloatBuffer mMatriceBuffer; public FloatBuffer mPivotBuffer; public short[] indicesTest = {0,1,2,3,4,5,3,5,6,7,5,8,7,8,9,10,7,9,11,10,9,12,1,0,13,12,14,15,13,14,14,10,11,15,14,11,0,14,12,16,17,18,19,16,18,18,20,19,21,16,19,22,21,19,22,19,23,4,24,25,25,26,27,25,27,28,4,25,28,5,4,28,5,28,8,29,30,31,29,31,19,29,19,20,32,33,31,32,31,30,32,34,33,35,22,23,36,35,23,37,36,23,37,23,38,39,37,38,40,39,38,41,40,38,41,38,1,42,41,1,12,43,1,42,1,43,17,27,26,26,18,17,44,45,46,46,47,44,48,49,50,51,52,53,53,54,51,55,51,54,54,56,55,57,48,50,50,58,57,52,59,60,60,53,52,59,44,47,47,60,59,61,62,63,63,64,61,65,66,67,67,68,65,69,70,71,71,72,69,66,69,72,72,67,66,73,65,68,68,74,73,70,75,76,76,71,70,75,61,64,64,76,75,77,78,79,79,80,77,81,82,62,62,61,81,83,81,61,61,75,83,84,63,62,62,82,84,63,84,85,86,87,88,89,90,91,92,93,87,87,86,92,94,95,96,96,97,94,98,99,100,100,101,98,102,103,104,104,105,102,106,107,108,108,109,106,110,111,112,78,77,113,114,115,78,112,111,116,117,118,115,119,116,120,121,122,123,123,124,121,125,126,127,127,128,125,129,130,131,132,133,5,5,133,6,5,134,135,135,134,136,134,137,136,137,138,136,129,139,130,139,140,141,140,142,141,137,141,138,141,142,138,141,130,139,143,144,145,144,146,145,147,145,146,144,148,146,148,149,146,146,149,150,151,132,152,153,152,154,154,152,155,152,132,155,132,5,155,155,5,135,156,157,158,158,157,146,146,157,147,159,160,158,158,160,156,34,160,159,149,161,150,161,162,150,162,163,150,150,163,164,163,165,164,165,166,164,166,167,164,164,167,129,167,168,129,169,139,129,129,168,169,154,143,153,145,153,143,170,171,172,173,172,171,174,175,176,177,178,179,180,179,178,178,181,180,182,180,181,175,183,176,184,176,183,185,177,186,179,186,177,171,185,173,186,173,185,187,188,189,190,189,188,191,192,193,194,193,192,195,196,197,198,197,196,196,191,198,193,198,191,192,199,194,200,194,199,201,195,202,197,202,195,188,201,190,202,190,201,203,204,205,206,205,204,207,208,187,188,187,208,208,209,188,201,188,209,189,210,187,207,187,210,210,189,211,212,213,214,215,216,217,218,219,220,221,220,219,222,223,224,225,226,227,228,229,230,231,230,229,232,233,234,235,236,237,238,239,240,241,242,243,123,244,124,245,246,203,204,203,246,247,248,203,249,250,251,252,253,247,248,247,253,159,33,34,254,255,256,256,257,254,255,244,123,123,256,255,244,258,121,121,124,244,259,260,125,125,128,259}; public float[] verticeTest = {20360.8f,20679.5f,611.547f,24248.7f,13527f,1074.93f,24207.4f,23005.5f,1503.19f,9819.59f,14845.7f,8.81875f,11126.3f,13982.2f,32.0718f,8379.01f,17678.5f,0.00115749f,8379.01f,15141.6f,0.00111471f,12137.8f,17973.8f,60.0461f,14591.9f,14509.2f,164.113f,15621.5f,15846.6f,223.075f,15136.7f,18549.5f,194.186f,16918.2f,16705.3f,310.215f,21081.8f,15846.6f,687.576f,19789f,16705.3f,554.435f,18467.9f,19868.7f,433.258f,18354.3f,17001.2f,423.539f,14591.9f,7402.34f,164.113f,13930.5f,9087.62f,131.015f,13039.7f,9096.18f,92.3283f,19110.4f,-8011.43f,490.311f,12811.7f,7228.03f,83.5128f,15621.5f,6064.9f,223.074f,16918.2f,5206.21f,310.215f,21807.5f,-426.492f,768.658f,11221.5f,13854f,34.3347f,12150f,12649.6f,60.4329f,12811.7f,10964.3f,83.513f,13702.6f,10955.8f,120.472f,13930.5f,12823.9f,131.015f,12150f,5542.76f,60.4327f,11119f,4205.31f,31.902f,15341.7f,-15792.9f,206.155f,9819.59f,3346.62f,8.81857f,10735.6f,-21752.5f,23.5976f,8379.01f,3050.73f,0.000981022f,18354.3f,4910.32f,423.538f,19789f,5206.21f,554.434f,21081.8f,6064.9f,687.576f,23336.1f,6399.27f,954.364f,22106.6f,7402.34f,803.393f,22764f,9087.62f,882.485f,22990.5f,10955.8f,910.595f,22764f,12823.9f,882.485f,22106.6f,14509.2f,803.393f,24248.7f,8492.36f,-3249.03f,24207.4f,17415.3f,-3297.97f,24207.4f,23005.5f,1503.19f,24248.7f,13527f,1074.93f,12728.3f,-24463.4f,-4243.56f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,19110.4f,-13046f,-3833.65f,21807.5f,-5461.09f,-3555.3f,21807.5f,-426.492f,768.658f,19110.4f,-8011.43f,490.311f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,23336.1f,1364.68f,-3369.59f,23336.1f,6399.27f,954.364f,24883.8f,8123.11f,-2819.08f,24859.5f,16025.8f,-2803.12f,24207.4f,17415.3f,-3297.97f,24248.7f,8492.36f,-3249.03f,13363.4f,-24832.7f,-3813.62f,15976.8f,-21196.8f,-3687.86f,15341.7f,-20827.5f,-4117.81f,12728.3f,-24463.4f,-4243.56f,19745.5f,-13415.3f,-3403.7f,22442.7f,-5830.35f,-3125.36f,21807.5f,-5461.09f,-3555.3f,19110.4f,-13046f,-3833.65f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,23222.6f,-2518.03f,-3057.67f,23336.1f,1364.68f,-3369.59f,10301.8f,-40240.8f,-15469.8f,10482f,-40907.1f,-14694f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,25648.8f,8121.58f,-2817.31f,25624.5f,16024.2f,-2801.34f,24056.1f,-2550.94f,-3019.36f,25678.7f,16560.2f,-2907.29f,25594.2f,17951.2f,-3237.71f,25624.5f,-88046.9f,-92182.7f,25678.7f,-87767f,-92508.6f,25678.7f,16560.2f,-2907.29f,25678.7f,16560.2f,-2907.29f,25624.5f,16024.2f,-2801.34f,25624.5f,-88046.9f,-92182.7f,25624.5f,-88413.1f,-92497.2f,25678.7f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,24820f,-88133.2f,-92823.1f,25678.7f,-88133.2f,-92823.1f,25624.5f,-88413.1f,-92497.2f,24765.7f,-89895.8f,-93770.7f,24820f,-89615.9f,-94096.6f,24820f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,25678.7f,-89596.5f,-94079.9f,25678.7f,-88133.2f,-92823.1f,24820f,-88133.2f,-92823.1f,24820f,-89615.9f,-94096.6f,23222.6f,-93458.9f,-81162.2f,24056.1f,-93491.8f,-81123.9f,24056.1f,-2550.94f,-3019.36f,23222.6f,-2518.03f,-3057.67f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-40907.1f,-14694f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-41291.8f,-14246f,10579f,-102925f,-68042.7f,10489f,-103571f,-67018.6f,10482f,-41713.9f,-13886.7f,10482f,-41291.8f,-14246f,10489f,-103571f,-67018.6f,8379.01f,-102145f,-69021.7f,10579.6f,-102089f,-68973.2f,10301.8f,-40240.8f,-15469.8f,8379.01f,-68082.6f,-39554.7f,8379.01f,-101057f,-70411.1f,10735.6f,-101057f,-70411.1f,10579.6f,-102089f,-68973.2f,8379.01f,-102145f,-69021.7f,-7490.7f,13527f,1074.93f,-3602.79f,20679.5f,611.547f,-7449.35f,23005.5f,1503.19f,5631.77f,13982.2f,32.0718f,6938.43f,14845.7f,8.81875f,4620.19f,17973.8f,60.0461f,2166.16f,14509.2f,164.113f,1136.48f,15846.6f,223.075f,1621.29f,18549.5f,194.186f,-160.178f,16705.3f,310.215f,-4323.73f,15846.6f,687.576f,-3030.97f,16705.3f,554.435f,-1709.92f,19868.7f,433.258f,-1596.32f,17001.2f,423.539f,2827.51f,9087.62f,131.015f,2166.16f,7402.34f,164.113f,3718.3f,9096.18f,92.3283f,-2352.36f,-8011.43f,490.311f,3946.3f,7228.03f,83.5128f,1136.48f,6064.9f,223.074f,-160.182f,5206.21f,310.215f,-5049.53f,-426.492f,768.658f,5536.51f,13854f,34.3347f,4608.07f,12649.6f,60.4329f,3946.3f,10964.3f,83.513f,3055.44f,10955.8f,120.472f,2827.51f,12823.9f,131.015f,5639.04f,4205.31f,31.902f,4608.07f,5542.76f,60.4327f,1416.3f,-15792.9f,206.155f,6022.45f,-21752.5f,23.5976f,6938.43f,3346.62f,8.81857f,-1596.32f,4910.32f,423.538f,-3030.97f,5206.21f,554.434f,-4323.73f,6064.9f,687.576f,-6578.08f,6399.27f,954.364f,-5348.56f,7402.34f,803.393f,-6006f,9087.62f,882.485f,-6232.44f,10955.8f,910.595f,-6006f,12823.9f,882.485f,-5348.57f,14509.2f,803.393f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,-7449.35f,23005.5f,1503.19f,-7490.7f,13527f,1074.93f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,1416.3f,-15792.9f,206.155f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,-5049.53f,-426.492f,768.658f,-2352.36f,-8011.43f,490.311f,1416.3f,-20827.5f,-4117.81f,1416.3f,-15792.9f,206.155f,6022.45f,-26787.1f,-4300.36f,6022.45f,-21752.5f,23.5976f,-6578.08f,1364.68f,-3369.59f,-6578.08f,6399.27f,954.364f,-8101.47f,16025.8f,-2803.12f,-8125.81f,8123.11f,-2819.08f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,781.19f,-21196.8f,-3687.86f,3394.66f,-24832.7f,-3813.62f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,-5684.64f,-5830.35f,-3125.36f,-2987.47f,-13415.3f,-3403.7f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-6464.54f,-2518.03f,-3057.67f,-6578.08f,1364.68f,-3369.59f,6276.06f,-40907.1f,-14694f,6456.25f,-40240.8f,-15469.8f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-8866.45f,16024.2f,-2801.34f,-8890.79f,8121.58f,-2817.31f,-7298.12f,-2550.94f,-3019.36f,-8920.72f,16560.2f,-2907.29f,-8836.13f,17951.2f,-3237.71f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,16560.2f,-2907.29f,-8866.45f,16024.2f,-2801.34f,-8920.72f,16560.2f,-2907.29f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8061.98f,-89615.9f,-94096.6f,-8007.72f,-89895.8f,-93770.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-8061.98f,-88133.2f,-92823.1f,-8061.98f,-89615.9f,-94096.6f,-8061.98f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-7298.12f,-93491.8f,-81123.9f,-6464.54f,-93458.9f,-81162.2f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-2518.03f,-3057.67f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-93458.9f,-81162.2f,6456.25f,-40240.8f,-15469.8f,6179.01f,-102925f,-68042.7f,6178.41f,-102089f,-68973.2f,6276.06f,-41291.8f,-14246f,6179.01f,-102925f,-68042.7f,6179.01f,-102925f,-68042.7f,6276.06f,-40907.1f,-14694f,6179.01f,-102925f,-68042.7f,6276.06f,-41713.9f,-13886.7f,6269.01f,-103571f,-67018.6f,6022.45f,-21752.5f,23.5976f,6022.45f,-26787.1f,-4300.36f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,6178.41f,-102089f,-68973.2f,6178.41f,-102089f,-68973.2f,6022.45f,-101057f,-70411.1f }; public String objectName; public int triangleCount; public int verticeCount; public float[] vertices; public float[] normals; public float[] textures; public short[] indices; public float[] matrices; public float[] pivots; public float[] animations; public void awake() { ByteBuffer vbb = ByteBuffer.allocateDirect(verticeTest.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asFloatBuffer(); mVertexBuffer.put(verticeTest); mVertexBuffer.position(0); ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length * 4); tbb.order(ByteOrder.nativeOrder()); mTextureBuffer = tbb.asFloatBuffer(); mTextureBuffer.put(textures); mTextureBuffer.position(0); //short has 2 bytes ByteBuffer ibb = ByteBuffer.allocateDirect(indicesTest.length*2); ibb.order(ByteOrder.nativeOrder()); indexBuffer = ibb.asShortBuffer(); indexBuffer.put(indicesTest); indexBuffer.position(0); verticeCount = (triangleCount*3); } public void draw(GL10 gl) { System.out.println("Draw Method Called in Object"); gl.glEnable(GL10.GL_TEXTURE_2D); //workaround bug 3623 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); System.out.println("Triangle Vertice Count is "+verticeCount); int x = vertices.length; System.out.println("Rendering following number of vertices "+x); int y = indices.length; System.out.println("Rendering following number of indices "+y); gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer); } } And here is the code where I call the draw method : import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Iterator; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLU; class GLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "GLRenderer"; private final Context context; private final GLCube cube = new GLCube(); private long startTime; private long fpsStartTime; private long numFrames; SceneObject drawObject; SceneObject object; //Used for object position and rotation. float zRotation; float xRotation; float yRotation; float kxRotation = 0.0f; float kyRotation = 0.0f; ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); boolean SEE_THRU = false; GLRenderer(Context context) { this.context = context; } public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Setup any OpenGL Options that are required. gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glEnable(GL10.GL_TEXTURE_2D); if (SEE_THRU) { gl.glDisable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); } //Optional - disable dither to boost peformance. //gl.glDisable(GL10.GL_DITHER); //Dithering enabled by default. //Turn on the lights. float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1}; float lightDiffuse[] = new float[] {1, 1, 1, 1}; float[] lightPos = new float[] {1 ,1 ,1 , 1}; gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0); //Specify which materials we should use. float matAmbient[] = new float[] {1, 1, 1, 1}; float matDiffuse[] = new float[] {1, 1, 1, 1}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0); } public void onSurfaceChanged(GL10 gl, int width, int height) { //Define the view frustrum gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); float ratio = (float)width/height; gl.glLoadIdentity(); //gl.glOrthof(0, 480f, 800f, 0, 0, 1); GLU.gluPerspective(gl, 45.0f, ratio, 1.0f, 100f); } public void onDrawFrame (GL10 gl) { //Defs for rotation of object. float kzRotation = 0.0f; kyRotation +=1.0f; kxRotation =280.0f; gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); SceneObject object = sceneObjects.get(13); //Get the object //Position the model. gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -30.0f); gl.glScalef(0.0001f, 0.0001f, 0.0001f); zRotation = kzRotation; xRotation = kxRotation; yRotation = kyRotation; gl.glRotatef(yRotation, 0.0f, 1.0f, 0.0f); gl.glRotatef(xRotation, 1.0f, 0.0f, 0.0f); gl.glRotatef(zRotation, 0.0f, 0.0f, 1.0f); object.draw(gl); } } } The problem is that the object is not displaying as it should, but instead looks warped and squashed. Can anyone spot what might be wrong ? EDIT - Changed the onSufaceChanged method as per Tim's answer below, however no improvement. I've added an image of how the object is rendering on Android and the same object rendering correct on the iPhone. The most noticeable problem is that the "legs" should be straight and not bend and overall the object should be much longer. I'm sure the vertices and indices in the code above are correct (they are exactly the same as the iPhone ones). In case it is relevant here is how I am setting up the surfaceview / view: public class SaxParserActivity extends Activity { /** Called when the activity is first created. */ ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); GLView view; view = new GLView(this, sceneObjects); //Pass down our sceneObjects into the view class. //view.sceneObjects = sceneObjects; setContentView(view); } } class GLView extends GLSurfaceView { private final GLRenderer renderer; ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); GLView(Context context, ArrayList<SceneObject> sceneObjects) { super (context); //Uncomment this to turn on error-checking and logging. //setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); renderer = new GLRenderer(context); //Pass down our sceneObjects. renderer.sceneObjects = sceneObjects; setRenderer(renderer); } }
I'm a bit confused by what you're doing. Why do you wipe on the projection matrix in onDrawFrame, after setting it in onSurfaceChanged? You should set projection in onSurfaceChanged like so: public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); //make sure to reset before glOrthof gl.glOrthof(0, 320f, 480f, 0, 0, 1); } And then change back to modelview and don't disturb the projection matrix during onDrawFrame. You'll probably need to recalibrate your scale and translate in onDrawFrame as well after doing this.