This line
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 2);
renders nothing. You need to put the number or vertices (6 in your case) there, not the number of primitives.
Question
I'm trying to draw a fairly simple scene:
A white quad (made out of two triangles) with corners (-0.5, -0.5)
, (0.5, -0.5)
, (-0.5, 0.5)
and (0.5, 0.5)
on a pink background. But somehow the quad doesn't end up on the screen.
I'm running the code with the lwjgl-debug.jar and lwjgl in debug mode but not a single error is reported back. I'm probalbly missing something small but I am unable to find it.
Here's the code:
GridShaderTest.java
import java.io.File;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
public class GridShaderTest {
private static final int WIDTH = 1024;
private static final int HEIGHT = Math.round(WIDTH/16f*9);
private int meshBufferID;
private int vaoID;
public GridShaderTest() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.create();
Display.setTitle("Beneath the Surface");
GL11.glClearColor(0.8f, 0f, 0.8f, 1f);
GL11.glViewport(0, 0, WIDTH, HEIGHT);
} catch(LWJGLException e) {
e.printStackTrace();
System.exit(1);
}
final Shader shader = new Shader(new File("target/classes/shaders/tileshader"), new String[] {"pos", "inColor"}, new String[] {});
createMeshBuffer();
createVAO(shader);
while(!Display.isCloseRequested()) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
shader.use();
GL30.glBindVertexArray(vaoID);
shader.enableVAttributes();
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 2);
shader.disableVAttributes();
GL30.glBindVertexArray(0);
GL20.glUseProgram(0);
Display.sync(60);
Display.update();
}
Display.destroy();
}
private void createMeshBuffer() {
// Layout: x,y,r,g,b
meshBufferID = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, meshBufferID);
final FloatBuffer meshBuffer = BufferUtils.createFloatBuffer(30);
meshBuffer
.put(-0.5f).put(-0.5f) .put(1f).put(1f).put(1f)
.put(0.5f).put(-0.5f) .put(1f).put(1f).put(1f)
.put(-0.5f).put(0.5f) .put(1f).put(1f).put(1f)
.put(-0.5f).put(0.5f) .put(1f).put(1f).put(1f)
.put(0.5f).put(-0.5f) .put(1f).put(1f).put(1f)
.put(0.5f).put(0.5f) .put(1f).put(1f).put(1f);
meshBuffer.flip();
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, meshBuffer, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void createVAO(Shader shader) {
vaoID = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, meshBufferID);
GL20.glVertexAttribPointer(shader.getAttribLocation("pos"), 2, GL11.GL_FLOAT, false, 20, 0);
GL20.glVertexAttribPointer(shader.getAttribLocation("inColor"), 3, GL11.GL_FLOAT, false, 20, 8);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
public static void main(String[] args) {
new GridShaderTest();
}
}
tileshader/vert.glsl
#version 150 core
in vec2 pos;
in vec3 inColor;
out vec3 passColor;
void main() {
gl_Position = vec4(pos, 0.0f, 1.0f);
passColor = inColor;
}
tileshader/frag.glsl
#version 150 core
in vec3 passColor;
out vec4 fragColor;
void main() {
fragColor = vec4(passColor, 1.0f);
}
I'm pretty sure the Shader
class is correct but for completeness here it is:
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VALIDATE_STATUS;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.OpenGLException;
public class Shader {
public final int id;
public final Map<String, Integer> attribLocations, uniformLocations;
public Shader(File path, String[] attribNames, String[] uniformNames) {
final int vsID = loadShader(new File(path, "vert.glsl"), GL20.GL_VERTEX_SHADER);
final int fsID = loadShader(new File(path, "frag.glsl"), GL20.GL_FRAGMENT_SHADER);
id = GL20.glCreateProgram();
GL20.glAttachShader(id, vsID);
GL20.glAttachShader(id, fsID);
GL20.glLinkProgram(id);
checkLinkage(id);
GL20.glValidateProgram(id);
checkValidation(id);
GL20.glDetachShader(id, vsID);
GL20.glDetachShader(id, fsID);
GL20.glDeleteShader(vsID);
GL20.glDeleteShader(fsID);
attribLocations = new HashMap<>(attribNames.length+1, 1);
for(String name: attribNames) {
attribLocations.put(name, GL20.glGetAttribLocation(id, name));
}
uniformLocations = new HashMap<>(uniformNames.length+1, 1);
for(String name: uniformNames) {
uniformLocations.put(name, GL20.glGetUniformLocation(id, name));
}
}
public void use() {
GL20.glUseProgram(id);
}
public void unload() {
GL20.glDeleteProgram(id);
}
public int getAttribLocation(String name) {
return attribLocations.get(name);
}
public int getUniformLocation(String name) {
return uniformLocations.get(name);
}
public void enableVAttributes() {
for(String s: attribLocations.keySet()) {
GL20.glEnableVertexAttribArray(attribLocations.get(s));
}
}
public void disableVAttributes() {
for(String s: attribLocations.keySet()) {
GL20.glDisableVertexAttribArray(attribLocations.get(s));
}
}
private static int loadShader(File file, int type) {
final StringBuilder builder = new StringBuilder();
try(BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while((line = reader.readLine()) != null) {
builder.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(2);
}
final int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, builder);
GL20.glCompileShader(shaderID);
checkCompilation(shaderID);
return shaderID;
}
private static void checkValidation(int programID) {
int error = glGetProgrami(programID, GL_VALIDATE_STATUS);
if(error == GL_FALSE) {
throw new OpenGLException(glGetProgramInfoLog(programID, glGetProgrami(programID, GL_INFO_LOG_LENGTH)));
}
}
private static void checkCompilation(int shaderID) {
int error = glGetShaderi(shaderID, GL_COMPILE_STATUS);
if(error == GL_FALSE) {
throw new OpenGLException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
}
}
private static void checkLinkage(int programID) {
int error = glGetProgrami(programID, GL_LINK_STATUS);
if(error == GL_FALSE) {
throw new OpenGLException(glGetProgramInfoLog(programID, glGetProgrami(programID, GL_INFO_LOG_LENGTH)));
}
}
}
Solution
This line
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 2);
renders nothing. You need to put the number or vertices (6 in your case) there, not the number of primitives.