繁体   English   中英

为什么我的OpenGL场景在z距离为1时被裁剪?

[英]Why is my OpenGL scene clipping at z distance of 1?

我正在阅读GLSL Cookbook,但是我正在使用C#进行编程,因此我尝试使用OpenTK转换代码。 我目前正在使用Phong Shading示例,并且可以使照明的原理正常工作,但是我使用的环面模型将不会渲染任何距离相机的Z距离大于1的元素。

这是正确渲染的示例(x旋转= 0,y旋转= 0,camera.z = 1,model.z = 0) 正确渲染圆环

在这里它与一个X和Y施加的旋转(X旋转= -0.5,Y旋转= 0.5,camera.z = 1,model.z = 0) 环面旋转表示削波

注意:如果在旋转的示例中,我将相机移到Z位置更靠近 0.4的位置,则出现圆环而没有剪切。 我不知道为什么将相机移近些会减少剪切!

有很多代码,所以我将尽量避免全部发布。 如果我确实需要发布更多信息,那么我很乐意这样做。

这是我的初始化块:

void InitProgram()
{
    // Compile and link shaders
    Compile();

    // Turn on depth testing
    GL.Enable(EnableCap.DepthTest);
    // Torus centred at (0,0,0), outer radius = 0.7, inner
    // radius = 0.3, 50 segments, 50 rings
    _torus = new VboTorus(0.7f, 0.3f, 50, 50);
    // Setup model matrix
    _model = Matrix4.Identity;
    _model *= Matrix4.CreateRotationX(-0.5f);
    _model *= Matrix4.CreateRotationY(0.5f);
    // Setup view matrix
    _view = Matrix4.LookAt(0f, 0f, 0.4f, 0f, 0f, 0.0f, 0f, 1f, 0f);
    // Setup projection matrix
    _projection = Matrix4.Identity;

    // Position the light
    var lightPos = new Vector4(5f, 5f, 2f, 1f);

    // Bind lighting attributes
    BindLightUniformBlock(lightPos);
    // Bind material attributes
    BindMaterialUniformBlock();
    // Output any errors
    var pil = GL.GetProgramInfoLog(_pgmId);
    Console.WriteLine(pil);
}

注意:GetProgramInfoLog()不会返回任何错误。 另外,我的着色器中有很多调试代码,可以验证传入的值正确无误。

这是render,update和resize方法:

protected override void OnUpdateFrame(FrameEventArgs e)
{
    base.OnUpdateFrame(e);

    if (Keyboard[Key.Escape])
        Exit();

    GL.UseProgram(_pgmId);
}

protected override void OnRenderFrame(FrameEventArgs e)
{
    base.OnRenderFrame(e);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    SetMatrices();
    _torus.Render();

    GL.Flush();
    SwapBuffers();
}

protected override void OnResize(EventArgs e)
{
    base.OnResize(e);
    GL.Viewport(0, 0, Width, Height);
}

这是设置我的M,V和P矩阵的方法:

private void SetMatrices()
{
    var modelView = _view*_model;

    var uniformIndices = new int[3];
    GL.GetUniformIndices(_pgmId, 3, new[] { "modelViewMatrix", "normalMatrix", "mvpMatrix" }, uniformIndices);

    GL.UniformMatrix4(uniformIndices[0], false, ref modelView);   // Set modelView matrix uniform
    var normMatrix = new float[]
    {
        modelView.M11, modelView.M21, modelView.M31,
        modelView.M12, modelView.M22, modelView.M32,
        modelView.M13, modelView.M23, modelView.M33
    };
    GL.UniformMatrix3(uniformIndices[1], 1, false, normMatrix);   // Set normal matrix uniform
    var temp = _projection*modelView;
    GL.UniformMatrix4(uniformIndices[2], false, ref temp);   // Set lightPosition uniform
}

最后是我的顶点着色器:

#version 430

layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec3 vertexNormal;

layout( std140 ) uniform lightInfo {
    vec4 position;
    vec3 ambientIntensity;
    vec3 diffuseIntensity;
    vec3 specularIntensity;
} light;

layout( std140 ) uniform materialInfo {
    vec3 ambientReflectivity;
    vec3 diffuseReflectivity;
    vec3 specularReflectivity;
    float shininess;
} material;

uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;
uniform mat4 mvpMatrix;

out vec3 lightIntensity;

void main()
{
    // Convert normal and position to eye coords
    vec3 tNorm = normalize( normalMatrix * vertexNormal );
    vec4 eyeCoords = modelViewMatrix * vec4( vertexPosition, 1.0 );
    vec3 s = normalize( vec3( light.position - eyeCoords ) );
    vec3 v = normalize( -eyeCoords.xyz );
    vec3 r = reflect( -s, tNorm );
    vec3 ambient = light.ambientIntensity * material.ambientReflectivity;
    float sDotN = max( dot( s, tNorm ), 0.0 );
    vec3 diffuse = light.diffuseIntensity * material.diffuseReflectivity * sDotN;

    // The diffuse shading equation
    vec3 spec = vec3( 0.0 );
    if( sDotN > 0.0 )
    {
        spec = light.specularIntensity * material.specularReflectivity * pow( max( dot( r, v ), 0.0 ), material.shininess );
    }
    lightIntensity = ambient + diffuse + spec;

    // Convert position to clip coordinates and pass along
    gl_Position = mvpMatrix * vec4( vertexPosition, 1.0 );
}

正如我所说,如果发布的代码不足以解决问题的根源,我很乐意将其余的代码发布出去。 在此先感谢您提供的任何建议。

我会说一切都按预期进行。 OpenGL的剪辑空间约定是标准化设备空间中沿所有3轴的[-1,1]立方体。 由于您使用身份作为投影矩阵,因此您的眼睛空间将变得与NDC相同。 换句话说,可见范围从相机后方的-1单位到相机前方的一个单位。

更糟糕的是,典型的OpenGL约定是右眼空间(z指向您,相机朝-z方向看),NDC /窗口空间左手(z轴指向屏幕)。 投影矩阵通常进行翻转。 由于您使用身份,因此您也不会获得身份-因此可能会感觉很不直观,但是您要限制当z_win = 1时通常用作近平面的z_win = 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM