0
votes

I can't bind my texture to the sampler2D in the fragment shader. In theory my program should draw the whole scene in one color (My image is a red, 64x64 large square). When using textureSize to get the sampler2D's dimensions, it return 1x1.

Neither the TextureID or the SamplerLocation return -1

What I am doing at the moment:

  1. Load the image into the gpu memory and get the Location (int TextureID) with loadImage().
  2. Get the UniformLocation of my sampler2D (int SamplerLocation)
  3. In the render method: Bind the texture and set the uniform location accordingly

SourceCode:

loadImage Method copied from http://neokabuto.blogspot.de/

    int loadImage(Bitmap image)
    {
        int texID = GL.GenTexture();

        GL.BindTexture(TextureTarget.Texture2D, texID);
        BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
            OpenTK.Graphics.OpenGL4.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

        image.UnlockBits(data);

        GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

        return texID;
    }

OnLoad Method called once on startup

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        int status_code;
        string info;

        Console.Out.WriteLine(GL.GetString(StringName.Version));

        m.loadFromOBJ("C:/Users/Anwender/Downloads/lpm_yard.obj");
        m.init();

        TextureID = loadImage("C:/Users/Anwender/Desktop/test.png");

        // Setup openGL
        GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        GL.Enable(EnableCap.DepthTest);
        GL.DepthFunc(DepthFunction.Lequal);

        // Create MVP-Matrices and Camera Data
        ProjectionMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Width / (float)Height, 0.5f, 10000.0f);
        WorldMatrix = new Matrix4();
        ModelviewMatrix = new Matrix4();
        CameraPosition = new Vector3(0.5f, 0.5f, 0);

        defaultPickSSB = new PickSSB();
        defaultPickSSB.DepthValue = float.MaxValue;
        defaultPickSSB.PickIndex = -1;

        string VertexSource = File.ReadAllText("C:/Users/Anwender/Source/Repos/ShaderDemo/ShaderDemo/Shader/vs.glsl");
        string FragmentSource = File.ReadAllText("C:/Users/Anwender/Source/Repos/ShaderDemo/ShaderDemo/Shader/fr.glsl");

        // Create Shaders
        int VertexID = GL.CreateShader(ShaderType.VertexShader);
        int FragmentID = GL.CreateShader(ShaderType.FragmentShader);

        // Compile vertex shader
        GL.ShaderSource(VertexID, VertexSource);
        GL.CompileShader(VertexID);
        GL.GetShaderInfoLog(VertexID, out info);
        GL.GetShader(VertexID, ShaderParameter.CompileStatus, out status_code);

        if (status_code != 1)
            throw new ApplicationException(info);

        // Compile fragment shader
        GL.ShaderSource(FragmentID, FragmentSource);
        GL.CompileShader(FragmentID);
        GL.GetShaderInfoLog(FragmentID, out info);
        GL.GetShader(FragmentID, ShaderParameter.CompileStatus, out status_code);

        if (status_code != 1)
            throw new ApplicationException(info);

        // Create and Link Program
        Program = GL.CreateProgram();
        GL.AttachShader(Program, FragmentID);
        GL.AttachShader(Program, VertexID);

        GL.BindFragDataLocation(Program, 0, "color");

        GL.LinkProgram(Program);

        GL.UseProgram(Program);

        // Get Buffer Locations
        PickColorLocation = GL.GetAttribLocation(Program, "vertex_pick_index");
        PositionLocation = GL.GetAttribLocation(Program, "vertex_position");
        NormalLocation = GL.GetAttribLocation(Program, "vertex_normal");
        ColorLocation = GL.GetAttribLocation(Program, "vertex_color");
        UniformMVPMatrixLocation = GL.GetUniformLocation(Program, "mvp_matrix");
        UniformMouseXLocation = GL.GetUniformLocation(Program, "mouse_x");
        UniformMouseYLocation = GL.GetUniformLocation(Program, "mouse_y");
        SamplerLocation = GL.GetUniformLocation(Program, "main_texture");


        GL.GenBuffers(1, out SSB);
        GL.BindBuffer(BufferTarget.ShaderStorageBuffer, SSB);
        GL.BufferData(BufferTarget.ShaderStorageBuffer, (IntPtr)(4 * sizeof(float)), ref defaultPickSSB, BufferUsageHint.DynamicCopy);
        GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 0, SSB);

        GL.UseProgram(0);
    }

OnRenderFrame Method

    protected override void OnRenderFrame(FrameEventArgs e)
    {
        base.OnRenderFrame(e);

        GL.Viewport(0, 0, Width, Height);
        GL.ClearColor(0.0f, 0.8f, 0.8f, 1.0f);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

        GL.UseProgram(Program);

        GL.BindTexture(TextureTarget.Texture2D, TextureID);
        GL.Uniform1(SamplerLocation, TextureID);

        m.draw(PositionLocation, NormalLocation, ColorLocation, PickColorLocation);

        GL.UseProgram(0);

        SwapBuffers();
    }

My fragment shader:

#version 430
in vec4 frag_color;
in vec4 gl_FragCoord;
flat in int frag_pick_index;

out vec4 color;

layout (std430, binding = 0) buffer mouse_color { int pick_index; float depth_value; };

uniform int mouse_x;
uniform int mouse_y;
uniform sampler2D main_texture;

void main(void)
{       
    if (int(gl_FragCoord.x) == mouse_x && int(gl_FragCoord.y) == mouse_y) {
        if (gl_FragCoord.z < depth_value) 
        {
            pick_index = frag_pick_index;
            depth_value = gl_FragCoord.z;
        }
    }

    // pick_index = textureSize(main_texture, 0).y;

    if (int(gl_FragCoord.x) == mouse_x || int(gl_FragCoord.y) == mouse_y) {
        color = vec4(0.0f, 1,0,1.0f);
    } else {
        color = frag_color;
    }

    color = texture(main_texture, vec2(0.5f, 0.5f));
}
1

1 Answers

1
votes

The integer you pass to the sampler has to be the index of the texture unit the texture is bound to, not the texture id. Unless you called GL.ActiveTexture somewhere, the active texture unit is TextureUnit.Texture0, which means you have to pass 0 to GL.Uniform1:

GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.Uniform1(SamplerLocation, 0);