IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Projets Discussion :

Nouveau moteur de jeux vidéo - présentation et recrutement.


Sujet :

Projets

  1. #461
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut
    Heu ? SFML et la SDL n'affiche pas de la 3D et tu me parles de faire un jeu en 3D ? Je ne comprend pas. Il est très difficile de débuguer quand tu ne comprends pas pourquoi, des triangles ne s'affichent pas, ou encore, le fragment shader lit de la merde. C'est comme si mon sheduler GPU était broken. Par exemple ici :

    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
    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
    #version 460
    #extension GL_ARB_separate_shader_objects : enable
    #extension GL_EXT_nonuniform_qualifier : enable
    #extension GL_EXT_debug_printf : enable
    #define NB_PRIMITIVE_TYPES 6
    #define MAX_FRAMES_IN_FLIGHT 2
    const uint MAX_TEXTURES = 1024;
    layout (push_constant) uniform PushConstant {
        layout(offset=136) int currentImageIndex;
    } pc;
    struct MaterialData {
        uint diffuseTextureIndex;
        uint specularTextureIndex;
        uint normalTextureIndex;
        uint metalnessTextureIndex;
        uint roughnessTextureIndex;
        uint aoTextureIndex;
        uint emissiveTextureIndex;
        uint materialType;
        uint taskOffset;
        uint nbVertices;
        uint nbIndexes;
        int instanceGroupId;
        uint vertsInstanceSet;
        uint materialId;
        uint nbBuffers;     
        uint opaque;
        uint pipelineType; 
    };
    layout (std430, set = 0, binding = 10) buffer MaterialDataSSBO {
        MaterialData materialData[];
    } materialDataBuffer[NB_PRIMITIVE_TYPES * MAX_FRAMES_IN_FLIGHT];
    layout(set = 0, binding = 11) uniform sampler2D diffuseTextures[MAX_TEXTURES];
    layout(set = 1, binding = 0) uniform sampler2D specularTextures[MAX_TEXTURES];
    layout(set = 2, binding = 0) uniform sampler2D normalTextures[MAX_TEXTURES];
    layout(set = 3, binding = 0) uniform sampler2D metalnessTextures[MAX_TEXTURES];
    layout(set = 4, binding = 0) uniform sampler2D roughnessTextures[MAX_TEXTURES];
    layout(set = 5, binding = 0) uniform sampler2D aoTextures[MAX_TEXTURES];
    layout(set = 6, binding = 0) uniform sampler2D emissiveTextures[MAX_TEXTURES];
    layout(location = 0) in vec4 fragColor;
    layout(location = 1) in vec2 fragTexCoord;
    layout(location = 2) in vec3 normal;
    layout(location = 3) flat in int materialID;
    layout(location = 4) flat in int primitiveType;
    layout(location = 5) flat in int currentFrame;
    layout(location = 0) out vec4 outColor;
    void main() {
        float epsilon = 0.0000001;
     
        /*if (materialID < 0 || materialID >= 7 || primitiveType != 3 || currentFrame < 0 || currentFrame >= MAX_FRAMES_IN_FLIGHT
        || fragColor.r < 1 - epsilon || fragColor.g < 1 - epsilon || fragColor.g < 1 - epsilon || fragColor.a < 1 - epsilon) {
            
            outColor = vec4(0, 0, 0, 0);
            return;
        }*/
        /*if (fragColor.r != 1 || fragColor.g != 1 || fragColor.b != 1)
        debugPrintfEXT("Flag : %i %i %i %i %v4f", flag, primitiveType, materialID, currentFrame, fragColor);*/
        //if (materialID > 6)
        //debugPrintfEXT("material id %i ", materialID);
        /*if (primitiveType > 6 || currentFrame > MAX_FRAMES_IN_FLIGHT) {
            outColor = vec4(0, 0, 0, 0);
            return;
        }*/
     
        MaterialData mat = materialDataBuffer[primitiveType * MAX_FRAMES_IN_FLIGHT+currentFrame].materialData[materialID];
     
     
        vec2 uv = vec2(fragTexCoord.x, 1-fragTexCoord.y);
     
     
        // --- Diffuse ---
        vec4 diffuse = fragColor;
        //diffuse = vec4(1, 1, 1, 1); 
        /*if (fragColor.r < 0.99 || fragColor.g < 0.99 || fragColor.b < 0.99) {
            //debugPrintfEXT("Error %v4f", fragColor);
            outColor = vec4(0, 0, 0, 0);
            return;
        }*/
        //debugPrintfEXT("material id %i, diffuse : %i", materialID, mat.diffuseTextureIndex);
        if (mat.diffuseTextureIndex > 0 && mat.diffuseTextureIndex < MAX_TEXTURES) {
     
            diffuse *= texture(diffuseTextures[mat.diffuseTextureIndex-1], uv);        
        }
        //diffuse = vec4(1, 1, 1, 1);
        // --- Normal map ---
        vec3 N = normalize(normal);
        if (mat.normalTextureIndex > 0 && mat.normalTextureIndex < MAX_TEXTURES) {
            vec3 nmap = texture(normalTextures[mat.normalTextureIndex-1], uv).xyz * 2.0 - 1.0;
            N = normalize(nmap);
        }
        // --- Specular ---
        float specularStrength = 1.0;
        if (mat.specularTextureIndex > 0 && mat.specularTextureIndex < MAX_TEXTURES) {
            //debugPrintfEXT("Specular");
            specularStrength = texture(specularTextures[mat.specularTextureIndex-1], uv).r;
        }
        // --- AO ---
        float ao = 1.0;
        if (mat.aoTextureIndex > 0 && mat.aoTextureIndex < MAX_TEXTURES) {
            //debugPrintfEXT("AO");
            ao = texture(aoTextures[mat.aoTextureIndex-1], uv).r;
        }
        // --- Emissive ---
        vec4 emissive = vec4(0.0);
        if (mat.emissiveTextureIndex > 0 && mat.emissiveTextureIndex < MAX_TEXTURES) {
            //debugPrintfEXT("Emissive");
            emissive = vec4(texture(emissiveTextures[mat.emissiveTextureIndex-1], uv).rgb, 0);
        }
        // --- Éclairage simple ---
        vec3 L = normalize(vec3(0.5, 1.0, 0.3));
        float diff = max(dot(N, L), 0.0);
        // Specular simple
        vec3 V = normalize(vec3(0,0,1));
        vec3 H = normalize(L + V);
        float spec = pow(max(dot(N, H), 0.0), 32.0) * specularStrength;
        //debugPrintfEXT("texture index : %i, normal : %v3f, fragTexCoord %v2f, color : %v4f, fragColor : %v4f", mat.diffuseTextureIndex, normal, fragTexCoord, diffuse * diff * ao + spec + emissive, fragColor);
        //debugPrintfEXT("normal : %v3f", N);
        //outColor = diffuse * diff * ao + spec + emissive;
        outColor = diffuse;
     
     
    };
    Mon fragment shader lit des données complètement aléatoire (non initialisées) en input. Hors qu'il ne faisait pas cela avant. Et pourtant quand je log mes datas dans mon mesh shader, c'est correcte :

    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
    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
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    #version 460
    #extension GL_EXT_mesh_shader : require
    #extension GL_EXT_debug_printf : enable
    #extension GL_EXT_nonuniform_qualifier : enable
    #define NB_PRIMITIVE_TYPES 6
    #define MAX_FRAMES_IN_FLIGHT 2
    #define MAX_BONES_INFLUENCE 4
    layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
     
    // Déclaration du type de primitive + limites
    layout (triangles, max_vertices = 256, max_primitives = 256) out;
    layout(location = 0) out vec4 fragColor[];
    layout(location = 1) out vec2 fragTexCoord[];
    layout(location = 2) out vec3 normal[];
    layout(location = 3) flat out int materialID[];
    layout(location = 4) flat out int primitiveType[];
    layout(location = 5) flat out int currentFrame[];
     
    struct MeshDrawCommand {
        uint groupXCount;
        uint groupYCount;
        uint groupZCount;
    };
    struct LODLevel {
        int index_offset;
        int index_count;
        int meshletOffset;
        int meshletCount;
    };
    struct TaskData {
        MeshDrawCommand meshDrawCommand;
        uint baseInstance;    
        uint vertexCount;
        uint primitiveCount;
        uint vertexOffset; 
        uint meshletOffset;     
    };
    struct AABB {
    	vec4 center;
    	vec4 size;
    };
    struct Cluster {
        AABB volume;
        int meshletOffset;
        int meshletCount;
        int id;
        int lodLevel;
        int leaf;
        int submeshId;   
    };
    struct Vertex {
        vec3 position; ///< 3D position of the vertex    
        uint color; ///< Color of the vertex
        vec2 texCoords; ///< Coordinates of the texture's pixel to map to the vertex
        vec3 normal;
        vec3 T;  
        vec3 B;    
        vec3 N;    
        int submeshId;
        //bone indexes which will influence this vertex
        int m_BoneIDs[MAX_BONES_INFLUENCE];
        //weights from each bone
        float m_Weights[MAX_BONES_INFLUENCE];
     
    };
    struct MeshLet {
        uint id;
        uint vertexOffset;
        uint indexOffset;
        uint nbVertices;
        uint nbIndexes;
        uint minVertex;
        uint maxVertex;				
        int clusterId;	
        uint lod;	
        int voxel;
        int rendered;
        int submeshId;
        vec4 mins;
        vec4 maxs;
        uint vertices[256];
        uvec4 triangles[256];
    };
    struct SubMesh {
    	AABB globalBounds;
    	int vertexOffset;
    	int indexOffset;
    	int primitiveType;
    	int materialId;
    	int nbVertices;
    	int nbIndexes;
    	int lodOffset;
    	int id;
        int lodLevel;
        int objectId; 
        int meshletOffset;
    	int meshletCount;	  
    };
     
    struct ModelData {
        mat4 modelMatrix;
        mat4 shadowProjMatrix;
        mat4 borderMatrices;
    };
    struct LodLevel {
        uint index_offset;
        uint nbLevels;
        int meshletOffset;
        int meshletCount;
    };
    struct TaskPayload {
        int taskId;
    };
    taskPayloadSharedEXT TaskPayload payload;
    layout (push_constant) uniform PushConstant {
        mat4 projMatrix;
        mat4 viewMatrix;
        int primitiveType;
        int currentFrame;
    } pc;
    layout (std430, set = 0, binding = 0) buffer TastDataSSBO {
        TaskData taskData[];
    } taskDatas[NB_PRIMITIVE_TYPES * MAX_FRAMES_IN_FLIGHT];
    layout(std430, set = 0, binding = 1) buffer TaskCountSSBO {
        uint taskCount;
    } TaskCounts[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    layout (std430, set = 0, binding = 2) buffer ModelDataSSBO {
        ModelData modelData[];
    } modelDataBuffer[NB_PRIMITIVE_TYPES * MAX_FRAMES_IN_FLIGHT];
    layout (std430, set = 0, binding = 3) buffer VisibleMeshletSSBO {
        uint meshlet[];
    } visibleMeshletDatas[MAX_FRAMES_IN_FLIGHT*NB_PRIMITIVE_TYPES];
    layout (std430, set = 0, binding = 4) buffer vertexBufferSSBO {
        Vertex vertices[];
    } vertexData[NB_PRIMITIVE_TYPES];
    layout (std430, set = 0, binding = 5) buffer indexBufferSSBO {
        uint indexes[];
    } indexData[NB_PRIMITIVE_TYPES];
    layout (std430, set=0, binding = 6) buffer LodLevelBuffer {
        LODLevel lodLevel[];
    } lodLevelData;
    layout (std430, set = 0, binding = 7) buffer SubMeshDataSSBO {
        SubMesh subMeshData[];
    } SubMeshDatas;
    layout (std430, set = 0, binding = 8) buffer MeshletsSSBO {
        MeshLet meshlet[];
    } meshletDatas;
     
    layout (std430, set = 0, binding = 9) buffer VerticesSSBO {
        Vertex vertices[];
    } outputVertices[MAX_FRAMES_IN_FLIGHT];
    vec4 unpackColor(uint c)
    {
        float r = float((c >> 24) & 0xFFu) / 255.0;
        float g = float((c >> 16) & 0xFFu) / 255.0;
        float b = float((c >>  8) & 0xFFu) / 255.0;
        float a = float((c      ) & 0xFFu) / 255.0;
     
        return vec4(r, g, b, a);
    }
    uint globalIndices[256];
    uint findLocalIndex(uint globalIndex, uint vertexCount) {
        for (uint i = 0; i < vertexCount; i++) {
     
            if (globalIndices[i] == globalIndex) {
                //debugPrintfEXT("i = %i %i", i, globalIndices[i]);
                return i;
            }
        }
        /*if (globalIndex
         == 1037)*/
            debugPrintfEXT("Erreur %i ", globalIndex);
        return 0; // ne devrait jamais arriver
    }
    void main() {      
     
        TaskData taskData = taskDatas[pc.primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].taskData[payload.taskId];
        if (pc.currentFrame >= MAX_FRAMES_IN_FLIGHT || pc.primitiveType > 3) {
            debugPrintfEXT("Current frame : %i %i", pc.currentFrame, pc.primitiveType);
        }
        /*if (taskData.vertexCount == 0)
            debugPrintfEXT("Error : %i", taskData.vertexCount);*/
        //Modèles 3D.
        if (taskData.vertexCount == 0) {  
            MeshLet meshlet = meshletDatas.meshlet[visibleMeshletDatas[pc.primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].meshlet[taskData.meshletOffset+gl_WorkGroupID.y]];
            //Cluster cluster = clusterDatas[pc.primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].clusters[taskData.clusterOffset+gl_WorkGroupID.y];         
            //if (cluster.meshletCount > 8) {
                //debugPrintfEXT("meshlet count : %i %i", cluster.submeshId, cluster.meshletOffset);
            //}
            SubMesh subMesh = SubMeshDatas.subMeshData[meshlet.submeshId];
     
            //debugPrintfEXT("Submesh material : %i, %i", subMesh.id, subMesh.materialId);
     
            /*if (gl_WorkGroupID.z >= cluster.meshletCount) {
                return;
            }*/
     
            if (meshlet.rendered == 1) { 
                //debugPrintfEXT("Rendered");           
                return;
            }
            /*if (cluster.submeshId != subMesh.id || cluster.submeshId != meshlet.submeshId || meshlet.submeshId != subMesh.id) {
                debugPrintfEXT("error submesh %i %i %i lod : %i %i %i\n", cluster.submeshId, meshlet.submeshId, subMesh.id, cluster.lodLevel, subMesh.lodOffset, meshlet.lod);
            }*/
     
            //debugPrintfEXT("mesh shader"); 
            //Instance id = taskId (base instance) + workGroupId.x (instance id).
            uint instanceId = taskDatas[pc.primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].taskData[payload.taskId].baseInstance + gl_WorkGroupID.x;
            //debugPrintfEXT("Instance id : %i", gl_WorkGroupID.x); 
            mat4 modelMatrix = modelDataBuffer[pc.primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].modelData[instanceId].modelMatrix;
            //debugPrintfEXT("model matrix : %v4f \n%v4f \n%v4f \n%v4f\n", modelMatrix[0], modelMatrix[1], modelMatrix[2], modelMatrix[3]);
     
     
     
            //Avoid to render it twice if the meshlet is between two clusters. (Deduplication)
     
            //debugPrintfEXT("mesh shader"); 
            meshletDatas.meshlet[taskData.meshletOffset+gl_WorkGroupID.y].rendered = 1;
     
            uint firstIndex = subMesh.indexOffset + lodLevelData.lodLevel[subMesh.lodOffset+meshlet.lod].index_offset + meshlet.indexOffset;
            //debugPrintfEXT("First index : %i,", firstIndex);
            //3 = Triangles.
            uint maxVerts = 256u;
            uint maxPrims = 256u;
            uint vertexCount   = meshlet.nbVertices;
            uint primitiveCount = meshlet.nbIndexes / 3u;
            /*if (primitiveCount > maxPrims)*/
                //debugPrintfEXT("vertex count : %i, primitive count : %i", vertexCount, primitiveCount);
            if (pc.primitiveType == 3) {
                SetMeshOutputsEXT(vertexCount, primitiveCount);
                for (uint i = 0; i < vertexCount; i++) {
     
                    uint globalIndex = meshlet.vertices[i];
                    /*if (globalIndex == 1037)
                        debugPrintfEXT("%i : 1037", i);*/
                    //debugPrintfEXT("global index : %i %i", i, globalIndex+1);
                    //uint v = subMesh.vertexOffset + meshlet.vertexOffset + i;                
                    uint v = subMesh.vertexOffset + globalIndex;
                    globalIndices[i] = globalIndex;
                    groupMemoryBarrier();
                    memoryBarrierBuffer();
                    barrier();  
     
                    vec4 color = unpackColor(vertexData[pc.primitiveType].vertices[v].color);
                    /*if (color.r < 0.9 || color.g < 0.9 || color.b < 0.9)
                        debugPrintfEXT("error : %v4f", color);*/
     
                    gl_MeshVerticesEXT[i].gl_Position = pc.projMatrix * pc.viewMatrix * modelMatrix * vec4(vertexData[pc.primitiveType].vertices[v].position, 1.0);
                    //debugPrintfEXT("vertex position %v3f : ",gl_MeshVerticesEXT[i].gl_Position);
                    fragColor[i] = color;
                    //debugPrintfEXT("color : %v4f", fragColor[i]);
                    fragTexCoord[i] = vertexData[pc.primitiveType].vertices[v].texCoords;
                    //debugPrintfEXT("tex coords : %v2f", fragTexCoord[i]);
                    normal[i] = mat3(transpose(inverse(modelMatrix))) * vertexData[pc.primitiveType].vertices[v].normal;
                    //debugPrintfEXT("normal %v3f", normal[i]);
                    materialID[i] = subMesh.materialId;
                    primitiveType[i] = pc.primitiveType;
                    currentFrame[i] = pc.currentFrame;                
                    //debugPrintfEXT("materialId %i", subMesh.materialId);
                    //debugPrintfEXT("position : %i",  i);
                }  
     
                for (uint tri = 0; tri < primitiveCount; tri++) {
     
                    //debugPrintfEXT("gen tri : %i", tri);
                    uint g0 = meshlet.triangles[tri].x;
                    uint g1 = meshlet.triangles[tri].y;
                    uint g2 = meshlet.triangles[tri].z;
                    // Trouver les indices locaux
                    uint i0 = findLocalIndex(g0, vertexCount);
                    uint i1 = findLocalIndex(g1, vertexCount);
                    uint i2 = findLocalIndex(g2, vertexCount);
                    /*uint g0 = indexData[pc.primitiveType].indexes[firstIndex+tri*3+0];
                    uint g1 = indexData[pc.primitiveType].indexes[firstIndex+tri*3+1];
                    uint g2 = indexData[pc.primitiveType].indexes[firstIndex+tri*3+2];
                    uint i0 = g0 - meshlet.vertexOffset;
                    uint i1 = g1 - meshlet.vertexOffset;
                    uint i2 = g2 - meshlet.vertexOffset;*/
                    //debugPrintfEXT("indexes : %i, %i, %i, %i %i %i",g0, g1, g2, i0, i1, i2);
                    //debugPrintfEXT("indexes : %i, %i", vertexCount, primitiveCount);  
                    if (i0 >= vertexCount || i1 >= vertexCount || i2 >= vertexCount) {
     
                        debugPrintfEXT("erreur : %i %i %i, %i,%i, %i, %i, %i",g0, g1, g2, i0, i1, i2, meshlet.nbIndexes, vertexCount); 
                        //continue;
                    }
                    gl_PrimitiveTriangleIndicesEXT[tri] = uvec3(i0, i1, i2);            
                }            
            } else {
                SetMeshOutputsEXT(0, 0);
            }
        //Face de heightmap ou voxel.
        } else {
            //debugPrintfEXT("Height Map");
            SetMeshOutputsEXT(taskData.vertexCount, taskData.primitiveCount);
            for (uint i = 0; i < taskData.vertexCount; i++) {        
                gl_MeshVerticesEXT[i].gl_Position = vec4(outputVertices[pc.currentFrame].vertices[taskData.vertexOffset+i].position, 1);        
            }
            for (uint tri = 0; tri < taskData.primitiveCount; tri++) {
                gl_PrimitiveTriangleIndicesEXT[tri*2] = uvec3(tri*4, tri*4+1, tri*4+2);
                gl_PrimitiveTriangleIndicesEXT[tri*2+1] = uvec3(tri*4, tri*4+2, tri*4+3);
            }
        }  
    }
    Hors comme on peut le voir sur ce rendu, mon fragment shader ne lit que de la merde :

    Nom : image_2026-10-03_112128146.png
Affichages : 131
Taille : 373,3 Ko

    Triangles de couleur aléatoire apparaissant à l'écran. (données non initalisée) ou triangles manquants avec le vertex pipeline. Alors que j'utilise mesh_optimizer pour le découpage de mes meshs.
    Mais oui, quand ça ne fonctionne plus, même si le code ne change pas, c'est toujours la faute du dev. (jamais ddu hardware, ni du driver)
    Peut être que je devrais arrêter les technologies capricieuses et, faire un jeu avec une lib existante. Les moteurs c'est cool quand ça fonctionne mais à partir du moment ou t'a se genre de bug incompréhensible ça devient beaucoup moins fun. Développer un jeu serait plus fun. En ce qui concerne dragonjoker il n'a pas toujours été aussi gentil il y a 10 ans. C'est d'ailleurs en parti à cause de lui que je suis parti dans un moteur et pas un jeu car à force de m'avoir dis que je faisais de la merde que je ne savait pas programmé en 2D et en 3D, j'ai voulu faire mieux que lui.

    PS : J'ai déjà perdu 2 emplois comme cela, mon code fonctionnait, on m'avait même félilicité et tout ça, et puis un bon jour ils ont essayé sur une autre machine ou je ne sais quoi et ça ne fonctionnait plus du coup la secrétaire m'apporte une lettre, je la lis : travail non concluant, vous devez quitter l'entreprise. J'ai eu le même problème lors d'un stage d'essai on m'avais demander de filmer une vidéo mais le logiciel que j'avais installé avait fait planté windows xp. (à l'époque) Je me suis fais démolir à cause de ça. Bref quand y'a un problème c'est toujours la faute du programmeur même si le code ne change pas, donc on le vire.

    PS 2 et j'utilisais des libs existantes à l'époque, pas mon moteur.

  2. #462
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut Remise du code en publique.
    Franchement je n'ai plus rien à perdre puisque l'affichage déconne (même si il est très improbable qu'un développeur plus chevronner m'aide et trouve pourquoi ça déconne l'affichage, même si je le payais.)

  3. #463
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut Je vais apprendre unreal.
    Bonjour, je suis entrain de télécharger unreal, je pense que ça serait une bonne idée d'apprendre à l'utiliser, et ça me permettrait peut être de comprendre pourquoi mon moteur foire au niveau de l'affichage, en inspectant les buffers. Plutôt que d'essayer de débuguer à l'aveugle, quoi qu'il en soit maintenant j'ai besoin d'un moteur existant qui fonctionne, par contre, le lien pour télécharger le code d'unreal qui est soi disant opensource ne fonctionne pas (erreur 404) même en liant mon compte git à celui d'epic games.

    J'aimerais bien trouver un tuto sur le fonctionnement du moteur au niveau de leur langage de script. (c++) Mais je pense que l'ia devrait m'aider pour apprendre.

  4. #464
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut
    Et pour information, j'ai déjà travaillé en tant que chef de projet, sur un jeu amateur. Mais le co-leader était tellement prétentieux qu'il a fait dissoudre toute l'équipe, avant de partir, pour faire le malin. Hors qu'on était plutôt bien parti. On a travailler ensemble pendant 5-6 mois avant que je reparte sur le développement du moteur. Et sans être payé. C'était une très belle expérience. Mais trop belle pour durer. Je m'entendais très bien avec les artistes sérieux surtout.

  5. #465
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 999
    Par défaut
    Hello,

    Plus de 450 messages, je vais pas tout lire, et ce qui fait foi me concernant c'est le code...

    Je vais être franc, vous ne maîtrisez pas l'environnement sur lequel vous travaillez, y compris l'architecture ! Je ne travaille pas dans les jeux, mais je travaille sur des sujets très complexes et si je vois ce type de développement, ça passera jamais la revue...

    Vous utilisez un langage objets complexe que vous ne maîtrisez pas, mais pire encore, la partie métier (ce que raconte votre histoire) qui devrait transpirer dans votre code, on ne là voit pas.

    Un exemple simple,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    while guerrier.est_vivant and barbare.est_vivant:
        combat(guerrier, barbare)
    Dans ce morceau de code on comprend que c'est un combat à mort entre un guerrier et un barbare, c'est lisible et il est facile à retrouver... après on découvre d'autres problématiques comme qui est-ce qui attaque et qui est-ce qui défend ? etc...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while guerrier.est_vivant and barbare.est_vivant:
        combat(guerrier, barbare)
        # On vérifie si le barbare est mort avant qu'il ne riposte (logique mais faut l'écrire)
    Gardez ce qui selon vous fonctionne, reprenez tout depuis le début avec une belle histoire et prenez le temps de prototyper avec un autre langage objets plus simple que le C++ permettant un développement rapide et vérifiez que tout est cohérent.

    IA ou pas IA si vous ne savez pas quoi faire, ça transpirera sur votre prompt, l'IA vous racontera une histoire qui a ni queue ni tête ! Si c'est pour débiter du code, l'histoire ne viendra plus de vous mais de l'IA ! Donc soyez clair dans votre tête, imaginez que vous recommenciez, que feriez vous pour améliorer tout ça ?

    Alors 450 messages, pourquoi je dis ça ? Soit vous n'avez pas écouté ce qu'on vous dit, soit on vous a raconté de la m...

    P.S

    Et pour information, j'ai déjà travaillé en tant que chef de projet, sur un jeu amateur.
    Vous le dîtes vous même, vous étiez chef de projet amateur, tout comme le jeu
    Et combien même, un chef de projet n'est ni architecte technique, ni DevOps, ni dev et vice versa.

    pourquoi mon moteur foire au niveau de l'affichage, en inspectant les buffers
    Ça peut être pour tellement de raisons... pas étonnant que personne n'y réponde, et sans doute que votre code n'aide pas non plus à vous lire...

    Question conne, vous faîtes quoi avec la ligne ci-dessous ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  6. #466
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 859
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    après on découvre d'autres problématiques comme qui est-ce qui attaque et qui est-ce qui défend ?
    La + grosse problématique c'est que dans un moteur de jeu, on ne doit pas retrouver de logique de jeu.
    Déjà que son moteur n'arrive pas à afficher 1 scène et 3 modèles (après recherche les fichiers .fbx sont propriétaires avec des spécifications non officielles)

    Certains lui ont dit, il s'éparpille de partout sans rien finir (juste fonctionnel)

  7. #467
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 999
    Par défaut
    La + grosse problématique c'est que dans un moteur de jeu, on ne doit pas retrouver de logique de jeu.
    Je parlais de la problématique liée au combat guerrier - barbare que je présentais sur mon code

    Le moteur de jeu est une toute autre problématique et n'est pas du tout liée aux entités du jeu, selon moi on devrait pouvoir séparer modèles et vues non ? Après on peut sans doute raccrocher tout cela avec le moteur ?
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  8. #468
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut
    Salut, j'ai ouvert render doc et, pour certains meshs, mes offsets (de mes draw commandes) on l'air mauvais, certains triangles de bistro ne s'affichent donc pas.

    Nom : image_2026-10-04_095459423.png
Affichages : 112
Taille : 229,6 Ko

    Mes bugs viennent pas d'une logique de jeu ou quoi que ce soit, ce sont juste, des bugs d'affichage.

    Je définit mes offsets comme ceci :

    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
    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
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    744
    745
    746
    747
    748
    749
    750
    751
    752
    753
    754
    755
    756
    757
    758
    759
    760
    761
    762
    763
    764
    765
    766
    767
    768
    769
    770
    771
    772
    773
    774
    775
    776
    777
    778
    779
    780
    781
    782
    783
    784
    785
    786
    787
    788
    789
    790
    791
    792
    793
    794
    795
    796
    797
    798
    799
    800
    801
    802
    803
    804
    805
    806
    807
    808
    809
    810
    811
    812
    813
    814
    815
    816
    817
    818
    819
    820
    821
    822
    823
    824
    825
    826
    827
    828
    829
    830
    831
    832
    833
    834
    835
    836
    void RenderTarget::updateBuffers() {
    			if (needToUpdateBuffers && gameObjects.size() > 0) {
    				//std::cout<<"update buffers"<<std::endl;
    				currentSubmeshesOffset = 0;
    				currentModelDataOffset = 0;	
    				currentMeshletsOffset = 0;
    				currentClustersOffset = 0;			
    				for (unsigned int i = 0; i < NB_PRIMITIVE_TYPES; i++) {
    					vertices[i].clear();
    					currentVertexOffset[i] = 0;
    					currentIndexOffset[i] = 0;
    				}
    				Material::updateIds();
    				std::deque<Material*> materials = Material::getAllMaterials();
    				std::vector<MaterialData> materialDatas;
    				/*std::cout<<"material : "<<materials.size()<<std::endl;
    				system("PAUSE");*/
    				for (unsigned int i = 0; i < materials.size(); i++) {
    					//std::cout<<"texture id : "<<materials[i]->getTexture(entity::SubMesh::DIFFUSE)->getId()<<std::endl;
    					MaterialData material;
    					//std::cout<<"material : "<<materials[i]<<std::endl;
    					material.diffuseTextureIndex = (materials[i]->getTexture(entity::SubMesh::DIFFUSE) != nullptr) ? materials[i]->getTexture(entity::SubMesh::DIFFUSE)->getId() : 0;
    					//std::cout<<"diffuse texture index : "<<material.diffuseTextureIndex<<std::endl;
    					//system("PAUSE");
    					material.specularTextureIndex = (materials[i]->getTexture(entity::SubMesh::SPECULAR) != nullptr) ? materials[i]->getTexture(entity::SubMesh::SPECULAR)->getId() : 0;
    					material.normalTextureIndex = (materials[i]->getTexture(entity::SubMesh::NORMAL) != nullptr) ? materials[i]->getTexture(entity::SubMesh::NORMAL)->getId() : 0;
    					material.metalnessTextureIndex = (materials[i]->getTexture(entity::SubMesh::METALNESS) != nullptr) ? materials[i]->getTexture(entity::SubMesh::METALNESS)->getId() : 0;
    					material.roughnessTextureIndex = (materials[i]->getTexture(entity::SubMesh::ROUGHNESS) != nullptr) ? materials[i]->getTexture(entity::SubMesh::ROUGHNESS)->getId() : 0;
    					material.aoTextureIndex = (materials[i]->getTexture(entity::SubMesh::AO) != nullptr) ? materials[i]->getTexture(entity::SubMesh::AO)->getId() : 0;
    					material.emissiveTextureIndex = (materials[i]->getTexture(entity::SubMesh::EMISSIVE) != nullptr) ? materials[i]->getTexture(entity::SubMesh::EMISSIVE)->getId() : 0;
    					/*material.uvScale = /*(materials[i]->getTexture(Material::DIFFUSE) != nullptr) ? math::Vec2f(1.f / materials[i]->getTexture(Material::DIFFUSE)->getSize().x(), 1.f / materials[i]->getTexture(Material::DIFFUSE)->getSize().y()) :*/ /*math::Vec2f(1.f, 1.f);
    					material.uvOffset = math::Vec2f(0.f, 0.f);*/
    					material.materialType = materials[i]->getType();
    					material.nbBuffers = (materials[i]->getTexture(entity::SubMesh::DIFFUSE) != nullptr) ? materials[i]->getTexture(entity::SubMesh::DIFFUSE)->getNbBuffers() : 0;
    					material.vertsInstanceSet  = 0;
    					material.nbVertices = 0;
    					material.nbIndexes = 0;
    					material.materialId = materials[i]->getId();
     
    					material.instanceGroupId = materials[i]->getInstanceGroupId();
    					/*if (material.instanceGroupId != -1)
    						system("PAUSE");*/					
    					material.opaque = materials[i]->opaque;
    					material.pipelineType = materials[i]->pipelineType;
    					/*std::cout<<"id : "<<material.materialId<<", reflectable : "<<material.reflectable<<"refractable : "<<material.refractable<<std::endl;
    					system("PAUSE");*/
    					/*if (material.instanceGroupId != -1)
    						system("PAUSE");**/
    					materialDatas.push_back(material);
     
    				}
    				std::vector<Object> objectDatas;
    				std::vector<ModelData> modelDatas;
    				std::vector<SubMeshData> subMeshesDatas;
    				std::vector<LODLevelData> lodLevelDatas;
    				std::vector<Meshlet> meshletDatas;
    				std::vector<Cluster> clusterDatas;
    				std::vector<CellData> cellDatas;
    				for (unsigned int i = 0; i < gameObjects.size(); i++) {
    					Object object;
    					physic::BoundingBox globalBounds = gameObjects[i]->getGameObject()->getGlobalBounds();
    					gameObjects[i]->getGameObject()->subMeshOffset = currentSubmeshesOffset;
    					AABB aabb;
    					float center[4], size[4];
    					globalBounds.getCenter().toVkVec(center);
    					globalBounds.getSize().toVkVec(size);
    					core::arrayCopy(center, aabb.center, 3);
    					core::arrayCopy(size, aabb.size, 3);
    					object.globalBounds = aabb;
    					object.type = gameObjects[i]->getGameObject()->getTypeInt();
    					object.subMeshesOffset = currentSubmeshesOffset;
    					object.modelDataOffset = currentModelDataOffset;
    					object.nbSubMeshes = gameObjects[i]->getGameObject()->getSubMeshesCount();
    					object.renderingType = gameObjects[i]->getGameObject()->renderingType;
    					//std::cout<<"nb submeshes : "<<object.nbSubMeshes<<std::endl;
    					objectDatas.push_back(object);
    					ModelData modelData;
    					float modelMatrix[16];
    					gameObjects[i]->getGameObject()->getTransform().getMatrix().transpose().toVkMatrix(modelMatrix);
    					core::arrayCopy(modelMatrix, modelData.modelMatrix, 16);
    					//std::cout<<"model matrix : "<<gameObjects[i]->getTransform().getMatrix()<<std::endl;
     
    					modelDatas.push_back(modelData);
    					currentModelDataOffset++;
    					for (unsigned int j = 0; j < gameObjects[i]->getGameObject()->getSubMeshesCount(); j++) {
    						//std::cout<<"add subMesh : "<<j<<std::endl;
    						entity::SubMesh& subMesh = gameObjects[i]->getGameObject()->getSubMeshes()[j];						
    						gameObjects[i]->getGameObject()->getSubMeshes()[j].vertexOffset = currentVertexOffset[subMesh.getVertexArray().getPrimitiveType()];
    						gameObjects[i]->getGameObject()->getSubMeshes()[j].indexOffset = currentIndexOffset[subMesh.getVertexArray().getPrimitiveType()];
    						SubMeshData subMeshData;
    						physic::BoundingBox subMeshGlobalBounds = subMesh.getVertexArray().getGlobalBounds(gameObjects[i]->getGameObject()->getTransform());
    						/*if (!subMeshGlobalBounds.intersects(m_camera.getViewVolume())) {
    							std::cout<<"out of furstrum"<<std::endl;
    						}*/
    						AABB subMeshAABB;
    						subMeshData.id = currentSubmeshesOffset;
    						float center[4], size[4];
    						subMeshGlobalBounds.getCenter().toVkVec(center);
    						subMeshGlobalBounds.getSize().toVkVec(size);
    						core::arrayCopy(center, subMeshAABB.center, 3);
    						core::arrayCopy(size, subMeshAABB.size, 3);
    						//std::cout<<"submesh offset : "<<currentSubmeshesOffset<<","<<gameObjects[i]->getSubMeshesCount()<<std::endl;
    						subMeshData.globalBounds = subMeshAABB;
    						unsigned int primitiveType = subMesh.getVertexArray().getPrimitiveType();
    						subMeshData.primitiveType = primitiveType;
    						subMeshData.vertexOffset = currentVertexOffset[primitiveType];
    						subMeshData.indexOffset = currentIndexOffset[primitiveType];
    						for (unsigned int m = 0; m < materials.size(); m++) {
    							//std::cout<<"j"<<" "<<gameObjects[i]->getMaterials().size()<<std::endl;
    							if (*materials[m] == *gameObjects[i]->getMaterials()[j]) {
    								/*if (materials[m]->getTexture(entity::SubMesh::DIFFUSE) != nullptr && materials[m]->getTexture(entity::SubMesh::DIFFUSE)->getId() == 4) {
    									std::cout<<"ids : "<<subMeshData.id<<","<<gameObjects[i]->getMaterials()[j]->getId()<<","<<materialDatas[gameObjects[i]->getMaterials()[j]->getId()].diffuseTextureIndex<<std::endl;
    									system("PAUSE");
    								}*/
    								//std::cout<<"reflectable  "<<materials[m]->isReflectable()<<"refractable : "<<materials[m]->isRefractable()<<std::endl;
    								subMeshData.materialId = gameObjects[i]->getMaterials()[j]->getId();
    								/*if (subMeshData.materialId > 0)
    									system("PAUSE");*/
    								subMesh.materialId = gameObjects[i]->getMaterials()[j]->getId();
    								/*if (materials[m]->isReflectable())
    									std::cout<<"material id : "<<subMeshData.materialId<<std::endl;
    								system("PAUSE");*/
    							}
    						}						
    						subMeshData.nbVertices = subMesh.getVertexArray().getVertexCount();
    						subMeshData.nbIndexes = subMesh.getVertexArray().getIndexCount();
    						subMeshData.objectId = i;						
    						/*if (subMeshData.id == 1590) {
    							std::cout<<"id : vertex offset : nbVertices : "<<subMeshData.id<<","<<subMeshData.vertexOffset<<","<<subMeshData.nbVertices<<std::endl;
    							system("PAUSE");
    						}*/
     
    						//std::cout<<"vertices count : "<<subMesh.getVertexBuffer().getVertexCount()<<std::endl;
    						/*int pause;
    						std::cin>>pause;*/
    						//std::cout<<"index count : "<<subMesh.getVertexBuffer().getIndexCount()<<std::endl;
     
    						/*std::cout<<"total vertex count : "<<vertices[primitiveType].getVertexCount()<<std::endl;
    						std::cout<<"total index count : "<<vertices[primitiveType].getIndexCount()<<std::endl;*/
    						//std::cout<<"vertx offset, texture id : "<<currentVertexOffset[primitiveType]<<","<<subMeshData.materialId<<std::endl;
    						subMesh.getVertexArray().updateLods();
    						//std::cout<<"vertex offset : "<<currentVertexOffset[primitiveType]<<std::endl;
    						unsigned int baseVertex = currentVertexOffset[primitiveType];
    						//std::cout<<"base vertex : "<<subMeshData.vertexOffset <<"nb vertices : "<<subMeshData.nbVertices<<std::endl;
    						if (gameObjects[i]->getMaterials()[j]->getInstanceGroupId() == -1 || (gameObjects[i]->getMaterials()[j]->getInstanceGroupId() != -1 && !gameObjects[i]->getMaterials()[j]->materialSet)) {
    							gameObjects[i]->getMaterials()[j]->materialSet = true;
    							for (unsigned int v = 0; v < subMesh.getVertexArray().getVertexCount(); v++) {
    								//std::cout<<"add vertex : "<<subMesh.getVertexBuffer()[v].position<<std::endl;
    								/*if (subMeshData.id == 2)
    									std::cout<<"position : "<<subMesh.getVertexArray()[v].position<<std::endl;*/
     
    								vertices[primitiveType].append(subMesh.getVertexArray()[v]);
    								vertices[primitiveType][baseVertex+v].drawableDataId = currentSubmeshesOffset;
    								//std::cout<<"drawable data id : "<<vertices[primitiveType][v].drawableDataId<<std::endl;
    								currentVertexOffset[primitiveType]++;
    							}
     
    							for (unsigned int v = 0; v < subMesh.getVertexArray().getIndexCount(); v++) {
    								uint32_t idx = subMesh.getVertexArray().getIndex(v);
    								vertices[primitiveType].addIndex(idx);
    								/*if (subMeshData.id == 2) {
    									std::cout<<"index : "<<subMesh.getVertexArray().getIndex(v)<<std::endl;
    									system("PAUSE");
    								}*/
    									/*if (v == 0)
    									std::cout<<"add index : "<<baseVertex<<","<<idx<<std::endl;*/
     
    								currentIndexOffset[primitiveType]++;
    							}
    							/*if (subMeshData.id == 2)
    								system("PAUSE");*/
    						}
    						/*std::cout<<"new total vertex count : "<<vertices[primitiveType].getVertexCount()<<std::endl;
    						std::cout<<"new total index count : "<<vertices[primitiveType].getIndexCount()<<std::endl;*/
    						subMeshData.meshletOffset =  meshletDatas.size();
    						std::array<entity::VertexArray::LODLevel, 5> lods = subMesh.getVertexArray().getLODs();
    						unsigned int currentSubmeshMeshletOffset = meshletDatas.size();						
    						for (unsigned int l = 0; l < lods.size() && lods[l].indexCount > 0; l++) {
    							LODLevelData lodLevelData{};
    							lodLevelData.index_offset = lods[l].indexOffset;
    							lodLevelData.index_count = lods[l].indexCount;
     
    							//std::cout<<"first index lod : "<<l<<","<<subMeshData.indexOffset+lods[l].indexOffset<<","<<lods[l].indexCount<<std::endl;					
    							unsigned int currentLodMeshletOffset = meshletDatas.size() - currentSubmeshMeshletOffset;
    							//std::cout<<"currentSubmeshMeshletOffset : "<<currentSubmeshMeshletOffset<<" "<<currentLodMeshletOffset<<","<<meshletDatas.size()<<std::endl;
    							lodLevelData.meshletOffset = currentLodMeshletOffset;
    							float x = subMeshGlobalBounds.getPosition().x();
    							float y = subMeshGlobalBounds.getPosition().y();
    							float z = subMeshGlobalBounds.getPosition().z();				
    							float w = subMeshGlobalBounds.getSize().x();
    							float h = subMeshGlobalBounds.getSize().y();
    							float d = subMeshGlobalBounds.getSize().z();							
    							/*Meshlet m;	
    							m.id = meshletDatas.size();
    							m.submeshId = subMeshData.id;						
    							m.minVertex = std::numeric_limits<unsigned int>::max();
    							m.maxVertex = 0;
    							m.mins = math::Vec3f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
    							m.maxs = math::Vec3f(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
    							m.nbIndexes = 0;
    							m.indexOffset = 0;
    							m.lod = l;	
    							m.voxel = 0;
    							m.rendered = 0;
    							m.clusterId = -1;
    							unsigned int meshletCount = 0;
     
    							currentMeshletsOffset++;	
    							meshletCount++;													
    							for (unsigned int tri = 0; tri < lods[l].indexCount / 3; tri++) {
    								int g0 = vertices[primitiveType].getIndex(subMeshData.indexOffset + lods[l].indexOffset+tri*3+0);								
    								int g1 = vertices[primitiveType].getIndex(subMeshData.indexOffset + lods[l].indexOffset+tri*3+1);
    								int g2 = vertices[primitiveType].getIndex(subMeshData.indexOffset + lods[l].indexOffset+tri*3+2);
     
     
     
    								//std::cout<<"vertices : "<<p1<<","<<p2<<","<<p3<<std::endl;
     
    								math::Vec3f p1, p2, p3;
    								p1 = vertices[primitiveType][g0].position;
    								p2 = vertices[primitiveType][g1].position;
    								p3 = vertices[primitiveType][g2].position;
    								unsigned int newMin = std::min(g0, std::min(g1, g2));
        							unsigned int newMax = std::max(g0, std::max(g1, g2));
    								m.minVertex = std::min(m.minVertex, newMin);
    								m.maxVertex = std::max(m.maxVertex, newMax);
    								newMin = m.minVertex;
    								newMax = m.maxVertex;
    								unsigned int newVertexCount = (newMax - newMin) + 1;
     
    								math::Vec3f mins = math::Vec3f(std::min(p1.x(), std::min(p2.x(), p3.x())), std::min(p1.y(), std::min(p2.y(), p3.y())), std::min(p1.z(), std::min(p2.z(), p3.z())));
    								math::Vec3f maxs = math::Vec3f(std::max(p1.x(), std::max(p2.x(), p3.x())), std::max(p1.y(), std::max(p2.y(), p3.y())), std::max(p1.z(), std::max(p2.z(), p3.z())));
    								m.mins = math::Vec3f(std::min(m.mins.x(), mins.x()), std::min(m.mins.y(), mins.y()), std::min(m.mins.z(), mins.z()));
    								m.maxs = math::Vec3f(std::max(m.maxs.x(), maxs.x()), std::max(m.maxs.y(), maxs.y()), std::max(m.maxs.z(), maxs.z()));
    								mins = m.mins;
    								maxs = m.maxs;		
     
    								// Si ce triangle dépasse les limites → nouveau meshlet
    								if (m.nbIndexes/3 >= MAX_PRIMS || newVertexCount > MAX_VERTS)
        							{									
    									m.vertexOffset = m.minVertex;
    									m.nbVertices   = (newMax - newMin) + 1;
     
     
    									meshletDatas.push_back(m);
     
    									// Nouveau meshlet
    									m = Meshlet();
    									m.id = meshletDatas.size();
    									m.submeshId = subMeshData.id;
    									m.nbIndexes = 0;
    									m.indexOffset = tri * 3;
    									m.voxel = 0;
    									m.rendered = 0;
    									m.lod = l;
    									m.clusterId = -1;
     
    									m.minVertex = std::numeric_limits<unsigned int>::max();
    									m.maxVertex = 0;
    									m.mins = math::Vec3f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
    									m.maxs = math::Vec3f(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
     
    									// Recalculer pour ce triangle
    									newMin = std::min(g0, std::min(g1, g2));
    									newMax = std::max(g0, std::max(g1, g2));
    									m.minVertex = std::min(m.minVertex, newMin);
    									m.maxVertex = std::max(m.maxVertex, newMax);
    									newVertexCount = (newMax - newMin) + 1;
     
    									mins = math::Vec3f(std::min(p1.x(), std::min(p2.x(), p3.x())), std::min(p1.y(), std::min(p2.y(), p3.y())), std::min(p1.z(), std::min(p2.z(), p3.z())));
    									maxs = math::Vec3f(std::max(p1.x(), std::max(p2.x(), p3.x())), std::max(p1.y(), std::max(p2.y(), p3.y())), std::max(p1.z(), std::max(p2.z(), p3.z())));
     
    									m.mins = math::Vec3f(std::min(m.mins.x(), mins.x()), std::min(m.mins.y(), mins.y()), std::min(m.mins.z(), mins.z()));
    									m.maxs = math::Vec3f(std::max(m.maxs.x(), maxs.x()), std::max(m.maxs.y(), maxs.y()), std::max(m.maxs.z(), maxs.z()));									
    									currentMeshletsOffset++;	
    									meshletCount++;							
    								}
    								// Ajouter triangle								
     
     
    								m.nbIndexes += 3;								
    							}
     
     
    							// Final meshlet
    							m.id = meshletDatas.size();							
    							m.vertexOffset = m.minVertex;							
    							m.nbVertices   = (m.maxVertex - m.minVertex) + 1;							
    							meshletDatas.push_back(m);*/
     
     
    							//std::cout<<x<<" ,"<<y<<" ,"<<z<<" ,"<<w<<" , "<<h<<" ,"<<d<<std::endl;						
     
    							//std::cout<<"cluster count : "<<clusterCount<<std::endl;
     
     
     
     
    							std::vector<entity::Vertex> verts(subMesh.getVertexArray().getVertexCount());														
     
     
    							for (uint32_t v = 0; v < subMesh.getVertexArray().getVertexCount(); v++)
    							{
    								verts[v] = subMesh.getVertexArray()[v];
    							}		
    							std::vector<uint32_t> indexes(lods[l].indexCount);
     
    							for (uint32_t v = 0; v < lods[l].indexCount; v++)
    							{
    								uint32_t gi = subMesh.getVertexArray().getIndex(lods[l].indexOffset + v);
    								indexes[v] = gi;
    							}		
    							size_t maxMeshlets = meshopt_buildMeshletsBound(
    								indexes.size(),
    								MAX_VERTS,   // ex: 64
    								MAX_PRIMS   // ex: 96
    							);	
    							std::vector<meshopt_Meshlet> meshlets(maxMeshlets);
    							std::vector<unsigned int> meshletVertices(maxMeshlets * MAX_VERTS);
    							std::vector<unsigned char> meshletTriangles(maxMeshlets * MAX_PRIMS * 3);
    							size_t meshlet_count = meshopt_buildMeshlets(
    								meshlets.data(),
    								meshletVertices.data(),
    								meshletTriangles.data(),
    								indexes.data(), indexes.size(),
    								reinterpret_cast<const float*>(verts.data()),verts.size(),
    								sizeof(entity::Vertex),
    								MAX_VERTS,
    								MAX_PRIMS,
    								0
    							);
     
     
    							unsigned int meshletCount = 0;
     
    							for (unsigned int m = 0; m < meshlet_count; m++) {								
    								const meshopt_Meshlet& meshlet = meshlets[m];
    								assert(meshlet.vertex_count <= 256);
    								assert(meshlet.triangle_count <= 256);
    								std::vector<uint32_t> localVertexIndices(meshlet.vertex_count);
     
    								for (uint32_t v = 0; v < meshlet.vertex_count; ++v) {
    									localVertexIndices[v] = meshletVertices[meshlet.vertex_offset + v];
    									//std::cout<<"v index : "<<localVertexIndices[v]<<std::end;
    								}
    								//std::cout<<"local vertices ok"<<std::endl;
    								std::vector<math::Vector4u> localTriangles(meshlet.triangle_count);
     
     
    								for (uint32_t t = 0; t < meshlet.triangle_count; ++t) {
    									uint32_t g0 = localVertexIndices[meshletTriangles[meshlet.triangle_offset + t * 3 + 0]];
    									uint32_t g1 = localVertexIndices[meshletTriangles[meshlet.triangle_offset + t * 3 + 1]];
    									uint32_t g2 = localVertexIndices[meshletTriangles[meshlet.triangle_offset + t * 3 + 2]];
    									bool findg0 = false, findg1  = false, findg2  = false;
    									for (unsigned int g = 0; g < localVertexIndices.size(); g++) {
    										if (g0 == localVertexIndices[g]) {
    											findg0 = true;
    										}
    										if (g1 == localVertexIndices[g]) {
    											findg1 = true;
    										}
    										if (g2 == localVertexIndices[g]) {
    											findg2 = true;
    										}
    									}	
    									if (!findg0 || !findg1 || !findg2) {
    										system("PAUSE");
    									}								
    									localTriangles[t] = math::Vector4u(g0, g1, g2, 0); // indices locaux.
    								}								
    								Meshlet ms;	
    								ms.id = meshletDatas.size();
    								ms.submeshId = subMeshData.id;
    								ms.lod = l;	
    								ms.voxel = 0;
    								ms.rendered = 0;
    								ms.clusterId = -1;								
    								//std::cout<<"vertex offset : "<<m.vertexOffset<<std::endl;								
    								//std::cout<<"index offset : "<<m.indexOffset<<std::endl;
    								ms.nbIndexes = meshlet.triangle_count*3;
    								ms.nbVertices = meshlet.vertex_count;
    								/*if (meshlet.vertex_count == 0) {
    									std::cout<<"nb vertices : "<<m.nbVertices<<std::endl;
    									system("PAUSE");
    								}*/
    								for (unsigned int v = 0; v < localVertexIndices.size(); v++)
    									ms.localVertices[v] = localVertexIndices[v];
    								for (unsigned int t = 0; t < localTriangles.size(); t++) {
    									unsigned int tri[4];
    									localTriangles[t].toVkVec(tri);
    									core::arrayCopy(tri, ms.localTriangles[t], 3);
    								}
    								meshopt_Bounds bounds = meshopt_computeMeshletBounds(
    									&meshletVertices[meshlet.vertex_offset],
    									&meshletTriangles[meshlet.triangle_offset],
    									meshlet.triangle_count,
    									reinterpret_cast<const float*>(verts.data()),
    									verts.size(),
    									sizeof(entity::Vertex)
    								);	
    								ms.mins[0] = bounds.center[0] - bounds.radius;
    								ms.mins[1] = bounds.center[1] - bounds.radius;
    								ms.mins[2] = bounds.center[2] - bounds.radius;
    								ms.maxs[0] = bounds.center[0] + bounds.radius;
    								ms.maxs[1] = bounds.center[1] + bounds.radius;
    								ms.maxs[2] = bounds.center[2] + bounds.radius;						
    								//std::cout<<"mins : "<<m.mins<<"maxs : "<<m.maxs<<std::endl;
    								meshletDatas.push_back(ms);
    								currentMeshletsOffset++;
    								meshletCount++;
     
    							}
     
    							//Récupérer les cellules de la grille de clusters.
    							//std::cout<<"min : "<<m.minVertex<<std::endl;
     
    							//std::cout<<currentMeshletsOffset<<" , "<<meshletCount<<" , "<<currentClustersOffset-clusterCount<<" , "<<clusterDatas.size()<<std::endl;
     
    							//std::cout<<"cluster added"<<std::endl;						
    							//std::cout<<"lod meshlet count : "<<(meshletDatas.size() - currentLodMeshletOffset - currentSubmeshMeshletOffset)<<std::endl;
    							lodLevelData.meshletOffset = currentLodMeshletOffset;
    							lodLevelData.meshletCount = meshletDatas.size() - currentLodMeshletOffset - currentSubmeshMeshletOffset;
    							//std::cout<<"meshlet count : "<<currentSubmeshMeshletOffset<<","<<currentLodMeshletOffset<<","<<lodLevelData.meshletCount<<std::endl;																		
    							lodLevelDatas.push_back(lodLevelData);
    							/*for (unsigned int m = currentSubmeshMeshletOffset+lodLevelData.meshletOffset; m < currentSubmeshMeshletOffset+lodLevelData.meshletOffset + lodLevelData.meshletCount; m++) {
    								Meshlet meshlet = meshletDatas[m];
    								unsigned int firstIndex = subMeshData.indexOffset + lods[l].indexOffset + meshlet.indexOffset; 
    								//std::cout<<"meshlet : "<<lodLevelData.meshletCount<<","<<currentSubmeshMeshletOffset<<","<<subMeshData.indexOffset<<","<<meshlet.nbIndexes<<","<<meshlet.nbVertices<<","<<meshlet.indexOffset<<","<<meshlet.vertexOffset<<std::endl;							
    								for (unsigned int t = 0; t < meshlet.nbIndexes  / 3; t++) {
    									int g0 = vertices[primitiveType].getIndex(subMeshData.indexOffset + lods[l].indexOffset + meshlet.indexOffset+t*3+0);
    									int g1 = vertices[primitiveType].getIndex(subMeshData.indexOffset + lods[l].indexOffset + meshlet.indexOffset+t*3+1);
    									int g2 = vertices[primitiveType].getIndex(subMeshData.indexOffset + lods[l].indexOffset + meshlet.indexOffset+t*3+2);
    									int i0 = g0 - meshlet.vertexOffset;
    									int i1 = g1 - meshlet.vertexOffset;
    									int i2 = g2 - meshlet.vertexOffset;
    									//std::cout<<"first index : "<<subMeshData.indexOffset + lods[l].indexOffset + meshlet.indexOffset<<","<<meshlet.vertexOffset<<std::endl;
    									//std::cout<<"vertex offset : "<<g0<<", "<<g1<<", "<<g2<<std::endl;
    									if (i0 >= meshlet.nbVertices || i1 >= meshlet.nbVertices || i2 >= meshlet.nbVertices) {
    										std::cout<<"indexes : "<<i0<<","<<i1<<","<<i2<<","<<meshlet.nbVertices<<std::endl;
    										system("PAUSE");
    									}
    								}
    							}	*/			
    							meshletsGrid.clear();
    							bool oneAdded = false;
    							//std::cout<<"add"<<std::endl;
    							for (unsigned int m = 0; m < meshletDatas.size(); m++) {							
    								//Reconstruction de l'AABB et ajout dans la grille de meshlets.
    								//std::cout<<"meshlet : "<<meshletDatas[m].id<<","<<meshletDatas[m].submeshId<<","<<subMeshData.id<<","<<l<<std::endl;
    								if ((meshletDatas[m].lod > l && meshletDatas[m].submeshId ==  subMeshData.id) || meshletDatas[m].submeshId > subMeshData.id) {
    									system("PAUSE");
    								}
    								if (meshletDatas[m].lod == l && meshletDatas[m].submeshId == subMeshData.id) {
    									//std::cout<<"meshlet : "<<meshletDatas[m].id<<","<<meshletDatas[m].submeshId<<","<<subMeshData.id<<","<<l<<std::endl;
    									//std::cout<<"meshlet : "<<meshletDatas[m].id<<","<<meshletDatas[m].submeshId<<","<<subMeshData.id<<","<<l<<std::endl;
    									physic::BoundingBox volume(
    										meshletDatas[m].mins[0], 
    										meshletDatas[m].mins[1],
    										meshletDatas[m].mins[2],
    										meshletDatas[m].maxs[0] - meshletDatas[m].mins[0],
    										meshletDatas[m].maxs[1] - meshletDatas[m].mins[1],
    										meshletDatas[m].maxs[2] - meshletDatas[m].mins[2]);
    									//std::cout<<"volume : "<<volume.getPosition()<<","<<volume.getSize()<<std::endl;
    									oneAdded = true;
    									//std::cout<<"add meshlet : "<<volume.getPosition()<<","<<volume.getSize()<<std::endl;
    									bool added = meshletsGrid.addEntity(meshletDatas[m], volume);
     
    									if (!meshletsGrid.containsEntity(meshletDatas[m])) {
    										std::cout<<"meshlet not added : "<<meshletDatas[m].mins<<","<<meshletDatas[m].maxs<<std::endl;
    										//system("PAUSE");
    									}
    								}
    									//std::cout<<"added!"<<std::endl;
    							}
    							if (!oneAdded) {
    								system("PAUSE");
    							}
     
     
    							math::Vec3f gridPos = meshletsGrid.getMins();
    							math::Vec3f gridSize = meshletsGrid.getSize();
     
     
    							cullingInfo.nbCellsPerRow[l][0] = meshletsGrid.getNbCasesPerRow();
    							cullingInfo.nbCellsPerRow[l][1] = meshletsGrid.getNbCasesPerCol(); 
    							cullingInfo.gridCellSize[l][0] = meshletsGrid.getCellWidth();
    							cullingInfo.gridCellSize[l][1] = meshletsGrid.getCellHeight();
    							cullingInfo.gridCellSize[l][2] = meshletsGrid.getCellDepth();
    							cullingInfo.gridPos[l][0] = gridPos.x();
    							cullingInfo.gridPos[l][1] = gridPos.y();
    							cullingInfo.gridPos[l][2] = gridPos.z();
    							cullingInfo.gridSize[l][0] = gridSize.x();
    							cullingInfo.gridSize[l][1] = gridSize.y();
    							cullingInfo.gridSize[l][2] = gridSize.z();
    							/*std::cout<<"grid pos, size : "<<gridPos<<","<<gridSize<<std::endl;
    							system("PAUSE");*/
     
    							//Ballayage de la grille.
    							std::vector<entity::GridCell<Meshlet>> casesMap = meshletsGrid.getCasesMap();				
    							for (unsigned int cm = 0; cm < casesMap.size(); cm++) {
    								//std::cout<<"grid cell : "<<x<<","<<y<<","<<z<<std::endl;
     
    								entity::GridCell<Meshlet> gridCell = casesMap[cm];
    								//Trou. (Il faut les gérer pour le ballayage GPU)
    								//std::cout<<"volume : "<<gridCell->getCellVolume().getPosition()<<","<<gridCell->getCellVolume().getSize()<<std::endl;
    								if (gridCell.empty()) {
    									if (gridCell.empty()) {
    										std::cout<<"empty : "<<gridCell.getCellVolume().getPosition()<<","<<gridCell.getCellVolume().getSize()<<std::endl;//std::cout<<"grid cell is null"<<std::endl;
    										system("PAUSE");
    									}
    									//std::cout<<"empty : "<<gridCell<<std::endl;
    									CellData emptyCell;
    									emptyCell.clusterId = -1;
    									emptyCell.clusterOffset = 0;
    									emptyCell.clusterCount = 0;									
    									cellDatas.push_back(emptyCell);
    								//Cluster rempli. 
    								} else {
    									//std::cout<<"not empty"<<std::endl;
    									//Ajout du root node et des enfants + création des clusters et assignation des ids.
    									std::deque<entity::BSPTree<Meshlet>::Node>& nodes = gridCell.getTreeNodes();
    									//std::cout<<"size : "<<nodes.size()<<std::endl;
    									std::deque<unsigned int> stack;
    									stack.push_back(0);	
    									CellData cellData;							
    									cellData.clusterId = currentClustersOffset;
    									cellData.clusterOffset = currentClustersOffset;
    									float center[4], size[4], coords[4];
    									gridCell.getCellVolume().getCenter().toVkVec(center);
    									gridCell.getCellVolume().getCenter().toVkVec(size);
    									core::arrayCopy(center, cellData.volume.center, 3);
    									core::arrayCopy(size, cellData.volume.size, 3);
    									gridCell.getCoords().toVkVec(coords);
    									core::arrayCopy(coords, cellData.coords, 3);
     
    									while (!stack.empty()) {										
    										size_t id = stack.back();
    										stack.pop_back();
    										//std::cout<<"leaf ? "<<node.leaf<<"size = "<<stack.size()<<std::endl;
    										entity::BSPTree<Meshlet>::Node& node = nodes[id];
    										/*Cluster clusterData;												
    										clusterData.submeshId = currentSubmeshesOffset;
    										clusterData.volume.center = node.volume.getCenter();
    										clusterData.volume.size = node.volume.getSize();
    										//std::cout<<"cluster AABB center, size : "<<childClusterData.volume.center<<","<<childClusterData.volume.size<<std::endl;
     
     
     
    										clusterData.leaf = 0;
    										clusterData.id = clusterDatas.size();
    										clusterData.lodLevel = l;
    										clusterData.meshletCount = 10;
    										clusterData.meshletOffset = 0;
     
     
    										clusterDatas.push_back(clusterData);
    										node.id = clusterDatas.size()-1;*/
    										//currentClustersOffset++;	
    										if (!node.leaf) {
    											//std::cout<<"children : "<<node.children.size()<<std::endl;
    											if (node.objects.size() > 0) {
    												std::cout<<"not leaf"<<std::endl;
    												system("PAUSE");
    											}								
     
    											/*std::cout<<"not leaf : "<<node.objects.size()<<"c : "<<
    											c<<","<<nodes[node.children[c]].objects.size()<<std::endl;*/													
    											for (unsigned int i = 0; i < node.children.size(); i++) {
    												stack.push_back(node.children[i]);
    											}
    											//node.id = clusterDatas.size()-1;
     
    											//std::cout<<"size : "<<nodes.size()<<"id : "<<id<<" "<<node.children[c]<<std::endl;										clusterDatas[clusterDatas.size()-1].children.push_back(clusterDatas.size());
     
     
    										} else if (node.objects.size() > 0) {
     
    											//system("PAUSE");
    											//entity::Octree<Meshlet>::Node& parent = nodes[node.parent];
    											//std::cout<<"id : "<<id<<" "<<std::endl;
     
    											//std::cout<<"size : "<<parent.children.size()<<std::endl;
     
    												/*std::cout<<"id : "<<id<<" "<<parent.children[c]<<std::endl;
    												if (nodes[parent.children[c]].objects.size() == 0) {
    													//std::cout<<"empty cluster"<<std::endl;
    													//std::cout<<"nb Objects : "<<nodes[parent.children[c]].objects.size()<<std::endl;
    												}*/
     
    												//std::cout<<"leaf : "<<node.objects.size()<<std::endl;
     
    											Cluster childClusterData;												
    											childClusterData.submeshId = subMeshData.id;
    											float center[4], size[4];
    											node.volume.getCenter().toVkVec(center);
    											node.volume.getSize().toVkVec(size);
    											core::arrayCopy(center, childClusterData.volume.center, 3);
    											core::arrayCopy(size, childClusterData.volume.size, 3);
    											//std::cout<<"cluster AABB center, size : "<<childClusterData.volume.center<<","<<childClusterData.volume.size<<std::endl;
    											childClusterData.id = clusterDatas.size();
    											childClusterData.lodLevel = l;														
    											childClusterData.meshletOffset = 0;	
    											childClusterData.meshletCount = node.objects.size();
    											childClusterData.leaf = 1;
    											clusterDatas.push_back(childClusterData);
    											currentClustersOffset++;
     
    											for (unsigned int o = 0; o < node.objects.size(); o++) {												
     
    												/*std::cout<<"id, size : "<<node.id<<", "<<node.objects.size()<<std::endl;
    												system("PAUSE");*/
     
    												//clusterData.children[c] = clusterDatas.size();
    												if (node.objects.size() > 8) {
    													std::cout<<"error : max object exceeds 8 : "<<node.objects.size()<<std::endl;
    													system("PAUSE");
    												}
    												//std::cout<<"id : "<<node.objects.size()<<std::endl;
    												meshletDatas[node.objects[o].id].clusterId = childClusterData.id;												
    												//std::cout<<"meshlet : "<<meshletDatas[node.objects[o].id].id<<","<<meshletDatas[node.objects[o].id].submeshId<<","<<meshletDatas[node.objects[o].id].lod<<","<<meshletDatas[node.objects[o].id].clusterId<<std::endl;
    												/*if (childClusterData.meshletCount > 0) {
     
    													std::cout<<"meshlet count : "<<childClusterData.meshletCount<<std::endl;
    													system("PAUSE");
    												}*/
    												/*std::cout<<"meshlet count : "<<childClusterData.meshletCount<<std::endl;
    												system("PAUSE");*/
    												//std::cout<<"nb objects : "<<nodes[parent.children[c]].objects.size()<<"AABB : cluster AABB center, size : "<<childClusterData.volume.center<<","<<childClusterData.volume.size<<std::endl;
     
    												//std::cout<<"size : "<<stack.size()<<std::endl;
     
    											}																										
     
    										}
     
    									}
     
    									cellData.clusterCount = currentClustersOffset - cellData.clusterOffset;
    									//std::cout<<"cluster count : "<<cellData.clusterCount<<std::endl;
     
    									cellDatas.push_back(cellData);
    								}
    							}														
     
    						}
     
    						subMeshData.lodOffset = currentSubmeshesOffset * lods.size();
    						subMesh.lodOffset = currentSubmeshesOffset * lods.size();	
    						//std::cout<<"submesh index offset : "<<subMeshData.vertexOffset<<std::endl;	
    						//std::cout<<"submesh meshlet count : "<<(meshletDatas.size() - currentSubmeshMeshletOffset)<<std::endl;
    						subMeshesDatas.push_back(subMeshData);	
    						currentSubmeshesOffset++;					
    					}									
    				}
    				/*std::cout<<"size : "<<vertices[entity::Triangles].getIndexCount()<<std::endl;
    				system("PAUSE");*/
    				cullingInfo.gridCellCount = cellDatas.size();
    				/*std::cout<<"cell : "<<cellDatas.size()<<std::endl;
    				system("PAUSE");*/
     
    				//Tri par lod. (D'abord clusters pour meshelts en lod0, puis 1, etc...)
    				/*for (unsigned int m = 0; m < meshletDatas.size(); m++) {
    					std::cout<<"meshlet : "<<meshletDatas[m].clusterId<<","<<meshletDatas[m].submeshId<<","<<meshletDatas[m].lod<<std::endl;
    				}*/
    				std::sort(meshletDatas.begin(), meshletDatas.end(), [](Meshlet m1, Meshlet m2){ return  m1.clusterId < m2.clusterId;});
     
    				unsigned int lastMeshletId = 0, lastClusterId = 0;				
    				for (unsigned int m = 0; m < meshletDatas.size(); m++) {
    					if (meshletDatas[m].clusterId != -1) {
    						//std::cout<<"id : "<<meshletDatas[m].clusterId<<","<<clusterDatas.size()<<std::endl;
     
    						if (meshletDatas[m].clusterId > lastClusterId) {	
    							lastMeshletId = m;
    							lastClusterId = meshletDatas[m].clusterId;				
    						}
     
    						//std::cout<<"meshlet : "<<meshletDatas[m].clusterId<<","<<lastMeshletId<<","<<clusterDatas[meshletDatas[m].clusterId].submeshId<<std::endl;
    						clusterDatas[meshletDatas[m].clusterId].meshletOffset = lastMeshletId;
     
    					} else {
    						std::cout<<"meshlet : "<<meshletDatas[m].clusterId<<","<<meshletDatas[m].submeshId<<","<<meshletDatas[m].lod<<std::endl;
    						//system("PAUSE");
    					}
    				}
    				//system("PAUSE");
     
    				//Tri des meshlets par cluster ids et placement des offsets.
     
    				totalMeshlets = meshletDatas.size();
    				/*std::cout<<"total sub meshes"<<totalSubMeshes<<std::endl;
    				system("PAUSE");*/
    				vkDeviceWaitIdle(device.getDevice());
    				computeCommandPool.beginRecordCommandBuffer(getCurrentFrame());
    				for (unsigned int i = 0; i < 1; i++) {
    					for (unsigned int j = 0; j < NB_PRIMITIVE_TYPES; j++) {
    						//std::cout<<"update vertices"<<std::endl;
    						vertices[j].setPrimitiveType(static_cast<entity::PrimitiveType>(j));
    						vertices[j].update(computeCommandPool.getHandle(getCurrentFrame()), i);
    					}
    				}
    				//std::cout<<"max lod index : "<<subMeshesDatas.size() * 5<<std::endl;
    				for (unsigned int i = 0; i < 1; i++) {
    					//std::cout<<"copy objects"<<std::endl;
    					staggingObjects[i].create(objectDatas.size() * sizeof(Object), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingObjects[i].update(objectDatas.data(), objectDatas.size() * sizeof(Object));
    					objects[i].create(objectDatas.size() * sizeof(Object), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingObjects[i], objects[i], objectDatas.size() * sizeof(Object), computeCommandPool.getHandle(getCurrentFrame()));
    					//std::cout<<"stagging object buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    					//std::cout<<"object buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					//std::cout<<"copy submeshes"<<std::endl;
    					staggingSubMeshes[i].create(subMeshesDatas.size() * sizeof(SubMeshData), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingSubMeshes[i].update(subMeshesDatas.data(), subMeshesDatas.size() * sizeof(SubMeshData));
    					subMeshes[i].create(subMeshesDatas.size() * sizeof(SubMeshData), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingSubMeshes[i], subMeshes[i], subMeshesDatas.size() * sizeof(SubMeshData), computeCommandPool.getHandle(getCurrentFrame()));
    					//std::cout<<"stagging submeshes buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    					//std::cout<<"submeshes buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					staggingGridCells[i].create(cellDatas.size() * sizeof(CellData), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingGridCells[i].update(cellDatas.data(), cellDatas.size() * sizeof(CellData));
    					inputCellDatas[i].create(cellDatas.size() * sizeof(CellData), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingGridCells[i], inputCellDatas[i], cellDatas.size() * sizeof(CellData), computeCommandPool.getHandle(getCurrentFrame()));
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					staggingClusters[i].create(clusterDatas.size() * sizeof(Cluster), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingClusters[i].update(clusterDatas.data(), clusterDatas.size() * sizeof(Cluster));
    					inputClusters[i].create(clusterDatas.size() * sizeof(Cluster), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingClusters[i], inputClusters[i], clusterDatas.size() * sizeof(Cluster), computeCommandPool.getHandle(getCurrentFrame()));
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					staggingMeshlets[i].create(meshletDatas.size() * sizeof(Meshlet), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingMeshlets[i].update(meshletDatas.data(), meshletDatas.size() * sizeof(Meshlet));
    					inputMeshlets[i].create(meshletDatas.size() * sizeof(Meshlet), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingMeshlets[i], inputMeshlets[i], meshletDatas.size() * sizeof(Meshlet), computeCommandPool.getHandle(getCurrentFrame()));
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					//std::cout<<"copy submeshes"<<std::endl;
    					staggingLODLevel[i].create(lodLevelDatas.size() * sizeof(LODLevelData), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingLODLevel[i].update(lodLevelDatas.data(), lodLevelDatas.size() * sizeof(LODLevelData));
    					lodLevel[i].create(lodLevelDatas.size() * sizeof(LODLevelData), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingLODLevel[i], lodLevel[i], lodLevelDatas.size() * sizeof(LODLevelData), computeCommandPool.getHandle(getCurrentFrame()));
    					//std::cout<<"stagging submeshes buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    					//std::cout<<"submeshes buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					//std::cout<<"copy model datas : "<<modelDatas.size()<<std::endl;
    					staggingModelDatas[i].create(modelDatas.size() * sizeof(ModelData), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingModelDatas[i].update(modelDatas.data(), modelDatas.size() * sizeof(ModelData));
    					this->modelDatas[i].create(modelDatas.size() * sizeof(ModelData), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					Buffer::copyBuffer(staggingModelDatas[i], this->modelDatas[i], modelDatas.size() * sizeof(ModelData), computeCommandPool.getHandle(getCurrentFrame()));
    					//std::cout<<"stagging object buffer : "<<staggingObjects[i].getHandle()<<std::endl;
    				}
    				for (unsigned int i = 0; i < 1; i++) {
    					staggingMaterialDatas[i].create(materialDatas.size() * sizeof(MaterialData), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
    					staggingMaterialDatas[i].update(materialDatas.data(), materialDatas.size() * sizeof(MaterialData));
    					for (unsigned int j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) {
    						for (unsigned int k = 0; k < NB_PRIMITIVE_TYPES; k++) {
    							this->materialDatas[k * MAX_FRAMES_IN_FLIGHT + j].create(materialDatas.size() * sizeof(MaterialData), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    							Buffer::copyBuffer(staggingMaterialDatas[i], this->materialDatas[k * MAX_FRAMES_IN_FLIGHT + j], materialDatas.size() * sizeof(MaterialData), computeCommandPool.getHandle(0));
    						}
    					}
    				}
    				//std::cout<<"buffers updated"<<std::endl;
    				needToUpdateBuffers = false;
    				computeCommandPool.endRecordCommandBuffer(getCurrentFrame());
    				/*std::unique_lock lock(mtx);	
    					//std::cout<<"wait!"<<std::endl;				
    				cv.wait(lock, [this]{return ParticleSystemUpdater::instance(cv, mtx).isSubmitReady() && MorphAnimUpdater::instance(cv, mtx).isSubmitReady() && BoneAnimUpdater::instance(cv, mtx).isSubmitReady();});
    				std::vector<VkFence> fences;
    				for (unsigned int i = 0; i < 3; i++) {
    					//std::cout<<"fence : "<<GPUContext::instance().getSharedFence(i)[0].getHandle()<<std::endl;
    					fences.push_back(GPUContext::instance().getSharedFence(i)[0].getHandle());
    				}
    				//std::cout<<"wait for fences!"<<std::endl;
    				vkWaitForFences(device.getDevice(), fences.size(),fences.data(), VK_TRUE, UINT64_MAX);
     
     
    				//vkResetFences(device.getDevice(), fences.size(),fences.data());*/
    				VkSubmitInfo submitInfo{};
    				submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    				submitInfo.commandBufferCount = 1;
    				submitInfo.pCommandBuffers = &computeCommandPool.getHandle(getCurrentFrame());
    				Device::QueueFamilyIndices indices = GPUContext::instance().getDevice().findQueueFamilies(GPUContext::instance().getDevice().getPhysicalDevice());
     
    				std::unique_lock lock(mtx);	
    					//std::cout<<"wait!"<<std::endl;				
    				cv.wait(lock, [this]{return ParticleSystemUpdater::instance(cv, mtx).isSubmitReady() && MorphAnimUpdater::instance(cv, mtx).isSubmitReady() && BoneAnimUpdater::instance(cv, mtx).isSubmitReady();});
     
    				//std::lock_guard<std::recursive_mutex> lock(getGlobalMutex());
    				/*std::cout << "update buffers main thread " << std::this_thread::get_id()
                    << " calling vkQueueSubmit" << std::endl;*/
     
    				if (vkQueueSubmit(GPUContext::instance().getDevice().getQueue(indices.graphicsFamily.value(), 0), 1, &submitInfo, computeFence.getHandle(getCurrentFrame())) != VK_SUCCESS) {
    					throw std::runtime_error("Echec de l'envoi d'un command buffer!");
    				}
    				vkWaitForFences(device.getDevice(), 1, &computeFence.getHandle(getCurrentFrame()), VK_TRUE, UINT64_MAX);
    				vkResetFences(device.getDevice(), 1, &computeFence.getHandle(getCurrentFrame()));
    				for (unsigned int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
    					ubo[i].update(&cullingInfo, sizeof(UBO));
    				}
    				//system("PAUSE");				
    				//commandPool.beginRecordCommandBuffer(getCurrentFrame());
    				//vertices.clear();
    				needToUpdateDescriptorSets = true;
     
    				//std::cout<<"data updated!"<<std::endl;
    				ParticleSystemUpdater::instance(cv, mtx).setBuffersReady(true);
    				ParticleSystemUpdater::instance(cv, mtx).cv3.notify_all();
     
    				MorphAnimUpdater::instance(cv, mtx).setBuffersReady(true);
    				MorphAnimUpdater::instance(cv, mtx).cv3.notify_all();
     
    				BoneAnimUpdater::instance(cv, mtx).setBuffersReady(true);
    				BoneAnimUpdater::instance(cv, mtx).cv3.notify_all();
     
    			}
    			if (currentSubmeshesOffset > totalSubMeshes) {
    				for (unsigned int j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) {
    					outputVertices.back().getVertexBuffer(j).create(sizeof(entity::Vertex) * vertices[entity::Triangles].getVertexCount(), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    					for (unsigned int k = 0; k < NB_PRIMITIVE_TYPES; k++) {
    						//std::cout<<"update : "<<j<<","<<k<<std::endl;						
    						outputObjectDatas[j * NB_PRIMITIVE_TYPES + k].create(sizeof(ModelData) * currentSubmeshesOffset, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    						outputModelDatas[j * NB_PRIMITIVE_TYPES + k].create(sizeof(ModelData) * currentSubmeshesOffset * Material::getAllMaterials().size(), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    						//std::cout<<"output model data : "<<outputModelDatas[j * NB_PRIMITIVE_TYPES + k].getRange()<<std::endl;
    						outputMaterialDatas[j * NB_PRIMITIVE_TYPES + k].create(sizeof(MaterialData) * currentSubmeshesOffset * Material::getAllMaterials().size(), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    						outputMeshes[j * NB_PRIMITIVE_TYPES + k].create(sizeof(entity::SubMesh) * currentSubmeshesOffset * Material::getAllMaterials().size(), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
    						outputMeshlets[j * NB_PRIMITIVE_TYPES + k].create(sizeof(unsigned int) * currentMeshletsOffset, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);						
    						//std::cout<<"output material datas : "<<registeredRenderTargets[i]->outputMaterialDatas[j * NB_PRIMITIVE_TYPES + k].getRange()<<std::endl;
    						//std::cout<<"output material datas : "<<registeredRenderTargets[i]->outputMaterialDatas[j * NB_PRIMITIVE_TYPES + k].getRange()<<std::endl;
    					}
    				}
    				totalSubMeshes = currentSubmeshesOffset;
    			}	
    		}
    Et dans mon compute shader :

    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
    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
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    #version 460
    #extension GL_EXT_debug_printf : enable
    #define MAX_BONE_INFLUENCE 4
    #define MAX_BONES 100 
    #define NB_PRIMITIVE_TYPES 6
    #define MAX_FRAMES_IN_FLIGHT 2
    /*Boîtes englobantes des objets*/
    const uint opaqueMask = 1 << 0;
    const uint transparentMask = 1 << 1;
    const uint rtPipeline = 2 << 1;
    const uint rasterPipeline = 3 << 1; 
    struct AABB {
    	vec4 center;
    	vec4 size;
    };
    /*Objets*/
    struct Object {
    	AABB globalBounds;
    	int id;	
    	int type;                             
    	int subMeshesOffset;
    	int modelDataOffset;		   
    	int nbSubMeshes;
        int renderingType;	
    };
    struct LODLevel {
        uint index_offset;
        uint index_count;
        int mesheltOffset;
        int meshletCount;
    };
    /*subMesh*/
    struct SubMesh {
    	AABB globalBounds;
    	int vertexOffset;
    	int indexOffset;
    	int primitiveType;
    	int materialId;
    	int nbVertices;
    	int nbIndexes;
    	int lodOffset;
    	int id;
        int lodLevel;
        int objectId;
        int meshletOffset;
        int meshletCount;
    };
    /*Matrices*/
    struct ModelData {
    	mat4 modelMatrix;
    	mat4 shadowProjMatrix;
    	mat4 borderMatrices;
    };        
    /*Matériaux*/
    struct MaterialData {   
        uint diffuseTextureIndex;
        uint specularTextureIndex;
        uint normalTextureIndex;
        uint metalnessTextureIndex;
        uint roughnessTextureIndex;
        uint aoTextureIndex;
        uint emissiveTextureIndex;
        uint materialType;
        uint taskOffset;
        uint nbVertices;
        uint nbIndexes;
        int instanceGroupId;
        uint vertsInstanceSet;
        uint materialId;
        uint nbBuffers;     
        uint opaque;
        uint pipelineType;    
    };
    struct IndirectElementsDrawCommand {
        uint index_count;
        uint instance_count;
        uint first_index;       // cf parametre offset de glDrawElements()
        uint vertex_base;
        uint instance_base;    
    };
    /*objets en entrée.*/
    layout(push_constant) uniform PushConstant {   
        uint currentFrame;
        uint opaqueMask;
    } pc;
    layout (set = 0, binding = 0) buffer ObjectTypesSSBO {
    	int types[];
    } objectTypes[MAX_FRAMES_IN_FLIGHT];
    layout (std430, set = 0, binding = 1) buffer inputObjectSSBO {
    	Object objects[];
    } inputObjectBuffer;
    /*SubMeshes en entrée.*/
    layout (std430, set = 0, binding = 2) buffer inputSubmeshesSSBO {
    	SubMesh subMeshes[];
    } inputSubmeshesBuffer;
    /*matrices en entrée.*/
    layout (std430, set = 0, binding = 3) buffer inputModelDataSSBO {
    	ModelData modelData[];
    } inputModelData;
    /*matériaux en entrée.*/
    layout (std430, set = 0, binding = 4) buffer inputMaterialDataSSBO {
    	MaterialData materialData[];
    } inputMaterialData[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*matériaux en sortie.*/
    layout (std430, set = 0, binding = 5) buffer outputMaterialDataSSBO {
    	MaterialData materialData[];
    } outputMaterialData[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*matrices des objets visibles pour les instances en sortie.*/
    layout (std430, set = 0, binding = 6) buffer outputModelDataSSBO {
    	ModelData modelData[];
    } outputModelData[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*Matrices des objets visible en sortie pour les non instances*/
    layout (std430, set = 0, binding = 7) buffer outputObjectDataSSBO {
    	SubMesh meshData[];
    } outputMeshesData[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*position dans le buffer de matrices de sortie pour les instance*/
    layout (std430, set = 0, binding = 8) buffer offsetInOutputModelDataSSBO {
    	uint modelDataOffset;
    } offsetInOutputModelData[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*position dans le buffer des matrices de sortie*/
    layout (std430, set = 0, binding = 9) buffer offsetInOutputMeshDataSSBO {
    	uint meshDataOffset;
    } offsetInOutputMeshData[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*Nombre de commandes pour le rendu indirect.*/
    layout (std430, set = 0, binding = 10) buffer outputIndirectDrawCountSSBO {
    	uint drawCount;
    } outputDrawCount[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    layout (std430, set = 0, binding = 11) buffer outputIndirectElementCommandSSBO {
    	IndirectElementsDrawCommand indirectElementsDrawCommands[];
    } outputIndirectElementsDrawCommands[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*position dans le buffer de commandes pour le rendu indirect.*/
    layout (std430, set = 0, binding = 12) buffer offsetInOutputElementsIndirectCommandSSBO {
    	uint offsetIndirectElementsDrawCommand;
    } offsetInOutputIndirectElementsDrawCommand[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    /*Buffer pour données de la frame*/
    layout (std430, set = 0, binding = 13) buffer offsetOutputMaterialSSBO {
    	uint materialOffset;
    } offsetInOutputMaterial[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    layout (std430, set = 0, binding = 14) buffer outputInstanceBaseSSBO {
    	uint instanceBase;
    } outputInstanceBase[NB_PRIMITIVE_TYPES*MAX_FRAMES_IN_FLIGHT];
    layout (std140, set = 0, binding = 15) uniform UniformBufferObject {
    	AABB frustrum;			
    	uint nbObjectTypes;
    	uint gridCellCount[5];    
        ivec4 gridCellSize[5];
        ivec4 nbCellsPerRow[5];    
        ivec4 gridSize[5];   
        ivec4 gridPos[5];
    } ubo[MAX_FRAMES_IN_FLIGHT];
    layout (std430, set=0, binding = 16) buffer LodLevelBuffer {
        LODLevel lodLevel[];
    } lodLevelData;
    layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
    bool intersects (AABB first, AABB second) {
        float hx1 = first.size.x * 0.5;
        float hy1 = first.size.y * 0.5;
        float hz1 = first.size.z * 0.5;
        float hx2 = second.size.x * 0.5;
        float hy2 = second.size.y * 0.5;
        float hz2 = second.size.z * 0.5;
        //Check the mins and max medians positions.
        float minX1 = first.center.x - hx1;
        float minX2 = second.center.x - hx2;
        float minY1 = first.center.y - hy1;
        float minY2 = second.center.y - hy2;
        float minZ1 = first.center.z - hz1;
        float minZ2 = second.center.z - hz2;
        float maxX1 = first.center.x + hx1;
        float maxX2 = second.center.x + hx2;
        float maxY1 = first.center.y + hy1;
        float maxY2 = second.center.y + hy2;
        float maxZ1 = first.center.z + hz1;
        float maxZ2 = second.center.z + hz2;
        //If the medians overlap, our two boxes intersects.
        for (int i = 0; i < 3; i++) {
            if (i == 0) {
                if (minX1 > maxX2 || maxX1 < minX2)
                    return false;
            } else if (i == 1) {
                if (minY1 > maxY2 || maxY1 < minY2)
                    return false;
            } else {
                if (minZ1 > maxZ2 || maxZ1 < minZ2)
                    return false;
            }
        }
        return true;
    }
    void main() {
        //debugPrintfEXT("nb object types : %i, %i, %i",gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, gl_GlobalInvocationID.z);
        Object object = inputObjectBuffer.objects[gl_GlobalInvocationID.x];
    	uint materialId = gl_GlobalInvocationID.y;
    	uint primitiveType = gl_GlobalInvocationID.z;
    	//debugPrintfEXT("nb object types : %v3f, %v3f, %i",ubo[pc.currentFrame].frustrum.center, ubo[pc.currentFrame].frustrum.size, ubo[pc.currentFrame].nbObjectTypes);
    	memoryBarrier();
    	for (uint t = 0; t < ubo[pc.currentFrame].nbObjectTypes; t++) {
    	    //debugPrintfEXT("type : %i,%i", t, object.type );
    		if (object.type == objectTypes[pc.currentFrame].types[t] && intersects(object.globalBounds, ubo[pc.currentFrame].frustrum)) {
    		    //debugPrintfEXT("Object in frustrum : %v3f %v3f", ubo[pc.currentFrame].frustrum.center, ubo[pc.currentFrame].frustrum.size);
                //debugPrintfEXT("nb sub meshes : %i", object.nbSubMeshes);			
                //Regroupement des données par matériaux et par type de primitive. (Batching)
                for (uint s = 0; s < object.nbSubMeshes; s++) {
                    SubMesh subMesh = inputSubmeshesBuffer.subMeshes[object.subMeshesOffset+s];
                    MaterialData material = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId];
                    //debugPrintfEXT("opaque mask : %i %i", rasterPipeline, material.pipelineType);
                    if ((pc.opaqueMask & material.opaque) != 0
                        && ((rasterPipeline & material.pipelineType) != 0) && subMesh.materialId == materialId && subMesh.primitiveType == primitiveType 
                        && intersects(subMesh.globalBounds, ubo[pc.currentFrame].frustrum)) {
                        //debugPrintfEXT("submesh in frustrum %i", s);
                        float dist = distance(ubo[pc.currentFrame].frustrum.center, subMesh.globalBounds.center);
                        float lodStep = 20.0;
                        int lod = clamp(int(dist / lodStep), 0, 4);
                        //debugPrintfEXT("primitiveType : %i", subMesh.primitiveType);
                        //Vérifie si les sommets pour l'instance n'ont pas déjà été ajoutés. (Les instances sont regroupée par instanceGroupId dans matériaux)
                        //Si le matériel est instancé.
                        if (inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].instanceGroupId != -1) {
                                debugPrintfEXT("Instanced! %i", inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].instanceGroupId);
     
                            uint instanceBase = atomicAdd(outputInstanceBase[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].instanceBase, 1);
     
                                //Si la commande n'est pas encore ajoutée pour cette instance, on l'ajoute.
                            if(inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].vertsInstanceSet == 0) {
                                inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].vertsInstanceSet = 1;
                                uint indirectElementsDrawCommandOffset = atomicAdd(outputDrawCount[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].drawCount, 1);
                                inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].taskOffset = indirectElementsDrawCommandOffset;   
                                IndirectElementsDrawCommand indirectElementsDrawCommand;
                                indirectElementsDrawCommand.index_count = lodLevelData.lodLevel[subMesh.lodOffset+lod].index_count;
                                indirectElementsDrawCommand.first_index = subMesh.indexOffset + lodLevelData.lodLevel[subMesh.lodOffset+lod].index_offset;
                                /*indirectElementsDrawCommand.index_count = subMesh.nbIndexes;
                                indirectElementsDrawCommand.first_index = subMesh.indexOffset;*/
                                indirectElementsDrawCommand.instance_base = instanceBase;
                                indirectElementsDrawCommand.vertex_base = subMesh.vertexOffset;
                                outputIndirectElementsDrawCommands[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].indirectElementsDrawCommands[indirectElementsDrawCommandOffset] = indirectElementsDrawCommand;
                                MaterialData material = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId];
                                material.materialId = materialId;
                                outputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[indirectElementsDrawCommandOffset] = material;
                            }
                            ModelData modelData = inputModelData.modelData[object.modelDataOffset];
                            outputModelData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].modelData[instanceBase] = modelData;
                            //nombre d'instances + 1.
                            uint indirectElementsDrawCommandOffset = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].taskOffset;
                            outputIndirectElementsDrawCommands[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].indirectElementsDrawCommands[indirectElementsDrawCommandOffset].instance_count++;
                            //Matériel non instancé.
                        } else {
     
                            uint indirectElementsDrawCommandOffset = atomicAdd(outputDrawCount[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].drawCount, 1);
                            uint instanceBase = atomicAdd(outputInstanceBase[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].instanceBase, 1);
                            uint offsetInOutputMeshData = atomicAdd(offsetInOutputMeshData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].meshDataOffset, 1);            
                            //debugPrintfEXT("indexes! %i, draw count : %i", instanceBase, indirectElementsDrawCommandOffset );
                            IndirectElementsDrawCommand indirectElementsDrawCommand;
                            /*if (subMesh.id == 1590)
                                debugPrintfEXT("submesh id : %i, vertex offset : %i, nb vertices : %i", subMesh.id, subMesh.vertexOffset, subMesh.nbVertices);*/
                            /*if (subMesh.lodOffset + lod >= 215)
                                debugPrintfEXT("lodOffset=%d lod=%d\n", subMesh.lodOffset, lod);*/
                            indirectElementsDrawCommand.index_count = lodLevelData.lodLevel[subMesh.lodOffset+lod].index_count;
                            indirectElementsDrawCommand.first_index = subMesh.indexOffset + lodLevelData.lodLevel[subMesh.lodOffset+lod].index_offset;
                            /*indirectElementsDrawCommand.index_count = subMesh.nbIndexes;
                            indirectElementsDrawCommand.first_index = subMesh.indexOffset;*/
                            indirectElementsDrawCommand.instance_base = instanceBase;
                            indirectElementsDrawCommand.vertex_base = subMesh.vertexOffset;
                            indirectElementsDrawCommand.instance_count = 1;
                            //debugPrintfEXT("offsets : %i, %i, %i, %i", indirectElementsDrawCommand.first_index, indirectElementsDrawCommand.index_count, indirectElementsDrawCommand.instance_base, indirectElementsDrawCommand.vertex_base);
                            //debugPrintfEXT("lod infos : %i, %i",subMesh.lodLevel[lod].index_offset,subMesh.lodLevel[lod].index_count);
                            //debugPrintfEXT("instance base %i", instanceBase);
     
                            outputIndirectElementsDrawCommands[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].indirectElementsDrawCommands[indirectElementsDrawCommandOffset] = indirectElementsDrawCommand;
                            //debugPrintfEXT("indirect elements draw command offset : %i", indirectElementsDrawCommandOffset);
                            ModelData modelData = inputModelData.modelData[object.modelDataOffset];
                            //debugPrintfEXT("model data matrix : %v4f\n%v4f\n%v4f\n%v4f", modelData.modelMatrix[0], modelData.modelMatrix[1], modelData.modelMatrix[2], modelData.modelMatrix[3]);
                            //debugPrintfEXT("object data offset : %i",objectDataOffset);
                            outputModelData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].modelData[instanceBase] = modelData;
                            //debugPrintfEXT("offset model : %i", instanceBase);
                            MaterialData material = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId];
                            //material.materialId = materialId;
                            //debugPrintfEXT("culling shader draw id : %i, material id : %i", indirectElementsDrawCommandOffset, materialId);
                            /*if (subMesh.materialId == 1)
                                debugPrintfEXT("sm id : %i, diffuse tex id : %i", subMesh.id, material.diffuseTextureIndex);*/
                            outputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[indirectElementsDrawCommandOffset] = material;
     
     
                            outputMeshesData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].meshData[offsetInOutputMeshData]  = subMesh;
                            //debugPrintfEXT("material datas %v2f", material.uvScale);
                            //debugPrintfEXT("Output Model Matrix : %i\n%v4f\n%v4f\n%v4f\n%v4f",objectDataOffset,outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[0], outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[1], outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[2], outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[3]);
                        } 
                    } /*else {
                        debugPrintfEXT("doesn't intersects");
                    } */             
                }
    		}
    	}
    }
    Curieux..., que je n'ai pas les bonnes données dans mon compute shader pour les offsets que côté CPU.

    PS : En gros je fais comme cela : j'ajoute tout les sommets et indices des mes meshs de la scène dans des buffers, et je passe pour chaque mesh, les offsets vers ses sommets en indices dans mes buffers, ainsi que le nombre d'indices pour ce mesh. Et mon compute shader génère les draw commandes pour chaque mesh visible. (En fonction du lod calculé avec la distance par rapport à la caméra) Chaque niveau de lod à ses offsets d'indices et ses nombres d'indices.

  9. #469
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 073
    Billets dans le blog
    12
    Par défaut
    As-tu essayé d'aligner tes données sur 16 bytes ? (TOUTES les données que tu mets dans les SSBO aussi)
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  10. #470
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut
    Bonjour, oui j'ai essayé. Il faudrait que je puisse trouver le code source d'un moteur de jeu existant qui fonctionne pour voir quel technique de rendu il utilise (si c'est la même technique que moi) et ainsi comprendre pourquoi mes shaders lisent de la merde (parfois des données non initailisée même) et que j'ai des triangles manquant à l'affichage. (Ou aléatoire) Je n'avais pas se soucis avec opengl et mon architecture CPU-driven mais ici je n'ai pas les même offsets avec le CPU et le GPU. Je pense que je vais reprendre mon backend opengl cpu driven.

  11. #471
    Invité de passage
    Homme Profil pro
    Analyse système
    Inscrit en
    Septembre 2026
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Septembre 2026
    Messages : 20
    Par défaut
    Mais t'avais pas dit 3 posts plus haut que t'allais faire un jeu sur unity ?

  12. #472
    Membre expérimenté
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 163
    Par défaut
    Je pense que je vais reprendre mon backend opengl cpu driven.
    Non. C'est pas vrai. On est reparti sur autre chose ? Encore un virage à 180 degrés ?

  13. #473
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 664
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 664
    Par défaut
    Citation Envoyé par Laurent7601 Voir le message
    et que j'ai des triangles manquant à l'affichage.
    je pense que ça vient d'un problème de normales perpendiculaires à la triangulation.
    Et non un problème de API de rendu.
    Il faut revoir comment les meshes 3d sont construites.
    Ne pas perdre de vue que pour utiliser la technique du z buffer il faut que les normales à une triangulation bref à une face de polygone soit correctement définies.
    Citation Envoyé par Laurent7601 Voir le message
    et ainsi comprendre pourquoi mes shaders lisent de la merde (parfois des données non initailisée même)
    quel format de fichier 3d utilisé ? Est-ce que l'objet en 3d est correctement affiché dans un logiciel de 3d mettons Blender ?

  14. #474
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 073
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Laurent7601 Voir le message
    Bonjour, oui j'ai essayé. Il faudrait que je puisse trouver le code source d'un moteur de jeu existant qui fonctionne pour voir quel technique de rendu il utilise (si c'est la même technique que moi) et ainsi comprendre pourquoi mes shaders lisent de la merde (parfois des données non initailisée même) et que j'ai des triangles manquant à l'affichage. (Ou aléatoire) Je n'avais pas se soucis avec opengl et mon architecture CPU-driven mais ici je n'ai pas les même offsets avec le CPU et le GPU. Je pense que je vais reprendre mon backend opengl cpu driven.
    Même les data struct GLSL qui correspondent à des data struct Vulkan ? (genre VkDrawIndexedIndirectCommand, VkDrawMeshTasksIndirectCommandEXT, qui ne sont pas alignées sur 16 bytes et pour lesquelles il faut donc ruser, si on les remplit via des passes GPU: dans le GLSL j'utilise des tableaux de uint).
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  15. #475
    Invité de passage
    Homme Profil pro
    Analyse système
    Inscrit en
    Septembre 2026
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Septembre 2026
    Messages : 20
    Par défaut
    Ah non c'était unreal enfin ça ne change pas trop quoi. Je pense qu'après 10ans de dev tu ne devrais pas avoir ces problèmes ça me semble basique comme problème. Si déjà la base est bancale laisse le reste à ceux qui ont un niveau en maths en ingénierie 3d afficher des polygones avec ta carte graphique et occupe toi du reste de la conception d'un jeu vidéo.

    Si ça avait dû marcher ça aurait déjà marché...

  16. #476
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 073
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Mat.M Voir le message
    je pense que ça vient d'un problème de normales perpendiculaires à la triangulation.
    Et non un problème de API de rendu.
    Il faut revoir comment les meshes 3d sont construites.
    Ne pas perdre de vue que pour utiliser la technique du z buffer il faut que les normales à une triangulation bref à une face de polygone soit correctement définies.

    quel format de fichier 3d utilisé ? Est-ce que l'objet en 3d est correctement affiché dans un logiciel de 3d mettons Blender ?
    Moi je pense à des soucis d'alignement lors du remplissage des buffers d'indirect...
    La scène est au format FBX et n'a aucun soucis de faces inversées à cet endroit.
    Ca ne vient clairement pas de "normales perpendiculaires à la triangulation" (pour ce que ça peut vouloir dire), ce n'est d'ailleurs pas la normale qui définit le sens d'affichage d'une face, mais l'ordre d'affichage des sommets (depuis lequel la normale peut être déduite).
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  17. #477
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 664
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 664
    Par défaut
    Citation Envoyé par dragonjoker59 Voir le message
    La scène est au format FBX et n'a aucun soucis de faces inversées à cet endroit.mais l'ordre d'affichage des sommets (depuis lequel la normale peut être déduite).
    D'une part est ce que les vecteurs qui permettent de dessiner la scène sont-ils normalisés ?
    Si ce n'est pas le cas c'est évident qu'on obtient n'importe quoi à l'écran.
    encore une fois est-ce que c'est correctement affiché avec un logiciel de 3d comme Blender ?

    Citation Envoyé par dragonjoker59 Voir le message
    ce n'est d'ailleurs pas la normale qui définit le sens d'affichage d'une face, mais l'ordre d'affichage des sommets (depuis lequel la normale peut être déduite).
    ok d'accord il me semble ne pas avoir parlé de sens d'affichage mais de la technique du Z-buffer
    Ensuite j'ai demandé à la personne à l'origine de ce fil de discussion de voir ce qui se passe avec Blender

  18. #478
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut
    Salut! On dirait bien que c'est un soucis de mauvais alignement avec le GPU. Les push constant doivent aussi être alignés sur 16 ? Le soucis avec vulkan c'est que dès qu'un élément est décalé ça décale tout le reste.

  19. #479
    Membre actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2023
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Novembre 2023
    Messages : 349
    Par défaut
    Ok bon j'ai trouvé pour certains bugs d'affichage, mesh_opi_simply me supprimait des triangles (par exemple dans le sol) donc, j'avais des trous ici : (J'avais même des lods level avec 0 indices pour les objets avec peut d'indices)

    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
    void VertexArray::updateLods() {
                float ratios[] = {1.0f, 0.5f, 0.25f, 0.12f, 0.06f};
                std::vector<uint32_t> current = indices; // copie
                indices.clear();
                unsigned int level = 0;
     
                for (float r : ratios)
                {
                    std::vector<unsigned int> lod(current.size());
                    size_t count = meshopt_simplify(
                    lod.data(),
                    current.data(),
                    current.size(),
                    reinterpret_cast<const float*>(m_vertices.data()),
                    m_vertices.size(),
                    sizeof(Vertex),
                    r,
                    1e-2f);
                    lod.resize(count);
                    LODLevel lodLevel;
                    lodLevel.indexOffset = indices.size();
                    lodLevel.indexCount = lod.size();
                    lods[level] = lodLevel;
                    indices.insert(indices.end(), lod.begin(), lod.end());
                    current = lod;
                    /*std::cout<<"indices : "<<indices.size()<<std::endl;
                    std::cout<<"level : "<<lods[level].indexOffset<<","<<lods[level].indexCount<<std::endl;*/
                    level++;
                }
            }
    Depuis que je n'utilise plus les lods, je n'ai plus ces soucis des triangles manquant, par contre, derrière la scènes, j'ai encore des fenêtre dans le vide, comme-ci la scène était incomplète.

  20. #480
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 073
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Mat.M Voir le message
    D'une part est ce que les vecteurs qui permettent de dessiner la scène sont-ils normalisés ? Si ce n'est pas le cas c'est évident qu'on obtient n'importe quoi à l'écran.
    Je suppose que tu parles des normales... Le fait qu'elles ne soient pas normalisées ne provoquerait pas ce genre de soucis

    Citation Envoyé par Mat.M Voir le message
    ok d'accord il me semble ne pas avoir parlé de sens d'affichage mais de la technique du Z-buffer
    C'est vrai, voyons ce que tu en as dit :
    Ne pas perdre de vue que pour utiliser la technique du z buffer il faut que les normales à une triangulation bref à une face de polygone soit correctement définies.
    Absolument pas, pour écrire dans le depth buffer il n'y a pas besoin de la normale.

    Bistro est une scène de test fournie par NVIDIA, qui fonctionne très bien sous Lumberyard, Castor3D, et plein d'autres moteurs (et sous Maya).
    La scène n'a pas de problème !!
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

Discussions similaires

  1. MANU, un nouveau moteur de jeux vidéo ne nécessitant pas de code
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 10
    Dernier message: 12/04/2020, 14h53
  2. Intrinsic : un nouveau moteur de jeux open source basé sur Vulkan
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 18
    Dernier message: 23/11/2016, 11h09
  3. Un nouveau moteur de jeux vidéo voit le jour : Lumberyard, développé par Amazon
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 6
    Dernier message: 11/02/2016, 15h02
  4. Paladin : un nouveau projet de moteur de jeux par la communauté Mozilla.
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 19
    Dernier message: 09/09/2011, 12h40
  5. Creer un nouveau moteur de jeux
    Par khenissi dans le forum Moteurs de jeux vidéo
    Réponses: 4
    Dernier message: 28/07/2010, 14h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo