C 渲染为1D纹理

C 渲染为1D纹理,c,opengl,glsl,shader,C,Opengl,Glsl,Shader,我正在尝试几种方法来实现一个简单的粒子系统。 在这里,我在几个纹理之间使用乒乓球技术,所有纹理都连接到一个独特的fbo 我认为所有的绑定/设置都是正确的,因为我看到它使用来自A纹理的数据写入B纹理 问题是B纹理中只有一个纹理被写入: 在这张图像中,我尝试将纹理从源纹理复制到目标纹理 让我们来看看代码: 设置代码 片段着色器 当我使用1D纹理时,我认为我需要发送的唯一数据是一个索引,我可以完美地使用gl_VertexID。这就是为什么我要发送0个属性数据 我认为问题在于我设置gl_FragCoo

我正在尝试几种方法来实现一个简单的粒子系统。 在这里,我在几个纹理之间使用乒乓球技术,所有纹理都连接到一个独特的fbo

我认为所有的绑定/设置都是正确的,因为我看到它使用来自A纹理的数据写入B纹理

问题是B纹理中只有一个纹理被写入:

在这张图像中,我尝试将纹理从源纹理复制到目标纹理

让我们来看看代码:

设置代码 片段着色器 当我使用1D纹理时,我认为我需要发送的唯一数据是一个索引,我可以完美地使用gl_VertexID。这就是为什么我要发送0个属性数据


我认为问题在于我设置gl_FragCoord的方式(遗憾的是,这是我唯一无法调试的变量:()问题在于如何调用着色器。基本上,您已经设置了一个标准的GPGPU片段着色器管道,处理输入纹理的每个纹理,并将结果写入输出纹理中相应的纹理。但是,您调用此GPGPU管道的方式,即渲染几何体的方式,完全是垃圾。所有其他的凝灰岩,尤其是你的碎片着色器和你使用
gl\u FragCoord
的方式是完全正确的

似乎将计算过程(要计算粒子位置的地方)与绘图过程(要渲染粒子的地方,可能是作为点)混淆了。但是在这个GPGPU阶段,绝对不需要渲染N个点,因为你在顶点着色器中没有做任何有用的事情。你只需要为帧缓冲区的每个像素生成一个片段。但是光栅化器已经为你实现了这一点。当你想在“法线”中绘制三角形时在图形应用程序中,您也不会自己将三角形细分为像素,并将其绘制为
GL_点
。失败的确切原因是您奇怪地使用
GL_顶点ID
作为坐标。由于您不使用任何变换,输出顶点坐标应位于[-1,1]-框中,其他所有点都会被剪裁掉。但您的点位于(0,0)、(1,0)、(2,0)位置,因此它们不会密集地覆盖帧缓冲区,只会绘制(0,0)处的点,这正是您看到的中心像素(由于舍入等原因,(1,0)处的点可能也会被剪裁掉)

所以你要做的就是画一个覆盖整个帧缓冲区的四边形。这意味着在没有任何变换的情况下,它应该覆盖整个剪辑空间,从而覆盖[-1,1]-正方形(事实上,当使用一个只有一个像素高的帧缓冲区时,一条线甚至可以)。然后,光栅化器生成您需要的所有片段。您仍然可以在不使用任何属性的情况下通过渲染单个四边形(不激活任何属性)来实现这一点:

然后使用顶点ID选择四边形的适当角点:

const vec2 corners[4] = { 
    vec2(-1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, 1.0), vec2(1.0, -1.0) };

void main()
{
    gl_Position = vec4(corners[gl_VertexID], 0.0, 1.0);   
}
然后,这将为每个像素生成一个片段,其他一切都会正常工作


顺便说一句,我不确定您是否真的想要1D纹理,因为与缓冲区相比,1D纹理具有相当严格的大小限制。您可以只使用2D纹理,这不会改变当前处理中的任何内容(尽管在实际绘制粒子时可能需要一些索引魔法)


事实上,当您已经使用OpenGL 4.3时,执行GPGPU任务(如粒子引擎)的更自然的方法是a。这样,您可以将粒子数据存储在缓冲区对象中,并直接使用计算着色器处理这些对象,而无需将其打包到纹理中(因为您可能希望稍后渲染它们,因此需要在顶点着色器中读取纹理),而无需滥用图形管道来执行计算任务,也无需任何乒乓球存储(只需在适当的缓冲区上工作).

问题是,我之前使用的粒子系统版本使用的是制服阵列、ubo、ssbo,其中您明确指出了要在哪里写入数据。但对于纹理,您需要使用顶点处理阶段的输出,正如您所解释的,由于剪裁,这是完全错误的。是的,我计划这样做也可以尝试计算着色器:)
static int pingpong = 1;

glUseProgram(integratorShader);
glBindVertexArray(0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

// Set the input textures to be the "a" textures
int i;
for (i = 0 ; i < 3 ; i++ )
{
    glActiveTexture(GL_TEXTURE0 + i);
    glBindTexture(GL_TEXTURE_1D, tex_a[i]);
}

// Set the draw buffers to be the "b" textures attachments
glDrawBuffers(3, GL_COLOR_ATTACHMENT0 + (pingpong * 3) );

glViewport(0, 0, NB_PARTICLE, 1);

glDrawArrays(GL_POINTS, 0, NB_PARTICLE);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glUseProgram(0);

// A became B and B became A
swapArray(tex_a, tex_b, 3);
pingpong++;
pingpong %= 2;
#version 430

void main() {

    gl_Position = vec4(gl_VertexID, 0, 0, 1);

}
#version 430

// binding = texture unit
layout (binding = 0) uniform sampler1D position_texture;
layout (binding = 1) uniform sampler1D vitesse_texture;
layout (binding = 2) uniform sampler1D couleur_texture;

// location = index in the "drawBuffers" array
layout (location = 0) out vec4 position_texel;
layout (location = 1) out vec4 vitesse_texel;
layout (location = 2) out vec4 couleur_texel;

void main() {

    vec4 old_position_texel = texelFetch(position_texture, int(gl_FragCoord.x), 0);
    vec4 old_vitesse_texel =  texelFetch(vitesse_texture, int(gl_FragCoord.x), 0);
    vec4 old_couleur_texel =  texelFetch(couleur_texture, int(gl_FragCoord.x), 0);

    position_texel = old_position_texel;
    vitesse_texel = old_vitesse_texel;
    couleur_texel = old_couleur_texel;
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
const vec2 corners[4] = { 
    vec2(-1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, 1.0), vec2(1.0, -1.0) };

void main()
{
    gl_Position = vec4(corners[gl_VertexID], 0.0, 1.0);   
}