2016-04-02 9 views
0

私はGLSL Cookbookを使っていますが、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

注、回転の例では、Iは、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()すべてのエラーを返しません

は、ここに私の初期化ブロックです。 また、シェーダーに渡される値が正しいことを確認するために、多くのデバッグコードがありました。最終的にここに

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 
} 

そして、私の頂点シェーダは、次のとおりです。ここで

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行列を設定するための方法であって、ここで

は、レンダリング、アップデートやサイズを変更する方法です。

#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

私はあなたの投影行列は実際にはどんな種類の投影ではなく、アイデンティティであることを正しく読んでいますか?だから、あなたは基本的にlookAtのせいでカメラの周りのシーンを回転させていて、NDCキューブの遠方の平面(右のもの)で切り取っています(http://www.songho.ca/opengl/ファイル/ gl_projectionmatrix01.png)?代わりにプロジェクションを試しましたか? – peppe

+0

私は、私の投影行列として単位行列を使用している点で正しいです。これは本当に私にクリッピング距離が1になることを制限します。そして、彼の答えでderhassが指摘しているように、モデルをカメラから遠くに移動させると、近くの平面に対してクリッピングが発生するという事実も考慮されます。投影行列に関するご質問に答えて、私はそれを試しましたが、現時点では動作させることができません。私は問題があれば、ここで別の質問を投稿しようとし続けます。ありがとう。 – PrioryOfScion

答えて

1

私はすべてが意図的であると言います。 OpenGLのクリップ空間規約は、正規化されたデバイス空間の3つの軸すべてに沿った[-1,1]立方体です。投影行列としてアイデンティティを使用するので、目の空間はNDCと同じになります。言い換えれば、目に見える範囲はカメラの後ろの-1単位からカメラの前の1単位になります。

一般的なOpenGLのコンベンションでは、視線が右利き(zはあなたを指し、カメラは-z方向を向いています)、NDC /ウィンドウスペースは左手(z軸は画面)。投影行列は通常フリップを行います。あなたはアイデンティティを使用するので、あなたもそれを取得しません - それは非常に直感的に感じるかもしれませんが、カメラがz_win = 1である場合、通常ニアプレーンとして使用されるものにクリッピングしています。

+0

左および右の座標系におけるスイッチに関する優れた点。私はそれについて全く考えていませんでした。私はスクリーン比率と0.01から100までのz方向のクリッピングに基づいて透視マトリックスを適用しようとしましたが、それはまだ動作していません。私は問題が引き続きある場合、ここに別の質問を投稿します。 – PrioryOfScion

関連する問題