web-dev-qa-db-fra.com

WebGL / GLSL - Comment fonctionne un ShaderToy?

J'ai fait le tour de Shadertoy - https://www.shadertoy.com/ - récemment, dans un effort pour en savoir plus sur OpenGL et GLSL en particulier.

D'après ce que je comprends jusqu'à présent, l'utilisateur OpenGL doit d'abord préparer toute la géométrie à utiliser et configurer le serveur OpenGL (nombre de lumières autorisées, stockage de texture, etc.). Une fois cela fait, l'utilisateur doit alors fournir au moins un programme de vertex shader et un fragment shader program avant qu'un programme OpenGL ne se compile.

Cependant, lorsque je regarde les exemples de code sur Shadertoy, je ne vois qu'un seul programme de shader, et la plupart de la géométrie utilisée semble être écrite directement dans le code GLSL.

Comment ça marche?

Je suppose qu'un vertex shader est déjà préparé à l'avance et que le shader modifiable/échantillon n'est qu'un fragment shader. Mais cela n'explique pas la géométrie dans certains des exemples les plus complexes ...

Quelqu'un peut-il expliquer comment fonctionne Shadertoy?

46
Charlie

ShaderToy est un outil pour écrire des pixel shaders.

Que sont les pixel shaders?

Si vous effectuez un rendu en plein écran, ce qui signifie que chacun des quatre points est placé dans l'un des quatre coins de la fenêtre d'affichage, le fragment shader de ce quad s'appelle pixel shader, car vous pourriez dire que maintenant chaque fragment correspond exactement à un pixel de l'écran. Un pixel shader est donc un fragment shader pour un quad en plein écran.

Les attributs sont donc toujours les mêmes, tout comme le vertex shader:

positions = [ [-1,1], [1,1], [-1,-1], [1,-1] ]
uv = [ [0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0] ]

Et ce quad est rendu comme TRIANGLE_STRIP. De plus, au lieu de définir explicitement UVs, certains préfèrent utiliser la variable intégrée du fragment shader gl_FragCoord, qui est ensuite divisé avec, par exemple, un uniform vec2 uScreenResolution.

Vertex shader:

attribute vec2 aPos;
attribute vec2 aUV;
varying vec2 vUV;

void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
    vUV = aUV;
}

Et le fragment shader ressemblerait alors à ceci:

uniform vec2 uScreenResolution;
varying vec2 vUV;

void main() {
    // vUV is equal to gl_FragCoord/uScreenResolution
    // do some pixel shader related work
    gl_FragColor = vec3(someColor);
}

ShaderToy peut vous fournir quelques uniformes par défaut, iResolution (alias uScreenResolution), iGlobalTime, iMouse, ... que vous pouvez utiliser dans votre pixel shader.

Pour coder la géométrie directement dans le fragment shader (aka pixel shader), le développeur utilise quelque chose appelé ray-tracing. C'est un domaine de programmation assez complexe, mais en bref: vous présentez votre géométrie à travers des formules mathématiques, et plus tard dans le pixel shader, lorsque vous souhaitez vérifier si certains pixels font partie de votre géométrie, vous utilisez cette formule pour récupérer ces informations. Un peu de recherche sur Google devrait vous donner beaucoup de ressources pour lire à partir de quoi et comment les traceurs de rayons sont construits exactement, et cela pourrait aider: Comment faire le lancer de rayons dans OpenGL moderne?

J'espère que cela t'aides.

61
Abstract Algorithm

ShaderToy affiche un GLSL simple qui est programmé pour gérer tout l'éclairage, la géométrie, etc., ce n'est pas la géométrie des sommets, c'est la plupart de la diffusion de rayons, les trucs 3D, ou vous pouvez faire des shaders 2D, etc.

Toutes les mathématiques de couleur et d'espace peuvent être programmées en langage GLSL. Des combinaisons d'algorithmes avancés créent des isosurfaces, des formes, puis projettent des textures sur des isosurfaces, et le raycasting, envoyant des lignes imaginaires du spectateur à distance, intercepte quoi que ce soit sur le chemin, il existe de nombreuses techniques de raycasting pour la 3D.

visitez www.iquilezles.org pour avoir une idée des différents outils utilisés dans les graphiques shadertoy/glsl

7
com.prehensible

Il s'agit simplement de pousser le code source du nuanceur de pixels GLSL directement sur la carte graphique.La vraie magie se produit dans les algorithmes incroyablement intelligents que les gens utilisent pour créer des effets étonnants, comme la marche des rayons, le lancer de rayons, le traçage des rayons. mieux pour jeter un œil à d'autres sandbox GLSL en direct comme: http://glsl.heroku.com/ et http://webglplayground.net/ . Il s'agit essentiellement de créer une fenêtre généralement deux triangles qui représentent l'écran, puis le shader fonctionne sur chaque pixel comme un ray tracer.
Je les ai regardés depuis un moment maintenant, et les algorithmes que les gens utilisent sont hallucinants, vous aurez besoin de quelques calculs mathématiques sérieux et de rechercher le code source du "codage de démonstration" pour pouvoir vous envelopper. leur. Beaucoup sur le jouet shader, soufflez simplement! Donc, pour résumer, il vous suffit d'apprendre le codage et les algorithmes du shader GLSL. Pas de solution facile.

6
panpsychist

Traditionnellement en infographie, la géométrie est créée à l'aide de sommets et rendue à l'aide d'une certaine forme de matériaux (par exemple, des textures avec éclairage). Dans GLSL, le vertex shader traite les sommets et le fragment (pixel) shader traite les matériaux.

Mais ce n'est pas le seul moyen de définir des formes. Tout comme une texture peut être définie de manière procédurale (au lieu de rechercher ses texels), une forme peut être définie de manière procédurale (au lieu de rechercher sa géométrie).

Ainsi, à l'instar du lancer de rayons, ces fragments de shaders sont capables de créer des formes sans que leur géométrie soit définie par des sommets.

Il existe encore plus de façons de définir des formes. Par exemple. données de volume (voxels), courbes de surface, etc. Un texte d'infographie devrait couvrir certains d'entre eux.

2
mlepage