J'essaie de faire fonctionner ce shader sur un très ancien iDevice, ainsi que finalement Androids.
Même lorsque je réduis le code à 2 fonctions sinus par fragment, le shader tourne à environ 20fps.
J'ai envisagé de prendre une feuille du livre des anciennes techniques d'ombrage et de créer un tableau qui contient un tas de valeurs de trig prédéfinies et de les utiliser d'une manière ou d'une autre pour approximer le shader.
Dans le shader que j'ai lié ci-dessus, je simule déjà qu'en arrondissant les valeurs envoyées à la fonction trig la plus à gauche de la souris (tout en bas) diminue la qualité du shader. C'est en fait assez cool car très proche du côté gauche, il ressemble à un shader complètement différent et assez cool.
Quoi qu'il en soit, j'ai deux dilemmes:
- Je ne sais pas quel est le moyen le plus efficace d'avoir un tableau de valeurs comme 360 dans un shader GLSL, constant ou uniforme?
Je ne peux pas comprendre comment mettre un nombre dans une plage comme d'habitude si je voulais un angle entre 0 et 360 (oui je sais que les GPU utilisent des radians), je le ferais comme ça.
func range(float angle) { float temp = angle while (temp > 360) {temp -= 360;} while (temp < 0) {temp += 360;} return temp; }
Cependant, GLSL n'autorise pas les boucles while ni les fonctions récursives.
la source
mod
fonction intégrée est ce que vous voulez. Vous écririezmod(angle, 360.0)
.Réponses:
Il a été suggéré à plusieurs reprises dans les commentaires, mais personne n'a ressenti le besoin de donner une réponse appropriée.Par souci d'exhaustivité, une solution simple et courante à ce problème pourrait être d'utiliser une texture comme table de recherche, en particulier une texture 1D qui contient toutes les valeurs de votre fonction pour la plage d'entrée possible (c'est-à-dire / ]. Cela présente divers avantages:[ 0 , 2 π )[0,360) [0,2π)
GL_REPEAT
comme mode d'habillage pour la texture et elle recommencera automatiquement au début lors de l'accès avec des arguments> 1 (et de même pour les arguments négatifs).GL_LINEAR
comme filtre de texture, de cette manière, vous obtenez des valeurs que vous n'avez même pas stockées. Bien sûr, l'interpolation linéaire n'est pas précise à 100% pour les fonctions trigonométriques, mais c'est certainement mieux que pas d' interpolation.float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;
Bien sûr, il reste à évaluer si c'est une meilleure solution, car l'accès aux textures n'est pas entièrement gratuit non plus, ainsi que la meilleure combinaison de taille et de format de texture.
En ce qui concerne le remplissage de la texture avec des données et l'adressage d'un de vos commentaires, vous devez considérer que le filtrage de texture renvoie la valeur exacte au centre du texel , c'est-à-dire une coordonnée de texture décalée de la moitié de la taille du texel. Alors oui, vous devez générer des valeurs au niveau des
.5
texels , c'est-à-dire quelque chose comme ça dans le code d'application:Cependant, vous souhaiterez peut-être toujours comparer les performances de cette approche avec une approche utilisant un petit tableau uniforme (c'est-à[0,360)
uniform float sinTable[361]
- dire , ou peut-être moins en pratique, gardez un œil sur la limite de votre implémentation sur la taille du tableau uniforme) que vous chargez simplement avec les valeurs respectives en utilisantglUniform1fv
et accédez en ajustant votre angle à utilisant la fonction et en l'arrondissant à la valeur la plus proche:mod
la source