Hot questions for Using Lightweight Java Game Library in shader

Question:

Shaders compile status is always 0, including zero errors. If i purposefully break the shader it properly shows the errors and even fails to link, however when the shader (I believe) is a correct and working shader it's compile status is still zero, (GL_FALSE) but the program links correctly. when the failed to compile shader is used in a program nothing renders.

code used to check shaders:

private static void checkShader(int handle,String path) {
    int status = glGetProgrami(handle,GL_COMPILE_STATUS);
    boolean compiled = status==GL_TRUE;
    if (compiled) return; // Shader compiled and everything is fine~
    String error = glGetShaderInfoLog(handle);
    System.err.println("==== SHADER FAILED TO COMPILE ====");
    System.err.println(path);
    System.err.println(error);
    System.err.println("==== ======================== ====");
}

code used to read shaders:

private static String getShaderData(String path) throws IOException {
    InputStream inputStream = ShaderManager.class.getResourceAsStream(path);
    if (inputStream == null) throw new BadShaderException("Could not find shader: "+path);
    Scanner scanner = new Scanner(inputStream);
    StringBuilder builder = new StringBuilder();
    while (scanner.hasNextLine())
        builder.append(scanner.nextLine()).append('\n');
    scanner.close();
    return builder.toString();
}

loading vertex shaders (same for fragment and geometry shader, but container class changed)

public static VertexShader loadVertexShader(String path) {
    String source;
    try {
        source = getShaderData(path);
    } catch (Exception e) {
        throw new BadShaderException("Failed to load data for shader: "+path);
    }
    int handle = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(handle,source);
    glCompileShader(handle);
    checkShader(handle,path);
    return new VertexShader(handle,path);
}

shader I'm trying to use

#version 330 core
layout(location = 0) in vec3 vpm;
uniform mat4 depthMatrix;

void main(){
 gl_Position =  depthMatrix * vec4(vpm,1);
}

and a shader I've found while searching for a "passthrough" shader to test

#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

void main(){
    gl_Position =  vec4(vertexPosition_modelspace,1);
    UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0;
}

I'm using lwjgl 3.1.4,

OpenGL version is (4.6.0 NVIDIA 388.13)

OpenGL Vendor is (NVIDIA Corporation)

OpenGL Renderer is (GeForce GTX 1060 6GB/PCIe/SSE2)

EDIT: I was using glGetProgrami instead of glGetShaderi


Answer:

I was using glGetProgrami instead of glGetShaderi when checking whether my shaders compiled correctly. I was unaware of the latter method and thought the prior was used for both.

Question:

I'm using LWJGL to try to make a 3D game, but I've run into an error I can't resolve on my own. Whenever I run the program, I get the error:

java.lang.Exception: Error compiling shader code: 2

I set this error up myself to alert me if the shader failed to compile, which it seems to be doing every time, and I can't understand why.

public static String loadResource(String file) throws Exception{
    BufferedReader reader = new BufferedReader(new FileReader(new File(file)));
    String out = "";

    String s = reader.readLine();
    while (s != null){
        out += s + "\n";
        s = reader.readLine();
    }
    reader.close();
    return out;
}

That is the method I use to load the text of my shader code and place it into a string. I've asked it to print it out afterwards, and as far as i can tell there aren't any issues with it.

public void createVertexShader(String shaderCode) throws Exception{
    vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
}

public void createFragmentShader(String shaderCode) throws Exception {
    vertexShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
}

These two methods above use the following method to create the vertex and fragment shaders:

public int createShader(String shaderCode, int shaderType) throws Exception {
    int shaderId = glCreateShader(shaderType);
    if(shaderId == 0){
        throw new Exception("Error creating shader code: " + shaderId);
    }

    glShaderSource(shaderId, shaderCode);
    glCompileShader(shaderId);

    if(glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0){
        throw new Exception("Error compiling shader code: " + shaderId);
    }

    glAttachShader(programId, shaderId);

    return shaderId;
}

The shader gets created with no errors, but when I check to see if it's been compiled properly, it throws the exception and stops my program. Here are my vertex and fragment shaders:

vertex.vs

#version 150

layout (location=0) in vec3 pos;

void main()
{
    gl_Position = vec4(position, 1.0);  
}

fragment.fs

#version 150

out vec4 fragColor;

void main()
{
    fragColor = vec4(0.0, 0.5, 0.5, 1.0);
}

I have verified that I am using the correct GLSL version in my shaders, but I got the actual shader code from a tutorial, so I don't know if the syntax is strictly correct or not.


Answer:

layout (location=0) in vec3 pos; this line will give you syntax error with #version 150 or below. Try #version 330 or higher in your vertex shader.

Also, in the vertex shader pos and position are different symbols and you've failed to provide a definition for position.

Question:

I have been writing a point light shader for my LWJGL + Java application. I am writing it based off of this tutorial. My problem is when I "walk around" with the camera, the light moves as well. Also, when I rotate the sphere, the light rotates with it. I believe that the problem is in the Vertex Shader, but I put the fragment shader in also just in case. Example 1 (No movement) Example 2 (Moved Left and rotated the camera)

Vertex Shader

#version 330

in vec4 in_Position;
in vec3 in_Normal;
in vec2 in_TextureCoord;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat3 normal;

uniform vec4 light_Pos; //Set to 0, 3, 0, 1

out Data {
    vec3 normal;
    vec3 eye;
    vec3 lDir;
    vec2 st;
} Out;

void main(void) {
    vec4 vert = view * model * light_Pos;
    vec4 pos = model * view * in_Position;
    Out.normal = normalize(in_Normal);
    Out.lDir = vec3(vert - pos);
    Out.eye = vec3(-pos);
    Out.st = in_TextureCoord;
    gl_Position = projection * view * model * in_Position;
}

Fragment Shader

#version 330

uniform sampler2D texture_diffuse;

in Data {
    vec3 normal;
    vec3 eye;
    vec3 lDir;
    vec2 st;
} In;

out vec4 color;

void main(void) {
    vec4 diffuse = texture(texture_diffuse, In.st);
    vec4 spec = vec4(0.0);

    vec3 n = normalize(In.normal);
    vec3 l = normalize(In.lDir);
    vec3 e = normalize(In.eye);

    float i = max(dot(n,l), 0.0);
    if (i > 0.0) {
        vec3 h = normalize(l+e);
        float intSpec = max(dot(h,n), 0.0);
        spec = vec4(1) * pow(intSpec, 50);  //50 is the shininess
    }
    color = max(i * diffuse + spec, vec4(0.2));
}

I already tried the solution presented in this question, it did not solve my problem.


Answer:

Just from a quick glance, looks like you're multiplying the light's position by the view and model matrix:

vec4 vert = view * model * light_Pos;

This means that whenever you walk around/move the camera you're changing the view matrix which affects the light's position, and likewise your when you move the sphere you're changing the model matrix which is also affects the light's position.

In other words if you want the light to be stationary in relation to the world then don't transform it by any matrices.

Question:

I want add an array of integers to my vertex array object, to define, which image should be used for that specific vertex, but somehow, the data is getting corrupted on the way or isn't loaded correctly.

I've already tried loading a preset array and just selecting the correct index using the gl_VertexID, which worked, but I would prefer having all the data in the vertex array and not having to load a uniform integer array each frame.

The vertex shader

#version 330 core

layout (location = 0) in vec4 position;
layout (location = 1) in vec2 textureCoordinate;
//layout (location = 2) in vec3 normals;
layout (location = 3) in int textureIndex;
//layout (location = 4) in mat4 modelMatrix;

// ---------------Temporary--------------
uniform mat4 view;
uniform mat4 model;
// ---------------Temporary end----------

flat out int textureIndexOut;

out DATA {
    vec2 tc;
} vs_out;

void main() {
    mat4 mvp = view * model; 
    gl_Position = mvp * position;
    vs_out.tc = textureCoordinate;
    textureIndexOut = textureIndex;
}

The fragment shader

#version 330 core

layout (location = 0) out vec4 color;

flat in int textureIndexOut;

in DATA {
    vec2 tc;
} fs_in;

uniform sampler2D textureSamplers[32];

void main() {
    color = texture(textureSamplers[1], fs_in.tc);
}

Creating a vertex array`

public static VertexArray createVAO(float[] vertices, int[] indices, float[] textureCoordinates, 
            float[] normals, int[]textureIndices) {
        int count = indices.length;
        int indexBufferObject = createIndexBuffer(indices);
        int vertexArrayObject = laodVertexArrayObject();
        storeDataInAttributeList(ShaderProgram.VERTEX_ATTRIB, vertices, 3);
        storeDataInAttributeList(ShaderProgram.TEXTURECOORDINATE_ATTRIB, textureCoordinates, 2);
        storeDataInAttributeList(ShaderProgram.TEXTURE_INDEX_ATTRIB, textureIndices, 1);
        return new VertexArray(count, vertexArrayObject, indexBufferObject, indices, vertices, normals, textureCoordinates);
    }

Creating a VAO

private static int laodVertexArrayObject() {
        int vertexArrayObjectID = glGenVertexArrays();
        vaos.add(vertexArrayObjectID);                                                          //Adding the VAO to the list of all VAOs
        glBindVertexArray(vertexArrayObjectID);
        return vertexArrayObjectID;
    }

Creating a VBO

private static int createIndexBuffer(int[] indices) {
        int indexBufferObjectID = glGenBuffers();
        ibos.add(indexBufferObjectID);                                                          //Adding the IBO to the list of all IBOs
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObjectID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createIntBuffer(indices), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        return indexBufferObjectID;
    }

The storeDataInAttributeList function

private static void storeDataInAttributeList(int attributeNumber, float[] data, int coordinateSize) {
        int vertexBufferObjectID = glGenBuffers();
        vbos.add(vertexBufferObjectID);                                                         //Adding the VBO to the list of all VBOs
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectID);
        glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(data), GL_STATIC_DRAW);
        glVertexAttribPointer(attributeNumber, coordinateSize, GL_FLOAT, false, 0, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

private static void storeDataInAttributeList(int attributeNumber, int[] data, int coordinateSize) {
        int vertexBufferObjectID = glGenBuffers();
        vbos.add(vertexBufferObjectID);                                                         //Adding the VBO to the list of all VBOs
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectID);
        glBufferData(GL_ARRAY_BUFFER, BufferUtils.createIntBuffer(data), GL_STATIC_DRAW);
        glVertexAttribPointer(attributeNumber, coordinateSize, GL_INT, false, 0, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

Rendering a batch

public void render() {
        // Final arrays
        float[] vertices = null;
        float[] textureCoordinates = null;
        float[] normals = null;
        int[] indices = null;
        int[] textureIndices = null;
        // The temporary array list of data
        ArrayList<Float> rawVertices = new ArrayList<Float>();
        ArrayList<Float> rawTextureCoordinates = new ArrayList<Float>();
        ArrayList<Float> rawNormals = new ArrayList<Float>();
        ArrayList<Integer> rawIndices = new ArrayList<Integer>();
        ArrayList<Integer> rawTextureIndices = new ArrayList<Integer>();
        // Adding all the data of all the vaos into the temporary array lists
        for(int j = 0; j < rawVAOs.size(); j++) {
            for(int i = 0; i < rawVAOs.get(j).getVertices().length; i++) {
                rawVertices.add(rawVAOs.get(j).getVertices()[i]);
            }
            for(int i = 0; i < rawVAOs.get(j).getIndices().length; i++) {
                if(j == 0) {
                    rawIndices.add(rawVAOs.get(j).getIndices()[i]);
                } else {
                    rawIndices.add(j*rawVAOs.get(j-1).getIndices().length + rawVAOs.get(j).getIndices()[i]);
                }
            }
            for(int i = 0; i < rawVAOs.get(j).getNormals().length; i++) {
                rawNormals.add(rawVAOs.get(j).getNormals()[i]);
            }
            for(int i = 0; i < rawVAOs.get(j).getTextureCoordinates().length; i++) {
                rawTextureCoordinates.add(rawVAOs.get(j).getTextureCoordinates()[i]);
            }
            for(int i = 0; i < rawVAOs.get(j).getTextureIndices().length; i++) {
                rawTextureIndices.add(rawVAOs.get(j).getTextureIndices()[i]);
            }
        }
        // Adding all the data from the temporaray array lists into the final arrays
        vertices = new float[rawVertices.size()];
        for(int i = 0; i < rawVertices.size(); i++) {
            vertices[i] = rawVertices.get(i);
        }
        indices = new int[rawIndices.size()];
        for(int i = 0; i < rawIndices.size(); i++) {
            indices[i] = rawIndices.get(i);
        }
        normals = new float[rawNormals.size()];
        for(int i = 0; i < rawNormals.size(); i++) {
            normals[i] = rawNormals.get(i);
        }
        textureCoordinates = new float[rawTextureCoordinates.size()];
        for(int i = 0; i < rawTextureCoordinates.size(); i++) {
            textureCoordinates[i] = rawTextureCoordinates.get(i);
        }
        textureIndices = new int[rawTextureIndices.size()];
        for(int i = 0; i < rawTextureIndices.size(); i++) {
            textureIndices[i] = rawTextureIndices.get(i);
        }
        // Creating the final vao and rendering it
        this.finalVAO = Loader.createVAO(vertices, indices, textureCoordinates, normals, textureIndices);
        Main.ShaderList.get(shaderIndex).prepare();
        //load transformation matrices
        for(int i = 0; i < texturePointers.size(); i++) {
            glActiveTexture(GL_TEXTURE0+i);
            Main.TextureBufferPointerList.get(texturePointers.get(i)).bind();
        }
        this.finalVAO.render();
        Main.ShaderList.get(shaderIndex).finish();
    }

If I load up an integer array consisting of 0 for all the vertices of the first object and 1 for the all the vertices of the second object, i would expect the first object to be shaded in with the first texture and the second object to be shaded in with the second texture. It works if I add 0 for both objects, but once I add 1 for the any object, I get this giant error message:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffee7914d6e, pid=5992, tid=0x00000000000006bc
#
# JRE version: Java(TM) SE Runtime Environment (8.0_211-b12) (build 1.8.0_211-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [ig9icd64.dll+0x24d6e]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  T H R E A D  ---------------

Current thread (0x000000001f03c800):  JavaThread "renderer" [_thread_in_native, id=1724, stack(0x0000000020990000,0x0000000020a90000)]

siginfo: ExceptionCode=0xc0000005, reading address 0x0000000000000220

Registers:
RAX=0x0000000024f20080, RBX=0x00000000013ae000, RCX=0x00000000013ae000, RDX=0x000000002d611b10
RSP=0x0000000020a8ebb0, RBP=0x000000002d611a50, RSI=0x0000000000000000, RDI=0x0000000024f20080
R8 =0x0000000001221bc0, R9 =0x0000000000008000, R10=0x00000000ffffffff, R11=0x0000000000000000
R12=0x0000000000000000, R13=0x000000001ca43bd0, R14=0x0000000025042310, R15=0x0000000000000000
RIP=0x00007ffee7914d6e, EFLAGS=0x0000000000010246

Top of Stack: (sp=0x0000000020a8ebb0)
0x0000000020a8ebb0:   0000000000000001 0000000001387e50
0x0000000020a8ebc0:   00000000228e5360 00007ffee7a6171f
0x0000000020a8ebd0:   fffffffffffffffe 000000001ca43bd0
0x0000000020a8ebe0:   000000000137ff20 00007ffee79145cf
0x0000000020a8ebf0:   0000000001394720 0000000000000000
0x0000000020a8ec00:   00000000013ae000 000000002d611a50
0x0000000020a8ec10:   000000000000000e 00007ffee7e35300
0x0000000020a8ec20:   0000000000000000 0000000025042310
0x0000000020a8ec30:   0000000024f20080 00007ffee790b731
0x0000000020a8ec40:   0000000001394720 00000000ffffffff
0x0000000020a8ec50:   0000000000000000 00000000ffffffff
0x0000000020a8ec60:   000000000137ff20 00007ffee7b0f4e2
0x0000000020a8ec70:   0000000000000000 00000000ffffffff
0x0000000020a8ec80:   0000000024f20080 000000000137ff20
0x0000000020a8ec90:   fffffffffffffffe 0000000025042310
0x0000000020a8eca0:   0000000000000000 0000000025042310 

Instructions: (pc=0x00007ffee7914d6e)
0x00007ffee7914d4e:   02 00 00 83 e6 01 0f 1f 40 00 0f 1f 84 00 00 00
0x00007ffee7914d5e:   00 00 4c 8b 9f 70 42 03 00 48 8d 95 c0 00 00 00
0x00007ffee7914d6e:   41 8b 8b 20 02 00 00 85 f6 0f 84 81 00 00 00 83
0x00007ffee7914d7e:   f9 10 73 06 48 6b c1 38 eb 5b 44 8d 41 f0 41 8b 


Register to memory mapping:

RAX=0x0000000024f20080 is an unknown value
RBX=0x00000000013ae000 is an unknown value
RCX=0x00000000013ae000 is an unknown value
RDX=0x000000002d611b10 is an unknown value
RSP=0x0000000020a8ebb0 is pointing into the stack for thread: 0x000000001f03c800
RBP=0x000000002d611a50 is an unknown value
RSI=0x0000000000000000 is an unknown value
RDI=0x0000000024f20080 is an unknown value
R8 =0x0000000001221bc0 is an unknown value
R9 =0x0000000000008000 is an unknown value
R10=0x00000000ffffffff is an unknown value
R11=0x0000000000000000 is an unknown value
R12=0x0000000000000000 is an unknown value
R13={method} {0x000000001ca43bd8} 'invokeV' '(J)V' in 'org/lwjgl/system/JNI'
R14=0x0000000025042310 is an unknown value
R15=0x0000000000000000 is an unknown value


Stack: [0x0000000020990000,0x0000000020a90000],  sp=0x0000000020a8ebb0,  free space=1018k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [ig9icd64.dll+0x24d6e]
C  [ig9icd64.dll+0x245cf]
C

Answer:

Integral attributes have to be specified by glVertexAttribIPointer - focus on I:

glVertexAttribIPointer(attributeNumber, coordinateSize, GL_INT, 0, 0);

See OpenGL 4.6 API Core Profile Specification; 10.2.1 Current Generic Attributes , page 349:

When values for a vertex shader attribute variable are sourced from an enabled generic vertex attribute array, the array must be specified by a command compatible with the data type of the variable. The values loaded into a shader attribute variable bound to generic attribute index are undefined if the array for index was not specified by:

  • VertexAttribFormat, for floating-point base type attributes;
  • VertexAttribIFormat with type BYTE, SHORT, or INT for signed integer base type attributes; or
  • VertexAttribIFormat with type UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT for unsigned integer base type attributes.

Further note that the Index buffer is stated in the Vertex Array Object. If no Vertex Array Object is bound, then no index buffer can be bound. (In a compatibility profile context there is the default vertex array object 0).

So the vertex array object has to be created and bound before the index buffer.

int vertexArrayObject = laodVertexArrayObject();
int count = indices.length;
int indexBufferObject = createIndexBuffer(indices);

Of course the association to the VAO must not be broken by glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);:

private static int createIndexBuffer(int[] indices) {
    int indexBufferObjectID = glGenBuffers();
    ibos.add(indexBufferObjectID);                                                          
    //Adding the IBO to the list of all IBOs
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObjectID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createIntBuffer(indices), GL_STATIC_DRAW);

    // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); <----- delete

    return indexBufferObjectID;
}

Question:

I'm trying to make a Mandelbrot set explorer, which will shade the pixels on the screen based on its coordinate in the window. I've done this before without using shaders but its extremely slow. I can't figure out how to get the position of the fragment so that I can use the algorithm I've already developed to render the Mandelbrot set.

I'm using ljgwl 3. I've been researching all day on how to do this, and I can't find any comprehensive findings on how to get the coordinates. It seems like gl_FragCoord should work and then I could use gl_FragCoord.x and gl_FragCoord.y to get the x and y values, which is all I need for the algorithm, but my screen always ends up being all red. I'm not passing any info from the vertex shader into my fragment shader because I need to render the color of each coordinate in the Mandelbrot based on its x and y values, so the vertex positions aren't helpful (I also don't understand how to get those).

Here is my fragment shader:

    in vec4 gl_FragCoord;
    uniform vec2 viewportDimensions;
    uniform float minX;
    uniform float maxX;
    uniform float minY;
    uniform float maxY;

    vec3 hsv2rgb(vec3 c){
        vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
        vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
        return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
    }

    void main(){
        float x = gl_FragCoord.x;
        float y = gl_FragCoord.y;

        vec2 c = vec2((x* (maxX-minX) / viewportDimensions.x + minX), (y*(maxY-minY)/ viewportDimensions.y + minY));
        vec2 z = c;

        float limit = 1000;
        float iterations = 0;
        for(int i = 0; i < int(limit); i++){
            float t = 2.0 * z.x * z.y + c.y;
            z.x = z.x * z.x - z.y * z.y + c.x;
            z.y = t;

            if(z.x * z.x + z.y *z.y > 4){
                break;
            }

            iterations += 1.0;
        }
        float itRGB = iterations/limit;
        vec3 hsv = vec3(itRGB, 1.0, 1.0);
        vec3 rgb = hsv2rgb(hsv);
        gl_FragColor = vec4(rgb, 1);
    }

I thought that I could use gl_FragCoord without declaring it as in first but it doesn't work either way. vec2 c is attempting to map the current coordinate to a coordinate in the complex number grid based on current resolution of the window.

This is all that's in my vertex shader:

    void main(){
        gl_Position = ftransform();
    }

And the relevant bit of my client code:

    glBegin(GL_POLYGON);
                glVertex2f(-1f, -1f);
                glVertex2f(1f, -1f);
                glVertex2f(1f, 1f);
                glVertex2f(-1f, 1f);
    glEnd();

This is running in my window loop, and just creates the square where the mandelbrot is supposed to render.

This is the output of my working java Mandelbrot program which doesn't use shaders:

This is the output of my shader program:

Fullscreen:

I also have no clue as to how to be able to resize the window properly without the black bars. I am attempting to do this with vec2 c in my code above as I have set the uniforms to be the windows height and width and am using that when mapping the coordinate to the complex number plane, but as gl_FragCoord doesn't seem to work then neither should this. A link to a current guide on lgjwl screen resizing based on glfwCreateWindow would be vastly appreciated.


Answer:

gl_FragCoord is a built-in input variables, it isn't necessary to declared the input variable gl_FragCoord. The x and y coordinate are window (pixel) coordinate. The lower left of gl_FragCoord is (0.5, 0.5) and the upper right is (W-0.5, H-0.5), where W and H are the width and the height of the viewport.

You've to map gl_FragCoord.x to the range [minX, maxX] and gl_FragCoord.y to the range [minY, maxy]. I recommend to us the GLSL function mix for this. viewportDimensions is assumed to contain the with and the height of the viewport rectangle in window (pixel) coordinates.

vec2 c = mix(vec2(minX, minY), vec2(maxX, maxY), gl_FragCoord.xy / viewportDimensions.xy);

See the (WebGL) example, where I applied the suggestions to the the fragment shader of the question. The bounds are initialized as follows

minX = -2.5
minY = -2.0
maxX =  1.5
maxY =  2.0 

(function loadscene() {    

var canvas, gl, vp_size, prog, bufObj = {};

function initScene() {

    canvas = document.getElementById( "ogl-canvas");
    gl = canvas.getContext( "experimental-webgl" );
    if ( !gl )
      return;

    progDraw = gl.createProgram();
    for (let i = 0; i < 2; ++i) {
        let source = document.getElementById(i==0 ? "draw-shader-vs" : "draw-shader-fs").text;
        let shaderObj = gl.createShader(i==0 ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
        gl.shaderSource(shaderObj, source);
        gl.compileShader(shaderObj);
        let status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
        if (!status) alert(gl.getShaderInfoLog(shaderObj));
        gl.attachShader(progDraw, shaderObj);
        gl.linkProgram(progDraw);
    }
    status = gl.getProgramParameter(progDraw, gl.LINK_STATUS);
    if ( !status ) alert(gl.getProgramInfoLog(progDraw));
    progDraw.inPos = gl.getAttribLocation(progDraw, "inPos");
    progDraw.minX = gl.getUniformLocation(progDraw, "minX");
    progDraw.maxX = gl.getUniformLocation(progDraw, "maxX");
    progDraw.minY = gl.getUniformLocation(progDraw, "minY");
    progDraw.maxY = gl.getUniformLocation(progDraw, "maxY");
    progDraw.viewportDimensions = gl.getUniformLocation(progDraw, "viewportDimensions");
    gl.useProgram(progDraw);

    var pos = [ -1, -1, 1, -1, 1, 1, -1, 1 ];
    var inx = [ 0, 1, 2, 0, 2, 3 ];
    bufObj.pos = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.pos );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( pos ), gl.STATIC_DRAW );
    bufObj.inx = gl.createBuffer();
    bufObj.inx.len = inx.length;
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
    gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( inx ), gl.STATIC_DRAW );
    gl.enableVertexAttribArray( progDraw.inPos );
    gl.vertexAttribPointer( progDraw.inPos, 2, gl.FLOAT, false, 0, 0 ); 
    
    gl.enable( gl.DEPTH_TEST );
    gl.clearColor( 0.0, 0.0, 0.0, 1.0 );

    window.onresize = resize;
    resize();
    requestAnimationFrame(render);
}

function resize() {
    //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
    vp_size = [window.innerWidth, window.innerHeight];
    //vp_size = [256, 256]
    canvas.width = vp_size[0];
    canvas.height = vp_size[1];
}

function render(deltaMS) {

    gl.viewport( 0, 0, canvas.width, canvas.height );
    gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
   
    gl.uniform1f(progDraw.minX, -2.5);
    gl.uniform1f(progDraw.minY, -2.0);
    gl.uniform1f(progDraw.maxX, 1.5);
    gl.uniform1f(progDraw.maxY, 2.0);
    gl.uniform2f(progDraw.viewportDimensions, canvas.width, canvas.height);
    gl.drawElements( gl.TRIANGLES, bufObj.inx.len, gl.UNSIGNED_SHORT, 0 );
    
    requestAnimationFrame(render);
}  

initScene();

})();
html,body { margin: 0; overflow: hidden; }
<script id="draw-shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec2 inPos;

void main()
{
    gl_Position = vec4( inPos.xy, 0.0, 1.0 );
}
</script>

<script id="draw-shader-fs" type="x-shader/x-fragment">
precision mediump float;

uniform vec2 viewportDimensions;
uniform float minX;
uniform float maxX;
uniform float minY;
uniform float maxY;

vec3 hsv2rgb(vec3 c){
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main()
{
  float x = gl_FragCoord.x;
  float y = gl_FragCoord.y;

  vec2 c = mix(vec2(minX, minY), vec2(maxX, maxY), gl_FragCoord.xy / viewportDimensions.xy);
  vec2 z = c;

  float limit = 64.0;
  float iterations = 0.0;
  for(int i = 0; i < 64; i++){
      float t = 2.0 * z.x * z.y + c.y;
      z.x = z.x * z.x - z.y * z.y + c.x;
      z.y = t;

      if(z.x * z.x + z.y *z.y > 4.0){
          break;
      }

      iterations += 1.0;
  }
  float itRGB = iterations/limit;
  vec3 hsv = vec3(itRGB, 1.0, 1.0);
  vec3 rgb = hsv2rgb(hsv);
  gl_FragColor = vec4(rgb, 1);
}
</script>

<canvas id="ogl-canvas" style="border: none"></canvas>

Question:

I am trying to load a VBO with projection by following the "The Quad with Projection" tutorial on the LWJGL website.

Here is my function for loading the shaders.

private int loadShader(String filename, int type) {
    StringBuilder shaderSource = new StringBuilder();
    int shaderID = 0;

    try {
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                shaderSource.append(line).append("\n");
            }
        }
    } catch (IOException e) {
        System.err.println("Could not read file.");
        e.printStackTrace();
        System.exit(-1);
    }

    shaderID = GL20.glCreateShader(type);
    GL20.glShaderSource(shaderID, shaderSource);
    GL20.glCompileShader(shaderID);

    if (GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
        System.err.println("Could not compile shader.");
        System.exit(-1);
    }

    this.exitOnGLError("loadShader");

    return shaderID;
}

When I run the program, this error occurs.

if (GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
    System.err.println("Could not compile shader.");
    System.exit(-1);
}

Here is my shader code:

Vertex:

#version 150 core

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

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;
    // Override gl_Position with our new calculated position
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * in_Position;

    pass_Color = in_Color;
    pass_TextureCoord = in_TextureCoord;
}

Fragment:

#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 = texture2D(texture_diffuse, pass_TextureCoord);
}

Thanks for your help.


Answer:

Your fragment shader is not valid, the function texture2D is not available in GLSL 1.50 core. Just use the function texture(). The compiler derives the type of the texture to sample from the type of sampler uniform it is called with.

Question:

When I attempt to implement transparency for my textures in LWJGL 3, the models seem to render with full transparency, and thus are not visible at all. When I remove the check, it works fine. Any clue's as to why?

Here is the shader code where the alpha component is checked:

#version 430

in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector[5];
in vec3 toCameraVector;
in float visibility;

out vec4 out_Color;

uniform sampler2D textureSampler;
uniform vec3 lightColour[5];
uniform vec3 attenuation[5];
uniform float shineDamper;
uniform float reflectivity;
uniform vec3 skyColour;

void main(void) {

    vec3 unitNormal = normalize(surfaceNormal);
    vec3 unitVectorToCamera = normalize(toCameraVector);

    vec3 totalDiffuse = vec3(0.0);
    vec3 totalSpecular = vec3(0.0);

    for (int i = 0; i < 5; i++) {
        float distance = length(toLightVector[i]);
        float attFactor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance);
        vec3 unitLightVector = normalize(toLightVector[i]);
        float nDot1 = dot(unitNormal, unitLightVector);
        float brightness = max(nDot1, 0.0);
        vec3 lightDirection = -unitLightVector;
        vec3 reflectedLightDirection = reflect(lightDirection, unitNormal);
        float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
        specularFactor = max(specularFactor, 0.0);
        float dampedFactor = pow(specularFactor, shineDamper);
        totalDiffuse = totalDiffuse + (brightness * lightColour[i])/attFactor;
        totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColour[i])/attFactor;
    }
    totalDiffuse = max(totalDiffuse, 0.2);


////////////////////////////////////////////////////////////////////////////
    vec4 textureColour = texture(textureSampler, pass_textureCoords);
    if (textureColour.a < 0.5) {
        discard;
    }
////////////////////////////////////////////////////////////////////////////

    out_Color = vec4(totalDiffuse, 1.0) * textureColour + vec4(totalSpecular, 1.0);
    out_Color = mix(vec4(skyColour,1.0),out_Color, visibility);

}

I've triple checked everything is loaded up to the shader in the correct order ect. but the only way to make the textures appear is to remove this check.

Anything else of use, please ask. Thanks!

EDIT 1:

Loading the texture from an image:

protected Texture loadTexture(BufferedImage image, String info) {
    Texture texture;

    int width = image.getWidth();
    int height = image.getHeight();
    int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);

    ByteBuffer buffer = BufferUtils.createByteBuffer((width * height) * 4);
    int id = glGenTextures();

    for (int i = 0; i < pixels.length; i++) {
        byte r = (byte)((pixels[i] >> 16) & 0xFF);
        byte g = (byte)((pixels[i] >> 8) & 0xFF);
        byte b = (byte)(pixels[i] & 0xFF);
        byte a = (byte)((pixels[i] >> 24) * 0xFF);
        buffer.put(r);
        buffer.put(g);
        buffer.put(b);
        buffer.put(a);
    }
    buffer.flip();
    glBindTexture(GL_TEXTURE_2D, id);
    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, buffer);
    glBindTexture(GL_TEXTURE_2D, 0);

    texture = new Texture(id, buffer, width, height);
    if (info != "") processData(info, texture);
    return texture;
}

EDIT 2:

After trying Out_Color = vec4(textureColour.aaa, 1.0);


Answer:

It was a simple fix as suggested by Rabbid76 that the alpha channel was getting lost when reading the image to a pixels array. Instead, i now use:

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int pixel = image.getRGB(x, y);
            byte alpha = (byte)((pixel >> 24) & 0xff);
            byte red = (byte)((pixel >> 16) & 0xff);
            byte green = (byte)((pixel >> 8) & 0xff);
            byte blue = (byte)((pixel >> 0) & 0xff);
            buffer.put(red);
            buffer.put(green);
            buffer.put(blue);
            buffer.put(alpha);
        }
    }

which works perfectly!

Question:

I am trying to use a GLSL shader I wrote from LWJGL. It is just a simple fragment-based phong shader. The shader has worked fine in the past, even on this computer. The other day, all of a sudden, it simply stopped compiling for no apparent reason. When I try to compile it and check the info log, I get this message:

Exception in thread "Thread-1" org.lwjgl.opengl.OpenGLException: Invalid value (1281)
    at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
    at org.lwjgl.opengl.GL20.glGetShaderi(GL20.java:542)
    at aspect.render.shader.ShaderProgram.getLogInfo(ShaderProgram.java:161)
    at aspect.render.shader.ShaderProgram.<init>(ShaderProgram.java:69)
    at aspect.render.shader.ShaderProgram.loadPrebuilt(ShaderProgram.java:168)
    at aspect.core.AspectLauncher$1.run(AspectLauncher.java:143)

My OpenGL info:

GL VENDOR: Intel
GL RENDERER: Intel(R) HD Graphics 3000
GL VERSION: 3.1.0 - Build 9.17.10.3347
GLSL VERSION: 1.40 - Intel Build 9.17.10.3347

Here is the shader itself:

Vertex:

#version 140

uniform int numLights;
uniform bool useLighting;

varying vec3 normal;
varying vec3 ambient;
varying vec3 color;

varying vec3 diffuse[8];
varying vec3 lightDir[8];
varying vec3 dist[8];

varying vec2 texCoord;

void main() { 
    vec4 position = gl_ModelViewMatrix * gl_Vertex;
    gl_Position = gl_ProjectionMatrix * position;
    normal = normalize(gl_NormalMatrix * gl_Normal);
    texCoord = gl_MultiTexCoord0.st;
    color = gl_Color.rgb;

    ambient = gl_FrontMaterial.emission.rgb + gl_LightModel.ambient.rgb * gl_FrontMaterial.ambient.rgb;

    if (useLighting) {
        for (int i = 0; i < numLights; i++) {

            float diffuseIntensity;

            if (gl_LightSource[i].position.w != 0.0) {
                vec3 toLight = (gl_LightSource[i].position - position).xyz;

                dist[i] = toLight;
                lightDir[i] = normalize(toLight);

                diffuseIntensity = dot(normalize(toLight), normal);
            } else {
                lightDir[i] = normalize(gl_LightSource[i].position.xyz);

                diffuseIntensity = dot(normalize(gl_LightSource[i].position.xyz), normal);
            }

            diffuseIntensity = max(diffuseIntensity, 0.0);

            diffuse[i] = gl_FrontMaterial.diffuse.rgb * gl_LightSource[i].diffuse.rgb * diffuseIntensity;

        }
    }
}

Fragment:

#version 140

uniform bool useTexture;
uniform bool useLighting;
uniform sampler2D tex;
uniform int numLights;

varying vec3 normal;
varying vec3 ambient;
varying vec3 color;

varying vec3 diffuse[8];
varying vec3 lightDir[8];
varying vec3 dist[8];

varying vec2 texCoord;

void main() {


    vec4 texColor;

    if (useTexture) {
        texColor = texture2D(tex, texCoord);
    } else {
        texColor = vec4(1.0);
    }

    if (texColor.a == 0.0) {
        discard;
    } else {
        texColor.a = 1.0;
    }

    vec3 lightColor;

    if (useLighting) {
        lightColor = ambient;

        for (int i = 0; i < numLights; i++) {
            float specularIntensity;

            float att = 1.0;

            if (gl_LightSource[i].position.w != 0.0) {

                float dist = length(dist[i]);

                att = 1.0 / (gl_LightSource[i].constantAttenuation +
                             gl_LightSource[i].linearAttenuation * dist +
                             gl_LightSource[i].quadraticAttenuation * dist * dist);

                vec3 halfVector = normalize(lightDir[i]) + vec3(0.0, 0.0, 1.0);

                specularIntensity = dot(normalize(halfVector), normalize(normal));
            } else {
                vec3 halfVector = normalize(lightDir[i]) + vec3(0.0, 0.0, 1.0);

                specularIntensity = dot(normalize(halfVector), normalize(normal));
            }

            specularIntensity = max(specularIntensity, 0.0);

            lightColor += diffuse[i] * att;
            lightColor += gl_FrontMaterial.specular.rgb * gl_LightSource[i].specular.rgb * pow(specularIntensity, gl_FrontMaterial.shininess) * att;
        }
    } else {
        lightColor = color;
    }

    gl_FragColor = texColor * vec4(lightColor, 1.0);
}

And finally, my code for loading a shader:

public class ShaderProgram {

    private final int programID;

    public ShaderProgram(int programID) {
        this.programID = programID;
    }

    public ShaderProgram(Shader... shaders) {

        int id;

        try {
            id = glCreateProgram();
        } catch (Exception ex) {
            Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
            programID = 0;
            return;
        }

        for (Shader shader : shaders) {
            glAttachShader(id, shader.id);
        }

        glLinkProgram(id); 
        if (glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE) {
            System.err.println(getLogInfo(id)); // This is the line that causes the error. It actually throws an exception (doesn't just print error info)
            programID = 0;
            return;
        }

        glValidateProgram(id);
        if (glGetProgrami(id, GL_VALIDATE_STATUS) == GL_FALSE) {
            System.err.println(getLogInfo(id));
            programID = 0;
            return;
        }

        programID = id;
    }

    public static String getLogInfo(int obj) {
        return glGetShaderInfoLog(obj, glGetShaderi(obj, GL_INFO_LOG_LENGTH));
    }

    public static ShaderProgram loadPrebuilt(String name) {
        Shader vert = Shader.loadPrebuilt(name + ".vert", Shader.Type.VERTEX);
        Shader frag = Shader.loadPrebuilt(name + ".frag", Shader.Type.FRAGMENT);

        return new ShaderProgram(vert, frag);
    }
}

This is the class for a single shader file (either fragment or vertex)

public class Shader {

    public final int id;

    public Shader(int id) {
        this.id = id;
    }

    public Shader(File file, Shader.Type type) {
        int shader = 0;
        try {
            shader = create(readIntoString(new FileInputStream(file)), type);
        } catch (IOException ex) {
            Logger.getLogger(Shader.class.getName()).log(Level.SEVERE, null, ex);
        }
        id = shader;
    }

    public Shader (String program, Shader.Type type) {
        id = create(program, type);
    }


    public static Shader loadPrebuilt(String name, Shader.Type type) {
        try {
            return new Shader(readIntoString(name), type);
        } catch (IOException | URISyntaxException ex) {
            Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
            return new Shader(0);
        }
    }

    private int create(String program, Type type) {
        int shader = 0;
        try {
            shader = glCreateShader(type.glType);

            glShaderSource(shader, program);

            glCompileShader(shader);

            if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
                System.err.println("Error creating shader (" + type.name() + "): " + getLogInfo(shader));
            }

        } catch (Exception ex) {
            glDeleteShader(shader);
            Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
            shader = 0;
        }

        return shader;
    }

    private static String readIntoString(String filename) throws IOException, URISyntaxException {
        InputStream stream = Shader.class.getResourceAsStream(filename);

        return readIntoString(stream);
    }

    private static String readIntoString(InputStream stream) throws IOException {

        String version = glGetString(GL_SHADING_LANGUAGE_VERSION);
        version = version.substring(0, version.indexOf(" ")).replaceFirst("\\.", "");

        return "#version " + version + "\n\n" + loadTextFile(stream);
    }
}

The line that fails is this:

ShaderProgram.loadPrebuilt("phong");

The files loads just fine. If I print it it prints exactly what I want, and it doesn't fail until I try to get the log info in ShaderProgram.java


Answer:

In this code sequence in the ShaderProgram constructor:

if (glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE) {
    System.err.println(getLogInfo(id));

id is a program id. You pass it to the getLogInfo() method:

public static String getLogInfo(int obj) {
    return glGetShaderInfoLog(obj, glGetShaderi(obj, GL_INFO_LOG_LENGTH));
}

Both glGetShaderInfoLog() and glGetShaderi() expect a shader id as the first argument. To get information about programs, you need to use the corresponding calls for programs instead:

public static String getLogInfo(int obj) {
    return glGetProgramInfoLog(obj, glGetProgrami(obj, GL_INFO_LOG_LENGTH));
}

Question:

When I render a vbo cube using a directional light shader, the light appears "inside out". (Sorry if I can't explain it better).

Here is my vertex shader code (My fragment shader just applies the color, all the work is done in the vertex shader).

#version 150 core
in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;
in vec3 in_Normal;

uniform sampler2D texture;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat3 normalMatrix;
uniform vec3 lDir;

out vec4 color;

void main(void) {
    mat3 nMat = normalMatrix;
    vec3 normal = normalize(in_Normal * nMat);
    vec3 dir = normalize(lDir);
    float nl = max(dot(dir, normal), 0.25);
    //color = NdotL * vec4(0,1,0,1);
    color = vec4(0,1,0,1) * nl;
    gl_Position = projection * view * model * in_Position;
}

The lDir uniform variable stores a float[] array of {0,1,1}. The uniform variable normalMatrix is calculated like this.

    FloatBuffer preBuffer = BufferUtils.createFloatBuffer(16);
    modelMatrix.store(preBuffer);
    preBuffer.flip();
    Matrix4f preMat = new Matrix4f();
    preMat.load(preBuffer);

    Matrix3f preModel3f;
    Matrix3f normal3f = new Matrix3f();
    preModel3f = Tk.to3f(preMat);
    preModel3f.transpose(normal3f);
    normal3f.invert();

    normal3f.store(nmBuffer);
    nmBuffer.flip();
    glUniformMatrix3(glGetUniformLocation(ss.pId, "normalMatrix"), false, nmBuffer);

the modelMatrix variable is self explanitory, minus the fact that it is a buffer, not a matrix. The normal3f variable stores the transposed inverse of the model matrix (which I am pretty sure is the correct way to calculate the normal Matrix). I have to put the modelMatrix buffer into a buffer called preBuffer, if I don't I get errors for some reason.

Leave a comment if you need anything else to help solve this.


Answer:

I figured out the problem, when I rendered the text to the screen (the text that describes the problem with the cube), I forgot to set the glBlendFunc() back to this setting,

glBlendFunc(GL_ONE, GL_ZERO);

This was causing the transparency issue and also fixed some other problems.

Question:

Im learning OpenGL and Im trying to draw a red triangle but my triangle stay black.

This is the code of my fragment shader:

#version 330 core

out vec4 color;

void main()
{
    color = vec4(1,0,0,1);
}

And my shaders compile without issue, I use this class for using shaders:

public class ShaderProgram
{
    private final int programId;

    private int vertexShaderId;

    private int fragmentShaderId;

    public ShaderProgram() throws Exception
    {
        programId = glCreateProgram();
        if (programId == 0) {
            throw new Exception("Could not create Shader");
        }
    }

    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. Code: " + shaderId);
        }

        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: " + glGetShaderInfoLog(programId, 1024));
        }

        glValidateProgram(programId);
        if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
            System.err.println("Warning validating Shader code: " + glGetShaderInfoLog(programId, 1024));
        }

    }

    public void bind() {
        glUseProgram(programId);
    }

    public void unbind() {
        glUseProgram(0);
    }

    public void cleanup() {
        unbind();
        if (programId != 0) {
            if (vertexShaderId != 0) {
                glDetachShader(programId, vertexShaderId);
            }
            if (fragmentShaderId != 0) {
                glDetachShader(programId, fragmentShaderId);
            }
            glDeleteProgram(programId);
        }
    }
}

Then this is my Game class:

public class Game {

    int vertexArrayID;
    int vertexBufferID;

    ShaderProgram fragmentShader;
    ShaderProgram vertexShader;

    float[] vertexData =
        {
            -1.0f, -1.0f, 0.0f,
            1.0f, -1.0f, 0.0f,
            0.0f,  1.0f, 0.0f,
        };

    FloatBuffer vertexBuffer;

    public Game() throws Exception {
        vertexArrayID = glGenVertexArrays();
        glBindVertexArray(vertexArrayID);

        vertexBufferID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);

        vertexBuffer = BufferUtils.createFloatBuffer(vertexData.length);
        vertexBuffer.put(vertexData);
        vertexBuffer.flip();

        glBufferData(GL_ARRAY_BUFFER, vertexBuffer,GL_STATIC_DRAW);

        fragmentShader = new ShaderProgram();
        vertexShader = new ShaderProgram();

        fragmentShader.createFragmentShader(loadShader("fragmentShader.glsl"));
        vertexShader.createVertexShader(loadShader("vertexShader.glsl"));

        fragmentShader.link();
        vertexShader.link();
    }

    public void update()
    {
        fragmentShader.bind();
        vertexShader.bind();

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,vertexBufferID);
        glVertexAttribPointer(0,3,GL_FLOAT,false,0,0);

        glDrawArrays(GL_TRIANGLES,0,3);
        glDisableVertexAttribArray(0);

        fragmentShader.unbind();
        vertexShader.unbind();
    }

    private String loadShader(String input) {
        String r = "";

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(Game.class.getResourceAsStream("/shaders/" + input)));
            String buffer = "";
            while ((buffer = reader.readLine()) != null) {
                r += buffer + "\n";
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return r;
    }
}

Why my triangle stay black after that ?


Answer:

It looks like you're misunderstanding the use of Programs and Shaders in OpenGL.

Shader objects correspond to "Shader Stages" in OpenGL, i.e. the Vertex Shader or the Fragment Shader or one of the other programmable stages in the OpenGL graphics pipeline.

Program objects correspond to the assembled chain of Shader Stages, sometimes referred to colloquially as the complete "Shader".

In your program, however, what you appear to be doing is creating two programs, attaching a vertex shader to one and attaching a fragment shader to the other, and using both of them. To my knowledge, this won't cause OpenGL to throw an error (it'll just use a basic pass-through shader for whichever stage is missing) but that also means that only one of those stages will be active at any time, negating the other. In your case, the code in your update function:

fragmentShader.bind();
vertexShader.bind();

Means that only the Vertex Shader is being used, which is why making changes to your Fragment Shader is having no effect.

To fix this, create only one ShaderProgram object, and attach both the Vertex and Fragment shader source code to that object with respective calls to create[X]Shader. Link it once, and then in the update function, only make a single call to use. The program should work as expected once you've done this.

Question:

I'm using LWJGL to draw "tiles", or textured 2D squares on the screen. However, the texture coordinate is always (0, 0) and therefore the textured square only uses the first pixel colour to fill it.

This is my vertex shader:

#version 330 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;
} 

And this is my fragment shader:

#version 330 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);
} 

And this is essentially the code I'm using to draw the square:

ARBShaderObjects.glUseProgramObjectARB(shaderProgram);  

glBindTexture(GL_TEXTURE_2D, sprite.getId());

glBegin(GL11.GL_QUADS); 
glVertex2d(screenMinX, screenMinY);
glTexCoord2d(0.0, 0.0);
glVertex2d(screenMaxX, screenMinY);
glTexCoord2d(1.0, 0.0);
glVertex2d(screenMaxX, screenMaxY);
glTexCoord2d(1.0, 1.0);
glVertex2d(screenMinX, screenMaxY);
glTexCoord2d(0.0, 1.0);
glEnd();

// release the shader
ARBShaderObjects.glUseProgramObjectARB(0);

I cannot fix it because I don't know how the above code works in the first place. I have not told the shaders what in_Position, in_Color or in_TextureCoord are but the first two seem to work just fine. It is in_TextureCoord, which is eventually passed to the fragment shader, that seems to have a constant value of (0, 0) - I have determined that by setting the output colour of the fragment shader to have one of the channels equal to the X-coordinate of the texture coordinate. It remained a solid colour throughout the square, indicating that there was no change in texture coordinate.

The square produced with the code above should be textured but instead is painted a solid colour - the first pixel of the texture given. How can I change the code to make the texture coordinate change accordingly? If I appear to have some misunderstanding to how this all fits together, please correct me.

This is the tutorial I used to try to accomplish the above.

p.s. I am aware that the Java snippet is using deprecated immediate-mode, but I don't know how to use glDrawArrays or any other commonly suggested method to accomplish the same. Could you help me to change this?


Answer:

I am aware that the Java snippet is using deprecated immediate-mode, but I don't know how to use glDrawArrays or any other commonly suggested method to accomplish the same. Could you help me to change this?

Since you do not need the attribute in_Color anymore, you have to delete the attribute from the vertex shader (and of course also pass_Color from the vertex shader and the fragment shader). Otherwise, you have to expand my solution logically by the color attribute.

Set up an array for the vertex positions an for the texture coordinates:

float[] posData = {
    screenMinX, screenMinY, 0.0, 1.0,
    screenMaxX, screenMinY, 0.0, 1.0,
    screenMaxX, screenMaxY, 0.0, 1.0,
    screenMinX, screenMaxY, 0.0, 1.0 };

float[] texData = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0 };

Generate a vertex array object:

int  vaoObj = glGenVertexArrays();
glBindVertexArray(vaoObj);

Generate array buffers for the vertices and texture coordinates, enable the attribute indices and associate them buffers to the attribute indices:

FloatBuffer posBuffer = MemoryUtil.memAllocFloat(posData.length);
posBuffer.put(posData).flip();
FloatBuffer texBuffer = MemoryUtil.memAllocFloat(texData.length);
texBuffer.put(texData).flip();

int vboPosObj = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboPosObj);
glBufferData(GL_ARRAY_BUFFER, posBuffer, GL_STATIC_DRAW);

// index 0 to associate with "in_Position"            
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0); 
glEnableVertexAttribArray(0); // 0 = attribute index of "in_Position"

int vboTexObj = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboTexObj);
glBufferData(GL_ARRAY_BUFFER, texBuffer, GL_STATIC_DRAW);

// index 0 to associate with "in_TextureCoord"
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1); // 1 = attribute index of "in_TextureCoord"

Release the vertex array object:

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

You have to specify the attribute indices of the attributes in_Position and in_TextureCoord.

Either you use explicit layout specifications in the vertex shader:

layout (location = 0) in vec4 in_Position;
layout (location = 1) in vec2 in_TextureCoord;

Or you specify the attribute indices in the shader program, right before you link the shader program (glLinkProgram).

glBindAttribLocation(shaderProgramID, 0, "in_Position");
glBindAttribLocation(shaderProgramID, 1, "in_TextureCoord");

If the object is to be drawn, it is sufficient to bind the Vertex Array Object:

glBindVertexArray(vaoObj);
glDrawArrays(GL_QUADS, 0, 4); // 4 = number of vertices 
glBindVertexArray(0);

Note, if a buffer objects or a vertex array object is not further used, it has to be deleted, to prevent memory leaks. Buffer objects are deleted by glDeleteBuffers and vertex array objects are deleted by glDeleteVertexArrays. Buffer objects are not "created under" vertex array objects, it is not sufficient to delete the vertex array object only (see OpenGL Vertex Array/Buffer Objects)

Question:

I'm trying to get the shaders from this tutorial to work: https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/discard.php

I copied the source code into two files, but neither will compile.

This is the code I have:

    shaderProgram = glCreateProgram();
    vertexShader  = glCreateShader(GL_VERTEX_SHADER);
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    StringBuilder vertexShaderSource   = new StringBuilder();
    StringBuilder fragmentShaderSource = new StringBuilder();

    try{
        BufferedReader reader = new BufferedReader(new FileReader("src/shader.vert"));
        String line;
        line = reader.readLine();

        while(line != null){
            line = reader.readLine();

            if(line != null){
                vertexShaderSource.append(line).append('\n');
            }
        }
        reader.close();


    } catch (IOException e) {
        System.err.println("Vertex no load.");
        Display.destroy();
        System.exit(1);
    }

    try{
        BufferedReader reader = new BufferedReader(new FileReader("src/shader.frag"));
        String line;
        line = reader.readLine();

        while(line != null){
            line = reader.readLine();

            if(line != null){
                fragmentShaderSource.append(line).append('\n');
            }
        }
        reader.close();


    } catch (IOException e) {
        System.err.println("Frag no load.");
        Display.destroy();
        System.exit(1);
    }
    System.out.println(fragmentShaderSource);


    glShaderSource(vertexShader, vertexShaderSource);
    glCompileShader(vertexShader);
    if(glGetShader(vertexShader, GL_COMPILE_STATUS) == GL_FALSE){
        System.err.println("Vertex no compile");
    }
    glShaderSource(fragmentShader, fragmentShaderSource);
    glCompileShader(fragmentShader);
    if(glGetShader(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE){
        System.err.println("frag no compile");
    }


    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glValidateProgram(shaderProgram);

I've had shaders work before, so its not the setup (that I know of) but when I copied and pasted neither file would compile anymore.

Is my setup wrong somehow?

EDIT >>>

I can't seem to import glGetShaderiv

I am using LWJGL and imported everything from there. Could I be missing a JAR file?

EDIT >>>

Related Question:

I get error "Exception in thread "main" org.lwjgl.opengl.OpenGLException: Invalid operation (1282)", what it is?, how I can fix it?


Answer:

You are reading the source files incorrectly.

line = reader.readLine();

while(line != null){
    line = reader.readLine();

    if(line != null){
        fragmentShaderSource.append(line).append('\n');
    }
}

Here, you first read the first line of the file. If it isn't null, you continue reading lines and appending them to the buffer. However, you don't actually append the line after the readLine() statement outside of the loop, which means it is discarded and the shader compiler gets a source file with the first line missing. Therefore it doesn't know about varying vec2 vTexCoord; or sampler2D myTexture;, raising compiler errors when they are used later in the code.

There are several ways to fix this:

  1. line = reader.readLine();
    if (line != null) {
        fragmentShaderSource.append(line).append('\n');
    }
    
    while (line != null) {
        // ...
    }
    
  2. while (true) {
        line = reader.readLine();
    
        if (line == null) {
            break;
        }
    
        fragmentShaderSource.append(line).append('\n');
    }
    
  3. while ((line = reader.readLine()) != null) {
        fragmentShaderSource.append(line).append('\n');
    }
    

Which one to use depends on your preferences. 1 contains redundant code, which is almost never the best solution. 2 is a commonly used way of reading arbitrary files; and while 3 is shorter, some people don't like assigning variables in loop control statements.

Question:

After testing a few things in my OpenGL application, I know that my textures are not loading correctly because the texture coordinates are failing to get from the vertex shader to the fragment shader (or atleast they are all passed as (0,0). I just don't know why.

Here are my positions, indices and texture coordinates for a square:

private static final float[] VERTICES = {
    -0.5f,  0.5f, 0f,
    -0.5f, -0.5f, 0,
     0.5f, -0.5f, 0f,
     0.5f,  0.5f, 0f
};

private static final int[] INDICES = {
    0, 1, 2,
    3, 0, 2
};

private static final float[] TEXTURE_COORDINATES = {
    0.0f, 0.0f,
    0.0f, 1.0f,
    1.0f, 1.0f,
    1.0f, 0.0f
};

Here is how I insert the texture coordinates into the vao at index 1. For the sake of brevity I won't show the other parts of my vao loader since they are in working order.

int vboTexCoordID = GL15.glGenBuffers();
ModelManager.recordVBO(vboTexCoordID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboTexCoordID);

FloatBuffer texCoordBuffer = BufferUtils.createFloatBuffer(texCoord.length);
verticesBuffer.put(texCoord);
verticesBuffer.flip();

GL15.glBufferData(GL15.GL_ARRAY_BUFFER, texCoordBuffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(1,2,GL11.GL_FLOAT, false,  0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

This is my render method:

    model.getShader().start(); // this calls GL20.glUseProgram()
    GL30.glBindVertexArray(model.getVaoID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexId());
    GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVerticesCount(), GL11.GL_UNSIGNED_INT,0);
    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);
    model.getShader().stop();

and finally mt vertex shader and fragment shader in that order:

#version 330 core

in vec3 position;
in vec2 texCoords;

out vec2 pass_texCoords;

void main(void){

    gl_Position = vec4(position.x, position.y, position.z, 1.0);
    pass_texCoords = texCoords;

}

fragment:

#version 330 core

in vec2 pass_texCoords;

out vec4 out_Color;

uniform sampler2D textureSampler;

void main(void){

    out_Color = texture(textureSampler, pass_texCoords);

}

Answer:

You never add data to texCoordBuffer:

FloatBuffer texCoordBuffer = BufferUtils.createFloatBuffer(texCoord.length);
verticesBuffer.put(texCoord);
verticesBuffer.flip();

GL15.glBufferData(GL15.GL_ARRAY_BUFFER, texCoordBuffer, GL15.GL_STATIC_DRAW);

texCoordBuffer is empty when you call glBufferData(), since you store the texture coordinates in verticesBuffer. You need to change this to:

FloatBuffer texCoordBuffer = BufferUtils.createFloatBuffer(texCoord.length);
texCoordBuffer.put(texCoord);
texCoordBuffer.flip();

GL15.glBufferData(GL15.GL_ARRAY_BUFFER, texCoordBuffer, GL15.GL_STATIC_DRAW);

You also need to make sure that the locations you use for the vertex attributes match up with the vertex shader. The easiest way to do this is to use layout directives in the vertex shader code:

layout(location=0) in vec3 position;
layout(location=1) in vec2 texCoords;

This specifies that the vertex shader will read the positions from attribute 0, and the texture coordinates from attribute 1.

Question:

I'm drawing a quad with a 512 x 512 texture composed of 4 squares with 4 different colors (yellow, blue, green, red). When i look at the image it's all yellow but the tex coords space from 0 to 1 and i'm quite sure they're mapped correctly... here's the code:

private void loadTexture(String textureFile) {
        TexHandle = glGenTextures();
        BufferedImage TextureBuffer = null;
        try {
            TextureBuffer = ImageIO.read(new File(textureFile));
        } catch (IOException ex) {
            System.err.println("Error while reading the texture: " + textureFile);
            System.exit(1);
        }
        Width = TextureBuffer.getWidth();
        Height = TextureBuffer.getHeight();
        AlphaChannel = TextureBuffer.getColorModel().hasAlpha();
        int pixel;
        int[] pixels = TextureBuffer.getRGB(0, 0, Width, Height, null, 0, Width);
        ByteBuffer Buffer = BufferUtils.createByteBuffer(Width * Height * 4);
        for(int i = 0; i < Height; i++){
            for(int j = 0; j < Width; j++){
                pixel = pixels[i * Width + j];

                Buffer.put((byte)( pixel        & 0xff));
                Buffer.put((byte)((pixel >> 8)  & 0xff));
                Buffer.put((byte)((pixel >> 16) & 0xff));

                if(AlphaChannel)
                    Buffer.put((byte)((pixel >> 24) & 0xff));
                else
                    Buffer.put((byte)0xff);
            }
        }
        glBindTexture(GL_TEXTURE_2D, TexHandle);

        Buffer.flip();
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, Buffer);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glBindTexture(GL_TEXTURE_2D, 0);
    }

public void initOpenGL() {
        glClearColor(0f, 0f, 0.4f, 1f);

        glFrontFace(GL_CCW);

        glCullFace(GL_BACK);
        glEnable(GL_CULL_FACE);

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);

        glDepthFunc(GL_LEQUAL);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_DEPTH_CLAMP);

        glEnable(GL_TEXTURE_2D);
    }

main :

    while(!window.isClosing()){

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        program.updateUniform("TextureIndex", 0);
        glActiveTexture(GL_TEXTURE0 + 0);
        glBindTexture(GL_TEXTURE_2D, TexHandle);
        glBegin(GL_QUADS);
        glNormal3f(0, 0, 0);

        glTexCoord2f(0, 0);
        glVertex3f(-.5f, -.5f, -2f);

        glTexCoord2f(1, 0);
        glVertex3f(.5f, -.5f, -2f);

        glTexCoord2f(1, 1);
        glVertex3f(.5f, .5f, -2f);

        glTexCoord2f(0, 1);
        glVertex3f(-.5f, .5f, -2f);

        glEnd();

        window.update();
    }

vertex :

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_texture_coord;
layout(location = 2) in vec3 in_normal;
out vec2 out_texture_coord;

void main(){

    gl_Position = vec4(in_position, 1.0);
    out_texture_coord  = in_texture_coord;

}

fragment :

    out vec4 out_color;
    in vec2 in_texture_coord; // passed from the vertex shader
    uniform sampler2D TextureIndex;

    void main(){

        out_color = texture2D(TextureIndex, in_texture_coord);

    }

Answer:

The posted code is mixing legacy OpenGL functionality with modern OpenGL functionality in unsupported ways. The vertex specification code uses old style fixed function attributes:

glNormal3f(0, 0, 0);
glTexCoord2f(0, 0);
glVertex3f(-.5f, -.5f, -2f);

While the vertex shader expects generic vertex attributes:

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_texture_coord;
layout(location = 2) in vec3 in_normal;

There is no direct correspondence between the two. The spec has some language saying that generic attribute 0 maps to the legacy vertex position, but even that does not always work reliably with all drivers. And it is certainly invalid to assume that for example values specified with glTexCoord2f() will map to an attribute with (location = 1) in the vertex shader.

There are two main ways to fix that:

  1. Change the shader code to work with the legacy calls used for specifying the vertex data. This is done by removing the in variable declarations in the vertex shader code, and using the pre-defined variables to access the attribute values:

    gl_Vertex for the vertex position

    gl_MultiTexCoord0 for the texture coordinates

    gl_Normal for the normal

  2. Use API functions for setting the values of generic vertex attributes instead of the fixed function attributes. For the code fragment above, and matching the locations from the vertex shader code:

    glVertexAttrib3f(2, 0.0f, 0.0f, 0.0f);
    glVertexAttrib2f(1, 0.0f, 0.0f);
    glVertexAttrib3f(0, -0.5f, -0.5f, -2.0f);
    

If you're ready to move towards modern OpenGL, option 2 will be the better direction. One of the next steps on that path would be to use vertex buffer objects (VBO) to specify the vertex data, instead of the immediate mode calls in your current code.

Question:

I have started OpenGL game development about 5 months ago. When i first started game development i wached a tutorial about a game engine. But now a fiew months later i would like to edit one of the openGL parts on that game engine but i have no idea how.

I would not like to use texture coords and a corresponding image but just use RGB collors that i parse to the OpenGL shader.

The code i use to render entities:

public void render(Map<TexturedModel, List<Entity>> entities){
    for(TexturedModel model:entities.keySet()){
        prepareTexturedModel(model);
        List<Entity> batch = entities.get(model);
        for(Entity entity:batch){
            prepareInstance(entity);
            GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
        }
        unbindTexturedModel();
    }
}

Answer:

If you have direct access to the shader object (which should be a primitive integer) you can do this:

in the fragment shader, which will probably end in .frag or .fsh:

uniform vec3 myColor;
out vec4 fragColor;
void main(){
    fragColor=vec4(myColor,1.0);
}

In the Java code, per-frame AFTER you have called glUseProgram(shaderID), you need to call glUniform3f(glGetUniformLocation(shaderID,"myColor"),red,green,blue); where red, green and blue are floats in the range [0,1]. If you don't have access to the integer shader id, then it really depends on which game engine you are using.

Question:

In my createShaderProgram method after glLinkProgram(pID) and glValidateProgram(pID) i have some simple error checking.

int errorCheckValue = glGetError();
if(errorCheckValue != GL_NO_ERROR)
{
    System.err.println("Could not create shaders " + GLU.gluErrorString(errorCheckValue));
   //System.exit(-1);
}

This peace of code fire an error message --> Could not create shaders Invalid operation. Because i commented System.exit(-1) everything works fine but i dont know why this error occurs. Is there any way of code some error handling function that is more specific about the error - something more specific than just Invalid operation?

EDIT: Here is the rest of the code

private static int createShader(String source, int shaderType)
{
    int shaderID = 0;
    shaderID = glCreateShader(shaderType);
    glShaderSource(shaderID, source);
    glCompileShader(shaderID);

    if(glGetShaderi(shaderID, GL_COMPILE_STATUS) == GL_FALSE)
    {
        System.err.println("Shader failed to compile!");
        System.err.println(glGetShaderInfoLog(shaderID, 2048));
        System.exit(-1);
    }

    return shaderID;
}

public static int[] createShaderProgram(String vertFilename, String fragFilename, Attribute locations[])
{
    int pID, vertID, fragID = 0;
    pID = glCreateProgram();
    vertID = createShader(FileUtils.loadFileAsString(vertFilename), GL_VERTEX_SHADER);
    fragID = createShader(FileUtils.loadFileAsString(fragFilename), GL_FRAGMENT_SHADER);
    glAttachShader(pID, vertID);
    glAttachShader(pID, fragID);
    for(int i = 0; i < locations.length; i++){locations[i].bindAttribute(pID);}
    glLinkProgram(pID);
    glValidateProgram(pID);
    int errorCheckValue = glGetError();
    if(errorCheckValue != GL_NO_ERROR)
    {
        System.err.println("Could not create shaders " + GLU.gluErrorString(errorCheckValue));
        //System.exit(-1);
    }

    int[] result = new int[] {pID, vertID, fragID};

    return result;
}

Answer:

You can check the link/validation status and print the program info log similar to how you are doing it with the shaders.

glLinkProgram(pID);
if (glGetProgrami(pID, GL_LINK_STATUS) == GL_FALSE) {
    System.err.println("Program failed to link");
    System.err.println(glGetProgramInfoLog(pID, glGetProgrami(pID, GL_INFO_LOG_LENGTH)));
}

(And the same with GL_VALIDATE_STATUS.)


If you are using LWJGL 3 (latest nightly build), you can setup an OpenGL debug message callback with

GLUtil.setupDebugMessageCallback();

This will automatically choose the correct OpenGL extension (or core functionality) to setup a callback that prints an error message every time an OpenGL error occurs (so no need to call glGetError() any more).

You can have a look at GLUtil's source code on how to manually setup the debug callbacks if you want more control over the output.

Question:

I am trying to correctly translate and project points of a mesh to the surface of a window using shaders (the point of interest is the vertex shader which is responsible for outputting the final vertex positions).

I will elaborate more on this question in approximately 6 hours, since I have to go to bed now. If anyone has the will to read through this (it isn't yet correctly highlihted and written as well as it could be) I would appreciate it even more.

The model (quad) is represented by the following vertices: [-0.5f, 0.5f, 0f] (V0), [-0.5f, -0.5f, 0f] (V1), [0.5f, -0.5f, 0f] (V2), [0.5f, 0.5f, 0].

I have the following pair of methods to create a perspective projection matrix:

public static Matrix4f getProjectionMatrix(float fovy, int width, int height, float zNear, float zFar) {
    float aspectRatio = (float) width / height;
    projectionMatrix.perspective(fovy, aspectRatio, zNear, zFar);
    return projectionMatrix;
}

This method is found in the Transformations class creates and returns a perspective projection matrix.

  • fovy = The vertical field of view
  • width = The width of the window
  • height = The height of the window
  • zNear = The near clipping plane
  • zFar = The far clipping plane

    public Matrix4f perspective(float fovy, float aspectRatio, float zNear, float zFar) {
        float scale = (float) (Math.tan(fovy * 0.5) * zNear);
        float top = scale;
        float right = top * aspectRatio;
        float bottom = -top;
        float left = bottom * aspectRatio;
    
        this.m00 = 2*zNear / (right - left);
        this.m03 = (right + left) / (right - left);
        this.m11 = 2*zNear / (top - bottom);
        this.m12 = (top + bottom) / (top - bottom);
        this.m22 = -(zFar + zNear) / (zFar - zNear);
        this.m23 = -2*zFar*zNear / (zFar - zNear);
        this.m32 = -1;
    
        return this;
    

    } This method is in the Matrix4f class.

Here is the beginning of the Matrix4f class, with the Matrix4f instance variables and the constructor:

public class Matrix4f {
    float m00, m01, m02, m03;
    float m10, m11, m12, m13;
    float m20, m21, m22, m23;
    float m30, m31, m32, m33;

public Matrix4f() {
    m00 = 1.0f; m01 = 0.0f; m02 = 0.0f; m03 = 0.0f;
    m10 = 0.0f; m11 = 1.0f; m12 = 0.0f; m13 = 0.0f;
    m20 = 0.0f; m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;
    m30 = 0.0f; m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;
}

After the constructor is called, the identity matrix is already created. The only thing left is to know how to initialize the perspective projection matrix. This is done when calling the constructor of class Transformations:

public class Transformations {
    private Matrix4f translationMatrix;
    private static Matrix4f projectionMatrix;

    public Transformations() {
        translationMatrix = new Matrix4f();
        projectionMatrix = new Matrix4f();
    }

Now for the translation matrix. The functionality for it's creation is provided in the Transformations class via the method getTranslationMatrix(float x, float y, float z) which creates and returns a translation matrix using the parameters:

public Matrix4f getTranslationMatrix(float x, float y, float z) {
    translationMatrix.m03 = x;
    translationMatrix.m13 = y;
    translationMatrix.m23 = z;
    return translationMatrix;
}

To actually have something that represents a game model, I've created a class called GameEntity. It represents the model's mesh and position:

public class GameEntity {

    private final Mesh mesh;
    private Vector3f position;

    public GameEntity(Mesh mesh) {
        this.mesh = mesh;
        position = new Vector3f(0, 0, 0);
    }

    public Vector3f getPosition() {
        return position;
    }    

    public void updatePosition(float x, float y, float z) {
        position.x += x;
        position.y += y;
        position.z += z;
    }

    public Mesh getMesh() {
        return mesh;
    }
}

The updatePosition method is supposed to move the entity around the window as a whole. I won't include code explanation for the Mesh class in here. All you need to know is that it holds mesh (vertex) data about a GameEntity, for example vertex positions, vertex colours, indices, etc, which are all stored inside a vertex array object which is then in turn used for rendering that Mesh instance onto the window. In my case, the two triangles which form a quad are represented as a GameEntity instance.

Moving the model: The updatePosition method is called every time any of the keys W, A, S, D, space or left shift are pressed. It updates the positon of the GameEntity instance (which is stored inside GameEntity[] entities array at index 0) by a set amount:

    private void processInput() {
        glfwPollEvents();

        if (window.keys[GLFW_KEY_W]) {
            entities[0].updatePosition(0, 0, -1.0f);
        } else if (window.keys[GLFW_KEY_S]){
            entities[0].updatePosition(0, 0, 1.0f);
        } else if (window.keys[GLFW_KEY_A]) {
            entities[0].updatePosition(1.0f, 0, 0);
        } else if (window.keys[GLFW_KEY_D]) {
            entities[0].updatePosition(-1.0f, 0, 0);
        } else if (window.keys[GLFW_KEY_SPACE]) {
            entities[0].updatePosition(0, 1.0f, 0);
        } else if (window.keys[GLFW_KEY_LEFT_SHIFT]) {
            entities[0].updatePosition(0, -1.0f, 0);
        } 
     }

This method is called inside the main game loop.

Then, inside the Renderer class, the translation matrix for the model is constructed based on it's position and the projection matrix is constructed based on the properties of the window object:

private ShaderProgram shaderProgram;
private Window window = new Window();

private final Transformations transformation;

private Matrix4f translationMatrix = new Matrix4f();
private Matrix4f projectionMatrix = new Matrix4f();


private static double angleOfView = 60.0;
private static final float FOVY = (float) Math.toRadians(angleOfView);
private static final float zNear = 0.01f;
private static final float zFar = 1000.0f;

shaderProgram.createUniform("translationMatrix");
shaderProgram.createUniform("projectionMatrix");

public void render(Window window, GameEntity[] entities) {
    i++;

    clear();

    if (window.isResized()) {
        glViewport(0, 0, window.getWidth(), window.getHeight());
        window.setResized(false);
    }

    //make the shaders active
    shaderProgram.bind();

    //update the projection matrix
    Matrix4f projectionMatrix = transformation.getProjectionMatrix(FOVY, window.getWidth(), window.getHeight(), zNear, zFar);

    shaderProgram.setUniformMatrix("projectionMatrix", projectionMatrix);

    //render each game item
    for(GameEntity entity : entities) {
        Matrix4f translationMat = transformation.getTranslationMatrix(entity.getPosition());
        shaderProgram.setUniformMatrix("translationMatrix", translationMat);
        entity.getMesh().render();
    }

    shaderProgram.unbind();
}

First, all of the uniform locations are defined (above the render() method).

The clear() method clears the rendering buffer - it prepares it to render a new image. In the following if clause, window resize operations are handled. If the window is resized, the if clause with corresponding methods will update the width and height of the window to match the resized window.

The projectionMatrix is constructed out of variables which are defined as instance variables of the Renderer class (FOVY, zNear, zFar) and two variables which get the current width and height of the window object (window.getWidth(), window.getHeight()).

Then, the projection matrix is "sent" to the vertex shader by callingshaderProgram.setUniformMatrix("projectionMatrix", projectionMatrix);:

private final Map<String, Integer> uniforms;

public void createUniform(String uniformName) throws Exception {
    int uniformLocation = glGetUniformLocation(programID, uniformName);

    if (uniformLocation < 0) {
        throw new Exception("[ShaderProgram.createUniform]: Couldn't find uniform: " + uniformName);
    }
    uniforms.put(uniformName, uniformLocation);
}

This method is located in the ShaderProgram class, which holds references to the active shader porgram and the uniform variables associated with it which are stored in the uniforms Hashmap..

Then, inside the for loop, the two quads are rendered. First, a translation matrix is constructed based on the value of GameInstance's position value, which is represented as a 3-tuple vector (x, y, z). Then, that created matrix is "sent" to the vertex shader.

Now, having sent both the perspective projection (projectionMatrix) and translation matrix (translationMatrix) to the vertex shader, it's time to call the render method on our Mesh instance to render it. The code for the render() method (in the context of entity.getMesh().render()) is:

public void render() {
    glBindVertexArray(getVaoID());
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getIndicesVboID());

    glDrawElements(GL_TRIANGLES, getVertexCount(), GL_UNSIGNED_INT, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDisableVertexAttribArray(0);
    glBindVertexArray(0);
}

The results are not satisfactory, however. When W or S are pressed, the quad (two triangles) goes off farther or closer to "us", which is correct. However, when A or D are pressed (which should translate the model on the x axis), the quad (two triangles) isn't translated. It just rotates around it's center. How to fix the issue? Thank you for the help and for the time taken to read through this long question.


Answer:

Seems there's something wrong with row/column nomenclature.

As I understand your code cell mij in the matrix is col=i, row=j

OpenGL expects a 16 values array, being the translation the 13,14,15 positions. Usually this is called "column major order", a translation is represented in the 4th column.

So Try this:

public Matrix4f getTranslationMatrix(float x, float y, float z) {
    translationMatrix.m30 = x;
    translationMatrix.m31 = y;
    translationMatrix.m32 = z;
    return translationMatrix;
}

Also, review your perspective. I think you have some mistakes in ij indices. ii cells look good.

Question:

When i was following tutorial on java lwjgl 2.9 3D Game tutorial on thinmatrix. I got annoying problem(Stuck at ep16:fog): 0(9) : error C0000: syntax error, unexpected reserved word "out", expecting ',' or ';' at token "out", Could not compile shader!

I Checked My code 2 times and still throws exception, i don't know what to do anymore just can't.

Any Help is greatly appreciated.

EDIT: If you need more code then comment about it.

terrainVertexShader

#version 400 core

in vec3 position;
in vec2 textureCoordinates;
in vec3 normal;

out vec2 pass_textureCoordinates;
out vec3 surfaceNormal;
out vec3 toLightVector;
out vec3 toCameraVector;
out float visibility;

uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;

const float density = 0.007;
const float gradient = 1.5;

void main(void){

    vec4 worldPosition = transformationMatrix * vec4(position,1.0);
    vec4 positionRelativeToCam = viewMatrix * worldPosition;
    gl_Position = projectionMatrix * positionRelativeToCam;
    pass_textureCoordinates = textureCoordinates * 40.0;

    surfaceNormal = (transformationMatrix * vec4(normal,0.0)).xyz;
    toLightVector = lightPosition - worldPosition.xyz;
    toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - 
    worldPosition.xyz;

    float distance = length(positionRelativeToCam.xyz);
    visibility = exp(-pow((distance*density), gradient));
    visibility = clamp(visibility, 0.0, 1.0);
}

terrainFragmentShader

#version 400 core

in vec2 pass_textureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCameraVector;
in float visibility

out vec4 out_Color;

uniform sampler2D modelTexture;
uniform vec3 lightColour;
uniform float shineDamper;
uniform float reflectivity;
uniform vec3 skyColour;

void main(void){

    vec3 unitNormal = normalize(surfaceNormal);
    vec3 unitLightVector = normalize(toLightVector);

    float nDotl = dot(unitNormal,unitLightVector);
    float brightness = max(nDotl,0.0);
    vec3 diffuse = brightness * lightColour;

    vec3 unitVectorToCamera = normalize(toCameraVector);
    vec3 lightDirection = -unitLightVector;
    vec3 reflectedLightDirection = reflect(lightDirection,unitNormal);

    float specularFactor = dot(reflectedLightDirection , 
    unitVectorToCamera);
    specularFactor = max(specularFactor,0.0);
    float dampedFactor = pow(specularFactor,shineDamper);
    vec3 finalSpecular = dampedFactor * reflectivity * lightColour;


    out_Color =  vec4(diffuse,1.0) * textureColour + 
    vec4(finalSpecular,1.0);
    out_Color = mix(vec4(skyColour,1.0), out_Color, visibility);


}

TerrainShader

package shaders;

import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import entities.Camera;
import entities.Light;
import toolbox.Maths;

public class TerrainShader extends ShaderProgram{


    private static final String VERTEX_FILE = 
    "src/shaders/terrainVertexShader.txt";
    private static final String FRAGMENT_FILE = 
    "src/shaders/terrainFragmentShader.txt";

    private int location_transformationMatrix;
    private int location_projectionMatrix;
    private int location_viewMatrix;
    private int location_lightPosition;
    private int location_lightColour;
    private int location_shineDamper;
    private int location_reflectivity;
    private int location_skyColour;

    public TerrainShader() {
        super(VERTEX_FILE, FRAGMENT_FILE);
    }

    @Override
    protected void bindAttributes() {
        super.bindAttribute(0, "position");
        super.bindAttribute(1, "textureCoordinates");
        super.bindAttribute(2, "normal");
    }

    @Override
    protected void getAllUniformLocations() {
        location_transformationMatrix = 
        super.getUniformLocation("transformationMatrix");
        location_projectionMatrix = 
        super.getUniformLocation("projectionMatrix");
        location_viewMatrix = super.getUniformLocation("viewMatrix");
        location_lightPosition = super.getUniformLocation("lightPosition");
        location_lightColour = super.getUniformLocation("lightColour");
        location_shineDamper = super.getUniformLocation("shineDamper");
        location_reflectivity = super.getUniformLocation("reflectivity");
        location_skyColour = super.getUniformLocation("skyColour");

    }

    public void loadSkyColour(float r, float g, float b) {
        super.loadVector(location_skyColour, new Vector3f(r,g,b));
    }

    public void loadShineVariables(float damper,float reflectivity){
        super.loadFloat(location_shineDamper, damper);
        super.loadFloat(location_reflectivity, reflectivity);
    }

    public void loadTransformationMatrix(Matrix4f matrix){
        super.loadMatrix(location_transformationMatrix, matrix);
    }

    public void loadLight(Light light){
        super.loadVector(location_lightPosition, light.getPosition());
        super.loadVector(location_lightColour, light.getColour());
    }

    public void loadViewMatrix(Camera camera){
        Matrix4f viewMatrix = Maths.createViewMatrix(camera);
        super.loadMatrix(location_viewMatrix, viewMatrix);
    }

    public void loadProjectionMatrix(Matrix4f projection){
        super.loadMatrix(location_projectionMatrix, projection);
    }
}

Answer:

In TerrainFragmentShader you are missing a semicolon after visibility

#version 400 core

in vec2 pass_textureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCameraVector;
in float visibility //<-semicolon here

Question:

I was following a tutorial on writing a game engine in Java using LWJGL. I wrote a fragment shader in GLSL and called it basicFragment.fs:

#version 330

out vec4 fragColor;

void main()
{
    fragColor = vec4(0,0, 1.0, 1.0, 1.0);
}

Now I followed the tutorial to write a way to compile the shader and it is here that I get an error. First, here is my Shader class.

package com.base.engine;

import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL21.*;
import static org.lwjgl.opengl.GL32.*;

public class Shader 
{
    private int program;

    public Shader()
    {
        program = glCreateProgram();

        if(program == 0)
        {
            System.err.println("Shader creation failed: Could not find valid memory location in constructor");
            System.exit(1);
        }
    }

    public void bind()
    {
        glUseProgram(program);
    }

    public void addVertexShader(String text)
    {
        addProgram(text, GL_VERTEX_SHADER);
    }

    public void addGeometryShader(String text)
    {
        addProgram(text, GL_GEOMETRY_SHADER);
    }

    public void addFragmentShader(String text)
    {
        addProgram(text, GL_FRAGMENT_SHADER);
    }

    public void compileShader()
    {
        glLinkProgram(program);

        if(glGetProgrami(program, GL_LINK_STATUS) == 0)
        {
            System.err.println(glGetShaderInfoLog(program, 1024));
            System.exit(1);
        }

        glValidateProgram(program);

        if(glGetProgrami(program, GL_VALIDATE_STATUS) == 0)
        {
            System.err.println(glGetShaderInfoLog(program, 1024));
            System.exit(1);
        }
    }

    private void addProgram(String text, int type)
    {
        int shader = glCreateShader(type);

        if(shader == 0)
        {
            System.err.println("Shader creation failed: Could not find valid memory location when adding shader");
            System.exit(1);
        }

        glShaderSource(shader,text);
        glCompileShader(shader);

        if(glGetShaderi(shader, GL_COMPILE_STATUS) == 0)
        {
            System.err.println(glGetShaderInfoLog(shader, 1024));
            System.exit(1);
        }

        glAttachShader(program, shader);
    }
}

Then, in my game class I do the following. (Hopefully the code is self explanatory. Let me know if I'm unclear anywhere):

public class Game 
{
    private Mesh mesh;
    private Shader shader;

    public Game()
    {
        mesh = new Mesh();
        shader = new Shader();

        Vertex[] data = new Vertex[] {new Vertex(new Vector3f(-1,-1,0)),
                                      new Vertex(new Vector3f(-1,1,0)),
                                      new Vertex(new Vector3f(0,1,0))};

        mesh.addVertices(data);

        shader.addVertexShader(ResourceLoader.loadShader("basicVertex.vs"));
        shader.addFragmentShader(ResourceLoader.loadShader("basicFragment.fs"));
        shader.compileShader();
    }

    public void render()
    {
        shader.bind();
        mesh.draw();

    }

So basically, when I call the function,

shader.addFragmentShader(ResourceLoader.loadShader("basicFragment.fs"));

The function gives me this error:

3.3.0 - Build 8.15.10.2712
ERROR: 0:7: 'constructor' : too many arguments

I don't get any error when I just implement the vertex shader so I've concluded it's the fragment shader.

That error is getting thrown from this part of the Shader class:

if(glGetShaderi(shader, GL_COMPILE_STATUS) == 0)
{
    System.err.println(glGetShaderInfoLog(shader, 1024));
    System.exit(1);
}

Which leads me to believe that the problem is that the shader isn't compiling because some constructor has too many arguments. I don't know exactly what constructor it is referring to.

Any help would be appreciated.


Answer:

I don't know exactly what constructor it is referring to.

The one in your shader code:

fragColor = vec4(0,0, 1.0, 1.0, 1.0);

That's a vec4 constructor. And you gave it 5 parameters. "0,0" is two of them. I rather suspect you meant to use a period rather than a comma.

Question:

I'm currently working on a LWJGL 2 game. I'M using the libraries from https://github.com/mattdesl/lwjgl-basics (for example the Texture and ShaderProgram class). I am aware, that you can get a limited amount of lights to be rendered in your shader, but I didn't find any solution to make the lighting more dynamic and efficient. I want to pass a Vector3f[] lights into the .frag file as uniform vec3 lights[]. How can I do that? Any other idea of dynamicly changing the number of lights im shading? Here's the code of the fragment shader:

    //attributes from vertex shader
    varying vec4 vColor;
    varying vec2 vTexCoord;

    uniform sampler2D u_texture;  
    uniform sampler2D u_normals;   


    //the array should be inserted as:

    uniform vec3 Lights[];  

    uniform int numOfLights;          
    uniform vec2 Resolution;     
    uniform float Rotation;      
    //uniform vec3 LightPos;   
    uniform vec4 LightColor;      
    uniform vec4 AmbientColor;  
    uniform vec3 Falloff;      

    void main() {

    vec4 sumColor = vec4(0.0,0.0,0.0,0.0);

    for(int i = 0;i < numOfLights;i++){
    vec3 LightPos = Lights[i];

    vec4 DiffuseColor = texture2D(u_texture, vTexCoord);
    vec3 NormalMap = texture2D(u_normals, vTexCoord).rgb;


    vec3 LightDir = vec3(LightPos.x - gl_FragCoord.x/ Resolution.x,LightPos.y - gl_FragCoord.y / Resolution.y, LightPos.z);

    float D = length(LightDir);

    vec3 N = normalize(NormalMap * 2.0 - 1.0);
    float LRot = atan(LightDir.y, LightDir.x);
    vec3 L = normalize(vec3(cos(LRot + Rotation),sin(LRot + Rotation),LightDir.z + 0.5));

    vec3 Diffuse = (LightColor.rgb * LightColor.a) * max(dot(N, L), 0.0);

    vec3 Ambient = AmbientColor.rgb * AmbientColor.a;

    float Attenuation = 1.0 / ( Falloff.x + (Falloff.y*D) + (Falloff.z*D*D) );

    vec3 Intensity = 2 * Ambient + Diffuse * Attenuation;
    vec3 FinalColor = DiffuseColor.rgb * Intensity;
//sumColor gets added as many times as there are lights
    sumColor = sumColor + vColor * vec4(FinalColor, DiffuseColor.a);
    }
    gl_FragColor = sumColor;
}

Currently I pass the other Vectors into the .frag file using the setUniformf(String name, Vector3f v) method from the ShaderProgram class. For Example, I would like to pass them in like:

public Vector3f[] lights;
//all the lights get add into the array
shader.setUniformf("Lights", lights);

It would be even more nice if I could store the lights in a ListArray<> and pass that into the fragment shader.


Answer:

I am afraid that is a problem with lighting in OpenGL. If you want to do what is called forward shading, you must have a limited amount of lights in your shader. There are several ways to do more advanced lighting calculations and still have a good performance, one of them is deferred shading.

You can find a great article about this here http://learnopengl.com/#!Advanced-Lighting/Deferred-Shading

Unfortunately it uses c++, but i hope you can find some more information on how to do it using java.

Question:

I am developing a program in OpenGl. My curent setup includes just one quad and a texture I want to render on it. The problem is that the texture doesn't render on to the quad. If I change the fragment shader to render a color it renders correctly.

Here is the render code:

glfwSwapBuffers(window);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glUseProgram(programID);

glBindVertexArray(vaoID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glDrawElements(GL_TRIANGLES, indicies.length, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);

glUseProgram(0);

Vertex shader:

#version 400 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 textureCoords;

out vec2 pass_TextureCoords;

void main() {
    gl_Position = vec4(position, 1.0);
    pass_TextureCoords = textureCoords;
}

Fragmen shader:

#version 400 core

in vec2 pass_textureCoords;

out vec4 out_Color;

uniform sampler2D textureSampler;

void main() {
    out_Color = texture(textureSampler, pass_textureCoords);
}

Answer:

You need to specify the uniform for textureSampler. Ie,

glUniform1i(textureSamplerHandle, 0);

Which you have retrieved from

textureSamplerHandle = glGetUniformLocation(shaderProgram, "textureSampler");