USSRocker's picture

Fog's bug

Project:The Open Toolkit library
Version:1.0-beta-2
Component:Code
Category:support request
Priority:normal
Assigned:Unassigned
Status:closed
Description

I programed at OpenTK beta 2 and saw a bug with fog. I work on Windows 7 with MS Visual Studio Express Editions (C#). My computer supports OpenGL 3.2.
I made example from NeHe OpenGL tutorials:
Without Fog
When I enable fog I have a bad graphics:
With Fog

My simple code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
 
namespace StarsExample
{
  class Star
  {
    float r, g, b;
    float distantion, angle;
    public float Angle
    {
      get { return angle; }
    }
    public float Distantion
    {
      get { return distantion; }
    }
    public Vector3 Color
    {
      get { return new Vector3(r, g, b); }
    }
    public Star(float dist)
    {
      distantion = dist;
      angle = 0;
      Random random = new Random(GetHashCode());
      r = (float)random.NextDouble();
      g = (float)random.NextDouble();
      b = (float)random.NextDouble();
    }
    public void AddAngle(float add)
    {
      angle += add;
    }
    public void AddDistantion(float add)
    {
      distantion += add;
    }
    public void ChangeColor()
    {
      Random random = new Random(GetHashCode());
      r = (float)random.NextDouble();
      g = (float)random.NextDouble();
      b = (float)random.NextDouble();
    }
  }
  class Game : GameWindow
  {
    int time = 0, numTexture;
    Bitmap texture;
    Vector4 LightAmbient = new Vector4(0.1f, 0.1f, 0.1f, 1.0f);
    Vector4 LightDiffuse = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
    Vector4 LightPosition = new Vector4(0.0f, 0.0f, 5.0f, 1.0f);
    Star[] stars = new Star[50];
    /// <summary>Creates a 800x600 window with the specified title.</summary>
    public Game(OpenTK.Graphics.GraphicsMode gm)
      : base(800, 600, gm, "OpenTK Quick Start Sample", GameWindowFlags.Default, DisplayDevice.Default, 3, 1, OpenTK.Graphics.GraphicsContextFlags.Default)
    {
      VSync = VSyncMode.On;
      time = Environment.TickCount;
    }
    /// <summary>Load resources here.</summary>
    /// <param name="e">Not used.</param>
    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);
 
      Keyboard.KeyDown += new EventHandler<KeyboardKeyEventArgs>(Keyboard_KeyDown);
 
      FirstSets();
      EnableLighting();
      EnableFog();
      EnableBlending();
      SetProjectionMatrix();
      SetModelViewMatrix();
      LoadTexture("star.bmp");
 
      for (int i = 0; i < stars.Length; i++)
        stars[i] = new Star((float)i / (float)stars.Length * 5.0f);
    }
    private void FirstSets()
    {
      GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f);
      GL.ClearDepth(1.0);
      GL.Enable(EnableCap.ColorMaterial);
      GL.Enable(EnableCap.Multisample);
      GL.ShadeModel(ShadingModel.Smooth);
      GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
      GL.Enable(EnableCap.Texture2D);
    }
    private void SetProjectionMatrix()
    {
      GL.MatrixMode(MatrixMode.Projection);
      GL.LoadIdentity();
      Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)Width / Height, 1.0f, 1000.0f);
      GL.LoadMatrix(ref proj);
    }
    private void SetModelViewMatrix()
    {
      Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
      GL.MatrixMode(MatrixMode.Modelview);
      GL.LoadMatrix(ref modelview);
      GL.LoadIdentity();
    }
    private void LoadTexture(string path)
    {
      texture = new Bitmap(path);
      GL.GenTextures(1, out numTexture);
      GL.BindTexture(TextureTarget.Texture2D, numTexture);
      BitmapData data = texture.LockBits(new System.Drawing.Rectangle(0, 0, texture.Width, texture.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
      GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Three, texture.Width, texture.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
      GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
      GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
      GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
      if (texture != null)
        texture.Dispose();
    }
    private void EnableLighting()
    {
      GL.Light(LightName.Light1, LightParameter.Ambient, LightAmbient);
      GL.Light(LightName.Light1, LightParameter.Diffuse, LightDiffuse);
      GL.Light(LightName.Light1, LightParameter.Position, LightPosition);
      GL.Enable(EnableCap.Lighting);
      GL.Enable(EnableCap.Light1);
    }
    private void EnableBlending()
    {
      GL.Color4(1, 1, 1, 0.5f);
      GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One);
      GL.Enable(EnableCap.Blend);
    }
    private void EnableFog()
    {
      GL.Enable(EnableCap.Fog);
      float[] color = { 0.5f, 0.5f, 0.5f, 1.0f };
      GL.Fog(FogParameter.FogMode, 1);
      GL.Fog(FogParameter.FogColor, color);
      GL.Fog(FogParameter.FogDensity, 0.35f);
      GL.Hint(HintTarget.FogHint, HintMode.Nicest);
      GL.Fog(FogParameter.FogStart, 1.0f);
      GL.Fog(FogParameter.FogEnd, 10.0f);
    }
    /// <summary>
    /// Called when your window is resized. Set your viewport here. It is also
    /// a good place to set up your projection matrix (which probably changes
    /// along when the aspect ratio of your window).
    /// </summary>
    /// <param name="e">Not used.</param>
    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);
 
      GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
 
      Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 1000.0f);
      GL.MatrixMode(MatrixMode.Projection);
      GL.LoadIdentity();
      GL.LoadMatrix(ref projection);
      Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
      GL.MatrixMode(MatrixMode.Modelview);
      GL.LoadMatrix(ref modelview);
      GL.LoadIdentity();
    }
    /// <summary>
    /// Called when it is time to setup the next frame. Add you game logic here.
    /// </summary>
    /// <param name="e">Contains timing information for framerate independent logic.</param>
    protected override void OnUpdateFrame(FrameEventArgs e)
    {
      base.OnUpdateFrame(e);
 
      if (Keyboard[Key.Escape])
        Exit();
    }
 
    int allElapsedTime = 0, elapsedTime;
    float depth = -15, tilt = 20, spin = 0;
    /// <summary>
    /// Called when it is time to render the next frame. Add your rendering code here.
    /// </summary>
    /// <param name="e">Contains timing information.</param>
    protected override void OnRenderFrame(FrameEventArgs e)
    {
      base.OnRenderFrame(e);
 
      elapsedTime = Environment.TickCount - time;
      allElapsedTime += elapsedTime;
      float fps = (float)1000 / elapsedTime;
      if (allElapsedTime > 500)
      {
        this.Title = fps.ToString();
        allElapsedTime -= 500;
      }
      time = Environment.TickCount;
 
      GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
      GL.MatrixMode(MatrixMode.Modelview);
      GL.LoadIdentity();
      for (int i = 0; i < stars.Length; i++)
      {
        GL.LoadIdentity();
        GL.Translate(0, 0, depth);
        GL.Rotate(tilt, Vector3.UnitX);
        GL.Rotate(stars[i].Angle, Vector3.UnitY);
        GL.Translate(stars[i].Distantion, 0, 0);
        GL.Rotate(-stars[i].Angle, Vector3.UnitY);
        GL.Rotate(-tilt, Vector3.UnitX);
 
        GL.Color3(stars[stars.Length - 1 - i].Color);
        DrawQuads();
        GL.Rotate(spin, Vector3.UnitZ);
        GL.Color3(stars[i].Color);
        DrawQuads();
        spin += 0.01f;
        stars[i].AddAngle((float)i / stars.Length);
        stars[i].AddDistantion(-0.01f);
        if (stars[i].Distantion < 5.0f)
        {
          stars[i].AddDistantion(5);
          stars[i].ChangeColor();
        }
      }
 
      SwapBuffers();
    }
    void DrawQuads()
    {
      GL.Begin(BeginMode.Quads);
      GL.Normal3(0, 0, 1);
      GL.TexCoord2(0, 0);
      GL.Vertex3(-1, -1, 0);
      GL.TexCoord2(1, 0);
      GL.Vertex3(1, -1, 0);
      GL.TexCoord2(1, 1);
      GL.Vertex3(1, 1, 0);
      GL.TexCoord2(0, 1);
      GL.Vertex3(-1, 1, 0);
      GL.End();
    }
    void Keyboard_KeyDown(object sender, KeyboardKeyEventArgs e)
    {
      if (e.Key == Key.Up)
      {
        depth -= (float)elapsedTime * 0.1f;
      }
      else if (e.Key == Key.Down)
      {
        depth += (float)elapsedTime * 0.1f;
      }
      if (e.Key == Key.W)
      {
        tilt -= 2.5f;
      }
      else if (e.Key == Key.S)
      {
        tilt += 2.5f;
      }
    }
 
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
      // The 'using' idiom guarantees proper resource cleanup.
      // We request 30 UpdateFrame events per second, and unlimited
      // RenderFrame events (as fast as the computer can handle).
      using (Game game = new Game(OpenTK.Graphics.GraphicsMode.Default))
      {
        game.Run(30.0);
      }
 
    }
  }
}

Maybe this methods are obsolete?
For example Glu methods gives bugs to my project, but compiler show me warnings that there are new methods and classes for it.

OpenTK is cool =) I wait for the stable 1.


Comments

Comment viewing options

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

#1

I recall a recent post on gamedev.net that reported problems when using fog + shaders. Are you using shaders? Also what video card are you using?

Some things to try:

  1. Upgrade your video drivers.
  2. Run your project with a debug version of OpenTK.dll (you can find this in the opentk-1.0-beta-2 zip). This dll will throw an exception if it encounters any OpenGL errors, which can help you track down the issue.

These methods are part of OpenGL 1.x and have been deprecated/removed in OpenGL 3.x. However, this only affects you if you wish to write 3.x code (if you wish, you can keep using without issue).

USSRocker's picture

#2

Just it's a simple program and it doesn't use shders.
My vendor: ATI Radeon HD 5770 (support for DX 11.0 & GL 3.2). Of course I got the newest driver from amd site =)

I tried to use debug dll but I didn't see a effect or exceptions =(

Excuse me, but I want to ask about GameWindow constructor.
public GameWindow(int width, int height, GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, GraphicsContextFlags flags);
If I have OpenGL 3.2 runtime dll, but there is "1" at constructor "major" and I call 2.x or 3.x functions, will it work?

the Fiddler's picture

#3

Category:bug report» support request

Ok, just tested this code on my system, and:

GL.Fog(FogParameter.FogMode, 1); // line 142 causes InvalidEnum error
GL.Fog(FogParameter.FogMode, (int)FogMode.Linear); // <- replace with this

This causes InvalidEnum error, because "1" is not a valid value here. According to the documentation, accepted values are are FogMode.Linear, Exp and Exp2.

The debug OpenTK.dll simply catches those errors and converts them to C# exceptions to help you debug the issue (which means that either Ati's drivers failed to raise an error or the debug OpenTK.dll was somehow overwritten by the release version which doesn't throw such exceptions).

To answer your question on OpenGL versions, according to the ARB_create_context specs, what you get is the highest compatible version to the one you specify (default: 1.0). For example, 1.0 will give you 2.1 plus backwards-compatible 3.x functions as extensions. 3.1 + GraphicsContextFlags.ForwardCompatible will give you 3.1 with all deprecated functions removed (using them will result in an OpenGL error).

Finally, the issue you are seeing cannot be caused by OpenTK itself. (OpenTK is simply a bridge between .Net and OpenGL and doesn't modify your data in any way. Incorrect/corrupt rendering usually indicates a driver or user error).

USSRocker's picture

#4

Thank you, but replacing strings doesn't help.
I try to solve this problem myself.

the Fiddler's picture

#5

If you have access to a different machine, it's worth testing your program there. (This will tell you whether you have hit a driver bug).

If you don't have a second machine, you can try with Mesa3d (a software renderer for OpenGL, easy to compile with Visual C++) or even a Virtual Machine (I keep a couple of Linux VMs in VirtualBox for testing stuff like this).

USSRocker's picture

#6

I tested my program and understood that fog works with it rightly but it gives this results because it's just stupid fog's and alpha-blending's influence together =))

the Fiddler's picture

#7

Status:open» closed

Interesting, it's been many years since I last used the fixed-function pipeline. This should be simple to solve using shaders, if you are willing to drop support for older hardware.