WebGL 与 openGL 中的着色器?

Shaders in WebGL vs openGL?

我想在 WebGL 中使用着色器,特别是 three.js。是否有 WebGL 和 three.js 使用的特定版本的 GLSL?

WebGL 着色器遵循 GLSL ES 1.017 规范

https://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf

这在几个方面与桌面 OpenGL 不同。一个是 GLSL ES 的 1.0 版本,其中 GLSL 4.2 版本的桌面 GL(不是 ES)

WebGL GLSL 与在 Internet 上找到的许多有关着色器的文章之间的一大区别是 OpenGL ES 2.0 中没有固定功能管道,因此 WebGL 中没有固定功能管道。

固定功能管道是 OpenGL 1.0 遗留下来的,您可以在其中使用 glLightglVertexglNormal 等命令。然后您的着色器需要一种方法来引用该数据。在 OpenGL ES 和 WebGL 中,所有这些都消失了,因为着色器所做的一切都是 100% 由用户决定的。 WebGL 所做的就是让您定义自己的输入(属性、制服)并根据需要命名它们。

WebGL2 着色器遵循 GLSL ES 3.00 规范

https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf

至于 three.js,three.js 是一个 3d 引擎,在生成着色器时会提供自己的一组标准输入、名称和其他功能。 See the docs for some of the details. The uniforms and attributes provided by default are documented here. You can also look at the source or check out an example

Three.js 还提供了一种称为 RawShaderMaterial 的东西,它显然不会添加任何预定义的东西,在这种情况下,您只需编写标准的 WebGL GLSL。

你可以找到three.js的标准属性和制服here

至于学习GLSL的地方我真的没有什么建议。这实际上取决于您的总体编程经验水平以及您喜欢的学习方式。我通过看例子比阅读手册更好地学习。也许其他人可以添加一些链接。

Shaders as a concept are pretty simple。您创建一对着色器,使用输入设置它们,调用 gl.drawArrays 或 gl.drawElements 并传入计数。您的顶点着色器将被调用 count 次,需要设置 gl_Position。每调用 1 到 3 次 WebGL 就会绘制一个点、线或三角形。为此,它将调用您的片段着色器,询问它要绘制什么颜色来制作该像素的每个像素。片段着色器需要设置gl_FragColor。着色器从 attributesuniformstexturesvaryings 获取数据。 attributes 是每个顶点数据。他们从缓冲区中提取数据,顶点着色器每次迭代每个属性一个数据。 Uniforms 就像在着色器运行前设置全局变量。您可以使用 varying 将数据从顶点着色器传递到片段着色器。当调用片段着色器为每个像素提供颜色时,该数据将在为图元(三角形)的每个顶点设置的值之间插值 或变化 ;)

您可以创造性地向着色器提供数据并创造性地使用该数据来设置 gl_Positiongl_FragColor。我从查看示例中获得大部分想法。

GLSL 本身非常简单。有几种类型 intfloatvec2vec3vec4mat2mat3mat4.它们响应运算符 +-*/ 等。有一些内置函数。

您可以在 WebGL Reference Card 的最后两页找到所有 GLSL 信息的简洁版本。

这对我来说已经足够了。然后看着 working programs.

对我来说,与大多数语言相比,一件有趣的事情是 vec 字段和 swizzling 的同义词。例如一个vec4

vec4 v = vec4(1.0, 2.0, 3.0, 4.0);

您可以使用 x,y,z,ws,t,u,vr,g,b,a 或数组样式来引用 v 的各种组件。例如

float red = v.r;  // OR
float red = v.x;  // same thing OR
float red = v.s;  // same thing OR
float red = v[0]; // same thing

您可以做的另一件事是混合

vec4 color = v.bgra;   // swap red and blue
vec4 bw    = v.ggga;   // make a monotone color just green & keep alpha

而且还可以获得子组件

vec2 just_xy = v.xy;