11
votes

Plusieurs images de texture mélangées ensemble sur un sol 3D

Comment les jeux informatiques rendent-ils leur sol? J'utiliserai une hauteur de hauteur de géométrie (bien que je l'optimise ultérieurement), mais je me demande quelle est la meilleure technique, par exemple, de «peindre» mon sol; L'herbe la plus partout, les chemins de terre ici et là, gravier dans des villes et transitions lisses entre chaque type de matériau.

Est-ce que je viens d'utiliser une énorme texture pré-cuit? Cela semble très inefficace, lorsque je pouvais tuiler des textures existantes. Alors puis-je utiliser une énorme carte alpha pour chaque texture existante? En théorie, ça me semble bien, mais comment puis-je réellement faire cela et quelles sont les conséquences? Je ne sais vraiment pas où commencer, et mes recherches Google ne se révèlent pas très efficaces.

Je préférerais ne pas avoir à "snaper" la texture sur la grille (c'est-à-dire que l'espace (0,0) est de l'herbe, l'espace (0,2) est la saleté, l'espace (0,1) est la transition d'herbe-saleté) ; Je préférerais être capable de peindre arbitrairement pour que cela semble plus convaincant. Bien sûr, ce serait le moyen facile, mais c'est trop de sacrifice de qualité graphique et de «réalisme».

Je cherche surtout la théorie et les options ici. J'utilise OpenGL, donc si vous pouvez fournir des conseils en ce qui concerne la manière de faire des choses de OpenGL, et des fonctions que je n'ai peut-être jamais entendu parler de ce qui serait génial.

Juste pour clarification, Oblivion est une bonne référence sur ce que je cherche. Je ne sais pas comment la géométrie du sol est (Hauteur, des modèles 3D statiques, etc.) mais leur terrain a des types de sol différents et des transitions lisses entre eux, comme je parle de. Voici un exemple d'image, remarquez comment le cobblestone se fond dans l'herbe, irréaliste mais en douceur: http://www.elitistnob.com/images/oblivion%202006-05-21%2008-38-25-15.jpg

Aussi, je pense que j'ai lu à ce sujet dans l'un des livres de gemmes de programmation de jeu, mais je ne l'ai pas accordé à l'époque, et maintenant que c'est l'été, je n'ai pas accès à la bibliothèque de ma université pour vérifier ! Je cherche des tables de contenu en ce moment et je vais éditer si je le trouve, mais je ne pourrai toujours pas la lire avant mi-août.

Edit: Ah Man, la programmation de jeux GEMS 7 a un chapitre 5.8 intitulée "Cartographie de grandes textures pour le rendu de terrain extérieure", cela ressemble exactement à ce dont j'ai besoin, mais ma bibliothèque de toi n'a même pas ce livre! Je n'ai rien trouvé exactement comme celui-ci dans les autres livres de gemmes de programmation de jeux, bien qu'un couple disposait d'articles de géométrie de terrain.


1 commentaires

Oblivion utilise des cartes hautes, par.


6 Réponses :


1
votes

Le préblaquage est très certainement inefficace. En fait, il est le plus efficace, car votre code d'exécution n'a pas à faire de nombreux calculs ou autres calculs. Il suffit de rendre la texture. Bien entendu, les techniques dynamiques offrent une simplification de lachaise et d'autres options.


1 commentaires

Cependant, gardez à l'esprit que de simples opérations de mélange sont essentiellement gratuites sur la plupart du matériel. Les principaux coûts de coûts ici proviennent de la quantité de mémoire de texture que vous utilisez et la fréquence à laquelle vous changez entre eux, ce qui rend les textures pré-cuits chères dans de nombreuses situations.



0
votes

En règle générale, les zones de transition sont préconisées, bien qu'il soit possible de faire certaines choses avec des canaux alpha et un mélange de textures.


0 commentaires

10
votes

J'ai récemment écrit un petit moteur de rendu de terrain à OpenGL qui fait quelque chose de similaire à ce dont vous parlez. La technique que j'utilise est la mieux décrite comme texture éclaboussant .

J'utilise cinq textures pour accomplir cela . Quatre de ces textures sont des textures détaillées: l'herbe, la roche, l'eau et le sable. Ces textures sont des textures mineures, 512x512 et sont carrelées sur le terrain. La cinquième texture est une mixmap. La MixMap est une texture géante qui couvre tout le terrain, dans mon cas est 4096x4096. P>

MixMap h2>

Ce mélange utilise tous les 4 canaux de couleur (R, G, B, A) pour décrire la quantité de texture de détail à afficher à cet emplacement spécifique. J'utilise le canal de couleur rouge pour déterminer la manière dont le sable est opaque, le vert est pour l'herbe, le bleu est pour l'eau et l'alpha est pour la roche. Cette mixmap est calculée sur la base de la chaîne de hauteur à l'initialisation et j'utilise des altitudes pour déterminer ces valeurs. Par exemple, près du niveau de la mer, je veux surtout de l'eau, je définit donc une valeur élevée dans le canal bleu et les valeurs basses dans les autres canaux. Alors que je suis plus élevé dans les montagnes, je définissais le canal de couleur alpha à une valeur élevée puisque je veux beaucoup de texture rocheuse, mais je définit tous les autres canaux de couleur sur des valeurs inférieures. P>

Shader

Ce mixmap est ensuite utilisé dans le shader de fragment, où je prends ces canaux de couleur de la mixmap et utilisez-les pour combiner les textures de détail. Voici le code GLSL que j'utilise pour le fragment Shader: P>

uniform sampler2D alpha;
uniform sampler2D grass;
uniform sampler2D water;
uniform sampler2D rock;
uniform sampler2D sand;
uniform float texscale;

varying vec3 normal, lightDir ;

void main()
{
   // Get the color information
   vec3 alpha    = texture2D( alpha, gl_TexCoord[0].st ).rgb;
   vec3 texSand  = texture2D( sand, gl_TexCoord[0].st * texscale ).rgb;
   vec3 texGrass = texture2D( grass,  gl_TexCoord[0].st * texscale ).rgb;
   vec3 texWater = texture2D( water, gl_TexCoord[0].st * texscale ).rgb;
   vec3 texRock  = texture2D( rock,  gl_TexCoord[0].st * texscale ).rgb;

   // Mix the colors together
   texSand *= mixmap.r;
   texGrass = mix(texSand,  texGrass, mixmap.g);
   texWater = mix(texGrass, texWater, mixmap.b);
   vec3 tx  = mix(texWater, texRock,  mixmap.a);

   // Lighting calculations
   vec3 dl = gl_LightSource[0].diffuse.rgb;   
   vec3 al = gl_LightSource[0].ambient.rgb;
   vec3 n = normalize(normal);
   vec3 d = tx * (dl * max( dot ( n, lightDir), 0.0 ) + al );   

   // Apply the lighting to the final color   
   vec4 finalColor = vec4( min(d, 1.0), 1.0);
   gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor);
}


2 commentaires

Le vôtre était le plus populaire et le plus semblable à ce que j'ai fini par faire, je vais le marquer comme la réponse acceptée. Cependant, au lieu d'utiliser des shaders, j'ai utilisé une texture opengl combinant. J'ai fait un doc.com de toutes les pages que j'ai utilisées lors de la recherche de cette technique et de les mettre ici: Docs. google.com/view?id=AJK9HXNZ95QM_107FNDCP6C8 La meilleure partie de celui-ci est qu'il ne nécessite pas de shader, et cela permet autant de textures et d'alphamaps que vous le souhaitez. J'espère que ce sera une ressource précieuse pour quelqu'un là-bas.


Ce shader n'a pas l'air bien. Vous avez déclaré deux fois alpha, il aurait plus de sens si le second était "MixMap" qui, autrement, n'est déclaré nulle part. Il devra également être un Vec4 que vous utilisez 4 composants. En outre, et je suis certes nitpicking ici, 4 valeurs alpha sont une sorte de superflue. Multiplier Texsand par le composant rouge est essentiellement un contrôle de luminosité pour Texsand. Avec 4 composants, vous pourriez aussi bien faire des pondérations, c'est-à-dire que vous multipliez chaque texture par la pondération et les résumer - il n'y aurait pas d'ordre de priorité, et ce serait un peu moins de travail pour le shader de fragment.



1
votes

Je semble avoir fabriqué le grand "Megatexture" (on parle 32k ^ 2-128k ^ 2) Travailler dans Quakewars.

Il y a un Q & A intéressant avec Carmack à ce sujet à P>

http://web.archive.org/web/20080121072936/http://www.gamerwithin.com/?view=article&article=1319&cat=2


3 commentaires

ça ... semble incroyablement énorme cependant. (128 000 * 128 000 * 3) * octets = 46 875 mégaoctets qui supposent 3 octets par pixel (couleur 24 bits, sans alpha) ... même si vous déclassez et dites 1 octet par pixel (ce qui serait juste merci) , c'est toujours 15 625 Mo de données. Et je présume qu'ils la compressent, mais même avec une très bonne compression, la taille finale doit toujours avoir la taille d'un DVD (ou deux) avec seulement des pixels de 8 bits ... c'est juste fou. Est-ce que je manque quelque chose?


32k x 32k est moins phénoménal, à 2,86 Go pour 3 octets par pixel. Après la compression, ce serait raisonnable; En supposant que la texture du paysage soit si importante qu'il faut adopter une si grande quantité d'espace. Mais avec des disques durs étant si gros aujourd'hui et que les jeux étant naturellement âgés de plus de 5 ans et plus au haut de gition, je suppose que c'est acceptable.


Merci pour le lien aussi. Je l'ai lu un peu. Je pense que je vais aller pour une approche différente. Bien qu'une grande texture soit faisable, c'est un déchet à moins que je voulais modifier manuellement le tout. La plupart du temps, je voudrais simplement pulvériser quelques images en maçonneuses quand même, il n'ya donc pas besoin d'avoir un pixel-parfait "Megatexture". Je vais continuer à regarder des solutions alternatives.



0
votes

Vous ne pouvez pas fuir le carrelage, mais peut-être que si vous utilisez une texture de base qui fait un peu de bruit sur le sol, il semble qu'il n'y ait pas de carrelage ...

Utilisez la texture de base avec les mêmes coordonnées de texture de texture alpha. La texture de base peut être n'importe quoi .. une image de Satelite, ou une texture d'herbe .. Cela correspondrait parfaitement s'il est lié à votre forme de terre ..

Et essayez d'utiliser des textures transparentes pour votre herbe, vos textures de roche ... Il ne résout pas mais le rend comme il n'y a pas de problème


0 commentaires

1
votes

Une des manières standard utilisées par exemple dans le moteur source (HL2) est d'avoir un par sommet alpha à mélanger entre deux matériaux. Les matériaux sont généralement constitués d'au moins un albédo et une carte normale. Dans le moteur source, seuls 2 matériaux par "texture de mélange" sont autorisés, ce qui est un type de merde.

Si vous voulez plus de 2 matériaux, vous devez le simuler en texturant différents déplacements avec des textures différentes, en veillant à ce que n'importe quel tuile ne contienne que 2 matériaux au plus.

Avoir un alpha per-vertex plutôt que par pixel donne une assez mauvaise apparence. Comme vous l'avez noté dans Oblivion, vous obtenez des pavés mélangés en douceur dans le sable par exemple. Il y a une solution pour ce défaut; Vous utilisez une autre texture qui module l'alpha sur une base pixelle, de sorte que les fissures entre les pierres de pavillon remplissent facilement, mais les hauts des pierres de pavillon restent à près de 1,0 alpha jusqu'à ce que le sommet alpha interpolé soit presque 0 pour le cobble Matériel. Cela peut rendre la transition vraiment sympa au lieu d'un frottis laids.

Vous pouvez également utiliser une texture faible résolution contenant les alphas (mais encore beaucoup plus élevé que 1 alpha par sommet). Les textures de Terain carrelées peuvent être 2048x2048, mais la texture utilisée pour les mélanger tolérance n'a pas besoin de résolution par Texel. Une texture de 256x256 8 bits par Texel n'est que de 96 Ko avec des cartes MIP.


0 commentaires