nlraley's picture

Polygon and blend function affecting other loaded textures...

Okay, I finally have my polygon being rendered the correct color and everything, so I was taking the next step towards achieving my end goal.

What I am attempting to do is draw a polygon, have it filled and semi transparent with a non transparent border.

I have the rectangle drawing correctly, but when I have the polygon being drawn in this manner, the transparency is being applied to all of the other textures that are loaded in my background. What am I doing wrong?

Here's my code:

List<Pixels> tempPoints = new List<Pixels>();
tempPoints.Add(new Pixels(300, 50));
tempPoints.Add(new Pixels(200, 200));
tempPoints.Add(new Pixels(250, 150));
tempPoints.Add(new Pixels(100, 100));
 
reference = tempPoints[0];
tempPoints.Sort(new Comparison<Pixels>(MapUtils.SortXYPointsClockwise));
 
//  Fetch the map bounds
MapUtils.GetMapBounds(ref mapBounds, Program.main.glControl1.Width, Program.main.glControl1.Height);
 
//  Clear the OpenGL control
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
//  Enable 2D texturing
GL.Enable(EnableCap.Texture2D);            
 
//  Set the hint
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
 
//  Fetch displayed tiles
MapUtils.FetchTiles();
 
//  Enable 2D blending
GL.Enable(EnableCap.Blend);
 
//  Enable anti aliasing
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.PolygonSmooth);
 
//  Draw Rectangle
GL.MatrixMode(MatrixMode.Modelview);
 
//  Set the polygon color
GL.Color4(0.0, 0.0, 1.0, 0.7);
//  Set the blend function
GL.BlendFunc(BlendingFactorSrc.OneMinusConstantAlpha, BlendingFactorDest.SrcAlpha);
 
//  Set the polygon mode for the fill
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
//  Draw the filled polygon
GL.Begin(BeginMode.Polygon);
foreach (Pixels point in tempPoints)
{
	GL.Vertex3(point.X, point.Y, 0);
}
GL.End();
 
////  Set the polygon color
GL.Color4(0.0, 0.0, 1.0, 1.0);
//  Set the blend function
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
 
//  Set the polygon mode for the outline
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
//  Draw the polygon outline
GL.Begin(BeginMode.Polygon);
foreach (Pixels point in tempPoints)
{
    GL.Vertex3(point.X, point.Y, 0);
}
GL.End();            
 
//  Reset the color back to white
GL.Color4(1.0, 1.0, 1.0, 1.0);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
 
GL.Disable(EnableCap.Blend);
 
//  Flush the buffer
GL.Flush();
//  Swap the buffers
glControl1.SwapBuffers();

The code above works with filling the poly with a semi transparent blue and a non transparent blue outline, but all of my textures in the background are semi transparent.

If I change the face value of the polygon then it won't draw the outline.

As you can see, I've attempted to reset the color and the blend function so the textures and everything else are not affected by the transparency, but nothing seems to work.

Any ideas?


Comments

Comment viewing options

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

Blending is a rendering state, i.e. it only affects what you render on screen, not what you load from disk.

When rendering translucent objects, enable blending. When rendering opaque objects, disable blending. (Optional: sort into two distinct groups for better performance). Make sure you draw back-to-front for blending to work correctly.

That's all there is to it!

In your code above, the call to GL.Disable(EnableCap.Blending) won't actually have any visible effect, since you re-enable blending just before you render everything (unless you have other rendering code that you have not shown).

Edit: a screenshot might help understand what is going on here.

nlraley's picture

The MapUtils.FetchTextures call renders the background tiles which the blending for the polygon is affecting.

Here is the background texture without drawing the blended poly:

Here is the render after rendering the blended poly:

As you can see, it completely messes with the rendering of the background textures.

darkprinze's picture

Sorry to open the old thread, but i am facing the same issue. How to fix this issue?

winterhell's picture

Have you narrowed down the code that messes up with the opaque textures?
Is it just GL.Enable(EnableCap.Blend); ?
After you are done with drawing the transparent objects try to reverse all relevant functions, for example GL.Disable(EnableCap.Blend);

darkprinze's picture

I didn't use GL.Enable(EnableCap.Blend) function. I just changed the the PolygonMode.Line to enable the wire frame. After changing mode, it hides the background texture. Here is the code in GLPaint event

// set background texture
 GL.Clear(ClearBufferMask.ColorBufferBit);
            GL.Disable(EnableCap.DepthTest);
            btexture = (int)LoadTexture(@"C:\Users\...\Downloads\Work\...\Files\bg.jpg");
            GL.BindTexture(TextureTarget.Texture2D, btexture);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
            GL.Ortho(0, 1, 1, 0, -1, 1);
            GL.DepthMask(false);
             if (isWireframe)
            {
                GL.PolygonMode(OpenTK.Graphics.OpenGL.MaterialFace.FrontAndBack, OpenTK.Graphics.OpenGL.PolygonMode.Line);
            }
            GL.Begin(PrimitiveType.Quads);
            {
                GL.TexCoord2(0f, 0f);
                GL.Vertex2(0, 0);
                GL.TexCoord2(0f, 1f);
                GL.Vertex2(0, 1f);
                GL.TexCoord2(1f, 1f);
                GL.Vertex2(1f, 1f);
                GL.TexCoord2(1f, 0f);
                GL.Vertex2(1f, 0);
            }
            GL.End();
            // background texture ends
 
            GL.DepthMask(true);            
            GL.Enable(EnableCap.DepthTest);         
            GL.Clear(ClearBufferMask.DepthBufferBit);            
            texture = (int)LoadTexture(@"C:\Users\..\Downloads\Work\..\Files\white.jpg");
            GL.BindTexture(TextureTarget.Texture2D, texture);
            GL.LoadIdentity();
            GL.PushMatrix();
 
            UpdateCamera();
 
            GL.Begin(PrimitiveType.Triangles);
            int j = 0;
            for (int i = 0; i < stl.Facets.Count; i++)
            {
                GL.Normal3(new Vector3d(stl.Facets[i].Normal.X, stl.Facets[i].Normal.Y, stl.Facets[i].Normal.Z));
                GL.TexCoord2(0, 0);
                GL.Vertex3(new Vector3d(stl.Facets[i].Vertices[0].X, stl.Facets[i].Vertices[0].Y, stl.Facets[i].Vertices[0].Z));
                GL.TexCoord2(0, 1);
                GL.Vertex3(new Vector3d(stl.Facets[i].Vertices[1].X, stl.Facets[i].Vertices[1].Y, stl.Facets[i].Vertices[1].Z));
                GL.TexCoord2(1, 0);
                GL.Vertex3(new Vector3d(stl.Facets[i].Vertices[2].X, stl.Facets[i].Vertices[2].Y, stl.Facets[i].Vertices[2].Z));
            }
 
            GL.PopMatrix();
            GL.End(); 
 if (isWireframe)
            {
                GL.PolygonMode(OpenTK.Graphics.OpenGL.MaterialFace.FrontAndBack, OpenTK.Graphics.OpenGL.PolygonMode.Fill);
            }

In button event, i am changing the mode

isWireframe = true;
//GL.PolygonMode(OpenTK.Graphics.OpenGL.MaterialFace.FrontAndBack, OpenTK.Graphics.OpenGL.PolygonMode.Line);                    
glControl.Invalidate();

If i change the mode to Fill then background texture appears.

winterhell's picture

From what I understand, you want to see the wireframe on top of the regular textures.
If so, in the button event you'll have

/*bool member*/ isWireframe=!isWireframe;
glControl.Invalidate();

And in your drawing code

....
 
GL.Begin(PrimitiveType.Quads)
....
GL.Begin(PrimitiveType.Triangles)
...
GL.End();
If(isWireframe)
{//same rendering code as above, it could as well be in another function to avoid code duplication
GL.PolygonMode(OpenTK.Graphics.OpenGL.MaterialFace.FrontAndBack, OpenTK.Graphics.OpenGL.PolygonMode.Line);
GL.Begin(PrimitiveType.Quads)
....
GL.Begin(PrimitiveType.Triangles)
...
GL.End();
GL.PolygonMode(OpenTK.Graphics.OpenGL.MaterialFace.FrontAndBack, OpenTK.Graphics.OpenGL.PolygonMode.Fill);
}

Alternatively you can render the lines as GL.Begin(PrimitiveType.Lines); That'd require like 6 points per triangle as opposed to 3.
If I remember correctly, in Direct3D directly drawing lines was much faster than the forced wireframe mode.

darkprinze's picture

Thanks for your quick reply . I made changes as you mentioned, and it still don't show the background texture.
I updated my code in above post.