Profet
Profet

Reputation: 942

GLSL change uniform texture for each object

I'm currently trying to draw simple meshes using different textures (using C# and OpenTK). I read a lot about TextureUnit and bindings, and that's my current implementation (not working as expected) :

private void ApplyOpaquePass()
{
    GL.UseProgram(this.shaderProgram);
    GL.CullFace(CullFaceMode.Back);

    while (this.opaqueNodes.Count > 0)
        Draw(this.opaqueNodes.Pop());

    GL.UseProgram(0);
}

And my draw method :

private void Draw(Assets.Model.Geoset geoset)
{
    GL.ActiveTexture(TextureUnit.Texture1);
    GL.BindTexture(TextureTarget.Texture2D, geoset.TextureId /*buffer id returned by GL.GenTextures*/ );
    GL.Uniform1(GL.GetUniformLocation(this.shaderProgram, "Texture1"), 1 /*see note below*/ );

    //Note: if I'm correct, it should be 1 when using TextureUnit.Texture1
    //      (2 for Texture2...), note that doesn't seem to work since no
    //      texture texture at all is sent to the shader, however a texture
    //      is shown when specifying any other number (0, 2, 3...)

    // Draw vertices & indices buffers...
}

And my shader code (that shouldn't be the problem since uv mapping is ok):

uniform sampler2D Texture1;

void main(void)
{
    gl_FragColor = texture2D(Texture1, gl_TexCoord[0].st);
}


What's the problem :


Ideas :



Thanks in advance for your answers :)

Regards,
Bruce

EDIT: that's how I generate textures in the renderer:

override public uint GenTexture(Bitmap bmp)
{
    uint texture;
    GL.GenTextures(1, out texture);

        //I disabled this line because I now bind the texture before drawing a geoset
        //Anyway, uncommenting this line doesn't show a better result
        //GL.BindTexture(TextureTarget.Texture2D, texture);

    System.Drawing.Imaging.BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
    bmp.UnlockBits(data);

    //temp settings
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

    return texture;
}

Upvotes: 1

Views: 5230

Answers (2)

Profet
Profet

Reputation: 942

I finally solved my problem ! All the answers perfected my understanding and lead me to the solution which lied on two major problems:

1) as Calvin1602 said, this is very important to bind a newly created texture before calling glTexImage2d.

2) also UncleZeiv rose my attention about the last GL.Uniform1's parameter. The OpenTK tutorial is very misleading because the guy pass the id of the texture object to the function, that happens to work here because the order of generation of the texture exactly matches the id of used TextureUnit. As I was unsure that my comprehension was exact, I wrongly changed this parameter back to the geoset.TextureId.

Thanks !

Upvotes: 2

Mikola
Mikola

Reputation: 9326

You don't need multiple shader programs if the only thing you are changing is the texture. Also uniform locations are constant throughout the lifetime of a shader program, so there is no need to retrieve those each frame. However, you do need to rebind the texture each time you change it, and you will need to bind each distinct texture to a separate texture ID.

As a result, I would conclude that what you posted ought to work and so the problem is likely somewhere else in your code.

EDIT: After the updated version it should still work. However I am concerned about why the following line is commented out:

 //GL.BindTexture(TextureTarget.Texture2D, texture);

This should be in there. Otherwise you will keep over writing the same texture (which is ridiculous). You need to bind the texture before you initialize. Now it is entirely conceivable that something else is broken, but given what I see now this is the only error that jumps out at me.

Upvotes: 0

Related Questions