saegeoff's picture

Texture Issues and Drivers

Hello everyone,

I am somewhat new to textures in OpenTK so I thought I would get some suggestions. The issue that I am having is that on certain computers in the office, my textures simply fail to appear. If we update the drivers on that machine then the issue goes away and the textures appear fine. Quads, Lines, etc all show up fine without updated drivers just not the textures. Can you please take a quick glance at my code to see if there is anything obviously wrong with it? Additionally, would there be any work around for not having to update the drivers? Right now we know how to get everything to work but it would make life easier if the end users of this application didn't have to update from generic Microsoft drivers to proper NVidia, ATI, etc. drivers.

The purpose of this code is to make Text(string) textures that rotate with an underlying model but do not get scaled with that model. This allows the text to always appear front facing and the same size.

Thanks in advance,
saegeoff

private Bitmap GenerateBitmap(string StringText)
{
    Bitmap sizeBmp = new Bitmap(400, 100);
 
    if (m_TextFont == null)
        m_TextFont = new Font(FontFamily.GenericSansSerif, 16);
 
    SolidBrush sldBrush = new SolidBrush(Color.Black);
    PointF drwPt = new PointF(0.0f, 0.0f);
 
    float TextWidth = 0;
    float TextHeight = 0;
 
    using (Graphics gfxSize = Graphics.FromImage(sizeBmp))
    {
        TextWidth = gfxSize.MeasureString(StringText, m_TextFont).Width;
        TextHeight = gfxSize.MeasureString(StringText, m_TextFont).Height;
    }
 
    Bitmap outBmp = new Bitmap((int)Math.Ceiling(TextWidth), (int)Math.Ceiling(TextHeight), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
    using (Graphics gfxReal = Graphics.FromImage(outBmp))
    {
        gfxReal.Clear(Color.Transparent);
        gfxReal.DrawString(StringText, m_TextFont, sldBrush, drwPt);
    }
 
    return outBmp;
}
 
private void CreateTexture()
{
    CleanUpTextureResources();
 
    Bitmap newBmp = GenerateBitmap(m_TextValue);
 
    m_TextureWidth = newBmp.Width;
    m_TextureHeight = newBmp.Height;
 
    m_TextureId = GL.GenTexture();
    GL.BindTexture(TextureTarget.Texture2D, m_TextureId);
 
    System.Drawing.Imaging.BitmapData data = newBmp.LockBits(new Rectangle(0, 0, newBmp.Width, newBmp.Height),
                                            System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, newBmp.Width, newBmp.Height, 0,
        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
 
    newBmp.UnlockBits(data);
    newBmp.Dispose();
 
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
 
    m_TextureCreated = true;
}
 
public override void Draw()
{
    if (!m_TextureCreated)
        CreateTexture();
 
    GL.PushMatrix();
 
    // Translate
    GL.Translate(m_OffsetVector);
 
    // Scale
    double xRef = m_PositionX * m_ScaleVector.X;
    double yRef = m_PositionY * m_ScaleVector.Y;
    double zRef = m_PositionZ * m_ScaleVector.Z;
 
 
    // Rotation
    double xRad = m_xRotateAngle * (Math.PI / 180.0);
    double yRad = m_yRotateAngle * (Math.PI / 180.0);
 
    double xPrime = xRef * Math.Cos(yRad) +
                    zRef * Math.Sin(yRad);
    double yPrime = xRef * Math.Sin(xRad) * Math.Sin(yRad) +
                    yRef * Math.Cos(xRad) -
                    zRef * Math.Sin(xRad) * Math.Cos(yRad
    double zPrime = -xRef * Math.Cos(xRad) * Math.Sin(yRad) +
                    yRef * Math.Sin(xRad) +
                    zRef * Math.Cos(xRad) * Math.Cos(yRad);
 
    xRef = xPrime;
    yRef = yPrime;
    zRef = zPrime;
 
 
    // Determine position of texture
    double xLeft = xRef - ((m_TextureWidth * 0.5) / 2.0);
    double xRight = xRef + ((m_TextureWidth * 0.5) / 2.0);
    double yTop = yRef + (m_TextureHeight * 0.5) + 5.0;
    double yBot = yRef;
 
    // Draw Texture
    GL.BindTexture(TextureTarget.Texture2D, m_TextureId);
 
    GL.Enable(EnableCap.Texture2D);
    GL.Enable(EnableCap.Blend);
    GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
 
    GL.Color3(Color.Transparent);
 
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0f, 0f); GL.Vertex3(xLeft, yTop, zRef);
    GL.TexCoord2(0f, 1f); GL.Vertex3(xLeft, yBot, zRef);
    GL.TexCoord2(1f, 1f); GL.Vertex3(xRight, yBot, zRef);
    GL.TexCoord2(1f, 0f); GL.Vertex3(xRight, yTop, zRef);
    GL.End();
 
    GL.Disable(EnableCap.Blend);
    GL.Disable(EnableCap.Texture2D);
 
    GL.PopMatrix();
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mOfl's picture

There are three possible sources of the error that I can think of right now:
- The texture size. Especially ATI/AMD video cards have had severe problems with handling textures with arbitrary sizes (i.e. everything that is not a power-of-2). For non-power-of-2 textures (which were originally the GL_TEXTURE_2D textures), the texture target GL_TEXTURE_RECTANGLE was introduced, which has several limitations, but was able to handle textures of arbitrary size (limited at a maximum size, of course). So instead of using the TextureTarget.Texture2D in GL.BindTexture, GL.TexImage2D, GL.TexParameter and GL.Enable, you could try TextureTarget.TextureRectangle.
This separation has, however, been overcome and on newer hardware and drivers it should be possible to use Texture2D for all sizes of textures. I'm not sure if the rectangle could lead to a small performance gain (or even drop?), but it is actually not worth using rectangle textures anymore.
- Texturing not enabled. In the CreateTexture function, you do not enable texturing, i.e. GL.Enable(EnableCap.Texture2D), before generating and binding the texture. Do you enable texturing anywhere else [b]before[/b] creating the texture? Maybe texturing is still disabled by default and the old driver does not want to do anything with textures until texturing is enabled.
- Order of texture commands.

GL.BindTexture(TextureTarget.Texture2D, m_TextureId);
 
GL.Enable(EnableCap.Texture2D);

It's the same argument as above, I could think of a stubborn driver not wanting to do anything texture-related without the texturing being enabled, so my advice would be to switch texture binding and the enable call - it also is more intuitive this way, I think.