I want to render a 3D scene whit some transparent objects in it,
This is an example of my output (I am using opentk in c#)
But the transparency is not working as i desired, I need something like this:
Here is my settings in code:
// before draw transparent object
GL.Enable(EnableCap.Blend);
// after draw transparent object
GL.Disable(EnableCap.Blend);
// # GLInit
GL.ClearColor(0.5f, 0.5f, 1f, 1f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
GL.ClearDepth(1);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
//GL.Enable(EnableCap.PolygonOffsetFill);
GL.PolygonOffset(0.01f, 0.01f);
GL.Enable(EnableCap.StencilTest);
GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Replace);
try
{
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.DstAlpha);
GL.BlendEquation(BlendEquationMode.FuncAdd);
//Gl.BlendEquation(BlendEquationMode.FuncAddExt);
}
catch { }
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.PointSmooth);
GL.Enable(EnableCap.PolygonSmooth);
GL.Disable(EnableCap.Dither);
GL.ShadeModel(ShadingModel.Smooth);
GL.Disable(EnableCap.Multisample);
GL.LineWidth(0.5f);
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.PolygonSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.FragmentShaderDerivativeHint, HintMode.Nicest);
I removed these two lines in GlInit() method
//GL.Enable(EnableCap.PointSmooth);
//GL.Enable(EnableCap.PolygonSmooth);
and now I have this
Related
I'm learning about OpenGL and I use C# for it.
I want to have a red cone and an opportunity to change its transparency.
This is what I do:
Gl.glColor4f(255, 0, 0, alpha);
Glut.glutSolidCone(cone.Radius, cone.Height, cone.Slices, cone.Stacks);
As a result I get something like this:
So it really is a cone but the color is just white (alpha = 1 when ran).
How to achieve the red color with an ability to make it transparent?
Thank you for your replies!
Finally, got a solution:
Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
Gl.glEnable(Gl.GL_COLOR_MATERIAL);
Gl.glColor4f(1.0f, 0, 0, alpha);
Glut.glutSolidCone(cone.Radius, cone.Height, cone.Slices, cone.Stacks);
So I have a Scroll Bar to change alpha parameter and the cone does change its transparency.
I hope this answer helps also.
The main render class, sets up the camera view and renders all the lights, and then renders all the objects in the scene:
public void RenderOnView(GLControl control)
{
control.MakeCurrent();
var camera = views[control];
GL.Clear(ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
GL.Disable(EnableCap.CullFace);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
camera.LookThrough();
if (EnableLights)
{
GL.LightModel(LightModelParameter.LightModelAmbient, new[] { 0.2f, 0.2f, 0.2f, 1f });
GL.LightModel(LightModelParameter.LightModelLocalViewer, 1);
GL.Enable(EnableCap.Lighting);
foreach (var light in lights)
{
light.Render();
}
}
else
{
GL.Disable(EnableCap.Lighting);
GL.ShadeModel(ShadingModel.Flat);
}
GL.Enable(EnableCap.LineSmooth); // This is Optional
GL.Enable(EnableCap.Normalize); // These is critical to have
GL.Enable(EnableCap.RescaleNormal);
for (int i = 0; i<objects.Count; i++)
{
GL.PushMatrix();
objects[i].Render();
GL.PopMatrix();
}
control.SwapBuffers();
}
So I am doing an oil pipeline simulation project which has three windows; the stats window (for pipeline details), the simulation window (for details about how the pipeline will work and the middle window- the 2D simulation of the oil pipeline.
The 2D simulation is in fact, there for aesthetic purposes- the main nitty-gritty is done within the Maths.cs class that I have already programmed. So my question is this:
Using shapes in the OpenTK library, all I can seem to build is triangles. I've inserted the code used to build the triangle but otherwise there seems to be no other shapes. Is there any way I can draw a 1) Circle, 2) Rectangle and 3) Line?
Also, what does the 'BeginMode' class do? I feel this would crack the problem, by using something other than BeginMode I can access other shapes through a different class??
Thanks :-)
private void viewportGL_Paint(object sender, PaintEventArgs e)
{
if (!loaded)
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Translate(x, 0, 0);
GL.Color3(Color.Aqua);
GL.Begin(BeginMode.Triangles);
GL.Vertex2(10, 20);
GL.Vertex2(100, 20);
GL.Vertex2(100, 50);
GL.End();
viewportGL.SwapBuffers();
}
int x = 0;
private void viewportGL_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
x+=4;
viewportGL.Invalidate();
}
So i will now extend to an answer:
float step = (float) Math.PI/10;
GL.Color3(Color.Aqua);
GL.Begin(BeginMode.Triangles);
for (float angle = 0.0f; angle < Math.PI*2 - 0.001f; angle += step) {
GL.Vertex2(0.0f, 0.0f);
GL.Vertex2(Math.Cos(angle), Math.Sin(angle));
GL.Vertex2(Math.Cos(angle - step), Math.Sin(angle - step));
}
GL.End();
BeginMode is an Enum and it basically tells OpenGL about the input primitive type. I think PrimitiveType does the same thing but one could argue that its meaning is more intuitive. For a rectangle you could write:
GL.Begin(PrimitiveType.Quads);
GL.Vertex2(-0.5f, -0.5f);
GL.Vertex2( 0.5f, -0.5f);
GL.Vertex2( 0.5f, 0.5f);
GL.Vertex2(-0.5f, 0.5f);
GL.End();
By the way you may want to take a look at The OpenTK Manual:
http://www.opentk.com/doc/graphics
I have my rendering engine more or less figured out. But I need to add functionality to render a 3d object that's pinned next to the camera (like holding a gun in an fps).
I tried first doing it by doing a lot of angle calculations and placing the object (in this case a cube) in the world at the coordinates where the camera would be looking at. This did not work out as I expected it to.
Then I searched on the web and people recommend drawing the object before applying the camera matrix. I've been trying to do this but with no success. The object doesn't appear at all.
The exact code segment is as follows:
camera_matrix = camera.Matrix;
GL.ClearColor(Color.White);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadMatrix(ref camera_matrix);
foreach (var obj in farobjects)
{
GL.PushMatrix();
GL.Translate(obj.Location);
obj.Render(camera);
GL.PopMatrix();
}
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
foreach (var obj in nearobjects)
{
GL.PushMatrix();
GL.LoadIdentity();
GL.Translate(obj.Location);
obj.Render(camera);
GL.PopMatrix();
}
Any ideas on what I'm doing wrong? The object I placed does not appear at all. I tried moving it to (1,0,1), (0,0,1) and (1,0,0) and the object is nowhere to be found.
I finally found the solution. I had to create a second camera matrix for this and apply it, as well as flush the z buffer.
camera_matrix = camera.Matrix;
GL.ClearColor(Color.White);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadMatrix(ref camera_matrix);
foreach (var obj in farobjects)
{
GL.PushMatrix();
GL.Translate(obj.Location);
obj.Render(camera);
GL.PopMatrix();
}
GL.PopMatrix();
GL.Clear(ClearBufferMask.DepthBufferBit);
GL.PushMatrix();
Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
GL.LoadMatrix(ref modelview);
foreach (var obj in nearobjects)
{
GL.PushMatrix();
GL.Translate(obj.Location);
obj.Render(camera);
GL.PopMatrix();
}
GL.PopMatrix();
I am working on a 2D menu for a game using OpenTK in C#.
At the moment, the menu is separated in 3 different texture quads, or 'layers', which looks like this.
Layer 1: The base appearance of the buttons.
Layer 2: The appearance of the 'continue' button when the mouse hovers over it.
Layer 3: A 'gear' which holds the buttons, as well as their text/name.
Each of these layers consists of a semi-transparent (32-bit .png) texture bound to a Quad.
When drawing only layers 1 & 3, the textures seem to work properly, but when I want to show Layer 2 as well, layer 3 disappears from my screen, as seen here. In this image, only my base buttons (layer 1) and highlighted 'continue' button (layer 2) are drawn.
I believe this is an issue with my blend function, and the fact that I am drawing more than 2 sprites. I am relatively new to OpenTK/OpenGL, and I was hoping someone here could help me fix this problem. I will add some of my code below:
When the game starts, I set up some GL properties:
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.Blend); //I migh t be missing something here, like textEnv?
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
This part of the code draws my 2D elements. I took it from a tutorial on OpenTK.
public void DrawHUD()
{
// Clear only the depth buffer, so that everything
// we draw for the HUD will appear in front of the
// world objects.
GL.Clear(ClearBufferMask.DepthBufferBit);
// Reset the ModelView matrix so the following
// objects are not affected by the camera position
GL.LoadIdentity();
////draw 3d hud elements (weapon in the main game)
// Disable lighting for the HUD graphics
// GL.Disable(EnableCap.Lighting);
// Save the current perspective projection
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
// Switch to orthogonal view
GL.LoadIdentity();
GL.Ortho(0, Width, 0, Height, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
// Go back to working with the ModelView
GL.MatrixMode(MatrixMode.Modelview);
//// Draw the HUD elements
GameEngine.Draw2D();
// Switch back to perspective view
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
// Turn lighting back on
// GL.Enable(EnableCap.Lighting);
}
I add the menu 'layers' to an arraylist, which I then use to draw using Graphic, a class which holds the position/texture info of my 'layer'
public virtual void Draw2D()
{
Vector2 pos;
int Z = 0; //to fight z-fighting? this fixed an issue where drawing a 2nd sprite would also make the 1st one dissapear partially
foreach (Graphic G in _2DList)
{
if (G.visible())
{
pos = G.position();
Renderer.DrawHUDSprite(pos.X, pos.Y, Z, G.W(), G.H(), G.Texture());
Z++;
}
}
}
Finally, my draw function for hudsprites looks like this:
public static void DrawHUDSprite(float x, float y, float z, float width, float height, int textID)
{
// Save the ModelView matrix
GL.PushMatrix();
// Move to the correct location on screen
GL.Translate(x, y, z);
GL.BindTexture(TextureTarget.Texture2D, textID);
// Setup for drawing the texture
GL.Color3(Color.White);
// Draw a flat rectangle
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(0, 0, 0);
GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(width, 0, 0);
GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(width, height, 0);
GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(0, height, 0);
GL.End();
// Restore the ModelView matrix
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.PopMatrix();
}
If this has anything to do with the way I load my textures, I will add the code for this as well.
I managed to solve my issue on my own: The problem lies with my draw2D() function, where I use a Z coordinate to prevent clipping issues. The Z-coordinate when drawing in 2D could only be in the range of [0..1].
My earlier solution which increments Z by 1 (Z++) would cause issues with more than 2 textures/Graphics (Z>1, meaning the quad is not displayed). The fixed version looks like this:
public virtual void Draw2D()
{
if (_2DList.Count > 0) { //pervents dividing by 0, and skips memory allocation if we have no Graphics
Vector2 pos;
float Z = 0; //to fight z-fighting, the sprites ar drawn in the order they were added.
float step = 1.0f / _2DList.Count; //limiting the Z between [0..1]
foreach (Graphic G in _2DList)
{
if (G.visible())
{
pos = G.position();
Renderer.DrawHUDSprite(pos.X, pos.Y, Z, G.W(), G.H(), G.Texture());
Z += step; //with z starting at 0, it will never be 1.
}
}
}
}
I'm using OpenTK and C#, I have defined a plane in 3D space as follows:
GL.Begin(BeginMode.Quads);
GL.Color3(Color.Magenta);
GL.Vertex3(-100.0f, -25.0f, -150.0f);
GL.Vertex3(-100.0f, -25.0f, 150.0f);
GL.Vertex3( 200.0f, -25.0f, 100.0f);
GL.Vertex3( 200.0f, -25.0f, -100.0f);
GL.End();
Can anyone please help me to make the plane transparent?
So you want something like this?
There are a lot of things to take care of to get there.
It all starts with a Color object that contains an alpha value<255. For example Color.FromArgb(85, Color.Turquoise) for the sphere below.
The main render class, sets up the camera view and renders all the lights, and then renders all the objects in the scene:
public void RenderOnView(GLControl control)
{
control.MakeCurrent();
var camera=views[control];
GL.Clear(ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
GL.Disable(EnableCap.CullFace);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
camera.LookThrough();
if (EnableLights)
{
GL.LightModel(LightModelParameter.LightModelAmbient, new[] { 0.2f, 0.2f, 0.2f, 1f });
GL.LightModel(LightModelParameter.LightModelLocalViewer, 1);
GL.Enable(EnableCap.Lighting);
foreach (var light in lights)
{
light.Render();
}
}
else
{
GL.Disable(EnableCap.Lighting);
GL.ShadeModel(ShadingModel.Flat);
}
GL.Enable(EnableCap.LineSmooth); // This is Optional
GL.Enable(EnableCap.Normalize); // These is critical to have
GL.Enable(EnableCap.RescaleNormal);
for (int i=0; i<objects.Count; i++)
{
GL.PushMatrix();
objects[i].Render();
GL.PopMatrix();
}
control.SwapBuffers();
}
Then each object has a base rendering code Render(), which calls more specialized code Draw()
public void Render()
{
if (Shading==ShadingModel.Smooth)
{
GL.Enable(EnableCap.ColorMaterial);
GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, SpecularColor);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, EmissionColor);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, Shinyness);
GL.Enable(EnableCap.Lighting);
}
else
{
GL.Disable(EnableCap.ColorMaterial);
GL.Disable(EnableCap.Lighting);
}
GL.ShadeModel(Shading);
GL.Translate(Position);
GL.Scale(Scale, Scale, Scale);
Draw(); // Draws triangles and quads to make up a shape
}
and for example to draw a quad surface you have
protected void DrawQuad(Color color, params Vector3[] nodes)
{
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Enable(EnableCap.PolygonOffsetFill);
// special code when translucent
if (color.A<255)
{
GL.Enable(EnableCap.Blend);
GL.DepthMask(false);
}
GL.Begin(PrimitiveType.Quads);
GL.Color4(color); //this is where the color with alpha is used
for (int i=0; i<nodes.Length; i++)
{
GL.Vertex3(nodes[i]);
}
GL.End();
// special code when translucent
if (color.A<255)
{
GL.Disable(EnableCap.Blend);
GL.DepthMask(true);
}
}
also the code to draw the outline of a quad to be called after DrawQaud()
protected void DrawLineLoop(Color color, params Vector3[] nodes)
{
GL.Disable(EnableCap.PolygonOffsetFill);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
if (color.A<255)
{
GL.Enable(EnableCap.Blend);
GL.DepthMask(false);
}
GL.Begin(PrimitiveType.LineLoop);
GL.Color4(color);
for (int i=0; i<nodes.Length; i++)
{
GL.Vertex3(nodes[i]);
}
GL.End();
if (color.A<255)
{
GL.Disable(EnableCap.Blend);
GL.DepthMask(true);
}
}
Finally I found solution of my question:
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One);
GL.Enable(EnableCap.Blend);
//Definition of Plane
GL.Begin(BeginMode.Quads);
GL.Color4(0, 0.2, 1, 0.5);
GL.Vertex3(-100.0f, -25.0f, -150.0f);
GL.Vertex3(-100.0f, -25.0f, 150.0f);
GL.Vertex3( 200.0f, -25.0f, 100.0f);
GL.Vertex3( 200.0f, -25.0f, -100.0f);
GL.End();
GL.Disable(EnableCap.Blend);
In computing, Transparency effects are fained using color blending.For The special case of transprency, we talk about Àlpha Blending`
For transparency the blending factor is usualy stored in the 4th component of the colour (the A in RGBA) which stands for alpha. So you have to set all your colors with it.
example for half transparent blue (like glass):
GL.Color4(0,0,1,0.5f);
In OpenGL, blending have to be activated with the following command, which enable a supplementary stage on the rendering pipeline.
GL.Enable( EnableCap.Blend );
Then, because blending could be used to mix colors for other purpose than transparency, you have to specify the blending function to use. Here is the common function for transparency:
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
http://www.opentk.com/doc/chapter/2/opengl/fragment-ops/blending
Simply use GL.Color4 instead of GL.Color3. The 4th value will be the alpha