使用几何着色器实现裁剪平面?
Implementing clip planes with geometry shaders?
我在用什么: Qt 5.11.1,MinGW 5.3,Windows 10,C++11,GPU:NVidia 820M(支持 OpenGL 4.5)
我的任务: 我有非实体(只是表面)对象,由 glDrawArrays 渲染,我需要按平面获取该对象的横截面。我发现了古老的 openGL 函数 glClipPlane,但它与 VAO 和 VBO 不兼容。我还发现可以通过几何着色器重写 glClipPlane。
我的questions/problems:
你知道其他实现这个任务的方法吗?
我真的不明白,如何在QtCreator中添加几何着色器,没有"icon"几何着色器,我尝试添加顶点着色器并将其重命名为.gsh或只是。 glsl,尝试使用 QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source)
并在程序中编写着色器代码,但每次我在添加几何着色器的字符串上得到 "QOpenGLShader: could not create shader"。
将着色器添加到程序中的外观
顶点着色器:
layout (triangles) in;
layout (triangles) out;
layout (max_vertices = 3) out;
void main()
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
几何着色器:
layout (triangles) in;
layout (triangles) out;
layout (max_vertices = 3) out;
void main()
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
片段着色器:
precision mediump float;
uniform highp float u_lightPower;
uniform sampler2D u_texture;
uniform highp mat4 u_viewMatrix;
varying highp vec4 v_position;
varying highp vec2 v_texCoord;
varying highp vec3 v_normal;
void main(void)
{
vec4 resultColor = vec4(0.25, 0.25, 0.25, 0.0);
vec4 diffMatColor = texture2D(u_texture, v_texCoord);
vec3 eyePosition = vec3(u_viewMatrix);
vec3 eyeVect = normalize(v_position.xyz - eyePosition);
float dist = length(v_position.xyz - eyePosition);
vec3 reflectLight = normalize(reflect(eyeVect, v_normal));
float specularFactor = 1.0;
float ambientFactor = 0.05;
vec4 diffColor = diffMatColor * u_lightPower * dot(v_normal, -eyeVect);// * (1.0 + 0.25 * dist * dist);
resultColor += diffColor;
gl_FragColor = resultColor;
}
先理清几个误区:
have found ancient openGL function glClipPlane
, but its not compability with VAOs and VBOs.
这是不正确的。用户通过 glClipPlane
定义的裁剪平面在现代 GL 中确实已弃用,并已从核心配置文件中删除。但是,如果您使用它们仍然存在的上下文,则可以毫无问题地将它们与 VAO 和 VBO 结合使用。
Also Ive found out that its possible to rewrite glClipPlane
via geometry shader.
自定义裁剪平面不需要几何着色器。
用户定义裁剪平面的现代方法是为每个顶点计算 gl_ClipDistance
。虽然您可以在几何着色器中修改此值,但您也可以直接在顶点着色器中生成它。如果您不需要几何着色器,绝对没有理由只为裁剪平面添加它。
I really dont understand, how to add geometry shader in QtCreator, there is no "icon" of geometry shader, I tried to add vertex shader and rename it to .gsh or just .glsl, tried to use OpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source)
and write shader code in program, but every time I get "QOpenGLShader: could not create shader" on string with adding geometry shader.
您首先需要找出您实际使用的 OpenGL 版本。使用 Qt,您可以轻松地以 OpenGLES 2.0 上下文结束(取决于您如何创建上下文,以及您的 Qt 是如何编译的)。您的着色器代码是桌面 GL 2.x (GLSL 1.10/1.20) 或 GLES 2.0 (GLSL 1.00ES),但在 OpenGL 的现代核心配置文件中无效。
GLES2 完全不支持几何着色器。它也不支持gl_ClipDistance
,所以如果你_really) 必须使用GLES2,你可以尝试emulate the clipping in the fragment shader。但更好的选择是切换到现代核心配置文件 GL 上下文。
虽然 glClipPlane
在现代 OpenGL 中已被弃用,但裁剪平面的概念并未被弃用。
在您的 CPU 代码中,在开始绘制要裁剪的几何图形之前,您必须启用其中一个裁剪平面。
glEnable(GL_CLIP_DISTANCE0);
完成绘图后,您将以类似的方式禁用它。
glDisable(GL_CLIP_DISTANCE0);
您保证能够启用最少 8 个裁剪平面。
然后在您的顶点或几何着色器中,您必须告诉 OpenGL 您的顶点与平面的有符号距离,以便它知道要剪裁什么。需要说明的是,您 不需要 用于裁剪的几何着色器,但如果您愿意,可以在那里完成。着色器代码如下所示:
// vertex in world space
vec4 vert_pos_world = world_matrix * vec4(vert_pos_model, 1.0);
// a horizontal plane at a specified height with normal pointing up
// could be a uniform or hardcoded
vec4 plane = vec4(0, 1, 0, clip_height_world);
// 0 index since that's the clipping plane we enabled
gl_ClipDistance[0] = dot(vert_pos_world, plane);
我在用什么: Qt 5.11.1,MinGW 5.3,Windows 10,C++11,GPU:NVidia 820M(支持 OpenGL 4.5)
我的任务: 我有非实体(只是表面)对象,由 glDrawArrays 渲染,我需要按平面获取该对象的横截面。我发现了古老的 openGL 函数 glClipPlane,但它与 VAO 和 VBO 不兼容。我还发现可以通过几何着色器重写 glClipPlane。
我的questions/problems:
你知道其他实现这个任务的方法吗?
我真的不明白,如何在QtCreator中添加几何着色器,没有"icon"几何着色器,我尝试添加顶点着色器并将其重命名为.gsh或只是。 glsl,尝试使用
QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source)
并在程序中编写着色器代码,但每次我在添加几何着色器的字符串上得到 "QOpenGLShader: could not create shader"。
将着色器添加到程序中的外观
顶点着色器:
layout (triangles) in;
layout (triangles) out;
layout (max_vertices = 3) out;
void main()
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
几何着色器:
layout (triangles) in;
layout (triangles) out;
layout (max_vertices = 3) out;
void main()
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
片段着色器:
precision mediump float;
uniform highp float u_lightPower;
uniform sampler2D u_texture;
uniform highp mat4 u_viewMatrix;
varying highp vec4 v_position;
varying highp vec2 v_texCoord;
varying highp vec3 v_normal;
void main(void)
{
vec4 resultColor = vec4(0.25, 0.25, 0.25, 0.0);
vec4 diffMatColor = texture2D(u_texture, v_texCoord);
vec3 eyePosition = vec3(u_viewMatrix);
vec3 eyeVect = normalize(v_position.xyz - eyePosition);
float dist = length(v_position.xyz - eyePosition);
vec3 reflectLight = normalize(reflect(eyeVect, v_normal));
float specularFactor = 1.0;
float ambientFactor = 0.05;
vec4 diffColor = diffMatColor * u_lightPower * dot(v_normal, -eyeVect);// * (1.0 + 0.25 * dist * dist);
resultColor += diffColor;
gl_FragColor = resultColor;
}
先理清几个误区:
have found ancient openGL function
glClipPlane
, but its not compability with VAOs and VBOs.
这是不正确的。用户通过 glClipPlane
定义的裁剪平面在现代 GL 中确实已弃用,并已从核心配置文件中删除。但是,如果您使用它们仍然存在的上下文,则可以毫无问题地将它们与 VAO 和 VBO 结合使用。
Also Ive found out that its possible to rewrite
glClipPlane
via geometry shader.
自定义裁剪平面不需要几何着色器。
用户定义裁剪平面的现代方法是为每个顶点计算 gl_ClipDistance
。虽然您可以在几何着色器中修改此值,但您也可以直接在顶点着色器中生成它。如果您不需要几何着色器,绝对没有理由只为裁剪平面添加它。
I really dont understand, how to add geometry shader in QtCreator, there is no "icon" of geometry shader, I tried to add vertex shader and rename it to .gsh or just .glsl, tried to use
OpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source)
and write shader code in program, but every time I get "QOpenGLShader: could not create shader" on string with adding geometry shader.
您首先需要找出您实际使用的 OpenGL 版本。使用 Qt,您可以轻松地以 OpenGLES 2.0 上下文结束(取决于您如何创建上下文,以及您的 Qt 是如何编译的)。您的着色器代码是桌面 GL 2.x (GLSL 1.10/1.20) 或 GLES 2.0 (GLSL 1.00ES),但在 OpenGL 的现代核心配置文件中无效。
GLES2 完全不支持几何着色器。它也不支持gl_ClipDistance
,所以如果你_really) 必须使用GLES2,你可以尝试emulate the clipping in the fragment shader。但更好的选择是切换到现代核心配置文件 GL 上下文。
虽然 glClipPlane
在现代 OpenGL 中已被弃用,但裁剪平面的概念并未被弃用。
在您的 CPU 代码中,在开始绘制要裁剪的几何图形之前,您必须启用其中一个裁剪平面。
glEnable(GL_CLIP_DISTANCE0);
完成绘图后,您将以类似的方式禁用它。
glDisable(GL_CLIP_DISTANCE0);
您保证能够启用最少 8 个裁剪平面。
然后在您的顶点或几何着色器中,您必须告诉 OpenGL 您的顶点与平面的有符号距离,以便它知道要剪裁什么。需要说明的是,您 不需要 用于裁剪的几何着色器,但如果您愿意,可以在那里完成。着色器代码如下所示:
// vertex in world space
vec4 vert_pos_world = world_matrix * vec4(vert_pos_model, 1.0);
// a horizontal plane at a specified height with normal pointing up
// could be a uniform or hardcoded
vec4 plane = vec4(0, 1, 0, clip_height_world);
// 0 index since that's the clipping plane we enabled
gl_ClipDistance[0] = dot(vert_pos_world, plane);