OpenTK C# Perspective Lighting looks glitchy - c#

My goal is to make lighting in perspective view smooth. I'm using the same light settings for both perspective and orthographic. The images below show that the orthographic lighting looks great. The perspective lighting looks glitchy and flickers when I rotate it. What am I missing that would make the perspective view lighting look okay?
Processor: AMD FX 6100 6-core 3.31GHz
Graphics: AMD Radeon HD 6800
Note: I referenced from an OpenGL example. I was playing with the different light settings to find out how they work. The code I pasted at the end of this post is the code that created the images.
Perspective: http://i.stack.imgur.com/pSXul.png
Orthographic: http://i.stack.imgur.com/Q7Yr2.png
Here is the relevant code within my paint method.
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!glLoaded)
return;
GL.Enable(EnableCap.DepthTest);
//GL.Enable(EnableCap.Blend);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
//SET PERSPECTIVE OR ORTHOGRAPHIC VIEW
if (chkPerspective.Checked)
{
double aspect = glControl1.Width / (double)glControl1.Height;
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)aspect, 0.0001f, 5000.0f);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.LoadMatrix(ref perspective);
Matrix4 lookat = Matrix4.LookAt(eyeOffset.X, eyeOffset.Y, eyeOffset.Z, 0, 0, 0, 0, 1, 0);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref lookat);
//GL.Translate(-boxOffset);
}
else
{
setupViewPort(); //Orthographic settings
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
}
GL.Rotate(angleY, 1.0f, 0, 0);
GL.Rotate(angleX, 0, 1.0f, 0);
//LIGHTING
if (chkLighting.Checked)
{
float[] mat_specular = { 1.0f, 1.0f, 1.0f, 1.0f };
float[] mat_shininess = { 50.0f };
float[] light_position = { 1000.0f, 1000.0f, 1000.0f, 100.0f };
float[] light_ambient = { 0.5f, 0.5f, 0.5f, 1.0f };
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//GL.ShadeModel(ShadingModel.Smooth);
//GL.Material(MaterialFace.Front, MaterialParameter.Specular, mat_specular);
//GL.Material(MaterialFace.Front, MaterialParameter.Shininess, mat_shininess);
GL.Light(LightName.Light0, LightParameter.Position, light_position);
//GL.Light(LightName.Light0, LightParameter.Ambient, light_ambient);
//GL.Light(LightName.Light0, LightParameter.Diffuse, mat_specular);
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
GL.Enable(EnableCap.ColorMaterial);
//GL.Enable(EnableCap.CullFace);
}
else
{
GL.Disable(EnableCap.Lighting);
GL.Disable(EnableCap.Light0);
}
foreach (Cube cube in cubes)
{
cube.drawCube(selectionCubeRadius);
}
glControl1.SwapBuffers();
}
Here is my orthographic viewport code in case it matters.
private void setupViewPort()
{
if (chkPerspective.Checked)
return;
int w = glControl1.Width;
int h = glControl1.Height;
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-w, w, -h, h, -5000, 5000); // Bottom-left corner pixel has coordinate (0, 0)
GL.Viewport(0, 0, w, h); // Use all of the glControl paintingarea
}

Based solely on the images, it looks like depth test is being disabled or some normals are flipped or non-normalized.
What does drawCube do exactly?

I found a solution that will work for now. In perspective view, I reduced the size of the cubes from 200.0 to 5.0. Then I moved the camera closer so they appear the same size. Some also said that I should decrease the far Z-plane when I create my perspective field of view.
Reducing the size of my models worked, but I also decreased the distance of the far z-plane for convention purposes. I'll also likely create an algorithm that determines what z-plane distance to use based on my current model size and angle.
User 'dflemstr' asked about my GL.Normal3f calls. The answer is that I have none. What do they do, and are they necessary?

Related

Opengl OpenTK - White screen when drawing depth Buffer [duplicate]

This question already has an answer here:
OpenGL 4.2 LookAt matrix only works with -z value for eye position
(1 answer)
Closed 2 years ago.
I am currently trying to add shadows with Shadow Mapping to my 3D Engine.
First I render the scene from the light's point of view, and save the depth values in a texture. Then I use the defeault FBO to draw from the texture. Just like in this tutorial.
The problem is that my screen stays white, no matter where I move.
GL.GetError() outputs noError and the SSBO's which I use in vertex shader have the right values. GL.CheckFramebufferStatus() returns FramebufferCompleteExt.
This is how I create the FBO for depth values:
_depthMapFBO = GL.GenFramebuffer();
_depthMapFBOColorBuffer = BufferObjects.FBO_TextureAttachment(_depthMapFBO, PixelInternalFormat.DepthComponent, PixelFormat.DepthComponent, FramebufferAttachment.DepthAttachment, 1024, 1024);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _depthMapFBO);
GL.DrawBuffer(DrawBufferMode.None);
GL.ReadBuffer(ReadBufferMode.None);
====================================
public static int FBO_TextureAttachment(int FrameBuffer, PixelInternalFormat PixelInternalFormat, PixelFormat PixelFormat, FramebufferAttachment FramebufferAttachment, int Width, int Height)
{
// PixelInternalFormat = DepthComponent && PixelFormat = DepthComponent && FramebufferAttachment = DepthAttachment && Width, Height = 1024,
GL.BindFramebuffer(FramebufferTarget.Framebuffer, FrameBuffer);
int _texture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, _texture);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat, Width, Height, 0, PixelFormat, PixelType.Float, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment, TextureTarget.Texture2D, _texture, 0);
return _texture;
}
In my Render function it looks like this:
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _depthMapFBO);
GL.Clear(ClearBufferMask.DepthBufferBit);
GL.Viewport(0, 0, 1024, 1024);
_simpleDepthProgram.Use();
float _nearPlane = 1.0f, _farPlane = 100f;
_lightProjection = Matrix4.CreateOrthographicOffCenter(-100.0f, 100.0f, -100.0f, 100.0f, _nearPlane, _farPlane);
_ligthView = Matrix4.LookAt(_allLamps[0].Position, new Vector3(0f), new Vector3(0.0f, 1.0f, 0.0f));
_lightSpaceMatrix = _lightProjection * _ligthView;
GL.UniformMatrix4(21, false, ref _lightSpaceMatrix);
// Copy all SSBO's
GL.ActiveTexture(TextureUnit.Texture2);
GL.BindTexture(TextureTarget.Texture2D, _depthMapFBOColorBuffer);
Scene();
And the shader where I draw the depthMap:
#version 450 core
out vec4 FragColor;
uniform sampler2D scene;
uniform sampler2D bloomed;
uniform sampler2D depthMap;
uniform float zNear;
uniform float zFar;
float LinearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0; // Back to NDC
return (2.0 * zNear * zFar) / (zFar + zNear - z * (zFar - zNear));
}
in vec2 TexCoord;
void main()
{
float depthValue = texture(depthMap, TexCoord).r;
//float depth = LinearizeDepth(gl_FragCoord.z) / far; // only for perspective
FragColor = vec4(vec3(depthValue), 1.0);
}
The computation of the _lightSpaceMatrix is wrong. The OpenTK matrix multiplication is reversed. See Problem with matrices #687:
Because of how matrices are treated in C# and OpenTK, multiplication order is inverted from what you might expect in C/C++ and GLSL. This is an old artefact in the library, and it's too late to change now, unfortunately.
Swap the _ligthView and _lightProjection when you multiply the matrices:
_lightSpaceMatrix = _lightProjection * _ligthView;
_lightSpaceMatrix = _ligthView * _lightProjection;

SharpGL 2D Texturing issue

I am trying to texture triangle with runtime generated texture using SharpGL wrapper.
I can't figure out why triangle remains not textured.
gl.Error() put in draw loop returns 0 which means GL_NO_ERROR.
private void openGLControl_OpenGLDraw(object sender, OpenGLEventArgs args)
{
OpenGL gl = openGLControl.OpenGL;
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT );
gl.LoadIdentity();
gl.Color(1.0f,1.0f,1.0f,1.0f);
gl.Begin(OpenGL.GL_TRIANGLES);
gl.TexCoord(0, 1.0f);
gl.Vertex(0.0f, 0.0f);
gl.TexCoord(1.0f, 0f);
gl.Vertex(1.0f, 0f);
gl.TexCoord(1.0f, 1.0f);
gl.Vertex(1.0f, 1.0f);
gl.End();
}
private void openGLControl_OpenGLInitialized(object sender, OpenGLEventArgs args)
{
Random rnd = new Random();
OpenGL gl = openGLControl.OpenGL;
gl.ClearColor(0, 0, 0, 0);
gl.Enable(OpenGL.GL_TEXTURE_2D);
byte[] colors = new byte[256 * 256 * 4];
for (int i = 0; i < 256 * 256 * 4; i++)
{
colors[i] = (byte)rnd.Next(256);
}
uint[] textureID = new uint[1];
gl.GenTextures(1, textureID);
gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA, 256, 256, 0, OpenGL.GL_RGBA, OpenGL.GL_BYTE, colors);
gl.BindTexture(OpenGL.GL_TEXTURE_2D, textureID[0]);
}
You have to call gl.BindTexture before calling gl.TexImage2D.
The reason for this is in the first argument of both functions. OpenGL has a state machine that keeps track of what is bound. When you call gl.TexImage2D, you are telling GL to upload the pixels to the texture currently bound to OpenGL.GL_TEXTURE_2D. gl.BindTexture binds the texture you generated to OpenGL.GL_TEXTURE_2D.
The reason why texture wasn't visible was lacking setting:
uint[] array = new uint[] { OpenGL.GL_NEAREST };
gl.TexParameterI(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, array);
gl.TexParameterI(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, array);
By default SharpGL is using MipMap which weren't generated.

OpenGL/SharpGL: Rendering 2D image is stretched horizontally

I'm playing around with OpenGL in C# (using SharpGL) and I come from a DirectX background... I figured OpenGL would be pretty similar, and it kinda is, except I'm having an issue with my projection matrices which causes my 2D image to be stretched horizontally a little bit (making Lena look VERY bloated).
I think my issue is stemming from my ortho projection, but I'm not positive - I stuffed a projection into the draw function, to make sure it was working as expected. The texture is rendering correctly to the vertices, the image is 512:512 as a BMP (verified when pulled into C#).
Perhaps someone could take a look at my code and help me out? I've copied most of this code from other examples, and have fiddled with it a bit, so this is my latest incarnation:
private bool TexturesInitialised = false;
private Bitmap gImage1;
private System.Drawing.Imaging.BitmapData gbitmapdata;
private uint[] gtexture = new uint[1];
private void InitialiseTexture(ref OpenGL gl)
{
gImage1 = new Bitmap(#"C:\Users\SJ\Pictures\lenaV.bmp");
Rectangle rect = new Rectangle(0, 0, gImage1.Width, gImage1.Height);
gbitmapdata = gImage1.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
gImage1.UnlockBits(gbitmapdata);
gl.GenTextures(1, gtexture);
gl.BindTexture(OpenGL.GL_TEXTURE_2D, gtexture[0]);
gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA, gImage1.Width, gImage1.Height, 0, OpenGL.GL_BGR_EXT, OpenGL.GL_UNSIGNED_BYTE, gbitmapdata.Scan0);
gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);
gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);
TexturesInitialised = true;
}
private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
{
// Get the OpenGL object.
OpenGL gl = openGLControl.OpenGL;
// Clear the color and depth buffer.
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
// Load the identity matrix.
gl.LoadIdentity();
if (!TexturesInitialised)
{
InitialiseTexture(ref gl);
}
gl.Enable(OpenGL.GL_TEXTURE_2D);
gl.BindTexture(OpenGL.GL_TEXTURE_2D, gtexture[0]);
gl.Color(1.0f, 1.0f, 1.0f, 0.1f);
gl.Begin(OpenGL.GL_QUADS);
gl.TexCoord(1.0f, 1.0f);
gl.Vertex(gImage1.Width, gImage1.Height, 1.0f);
gl.TexCoord(0.0f, 1.0f);
gl.Vertex(0.0f, gImage1.Height, 1.0f);
gl.TexCoord(0.0f, 0.0f);
gl.Vertex(0.0f, 0.0f, 1.0f);
gl.TexCoord(1.0f, 0.0f);
gl.Vertex(gImage1.Width, 0.0f, 1.0f);
gl.End();
gl.Disable(OpenGL.GL_TEXTURE_2D);
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.LoadIdentity();
gl.Ortho(0.0, (double)gImage1.Width, (double)gImage1.Height, 0.0, -1.0, 1.0);
gl.MatrixMode(OpenGL.GL_MODELVIEW);
gl.Disable(OpenGL.GL_DEPTH_TEST);
}
private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
{
// Get the OpenGL object.
OpenGL gl = openGLControl.OpenGL;
// Set the clear color.
gl.ClearColor(0, 0, 0, 0);
}
private void openGLControl_Resized(object sender, EventArgs e)
{
OpenGL gl = openGLControl.OpenGL;
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.LoadIdentity();
if (!TexturesInitialised)
{
gl.Ortho(-1, 1, -1, 1, -1, 1);
}
else
{
gl.Ortho(0, gImage1.Width, gImage1.Height, 0, -1, 1);
}
gl.MatrixMode(OpenGL.GL_MODELVIEW);
gl.Disable(OpenGL.GL_DEPTH_TEST);
}
Full credit to GeirGrusom for this one. The change was as simple as setting:
gl.Ortho(0.0, (double)gImage1.Width, (double)gImage1.Height, 0.0, -1.0, 1.0);
to:
gl.Ortho(0.0, (double)openGLControl.Width, (double)openGLControl.Height, 0.0, -1.0, 1.0);

OpenTK Ortho Camera causes objects not to show

I'm trying to draw objects on my screen in 2D and translate them on a pixel by pixel bases.
Here is my render code, and for some reason it's not showing my objects anymore. It showed them before I added the Ortho Camera. What's going on?
Thanks!
game.RenderFrame += (sender, e) =>
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, 800, 600, 0, -1, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
// GL.ActiveTexture(TextureUnit.Texture0);
int textID = loadTexture(Rock);
GL.BindTexture(TextureTarget.Texture2D, textID);
drawObject(100, 20, 0.15f, 0.15f);
drawObject(100, 60, 0.15f, 0.15f);
drawObject(100, 100,0.15f, 0.15f);
game.SwapBuffers();
};
drawObject(PosX, PosY, ScaleX, ScaleY);
and within my drawObject method I am using
`GL.Translate(PosX, PosY, 0);`

How to rotate a 3D model based on the projection coordinates

I'm trying to implement something using OpenTK in C# where when you render a 3d plot, you can rotate it around the z axis (pointing up) as I move the mouse.
I already have it working but as shown below, I had to come up with an arbitrary constant 500;
The equation is:
arc_length = radius * theta
theta = arc_length / radius
where radius = eye_pos.Length
arc_length is the delta_x in model coordinate, but
(e.X - mouse_down_pos.X) is in screen coordinate.
so that 500 was used to map model coordinate to screen projected coordinate.
QUESTION: is there a way to eliminate this constant and properly obtain the conversion factor?
My educated guess is that I should use somehow multiply [delta_x, 0, 0] by inverse of the projection matrix...but do not have a clue how.
private static Vector3 eye_pos = new Vector3(30.0f, 0.0f, 0.0f);
GL.MatrixMode(MatrixMode.Modelview);
Matrix4 lookat = Matrix4.LookAt(eye_pos.X, eye_pos.Y, eye_pos.Z, 0, 0, 0, 0, 0, 1);
...
private void glControl1_MouseMove(object sender, MouseEventArgs e)
{
if (mouse_op == Mouse_Operation.Rotate)
{
decimal yaw = (decimal)MathHelper.DegreesToRadians((e.X - mouse_down_pos.X) * 500 / eye_pos.Length) + ref_yaw;
SetYawAndRedraw(yaw);
}
}

Categories