Opengl GLSL如何使用几何体着色器显示法线?

Opengl GLSL如何使用几何体着色器显示法线?,opengl,glsl,geometry-shader,Opengl,Glsl,Geometry Shader,我有顶点着色器 和片段着色器 它将索引的GL_三角形_条作为输入 代码按预期工作,但我不确定我的法线是否正确排列:它们存储为字节,在b/FF时转换为GLfloat,坐标xyz发生变化,有些可能需要求反 有人能给我看一下几何体着色器以线的形式显示法线吗?这些着色器根本不起作用,而且它似乎在顶点和片段着色器之间丢失了输出/输入数据 另外,我不确定我是否在启动OpenGL和GLSL时做了所有正确的事情,所以任何建议都非常感谢 编辑: 我通过示例制作了简单的几何体着色器 // This is a ver

我有顶点着色器

和片段着色器

它将索引的GL_三角形_条作为输入

代码按预期工作,但我不确定我的法线是否正确排列:它们存储为字节,在b/FF时转换为GLfloat,坐标xyz发生变化,有些可能需要求反

有人能给我看一下几何体着色器以线的形式显示法线吗?这些着色器根本不起作用,而且它似乎在顶点和片段着色器之间丢失了输出/输入数据

另外,我不确定我是否在启动OpenGL和GLSL时做了所有正确的事情,所以任何建议都非常感谢

编辑: 我通过示例制作了简单的几何体着色器

// This is a very simple pass-through geometry shader
#version 330 core

layout (triangles) in;
layout (triangle_strip, max_vertices = 145) out;

in VS_GS_VERTEX
{
    vec2 UV;
    vec3 vs_worldpos;
    vec3 vs_normal;
} vertex_in[];

out GS_FS_VERTEX
{
    vec2 UV;
    vec3 vs_worldpos;
    vec3 vs_normal;
} vertex_out;

uniform float uNormalsLength = 0.5;

void main()
{
    int i;
    // Loop over the input vertices
    for (i = 0; i < gl_in.length(); i++)
    {
        vertex_out.UV = vertex_in[i].UV;
        vertex_out.vs_worldpos = vertex_in[i].vs_worldpos;
        vertex_out.vs_normal = vertex_in[i].vs_normal;

        // Copy the input position to the output
        gl_Position = gl_PositionIn[i];
        EmitVertex();

        gl_Position = gl_ModelViewProjectionMatrix * (gl_PositionIn[i] + (vec4(vertex_in[i].vs_normal, 0) * uNormalsLength));
        gl_FrontColor = vec4(0.0, 0.0, 0.0, 1.0); //gl_FrontColorIn[i];
        EmitVertex();      
    }
    // End the primitive. This is not strictly necessary
    // and is only here for illustrative purposes.
    EndPrimitive();
}
但我不知道gl_ModelViewProjectionMatrix在哪里被使用,结果看起来很糟糕,似乎所有东西都被去除了,包括法线。图片在GLPOLYGONMODEGLU前,GLU线模式,纹理也试图映射到这些。

看起来,您在一次传递中完成了所有操作,实际上每个传入三角形发射6个顶点。这不是你想要的

分两次进行,即一次用于网格,另一次用于法线,或者尝试发射原始三角形和法线的退化三角形。为简单起见,我选择双通道版本:

在渲染循环中:

渲染地形 当且仅当要渲染调试几何体时 启用调试法线着色器 再次渲染地形网格,将点传递给顶点着色器 要实现这一点,您将需要第二个程序对象,该对象与之前链接到的博客文章中的内容类似,由一个简单的通过顶点着色器、以下几何体着色器和一个片段着色器组成,用于为表示法线的线着色

顶点和片段着色器应该没有问题。假设您有一个平滑的网格,即您有实际的平均顶点法线,您可以简单地传入点并发射线

#version 330 core

// assuming you have vertex normals, you need to render a vertex
// only a single time. with any other prim type, you may render
// the same normal multiple times
layout (points) in; 

// Geometry shaders can only output points, line strips or triangle
// strips by definition. you output a single line per vertex. therefore, 
// the maximum number of vertices per line_strip is 2. This is effectively
// the same as rendering distinct line segments.
layout (line_strip, max_vertices = 2) out;

in      vec3  vs_normal[];
uniform float normal_scale = 0.5; // don't forget: this is the default value! 

/* if you're never going to change the normal_scale, consider simply putting a 
  constant there instead:
  const float normal_scale = 0.5;
*/

void main()
{
    // we simply transform and emit the incoming vertex - this is v0 of our
    // line segment
    vec4 v0     = gl_in[0].gl_Position;
    gl_Position = gl_ModelViewProjectionMatrix * v0;
    EmitVertex();

    // we calculate v1 of our line segment
    vec4 v1     = v0 + vec4(vs_normal[0] * normal_scale, 0);
    gl_Position = gl_ModelViewProjectionMatrix * v1;
    EmitVertex();

    EndPrimitive();
}
警告:未测试的代码

这可能是最简单的。向片段着色器添加统一的颜色,以便可以根据需要为法线着色,或仅导出恒定的颜色

注意:此代码仍然使用gl_ModevelViewProjectionMatrix。如果您正在编写GL核心代码,请考虑用您自己的东西替换传统的GL构造,比如矩阵堆栈!p>
注2:您的几何体着色器不是通常所指的通过着色器。首先,您对传入数据进行处理,而不仅仅是将传入值分配给传出值。第二,如果生成几何体,它如何成为穿透着色器?“传递”意味着,除了将传入值传递到下一个着色器阶段之外,您不做任何其他事情。

看起来,您在一次传递中完成了所有操作,并且每个传入三角形实际上发射6个顶点。这不是你想要的

分两次进行,即一次用于网格,另一次用于法线,或者尝试发射原始三角形和法线的退化三角形。为简单起见,我选择双通道版本:

在渲染循环中:

渲染地形 当且仅当要渲染调试几何体时 启用调试法线着色器 再次渲染地形网格,将点传递给顶点着色器 要实现这一点,您将需要第二个程序对象,该对象与之前链接到的博客文章中的内容类似,由一个简单的通过顶点着色器、以下几何体着色器和一个片段着色器组成,用于为表示法线的线着色

顶点和片段着色器应该没有问题。假设您有一个平滑的网格,即您有实际的平均顶点法线,您可以简单地传入点并发射线

#version 330 core

// assuming you have vertex normals, you need to render a vertex
// only a single time. with any other prim type, you may render
// the same normal multiple times
layout (points) in; 

// Geometry shaders can only output points, line strips or triangle
// strips by definition. you output a single line per vertex. therefore, 
// the maximum number of vertices per line_strip is 2. This is effectively
// the same as rendering distinct line segments.
layout (line_strip, max_vertices = 2) out;

in      vec3  vs_normal[];
uniform float normal_scale = 0.5; // don't forget: this is the default value! 

/* if you're never going to change the normal_scale, consider simply putting a 
  constant there instead:
  const float normal_scale = 0.5;
*/

void main()
{
    // we simply transform and emit the incoming vertex - this is v0 of our
    // line segment
    vec4 v0     = gl_in[0].gl_Position;
    gl_Position = gl_ModelViewProjectionMatrix * v0;
    EmitVertex();

    // we calculate v1 of our line segment
    vec4 v1     = v0 + vec4(vs_normal[0] * normal_scale, 0);
    gl_Position = gl_ModelViewProjectionMatrix * v1;
    EmitVertex();

    EndPrimitive();
}
警告:未测试的代码

这可能是最简单的。向片段着色器添加统一的颜色,以便可以根据需要为法线着色,或仅导出恒定的颜色

注意:此代码仍然使用gl_ModevelViewProjectionMatrix。如果您正在编写GL核心代码,请考虑用您自己的东西替换传统的GL构造,比如矩阵堆栈!p>
注2:您的几何体着色器不是通常所指的通过着色器。首先,您对传入数据进行处理,而不仅仅是将传入值分配给传出值。第二,如果生成几何体,它如何成为穿透着色器?“传递”意味着,除了将传入值传递到下一个着色器阶段之外,您不做任何事情。

为什么该代码不起作用?这非常简单。它将法线从应用程序传递到顶点着色器,并将法线传递到geomerty着色器。在GS中,它仅使用顶点位置和偏移顶点位置生成线段,即顶点位置沿顶点法线平移一定距离,这两个位置都使用MVP矩阵进行变换。就这样。我想不出如何为它制作几何体着色器。我在哪里做了简单的穿越
我将vs中的参数输出为in,将它们输出为out,但没有显示任何没有错误的编译。要弄清楚什么?几何体着色器代码就在链接的页面上。您可以将其调整到GLSL 330,而不会出现任何问题。先试试这个,然后再回答更具体的问题。或者你根本不确定几何体着色器是如何工作的?当然,我不确定每件事情是如何工作的,因为我已经学习OpenGL几个月了。在Hello world之间的所有东西,过时的和不推荐的。每一个建议,如它是简单的,通过XXX没有例子或例子与glBegin和着色器v130。到目前为止,我会改变,但结果很糟糕。为什么代码不起作用?这非常简单。它将法线从应用程序传递到顶点着色器,并将法线传递到geomerty着色器。在GS中,它仅使用顶点位置和偏移顶点位置生成线段,即顶点位置沿顶点法线平移一定距离,这两个位置都使用MVP矩阵进行变换。就这样。我想不出如何为它制作几何体着色器。我做了一个简单的passthrough,在这里我把vs中的参数作为in输出,把它们作为out输出,但是没有显示任何没有错误的编译?几何体着色器代码就在链接的页面上。您可以将其调整到GLSL 330,而不会出现任何问题。先试试这个,然后再回答更具体的问题。或者你根本不确定几何体着色器是如何工作的?当然,我不确定每件事情是如何工作的,因为我已经学习OpenGL几个月了。在Hello world之间的所有东西,过时的和不推荐的。每一个建议,如它是简单的,通过XXX没有例子或例子与glBegin和着色器v130。到目前为止,我会改变,但结果很糟糕。谢谢你详细的回答!静读。不确定,如果你正在编写GL核心代码,请考虑替换传统的GL构建,以及从GLYMoDeVIEWVIEW投影矩阵等等。我正在学习Addison Wesley - OpenGL程序指南第八版,并以实例为核心。但我现在似乎更了解这个想法以及它是如何工作的。红皮书的第8版使用了内置的兼容性?请看,背景是,如果您真正使用的是核心上下文,则没有内置变量gl_ModelViewProjectionMatrix,因为它只提供了位于投影和MODELVIEW堆栈MVP=P*VM顶部的矩阵的乘积。如果你有一个兼容性上下文,这个东西仍然可用。如果要确保只编写核心代码,请设置核心概要文件上下文。你使用什么样的窗口工具包?我制作纯Delphi+OpenGL项目,只使用dglOpenGL来研究什么是OpenGL。魔兽世界MPQ的顶点和其他东西。现在在地形部分。除了红皮书之外,请阅读杰森·麦凯森的教程:我知道事实上你在那里有很好的人手;此外,OpenGL Wiki有大量的信息,主要由同一作者和其他人编写:感谢您的详细回答!静读。不确定,如果你正在编写GL核心代码,请考虑替换传统的GL构建,以及从GLYMoDeVIEWVIEW投影矩阵等等。我正在学习Addison Wesley - OpenGL程序指南第八版,并以实例为核心。但我现在似乎更了解这个想法以及它是如何工作的。红皮书的第8版使用了内置的兼容性?请看,背景是,如果您真正使用的是核心上下文,则没有内置变量gl_ModelViewProjectionMatrix,因为它只提供了位于投影和MODELVIEW堆栈MVP=P*VM顶部的矩阵的乘积。如果你有一个兼容性上下文,这个东西仍然可用。如果要确保只编写核心代码,请设置核心概要文件上下文。你使用什么样的窗口工具包?我制作纯Delphi+OpenGL项目,只使用dglOpenGL来研究什么是OpenGL。魔兽世界MPQ的顶点和其他东西。现在在地形部分。除了红皮书之外,请阅读杰森·麦凯森的教程:我知道事实上你在那里有很好的人手;此外,OpenGL Wiki包含大量信息,主要由同一作者和其他一些人编写:
// This is a very simple pass-through geometry shader
#version 330 core

layout (triangles) in;
layout (triangle_strip, max_vertices = 145) out;

in VS_GS_VERTEX
{
    vec2 UV;
    vec3 vs_worldpos;
    vec3 vs_normal;
} vertex_in[];

out GS_FS_VERTEX
{
    vec2 UV;
    vec3 vs_worldpos;
    vec3 vs_normal;
} vertex_out;

uniform float uNormalsLength = 0.5;

void main()
{
    int i;
    // Loop over the input vertices
    for (i = 0; i < gl_in.length(); i++)
    {
        vertex_out.UV = vertex_in[i].UV;
        vertex_out.vs_worldpos = vertex_in[i].vs_worldpos;
        vertex_out.vs_normal = vertex_in[i].vs_normal;

        // Copy the input position to the output
        gl_Position = gl_PositionIn[i];
        EmitVertex();

        gl_Position = gl_ModelViewProjectionMatrix * (gl_PositionIn[i] + (vec4(vertex_in[i].vs_normal, 0) * uNormalsLength));
        gl_FrontColor = vec4(0.0, 0.0, 0.0, 1.0); //gl_FrontColorIn[i];
        EmitVertex();      
    }
    // End the primitive. This is not strictly necessary
    // and is only here for illustrative purposes.
    EndPrimitive();
}
#version 330 core

// assuming you have vertex normals, you need to render a vertex
// only a single time. with any other prim type, you may render
// the same normal multiple times
layout (points) in; 

// Geometry shaders can only output points, line strips or triangle
// strips by definition. you output a single line per vertex. therefore, 
// the maximum number of vertices per line_strip is 2. This is effectively
// the same as rendering distinct line segments.
layout (line_strip, max_vertices = 2) out;

in      vec3  vs_normal[];
uniform float normal_scale = 0.5; // don't forget: this is the default value! 

/* if you're never going to change the normal_scale, consider simply putting a 
  constant there instead:
  const float normal_scale = 0.5;
*/

void main()
{
    // we simply transform and emit the incoming vertex - this is v0 of our
    // line segment
    vec4 v0     = gl_in[0].gl_Position;
    gl_Position = gl_ModelViewProjectionMatrix * v0;
    EmitVertex();

    // we calculate v1 of our line segment
    vec4 v1     = v0 + vec4(vs_normal[0] * normal_scale, 0);
    gl_Position = gl_ModelViewProjectionMatrix * v1;
    EmitVertex();

    EndPrimitive();
}