OpenGL. Moving light source - c#

in my program I use OpenTK with C#. And, I have a trouble with light source. I can't tie it to the camera. It only stay on fixed position.
Here is code of glControl1_Load():
float[] light_ambient = { 0.2f, 0.2f, 0.2f, 1.0f };
float[] light_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
float[] light_specular = { 1.0f, 1.0f, 1.0f, 1.0f };
float[] spotdirection = { 0.0f, 0.0f, -1.0f };
GL.Light(LightName.Light0, LightParameter.Ambient, light_ambient);
GL.Light(LightName.Light0, LightParameter.Diffuse, light_diffuse);
GL.Light(LightName.Light0, LightParameter.Specular, light_specular);
GL.Light(LightName.Light0, LightParameter.ConstantAttenuation, 1.8f);
GL.Light(LightName.Light0, LightParameter.SpotCutoff, 45.0f);
GL.Light(LightName.Light0, LightParameter.SpotDirection, spotdirection);
GL.Light(LightName.Light0, LightParameter.SpotExponent, 1.0f);
GL.LightModel(LightModelParameter.LightModelLocalViewer, 1.0f);
GL.LightModel(LightModelParameter.LightModelTwoSide, 1.0f);
GL.Enable(EnableCap.Light0);
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.ColorMaterial);
GL.ShadeModel(ShadingModel.Flat);
glControl1_Paint():
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref cameramatrix);
GL.Light(LightName.Light0, LightParameter.Position, new float[]{0.0f, 0.0f, 0.0f, 1.0f});
If I'm not wrong, the coordinates light source stored in eye space coord. So, what's wrong?

LoadIdentity instead of your camera matrix for the model view. Your light source will always stay at the same location relative to your camera.
"If the w value is nonzero, the light is positional, and the (x, y, z) values specify the location of the light in homogeneous object coordinates. (See Appendix F.) This location is transformed by the modelview matrix and stored in eye coordinates."
more details here Look for "Example 5-7"

Related

Perspective Projection Matrix transforms like Orthogonal

Suppose I have a point which is not in (0, 0, 0) and a perspective camera which is looking at (0, 0, 0).
To my understanding, if I move the perspective camera along the z axis, the point on the screen should move as well. The further the camera is, the closer the point should be towards (0, 0) in screen coordinates.
In my C# program, the camera movement does not affect screen coordinates (x, y) at all. It only changes the z coordinate just like an orthogonal camera. Here is the minimal example:
Vector3 v = new Vector3(3.0f);
// Move camera z to -10 from the center
Matrix4x4 viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0.0f, 0.0f, -10.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
Matrix4x4 projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView((float)Math.PI / 3.0f, 1.0f, 0.1f, 100.0f);
Vector3 v1 = Vector3.Transform(v, viewMatrix * projectionMatrix);
Console.WriteLine(v1); //<-5.1961527, 5.1961527, 12.912912>
// Move camera z to -1 from the center
viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0.0f, 0.0f, -1.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
Vector3 v2 = Vector3.Transform(v, viewMatrix * projectionMatrix);
Console.WriteLine(v2); //<-5.1961527, 5.1961527, 3.903904>
What is wrong in my reasoning?
Maybe the W of projected coord is not 1.
In vertex shaders, the returned W means point or vector. If 1, it is point. But for some reason, the vertex shaders automately divide XYZ by W. Therefore, the vertex shader need not to set W as 1 explicitly and almost of 3D math libraries return W as divisor instead of 1.
If you want to get proper projected coord, manually divide. Vector4.Transform() and divide XYZ by the W.

SharpGL Screen / Cursor Coordinate to Model View

Using SharpGL, is it possible to transform the screen cursor position back to a model view location (ie. create a ray-cast function)?
The example I have been working with is similar to the following:
private void OpenGLControl_OpenGLDraw(object sender, SharpGL.OpenGLEventArgs args)
{
OpenGL gl = args.OpenGL;
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.LoadIdentity();
gl.Translate(0.0f, 0.0f, -6.0f);
gl.Rotate(rotatePyramid, 0.0f, 1.0f, 0.0f);
gl.Begin(OpenGL.GL_TRIANGLES);
gl.Color(1.0f, 0.0f, 0.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Color(0.0f, 1.0f, 0.0f);
gl.Vertex(-1.0f, -1.0f, 1.0f);
gl.Color(0.0f, 0.0f, 1.0f);
gl.Vertex(1.0f, -1.0f, 1.0f);
gl.Color(1.0f, 0.0f, 0.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Color(0.0f, 0.0f, 1.0f);
gl.Vertex(1.0f, -1.0f, 1.0f);
gl.Color(0.0f, 1.0f, 0.0f);
gl.Vertex(1.0f, -1.0f, -1.0f);
gl.Color(1.0f, 0.0f, 0.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Color(0.0f, 1.0f, 0.0f);
gl.Vertex(1.0f, -1.0f, -1.0f);
gl.Color(0.0f, 0.0f, 1.0f);
gl.Vertex(-1.0f, -1.0f, -1.0f);
gl.Color(1.0f, 0.0f, 0.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Color(0.0f, 0.0f, 1.0f);
gl.Vertex(-1.0f, -1.0f, -1.0f);
gl.Color(0.0f, 1.0f, 0.0f);
gl.Vertex(-1.0f, -1.0f, 1.0f);
gl.End();
gl.Flush();
}
Using SharpGL, and the approach demonstrated in the above sample, is it possible to implement a ray-cast/mouse selection? Or would I need to delve deeper into the OpenGL workings (Manually manage matrices etc) to achieve this?
Edit: To clarify, I am trying to retrieve the 3D interpretation of the 2D cursor location. Maybe through perspective (w) scaling etc.
You can just use gluUnproject() and pass it the 2D screen space mouse position you retrieved from mouse callback.This function will return the 3D world space position for you which you can use as you want.
I don't know if the previous answers were good for you, but BTW glVertex, glRotate, glBegin and so on are very old GL functions (v1 or v2). Is it your choice to use them, or don't you know about v3 or v4 way of doing 3D things with opengl (VAO, VBO, and so on)?

Create an Octahedron (Flip Pyramid Upside Down) OpenTK

I am using OpenTK to make an octahedron. I have a square pyramid created and need to translate another beneath the top one and flip it upside down to create the octahedron.
How do I flip the second pyramid upside down?
Here is my code so far:
#region --- Using Directives ---
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform;
#endregion
namespace Octahedron
{
public class Octahedron : GameWindow
{
#region --- Fields ---
const float rotation_speed = 180.0f;
float angle;
#endregion
#region --- Constructor ---
public Octahedron()
: base(800, 600)
{ }
#endregion
#region OnLoad
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
GL.ClearColor(Color.MidnightBlue);
GL.Enable(EnableCap.DepthTest);
}
#endregion
#region OnResize
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
GL.Viewport(0, 0, Width, Height);
double aspect_ratio = Width / (double)Height;
OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)aspect_ratio, 1, 64);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref perspective);
}
#endregion
#region OnUpdateFrame
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
var keyboard = OpenTK.Input.Keyboard.GetState();
if (keyboard[OpenTK.Input.Key.Escape])
{
this.Exit();
return;
}
}
#endregion
#region OnRenderFrame
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Matrix4 lookat = Matrix4.LookAt(0, 5, 10, 0, 0, 2, 0, 5, 0);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref lookat);
angle += rotation_speed * (float)e.Time;
GL.Rotate(angle, 0.0f, 1.0f, 0.0f);
DrawPyramid();
GL.Translate(0.0f, -2.0f, 0.0f);
DrawPyramid();
this.SwapBuffers();
Thread.Sleep(1);
}
#endregion
#region private void DrawPyramid()
private void DrawPyramid()
{
GL.Begin(PrimitiveType.Triangles);
//Side0 (red)
//x, y, z
GL.Color3(1.0f, 0.0f, 0.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);//Top Vertex
//x, y, z
GL.Color3(1.0f, 0.0f, 0.0f); GL.Vertex3(-1.0f, -1.0f, 1.0f);//Bottom Left Vertex
//x, y, z
GL.Color3(1.0f, 0.0f, 0.0f); GL.Vertex3(1.0f, -1.0f, 1.0f);//Bottom Right Vertex
//Side1 (blue)
//x, y, z
GL.Color3(0.0f, 0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);//Top Vertex
//x, y, z
GL.Color3(0.0f, 0.0f, 1.0f); GL.Vertex3(1.0f, -1.0f, 1.0f);//Bottom Left Vertex
//x, y, z
GL.Color3(0.0f, 0.0f, 1.0f); GL.Vertex3(1.0f, -1.0f, -1.0f);//Bottom Right Vertex
// Side2 (yellow)
//x, y, z
GL.Color3(1.0f, 1.0f, 0.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);
//x, y, z
GL.Color3(1.0f, 1.0f, 0.0f); GL.Vertex3(1.0f, -1.0f, -1.0f);
//x, y, z
GL.Color3(1.0f, 1.0f, 0.0f); GL.Vertex3(-1.0f, -1.0f, -1.0f);
// Side3 (pink)
//x, y, z
GL.Color3(1.0f, 0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);
//x, y, z
GL.Color3(1.0f, 0.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, -1.0f);
//x, y, z
GL.Color3(1.0f, 0.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, 1.0f);
//Side4 (red)
//x, y, z
GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);//Top Vertex
//x, y, z
GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, 1.0f);//Bottom Left Vertex
//x, y, z
GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(1.0f, -1.0f, 1.0f);//Bottom Right Vertex
GL.End();
}
#endregion
#region public static void Main()
[STAThread]
public static void Main()
{
using (Octahedron oct = new Octahedron())
{
oct.Run(60.0, 0.0);
}
}
#endregion
}
}
Hint: for simple things which align neatly with a reference plane in x,y,z coordinate space (i.e the planes (x,y), (x,z), (y,z)), flipping something along a certain axis is equivalent to multiplying the particular coordinate by -1. In the more general case you can use a matrix multiplication, using a predefined matrix representing the proper rotation of all coordinates.

OpenTK - transparency issue on VBO

I just want to create an .obj file loader, which will load 3D objects. Everything went alright but when i try to load a transparent object i got a problem.
So, here is a picture of the issue. Transparency is working but i don't know why, there are triangles. I try to load different objects (with and without texture also) but i got this issue always.
here is my light settings:
class Light
{
public static void SetLight()
{
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
GL.Enable(EnableCap.ColorMaterial);
Vector4 position = new Vector4(0.0f, 200.0f, 300.0f, 1.0f);
Vector4 ambient = new Vector4(0.2f, 0.2f, 0.2f, 1.0f);
Vector4 diffuse = new Vector4(0.7f, 0.7f, 0.7f, 1.0f);
Vector4 specular = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
GL.Light(LightName.Light0, LightParameter.Position, position);
GL.Light(LightName.Light0, LightParameter.Ambient, ambient);
GL.Light(LightName.Light0, LightParameter.Diffuse, diffuse);
GL.Light(LightName.Light0, LightParameter.Specular, specular);
}
public static void SetMaterial()
{
GL.Color4(1.0f, 1.0f, 1.0f, 0.5f);
Vector4 ambient = new Vector4(0.3f, 0.3f, 0.3f, 0.5f);
Vector4 diffuse = new Vector4(1.0f, 1.0f, 1.0f, 0.5f);
Vector4 specular = new Vector4(0.0f, 0.0f, 0.0f, 0.5f);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, ambient);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, diffuse);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, specular);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, 1.0f);
}
}
and in the main Load function a also have these settings
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
//GL.Enable(EnableCap.DepthTest);
//GL.Enable(EnableCap.CullFace);
i know that maybe my answer is not the best, but i don't know what is this issue and i don't even find similar issues on the net.
Your problem is this:
You need to sort the transparent faces from the furthest to the closest before drawing them.

Texture in OpenGL show as single color

I'm fiddling with OpenGL with the help of OpenTK but I can't display a simple texture.
My main problem is that my rectangle don't display the texture but rather a color from it.
Here is my display loop :
// render graphics
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 4.0);
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, textureId);
GL.Begin(PrimitiveType.Quads);
GL.Vertex2(-1.0f, 1.0f);
GL.Vertex2(1.0f, 1.0f);
GL.Vertex2(1.0f, -1.0f);
GL.Vertex2(-1.0f,-1.0f);
GL.End();
GL.Disable(EnableCap.Texture2D);
game.SwapBuffers();
You need some texture coordinates. Right now it's just using the default (0, 0) texcoord.
Something like this:
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0.0f, 0.0f);
GL.Vertex2(-1.0f, 1.0f);
GL.TexCoord2(1.0f, 0.0f);
GL.Vertex2(1.0f, 1.0f);
GL.TexCoord2(1.0f, 1.0f);
GL.Vertex2(1.0f, -1.0f);
GL.TexCoord2(0.0f, 1.0f);
GL.Vertex2(-1.0f,-1.0f);
GL.End();

Categories

Resources