OpenTK C#透视照明看起来很炫目

OpenTK C#透视照明看起来很炫目,c#,opengl,perspective,lighting,opentk,C#,Opengl,Perspective,Lighting,Opentk,我的目标是使透视视图中的照明平滑。我对透视视图和正交视图使用相同的灯光设置。下面的图像显示正交照明看起来很棒当我旋转透视照明时,它看起来会闪烁。我遗漏了什么可以使透视照明看起来正常 处理器:AMD FX 6100 6核3.31GHz 图形:AMD Radeon HD 6800 注意:我引用了一个OpenGL示例。我在玩不同的灯光设置来了解它们是如何工作的。我在本文末尾粘贴的代码就是创建图像的代码 透视图: 正字法: 这是我的绘画方法中的相关代码。 private void glControl1_

我的目标是使透视视图中的照明平滑。我对透视视图和正交视图使用相同的灯光设置。下面的图像显示正交照明看起来很棒当我旋转透视照明时,它看起来会闪烁。我遗漏了什么可以使透视照明看起来正常

处理器:AMD FX 6100 6核3.31GHz

图形:AMD Radeon HD 6800

注意:我引用了一个OpenGL示例。我在玩不同的灯光设置来了解它们是如何工作的。我在本文末尾粘贴的代码就是创建图像的代码

透视图:

正字法:

这是我的绘画方法中的相关代码。

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();
}
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
}

这是我的正交视口代码,以防万一。

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();
}
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
}

仅基于图像,看起来深度测试被禁用,或者某些法线被翻转或未规范化


drawCube到底做了什么?

我找到了一个暂时可行的解决方案。在透视图中,我将立方体的大小从200.0减小到5.0。然后我把相机移近一点,让它们看起来一样大。有些人还说,当我创建透视视野时,应该减小远Z平面

缩小模型的尺寸是可行的,但出于常规目的,我还缩短了远z平面的距离。我还可能创建一个算法,根据当前模型大小和角度确定要使用的z平面距离


用户“dflemstr”询问我的GL.Normal3f呼叫。答案是我没有。它们是做什么的?它们是必要的吗?

这是一个很好的问题,它似乎拥有帮助专家解决问题所需的所有相关信息。我绝对不是那种专家;我向你保证,你比我更了解这些东西的编码!当我看到一个时,我只知道一个好的Q…你确定你想要100.0f作为灯光位置。w,而不是1.0f?将w更改为1.0会使灯光强度从块的一侧到另一侧的变化不那么明显。透视视图中的闪烁仍然存在,但是.DrawCube()包含GL.Begin(BeginMode.Quads),绘制立方体的6个面,然后是GL.End()。仅此而已。有什么方法可以确保法线是正确的吗?目前您的
GL.Normal3f
调用是什么?它们必须包含单位长度的向量。只需发布代码!法线是一个长度为1的向量,它指向“超出”曲面。每个顶点都有一条法线。例如,对于立方体的顶部正方形,每个顶点的法线为(0,1,0),因为曲面指向上(正Y)。如果不指定法线,则驱动程序必须猜测法线,灯光计算将出错。