0
\$\begingroup\$

I am learning opengl and tried to add texture to a rectangle using shaders but unfortunately my rectangle is not displaying at correct location and changing the coordinate of the rectangle does not seem to change it's position but rather changes the size of texture applied. I'm using opengl 2.1. And here are my codes and screenshot of my problem.

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;

import RenderEngine.Window;

public class Test {

    private int vertexShaderID;
    private int fragmentShaderID;
    private int programID;

    public static void main(String[] args) {
        new Test().run();
    } 

    public void run() {
        Window.CreateWindow();

        float[] vertices = { 
                -0.5f, 0.5f, 0f,
                -0.5f, -0.5f, 0f,
                0.5f, -0.5f, 0f,
                0.5f, 0.5f, 0f 
        };

        float[] texCoords = { 
                0f, 0f,
                0f, 1f,
                1f, 1f,
                1f, 0f 
        };

        short[] indices = { 0, 1, 2, 2, 3, 0 };

        int tex = loadTexture("res/image.png");

        int v_id = bindArrayBuffer(vertices);
        int t_id = bindArrayBuffer(texCoords);
        int i_id = bindIndices(indices);

        initShader();

        while(!Window.isCloseRequested()){
            Window.PollEvents();
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);

            GL20.glUseProgram(programID);

            GL13.glActiveTexture(GL13.GL_TEXTURE0);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex);

            int loc = GL20.glGetUniformLocation(programID, "samplr");
            if (loc != -1){
                GL20.glUniform1i(loc, 0);
            }

            GL20.glEnableVertexAttribArray(0);
            GL20.glEnableVertexAttribArray(1);

            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, v_id);
            GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

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

            GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, i_id);

            GL11.glDrawElements(GL11.GL_TRIANGLES, indices.length, GL11.GL_UNSIGNED_SHORT, 0);

            GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

            GL20.glDisableVertexAttribArray(1);
            GL20.glDisableVertexAttribArray(0);

            GL20.glUseProgram(0);

            Window.UpdateWindow();
        }

        GL20.glDetachShader(programID, vertexShaderID);
        GL20.glDetachShader(programID, fragmentShaderID);
        GL20.glDeleteShader(vertexShaderID);
        GL20.glDeleteShader(fragmentShaderID);
        GL20.glDeleteProgram(programID);

        Window.CloseWindow();
    }

    public void initShader(){
        vertexShaderID = loadShader("src/shaders/vertexShader.glsl", GL20.GL_VERTEX_SHADER);
        fragmentShaderID = loadShader("src/shaders/fragmentShader.glsl", GL20.GL_FRAGMENT_SHADER);
        programID = GL20.glCreateProgram();
        GL20.glAttachShader(programID, vertexShaderID);
        GL20.glAttachShader(programID, fragmentShaderID);
        GL20.glLinkProgram(programID);
        GL20.glValidateProgram(programID);
        GL20.glBindAttribLocation(programID, 0, "position");
        GL20.glBindAttribLocation(programID, 1, "textures");
    }

    private int bindArrayBuffer(float[] vertices) {
        int b_id = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, b_id);
        FloatBuffer buffer = toFloatBuffer(vertices);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        return b_id;
    }

    private int bindIndices(short[] indices) {
        int b_id = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, b_id);
        ShortBuffer buffer = toShortBuffer(indices);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        return b_id;
    }

    private static ShortBuffer toShortBuffer(short[] data) {
        ShortBuffer buffer = BufferUtils.createShortBuffer(data.length);
        buffer.put(data);
        buffer.flip();
        return buffer;
    }

    private static FloatBuffer toFloatBuffer(float[] data) {
        FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
        buffer.put(data);
        buffer.flip();
        return buffer;
    }

    public int loadTexture(String fileName){
        BufferedImage bi;
        try {
            bi = ImageIO.read(new File(fileName));
            int width = bi.getWidth();
            int height = bi.getHeight();

            int[] pixel_raw = new int[width * height * 4];
            pixel_raw = bi.getRGB(0, 0, width, height, null, 0, width);

            ByteBuffer pixels = BufferUtils.createByteBuffer(width * height * 4);

            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++){
                    // 0xAARRGGBB
                    int pixel = pixel_raw[i * width + j];
                    pixels.put((byte) ((pixel >> 16 ) & 0xFF)); // RED
                    pixels.put((byte) ((pixel >> 8) & 0xFF));   // GREEN
                    pixels.put((byte) ((pixel) & 0xFF));    // BLUE
                    pixels.put((byte) ((pixel >> 24) & 0xFF));  // ALPHA
                }
            }

            pixels.flip();

            int id = GL11.glGenTextures();

            GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixels);

            return id;
        } catch (IOException e) {
            System.err.println("Could not load texture: " + fileName);
            e.printStackTrace();
            System.exit(-1);
        }

        return -1;
    }

    public int loadShader(String file, int type) {
        StringBuilder shaderSource = new StringBuilder();

        try {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String line;
            while ((line = reader.readLine()) != null) {
                shaderSource.append(line).append('\n');
            }
            reader.close();
        } catch (IOException e) {
            System.out.println(String.format("Could not read file %s:", file));
            e.printStackTrace();
            System.exit(-1);
        }

        int shaderID = GL20.glCreateShader(type);
        GL20.glShaderSource(shaderID, shaderSource);
        GL20.glCompileShader(shaderID);
        if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
            System.out.println(GL20.glGetShaderInfoLog(shaderID));
            System.err.println("Could not compile shader!");
            System.exit(-1);
        }
        return shaderID;
    }

}

Vertex Shader

#version 120

attribute vec3 position;
attribute vec2 textures;

varying vec2 tex_coord;

void main()
{
    tex_coord = textures;
    gl_Position = vec4(position, 1);
}

Fragment Shader

#version 120

uniform sampler2D samplr;

varying vec2 tex_coord;

void main()
{
    gl_FragColor = texture2D(samplr, tex_coord);
}

Output

output with half size

When I change my vertices to:

    float[] vertices = { 
        -1f, 1f, 0f,
        -1f, -1f, 0f,
        1f, -1f, 0f,
        1f, 1f, 0f 
    };

output with full size

Without Texture

output without texture

Problem : For some reason texCoords is acting as position and vertices is acting as textures in shaders.

Fix Apparently adding the vertex buffer to attrib index 1 fixes the problem.

GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, t_id);
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);

GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, v_id);
GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0);

Even though position is binded to attrib location 0.

GL20.glBindAttribLocation(programID, 0, "position");
GL20.glBindAttribLocation(programID, 1, "textures");

Can anyone explain this?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

After calling glBindAttribLocation you need to link your program again: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindAttribLocation.xhtml

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .