Salut, j'essaye de comprendre les opérations atomique avec l'opengl moderne, cependant j'ai quelque soucis.

Je voudrais faire une per-pixel-linked-list, donc j'ai penser à faire ceci :

Dans le code c++, je dessine d'abord sur tout l'écran pour initialiser mes images avant de dessiner mes objets, j'en ai 3 :

-Une première image en 2D dans laquelle j'écris le nombre de fragments.
-Une seconde image en 3D dans laquelle j'écris la profondeur de chaque fragments.
-Et la dernière dans laquelle j'écris la couleur de chaque fragments.

Pour chaque positions en x et y à l'écran j'ai donc la couleur, la profondeur de tout les fragments, ainsi que le nombre de fragment qui se superposent.

Ce qui donne le code source suivant :
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
 
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <glew.h>
#include <vector>
// Include GLFW
#include <GLFW/glfw3.h>
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
 
    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
 
    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if(VertexShaderStream.is_open())
    {
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    }
 
    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    }
 
    GLint Result = GL_FALSE;
    int InfoLogLength;
 
    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);
 
    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
 
    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);
 
    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
 
    // Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);
 
    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
 
    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);
 
    return ProgramID;
}
GLFWwindow* window;
 
int main( void )
{
	// Initialise GLFW
	if( !glfwInit() )
	{
		fprintf( stderr, "Failed to initialize GLFW\n" );
		return -1;
	}
 
	glfwWindowHint(GLFW_SAMPLES, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 
	// Open a window and create its OpenGL context
	window = glfwCreateWindow( 1024, 768, "Tutorial 01", NULL, NULL);
	if( window == NULL ){
		fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) {
		fprintf(stderr, "Failed to initialize GLEW\n");
		return -1;
	}
	GLuint abufferTexID, abufferCounterTexID, adepthbufferTexID;
	glGenTextures(1, &abufferTexID);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, 1024, 768, 16, 0,  GL_RGBA, GL_FLOAT, 0);
    glBindImageTextureEXT(0, abufferTexID, 0, true, 0,  GL_READ_WRITE, GL_RGBA32F);
    glGenTextures(1, &abufferCounterTexID);
    glBindTexture(GL_TEXTURE_2D, abufferCounterTexID);
 
    // Set filter
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
    //Texture creation
    //Uses GL_R32F instead of GL_R32I that is not working in R257.15
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1024, 768, 0,  GL_RED, GL_FLOAT, 0);
    glBindImageTextureEXT(1, abufferCounterTexID, 0, false, 0,  GL_READ_WRITE, GL_R32UI);
    glGenTextures(1, &adepthbufferTexID);
    glBindTexture(GL_TEXTURE_2D, adepthbufferTexID);
 
    // Set filter
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
    //Texture creation
    //Uses GL_R32F instead of GL_R32I that is not working in R257.15
    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 1024, 768, 16, 0,  GL_RED, GL_FLOAT, 0);
    glBindImageTextureEXT(1, adepthbufferTexID, 0, true, 0,  GL_READ_WRITE, GL_R32F);
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
    // An array of 3 vectors which represents 3 vertices
    static const GLfloat g_vertex_buffer_data2[] = {
       -1.0f, -1.f, 0.f,
       1.f, -1.f, 0.f,
       1.f, 1.f, 0.f,
       -1.f, 1.f, 0.f
    };
    static const GLfloat g_vertex_buffer_data[] = {
       -1.0f, -1.0f, 0.0f,
       1.0f, -1.0f, 0.0f,
       0.0f,  1.0f, 0.0f,
    };
    // This will identify our vertex buffer
    GLuint vertexbuffer, vertexbuffer2;
 
    // Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &vertexbuffer);
 
    // The following commands will talk about our 'vertexbuffer' buffer
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
 
    // Give our vertices to OpenGL.
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
    glGenBuffers(1, &vertexbuffer2);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data2), g_vertex_buffer_data2, GL_STATIC_DRAW);
    // Create and compile our GLSL program from the shaders
    GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
    GLuint programID2 = LoadShaders("SimpleVertexShader.vertexshader","ClearABuffer.fragmentshader");
    GLuint abufferLocation = glGetUniformLocation(programID, "abufferImg");
    GLuint abufferCounterLocation = glGetUniformLocation(programID, "abufferCounterImg");
    GLuint adepthbufferLocation = glGetUniformLocation(programID, "adepthbufferImg");
    GLuint abufferLocation2 = glGetUniformLocation(programID2, "abufferImg");
    GLuint abufferCounterLocation2 = glGetUniformLocation(programID2, "abufferCounterImg");
    GLuint adepthbufferLocation2 = glGetUniformLocation(programID2, "adepthbufferImg");
	// Initialize GLEW
 
 
	// Ensure we can capture the escape key being pressed below
	glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
 
	// Dark blue background
	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
 
	do{
 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(
           0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
           3,                  // size
           GL_FLOAT,           // type
           GL_FALSE,           // normalized?
           0,                  // stride
           (void*)0            // array buffer offset
        );
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
        glUseProgram(programID2);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
 
        glUseProgram(programID);
        // Draw the triangle !
        glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
 
        glDisableVertexAttribArray(0);
		glfwSwapBuffers(window);
		glfwPollEvents();
 
	} // Check if the ESC key was pressed or the window was closed
	while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
		   glfwWindowShouldClose(window) == 0 );
 
	// Close OpenGL window and terminate GLFW
	glfwTerminate();
 
	return 0;
}

Là je veux simplement dessiner un triangle rouge sur fond bleu.

Au niveau du code source pour le vertex shader, rien de bien compliqué :

SimpleVertexShader.vertexshader

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
 
#version 420 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main() {
	gl_Position.xyz = vertexPosition_modelspace;
        gl_Position.w = 1.0;
}
Au niveau du fragment shader j'ai deux codes, le premier pour effacer mes images :

ClearABuffer.fragmentshader

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
#version 420 core
#extension GL_EXT_shader_image_load_store : enable
uniform layout(size1x32) uimage2D abufferCounterImg;
uniform layout(size1x32) image2DArray adepthbufferImg;
uniform layout(size4x32) image2DArray abufferImg;
void main() {
	ivec2 coords = ivec2(gl_FragCoord.xy);
        imageStore(abufferCounterImg, coords, ivec4(0, 0, 0, 0));
	for (int i = 0; i < 16; i++) {
	     imageStore(adepthbufferImg, ivec3(coords, i), vec4(0, 0, 0, 0));
	     imageStore(abufferImg, ivec3(coords, i), vec4(0, 0, 0, 0));
	}
	discard;
}
Et le second pour trier les fragments et appliquer le blending alpha.

SimpleFragmentShader.fragmentshader

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
#version 420 core
#extension GL_EXT_shader_image_load_store : enable
uniform layout(size1x32) uimage2D abufferCounterImg;
uniform layout(size1x32) image2DArray adepthbufferImg;
uniform layout(size4x32) image2DArray abufferImg;
out vec4 color;
vec4 backgroundColor = vec4(0, 0, 0, 1);
void main() {	
	ivec2 coords = ivec2 (gl_FragCoord.xy);
        float z = gl_FragCoord.z;
        int nbFrag = int(imageLoad(abufferCounterImg, coords).r);
        int fragPos = 0;        
        while (fragPos < nbFrag && z >= imageLoad(adepthbufferImg, ivec3(coords, fragPos)).r)
		fragPos++;
	int i = nbFrag;
	while(i > fragPos) {
		float adepthbuffervalue = imageLoad(adepthbufferImg, ivec3(coords, i-1)).r;
		vec4 abuffervalue = imageLoad(abufferImg, ivec3(coords, i-1));
		imageStore(adepthbufferImg, ivec3(coords, i), vec4(adepthbuffervalue, 0, 0, 0));
		imageStore(abufferImg, ivec3(coords, i), abuffervalue);		
		i--;
	}	
	imageStore(adepthbufferImg, ivec3(coords, fragPos), vec4(z, 0, 0, 0)); 
    	imageStore(abufferImg, ivec3(coords, fragPos), vec4(1, 0, 0, 1));
	nbFrag++;
	imageStore(abufferCounterImg, coords, ivec4(nbFrag, 0, 0, 0));
	vec4 finalColor = backgroundColor;
	for (i = 0; i < nbFrag; i++) {
            vec4 currentColor = imageLoad(abufferImg, ivec3(coords, i));
            finalColor = currentColor * currentColor.a + finalColor * (1 - currentColor.a);
	}
	color = finalColor;
}
Le problème c'est que la couleur stockée dans mon image 3D abuffer reste noire, et pas rouge comme elle devrait l'être.

Et je ne comprends absolument pas pourquoi.

Merci d'avance pour votre aide.