2016-04-02 79 views
0

我正在通過GLSL食譜,但我正在用C#編程,所以我試圖使用OpenTK轉換代碼。 我目前正在使用Phong Shading示例,並且我可以獲得正確工作的照明機制,但是我使用的環面模型不會呈現遠離Z軸距離1的任何元素相機。爲什麼我的OpenGL場景在z距離處裁剪1?

這裏是示例呈現正確(X旋轉= 0,Y旋轉= 0,camera.z = 1,model.z = 0) Torus Rendering Correctly

這與X和Y旋轉而施加( X旋轉= -0.5,Y旋轉= 0.5,camera.z = 1,model.z = 0) Torus rotated showing clipping

注意:如果,在旋轉的實例中,我移動相機接近到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()不返回任何錯誤。 另外,我在着色器中有很多調試代碼來驗證傳入的值是否正確 - 它們是。

這裏有渲染,更新和調整方法:

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

正如我所說,如果發佈的代碼是不足以得到問題的根源,我很樂意發佈其餘的內容。 在此先感謝您提供的任何建議。

+0

我是否正確地閱讀它,您的投影矩陣實際上並不是任何一種投影,而是身份?所以你基本上只是在相機周圍旋轉場景,然後被[NDC立方體的遠平面(右邊的那個))剪裁(http://www.songho.ca/opengl/)文件/ gl_projectionmatrix01.png)?您是否嘗試過使用投影? – peppe

+0

你是正確的,我使用單位矩陣作爲我的投影矩陣。這確實限制了我的剪輯距離爲1.並且正如皮爾斯在他的回答中指出的那樣,這也解釋了將模型從相機移開進而導致對近平面進行裁剪的事實。在回答關於投影矩陣的問題時,是的,我已經嘗試過了,但目前我無法使用它。如果我遇到問題,我會繼續嘗試並在此發佈另一個問題。謝謝。 – PrioryOfScion

回答

1

我會說一切都按照滿意的方式工作。 OpenGL的剪輯空間約定是規範化設備空間中沿着所有3軸的[-1,1]立方體。由於您使用身份作爲投影矩陣,因此您的眼睛空間將與NDC相同。換句話說,可見光範圍將從相機後面的-1單位變爲相機前面的一個單位。更糟糕的是,典型的OpenGL習慣是眼睛空間是右手的(z指向你,攝像頭正在朝-z方向看),而NDC /窗口空間左手(z軸指向屏幕)。投影矩陣通常會翻轉。既然你使用了身份,你也不會這麼做 - 所以它可能會感覺非常不直觀,但是當你的照相機是z_win = 1時,你正在裁剪通常用作近平面的東西。

+0

關於左手和右手座標系中開關的優點。我沒有想到這一點。我曾嘗試應用基於屏幕比例和裁剪從0.01到100的z方向的透視矩陣,但尚未得到它的工作。如果我繼續遇到問題,我會在此發佈另一個問題。 – PrioryOfScion