webGL2统一缓冲区对象和布局的使用(std140)

Posted

技术标签:

【中文标题】webGL2统一缓冲区对象和布局的使用(std140)【英文标题】:Usage of webGL2 Uniform Buffer Object and layout(std140) 【发布时间】:2015-11-22 16:43:20 【问题描述】:

我正在做一个 webgl 布料模拟项目,尝试使用变换反馈。模拟将在顶点着色器中完成。我需要访问顶点的相邻顶点来计算力。我正在考虑使用统一缓冲区对象来存储所有顶点的位置。

我定义了一个统一的块,如下所示:

layout(std140) uniform u_testBlock

    vec4 v0;
    vec4 v1;
    ...
;

但是,我遇到了“布局:语法错误”。这是在 webGL2 中使用 UBO 的正确方法吗? webGL2规范说统一块只支持std140布局,为什么会出现这样的语法错误?

非常感谢!

【问题讨论】:

我不知道你是否意识到这一点,但是 atm 对 webGL 2 的支持非常低。先检查webglreport.com/?v=2,看看你的浏览器是否支持webGL 2。 您是否声明了适当的 GLSL ES #version 【参考方案1】:

您是否在着色器前添加了#version 300 es?这必须是使用 gls es 3.0 功能的第一行(前面没有空行)

您的精度也必须匹配。

您的示例在 Firefox 中适用于我。 Chrome Canary 版本 54.0.2824.0 似乎已损坏(它曾经可以工作)。我相信它很快就会修复。

var vs = `#version 300 es

// NOTE: We need to mark these as mediump to match
// the fragment shader (or of course we could mark
// the fragment shader's uniform block to highp)
//
layout(std140) uniform u_testBlock

    mediump vec4 v0;
    mediump vec4 v1;
;

void main() 
  gl_Position = v0;

`;
var fs = `#version 300 es
precision mediump float;

layout(std140) uniform u_testBlock

    vec4 v0;
    vec4 v1;
;

out vec4 theColor;

void main() 
  theColor = v1;

`;

var gl = document.createElement("canvas").getContext("webgl2");
if (!gl) 
  log ("ERROR: need WebGL 2 support");

var prg = createProgram(gl, [vs, fs]);
log("there should be no errors above");

function log() 
  var pre = document.createElement("pre");
  pre.appendChild(document.createTextNode(Array.prototype.join.call(arguments, " ")));
  document.body.appendChild(pre);


function createShader(gl, type, src) 
  var s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) 
    log("ERROR:", gl.getShaderInfoLog(s));
  
  return s;


function createProgram(gl, shaders) 
  var prg = gl.createProgram();
  gl.attachShader(prg, createShader(gl, gl.VERTEX_SHADER, shaders[0]));
  gl.attachShader(prg, createShader(gl, gl.FRAGMENT_SHADER, shaders[1]));
  gl.linkProgram(prg);
  if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) 
    log("ERROR:", gl.getProgramInfoLog(prg));
  
  return prg;

【讨论】:

不确定这对阅读本文的人是否有用,但 Canary 57.0.2926.0 仍然提供ERROR: Interface blocks with the same name but different fields/layout: u_testBlock 和上面的示例代码。如果我在顶点着色器中指定precision mediump float;(即匹配片段着色器),错误就会消失。 谢谢。是的,这个限制是在我写完上述内容之后的某个时候添加的。固定

以上是关于webGL2统一缓冲区对象和布局的使用(std140)的主要内容,如果未能解决你的问题,请参考以下文章

WebGL2系列之实例数组(Instanced Arrays)

opengl:将数组类型加载到统一缓冲区对象

WebGL2:不完整的帧缓冲区

我应该在统一缓冲区或着色器存储缓冲区对象中使用“vec3”吗?

如何在 webgl2 中使用深度纹理

OpenGL GLSL 统一缓冲区对象