The problem is that i am trying to create a 3D Cube via using the shaders, but the problem is that, it doesn't read the file correctly.
Here are the shaders that I have created, the problem is that it reads not correctly the sharders and give the error
I also get just a black screen as a result
My Shaders
Vertex shader
// vertex.glsl
#version 430
layout (location = 0) in vec3 position;
uniform mat4 proj_matrix;
uniform mat4 mv_matrix;
void main(void) {
gl_Position = proj_matrix * mv_matrix * vec4(position, 1.0);
}
Fragemtn shader
// fragment.glsl
#version 430
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
void main(void) {
color = vec4(1.0, 0.0, 0.0, 1.0);
}
main code
// my main code
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.Date;
import java.util.Random;
import java.util.Scanner;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.math.Matrix4;
import com.jogamp.opengl.math.Quaternion;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.*;
public class GOVNO extends JFrame implements GLEventListener {
private GLCanvas myCanvas;
private int rendering_program;
private int vbo[] = new int[2];
private int mTrans;
public GOVNO() {
setTitle("Chapter2 - program1");
setSize(600, 400);
setLocation(200, 200);
GLProfile profile = GLProfile.getDefault();
GLCapabilities capabilities = new GLCapabilities(profile);
myCanvas = new GLCanvas(capabilities);
myCanvas.addGLEventListener(this);
this.add(myCanvas);
setVisible(true);
}
public void display(GLAutoDrawable drawable) {
GL2 gl = (GL2) GLContext.getCurrentGL();
gl.glUseProgram(rendering_program);
float a = 0;
//Matrix4 mTransMatrix = new Matrix4();
float mTransMatrix[] = {
(float) Math.cos(a), (float) -Math.sin(a), 0, 0,
(float) Math.sin(a), (float) Math.cos(a), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
gl.glUniformMatrix4fv(mTrans, 1, false, mTransMatrix, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[0]);
gl.glVertexAttribPointer(0, 2, GL3.GL_FLOAT, false, 0, 0);
gl.glEnableVertexAttribArray(0);
gl.glDrawArrays(GL3.GL_TRIANGLES, 0, 6);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[1]);
gl.glVertexAttribPointer(0, 2, GL3.GL_FLOAT, false, 0, 0);
gl.glEnableVertexAttribArray(0);
gl.glDrawArrays(GL3.GL_QUADS, 0, 8);
}
public void init(GLAutoDrawable drawable) {
GL2 gl = (GL2) GLContext.getCurrentGL();
rendering_program = createShaderProgram();
// generating location for transformation matrix
mTrans = gl.glGetUniformLocation(rendering_program, "trans");
float[] vertex_positions = { -0.5f, -1.0f, 0.0f, -0.5f, 0.5f, -1.0f, };
gl.glGenBuffers(vbo.length, vbo, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[0]);
FloatBuffer vertBuf Buffers.newDirectFloatBuffer(vertex_positions);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertBuf.limit() * 4, vertBuf, GL3.GL_STATIC_DRAW);
float[] vertex_positions2 = { -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f };
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[1]);
FloatBuffer vertBuf2 = Buffers.newDirectFloatBuffer(vertex_positions2);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertBuf2.limit() * 4, vertBuf2, GL3.GL_STATIC_DRAW);
}
private int createShaderProgram() {
GL2 gl = (GL2) GLContext.getCurrentGL();
String vshaderSource[] = readShaderSource("src/vertex.glsl");
String fshaderSource[] = readShaderSource("src/fragment.glsl");
int vShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
gl.glShaderSource(vShader, vshaderSource.length, vshaderSource, null, 0);
gl.glCompileShader(vShader);
printShaderLog(vShader);
int fShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
gl.glShaderSource(fShader, fshaderSource.length, fshaderSource, null, 0);
gl.glCompileShader(fShader);
printShaderLog(fShader);
int vfprogram = gl.glCreateProgram();
gl.glAttachShader(vfprogram, vShader);
gl.glAttachShader(vfprogram, fShader);
gl.glLinkProgram(vfprogram);
gl.glDeleteShader(vShader);
gl.glDeleteShader(fShader);
printProgramLog(vfprogram);
return vfprogram;
}
private String[] readShaderSource(String filename) {
Vector<String> lines = new Vector<String>();
Scanner sc;
try {
sc = new Scanner(new File(filename));
} catch (IOException e) {
System.err.println("IOException reading file: " + e);
return null;
}
while (sc.hasNext()) {
lines.addElement(sc.nextLine());
}
String[] program = new String[lines.size()];
for (int i = 0; i < lines.size(); i++) {
program[i] = (String) lines.elementAt(i) + "\n";
System.out.print(program[i]);
}
return program;
}
private void printShaderLog(int shader) {
GL2 gl = (GL2) GLContext.getCurrentGL();
int[] len = new int[1];
int[] chWrittn = new int[1];
byte[] log = null;
// determine the length of the shader compilation log
gl.glGetShaderiv(shader, GL3.GL_INFO_LOG_LENGTH, len, 0);
if (len[0] > 0) {
log = new byte[len[0]];
gl.glGetShaderInfoLog(shader, len[0], chWrittn, 0, log, 0);
System.out.println("Shader Info Log: ");
for (int i = 0; i < log.length; i++) {
System.out.print((char) log[i]);
}
}
}
void printProgramLog(int prog) {
GL2 gl = (GL2) GLContext.getCurrentGL();
int[] len = new int[1];
int[] chWrittn = new int[1];
byte[] log = null;
// determine the length of the program linking log
gl.glGetProgramiv(prog, GL3.GL_INFO_LOG_LENGTH, len, 0);
if (len[0] > 0) {
log = new byte[len[0]];
gl.glGetProgramInfoLog(prog, len[0], chWrittn, 0, log, 0);
System.out.println("Program Info Log: ");
for (int i = 0; i < log.length; i++) {
System.out.print((char) log[i]);
}
}
}
public static void main(String[] args) {
System.out.println("Working Directory = " + System.getProperty("user.dir"));
new GOVNO();
}
}
Related
I'm learning LWJGL and OpenGL by following this tutorial i found, i tried my best to change the code to be compatible with the never versions and hadnt a problem with it so far. But now my Tilerenderer wont render more than one type of tile/one texture for the VBO's and i tried to fix it now since 3 days (in the beginning it didn't render anything at all) but couldn't find anything that fixes this problem.
I'm using Java 9.0.4 and LWJGL 3.2.1 build 12 with JOML 1.9.13, GLFW, OpenGL and stb.
So far i tried changing the entire code involved in this problem and changing different variables for shaders but nothing seemed to work so far.
Here are all classes i figured might have something to do with the problem.
The Main class
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL;
public class Main {
public static void main(String[] args) {
int speed = 5;
Window.setCallbacks();
if (!glfwInit()) {
throw new IllegalStateException("Failed to init GLFW");
}
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
Window window = new Window();
window.setSize(640, 480);
window.setFullscreen(false);
window.createWindow("GAME");
GL.createCapabilities();
Camera camera = new Camera(window.getWidth(), window.getHeight());
glEnable(GL_TEXTURE_2D);
TileRenderer tiles = new TileRenderer();
Shader shader = new Shader("shader");
World world = new World();
world.setTile(Tile.test_tile, 0, 0);
double frameCap = 1.0 / 60.0;
double frameTime = 0;
double time = Timer.getTime();
double unprocessed = 0;
int frames = 0;
while(!window.shouldClose()) {
boolean canRender = false;
double time2 = Timer.getTime();
double passed = time2 - time;
unprocessed+=passed;
frameTime += passed;
time = time2;
while (unprocessed >= frameCap) {
canRender = true;
unprocessed-=frameCap;
if(window.getInput().isMouseButtonDown(0)) {
glfwSetWindowShouldClose(window.getWindow(), true);
}
if (window.getInput().isKeyPressed(GLFW_KEY_ESCAPE)) {
glfwSetWindowShouldClose(window.getWindow(), true);
}
if(window.getInput().isKeyDown(GLFW_KEY_W)) {
camera.addPosition(new Vector3f(0, -speed, 0));
}
if(window.getInput().isKeyDown(GLFW_KEY_A)) {
camera.addPosition(new Vector3f(speed, 0, 0));
}
if(window.getInput().isKeyDown(GLFW_KEY_S)) {
camera.addPosition(new Vector3f(0, speed, 0));
}
if(window.getInput().isKeyDown(GLFW_KEY_D)) {
camera.addPosition(new Vector3f(-speed, 0, 0));
}
if(window.getInput().isKeyDown(GLFW_KEY_O)) {
speed = 5;
}
if(window.getInput().isKeyDown(GLFW_KEY_P)) {
speed = 25;
}
window.update();
if (frameTime >= 1.0) {
frameTime = 0;
System.out.println("FPS:" + frames);
frames = 0;
}
}
if (canRender) {
glClear(GL_COLOR_BUFFER_BIT);
world.render(tiles, shader, camera);
window.swapBuffers();
frames++;
}
}
glfwTerminate();
}
}
The World class
import org.joml.Matrix4f;
import org.joml.Vector3f;
public class World {
private byte[] tiles;
private int width;
private int height;
private Matrix4f world;
public World () {
width = 16;
height = 16;
tiles = new byte [width * height];
world = new Matrix4f().setTranslation(new Vector3f(0));
world.scale(32);
}
public void render(TileRenderer renderer, Shader shader, Camera camera) {
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
renderer.renderTile(tiles[x + y * width], y, -x, shader, world, camera);
}
}
}
public void setTile (Tile tile, int x, int y) {
System.err.println(tile.getId());
tiles[x + y * width] = tile.getId();
}
}
The Tilerenderer class
import java.util.HashMap;
import org.joml.Matrix4f;
import org.joml.Vector3f;
public class TileRenderer {
private HashMap<String, Texture> tileTextures;
private Model tileModel;
public TileRenderer() {
tileTextures = new HashMap<>();
float[] vertices = new float[]{
-1f, 1f, 0, // TOP LEFT 0
1f, 1f, 0, // TOP RIGHT 1
1f, -1f, 0, // BOTTOM RIGHT 2
-1f, -1f, 0,// BOTTOM LEFT 3
};
float[] texture = new float[]{0, 0, 1, 0, 1, 1, 0, 1,};
int[] indices = new int[]{0, 1, 2, 2, 3, 0};
tileModel = new Model(vertices, texture, indices);
for (int i = 0; i < Tile.tiles.length; i++) {
if (Tile.tiles[i] != null) {
if (!tileTextures.containsKey(Tile.tiles[i].getTexture())) {
String tex = Tile.tiles[i].getTexture();
tileTextures.put(tex, new Texture(tex + ".png"));
}
}
}
}
public void renderTile (byte id, int x, int y, Shader shader, Matrix4f world, Camera camera) {
shader.bind();
if (tileTextures.containsKey(Tile.tiles[id].getTexture())) {
tileTextures.get(Tile.tiles[id].getTexture()).bind(0);
}
Matrix4f tilePos = new Matrix4f().translate(new Vector3f(x*2, y*2, 0));
Matrix4f target = new Matrix4f();
camera.getProjection().mul(world, target);
target.mul(tilePos);
shader.setUniform("sampler", 0);
shader.setUniform("projection", target);
tileModel.render();
}
}
The Tile class
public class Tile {
public static Tile tiles[] = new Tile[16];
public static final Tile testTile = new Tile((byte)0, "Test");
public static final Tile testTile2 = new Tile((byte)1, "Test2");
private byte id;
private String texture;
public Tile(byte id, String texture) {
this.id = id;
this.texture = texture;
if (tiles[id] != null) {
throw new IllegalStateException("Tiles at: [" + id + "] is already being used!");
}
tiles[id] = this;
}
public byte getId () {return id;}
public String getTexture () {return texture;}
}
The Model class
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
public class Model {
private int draw_count;
private int v_id;
private int t_id;
private int i_id;
public Model (float[] vertices, float[] tex_coords, int[] indices) {
draw_count = indices.length;
IntBuffer buffer = BufferUtils.createIntBuffer(indices.length);
buffer.put(indices);
buffer.flip();
v_id = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, v_id);
glBufferData(GL_ARRAY_BUFFER, createBuffer(vertices), GL_STATIC_DRAW);
t_id = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, t_id);
glBufferData(GL_ARRAY_BUFFER, createBuffer(tex_coords), GL_STATIC_DRAW);
i_id = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void render() {
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, v_id);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, t_id);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);
glDrawElements(GL_TRIANGLES, draw_count, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
private FloatBuffer createBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
The Texture class
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.stb.STBImage.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import org.lwjgl.BufferUtils;
public class Texture {
private int id;
private int width;
private int heigth;
public Texture (String filename) {
IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer heigth = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
ByteBuffer data = stbi_load("./res/" + filename, width, heigth, comp, 4);
this.width = width.get();
this.heigth = heigth.get();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this.width, this.heigth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
public void bind (int sampler) {
if (sampler >= 0 && sampler <= 31) {
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(GL_TEXTURE_2D, sampler);
}
}
}
The Shader class
import static org.lwjgl.opengl.GL20.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.FloatBuffer;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
public class Shader {
private int program;
private int vs;
private int fs;
public Shader (String filename) {
program = glCreateProgram();
vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, readFile(filename + ".vs"));
glCompileShader(vs);
if (glGetShaderi(vs, GL_COMPILE_STATUS) != 1) {
System.err.println(glGetShaderInfoLog(vs));
System.exit(1);
}
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, readFile(filename + ".fs"));
glCompileShader(fs);
if (glGetShaderi(fs, GL_COMPILE_STATUS) != 1) {
System.err.println(glGetShaderInfoLog(fs));
System.exit(1);
}
glAttachShader(program, vs);
glAttachShader(program, fs);
glBindAttribLocation(program, 0, "vertices");
glBindAttribLocation(program, 1, "textures");
glLinkProgram(program);
if (glGetProgrami(program, GL_LINK_STATUS) != 1) {
System.err.println(glGetProgramInfoLog(program));
System.exit(1);
}
glValidateProgram(program);
if (glGetProgrami(program, GL_VALIDATE_STATUS) != 1) {
System.err.println(glGetProgramInfoLog(program));
System.exit(1);
}
}
public void bind () {
glUseProgram(program);
}
private String readFile (String filename) {
StringBuilder string = new StringBuilder();
BufferedReader br;
try {
br = new BufferedReader(new FileReader(new File("./shaders/" + filename)));
String line;
while((line = br.readLine()) != null) {
string.append(line);
string.append("\n");
}
} catch (IOException e ) {e.printStackTrace();}
return string.toString();
}
public void setUniform (String name, int value) {
int location = glGetUniformLocation(program, name);
if (location != -1) {
glUniform1i(location, value);
}
}
public void setUniform (String name, Matrix4f value) {
int location = glGetUniformLocation(program, name);
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
value.get(buffer);
if (location != -1) {
glUniformMatrix4fv(location, false, buffer);
}
}
}
The Fragment Shader
#version 120
uniform sampler2D sampler;
varying vec2 tex_coords;
void main () {
gl_FragColor = texture2D(sampler, tex_coords);
}
The Vertex Shader
#version 120
attribute vec3 vertices;
attribute vec2 textures;
varying vec2 tex_coords;
uniform mat4 projection;
void main() {
tex_coords = textures;
gl_Position = projection*vec4(vertices, 1);
}
So far I'm creating 16x16 tiles all with the same texture but it is supposed to change the tile at 0, 0 (top left corner) to have a different texture
There is a basic misunderstanding, about how texturing works in OpenGL.
You have to create a separate texture object for each texture by glGenTextures. (See also Java Code Examples for org.lwjgl.opengl.GL11.glTexImage2D()).
int textureObject = glGenTextures();
This texture object has to be bound before loading the texture and before rendering the mesh. The texture is bound to the active texture unit, which is set by glActiveTexture.
int textureUnitIndex = 0; // e.g
glActiveTexture(GL_TEXTURE0 + textureUnitIndex);
glBindTexture(GL_TEXTURE_2D, textureObject);
The texture unit is a binding point for the shader program. The texture sampler in the shader program has to be associated to the same binding point. This can be done by glUniform1i:
GLSL:
uniform sampler2D sampler;
Java:
int location = glGetUniformLocation(program, "sampler");
glUniform1i(location, textureUnitIndex);
Sidenote: since GLSL version 4.2 this can be done in the fragment shader by specifying binding points - See OpenGL Shading Language 4.20 Specification - 4.4.4 Opaque-Uniform Layout Qualifiers; page 60:
#version 420
layout (binding = 0) uniform sampler2D sampler;
In your code never a texture object is generated. So the default texture object 0 is used for all textures. This causes that you code doesn't work.
Change the class Texture, somehow as follows, to solve the issue:
public class Texture {
private int textureObject;
private int width;
private int heigth;
public Texture (String filename) {
IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer heigth = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
ByteBuffer data = stbi_load("./res/" + filename, width, heigth, comp, 4);
this.width = width.get();
this.heigth = heigth.get();
textureObject = glGenTextures(); // generate texture name
glBindTexture(GL_TEXTURE_2D, textureObject);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this.width, this.heigth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
public void bind (int sampler) {
if (sampler >= 0 && sampler <= 31) {
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(GL_TEXTURE_2D, textureObject); // bind texture object
}
}
}
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?
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.
I'm having an issue with lighting. I'm using GLSL to achieve this. All seems fine however I'm having an issue I believe its called "banding". Essentially it's giving a gradient like effect to my lights. Perhaps I'm doing something wrong, here is my code that I'm using a long with an image of the problem. I'm a beginner in GLSL and not sure if the code I have is the most efficient way.
Main Code
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.glUseProgram;
import java.util.ArrayList;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
public class Main {
public final int width = 1280;
public final int height = 720;
public ArrayList<Light> lights = new ArrayList<Light>();
private Shader shader;
private int bufferIndex;
private float[] vertices;
private Light lighter;
private Vector2f lightPos;
private boolean lockedIn = false;
private void render() {
glClear(GL_COLOR_BUFFER_BIT);
for (Light light : lights) {
shader.bind();
shader.setUniformf("lightLocation", light.getLocation().x,
light.getLocation().y);
shader.setUniform("lightColor", new Vector3f(light.getColors()));
shader.setUniform("ambientLight", new Vector3f(0.1f, 0.1f, 0.1f));
shader.setUniform("baseColor", new Vector3f(0.2f, 0.2f, 0.2f));
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
VertexBufferObject.GetInstance().render();
glDisable(GL_BLEND);
glUseProgram(0);
}
Display.update();
Display.sync(60);
}
private void input() {
if (Input.getMouse(0))
lockedIn = true;
else if (Input.getMouse(1))
lockedIn = false;
if (lockedIn) {
Mouse.setGrabbed(true);
lightPos.set(Input.getMousePosition().x, Input.getMousePosition().y);
if (Input.getKey(Input.KEY_UP)) {
lighter.setBlue((float) (lighter.getBlue() + 1));
lighter.setRed(lighter.getRed() + 1);
lighter.setGreen(lighter.getGreen() + 1);
}
if (Input.getKey(Input.KEY_DOWN)) {
lighter.setBlue((float) (lighter.getBlue() - 1));
lighter.setRed(lighter.getRed() - 1);
lighter.setGreen(lighter.getGreen() - 1);
}
if (Input.getKey(Input.KEY_L)) {
lights.add(new Light(new Vector2f(Input.getMousePosition().x,
Input.getMousePosition().y), lighter.getRed(), lighter
.getGreen(), lighter.getBlue()));
lighter.setBlue((float) Math.random() * 10);
lighter.setGreen((float) Math.random() * 10);
lighter.setRed((float) Math.random() * 10);
}
} else {
Mouse.setGrabbed(false);
}
}
private void setUpObjects() {
lightPos = new Vector2f(50, 50);
lighter = new Light(lightPos, 0, 5, 10);
lights.add(lighter);
lights.add(new Light(new Vector2f(60, 60), 120, 0, 120));
}
private void initialize() {
try {
Display.setDisplayMode(new DisplayMode(width, height));
Display.setTitle("2D Lighting");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
vertices = new float[] { 0, 0, 0, width, 0, 0, 0, height, 0, width,
height, 0, 0, height, 0, width, 0, 0 };
bufferIndex = glGenBuffers();
int b2 = glGenBuffers();
VertexBufferObject.GetInstance().addObject(bufferIndex, vertices);
VertexBufferObject.GetInstance().addObject(
b2, new float[] { 100, 100, 0, 200, 100, 0, 100, 200, 0, 200, 200,
0, 100, 200, 0, 200, 100, 0 });
VertexBufferObject.GetInstance().initObjects();
shader = new Shader();
shader.addFragmentShader(Shader.loadShader("shader.frag"));
shader.addVertexShader(Shader.loadShader("shader.vertex"));
shader.compileShader();
shader.addUniform("ambientLight");
shader.addUniform("baseColor");
shader.addUniform("lightLocation");
shader.addUniform("lightColor");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
}
private void cleanup() {
shader.unbind();
Display.destroy();
}
public static void main(String[] args) {
Main main = new Main();
main.setUpObjects();
main.initialize();
while (!Display.isCloseRequested()) {
if (Input.getKey(Input.KEY_ESCAPE))
System.exit(1);
main.input();
main.render();
}
main.cleanup();
}
}
GLSL Code
#verson 120
uniform vec2 lightLocation;
uniform vec3 lightColor;
uniform vec3 ambientLight;
uniform vec3 baseColor;
void main() {
vec4 light = vec4(ambientLight, 1);
vec4 color = vec4(baseColor,1);
float distance = length(lightLocation - gl_FragCoord.xy);
float attenuation = 1 / distance;
vec4 lColor = vec4(attenuation, attenuation, attenuation, pow(attenuation, 3)) * vec4(lightColor, 1);
color += lColor;
gl_FragColor = color * light;
}
Vertex Shader
#version 120
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
A result from the code:
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.