C# 为什么我的OpenGL场景剪辑的z距离为1?
我正在阅读GLSL食谱,但我正在使用C#编程,所以我尝试使用OpenTK转换代码。 我目前正在处理一个Phong着色示例,我可以使照明机制正常工作,但我使用的圆环模型不会渲染任何距离摄影机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,则圆环体将不进行剪裁。我不知道为什么把相机移近一点会减少剪辑 有很多代码,所以我会尽量避免发布所有代码。如果我真的需要发布更多,那么我很乐意这样做 这是我的初始化块:C# 为什么我的OpenGL场景剪辑的z距离为1?,c#,opengl,glsl,opentk,vertex-shader,C#,Opengl,Glsl,Opentk,Vertex Shader,我正在阅读GLSL食谱,但我正在使用C#编程,所以我尝试使用OpenTK转换代码。 我目前正在处理一个Phong着色示例,我可以使照明机制正常工作,但我使用的圆环模型不会渲染任何距离摄影机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()不返回任何错误。
此外,我的着色器中有很多调试代码,用于验证传入的值是否正确——它们是正确的
以下是渲染、更新和调整大小的方法:
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
的时候,你是在对通常用作近平面的东西进行剪裁,你的投影矩阵实际上不是任何类型的投影,而是标识吗?所以你基本上只是在镜头周围旋转场景,然后被镜头剪辑?你试过用投影代替吗?你是对的,我用单位矩阵作为投影矩阵。这确实将我的剪辑距离限制为1。正如德哈斯在他的回答中指出的那样,这也解释了一个事实,即将模型移离相机更远会导致对近平面的剪切。在回答你关于投影矩阵的问题时,是的,我已经试过了,但是我现在无法让它工作。如果我有问题,我会继续尝试并在这里发布另一个问题。谢谢。关于左手坐标系和右手坐标系的转换,观点非常好。我一点也没想到。我曾尝试应用基于屏幕比例的透视矩阵,并在z方向上从0.01剪裁到100,但目前还没有成功。如果我仍然有问题,我会在这里发布另一个问题。