javascript WebGL/GLSL - ShaderToy 如何工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19449590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 15:37:58  来源:igfitidea点击:

WebGL/GLSL - How does a ShaderToy work?

javascriptglslwebglshaderpixel-shader

提问by Charlie

I've been knocking around Shadertoy - https://www.shadertoy.com/- recently, in an effort to learn more about OpenGL and GLSL in particular.

最近,我一直在访问 Shadertoy - https://www.shadertoy.com/- 特别是为了了解有关 OpenGL 和 GLSL 的更多信息。

From what I understand so far, the OpenGL user first has to prepare all the geometry to be used and configure the OpenGL server (number of lights allowed, texture storage, etc). Once that's done, the user then has to provide at least one vertex shader program, and one fragment shader program before an OpenGL program compiles.

据我目前所知,OpenGL 用户首先必须准备所有要使用的几何图形并配置 OpenGL 服务器(允许的灯光数量、纹理存储等)。完成后,用户必须在编译 OpenGL 程序之前提供至少一个顶点着色器程序和一个片段着色器程序。

However, when I look at the code samples on Shadertoy, I only ever see one shader program, and most of the geometry used appears to be written directly into the GLSL code.

然而,当我查看 Shadertoy 上的代码示例时,我只看到了一个着色器程序,并且使用的大部分几何体似乎直接写入了 GLSL 代码。

How does that work?

这是如何运作的?

My guess is that a vertex shader is already prepared upfront, and that the editable/sample shader is only a fragment shader. But then that doesn't explain the geometry in some of the more complex examples...

我的猜测是顶点着色器已经预先准备好了,可编辑/样本着色器只是一个片段着色器。但这并不能解释一些更复杂的例子中的几何......

Can anyone explain how Shadertoy works?

谁能解释一下Shadertoy是如何工作的?

回答by Abstract Algorithm

ShaderToy is a tool for writing pixel shaders.

ShaderToy 是一个用于编写像素着色器的工具。

What are pixel shaders?

什么是像素着色器?

If you render a full screen quad, meaning that each of four points is placed in one of the four corners of the viewport, then the fragment shader for that quad is called pixel shader, because you could say that now each fragment corresponds to exactly one pixel of the screen. So a pixel shader is a fragment shader for a fullscreen quad.

如果渲染全屏四边形,这意味着四个点中的每一个都放置在视口的四个角之一中,那么该四边形的片段着色器称为像素着色器,因为您可以说现在每个片段都恰好对应一个屏幕的像素。所以像素着色器是全屏四边形的片段着色器。

So attributes are always the same and so is a 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] ]

And that quad is rendered as TRIANGLE_STRIP. Also, instead of setting UVsexplicitly, some prefer to use fragment shader's built-in variable gl_FragCoord, which is then divided with, for example, a uniform vec2 uScreenResolution.

该四边形呈现为TRIANGLE_STRIP. 此外,UVs有些人没有明确设置,而是更喜欢使用片段着色器的内置变量gl_FragCoord,然后将其除以例如 a 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;
}

And fragment shader would then look something like this:

然后片段着色器看起来像这样:

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 can supply you with a few uniforms on default, iResolution(aka uScreenResolution), iGlobalTime, iMouse,... which you can use in your pixel shader.

ShaderToy可以在默认的几个校服供应你,iResolution(又名uScreenResolutioniGlobalTimeiMouse......你可以在你的像素着色器使用。

For coding geometry directly into the fragment shader (aka pixel shader), developer use something called ray-tracing. That is quite complex area of programming but in short: You present your geometry through some mathematical formulas, and later in pixel shader, when you wish to check if some pixel is a part of your geometry you use that formula to retrieve that information. Google-ing a bit should give you plenty of resources to read from what and how ray tracers are built exactly, and this might help: How to do ray tracing in modern OpenGL?

为了将几何图形直接编码到片段着色器(又名像素着色器)中,开发人员使用称为光线跟踪的东西。这是一个相当复杂的编程领域,但简而言之:您通过一些数学公式展示您的几何图形,然后在像素着色器中,当您希望检查某个像素是否是您的几何图形的一部分时,您可以使用该公式来检索该信息。谷歌一点应该给你足够的资源来阅读光线追踪器是什么以及如何构建的,这可能会有所帮助: 如何在现代 OpenGL 中进行光线追踪?

Hope this helps.

希望这可以帮助。

回答by com.prehensible

ShaderToy displays simple GLSL that is programmed to handle all the lighting, geometry, etc, it's not vertex geometry, it's raycasting most of it, the 3D stuff, or you can do 2D shaders, etc.

ShaderToy 显示了简单的 GLSL,它被编程来处理所有的光照、几何体等,它不是顶点几何体,它是光线投射的大部分,3D 的东西,或者你可以做 2D 着色器等。

Any color and spacial maths can be programmed in GLSL language. Combinations of advanced algorithms makes isosurfaces, shapes, and then project textures onto isosurfaces, and raycasting, sending imaginary lines from viewer to distance, intercepts anything in the way, there are many raycasting techniques for 3D.

任何颜色和空间数学都可以用 GLSL 语言编程。高级算法的组合制作等值面、形状,然后将纹理投影到等值面上,然后进行光线投射,将假想的线从观察者发送到远处,拦截任何东西,3D 有许多光线投射技术。

visit www.iquilezles.orgfor an idea of the different tools that are used in shadertoy/glsl graphics

访问www.iquilezles.org了解在 shadertoy/glsl 图形中使用的不同工具

回答by panpsychist

It's just basically pushing GLSL pixel shader source code directly onto the graphics card.The real magic happens in the incredibly clever algorithms that people use to create amazing effects, like ray marching, ray casting, ray tracing. best to have a look at some other live GLSL sandboxes like: http://glsl.heroku.com/and http://webglplayground.net/. Its basically creating a window typically two triangles which represent the screen, then the shader works on each pixel just like a ray tracer.
I've been looking at these a while now, and the algorithms people use are mind blowing, you'll need to some serious math chops and look up "demo coding" source code to able to wrap your head around them. Many on shader toy, just blow your mind ! So to summarise, you just need to learn GLSL shader coding and algorithms. No easy solution.

它基本上只是将 GLSL 像素着色器源代码直接推送到显卡上。真正的魔法发生在人们用来创造惊人效果的难以置信的聪明算法中,例如光线行进、光线投射、光线追踪。最好看看其他一些实时 GLSL 沙箱,例如:http: //glsl.heroku.com/http://webglplayground.net/。它基本上创建了一个窗口,通常是两个代表屏幕的三角形,然后着色器像光线追踪器一样作用于每个像素。
我一直在研究这些一段时间,人们使用的算法令人兴奋,您需要进行一些严肃的数学运算并查找“演示编码”源代码,以便能够理解它们。许多着色器玩具,让您大吃一惊!所以总而言之,您只需要学习 GLSL 着色器编码和算法。没有简单的解决办法。

回答by mlepage

Traditionally in computer graphics, geometry is created using vertices and rendered using some form of materials (e.g. textures with lighting). In GLSL, the vertex shader processes the vertices and the fragment (pixel) shader processes the materials.

传统上,在计算机图形学中,几何图形是使用顶点创建的,并使用某种形式的材料(例如带照明的纹理)进行渲染。在 GLSL 中,顶点着色器处理顶点,而片段(像素)着色器处理材料。

But that is not the only way to define shapes. Just as a texture could be procedurally defined (instead of looking up its texels), a shape could be procedurally defined (instead of looking up its geometry).

但这并不是定义形状的唯一方法。正如纹理可以在程序上定义(而不是查找其纹素),形状也可以在程序上定义(而不是查找其几何形状)。

So, similar to ray tracing, these fragment shaders are able to create shapes without having their geometry defined by vertices.

因此,类似于光线追踪,这些片段着色器能够创建形状而无需顶点定义其几何形状。

There's still more ways to define shapes. E.g. volume data (voxels), surface curves, and so on. A computer graphics text should cover some of them.

还有更多的方法来定义形状。例如体积数据(体素)、曲面曲线等。计算机图形文本应该涵盖其中的一些。