jjzjj

javascript - WebGL - 顶点着色器调用的变量数组大小

coder 2024-12-31 原文

上下文

我正在尝试在 Canvas 中绘制贝塞尔曲线。 我实现了从着色器中绘制二次和三次曲线,但到目前为止我确实为每个控制点设置了统一变量。

因此,我在 Canvas 上单击,添加点,当我有足够的点(分别为 3 和 4)时,我绘制曲线。

现在我正在尝试概括贝塞尔曲线。虽然我在 JavaScript 端实现了这一点,但我觉得从着色器端完成它会更好,因为渲染速度会大大提高。

因此,我想在至少有两个点后立即绘制曲线。但我可以继续添加点并使用每个点绘制曲线,以作为控制点。

解释

所以我知道在 GLSL 中设置动态数组是不可能的,但是是否可以基于 JS 变量动态声明 GLSL 数组?

如果我的问题不清楚(我知道我很难马上表述清楚),让我用一个例子来解释。

uniform vec2 uMyPoints[<length>];

所以这就是我想要实现的,但是当然,根据 glsl 规范,数组大小必须是常量。

但是,从我的 Angular 来看,我觉得我应该能够从 JS 变量设置 length。我的直觉是,在渲染期间不同着色器的执行期间,GLSL 中的数组大小将保持不变,但可以从一个渲染更改为另一个渲染。

问题

所以我要问你的问题是:基于这些,你是否知道能够从 javascript 变量在 GLSL 中设置常量的任何好方法或技巧?

如果这似乎是可能的,这将对我有很大帮助。感谢您的考虑。

作为比较:我们如何从 JS 设置“numLights" in this example”?

回答

字符串替换非常适合我的需要。虽然这有点棘手,但它会做得很好。进一步的研究让我知道隐式数组大小在 Open GL ES 版本 3 中可用, future 版本的 WebGL 应该会使用它,但不是现在。

另一方面,第二个建议不符合我的需要,因为我正是想避免在着色器中有 N 个点,因为点的数量可能会改变。

感谢您的回答;)

最佳答案

字符串替换有效

<script id="vs" type="notjs">    
uniform vec2 uMyPoints[<length>];
...
</script>

js

var numPoints = 10;
var vSrc = document.getElementById("vs").text;
vSrc = vSrc.replace(/<length>/g, numPoints);

这是大多数复杂程序为着色器做的事情。他们通过字符串操作生成着色器。

当然,您可能希望使用更好的函数来进行字符串替换。例如可能是这样的

  /**
   * Replace %(id)s in strings with values in objects(s)
   *
   * Given a string like `"Hello %(name)s from $(user.country)s"`
   * and an object like `{name:"Joe",user:{country:"USA"}}` would
   * return `"Hello Joe from USA"`.
   *
   * @function
   * @param {string} str string to do replacements in
   * @param {Object|Object[]} params one or more objects.
   * @returns {string} string with replaced parts
   * @memberOf module:Strings
   */
  var replaceParams = (function() {
    var replaceParamsRE = /%\(([^\)]+)\)s/g;

    return function(str, params) {
      if (!params.length) {
        params = [params];
      }

      return str.replace(replaceParamsRE, function(match, key) {
        var keys = key.split('.');
        for (var ii = 0; ii < params.length; ++ii) {
          var obj = params[ii];
          for (var jj = 0; jj < keys.length; ++jj) {
            var part = keys[jj];
            obj = obj[part];
            if (obj === undefined) {
              break;
            }
          }
          if (obj !== undefined) {
            return obj;
          }
        }
        console.error("unknown key: " + key);
        return "%(" + key + ")s";
      });
    };
  }());

现在如果你的着色器看起来像这样

uniform Lights u_lights[%(numLights)s];
uniform vec2 u_points[%(numPoints)s];

你可以替换为

vSrc = replaceParams(vsrc, {
   numLights: 4,
   numPoints: 10,
});

当然你也可以在着色器中使用`#define

#define NUM_LIGHTS %(numLights)s
#define NUM_POINTS %(numPoints)s

uniform Lights u_lights[NUM_LIGHTS];
uniform vec2 u_points[NUM_POINTS];

void main() {
  for (int i = 0; i < NUM_LIGHTS; ++i) {
    ...
  }
}

等..

但是,老实说,大多数人不会通过贝塞尔曲线控制点作为制服,因为对制服的数量有严格的限制。大多数人会通过属性中的贝塞尔曲线控制点。你甚至可以在调用 gl.vertexAttribPointer 时设置步幅和偏移量,这样如果你的点数不对

 [pt0, pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8, ..]

可以制作4个属性

attribute vec2 p0;
attribute vec2 p1;
attribute vec2 p2;
attribute vec2 p3;

然后用偏移量和步幅指向所有这些点以设置您的 4 个属性,以便提取点

p0 = pt0, p1 = pt1, p2 = pt2, p3 = pt3,
p0 = pt1, p1 = pt2, p2 = pt3, p3 = pt4,
p0 = pt2, p1 = pt3, p2 = pt4, p3 = pt5,
p0 = pt3, p1 = pt4, p2 = pt5, p3 = pt6,

等..

关于javascript - WebGL - 顶点着色器调用的变量数组大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33299796/

有关javascript - WebGL - 顶点着色器调用的变量数组大小的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  6. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  7. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  8. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  9. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  10. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

随机推荐