OpenGL,为什么此代码不能按我的预期工作?
你好,对于问这样一个具体问题感到抱歉。OpenGL,为什么此代码不能按我的预期工作?
我有以下GLSL顶点着色器:
#version 140
uniform vec2 viewport_size;
in vec2 vertex_position;
in vec2 in_texture_uv;
varying vec2 texture_uv;
void main(void)
{
texture_uv = in_texture_uv;
gl_Position = vec4(vertex_position/viewport_size, 0, 1);
}
和相应的片段着色器:
#version 140
uniform sampler2D texture_image;
out vec4 out_frag_color;
varying vec2 texture_uv;
void main(void)
{
out_frag_color = texture(texture_image, texture_uv);
}
产生此输出(注意左下角的小蓝点):
奇怪的是,如果我替换
texture_uv = in_texture_uv;
与
texture_uv = vertex_position;
输出变为:(注意在底部和左侧的边界)。
最后,如果我写:
texture_uv = vertex_position;
texture_uv = in_texture_uv;
输出是正确的:,这没有任何意义,我...
有人能解释为什么这种事情发生?谢谢你的时间!
相关代码片段:
float[] positionVboData = new float[] {
// X Y U V
0.0f, 0.0f, 0f, 0f,
50.0f, 0.0f, 1f, 0f,
50.0f, 25.0f, 1f, .5f,
0.0f, 50.0f, 0f, 1f,
};
。
// vertices
GL.GenBuffers(1, out verticesHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, verticesHandle);
GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
// vertices: vertex_position
GL.EnableVertexAttribArray(0);
GL.BindAttribLocation(program, 0, "vertex_position");
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, sizeof(float)*4, 0);
// vertices: texture_uv
GL.EnableVertexAttribArray(1);
GL.BindAttribLocation(program, 1, "in_texture_uv");
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float)*4, sizeof(float) * 2);
质地:
你的主要问题是最有可能是您的BindAttribLocation()
通话来得晚:
GL.BindAttribLocation(program, 0, "vertex_position");
...
GL.BindAttribLocation(program, 1, "in_texture_uv");
我们没有看到你在哪里以及如何构建着色器程序,但是基于上下文,我怀疑你已经在此时构建了着色器程序。在连接着色器程序之前,您需要调用BindAttribLocation()
调用。否则这些位置将不会生效。
如果将着色器版本增加到330
还可以,则还可以使用layout (location=...)
指令在着色器代码本身中指定顶点着色器输入的位置。
非常感谢,你解决了一个让我的头痛一整天的问题! –
请注意,即使着色器版本为“150”,某些平台(即OSX)也具有'GL_ARB_explicit_attrib_location'扩展名,以便您可以使用'layout(location = ...) –
需要一个比我在评论更多的空间......
假设GL.Viewport
实际上是glViewport
的包装,然后
GL.Viewport(-Width, -Height, Width*2, Height*2)
没有什么意义,因为它会将3/4视口带到窗口外部。 只需通过(0, 0, width, height)
即可在整个窗口上绘画,0,0位于左下角。如果要限制GL输出到窗口的子集,请相应地调整参数。
技术上,glViewport定义标准化设备坐标到窗口坐标转化为X和Y,了解OpenGL的空间是很重要的。花点时间吧。
刚才说过,顶点着色器的输出也很奇怪。如果你想与你的polygon¹以“填补你的窗口”,你不需要做怪
vertex_position/viewport_size
师在你的顶点着色器。
请记住,在剪辑中的顶点着色器输出坐标,在这之后的OpenGL带来规格化设备坐标的通过将X坐标,Y,Z由W.归一化装置在所有三个坐标范围从-1到1尺寸。只落在这个2x2x2立方体内的点将被实际光栅化。
还记得我说的关于glViewport
?
那么,有什么诀窍?只需输出W = 1的坐标,以便它们已经在NDC中有效。所以,如果你想有一个四边形在由GL绘制你的窗口的整个区域跨越,只是建立类似
float coords[] = { -1, -1,
1, -1,
1, 1,
-1, 1 };
或者,根据您的原代码,如果你想有一个梯形,使用类似
float coords[] = { -1, -1,
1, -1,
1, 0,
-1, 1 };
然后通过顶点着色器将它们传递:
in vec2 position;
void main() {
gl_Position = vec4(position, 0, 1);
}
结果:
¹请,请即是GL_TRIANGLE_FAN
,而不是一个GL_QUAD
也不是GL_POLYGON
'假设GL.Viewport实际上是glViewport的包装器是的,我使用托管代码,但是包装是直接的。 我正在使用这些数字,因为我来自喜欢整数而不是浮动的软件图形界面,而且我实际上只希望该图像只有50px宽。 我会将这些计算委托给GPU,并避免无效的'uniform vec2 viewport_size;'然后。 感谢您的好解释! –
我不认为这应该是问题,但你应该避免混合'变化'/'属性'(_deprecated_)和'in' /'出' –
好吧,我只是试图用“出“在顶点着色器中,并在片段着色器中使用”in“。 没有变化。 –
你想用'vertex_position/viewport_size'完成什么?这不是转换为窗口空间的正确方法。 –