So Im following this tutorial on Youtube and I seem to have made an error somewhere.
Full Error:
Exception in thread "main" org.lwjgl.opengl.OpenGLException: Invalid operation (1282)
at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
at org.lwjgl.opengl.GL11.glDrawArrays(GL11.java:1205)
at renderEngine.Renderer.render(Renderer.java:21)
at engineTester.MainGameLoop.main(MainGameLoop.java:33)
Code:
Renderer.java:
package renderEngine;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import renderEngine.RawModel;
public class Renderer {
public void prepare() {
GL11.glClearColor(1, 0, 0, 1);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
}
public void render(RawModel model) {
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLE, 0, model.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
RawModel.java
package renderEngine;
public class RawModel {
private int vaoID;
private int vertexCount;
public RawModel(int vaoID, int vertexCount) {
this.vaoID = vaoID;
this.vertexCount = vertexCount;
}
public int getVaoID() {
return vaoID;
}
public int getVertexCount() {
return vertexCount;
}
}
MainGameLoop.java:
package engineTester;
import org.lwjgl.opengl.Display;
import renderEngine.DisplayManager;
import renderEngine.Loader;
import renderEngine.RawModel;
import renderEngine.Renderer;
public class MainGameLoop {
public static void main(String[] args) {
DisplayManager.createDisplay();
Loader loader = new Loader();
Renderer renderer = new Renderer();
float[] vertices = {
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f
};
RawModel model = loader.loadToVao(vertices);
while(!Display.isCloseRequested()) {
renderer.prepare();
renderer.render(model);
DisplayManager.updateDisplay();
}
loader.cleanUp();
DisplayManager.closeDisplay();
}
}
DisplayManager.java:
package renderEngine;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.PixelFormat;
public class DisplayManager {
private static final int WIDTH = 1280;
private static final int HEIGHT = 720;
private static final int FPSCAP = 120;
public static void createDisplay() {
ContextAttribs attribs = new ContextAttribs(3,2).withForwardCompatible(true).withProfileCore(true);
try {
Display.setDisplayMode(new DisplayMode(WIDTH,HEIGHT));
Display.create(new PixelFormat(), attribs);
Display.setTitle("Game");
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glViewport(0, 0, WIDTH, HEIGHT);
}
public static void updateDisplay() {
Display.sync(FPSCAP);
Display.update();
}
public static void closeDisplay() {
Display.destroy();
}
}
Loader.java:
package renderEngine;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
public RawModel loadToVao(float[] positions) {
int vaoID = createVAO();
storeDataInAttributeList(0,positions);
unbindVAO();
return new RawModel(vaoID,positions.length/3);
}
public void cleanUp() {
for(int vao:vaos) {
GL30.glDeleteVertexArrays(vao);
}
for(int vbo:vbos) {
GL15.glDeleteBuffers(vbo);
}
}
private int createVAO() {
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
private void storeDataInAttributeList(int attributeNumber, float[] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void unbindVAO() {
GL30.glBindVertexArray(0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
I do see that it is telling me that something is wrong in the renderer file at line 21 and it ran into the error while performing MainGameLoop line 33
But other than that, I cant figure it out.
I am using Java SDK 8
LWJGL 2.8.9 (or something like that)
Related
source:
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
public RawModel loadToVAO(float[] positions) {
int vaoID = createVAO();
storeDataInAttributeList(0,positions);
unbindVAO();
return new RawModel(vaoID,positions.length/3);
}
public void cleanUP() {
for(int vao:vaos) {
GL30.glDeleteVertexArrays(vao);
}
for(int vbo:vbos) {
GL30.glDeleteVertexArrays(vbo);
}
}
private int createVAO() {
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
private void storeDataInAttributeList(int attributeNumber,float[] data) {
int vaoID = GL15.glGenBuffers();
vbos.add(vaoID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vaoID);
FloatBuffer buffer = storeDataImFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void unbindVAO(){
GL30.glBindVertexArray(0);
}
private FloatBuffer storeDataImFloatBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
error:
FATAL ERROR in native method: Thread[main,5,main]: No context is current or a function that is not available in the current context was called.
The JVM will abort execution.
at org.lwjgl.opengl.GL30C.nglGenVertexArrays(Native Method)
at org.lwjgl.opengl.GL30C.glGenVertexArrays(GL30C.java:2420)
at org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:2369) at Loader.createVAO(Loader.java:32)
at Loader.loadToVAO(Loader.java:16) at MainGameLoop.main(MainGameLoop.java:21)
You have not called glfwMakeContextCurrent(window) or GL.createCapabilities() to actually make the OpenGL context. Add these two lines just after window creation.
If you are on macOS do this after the display creation in LWJGL 3:
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 1);
I want to create isometric 2D game. I use modern LWJGL (vertex arrays, shaders etc.) I found true isometric projection with opengl and: I tried to rotate my projection matrix, but it created black triangles on corners of screen. I tried to rotate model matrix, but I found that I can't rotate x and y on ortho matrix (because it's 2D), it does
but I need to rotate x and y axis to get isometric matrix. Then I found this https://www.gamedev.net/blog/33/entry-2250273-isometric-map-in-sfml/ and it says that I only need place tiles on right spots. Who is right? And why in first link they rotate model matrix in old OpenGL even though it's 2D projection matrix and I can't rotate it on modern OpenGL? (Sorry for my bad English)
Edit: How I create model matrix (I use joml for them):
public Matrix4f getModel(GameItem item){
Vector3f rot = item.getRotation();
return new Matrix4f().translate(item.getPosition()).rotateX((float)Math.toRadians(-rot.x)).rotateY((float)Math.toRadians(-rot.y)).rotateZ((float)Math.toRadians(-rot.z)).scale(item.getScale());
}
How I create projection matrix:
public void updateProjectionMatrix(Window window){
projectionMatrix2D.identity().ortho2D(-window.getWidth(), window.getWidth(), -window.getHeight(), window.getHeight());
}
If I rotate matrix before ortho2D() everything is rotated correctly, however there are black triangles on two of screen's corners. If I rotate it after ortho2D() it does exactly like rotating model matrix (shrinks object). In render() I pass matrixes to vertex shader:
#version 330
layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;
out vec2 outTexCoord;
uniform mat4 projectionMatrix;
uniform mat4 model;
void main()
{
gl_Position = projectionMatrix* model * vec4(position, 1.0);
outTexCoord = texCoord;
}
Edit 2:
Creating view matrix works:
However it does exactly like rotating projection matrix before ortho2D() - it creates black (because that's my clear color) triangles on two of screen's corners:
and there:
How do I get rid of them?
Edit 3:
I rewrote my code, but nothing has changed.
To run my code, you should add to project LWJGL library, LWJGL-GLFW, LWJGL-STB, LWJGL-OpenGl and JOML library (it's not downloaded with LWJGL). You will also need a random .png image.
Main class:
import Core.Engine;
public class Main {
public static void main(String[] args){
try{
//Is vsync enabled?
boolean vsync = true;
Engine engine = new Engine("GAME", vsync);
//Start program
engine.start();
}
catch(Exception ex){
ex.printStackTrace();
System.exit(-1);
}
}
}
Engine class:
package Core;
public class Engine implements Runnable{
public static final int TARGET_FPS = 60;
public static final int TARGET_UPS = 30;
private final Window window;
//Program thread
private final Thread gameLoopThread;
//Timer for gameLoop
private final Timer timer;
//Creates everything that is on screen
private final Logic logic;
public Engine(String windowTitle, boolean vSync) throws Exception {
gameLoopThread = new Thread(this, "GAME_LOOP_THREAD");
window = new Window(windowTitle, vSync);
logic = new Logic();
timer = new Timer();
}
public void start() {
String osName = System.getProperty("os.name");
if ( osName.contains("Mac") ) {
gameLoopThread.run();
} else {
gameLoopThread.start();
}
}
#Override
public void run() {
try {
init();
gameLoop();
} catch (Exception excp) {
excp.printStackTrace();
}
}
protected void init() throws Exception {
window.init();
timer.init();
logic.init(this.window);
}
protected void gameLoop() {
float elapsedTime;
float accumulator = 0f;
float interval = 1f / TARGET_UPS;
boolean running = true;
while (running && !window.shouldClose()) {
elapsedTime = timer.getElapsedTime();
accumulator += elapsedTime;
input();
while (accumulator >= interval) {
update(interval);
accumulator -= interval;
}
render();
if (!window.isVsync()) {
sync();
}
}
}
private void sync() {
float loopSlot = 1f / TARGET_FPS;
double endTime = timer.getLastLoopTime() + loopSlot;
while (Timer.getTime() < endTime) {
try {
Thread.sleep(1);
} catch (InterruptedException ie) {
}
}
}
protected void input() {
logic.input(window);
}
protected void update(float interval) {
logic.update(interval,window);
}
protected void render() {
logic.render(window);
window.update();
}
}
Timer class:
package Core;
public class Timer {
private double lastLoopTime;
public void init(){
lastLoopTime = getTime();
}
public static double getTime(){
return (double)((double)System.nanoTime() / (double)1000_000_000L);
}
public float getElapsedTime(){
double time = getTime();
float elapsedTime =(float) (time-lastLoopTime);
lastLoopTime = time;
return elapsedTime;
}
public double getLastLoopTime(){
return lastLoopTime;
}
}
Window class:
package Core;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
public class Window {
private long window;
private int width, height;
private boolean vsync;
private String title;
public Window(String title,boolean vsync){
this.title = title;
this.vsync = vsync;
}
public long getInstance(){
return window;
}
public void init(){
GLFWErrorCallback.createPrint(System.err).set();
if(!glfwInit()){
// Throw an error.
throw new IllegalStateException("GLFW initialization failed!");
}
glfwWindowHint(GLFW_VISIBLE, GL_TRUE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // the window will not be resizable
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
width = vidmode.width();
height = vidmode.height() -30;
System.out.println(width + " "+ height);
window = GLFW.glfwCreateWindow(width,height, title,NULL, NULL);
if(window == NULL){
throw new RuntimeException("ERROR with Window");
}
GLFW.glfwSetWindowPos(window, 0, 29);
glfwMakeContextCurrent(window);
if(vsync)
GLFW.glfwSwapInterval(1);
glfwShowWindow(window);
GL.createCapabilities();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
public boolean isKeyPressed(int keyCode) {
return GLFW.glfwGetKey(window, keyCode) == GLFW.GLFW_PRESS;
}
public void setClearColor(float r, float g, float b, float alpha) {
glClearColor(r, g, b, alpha);
}
public boolean shouldClose(){
return glfwWindowShouldClose(window);
}
public void update(){
glfwSwapBuffers(window);
glfwPollEvents();
}
public void setVsync(boolean aflag){
this.vsync = aflag;
}
public boolean isVsync(){
return vsync;
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
}
Logic class:
package Core;
import org.joml.Vector3f;
import org.lwjgl.glfw.GLFW;
public class Logic {
private Renderer render;
private GameItem item;
public void init(Window window) throws Exception {
//create object
float[] positions = new float[]{
-600, 600, 0f,//0
-600, -600, 0f,//1
600, -600, 0,//2
600, 600, 0f//3
};
float[] texCoords = new float[]{
0,0,//0
0,1,//1
1,1,//2
1,0 //3
};
int[] indices = new int[]{
0, 1, 3, 3, 1, 2,
};
render = new Renderer();
render.init(window);
Texture texture = new Texture("Textures/image.png");
Mesh mesh = new Mesh(positions,texCoords,indices,texture);
item = new GameItem(mesh);
item.setPosition(-100, 0, 0);
}
public void input(Window window) {
//move
Vector3f s = item.getPosition();
if(window.isKeyPressed(GLFW.GLFW_KEY_W)){
item.setPosition(s.x, s.y+5, s.z);
}
else if(window.isKeyPressed(GLFW.GLFW_KEY_S)){
item.setPosition(s.x, s.y-5, s.z);
}
else if(window.isKeyPressed(GLFW.GLFW_KEY_A)){
item.setPosition(s.x-5, s.y, s.z);
}
else if(window.isKeyPressed(GLFW.GLFW_KEY_D)){
item.setPosition(s.x+5, s.y, s.z);
}
}
public void update(float interval, Window window) {
}
public void render(Window window) {
render.render(window,item);
}
public void cleanup() {
render.cleanup();
}
}
Renderer class:
package Core;
import static org.lwjgl.opengl.GL11.*;
import org.joml.Matrix4f;
import org.joml.Vector3f;
public class Renderer {
private Matrix4f projectionMatrix2D;
private Matrix4f view;
private ShaderProgram shaderProgram;
public Renderer() {
projectionMatrix2D= new Matrix4f();
}
public void init(Window window) throws Exception {
shaderProgram = new ShaderProgram();
shaderProgram.createVertexShader(Utils.load("Shaders/vertex.vs"));
shaderProgram.createFragmentShader(Utils.load("Shaders/fragment.fs"));
shaderProgram.link();
shaderProgram.createUniform("projectionMatrix");
shaderProgram.createUniform("model");
shaderProgram.createUniform("texture_sampler");
shaderProgram.createUniform("view");
view = new Matrix4f().lookAt(new Vector3f(1,1,1), new Vector3f(0), new Vector3f(0,1,0));
updateProjectionMatrix(window);
}
public void clear() {
glClear(GL_COLOR_BUFFER_BIT);
}
public void render(Window window,GameItem item) {
clear();
updateProjectionMatrix(window);
shaderProgram.bind();
shaderProgram.setUniform("projectionMatrix", projectionMatrix2D);
shaderProgram.setUniform("view", view);
shaderProgram.setUniform("texture_sampler", 0);
Vector3f rot = item.getRotation();
Matrix4f model = new Matrix4f().translate(item.getPosition()).rotateX((float)Math.toRadians(-rot.x))
.rotateY((float)Math.toRadians(-rot.y))
.rotateZ((float)Math.toRadians(-rot.z))
.scale(item.getScale());
shaderProgram.setUniform("model", model);
item.getMesh().render();
shaderProgram.unbind();
}
public void updateProjectionMatrix(Window window){
projectionMatrix2D.identity().ortho2D(-window.getWidth(), window.getWidth(), -window.getHeight(), window.getHeight());
//it creates weird triangle on right screen corner
// projectionMatrix2D.identity().ortho2D(-1, 1, -1, 1);
}
public void cleanup() {
if (shaderProgram != null) {
shaderProgram.cleanup();
}
}
}
ShaderProgram class:
package Core;
import static org.lwjgl.opengl.GL20.*;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;
import org.joml.Matrix4f;
import org.joml.Vector2f;
import org.joml.Vector3f;
import org.lwjgl.system.MemoryStack;
public class ShaderProgram {
private final int programId;
private int vertexShaderId;
private int fragmentShaderId;
private final Map<String, Integer> uniforms;
public ShaderProgram() throws Exception {
programId = glCreateProgram();
if (programId == 0) {
throw new Exception("Could not create Shader");
}
uniforms = new HashMap<>();
}
public void createUniform(String uniformName) throws Exception {
int uniformLocation = glGetUniformLocation(programId, uniformName);
if (uniformLocation < 0) {
throw new Exception("Could not find uniform:" + uniformName);
}
uniforms.put(uniformName, uniformLocation);
}
public void setUniform(String uniformName, Matrix4f value) {
try (MemoryStack stack = MemoryStack.stackPush()) {
FloatBuffer fb = stack.mallocFloat(16);
value.get(fb);
glUniformMatrix4fv(uniforms.get(uniformName), false, fb);
}
}
public void setUniform(String uniformName, int value) {
glUniform1i(uniforms.get(uniformName), value);
}
public void setUniform(String uniformName, float value) {
glUniform1f(uniforms.get(uniformName), value);
}
public void setUniform(String uniformName, Vector3f value) {
glUniform3f(uniforms.get(uniformName), value.x, value.y, value.z);
}
public void setUniform(String uniformName, org.joml.Vector4f value) {
glUniform4f(uniforms.get(uniformName), value.x, value.y, value.z, value.w);
}
public void setUniform(String uniformName, Vector2f vector2f) {
glUniform2f(uniforms.get(uniformName),vector2f.x,vector2f.y);
}
public void createVertexShader(String shaderCode) throws Exception {
vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
}
public void createFragmentShader(String shaderCode) throws Exception {
fragmentShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
}
protected int createShader(String shaderCode, int shaderType) throws Exception {
int shaderId = glCreateShader(shaderType);
if (shaderId == 0) {
throw new Exception("Error creating shader. Type: " + shaderType);
}
glShaderSource(shaderId, shaderCode);
glCompileShader(shaderId);
if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) {
throw new Exception("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024));
}
glAttachShader(programId, shaderId);
return shaderId;
}
public void link() throws Exception {
glLinkProgram(programId);
if (glGetProgrami(programId, GL_LINK_STATUS) == 0) {
throw new Exception("Error linking Shader code: " + glGetProgramInfoLog(programId, 1024));
}
if (vertexShaderId != 0) {
glDetachShader(programId, vertexShaderId);
}
if (fragmentShaderId != 0) {
glDetachShader(programId, fragmentShaderId);
}
glValidateProgram(programId);
if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
System.err.println("Warning validating Shader code: " + glGetProgramInfoLog(programId, 1024));
}
}
public void bind() {
glUseProgram(programId);
}
public void unbind() {
glUseProgram(0);
}
public void cleanup() {
unbind();
if (programId != 0) {
glDeleteProgram(programId);
}
}
}
GameItem class:
package Core;
import org.joml.Vector3f;
public class GameItem {
//Mesh for this gameItem
private Mesh mesh;
private final Vector3f position;
private float scale = 1;
private final Vector3f rotation;
public GameItem() {
position = new Vector3f(0, 0, 0);
scale = 1;
rotation = new Vector3f(0, 0, 0);
}
public GameItem(Mesh mesh) {
this();
this.mesh = mesh;
}
public GameItem(GameItem item){
this();
position.set(item.position);
scale =1;
rotation.set(item.rotation);
this.mesh = item.mesh;
}
public Vector3f getPosition() {
return position;
}
public void setPosition(float x, float y, float z) {
this.position.x = x;
this.position.y = y;
this.position.z = z;
}
public float getScale() {
return scale;
}
public void setScale(float scale) {
this.scale = scale;
}
public Vector3f getRotation() {
return rotation;
}
public void setRotation(float x, float y, float z) {
this.rotation.x = x;
this.rotation.y = y;
this.rotation.z = z;
}
public Mesh getMesh() {
return mesh;
}
public void setMesh(Mesh mesh){
this.mesh = mesh;
}
}
Utils class:
package Core;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Utils {
//Load strings
public static String load(String path){
StringBuilder builder = new StringBuilder();
try (InputStream in = new FileInputStream(path);
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
String line;
while ((line = reader.readLine()) != null) {
builder.append(line).append("\n");
}
} catch (IOException ex) {
throw new RuntimeException("Failed to load a shader file!"
+ System.lineSeparator() + ex.getMessage());
}
String source = builder.toString();
return source;
}
}
Mesh class:
package Core;
import java.util.List;
import org.lwjgl.system.MemoryUtil;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
public class Mesh{
private final int vaoId;
private final List<Integer> vboIdList;
private final int vertexCount;
private Texture texture;
public Mesh(float[] positions, float[] textCoords, int[] indices,Texture texture) {
this.texture = texture;
FloatBuffer posBuffer = null;
FloatBuffer textCoordsBuffer = null;
IntBuffer indicesBuffer = null;
try {
vertexCount = indices.length;
vboIdList = new ArrayList<>();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
// Position
int vboId = glGenBuffers();
vboIdList.add(vboId);
posBuffer = MemoryUtil.memAllocFloat(positions.length);
posBuffer.put(positions).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, posBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
// Texture coordinates
vboId = glGenBuffers();
vboIdList.add(vboId);
textCoordsBuffer = MemoryUtil.memAllocFloat(textCoords.length);
textCoordsBuffer.put(textCoords).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, textCoordsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
// Index
vboId = glGenBuffers();
vboIdList.add(vboId);
indicesBuffer = MemoryUtil.memAllocInt(indices.length);
indicesBuffer.put(indices).flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
} finally {
if (posBuffer != null) {
MemoryUtil.memFree(posBuffer);
}
if (textCoordsBuffer != null) {
MemoryUtil.memFree(textCoordsBuffer);
}
if (indicesBuffer != null) {
MemoryUtil.memFree(indicesBuffer);
}
}
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public int getVaoId() {
return vaoId;
}
public int getVertexCount() {
return vertexCount;
}
public void cleanUp() {
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
for (int vboId : vboIdList) {
glDeleteBuffers(vboId);
}
texture.cleanup();
glBindVertexArray(0);
glDeleteVertexArrays(vaoId);
}
public void render(){
glBindVertexArray(getVaoId());
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, getVertexCount(), GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
}
}
Texture class:
package Core;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.lwjgl.system.MemoryStack;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL30.glGenerateMipmap;
import static org.lwjgl.stb.STBImage.*;
public class Texture {
private final int id;
public Texture(String fileName) throws Exception {
this(loadTexture(fileName));
}
public Texture(int id) {
this.id = id;
}
public void bind() {
glBindTexture(GL_TEXTURE_2D, id);
}
public int getId() {
return id;
}
private static int loadTexture(String fileName) throws Exception {
int width;
int height;
ByteBuffer buf;
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer channels = stack.mallocInt(1);
buf = stbi_load(fileName, w, h, channels, 4);
if (buf == null) {
throw new Exception("Image file " + fileName + " not loaded: " + stbi_failure_reason());
}
width = w.get();
height = h.get();
}
int textureId = glGenTextures();
glBindTexture(GL_TEXTURE_2D, textureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, buf);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(buf);
return textureId;
}
public void cleanup() {
glDeleteTextures(id);
}
}
Vertex shader:
#version 330
layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;
out vec2 outTexCoord;
uniform mat4 projectionMatrix;
uniform mat4 model;
uniform mat4 view;
void main()
{
gl_Position = projectionMatrix * view * model * vec4(position, 1.0); // if view is after vec4 it creates actually object, but it creates black triangles as well. Without view matrix it is just a normal square
outTexCoord = texCoord;
}
Fragment shader:
#version 330
in vec2 outTexCoord;
out vec4 fragColor;
uniform sampler2D texture_sampler;
void main()
{
fragColor = texture(texture_sampler,outTexCoord);
}
I have been spending the last few days trying to scale a texture to a Quad (OpenGL 3)...
But for some reason I am getting only the top left pixel of the image rendered on to the quad, I am using Slick-Utils to load and bind the texture....
Here is the code:
MainGame.java
package test.game;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.PixelFormat;
import org.newdawn.slick.opengl.Texture;
import test.engine.Loader;
import test.engine.rendersystem.Model;
import test.engine.rendersystem.ShaderProgram;
import static org.lwjgl.opengl.GL11.*;
import java.io.IOException;
import java.util.HashMap;
public class MainGame {
// Constants
public static final String WINDOW_TITLE = "Neon Indev";
public static final int WIDTH = 800;
public static final int HEIGHT = 480;
public static final ContextAttribs OPENGL_CONTEXTS_ATTRIBS = new ContextAttribs(3, 2).withForwardCompatible(true).withProfileCore(true);
public static final int SYNC_FPS = 60;
static float[] vertexData =
{
-0.5f, 0.5f,
0.5f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f
};
static float[] colorData = { 0f, 1f, 1f, 1f,
0f, 1f, 1f, 1f,
0f, 1f, 1f, 1f,
0f, 1f, 1f, 1f,
0f, 1f, 1f, 1f,
0f, 1f, 1f, 1f};
static int[] indexData = {
0, 1, 3,
3, 1, 2
};
static float[] texData = {
0,0,
1,0,
1,1,
0,1
};
static Model model;
static ShaderProgram shader;
static Texture testTexture;
public static void main(String[] args) {
init();
render();
}
private static void init() {
// Display Initialization
try {
Display.setTitle(WINDOW_TITLE);
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.create(new PixelFormat(), OPENGL_CONTEXTS_ATTRIBS);
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(1);
}
// OpenGL Initialization
glViewport(0, 0, WIDTH, HEIGHT);
glClearColor(0f, 0f, 0f, 1f);
model = new Model(vertexData, colorData, indexData);
try {
testTexture = Loader.loadTexture("res/images/png/image02 (1).png", "PNG");
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
model.setTexture(testTexture, texData);
// Shader Initialization
HashMap<String, Integer> vboDataToBind = new HashMap<String, Integer>();
vboDataToBind.put("in_Position", Model.ATTRIB_VERTEX);
vboDataToBind.put("in_Color", Model.ATTRIB_COLOR);
vboDataToBind.put("in_TextureCoord", Model.ATTRIB_TEXTURE);
shader = new ShaderProgram("res/shaders/frag/color.frag", "res/shaders/vert/color.vert", true, true, vboDataToBind);
}
private static void render() {
// Resize Check
if (Display.wasResized()) {
resize();
}
// Render loop
while (!Display.isCloseRequested()) {
glClear(GL_COLOR_BUFFER_BIT);
shader.bind();
model.render();
shader.unbind();
Display.update();
Display.sync(SYNC_FPS);
}
// Dispose if out of the loop
dispose();
}
private static void resize() {
// Resize code goes here
}
private static void dispose() {
model.dispose();
shader.dispose();
Display.destroy();
}
}
ShaderProgram.java
package test.game.engine.rendersystem;
import java.io.IOException;
import java.util.HashMap;
import java.util.Set;
import test.engine.Loader;
import static org.lwjgl.opengl.GL20.*;
public class ShaderProgram {
String fragmentShader;
String vertexShader;
int programID, vertexShaderID, fragmentShaderID;
boolean initialized;
public ShaderProgram(String fragmentShader, String vertexShader, boolean url, boolean init, HashMap<String, Integer> vboDataToBind) {
if (url) {
try {
this.fragmentShader = Loader.getStringFromTextFile(fragmentShader);
this.vertexShader = Loader.getStringFromTextFile(vertexShader);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
} else {
this.fragmentShader = fragmentShader;
this.vertexShader = vertexShader;
}
if (init) {
init(vboDataToBind);
this.initialized = true;
} else {
this.initialized = false;
}
}
public void init(HashMap<String, Integer> vboDataToBind) {
if (!initialized) {
// Initialize the shaders
vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Setting up the shader values
glShaderSource(vertexShaderID, vertexShader);
glShaderSource(fragmentShaderID, fragmentShader);
// Compile the shaders
glCompileShader(vertexShaderID);
glCompileShader(fragmentShaderID);
// Create the shader program and attach them
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
// Bind any needed data
if (!vboDataToBind.isEmpty()) {
Set<String> keys = vboDataToBind.keySet();
for (String key : keys) {
bindVBOAttrib(vboDataToBind.get(key), key);
}
}
// Link and validate the program
glLinkProgram(programID);
glValidateProgram(programID);
}
}
public void bind() {
glUseProgram(programID);
}
public void unbind() {
glUseProgram(0);
}
public void dispose() {
glDeleteProgram(programID);
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
}
public void bindVBOAttrib(int attribNumber, String variableName) {
glBindAttribLocation(programID, attribNumber, variableName);
}
public String getFragmentShader() {
return fragmentShader;
}
public String getVertexShader() {
return vertexShader;
}
public int getProgramID() {
return programID;
}
public int getVertexShaderID() {
return vertexShaderID;
}
public int getFragmentShaderID() {
return fragmentShaderID;
}
}
Vertex Shader:
#version 150 core
in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;
out vec4 pass_Color;
out vec2 pass_TextureCoord;
void main(void) {
gl_Position = in_Position;
pass_Color = in_Color;
pass_TextureCoord = in_TextureCoord;
}
Fragment Shader:
#version 150 core
uniform sampler2D texture_diffuse;
in vec4 pass_Color;
in vec2 pass_TextureCoord;
out vec4 out_Color;
void main(void) {
out_Color = pass_Color;
// Override out_Color with our texture pixel
out_Color = texture(texture_diffuse, pass_TextureCoord);
}
Loader.java
package test.game.engine;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
public class Loader {
public static String getStringFromTextFile(String url) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(new File(url)));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line).append("\n");
}
reader.close();
return response.toString();
}
public static Texture loadTexture(String url, String format) throws IOException {
return TextureLoader.getTexture(format, ResourceLoader.getResourceAsStream(url));
}
}
Model.java
package test.game.engine.rendersystem;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL11.*;
import org.newdawn.slick.opengl.Texture;
public class Model {
// Attribute Numbers
public static final int ATTRIB_VERTEX = 0;
public static final int ATTRIB_INDEX = 1;
public static final int ATTRIB_COLOR = 2;
public static final int ATTRIB_TEXTURE = 3;
// Dimensions
public static final int DIMEN_VERTEX = 2;
public static final int DIMEN_INDEX = 1;
public static final int DIMEN_COLOR = 4;
public static final int DIMEN_TEXTURE = 2;
int vaoID;
int vertexCount;
VBO vertexData;
VBO colorData;
VBO textureData;
IntVBO indexData;
boolean textured;
Texture texture;
public Model(float[] vertexData, float[] colorData, int[] indexData) {
this.vertexCount = vertexData.length;
this.vaoID = glGenVertexArrays();
this.textured = false;
bindVertexArray();
this.vertexData = new VBO(ATTRIB_VERTEX, vaoID, vertexData, DIMEN_VERTEX, true);
this.colorData = new VBO(ATTRIB_COLOR, vaoID, colorData, DIMEN_COLOR, true);
this.indexData = new IntVBO(ATTRIB_INDEX, vaoID, indexData, DIMEN_INDEX, true);
unbindVertexArray();
}
public boolean isTextured() {
return textured;
}
public void setTexture(Texture texture, float[] texCoords) {
this.textured = true;
this.textureData = new VBO(ATTRIB_TEXTURE, vaoID, texCoords, DIMEN_TEXTURE, true);
this.texture = texture;
}
public void unbindVertexArray() {
glBindVertexArray(0);
}
public void bindVertexArray() {
glBindVertexArray(vaoID);
}
public void dispose() {
vertexData.dispose();
colorData.dispose();
indexData.dispose();
glDeleteVertexArrays(vaoID);
}
public void render() {
bindVertexArray();
colorData.bind();
vertexData.bind();
if (textured) textureData.bind();
indexData.bind();
vertexData.enable();
if (textured) textureData.enable();
colorData.enable();
indexData.enable();
// Loading in the texture data
if (textured) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.getTextureID());
}
glDrawElements(GL_TRIANGLES, this.vertexCount, GL_UNSIGNED_INT, 0);
colorData.disable();
vertexData.disable();
indexData.disable();
if (textured) textureData.disable();
vertexData.unbind();
colorData.unbind();
indexData.unbind();
if (textured) textureData.disable();
unbindVertexArray();
}
}
VBO.java
package test.game.engine.rendersystem;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL11.*;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL15.*;
public class VBO {
public int vboID;
public int attributeNumber;
public int vaoID;
public int dataDimensions;
public float[] data;
public VBO(int attributeNumber, int vaoID, float[] data, int dimensions, boolean loadToVBO) {
this.attributeNumber = attributeNumber;
this.vaoID = vaoID;
this.data = data;
this.dataDimensions = dimensions;
if (loadToVBO) {
loadToVBO();
}
}
public void loadToVBO() {
this.vboID = glGenBuffers();
bind();
glBufferData(GL_ARRAY_BUFFER, storeDataInFloatBuffer(), GL_STATIC_DRAW);
glVertexAttribPointer(attributeNumber, dataDimensions, GL_FLOAT, false, 0, 0);
unbind();
}
public void bind() {
glBindBuffer(GL_ARRAY_BUFFER, vboID);
}
public void unbind() {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
public void enable() {
glEnableVertexAttribArray(attributeNumber);
}
public void disable() {
glDisableVertexAttribArray(attributeNumber);
}
public void dispose() {
glDeleteBuffers(vboID);
}
private FloatBuffer storeDataInFloatBuffer() {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
Here is the image I wanted to render (It is a test image) (It is in PNG)
A cow:
Here is the output I got. A cow on the quad:
P.S I am a new to OpenGL and low level graphics APIs.... So forgive me if I did any newb/noob mistakes.
I believe your problem lies here:
public void setTexture(Texture texture, float[] texCoords) {
this.textured = true;
this.textureData = new VBO(ATTRIB_TEXTURE, vaoID, texCoords, DIMEN_TEXTURE, true);
this.texture = texture;
}
When you created the initial vbos you bound the VAO then unbound it which allowed the drawing to take place, but when you add the texture coordinates no VAO is bound leading to your vbo being bound to nothing. When render is then called and the texture coordinates called upon nothing is found and so the default 0;0 coordinates, aka the single corner pixel, are used.
What I am trying to do is map a texture to an OpenGL model within LWJGL. I know that LWJGL 3 and slick-util sometimes work together and sometimes don't. In my case, it works a little and then tries to access a method in OpenGL that doesn't exist anymore for LWJGL 3. My posting this isn't necessarily trying to fix this error, but to find a way to circumvent it. I have tried downgrading to/running LWJGL 2 instead of/with LWJGL 3 and that went terribly, and I've also tried my hand at a couple of different PNG decoders to get what I want, but I can't figure them out. Also, I have went and gotten the "LWJGL 3 Compatible slick-util" but it doesn't have any classes/methods in it that I need. If anyone can fix my code for me or tell me how to fix it myself, that'd be lovely.
Here's the error:
Mon Feb 15 18:38:13 EST 2016 INFO:Use Java PNG Loader = true
Exception in thread "main" java.lang.NoSuchMethodError: org.lwjgl.opengl.GL11.glGetInteger(ILjava/nio/IntBuffer;)V
at org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer.glGetInteger(ImmediateModeOGLRenderer.java:194)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:317)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:254)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:200)
at org.newdawn.slick.opengl.TextureLoader.getTexture(TextureLoader.java:64)
at org.newdawn.slick.opengl.TextureLoader.getTexture(TextureLoader.java:24)
at Graphics.Loader.loadTexture(Loader.java:37)
at Graphics.LaunchWindow.loop(LaunchWindow.java:116)
at Graphics.LaunchWindow.run(LaunchWindow.java:43)
at Graphics.LaunchWindow.main(LaunchWindow.java:155)
Here's the LaunchWindow class:
package Graphics;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.util.Display;
import Controls.KeyParser;
import Controls.KeyboardInput;
import Controls.MouseInput;
import Controls.MouseParser;
import Graphics.Shaders.StaticShader;
import Controls.Cursor;
import Models.Model1;
import Models.RawModel;
import Models.TexturedModel;
import Textures.ModelTexture;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
import java.nio.ByteBuffer;
#SuppressWarnings("unused")
public class LaunchWindow {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private GLFWMouseButtonCallback mouseButtonCallback;
private GLFWCursorPosCallback cursorPosCallback;
public int width = 1024;
public int height = 600;
public String title = "Duplicity";
public long fullscreen = NULL;
public long window;
private Cursor cursor;
public void run() {
try {
init();
loop();
glfwDestroyWindow(window);
keyCallback.release();
} finally {
glfwTerminate();
errorCallback.release();
}
}
private void init() {
glfwSetErrorCallback(errorCallback = GLFWErrorCallback.createPrint(System.err));
KeyboardInput.initiate();
MouseInput.initiateMouse();
if ( glfwInit() != GLFW_TRUE )
throw new IllegalStateException("Unable to initialize GLFW");
if(fullscreen == NULL){
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
}
window = glfwCreateWindow(width, height, title, fullscreen, NULL);
if (window == NULL)
throw new RuntimeException("Failed to create the GLFW window");
glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
});
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
keyCallback = GLFWKeyCallback.create(KeyboardInput::glfw_key_callback);
keyCallback.set(window);
mouseButtonCallback = GLFWMouseButtonCallback.create(MouseInput::glfw_mouse_button_callback);
mouseButtonCallback.set(window);
cursorPosCallback = GLFWCursorPosCallback.create(MouseInput::glfw_cursor_pos_callback);
cursorPosCallback.set(window);
cursor = new Cursor(Cursor.Standard.ARROW);
glfwSetCursor(window, cursor.getCursor());
GL.createCapabilities();
}
public void updateInput() {
KeyboardInput.update();
MouseInput.update();
glfwPollEvents();
}
public void loop() {
Loader loader = new Loader();
Render render = new Render();
Model1 model1 = new Model1();
Display display = new Display();
StaticShader shader = new StaticShader();
RawModel model = loader.loadToVAO(model1.Model1Vertices(), model1.Model1Indices());
ModelTexture texture = new ModelTexture(loader.loadTexture("marble"));
TexturedModel texturedModel = new TexturedModel(model, texture);
GL.createCapabilities();
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
if(width != 1024 && height != 600){
System.out.println("resized");
}
while ( glfwWindowShouldClose(window) == GLFW_FALSE ) {
render.prepare();
shader.start();
render.render(texturedModel);
shader.stop();
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
try {
new KeyParser().checkKeyState();
new MouseParser().checkMouseState();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
shader.cleanUp();
loader.cleanUp();
}
public void setCursor(Cursor cursor) {
this.cursor = cursor;
glfwSetCursor(window, cursor.getCursor());
}
public Cursor getCursor() {
return cursor;
}
public static void main(String[] args) {
new LaunchWindow().run();
}
}
And here's Loader:
package Graphics;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import Models.RawModel;
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
private List<Integer> textures = new ArrayList<Integer>();
public RawModel loadToVAO(float[] positions, int[] indices){
int vaoID = createVAO();
bindIndicesBuffer(indices);
storeDataInAttributeList(0, positions);
unbindVAO();
return new RawModel(vaoID, indices.length);
}
public int loadTexture(String fileName){
Texture texture = null;
try {
texture = TextureLoader.getTexture("PNG", new FileInputStream("res/" + fileName + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
int textureID = texture.getTextureID();
textures.add(textureID);
return textureID;
}
public void cleanUp(){
for(int vao:vaos){
GL30.glDeleteVertexArrays(vao);
}
for(int vbo:vbos){
GL15.glDeleteBuffers(vbo);
}
for(int texture:textures){
GL11.glDeleteTextures(texture);
}
}
private int createVAO(){
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
private void storeDataInAttributeList(int attNumber, float[] data){
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_DYNAMIC_DRAW); //change to static if static model
GL20.glVertexAttribPointer(attNumber, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void unbindVAO(){
GL30.glBindVertexArray(0);
}
private void bindIndicesBuffer(int[] indices){
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = storeDataInIntBuffer(indices);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_DYNAMIC_DRAW); //change to static of static model
}
private IntBuffer storeDataInIntBuffer(int[] data){
IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
private FloatBuffer storeDataInFloatBuffer(float[] data){
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
You can download slick util compatible to lwjgl3 here: *click*
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?