- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
借助 WebGL 2,我们现在可以使用统一缓冲区对象。
它们看起来是个好主意,不必将通用制服附加到每个单独的程序(例如每个正在渲染的对象都通用的投影和 View 矩阵)。
我创建了一个辅助类,每次我想绑定(bind)一个统一的缓冲区对象时都会调用它。
class UniformBuffer {
constructor(gl, data, boundLocation = 0) {
this.boundLocation = boundLocation;
this.data = new Float32Array(data);
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferData(gl.UNIFORM_BUFFER, this.data, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
update(gl, data, offset = 0) {
this.data.set(data, offset);
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferSubData(gl.UNIFORM_BUFFER, 0, this.data, 0, null);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
};
是否像这样创建统一缓冲区的想法
const perScene = new UniformBuffer(gl, [
...vec4.create(),
...vec4.create(),
], 0); // and bind it to bind location 0?
const perObject = new UniformBuffer(gl, [
...vec4.create(),
], 1); // and bind it to bind location 1?
在我的渲染循环中,然后我通过调用更新“perScene”制服
perScene.update(gl, [
...vec4.fromValues(1, 0, 0, 1),
], 4); // giving an offset to update only the 2nd color.
然后我将查看场景中的所有对象,我的想法是像这样更新 perObject 统一缓冲区
for (let i = 0; i < objects.length; i++) {
perObject.update(gl, [
...vec4.fromValues(0, 0, 1, 1),
]);
}
我在谈论 vec4
只是为了使示例更简单,但其想法是在 perScene 上拥有矩阵(投影和 View ),在 perObject 上拥有(对象和法线矩阵)。
在我的着色器中,我将它们声明为
uniform perScene {
vec4 color1;
vec4 color2;
};
uniform perModel {
vec4 color3;
};
我在这里有一个工作片段
class UniformBuffer {
constructor(gl, data, boundLocation = 0) {
this.boundLocation = boundLocation;
this.data = new Float32Array(data);
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferData(gl.UNIFORM_BUFFER, this.data, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
update(gl, data, offset = 0) {
this.data.set(data, offset);
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferSubData(gl.UNIFORM_BUFFER, 0, this.data, 0, null);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
};
const vertex = `#version 300 es
uniform perScene {
vec4 color1;
vec4 color2;
};
uniform perModel {
vec4 color3;
};
in vec3 a_position;
out vec3 v_color;
void main() {
gl_Position = vec4(a_position, 1.0);
v_color = color1.rgb + color2.rgb; // WORKS
// v_color = color1.rgb + color2.rgb + color3.rgb; // DOESNT WORK
}
`;
const fragment = `#version 300 es
precision highp float;
precision highp int;
in vec3 v_color;
out vec4 outColor;
void main() {
outColor = vec4(v_color, 1.0);
}
`;
const geometry = {
positions: [-0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0],
indices: [0, 2, 1, 1, 2, 3],
};
const renderList = [];
// STEP 1 (create canvas)
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl2");
if (!gl) {
console.log('no webgl2 buddy');
}
// STEP 2 (create program)
const v = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(v, vertex);
gl.compileShader(v);
const f = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(f, fragment);
gl.compileShader(f);
const program = gl.createProgram();
gl.attachShader(program, v);
gl.attachShader(program, f);
gl.linkProgram(program);
// STEP 3 (create VAO)
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
const colorUniformLocation = gl.getUniformLocation(program, 'color');
const positionsBuffer = gl.createBuffer();
const indicesBuffer = gl.createBuffer();
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
// position & indices
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionsBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geometry.positions), gl.STATIC_DRAW);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(geometry.indices), gl.STATIC_DRAW);
// STEP 4 (create UBO)
// bound to location 0
const perScene = new UniformBuffer(gl, [
...vec4.create(), // color 1
...vec4.create(), // color 2
], 0);
// bound to location 1 ?
const perModel = new UniformBuffer(gl, [
...vec4.create(), // color 3
], 3);
// STEP 5 (add instances)
for (let i = 0; i < 1; i++) {
renderList.push({
id: i,
vao: vao,
program: program,
color: [0, 1, 1],
});
}
// STEP 6 (draw)
gl.clearColor(0, 0, 0, 0);
gl.enable(gl.DEPTH_TEST);
gl.viewport(0, 0, canvas.width, canvas.height);
perScene.update(gl, [
...vec4.fromValues(1, 0, 0, 1),
...vec4.fromValues(0, 1, 0, 1),
]);
for (let i = 0; i < renderList.length; i++) {
const current = renderList[i];
gl.useProgram(current.program);
gl.bindVertexArray(current.vao);
// update perObject
perModel.update(gl, [
...vec4.fromValues(0, 0, 1, 1),
]);
gl.drawElements(gl.TRIANGLES, geometry.indices.length, gl.UNSIGNED_SHORT, 0);
// unbind
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
console.log('compiled!');
canvas {
background-color: black;
}
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
我不应该看到一个白色方 block ,因为所有颜色加起来会产生 vec4(1.0, 1.0, 1.0, 1.0)
? (jsfiddle 第 41 行)
我做错了什么?谢谢
最佳答案
所以,你做错的第一件事是你没有调用 gl.getUniformBlockIndex
。就像制服一样,您必须查询位置,或者在这种情况下查询每个 block 的索引。
第二件事是 block 统一是间接的一级,你需要调用 gl.uniformBlockBinding(program, uniformBlockIndex, uniformBufferIndex)
;
uniformBlockIndex
是您从 gl.getUniformBlockIndex
获得的索引。 uniformBufferIndex
类似于一个纹理单元。有 N 个统一缓冲区索引。您可以选择从 0
到 MAX_UNIFORM_BUFFER_BINDINGS - 1
的任何缓冲区索引。
如果您有一个程序使用 block A、B 和另一个使用 A 和 C 的程序,则此间接会有所帮助。在这种情况下, block A 可能在 2 个程序中具有不同的索引,但您让它从同一个 uniformBufferIndex 中提取其值.
请注意,此状态是每个程序状态,因此如果您计划始终为同一个统一 block 使用相同的统一缓冲区索引,则可以在初始化时设置它。
更详细地说明它。你有一个着色器程序。它有状态
var someProgram = {
uniforms: {
projectionMatrix: [1, 0, 0, 0, 0, ... ], // etc
},
uniformBlockIndcies[ // one per uniform block
0,
0,
0,
],
...
}
接下来你有统一的缓冲区索引,它们是全局状态
glState = {
textureUnits: [ ... ],
uniformBuffers: [ null, null, null ..., ],
};
您告诉程序对于每个统一缓冲区 block ,使用 gl.uniformBlockBinding
使用哪个统一缓冲区索引。然后使用 gl.bindBufferBase
或 gl.bindBufferRange
将缓冲区绑定(bind)到该索引。
这非常类似于告诉程序使用哪个纹理单元,然后将纹理绑定(bind)到该单元。当你这样做时,在初始化时间或渲染时间真的取决于你。在我看来,我似乎更有可能在初始化时决定我的 perScene 东西总是在缓冲区索引 0 和 perModel 东西在索引 1 上,因此我可以设置它们的程序部分(调用 gl.uniformBlockBinding
) 在初始化时。
class UniformBuffer {
constructor(gl, data, boundLocation = 0) {
this.boundLocation = boundLocation;
this.data = new Float32Array(data);
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferData(gl.UNIFORM_BUFFER, this.data, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
update(gl, data, offset = 0) {
this.data.set(data, offset);
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferSubData(gl.UNIFORM_BUFFER, 0, this.data, 0, null);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
};
const vertex = `#version 300 es
uniform perScene {
vec4 color1;
vec4 color2;
};
uniform perModel {
vec4 color3;
};
in vec3 a_position;
out vec3 v_color;
void main() {
gl_Position = vec4(a_position, 1.0);
v_color = color1.rgb + color2.rgb + color3.rgb;
}
`;
const fragment = `#version 300 es
precision highp float;
precision highp int;
in vec3 v_color;
out vec4 outColor;
void main() {
outColor = vec4(v_color, 1.0);
}
`;
const geometry = {
positions: [-0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0],
indices: [0, 2, 1, 1, 2, 3],
};
const renderList = [];
// STEP 1 (create canvas)
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl2");
if (!gl) {
console.log('no webgl2 buddy');
}
// STEP 2 (create program)
const v = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(v, vertex);
gl.compileShader(v);
const f = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(f, fragment);
gl.compileShader(f);
const program = gl.createProgram();
gl.attachShader(program, v);
gl.attachShader(program, f);
gl.linkProgram(program);
// STEP 3 (create VAO)
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
const colorUniformLocation = gl.getUniformLocation(program, 'color');
const positionsBuffer = gl.createBuffer();
const indicesBuffer = gl.createBuffer();
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
// position & indices
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionsBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geometry.positions), gl.STATIC_DRAW);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(geometry.indices), gl.STATIC_DRAW);
// STEP 4 (create UBO)
// bound to location 0
const perScene = new UniformBuffer(gl, [
...vec4.create(), // color 1
...vec4.create(), // color 2
], 0);
// bound to location 1 ?
const perModel = new UniformBuffer(gl, [
...vec4.create(), // color 3
], 1);
gl.uniformBlockBinding(program, gl.getUniformBlockIndex(program, "perScene"), perScene.boundLocation);
gl.uniformBlockBinding(program, gl.getUniformBlockIndex(program, "perModel"), perModel.boundLocation);
// STEP 5 (add instances)
for (let i = 0; i < 1; i++) {
renderList.push({
id: i,
vao: vao,
program: program,
color: [0, 1, 1],
});
}
// STEP 6 (draw)
gl.clearColor(0, 0, 0, 0);
gl.enable(gl.DEPTH_TEST);
gl.viewport(0, 0, canvas.width, canvas.height);
perScene.update(gl, [
...vec4.fromValues(1, 0, 0, 1),
...vec4.fromValues(0, 1, 0, 1),
]);
for (let i = 0; i < renderList.length; i++) {
const current = renderList[i];
gl.useProgram(current.program);
gl.bindVertexArray(current.vao);
// update perObject
perModel.update(gl, [
...vec4.fromValues(0, 0, 1, 1),
]);
gl.drawElements(gl.TRIANGLES, geometry.indices.length, gl.UNSIGNED_SHORT, 0);
// unbind
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
console.log('compiled!');
canvas {
background-color: black;
}
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
在 this example有5个统一的 block 。
projection
和 view
和 viewProjection
world
和 worldInverseTransform
lightPosition
和 lightColor
。 我并不是说这是完美的设置。我真的不知道。但是制作一种称为“ Material ”的东西并在多个模型之间共享该 Material 是很常见的,所以这就像一个不同于 perModel
block 的 perMaterial
block 。共享照明信息也很常见。我不知道理想的设置是什么,只是指出 perScene
和 perModel
对于相当常见的情况可能还不够。
另一件事,这条线
// unbind
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
没有意义。 ELEMENT_ARRAY_BUFFER
是 VAO 状态的一部分。
关于glsl - 绑定(bind)多个统一缓冲区对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44629165/
这个问题在这里已经有了答案: Possible to make an event handler wait until async / Promise-based code is done? (2
我经常有多个运行的进程(R,Python,eshell/shell),对于每个进程,我经常都有一个相关的脚本,可以从中发送摘要。为此,我通常将每个框架垂直地分成两个窗口,以便脚本文件(例如.py)位于
如何修改 emacs 在关闭缓冲区后选择要显示的缓冲区的方式? 当我有多个列显示相同的缓冲区,然后在其中一个缓冲区中打开另一个文件,然后关闭新打开的缓冲区时,它不会切换回前一个缓冲区,而是切换到另一个
如何将 ex 命令复制到剪贴板或粘贴到缓冲区? 在 Windows 上使用 gvim。 最佳答案 windows剪贴板可以通过the buffer + 访问.因此,可以使用 + 将剪贴板粘贴为前命令。
在 javascript 中如何以比以下更简单的方式获取 b 缓冲区? var num=6553599 var a = new Buffer(4); a.writeInt32LE(num)
每次我在 Google 上搜索有关 OpenGL 编程的文章时,我都会找到一些文章,但似乎所有文章都提到了着色器和缓冲区。那些是什么?你能解释其中的一些吗: 深度缓冲区 模板缓冲区 像素着色器 帧缓冲
我有java考试,当我学习时,我看到了这个练习,我尝试解决它,但我发现一些困难,所以请帮助我考虑实用程序中方法的以下注释、 header 和部分代码名为 Atbash 的加密类。 /**
每次我在 Google 上搜索有关 OpenGL 编程的文章时,我都会找到一些文章,但似乎所有文章都提到了着色器和缓冲区。那些是什么?你能解释其中的一些吗: 深度缓冲区 模板缓冲区 像素着色器 帧缓冲
对于每个属性使用跨步顶点缓冲区与紧密打包缓冲区有何优缺点?我的意思是例如: 步幅:xyzrgb xyzrgb xyzrgb 紧:xyzxyzxyz rgbrgbrgb 乍一看,使用步幅时您似乎可以轻松
我正在尝试将文本文件中每行的数字读取到 ArrayList 中。当我执行以下函数时,它总是跳过最后一个元素。有人可以帮我吗?因为我在这里没有遇到问题,因为它读取直到缓冲区为空,所以他应该在到达 Fil
#include #include int main () { time_t time_raw_format; struct tm * ptr_time; char *buff
基本上我有一个包含不同类型数据的自定义结构。例如: typedef struct example_structure{ uint8_t* example_1[4]; int example_2[4];
我之前的列表实现是一个简单的 LinearLayout,位于一个装满我的项目的 ScrollView 中。 我切换到 ListView 的 Android 实现以简单地使用 CursorAdapter
我想创建一个可变长度的输入事件窗口/缓冲区,当它接收到额外的事件时会变长。 这是为了实现“键入时搜索”功能。我想捕获点击,但为了不给服务器造成压力,我想明智地进行服务调用。 我想到的逻辑是缓冲击键,从
我想将 yuv420P 像素写入缓冲区而不是二进制文件。假设我在指针中存储了 luma 、 Cb 和 Cr。 luma = output_pixel.luma; cb = output_pixel.c
我想在 Go 中构建一个支持多个并发读取器和一个写入器的缓冲区。所有写入缓冲区的内容都应由所有读者读取。允许新读者随时加入,这意味着已经写入的数据必须能够为迟到的读者回放。 缓冲区应满足以下接口(in
本文转载自微信公众号「小明菜市场」,作者小明菜市场。转载本文请联系小明菜市场公众号。 前言 Java NIO 需要理解的主要有缓冲区,通道,选择器,这三个主要的部分。 基础
一 点睛 NIO,可以称为 New IO 或 Non Blocking IO,是在 JDK 1.4 后提供的新 API。传统的I/O 是阻塞式的 I/O、面向流的操作;而 NIO 是非阻塞 I/O 、
我正在寻找一种切换到包含搜索文本的缓冲区的方法。 例如。如果我打开了 100 个缓冲区,我想切换到一个包含 'fooBar = 1' 的缓冲区 最佳答案 我写了一个 Vim 插件来做到这一点:buff
我正在尝试将提取的视频帧(我使用 ffmpeg)推送到 FFMPEG 缓冲区中。我已经查看了 ffmpeg 的缓冲区源文件,例如 buffersrc.c 和 fifo.c,以确定我是否可以这样做,但我
我是一名优秀的程序员,十分优秀!