1

Hello,

Je préviens tout de suite : #noob#, je fais juste quelques tests avec WebGL pour voir ce que ça permettra de faire une fois que ça sera supporté officiellement par les navigateurs.

Dans mon fragment shader, je cherche à appliquer une lumière spéculaire en utilisant une gloss map (ou specular map ? je ne sais pas s'il y a une appellation officielle, mais il s'agit de la texture qui spécifie quelles sont les zones les plus réfléchissantes de mon matériau). La formule que je retrouve partout, et qui fonctionne presque très bien, est :
specularLightPower = pow (cosine, texture2D (glossMap, fragCoord).r * materialShininess);
Où "cosine" est le cosinus (> 0) entre mon angle de vue et l'angle de réflexion de la lumière, "materialShininess" est la valeur de réflexion de base du matériau, et "glossMap" est ma gloss map qui permet de faire varier la réflexion de base (j'ai choisi arbitrairement la couleur rouge pour représenter le coefficient de réflexion).

Le souci c'est que si ma gloss map contient des points où la composante rouge est nulle, alors je fais un "pow (cosine, 0)" et je me retrouve avec une lumière maximale même si le cosinus était très faible au départ, ce qui me fait des petits points blancs qui apparaissent (cf. screenshot). [edit] c'est encore plus flagrant si je n'active que la gloss map : screenshot.

Alors déjà est-ce que je m'y prends comme un pied, et est-ce qu'il y a une façon élégante d'éviter ce problème ? (je pourrais éviter d'avoir des points où r=0 sur ma texture, ou bien ajouter une constante très faible à chaque point, mais c'est pas top comme solution je trouve).

Merci smile
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

2

Ben heu, l'équation fonctionne très bien, mais l'équation sert à appliquer l'éclairage spéculaire. Si tu en veux, tu appliques l'équation, si tu n'en veux pas tu ne l'appliques pas tongue
Tu as envisagé de poser une condition dans ton code ? (Bien avant que les branchements statiques et dynamiques aient été ajoutés, les shader supportaient déjà des instructions conditionnelles statiques… je suppose que c'est géré en GLSL ^^) niness) : 0;Par exemple:specularLightPower = fragCoord.r > 0 ? pow (cosine, texture2D (glossMap, fragCoord).r * materialShiNon ? (Bon je ne connais pas le GLSL, mais j'ose supposer qu'il supporte ?: ^^)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

3

Heu non, tu as inversé la formule happy

Pour diminuer la réflexion de la lumière, c'est à dire diminuer specularLightPower, il faut avoir un r aussi grand que possible, en l'occurrence, r = 1.0 (puisque le cosinus est <= 1.0). On pourrait tout à fait traiter le cas particulier r = 1.0 comme tu le proposes ("specularLightPower = (r < 1.0 ? pow (blabla) : 0);"), mais c'est le cas r = 0.0 qui m'intéresse ici.

Quand r tend vers zéro, la réflexion du matériau augmente, donc quelque part c'est logique qu'un r à zéro implique une lumière maximale, mais là ça la fixe à 1 quelque soit l'angle donc c'est un peu trop violent ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

4

Heu merde, tu as raison, j'ai inversé la formule dans ma réflexion… cheeky (Le pire c'est que je sais parfaitement comment ça marche pour l'avoir codé en shaders n fois…)
En fait le début de ma réflexion est que le 0 est une valeur aberrante. Comme tu l'explique ça fait 1 quel que soit la valeur x… Je m'étais arrêté là ^^ (Et donc pour aller plus loin, cette fois-ci sur le bon chemin, c'est tout à fait normal)
Donc tu devrais l'éliminer… le code que j'ai indiqué reste bon je pense.
(Et puis de cette manière, tu peux toujours avoir un énorme éclairage spéculaire avec R = 10^-n (avec n très grand tongue) du coup)
Ou bien en fait tu peux juste ne jamais mettre de 0 dans ta texture, ce qui serait aussi très sage. cheeky
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

5

C'est ce que j'ai fait temporairement, mais c'est crade (encore plus que d'ajouter artificiellement une constante assez faible à r grin)

Je suis d'accord que 0 est une valeur aberrante (ou en tout cas qui n'arrange pas les calculs tongue), mais autant pour 1.0 je peux simplement désactiver la réflexion, autant pour 0.0 je ne peux pas trop remplacer par une autre valeur (à part 1.0, que je veux précisément éviter ^^).

S'il n'y a pas de solution je me démerderai pour qu'il n'y ait pas de 0.0 dans la texture, mais je me demandais quand même s'il n'y avait pas une façon plus élégante de contourner le problème smile
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

6

Tu ne pourrais pas ne pas appliquer cet effet sur les textures qui ne reçoivent pas de lumière ?
avatar

7

Si, mais ça ne corrigerait pas le problème pour autant : une texture qui reçoit une très faible lumière continuera à afficher des pixels blancs là où r=0 (cf. les deux screenshots, c'est assez parlant).
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

8

Pour les autres points que l'on voit, en fait, je ne pense pas qu'il s'agisse d'une erreur. En fait, d'après la définition que tu donnes de cet effet, je me demande pourquoi tu voudrais que cette brillance soit limitée à une certaine valeur. Il me semble normal qu'on puisse obtenir un matériau extrêmement brillant qui pourrait réfléchir de la lumière même rasante...

C'est ta texture qui est mal faite smile Le ciment ne devrait pas atteindre de telles valeurs tongue
(Par contre, il faut bien supprimer l'effet lorsque la surface est dos à la lumière)
avatar

9

pencil
Mais par contre pour la surface dos à la lumière ce tu n'en as besoin que si le culling est désactivé ^^
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

10

Bah si la surface est dos à la lumière, le cosinus est < 0 donc la lumière n'est pas prise en compte.

Sinon je ne voudrais pas que la brillance soit limitée à une certaine valeur, ce qui me gène c'est le passage trop net quand la brillance est à zéro ; le fait que x^0 = 1 quel que soit x provoque un passage d'un pixel sombre à un pixel totalement blanc, et j'aurais souhaité avoir une transition souple même pour ce cas extrême. Mais mathématiquement c'est tout à fait normal que j'obtienne ce résultat avec la formule que j'ai utilisé, oui ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

11

Ben alors ajoute une constante très faible comme tu l'as proposé. (Me semble que dans les shader la précision est supérieure à 8 bits donc tu peux vraiment mettre un truc très faible)
Par contre d'un point de vue performances (attention, c'est de la micro optimisation grin), je pense que c'est mieux de faire des textures sans 0 que d'ajouter une constante à chaque calcul de luminosité.
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

12

iwannabeamaki (./10) :
Bah si la surface est dos à la lumière, le cosinus est < 0 donc la lumière n'est pas prise en compte.
Je te dis ça, c'est pour qu'il n'y ait plus les points du côté ombragé wink Le truc du cosine = 0 ne fonctionne pas à cause du ^0, il faut faire autrement...
iwannabeamaki (./10) :
Sinon je ne voudrais pas que la brillance soit limitée à une certaine valeur, ce qui me gène c'est le passage trop net quand la brillance est à zéro ; le fait que x^0 = 1 quel que soit x provoque un passage d'un pixel sombre à un pixel totalement blanc, et j'aurais souhaité avoir une transition souple même pour ce cas extrême. Mais mathématiquement c'est tout à fait normal que j'obtienne ce résultat avec la formule que j'ai utilisé, oui ^^
Cette valeur 0 ne devrait être utilisée que pour des objets extrêmement brillants, comme un éclat de verre pris dans le ciment de ton mur ou pour les petits cailloux les plus brillants.

Si c'est la taille du point qui te dérange parce que ça fait quand même beaucoup de lumière pour un tout petit truc qui brille, c'est que le problème est ailleurs que dans la formule ^^. Ta texture ne devrait présenter des pixels de cette couleur que de façon isolée. Ces pixels doivent bien sûr être bien plus petits que les pixels de l'image finale. En fait, ce qui te manque, c'est de l'antialiasing smile
avatar

13

GoldenCrystal (./11) :
Ben alors ajoute une constante très faible comme tu l'as proposé. (Me semble que dans les shader la précision est supérieure à 8 bits donc tu peux vraiment mettre un truc très faible)
Par contre d'un point de vue performances (attention, c'est de la micro optimisation grin), je pense que c'est mieux de faire des textures sans 0 que d'ajouter une constante à chaque calcul de luminosité.

Oui, la précision est plus fine que les 8 bits originaux de la texture, pas de souci de ce côté-là. On gagne bien quelques additions en préparant à l'avance une texture sans zéro, mais comparé au reste, je suis pas sûr que ce soit un gain mesurable grin
RHJPP (./12) :
Je te dis ça, c'est pour qu'il n'y ait plus les points du côté ombragé wink Le truc du cosine = 0 ne fonctionne pas à cause du ^0, il faut faire autrement...

C'est déjà fait, le screenshot était bien là pour montrer que même avec une très faible lumière (elle touche le mur avec un angle de quasiment 90°) le pixel est totalement blanc.
Cette valeur 0 ne devrait être utilisée que pour des objets extrêmement brillants, comme un éclat de verre pris dans le ciment de ton mur ou pour les petits cailloux les plus brillants.

Si c'est la taille du point qui te dérange parce que ça fait quand même beaucoup de lumière pour un tout petit truc qui brille, c'est que le problème est ailleurs que dans la formule ^^. Ta texture ne devrait présenter des pixels de cette couleur que de façon isolée. Ces pixels doivent bien sûr être bien plus petits que les pixels de l'image finale. En fait, ce qui te manque, c'est de l'antialiasing smile

Même un caillou, aussi brillant soit-il, ça ne me semble normal qu'il passe instantanément de noir à blanc si y'a un pauvre rayon de lumière extrêmement faible qui le touche à peine :/

En revanche peut-être qu'avec de l'AA le résultat serait plus lissé et donc plus crédible, en effet smile
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)