Je suis sur une fonction me permettant de refléter une image "dans l'eau" et m'approcher du rendu de l'eau dans kingdom :
Rien de bien complexe : je fais une symétrie verticale (avec échelle) et chaque pixel de destination en x est pioché au pif dans [x-1, x+1] de la source (ébauche) :
Cela fonctionne parfaitement avec une image fixe et un rendu qui me surprend moi-même vu la simplicité de l'algo. Je pourrais bien évidemment attaquer directement les pixels de la texture dst pour éviter les recopies (pixels de waterPic + CEV_blit), mais pour l'instant, je me concentre sur le rendu de l'algo, l'optimisation viendra plus tard.
La contrainte étant de ne pas recalculer le reflet trop souvent pour ne pas tuer les épileptiques. Disons qu'entre 100 et 150 ms, ça fait à peu-près naturel.
Pour l'incorporer à mon jeu, je me vois obligé de recalculer le reflet du monde dès que celui-ci évolue avec le scrolling, soit potentiellement toutes les 16/17 ms (60 ips) pour compléter à droite ou à gauche et refléter les joueur/pnj dans la bonne position, du coup c’est trop rapide et ça fait plus un flou qu'un reflet.
Mon premier réflexe a été de passer par une table[32] de randomisation (le "filtre") contenant les valeurs de décalage au pif dans [-1, 1], ainsi en corrigeant l'index avec l'avance du scrolling, je peux conserver le même décalage par "colonne" et en plus modifier l'index (ou régénérer la table) toutes les 150 ms pour faire évoluer la génération du "filtre". Le problème est que comme j'utilise un index circulaire au sein d'une même génération (index = (index+1) & 31) cela créé un pattern du plus mauvais effet dans le reflet...
Et là... C'est le drame. Je n'arrive pas à entrevoir une solution pour conserver mon reflet en face du monde en permanence sans que le "filtre" ne change trop souvent et qu'il soit fidèle au monde à tout moment... à part un filtre géant de la taille de l'image, ce qui me semble un peu lourd.
Voilà donc... Si une astuce vous vient, je suis preneur.
un premier point que je vois serais un module à part entière pour gérer tous les problèmes de temps, par exemple une fonction qui, toutes les millisecondes, lance les fonctions qu'on lui a passées (via des pointeurs de fonction) et donc avec une fonction basique on aurait :
// var
static volatile int x = 0;
// prototype
void process_ms(void);
// fonction
void init(void){
ma_fonction_ms(&process_ms);
}
void process_ms(void){
static int ms = NBR_MS_TO_UPDATE;
if(!ms){
ms = NBR_MS_TO_UPDATE;
// mise à jour de x
x = rand()%3 - 1;
}
ms--;
}
c'est le best que je vois
Sinon si le nombre de frame ne bouge pas (et donc le nombre fois que tu passes dans la boucle par seconde) tu peux utiliser la méthode du filtre avec du random. Tu peux définir le nombre de coupure dans tableau que tu vas avoir, par exemple 3 sur un tableau de 30, donc de 0 à 9 sera rand()%2 -1, de 10 à 19 ... jusqu'à la fin, tu auras donc un tableau avec 3 parties remplis du même nombre random.
Pour modifier et rendre un peu plus "vivant" tu peux encore faire du random pour déterminer la taille des parties : tu tires autant de nombres aléatoires que de parties (avec un modulo pour réduire la taille des nombres). La somme de tous ces nombres correspondra à la taille de ton tableau et par une règle de trois tu peux convertir chaque nombre à la taille d'une partie du filtre qui sera remplie avec le même le nombre.
j'espère que j'aurais été assez claire car c'est pas très facile à explique mais en gros prend en pour référence la barre en dessous de la map :
Du coup, j'ai fait un grand filtre précalculé de 32 lignes par la largeur de l'image. Mais la SDL2, c'est la galère pour les accès aux pixels des textures plus l'impossibilité d'appliquer une texture sur une autre (sans ACCESS_TARGET)... C'est vachement plus simple avec les surfaces. Du coup, je suis obligé de relire le renderer...
J'ai fait ça pour l'instant, rien n'est encore sécurisé :
typedef struct CEV_WaterReflection
{
char direction,//effect direction
*filter; //filter array
CEV_Timer timer;//filter generation tick
uint32_t index;//filter row index
SDL_Rect srcClip, //what part of render to reflect
dstBlit; //where to display (dim only)
SDL_Texture *water;
void *pixels; //to copy render
}
CEV_WaterReflection;
CEV_WaterReflection* CEV_waterCreate(int w, int h, unsigned int refreshRate, SDL_Rect srcRect);
void CEV_waterShow(CEV_WaterReflection* effect, SDL_Rect blitPos);
void CEV_waterDestroy(CEV_WaterReflection* effect);
La doc semble dire qu'il est lent de relire le renderer, mais je n'ai pas le choix. Cela semble assez rapide pour le framerate imposé, donc pas de souci.
ça me semble pas trop mal, je vais tester un render plus large et faire bouger l'image pour voir si ça rend correct.
ah d'accord je commence à comprendre toutes la subtilité du problème. Tu ne veux pas appliquer un [x-1, x+1] à ton image mais une partie de ton image.
Ce que je penses à premièrement c'est de découpé ton image en plusieurs partie que tu feras bougé indépendamment. J'ai utiliser les SDL_Rect de SDL_RenderCopyEx pour pouvoir appliquer des zoom, mais tu peux aussi l'utiliser pour couper ton image sans faire de copie ou de la relire. C'est très délicat à utiliser mais voilà un code que j'ai fais en C++ qui utilise la SDL et ce principe de Rect pour appliquer des zooms et autres par rapport à une image de référence.
Tu peux y aller en brute force avec cette méthode pour prendre pixel par pixel
Si tu peux aussi envoyer des images du rendu car je ne vois pas très bien les problèmes que tu rencontres
[SDL2] Refleter le monde
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Bonhomme !! | Jeu de plateforme : Prototype.
Bonhomme !! | Jeu de plateforme : Prototype.