Question

J'écris un Minecraft comme un monde de bloc 3D statique en C ++ / OpenGL. Je travaille dans l'amélioration des fractures et jusqu'à présent, j'ai mis en œuvre un abattage de Frustum à l'aide d'un Octree. Cela aide, mais je vois toujours des fréquences d'images modérées à mauvaises. L'étape suivante serait d'abattre les cubes qui sont cachés au point de vue par des cubes plus proches. Cependant, je n'ai pas pu trouver de nombreuses ressources sur la façon d'accomplir cela.

Était-ce utile?

La solution

Créez une cible de rendu avec un Buffer Z (ou "Defth Buffer") activé. Assurez-vous ensuite de trier tous vos objets opaques afin qu'ils soient rendus d'avant en arrière, c'est-à-dire ceux les plus proches de l'appareil photo d'abord. Tout ce qui utilise le mélange alpha doit encore être rendu à l'avant, après avoir rendu tous vos objets opaques.

Une autre technique est l'abattage d'occlusion: vous pouvez "rendu à sec" votre géométrie, puis savoir combien de pixels ont échoué au test de profondeur. Il y a un support de requête d'occlusion dans DirectX et OpenGL, bien que tous les GPU ne puissent pas le faire.

L'inconvénient est que vous avez besoin d'un délai entre le rendu et la récupération du résultat - en fonction de la configuration (comme lors de l'utilisation du carrelage prédié), il peut être un cadre complet. Cela signifie que vous devez être créatif là-bas, comme rendre une boîte de délimitation plus grande que l'objet lui-même et rejeter les résultats après une coupe de caméra.

Et une autre chose: une solution plus traditionnelle (que vous pouvez utiliser simultanément avec l'abattage d'occlusion) est un système de pièce / portail, où vous définissez les régions comme des "pièces", connectées via des "portails". Si un portail n'est pas visible depuis votre pièce actuelle, vous ne pouvez pas voir la pièce qui y est connectée. Et même c'est le cas, vous pouvez cliquer sur votre fenêtre pour ce qui est visible via le portail.

Autres conseils

L'approche que j'ai adoptée Ce rendu de niveau minecraft est essentiellement un remplissage d'inondation limité en frustum. Les morceaux 16x16x128 sont divisés en morceaux 16x16x16, chacun avec un VBO avec la géométrie pertinente. Je commence un remplissage dans la grille de morceaux à l'emplacement du joueur pour trouver des morceaux à rendre. Le remplissage est limité par:

  1. La vue Frustum
  2. Chunklets solides - Si le côté entier d'un morceau est des blocs opaques, alors le décalage d'inondation n'entrera pas dans le morceau dans cette direction
  3. Direction - L'inondation ne s'inverse pas, par exemple: si le morceau actuel est au nord du morceau de départ, ne pas inonder dans le morceau au sud

Cela semble fonctionner correctement. Je suis sur Android, donc même si une analyse plus complexe (Antiportals comme indiqué par Mike Daniels) entraînerait plus de géométrie, je suis déjà limité au processeur, donc il n'y a pas beaucoup de points.

Je viens de voir votre réponse à Alan: l'abattage n'est pas votre problème - c'est quoi et comment vous envoyez à OpenGL qui est lent.

Quoi de dessiner: Ne rendez pas un cube pour chaque bloc, rendez les faces de blocs transparents qui bordaient un bloc opaque. Considérez un cube 3x3x3 de, disons, des blocs de pierre: il est inutile de dessiner le bloc central car il n'y a aucun moyen que le joueur puisse le voir. De même, le joueur ne verra jamais les visages entre deux blocs de pierre adjacents, alors ne les dessinez pas.

Comment dessiner: Comme l'a noté ALAN, utilisez VBOS pour laver la géométrie. Vous ne croirez pas à quel point ils rendent les choses plus rapides.

Une approche plus facile, avec un minimum de modifications à votre code existant, serait d'utiliser listes d'affichage. C'est ce que Minecraft utilise.

Combien de blocs rendez-vous et sur quel matériel? Le matériel moderne est très rapide et est très difficile à submerger avec la géométrie (sauf si nous parlons d'une plate-forme portable). Sur n'importe quel matériel de bureau modérément récent, vous devriez pouvoir rendre des centaines de milliers de cubes par cadre à 60 images par seconde sans aucune astuce de désabonnement.

Si vous dessinez chaque bloc avec un appel de tirage séparé (Gldrawelements / tableaux, glbegin / glend, etc.) (points bonus: n'utilisez pas Glbegin / Glend), ce sera votre goulot d'étranglement. C'est un piège commun pour les débutants. Si vous faites cela, vous devez regrouper tous les triangles qui partagent des paramètres de texture et d'ombrage en un seul appel pour chaque configuration. Si la géométrie est statique et ne change pas de cadre en trame, vous voulez en utiliser un Objet tampon de sommet pour chaque lot de triangles.

Cela peut toujours être combiné avec une rupture de Frustum avec un Octree si vous n'avez généralement qu'une petite partie de votre monde de jeu total dans la vue Frustum en même temps. Les tampons de sommet sont toujours chargés statiquement et non modifiés. FRUSTUM réduisez l'OCTREE pour générer uniquement les tampons d'index pour les triangles dans le Frustum et télécharger dynamiquement chaque trame.

Si vous avez des surfaces proches de la caméra, vous pouvez créer un frustum qui représente une zone qui n'est pas visible et rétracter des objets qui sont entièrement contenus dans ce frustum. Dans le diagramme ci-dessous, C est la caméra, | est une surface plane près de la caméra, et la région en forme de frustum composée de . représente la zone occluse. La surface est appelée un antiportal.

        .
       ..
      ...
     ....
    |....
    |....
    |....
    |....
C   |....
    |....
    |....
    |....
     ....
      ...
       ..
        .

(Vous devez bien sûr également activer les tests en profondeur et l'écriture de profondeur comme mentionné dans d'autres réponses et commentaires - c'est très simple à faire dans OpenGL.)

L'utilisation d'un bouffon z garantit que les polygones se chevauchent correctement.

L'activation du test de profondeur fait que chaque opération de dessin vérifie le buffre Z avant de placer des pixels sur l'écran.

Si vous avez des objets convexes, vous devez (pour les performances) activer la backface culling!

Exemple de code:

glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE);

Vous pouvez modifier le comportement de glCullFace () passer GL_FRONT ou GL_BACK ...

glCullFace(...);

// dessine le "monde du jeu" ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top