Sunday, 8 January 2017

Déplacement Moyenne Circulaire Tampon

Chapitre 14 Maintenant que vous le savez Ce chapitre n'a pas d'objectifs de la même manière que les chapitres précédents. C'est tout simplement une collection de sujets qui décrivent des idées que vous pourriez trouver utiles pour votre application. Certains sujets, tels que la gestion des erreurs, ne correspondent pas à d'autres catégories, mais sont trop courts pour un chapitre entier. OpenGL est une sorte de sac d'outils de bas niveau maintenant que vous connaissez ces outils, vous pouvez les utiliser pour mettre en œuvre des fonctions de niveau supérieur. Ce chapitre présente plusieurs exemples de ces capacités de niveau supérieur. Ce chapitre traite de diverses techniques basées sur des commandes OpenGL qui illustrent certains des usages non évidents auxquels vous pouvez mettre ces commandes. Les exemples ne sont pas dans un ordre particulier et ne sont pas liés entre eux. L'idée est de lire les titres de section et de sauter aux exemples que vous trouvez intéressants. Pour votre commodité, les titres sont énumérés et expliqués brièvement ici. Remarque: La plupart des exemples du reste de ce guide sont complets et peuvent être compilés et exécutés en l'état. Dans ce chapitre, cependant, il n'y a pas de programmes complets, et vous devez faire un peu de travail sur votre propre pour les faire fonctionner. La gestion des erreurs vous indique comment vérifier les conditions d'erreur OpenGL. La version que j'utilise décrit comment obtenir des détails sur l'implémentation, y compris le numéro de version. Cela peut être utile pour écrire des applications qui sont rétrocompatibles avec les versions antérieures d'OpenGL. Les extensions de la norme présentent des techniques permettant d'identifier et d'utiliser des extensions spécifiques au fournisseur à la norme OpenGL. Cheesy Translucency explique comment utiliser les pointillés polygones pour obtenir une translucidité, ce qui est particulièrement utile lorsque vous n'avez pas de matériel de mélange disponible. Un Easy Fade Effect montre comment utiliser les polygones pour créer l'effet d'un fondu dans l'arrière-plan. Sélection d'objet L'utilitaire Back Buffer décrit comment utiliser le tampon arrière dans un système à double tampon pour gérer la sélection d'objet simple. Cheap Image Transformation explique comment dessiner une version distordue d'une image bitmap en dessinant chaque pixel comme un quadrilatère. Affichage des calques explique comment afficher plusieurs couches de matériaux différents et indiquer où les matériaux se chevauchent. Antialiased Characters décrit comment dessiner des polices plus lisses. Dessiner des points ronds décrit comment dessiner des points proches. Interpoler des images montre comment mélanger doucement d'une image à l'autre. Faire des décalcomanies explique comment dessiner deux images, où l'on est une sorte de décalcomanie qui devrait toujours apparaître au-dessus de l'autre. Dessin rempli, les polygones concaves à l'aide du tampon Stencil vous dit comment dessiner des polygones concaves, des polygones non-simples, et des polygones avec des trous en utilisant le tampon stencil. Trouver des régions d'interférence décrit comment déterminer où se chevauchent les pièces tridimensionnelles. Ombres décrit comment dessiner des ombres d'objets éclairés. Hidden-Line Removal explique comment dessiner un objet wireframe avec des lignes cachées supprimées en utilisant le tampon stencil. Texture-Mapping Applications décrit plusieurs utilisations intelligentes pour la cartographie des textures, telles que les images tournantes et déformées. Dessiner Image protégée en profondeur vous explique comment combiner des images dans un environnement tampon en profondeur. Dirichlet Domains explique comment trouver le domaine de Dirichlet d'un ensemble de points en utilisant le tampon de profondeur. Life in the Stencil Buffer explique comment mettre en œuvre le Jeu de la vie en utilisant le tampon stencil. Utilisations alternatives pour glDrawPixels () et glCopyPixels () décrit comment utiliser ces deux commandes pour des effets tels que la vidéo fausse, l'aérographe et les images transposées. La gestion des erreurs La vérité est, votre programme fera des erreurs. L'utilisation de routines de gestion des erreurs est essentielle au cours du développement et est fortement recommandée pour les applications commercialisées. (Sauf si vous pouvez donner une garantie de 100 votre programme ne sera jamais générer une condition d'erreur OpenGL. Get real) OpenGL a simples routines de gestion des erreurs pour les bibliothèques GL et GLU de base. Lorsque OpenGL détecte une erreur (dans GL ou GLU de base), il enregistre un code d'erreur actuel. La commande qui a causé l'erreur est ignorée, donc elle n'a aucun effet sur l'état OpenGL ou sur le contenu framebuffer. (Si l'erreur enregistrée était GLOUTOFMEMORY, les résultats de la commande ne sont pas définis.) Une fois enregistré, le code d'erreur actuel n'est pas effacé - c'est-à-dire que des erreurs supplémentaires ne sont pas enregistrées - jusqu'à ce que vous appeliez la commande query glGetError (). Qui retourne le code d'erreur actuel. Après avoir interrogé et effacé le code d'erreur actuel, ou si theres aucune erreur pour commencer, glGetError () retourne GLNOERROR. GLenum glGetError (void) Renvoie la valeur du drapeau d'erreur. Lorsqu'une erreur se produit dans le GL ou GLU, le drapeau d'erreur est défini sur la valeur de code d'erreur appropriée. Si GLNOERROR est retourné, il n'y a pas eu d'erreur détectable depuis le dernier appel à glGetError (). Ou depuis le GL a été initialisé. Aucune autre erreur n'est enregistrée jusqu'à ce que glGetError () soit appelée, que le code d'erreur soit renvoyé et que l'indicateur soit remis à GLNOERROR. Il est fortement recommandé d'appeler glGetError () au moins une fois dans chaque routine display (). Le tableau 14-1 répertorie les codes d'erreur OpenGL de base définis. Tableau 14-1: Codes d'erreur OpenGL Il ne reste pas suffisamment de mémoire pour exécuter la commande Il existe également trente-sept erreurs GLU NURBS (avec des noms de constantes non descriptives, GLUNURBSERROR1, GLUNURBSERROR2, etc.), quatorze erreurs tessellator (GLUTESSMISSINGBEGINPOLYGON, GLUTESSMISSINGENDPOLYGON, GLUTESSMISSINGBEGINCONTOUR , GLUTESSMISSINGENDCONTOUR, GLUTESSCOORDTOOLARGE, GLUTESSNEEDCOMBINECALLBACK, et huit nommés génériquement GLUTESSERROR), et GLUINCOMPATIBLEGLVERSION. De plus, le GLU définit les codes d'erreur GLUINVALIDENUM, GLUINVALIDVALUE et GLUOUTOFMEMORY, qui ont la même signification que les codes OpenGL associés. Pour obtenir une chaîne descriptive imprimable correspondant à un code d'erreur GL ou GLU, utilisez la routine GLU gluErrorString (). Const GLubyte gluErrorString (GLenum errorCode) Renvoie un pointeur vers une chaîne descriptive qui correspond au numéro d'erreur OpenGL ou GLU passé dans errorCode. Dans l'Exemple 14-1, une simple routine de traitement d'erreurs est représentée. Exemple 14-1: Interrogation et impression d'une erreur Remarque: La chaîne renvoyée par gluErrorString () ne doit pas être modifiée ou libérée par l'application. Quelle version dois-je utiliser? La portabilité des applications OpenGL est l'une des fonctionnalités intéressantes d'OpenGL. Cependant, les nouvelles versions d'OpenGL introduisent de nouvelles fonctionnalités, ce qui peut introduire des problèmes de compatibilité ascendante. En outre, vous voudrez peut-être que votre application fonctionne aussi bien sur une variété d'implémentations. Par exemple, vous pouvez rendre le mappage de texture le mode de rendu par défaut sur une machine, mais seulement avoir l'ombrage plat sur un autre. Vous pouvez utiliser glGetString () pour obtenir des informations de publication sur votre implémentation OpenGL. Const GLubyte glGetString (nom GLenum) Renvoie un pointeur vers une chaîne qui décrit un aspect de la mise en œuvre OpenGL. Nom peut être l'un des suivants: GLVENDOR, GLRENDERER, GLVERSION, ou GLEXTENSIONS. GLVENDOR renvoie le nom de l'entreprise responsable de la mise en œuvre d'OpenGL. GLRENDERER renvoie un identifiant du rendu, qui est habituellement la plate-forme matérielle. Pour plus d'informations sur GLEXTENSIONS, voir la section suivante, Extensions de la norme. GLVERSION renvoie une chaîne qui identifie le numéro de version de cette implémentation d'OpenGL. La chaîne de version est disposée comme suit: ltversion numbergtltspacegtltvendor-specific informationgt Le numéro de version est soit du formulaire où tous les numéros ont un ou plusieurs chiffres. Les informations spécifiques au fournisseur sont facultatives. Par exemple, si cette implémentation OpenGL provient de la XYZ Corporation fictive, la chaîne retournée pourrait être ce qui signifie que cette implémentation est la quatrième version de XYZs d'une bibliothèque OpenGL conforme à la spécification pour OpenGL Version 1.1. Cela signifie probablement aussi que c'est la version 3.2 du système d'exploitation propriétaire XYZs. Une autre façon d'interroger le numéro de version pour OpenGL consiste à rechercher la constante symbolique (utilisez l'instruction ifdef de préprocesseur) nommée GLVERSION11. L'absence de la constante GLVERSION11 signifie que vous avez OpenGL version 1.0. Remarque: Si vous exécutez du client au serveur, par exemple lorsque vous effectuez un rendu indirect avec l'extension OpenGL vers le système X Window, le client et le serveur peuvent être des versions différentes. Si votre version client est en avance sur votre serveur, votre client peut demander une opération qui n'est pas prise en charge sur votre serveur. Version de la bibliothèque utilitaire gluGetString () est une fonction de requête pour la bibliothèque utilitaire (GLU) et est similaire à glGetString (). Const GLubyte gluGetString (nom GLenum) Renvoie un pointeur vers une chaîne qui décrit un aspect de la mise en œuvre OpenGL. Nom peut être l'un des suivants: GLUVERSION, ou GLUEXTENSIONS. Notez que gluGetString () n'était pas disponible dans GLU 1.0. Une autre façon d'interroger le numéro de version pour GLU est de rechercher la constante symbolique GLUVERSION11. L'absence de la constante GLUVERSION11 signifie que vous avez GLU 1.0. Extensions de la norme OpenGL a une spécification écrite formelle qui décrit quelles opérations comprennent la bibliothèque. Un fournisseur individuel ou un groupe de fournisseurs peut décider d'inclure des fonctionnalités supplémentaires à leur implémentation libérée. Les nouveaux noms de constantes routinières et symboliques indiquent clairement si une fonctionnalité fait partie de la norme OpenGL ou d'une extension spécifique au fournisseur. Pour créer un nom spécifique au fournisseur, le fournisseur ajoute un identifiant d'entreprise (en majuscules) et, si nécessaire, des informations supplémentaires, telles qu'un nom d'ordinateur. Par exemple, si XYZ Corporation veut ajouter une nouvelle routine et une constante symbolique, elle peut être de la forme glCommandXYZ () et GLDEFINITIONXYZ. Si XYZ Corporation veut avoir une extension qui n'est disponible que sur sa carte graphique FooBar, les noms peuvent être glCommandXYZfb () et GLDEFINITIONXYZFB. Si deux de plus de fournisseurs acceptent de mettre en œuvre la même extension, les procédures et les constantes sont suffixes avec les EXT les plus génériques (glCommandEXT () et GLDEFINITIONEXT). Si vous voulez savoir si une extension particulière est prise en charge sur votre implémentation, utilisez glGetString (GLEXTENSIONS). Cela retourne une liste de toutes les extensions de l'implémentation, séparées par des espaces. Si vous voulez savoir si une extension spécifique est prise en charge, utilisez le code de l'exemple 14-2 pour effectuer une recherche dans la liste et faire correspondre le nom de l'extension. Retourner GLTRUE, s'il est GLFALSE, si ce n'est pas le cas. Exemple 14-2: Déterminer si une extension est prise en charge Translucidité de fromage Vous pouvez utiliser le pointillage de polygone pour simuler un matériau translucide. C'est une solution particulièrement bonne pour les systèmes qui n'ont pas de matériel de mélange. Étant donné que les motifs de polygones sont 32x32 bits, ou 1024 bits, vous pouvez passer de l'opaque à transparent en 1023 étapes. Par exemple, si vous voulez une surface qui permet à travers 29 pour cent de la lumière, il suffit de composer un motif stipple où 29 pour cent (environ 297) des pixels dans le masque sont zéro Et les autres ne font qu'un. Même si vos surfaces ont la même translucidité, n'utilisez pas le même modèle de pointillé pour chacune d'elles, car elles couvrent exactement les mêmes bits sur l'écran. Composer un modèle différent pour chacun en sélectionnant au hasard le nombre approprié de pixels à zéro. Si vous n'aimez pas l'effet avec des pixels aléatoires activés, vous pouvez utiliser des motifs réguliers, mais ils ne fonctionnent pas aussi bien lorsque les surfaces transparentes sont empilées. (Voir Affichage des points, des lignes et des polygones au chapitre 2. Ce n'est souvent pas un problème parce que la plupart des scènes ont relativement peu de régions translucides qui se chevauchent. Dans une image d'une automobile avec des fenêtres translucides, votre ligne de vue peut passer par au plus deux fenêtres, et généralement son seul. Un effet de fondu facile Supposons que vous ayez une image que vous voulez graduer progressivement à une certaine couleur de fond. Définir une série de motifs de points de polygone, dont chacun a plus de bits activés de sorte qu'ils représentent des motifs plus denses et plus denses. Ensuite, utilisez ces motifs à plusieurs reprises avec un polygone assez grand pour couvrir la région sur laquelle vous voulez se faner. Par exemple, supposons que vous souhaitiez passer au noir en 16 étapes. Définissez d'abord 16 matrices de motifs différents: Chargez-les de telle sorte que chacun ait un seizième des pixels dans un motif de pointillés 32 à 180 32 activé et que le OU bit à bit de tous les motifs de pointillés soit tous les uns. Après cela, le code suivant fait l'affaire: Dans certaines implémentations OpenGL, vous pourriez obtenir de meilleures performances en compilant d'abord les modèles de pointillés dans les listes d'affichage. Au cours de votre initialisation, faites quelque chose comme ceci: Ensuite, remplacez cette ligne dans le premier fragment de code En compilant la commande pour définir le stipple dans une liste d'affichage, OpenGL pourrait être en mesure de réorganiser les données dans le tableau stips dans le formulaire spécifique au matériel Nécessaire pour une vitesse maximale de réglage des pointillés. Une autre application pour cette technique est si vous êtes dessinant une image changeante et que vous voulez laisser un peu de flou derrière qui disparaît peu à peu pour donner une certaine indication du mouvement passé. Par exemple, supposons que vous simulez un système planétaire et que vous voulez laisser des traînées sur les planètes pour montrer une portion récente de leur chemin. Encore une fois, en supposant que vous voulez faire fondre en seize étapes, configurer les modèles stipple comme avant (à l'aide de la version liste d'affichage, disons), et ont la boucle de simulation principale ressembler à ceci: Chaque fois à travers la boucle, Seizième des pixels. Tout pixel qui n'a pas eu une planète sur elle pour seize images est certain d'être effacé au noir. Bien sûr, si votre système prend en charge le mélange dans le matériel, son plus facile à mélanger dans une certaine quantité de couleur de fond à chaque cadre. (Voir Affichage des points, des lignes et des polygones au chapitre 2 pour plus d'informations sur les listes d'affichage et Chapitre 6 pour plus d'informations sur le mélange.) Sélection d'objets à l'aide du tampon arrière Bien que le mécanisme de sélection OpenGL Sélection dans le chapitre 13) est puissant et flexible, il peut être lourd à utiliser. Souvent, la situation est simple: Votre application dessine une scène composée d'un nombre important d'objets que l'utilisateur pointe vers un objet avec la souris et l'application doit trouver l'élément sous la pointe du curseur. Une façon de le faire nécessite que votre application s'exécute en mode double-tampon. Lorsque l'utilisateur sélectionne un objet, l'application redessine la scène entière dans le tampon arrière, mais au lieu d'utiliser les couleurs normales pour les objets, elle encode une sorte d'identificateur d'objet pour chaque couleur d'objet. L'application lit simplement le pixel sous le curseur et la valeur de ce pixel code le nombre de l'objet sélectionné. Si de nombreux pics sont attendus pour une seule image statique, vous pouvez lire le tampon de couleur entier une seule fois et chercher dans votre copie pour chaque choix tenté, plutôt que de lire chaque pixel individuellement. Notez que ce schéma présente un avantage par rapport à la sélection standard en ce qu'il sélectionne l'objet qui est devant si plusieurs objets apparaissent au même pixel, l'un derrière l'autre. Puisque l'image avec de fausses couleurs est dessinée dans le tampon arrière, l'utilisateur ne voit jamais que vous pouvez redessiner le tampon arrière (ou le copier du tampon avant) avant d'échanger les tampons. En mode index couleur, l'encodage est simple: envoyez l'identificateur d'objet comme index. En mode RGBA, encoder les bits de l'identificateur dans les composants R, G et B. Soyez conscient que vous pouvez manquer d'identificateurs s'il ya trop d'objets dans la scène. Par exemple, supposons que vous fonctionniez en mode index couleur sur un système comportant des tampons de 4 bits pour les informations d'index de couleur (16 index différents possibles) dans chacun des tampons de couleurs, mais que la scène contient des milliers d'éléments sélectionnables. Pour résoudre ce problème, la cueillette peut se faire en quelques passages. Pour y réfléchir concrètement, supposons qu'il ya moins de 4096 éléments, de sorte que tous les identificateurs d'objets peuvent être codés en 12 bits. Dans la première passe, dessinez la scène en utilisant les indices composés des 4 bits de poids fort, puis utilisez les deuxième et troisième passes pour dessiner les 4 bits du milieu et les 4 bits de poids faible. Après chaque passe, lisez le pixel sous le curseur, extrayez les bits et assemblez-les à la fin pour obtenir l'identifiant de l'objet. Avec cette méthode, la cueillette prend trois fois plus longtemps, mais thats souvent acceptable. Notez qu'après avoir les 4 bits d'ordre élevé, vous éliminez 1516 de tous les objets, donc vous avez vraiment besoin de dessiner seulement 116 pour la deuxième passe. De même, après la deuxième passe, 255 des 256 items possibles ont été éliminés. La première passe prend ainsi environ aussi longtemps que le tirage d'une seule trame, mais les deuxième et troisième passages peuvent être jusqu'à 16 et 256 fois plus rapides. Si vous essayez d'écrire du code portable qui fonctionne sur différents systèmes, divisez vos identificateurs d'objet en morceaux qui correspondent au plus petit dénominateur commun de ces systèmes. N'oubliez pas non plus que votre système peut effectuer un tramage automatique en mode RVB. Si c'est le cas, désactivez le tramage. Transformation peu coûteuse de l'image Si vous voulez dessiner une version distordue d'une image bitmap (peut-être simplement étirée ou tournée, ou peut-être considérablement modifiée par une fonction mathématique), il existe de nombreuses possibilités. Vous pouvez utiliser l'image comme carte de texture, ce qui vous permet d'effectuer une mise à l'échelle, de la faire pivoter ou de fausser l'image. Si vous voulez juste l'échelle de l'image, vous pouvez utiliser glPixelZoom (). Dans de nombreux cas, vous pouvez obtenir de bons résultats en dessinant l'image de chaque pixel comme un quadrilatère. Bien que ce schéma doesnt produire des images qui sont aussi agréables que ceux que vous obtiendriez en appliquant un algorithme de filtrage sophistiqué (et il pourrait ne pas être suffisant pour les utilisateurs sophistiqués), son beaucoup plus rapide. Pour rendre le problème plus concret, supposons que l'image originale est m pixels par n pixels, avec des coordonnées choisies de 0, m -1 180 0, n -1. Soit x (m, n) et y (m, n) les fonctions de distorsion. Par exemple, si la distorsion est simplement un zoom d'un facteur de 3.2, alors x (m, n) 3.2 m et y (m, n) 3.2 n. Le code suivant dessine l'image déformée: Ce code trace chaque pixel transformé en une couleur unie égale à cette couleur de pixels et calcule la taille de l'image de 3.2. La routine setcolor () représente la commande OpenGL appropriée pour définir la couleur du pixel de l'image. Ce qui suit est une version légèrement plus complexe qui déforme l'image en utilisant les fonctions x (i, j) et y (i, j): Une image encore mieux déformée peut être dessinée avec le code suivant: Ce code intercale en douceur la couleur sur chaque quadrilatère . Notez que cette version produit un moins de quadrilatère dans chaque dimension que les versions à l'ombre car l'image couleur est utilisée pour spécifier les couleurs aux sommets quadrilatéraux. En outre, vous pouvez antialias les polygones avec la fonction de mélange appropriée (GLSRCALPHA, GLONE) pour obtenir une image encore plus agréable. Affichage des couches Dans certaines applications telles que les programmes de mise en page des semi-conducteurs, vous souhaitez afficher plusieurs couches de matériaux différents et indiquer où les matériaux se chevauchent. Comme un exemple simple, supposons que vous avez trois substances différentes qui peuvent être stratifiés. À tout moment, huit combinaisons possibles de couches peuvent se produire, comme le montre le tableau 14-2. Tableau 14-2: Huit combinaisons de calques Vous souhaitez que votre programme affiche huit couleurs différentes, en fonction des calques présents. Une possibilité arbitraire est indiquée dans la dernière colonne du tableau. Pour utiliser cette méthode, utilisez le mode d'index des couleurs et chargez votre carte de couleurs de sorte que l'entrée 0 soit noire, l'entrée 1 rouge, l'entrée 2 verte et ainsi de suite. Notez que si les nombres de 0 à 7 sont écrits en binaire, le bit 4 est activé chaque fois que la couche 3 apparaît, le 2 bits chaque fois que la couche 2 apparaît et le bit 1 quand la couche 1 apparaît. Pour effacer la fenêtre, réglez writemask sur 7 (tous les trois calques) et définissez la couleur de correction sur 0. Pour dessiner votre image, définissez la couleur sur 7, puis lorsque vous souhaitez dessiner quelque chose dans la couche n. Ajustez la writemask à n. Dans d'autres types d'applications, il peut être nécessaire d'effacer une couche de manière sélective, auquel cas vous utiliserez les writemasks dont il vient d'être question, mais définissez la couleur sur 0 au lieu de 7. (Voir Masking Buffers au chapitre 10 pour plus d'informations sur writemasks .) Caractères anti-alias Utilisation de la technique standard pour dessiner des caractères avec glBitmap (). Le dessin de chaque pixel d'un personnage est une affaire de tout ou rien - le pixel est allumé ou non. Si vous dessinez des caractères noirs sur un fond blanc, par exemple, les pixels résultants sont soit noir ou blanc, jamais une nuance de gris. Des images beaucoup plus lisses et de meilleure qualité peuvent être obtenues si des couleurs intermédiaires sont utilisées lors du rendu des caractères (gris, dans cet exemple). En supposant que vous dessinez des caractères noirs sur un fond blanc, imaginez une image très agrandie des pixels à l'écran, avec un contour de caractère haute résolution superposé à celui-ci, comme le montre le côté gauche de la Figure 14-1. Figure 14-1: Caractères anti-alésés Notez que certains des pixels sont complètement entourés par le contour des caractères et doivent être peints en noir. Certains pixels sont complètement en dehors du contour et devraient être peints en blanc, mais de nombreux pixels devraient idéalement être peints un peu de gris, L'obscurité du gris correspond à la quantité de noir dans le pixel. Si cette technique est utilisée, l'image obtenue à l'écran semble meilleure. Si la vitesse et l'utilisation de la mémoire ne sont pas préoccupantes, chaque caractère peut être dessiné sous la forme d'une petite image au lieu d'une image bitmap. Si vous utilisez le mode RGBA, cependant, cette méthode peut nécessiter jusqu'à 32 bits par pixel du caractère à stocker et à tracer, au lieu du bit 1 par pixel dans un caractère standard. Vous pouvez également utiliser un index de 8 bits par pixel et convertir ces indices en RGBA par recherche de table lors du transfert. Dans de nombreux cas, un compromis est possible qui vous permet de dessiner le personnage avec quelques niveaux de gris entre noir et blanc (disons deux ou trois), et la description de police résultante ne nécessite que 2 ou 3 bits par pixel de stockage. Les chiffres du côté droit de la figure 14-1 indiquent le pourcentage approximatif de couverture de chaque pixel: 0 signifie approximativement vide, 1 signifie environ un tiers de couverture, 2 signifie deux tiers et 3 signifie complètement recouvert. Si les pixels étiquetés 0 sont peints en blanc, les pixels marqués 3 sont peints en noir, et les pixels étiquetés 1 et 2 sont peints un tiers et deux tiers en noir, respectivement, le caractère résultant semble assez bon. Seuls 2 bits sont nécessaires pour stocker les nombres 0, 1, 2 et 3, donc pour 2 bits par pixel, quatre niveaux de gris peuvent être enregistrés. Il existe essentiellement deux méthodes pour implémenter des caractères anti-alias, selon que vous êtes en mode RGBA ou couleur. En mode RGBA, définissez trois bitmaps de caractères différents, correspondant à l'endroit où 1, 2 et 3 apparaissent dans la Figure 14-1. Définissez la couleur sur blanc et effacez l'arrière-plan. Définissez la couleur sur un tiers de gris (RGB (0.666, 0.666, 0.666)), et dessinez tous les pixels avec un 1 en eux. Ensuite, définissez RGB (0.333, 0.333, 0.333), dessinez avec le bitmap 2, et utilisez RGB (0.0, 0.0, 0.0) pour le bitmap 3. Ce que vous faites est de définir trois polices différentes et de redessiner la chaîne trois fois, où chaque passe remplit les bits de la densité de couleur appropriée. En mode index couleur, vous pouvez faire exactement la même chose, mais si vous êtes prêt à configurer correctement la carte couleur et à utiliser writemasks, vous ne pouvez obtenir que deux bitmaps par caractère et deux passes par chaîne. Dans l'exemple précédent, configurez un bitmap qui a un 1 où 1 ou 3 apparaît dans le caractère. Mettre en place une deuxième bitmap qui a un 1 partout où un 2 ou un 3 apparaît. Chargez la carte de couleur de sorte que 0 donne le blanc, 1 donne le gris clair, 2 donne le gris foncé, et 3 donne le noir. Définissez la couleur sur 3 (11 en binaire) et sur writemask sur 1 et tracez la première image bitmap. Ensuite, changez le writemask en 2 et dessinez le second. Lorsque 0 apparaît sur la Figure 14-1, rien n'est tracé dans le tampon de trame. Lorsque 1, 2 et 3 apparaissent, 1, 2 et 3 apparaissent dans le tampon de trame. Pour cet exemple avec seulement quatre niveaux de gris, l'épargne est faible - deux passes au lieu de trois. Si huit niveaux de gris étaient utilisés à la place, la méthode RGBA nécessiterait sept passages, et la technique de masquage de carte de couleur ne nécessiterait que trois. Avec seize niveaux de gris, la comparaison est de quinze passages à quatre passes. (Voir Masking Buffers dans le Chapitre 10 pour plus d'informations sur writemasks et Bitmaps et Fonts au Chapitre 8 pour plus d'informations sur le dessin de bitmaps.) Pouvez-vous voir comment faire le rendu RGBA en utilisant plus d'images que le cas de couleur optimisée? Fragments RVB normalement fusionnés dans le tampon de couleur lorsque l'antialiasing est souhaité Dessiner des points ronds Dessiner près de rondes, aliased points en activant antialiasing point, en tournant blending off, et en utilisant une fonction alpha qui ne passe que des fragments avec alpha supérieur à 0,5. Interpolation d'images Supposez que vous ayez une paire d'images (où image peut signifier une image bitmap, ou une image générée en utilisant la géométrie de la manière habituelle) et que vous voulez Mélanger doucement d'un à l'autre. Cela peut se faire facilement en utilisant la composante alpha et les opérations de mélange appropriées. Disons que vous voulez réaliser le mélange en dix étapes, où l'image A est montrée dans le cadre 0 et l'image B est montrée dans le cadre 9. L'approche évidente est de dessiner l'image A avec alpha égal à (9- ampigr) 9 et l'image B Avec un alpha de i 9 dans le cadre i. Le problème avec cette méthode est que les deux images doivent être dessinées dans chaque cadre. Une approche plus rapide est de dessiner l'image A dans le cadre 0. Pour obtenir le cadre 1, mélangez-en 19 de l'image B et 89 de ce qui est là. Pour le cadre 2, mélangez en 18 de l'image B avec 78 de ce qui s'y trouve. Pour le cadre 3, mélangez 17 dans l'image B avec 67 de ce qui est là, et ainsi de suite. Pour la dernière étape, vous êtes juste le dessin 11 de l'image B mélangé avec 01 de ce qui est laissé, donnant l'image B exactement. Pour voir que cela fonctionne, si pour le cadre i vous avez et vous mélangez en B (9 ampigr) avec (8 ampigr) (9 ampigr) de ce qui est là, vous obtenez décalques Supposons que vous êtes le dessin d'une image tridimensionnelle complexe En utilisant la profondeur de tampon pour éliminer les surfaces cachées. Supposez en outre qu'une partie de votre image est composée de figures coplanaires A et B, où B est une sorte de décalque qui devrait toujours apparaître au-dessus de la figure A. Votre première approche pourrait être de dessiner B après avoir dessiné A, en définissant la profondeur - buffering fonction de remplacer sur plus ou moins. En raison de la précision finie des représentations à virgule flottante des sommets, cependant, l'erreur d'arrondi peut faire que le polygone B soit parfois un peu en avant et parfois un peu en retrait par rapport à la figure A. Il y a une solution à ce problème. Désactivez le tampon de profondeur pour l'écriture et rendez A. Activez le tampon de profondeur pour l'écriture et le rendu B. Désactivez le tampon de couleur pour l'écriture et réexécutez A. Activez le tampon de couleur pour l'écriture. Notez que pendant le processus entier, le test de tampon de profondeur est activé. A l'étape 1, A est rendu là où il devrait être, mais aucune des valeurs de profondeur-tampon n'est changée ainsi, à l'étape 2, où B apparaît sur A, B est garanti pour être tiré. L'étape 3 s'assure simplement que toutes les valeurs de profondeur sous A sont mises à jour correctement, mais comme les écritures RGBA sont désactivées, les pixels de couleur ne sont pas affectés. Enfin, l'étape 4 retourne le système à l'état par défaut (l'écriture est activée à la fois dans le tampon de profondeur et dans le tampon de couleur). Si un tampon stencil est disponible, la technique simple suivante fonctionne. Configurez le tampon de stencil pour écrire un si le test de profondeur passe, et zéro autrement. Rendu A. Configurez le tampon du stencil pour ne pas modifier la valeur du stencil, mais pour le rendre uniquement lorsque les valeurs du stencil sont un. Désactivez le test du tampon de profondeur et sa mise à jour. Render B. Avec cette méthode, il n'est pas nécessaire d'initialiser le contenu du tampon stencil à tout moment, car la valeur du stencil de tous les pixels d'intérêt (c'est-à-dire, ceux rendus par A) sont définies lorsque A est rendu. N'oubliez pas de réactiver le test de profondeur et de désactiver le test de stencil avant de créer des polygones supplémentaires. (Voir Choix des tampons de couleur pour l'écriture et la lecture, Test de profondeur et Test de pochoir au Chapitre 10.) Polygones concaves remplis de dessin à l'aide du tampon de stencil Prenons le polygone concave 1234567 illustré à la Figure 14-2. Imaginez qu'il soit dessiné sous la forme d'une série de triangles: 123, 134, 145, 156, 167, qui sont tous représentés sur la figure. La ligne plus lourde représente la limite du polygone d'origine. Dessinant tous ces triangles divise le tampon en neuf régions A, B, C. I, où la région I est en dehors de tous les triangles. Figure 14-2: Polygone concave Dans le texte de la figure, chaque nom de région est suivi d'une liste des triangles qui la recouvrent. Les régions A, D et F constituent la note polygonale originale que ces trois régions sont couvertes par un nombre impair de triangles. Chaque autre région est couverte par un nombre pair de triangles (éventuellement zéro). Ainsi, pour rendre l'intérieur du polygone concave, il suffit de rendre les régions qui sont entourées par un nombre impair de triangles. Cela peut être fait en utilisant le tampon stencil, avec un algorithme à deux passes. Tout d'abord, effacer le tampon stencil et désactiver l'écriture dans le tampon de couleur. Ensuite, dessinez chacun des triangles à tour de rôle, en utilisant la fonction GLINVERT dans le tampon du stencil. (Pour obtenir les meilleures performances, utilisez des ventilateurs triangulaires.) Cette valeur retourne entre zéro et une valeur non nulle chaque fois qu'un triangle est dessiné qui couvre un pixel. Après que tous les triangles sont dessinés, si un pixel est recouvert d'un nombre pair de fois, la valeur dans les tampons stencil est zéro sinon, son non-zéro. Enfin, dessinez un grand polygone sur toute la région (ou redessinez les triangles), mais n'autorisez le dessin que lorsque le tampon stencil est non nul. Note: Il ya une légère généralisation de la technique précédente, où vous n'avez pas besoin de commencer avec un sommet de polygone. Dans l'exemple 1234567, soit P un point quelconque sur ou hors du polygone. Dessinez les triangles: P12, P23, P34, P45, P56, P67 et P71. Les régions couvertes par un nombre impair de triangles sont à l'intérieur d'autres régions sont à l'extérieur. Ceci est une généralisation en ce que si P se trouve être un des arêtes polygones, l'un des triangles est vide. Cette technique peut être utilisée pour remplir des polygones non-simples (polygones dont les bords se croisent) et des polygones avec des trous. L'exemple suivant illustre comment gérer un polygone compliqué avec deux régions, une à quatre faces et une à cinq faces. Supposons en outre qu'il existe un trou triangulaire et un trou à quatre côtés (il importe peu dans quelles régions les trous se trouvent). Que les deux régions soient abcd et efghi, et les trous jkl et mnop. Soit z un point quelconque du plan. Tracez les triangles suivants: zab zbc zcd zda zef zfg zgh zhi zie zjk zkl zlj zmn zno zop zpm Marquez les régions couvertes par un nombre impair de triangles comme dans. Et ceux couverts par un nombre pair comme out. Trouver des régions d'interférence Si vous concevez une pièce mécanique faite à partir de petites pièces tridimensionnelles, vous souhaitez souvent afficher les régions où les pièces se chevauchent. In many cases, such regions indicate design errors where parts of a machine interfere with each other. In the case of moving parts, it can be even more valuable, since a search for interfering regions can be done through a complete mechanical cycle of the design. The method for doing this is complicated, and the description here might be too brief. Complete details can be found in the paper Interactive Inspection of Solids: Cross-sections and Interferences . by Jarek Rossignac, Abe Megahed, and Bengt-Olaf Schneider (SIGGRAPH 1992 Proceedings). The method is related to the capping algorithm described in Stencil Test in Chapter 10. The idea is to pass an arbitrary clipping plane through the objects that you want to test for interference, and then determine when a portion of the clipping plane is inside more than one object at a time. For a static image, the clipping plane can be moved manually to highlight interfering regions for a dynamic image, it might be easier to use a grid of clipping planes to search for all possible interferences. Draw each of the objects you want to check and clip them against the clipping plane. Note which pixels are inside the object at that clipping plane using an odd-even count in the stencil buffer, as explained in the preceding section. (For properly formed objects, a point is inside the object if a ray drawn from that point to the eye intersects an odd number of surfaces of the object.) To find interferences, you need to find pixels in the framebuffer where the clipping plane is in the interior of two or more regions at once in other words, in the intersection of the interiors of any pair of objects. If multiple objects need to be tested for mutual intersection, store 1 bit every time some intersection appears, and another bit wherever the clipping buffer is inside any of the objects (the union of the objects interiors). For each new object, determine its interior, find the intersection of that interior with the union of the interiors of the objects so far tested, and keep track of the intersection points. Then add the interior points of the new object to the union of the other objects interiors. You can perform the operations described in the preceding paragraph by using different bits in the stencil buffer together with various masking operations. Three bits of stencil buffer are required per pixel - one for the toggling to determine the interior of each object, one for the union of all interiors discovered so far, and one for the regions where interference has occurred so far. To make this discussion more concrete, assume the 1 bit of the stencil buffer is for toggling interiorexterior, the 2 bit is the running union, and the 4 bit is for interferences so far. For each object that youre going to render, clear the 1 bit (using a stencil mask of one and clearing to zero), then toggle the 1 bit by keeping the stencil mask as one and using the GLINVERT stencil operation. You can find intersections and unions of the bits in the stencil buffers using the stenciling operations. For example, to make bits in buffer 2 be the union of the bits in buffers 1 and 2, mask the stencil to those 2 bits, and draw something over the entire object with the stencil function set to pass if anything nonzero occurs. This happens if the bits in buffer 1, buffer 2, or both are turned on. If the comparison succeeds, write a 1 in buffer 2. Also, make sure that drawing in the color buffer is disabled. An intersection calculation is similar - set the function to pass only if the value in the two buffers is equal to 3 (bits turned on in both buffers 1 and 2). Write the result into the correct buffer. (See Stencil Test in Chapter 10 .) Every possible projection of three-dimensional space to three-dimensional space can be achieved with a suitable 4 180 4 invertible matrix and homogeneous coordinates. If the matrix isnt invertible but has rank 3, it projects three-dimensional space onto a two-dimensional plane. Every such possible projection can be achieved with a suitable rank-3 4 180 4 matrix. To find the shadow of an arbitrary object on an arbitrary plane from an arbitrary light source (possibly at infinity), you need to find a matrix representing that projection, multiply it on the matrix stack, and draw the object in the shadow color. Keep in mind that you need to project onto each plane that youre calling the ground. As a simple illustration, assume the light is at the origin, and the equation of the ground plane is ax by c d 0. Given a vertex S( sx, sy, sz ,1), the line from the light through S includes all points ampagr S, where ampagr is an arbitrary real number. The point where this line intersects the plane occurs when ampagr ( asz bsy csz ) d 0, ampagr - ampdgr ( asx bsy csz ). Plugging this back into the line, we get - ampdgr ( ampsgr ampxgr. ampsgr amppsgr. ampsgr ampzgr )( ampagr ampsgr ampxgr ampbgr ampsgr amppsgr ampkhgr ampsgr ampzgr ) for the point of intersection. The matrix that maps S to this point for every S is This matrix can be used if you first translate the world so that the light is at the origin. If the light is from an infinite source, all you have is a point S and a direction D ( dx, dy, dz ). Points along the line are given by Proceeding as before, the intersection of this line with the plane is given by a(sx ampagr dx)b(sy ampagr dy)c(sz ampagr dz)d 0 Solving for ampagr. plugging that back into the equation for a line, and then determining a projection matrix gives This matrix works given the plane and an arbitrary direction vector. Theres no need to translate anything first. (See Chapter 3 and Appendix F .) Hidden-Line Removal If you want to draw a wireframe object with hidden lines removed, one approach is to draw the outlines using lines and then fill the interiors of the polygons making up the surface with polygons having the background color. With depth-buffering enabled, this interior fill covers any outlines that would be obscured by faces closer to the eye. This method would work, except that theres no guarantee that the interior of the object falls entirely inside the polygons outline in fact, it might overlap it in various places. Theres an easy, two-pass solution using either polygon offset or the stencil buffer. Polygon offset is usually the preferred technique, since polygon offset is almost always faster than stencil buffer. Both methods are described here, so you can see how both approaches to the problem work. Hidden-Line Removal with Polygon Offset To use polygon offset to accomplish hidden-line removal, the object is drawn twice. The highlighted edges are drawn in the foreground color, using filled polygons but with the polygon mode GLLINE to rasterize it as a wireframe. Then the filled polygons are drawn with the default polygon mode, which fills the interior of the wireframe, and with enough polygon offset to nudge the filled polygons a little farther from the eye. With the polygon offset, the interior recedes just enough that the highlighted edges are drawn without unpleasant visual artifacts. You may need to adjust the amount of offset needed (for wider lines, for example). (See Polygon Offset in Chapter 6 for more information.) Hidden-Line Removal with the Stencil Buffer Using the stencil buffer for hidden-line removal is a more complicated procedure. For each polygon, youll need to clear the stencil buffer, and then draw the outline both in the framebuffer and in the stencil buffer. Then when you fill the interior, enable drawing only where the stencil buffer is still clear. To avoid doing an entire stencil-buffer clear for each polygon, an easy way to clear it is simply to draw 0s into the buffer using the same polygon outline. In this way, you need to clear the entire stencil buffer only once. For example, the following code represents the inner loop you might use to perform such hidden-line removal. Each polygon is outlined in the foreground color, filled with the background color, and then outlined again in the foreground color. The stencil buffer is used to keep the fill color of each polygon from overwriting its outline. To optimize performance, the stencil and color parameters are changed only twice per loop by using the same values both times the polygon outline is drawn. Texture-Mapping Applications Texture mapping is quite powerful, and it can be used in some interesting ways. Here are a few advanced applications of texture mapping. Antialiased text - Define a texture map for each character at a relatively high resolution, and then map them onto smaller areas using the filtering provided by texturing. This also makes text appear correctly on surfaces that arent aligned with the screen, but are tilted and have some perspective distortion. Antialiased lines - These can be done like antialiased text: Make the line in the texture several pixels wide, and use the texture filtering to antialias the lines. Image scaling and rotation - If you put an image into a texture map and use that texture to map onto a polygon, rotating and scaling the polygon effectively rotates and scales the image. Image warping - As in the preceding example, store the image as a texture map, but map it to some spline-defined surface (use evaluators). As you warp the surface, the image follows the warping. Projecting images - Put the image in a texture map, and project it as a spotlight, creating a slide projector effect. (See The q Coordinate in Chapter 9 for more information about how to model a spotlight using textures.) (See Chapter 3 for information about rotating and scaling, Chapter 9 for more information about creating textures, and Chapter 12 for details on evaluators.) Drawing Depth-Buffered Images For complex static backgrounds, the rendering time for the geometric description of the background can be greater than the time it takes to draw a pixel image of the rendered background. If theres a fixed background and a relatively simple changing foreground, you may want to draw the background and its associated depth-buffered version as an image rather than render it geometrically. The foreground might also consist of items that are time-consuming to render, but whose framebuffer images and depth buffers are available. You can render these items into a depth-buffered environment using a two-pass algorithm. For example, if youre drawing a model of a molecule made of spheres, you might have an image of a beautifully rendered sphere and its associated depth-buffer values that were calculated using Phong shading or ray-tracing or by using some other scheme that isnt directly available through OpenGL. To draw a complex model, you might be required to draw hundreds of such spheres, which should be depth-buffered together. To add a depth-buffered image to the scene, first draw the images depth-buffer values into the depth buffer using glDrawPixels() . Then enable depth-buffering, set the writemask to zero so that no drawing occurs, and enable stenciling such that the stencil buffers get drawn whenever a write to the depth buffer occurs. Then draw the image into the color buffer, masked by the stencil buffer youve just written so that writing occurs only when theres a 1 in the stencil buffer. During this write, set the stenciling function to zero out the stencil buffer so that its automatically cleared when its time to add the next image to the scene. If the objects are to be moved nearer to or farther from the viewer, you need to use an orthographic projection in these cases, you use GLDEPTHBIAS with glPixelTransfer() to move the depth image. (See Coordinate System Survival Kit in Chapter 2. Depth Test and Stencil Test in Chapter 10. and Chapter 8 for details on glDrawPixels() and glPixelTransfer() .) Dirichlet Domains Given a set S of points on a plane, the Dirichlet domain or Voronoi polygon of one of the points is the set of all points in the plane closer to that point than to any other point in the set S. These points provide the solution to many problems in computational geometry. Figure 14-3 shows outlines of the Dirichlet domains for a set of points. Figure 14-3 : Dirichlet Domains If you draw a depth-buffered cone with its apex at the point in a different color than each of the points in S, the Dirichlet domain for each point is drawn in that color. The easiest way to do this is to precompute a cones depth in an image and use the image as the depth-buffer values as described in the preceding section. You dont need an image to draw in the framebuffer as in the case of shaded spheres, however. While youre drawing into the depth buffer, use the stencil buffer to record the pixels where drawing should occur by first clearing it and then writing nonzero values wherever the depth test succeeds. To draw the Dirichlet region, draw a polygon over the entire window, but enable drawing only where the stencil buffers are nonzero. You can do this perhaps more easily by rendering cones of uniform color with a simple depth buffer, but a good cone might require thousands of polygons. The technique described in this section can render much higher-quality cones much more quickly. (See A Hidden-Surface Removal Survival Kit in Chapter 5 and Depth Test in Chapter 10 .) Life in the Stencil Buffer The Game of Life, invented by John Conway, is played on a rectangular grid where each grid location is alive or dead. To calculate the next generation from the current one, count the number of live neighbors for each grid location (the eight adjacent grid locations are neighbors). A grid location is alive in generation n 1 if it was alive in generation n and has exactly two or three live neighbors, or if it was dead in generation n and has exactly three live neighbors. In all other cases, it is dead in generation n 1. This game generates some incredibly interesting patterns given different initial configurations. (See Martin Gardner, Mathematical Games, Scientific American . vol. 223, no. 4, October 1970, p. 120123.) Figure 14-4 shows six generations from a game. Figure 14-4 : Six Generations from the Game of Life One way to create this game using OpenGL is to use a multipass algorithm. Keep the data in the color buffer, one pixel for each grid point. Assume that black (all zeros) is the background color, and the color of a live pixel is nonzero. Initialize by clearing the depth and stencil buffers to zero, set the depth-buffer writemask to zero, and set the depth comparison function so that it passes on not-equal. To iterate, read the image off the screen, enable drawing into the depth buffer, and set the stencil function so that it increments whenever a depth comparison succeeds but leaves the stencil buffer unchanged otherwise. Disable drawing into the color buffer. Next, draw the image eight times, offset one pixel in each vertical, horizontal, and diagonal direction. When youre done, the stencil buffer contains a count of the number of live neighbors for each pixel. Enable drawing to the color buffer, set the color to the color for live cells, and set the stencil function to draw only if the value in the stencil buffer is 3 (three live neighbors). In addition, if this drawing occurs, decrement the value in the stencil buffer. Then draw a rectangle covering the image this paints each cell that has exactly three live neighbors with the alive color. At this point, the stencil buffers contain 0, 1, 2, 4, 5, 6, 7, 8, and the values under the 2s are correct. The values under 0, 1, 4, 5, 6, 7, and 8 must be cleared to the dead color. Set the stencil function to draw whenever the value is not 2, and to zero the stencil values in all cases. Then draw a large polygon of the dead color across the entire image. Youre done. For a usable demonstration program, you might want to zoom the grid up to a size larger than a single pixel its hard to see detailed patterns with a single pixel per grid point. (See Coordinate System Survival Kit in Chapter 2. and Depth Test and Stencil Test in Chapter 10 .) Alternative Uses for glDrawPixels() and glCopyPixels() You might think of glDrawPixels() as a way to draw a rectangular region of pixels to the screen. Although this is often what its used for, some other interesting uses are outlined here. Video - Even if your machine doesnt have special video hardware, you can display short movie clips by repeatedly drawing frames with glDrawPixels() in the same region of the back buffer and then swapping the buffers. The size of the frames you can display with reasonable performance using this method depends on your hardwares drawing speed, so you might be limited to 100 180 100 pixel movies (or smaller) if you want smooth fake video. Airbrush - In a paint program, your airbrush (or paintbrush) shape can be simulated using alpha values. The color of the paint is represented as the color values. To paint with a circular brush in blue, repeatedly draw a blue square with glDrawPixels() where the alpha values are largest in the center and taper to zero at the edges of a circle centered in the square. Draw using a blending function that uses alpha of the incoming color and (1-alpha) of the color already at the pixel. If the alpha values in the brush are all much less than one, you have to paint over an area repeatedly to get a solid color. If the alpha values are near one, each brush stroke pretty much obliterates the colors underneath. Filtered Zooms - If you zoom a pixel image by a nonintegral amount, OpenGL effectively uses a box filter, which can lead to rather severe aliasing effects. To improve the filtering, jitter the resulting image by amounts less than a pixel and redraw it multiple times, using alpha blending to average the resulting pixels. The result is a filtered zoom. Transposing Images - You can swap same-size images in place with glCopyPixels() using the XOR operation. With this method, you can avoid having to read the images back into processor memory. If A and B represent the two images, the operation looks like this:Moving Landscapes Matharoo Associates The idea for moving landscape germinated from stumbling upon a stone, Bidasar Forest, that possesses an impression, as if, of tropical arid landscape fossilized within itself. Its polished surfaces against the native verdure of the Ahmedabad region made for the perfect setting, blurring the lines between reality and illusion. Save this picture The nations booming economy in the last decade has made individual houses accessible to a larger section of society. Coupled with the demand for an independence that protects individuality, the age old tradition of joint family living has disintegrated into small nuclear families. Despite this change of cultural attitude in the present Indian context, a large number of families, bound by family business and obliged by traditional ingrained values, still choose to live together. Whilst this allows them to benefit from shared responsibility across generations, it often leads to the creation of autonomous suites within a house that isolates families even under the same roof. The challenge therefore lies in simultaneously integrating the requirements of these opposing lifestyles - making it equally imperative to provide opportunities for communal collision, while providing privacy. Situated on the outskirts of Ahmedabad. the house is meant to accommodate one of the citys most prolific real-estate developers and his wife, along with his two sons families and extended visiting members. The client also shares the grounds with his two other brothers houses and their joint families in a large 20000 m2 plot. Save this picture The plan of the house is interpreted as a linear pavilion, ensuring that every space in the house is lined with glass on the facing sides the first enclosure. The rest of the structure is in 200mm thin walls in concrete, eliminating the need for any beams and columns and making for cleanest interior volumes. Additionally, this saves constructed dead space by about 3 and for the 18,000 total covered area, this equals to 540 sq. ft or the size of an average sized room. This pavilion is oriented around the margin of the site as three wings. The flanks holds the houses private spaces with suites for each of the sons families, while the central one hosts the living space for all communal activities. The residual corner voids by the turning of the blocks, are snugly protected by tall circular walls to form smaller sheltered spaces while one cradles the houses utility space, the other acts as a court distant from the joint families gaze. These also carry the staircases and lift, rendering outer spaces clear of all encumbrances for the Bidasar drama to unfold. The composition as a whole footprint defines a large multi family courtyard at the heart of the site. Save this picture The second enclosure is a layer of massive 15 high, 9 wide and 16mm thick Bidaser stone walls along the entire perimeter an impregnable shell. Akin to the amethysts hard exterior cracking open to reveal its crystalline heart, at the push of a button, this imposingly heavy stone wall cracks open, as it becomes an array of panels spinning gently about their centres or sliding away to reveal a transparent cocooned interior. Can be employed at will whenever desired and dissolved when not. Save this picture This layer of stone panels help create a buffer between the inside and the outside, protecting the inner layer shell of concrete and glass from intense sun light and 45o heat, thereby reducing the total heat gain on the air-conditioning. Moreover, this space doubles up as passages, verandahs, entrance vestibule and circulation space, and also as protection from rain, eliminating the need for air-conditioning in 8000sq. ft out of a total of 18000 habitable space. This saving is substituted with enhanced living and direct contact with nature in what we term as value architecture. Save this picture Savings from the air-conditioning and sealing the house, is then channelled into making inhouse custom designed motorized pivots and giant sliding systems. Architecturally and structurally both, this entire layer is kept completely detached from the inside structure, almost as a heat buffer, and is only supported on hidden structures within in the sliding and pivoting systems, making for the awe in having thick concrete slabs floating on moving stones. Save this picture Lights are machined out of alabaster stone providing for the most natural ambience. Most furniture is bought out from various design houses in Italy and a sole bar table is one custom designed by the Architects. It is a 3 dimensional mobius strip in stainless steel, locally fabricated, that can be subject of discussion and intellectual discourse after a couple of drinks. Lights and water under the moving walls light the water to make the heavy stones appear floating on water. Toilets too open on opposite ends and the water closet, the shower and the basin, all three are positioned on 3 side of the duct, the fourth side left for easy service access and ventilation to the duct from outside. To carry on with the material amp weight amazement further the thick concrete basin counter is cantilevered from the floor to ceiling mirror. In line with the same philosophy of the easy maintenance and serviceblity AC units have been kept on the roof with just holes cut in slab for blower. This approach of integrating the services and interiors in construction itself doesnt only make it easy to service it also saved a lot of time off construction. The entire building was ready in 18 months time from start to furnish. Save this picture Resonating with the harshest aspects of nature, in motion, these walls intermingle with the glass inside and the wild landscape outside, the third enclosure, to sometimes allow a glimse of the outdoors, sometimes reflect it and sometimes reflecting themselves. It is in this layering of space and screen, the houses entire envelope becomes an interface to mediate between the artifice of the inside and verdant site outside. Save this picture The houses environs look deep inside their interior, as the house merges into an illusion of landscape constantly moving that we sometimes catch ourselves reflecting amongst, reflecting on the nature both within us and outside of us. The epitome of their experience is to be found at the entrance passage of the house, where all of these reflections find the surface of water to make the landscape a truly moving one. Text: Robert Taylor amp Trisha Patel The best of ArchDaily, directly to your inbox


No comments:

Post a Comment