【问题标题】:Shadertoy - fragCoord vs iResolution vs fragColorShadertoy - fragCoord vs iResolution vs fragColor
【发布时间】:2021-12-29 23:08:59
【问题描述】:

总的来说,我对 Shadertoy 和 GLSL 还很陌生。我已经成功地将许多 Shadertoy 着色器复制到 Blender 中,但实际上并不知道它是如何工作的。我一直在寻找教程,但我更像是视觉学习者。

如果有人可以解释,或者更好的是,提供一些描述 fragCoord、iResolution 和 fragColor 之间区别的图像。那太好了!

我主要对数字感兴趣。因为我使用 Blender,所以我习惯于画布是 0 到 1 -或- -1 到 1

尤其是这个让我有点困惑。

vec2 u = (fragCoord - iResolution.xy * .5) / iResolution.y * 8.;

在不知道坐标系的情况下,我无法在 Blender 中重现剩余的代码。

任何帮助将不胜感激!

【问题讨论】:

  • 学习问题,你是什么意思:“我已经成功地将许多 Shadertoy 着色器复制到 Blender 中”。在 Blender OSL 或 Blender 2.8 PyGL 界面中,或通过视觉匹配输出?
  • @nabr 在 Blender 2.8 中使用 Cycles 节点。由于 glsl 的数学运算方式,我不得不创建许多向量数学组。

标签: glsl shader


【解决方案1】:

这是正常的,在不知道坐标系的情况下无法在blender中重现这段代码。

The Shadertoy documentation states:

图像着色器实现 mainImage() 函数来生成 通过计算图像中每个像素的颜色来生成程序图像。 此函数在每个像素和主机应用程序中调用一次 必须提供适当的输入数据并检索输出颜色 将其分配给屏幕上的相应像素。签名 这个函数是:

void mainImage(out vec4 fragColor, in vec2 fragCoord);

其中 fragCoord 包含像素的坐标, 着色器必须计算颜色。这些坐标以像素为单位 整个渲染过程中的值从 0.5 到 resolution-0.5 表面和该表面的分辨率传输到 着色器通过统一 iResolution 变量。

让我解释一下。

iResolution 变量是一个 uniform vec3,它包含窗口的尺寸,并通过一些 openGL 代码发送到着色器。

fragCoord 变量是一个内置变量,其中包含应用着色器的像素坐标。

更具体地说:

  • fragCoord :是一个vec2,在 X 轴上 0 > 640 和 Y 轴上 0 > 360 之间
  • iResolution:是一个vec2,X 值为 640,Y 值为 360

关于向量如何在 OpenGL 中工作的快速说明:

  • 如果您也很难理解矢量在 OpenGL 中的工作原理,我强烈建议您阅读下面的 Homan 的回答,这是对 OpenGL swizzling 的非常有用的介绍。

这张图片是用下面的代码计算出来的:

    // Normalized pixel coordinates (between 0 and 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Set R and G values based on position
    vec3 col = vec3(uv.x,uv.y,0);

    // Output to screen
    fragColor = vec4(col,1.0);

输出范围从左下角的0,0 和右上角的1,1。这是 OpenGL 设置的默认左下窗口空间。


此图像是使用以下代码计算得出的:

    // Normalized pixel coordinates (between -0.5 and 0.5)
    vec2 uv = (fragCoord - iResolution.xy * 0.5)/iResolution.xy;
    
    // Set R and G values based on position
    vec3 col = vec3(uv.x,uv.y,0);

    // Output to screen
    fragColor = vec4(col,1.0);

输出范围从左下角的-0.5,-0.50.5,0.5,因为 在第一步中,我们从每个像素坐标 [fragCoord] 中减去一半的窗口大小 [0.5]。您可以看到效果,因为红色和绿色值直到很久以后才会出现。

您可能还想通过将第一步更改为

标准化 y 轴
vec2 uv = (fragCoord - iResolution.xy * 0.5)/iResolution.y;

根据您的目的,如果您对两个轴进行归一化,图像可能看起来很奇怪,因此这是一种可能的策略。


这张图片是用下面的代码计算出来的:

    // Normalized pixel coordinates (between -0.5 to 0.5)
    vec2 uv = (fragCoord - iResolution.xy * 0.5)/iResolution.xy;
   
    // Set R and G values based on position using ceil() function
    // The ceil() function returns the smallest integer that is greater than the uv value
    vec3 col = vec3(ceil(uv.x),ceil(uv.y),0);

    // Output to screen
    fragColor = vec4(col,1.0);

ceil()函数可以让我们看到图片的中心是0, 0


关于shadertoy文档的第二部分:

输出颜色在 fragColor 中作为四分量向量返回, 客户端忽略的最后一个组件。结果是 在预期未来添加的“out”变量中检索 几个渲染目标。

这实际上意味着fragColor 包含四个值,这些值被存储到渲染管道的下一个阶段。 You can find more about in and out variables here.

fragColor 中的值决定了应用着色器的像素的颜色。

如果您想了解有关着色器的更多信息,以下是一些不错的起点:

the book of shader - uniform
learn OpenGL - shader

【讨论】:

  • 所以,这就是让我失望的东西... fragCoord.x = {0, 1, 2, 3, 4...} fragCoord.y = {0, 1, 2, 3, 4...} iResolution = (640, 480)
  • 在我原来的问题中进行数学运算...我得到了一个从 (-7.1, -4) 到 (7.1, 4) 的坐标系。是吗?不?哈哈
  • 让我失望的是“混搭”。 khronos.org/opengl/wiki/Data_Type_(GLSL)#Vectors iResolution.xy 会给你一个 vec2,但仅仅除以 iResolution 会给你不兼容的类型。 iResolution(不带 .xy)不是 vec2
【解决方案2】:

不要拿走已接受的答案,这是非常彻底的。但万一其他人对这些类型感到困惑,iResolution 是“浮点的统一 highp 3 分量向量”......所以实际上是 vec3?这就是为什么我们在示例中看到 fragCoord(实际上是一个 vec2)除以 iResolution.xy(.xy 给我们一个 vec2)。但是“.xy”是什么东西?它是一种方法吗?属性或属性?通过一些随机的谷歌搜索,我发现最后添加的“.xy”被称为“swizzling”

https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Vectors

(为方便起见,下面是它的要点)

混搭

您可以使用以下语法访问向量的组件:

vec4 someVec;
someVec.x + someVec.y;
This is called swizzling. You can use x, y, z, or w, referring to the 
first, second, third, and fourth components, respectively.

之所以叫它“swizzling”,是因为下面的语法是完全有效的:

vec2 someVec;
vec4 otherVec = someVec.xyxx;
vec3 thirdVec = otherVec.zyy;

您可以使用最多 4 个字母的任意组合来创建该长度的向量(基本类型相同)。所以 otherVec.zyy 是一个 vec3,我们可以用它来初始化一个 vec3 值。最多 4 个字母的任何组合都是可接受的,只要源向量实际上具有这些组件。例如,尝试访问 vec3 的“w”组件是一个编译时错误。

Swizzling 也适用于左值(左值?):

vec4 someVec;
someVec.wzyx = vec4(1.0, 2.0, 3.0, 4.0); // Reverses the order.
someVec.zx = vec2(3.0, 5.0); // Sets the 3rd component of someVec to 3.0 and the 1st component to 5.0

但是,当您使用 swizzle 作为设置组件值的一种方式时,您不能两次使用同一个 swizzle 组件。所以 someVec.xx = vec2(4.0, 4.0);不允许。

此外,还有 3 套调酒面膜。您可以使用 xyzw、rgba(用于颜色)或 stpq(用于纹理坐标)。这三套没有实际区别;它们只是语法糖。您不能在单个 swizzle 操作中组合来自不同集合的名称。所以“.xrs”不是有效的调酒掩码。

在 OpenGL 4.2 或 ARB_shading_language_420pack 中,标量也可以混合。它们显然只有一个源组件,但这样做是合法的:

float aFloat;
vec4 someVec = aFloat.xxxx;

【讨论】:

  • 一个非常有用的答案!将编辑我的回复,让人们知道要注意你的。没想到 swizzling 是一件很难接受的事情,因为会写下答案!
【解决方案3】:

// -1 to 1
vec2 uv = (2.0 * fragCoord - iResolution.xy) / iResolution.xy;

vec3 col = vec3(uv.x, uv.y, 0.0);

fragColor = vec4(col1, 1.0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-17
    • 2011-09-18
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 2010-12-09
    • 2017-06-20
    相关资源
    最近更新 更多