我想将延迟渲染器和前向渲染器组合在一起.为了共享相同的深度缓冲区,我使用一个带有4个颜色附件的帧缓冲区对象,用于G缓冲区渲染的COLOR_ATTACHMENT0-2,用于延迟着色和前向渲染的COLOR_ATTACHMENT3,这里是pesudo代码:
//**Gbufffer part**
Bind G-Buffer FBO
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
draw the G buffer
//**Lighting part**
Bind Lighting buffer FBO
//**Shading part**
Bind G-Buffer FBO
gl.drawBuffers([gl.COLOR_ATTACHMENT3]);
//**Forward rendring part**
//Still use the G-Buffer FBO and COLOR_ATTACHMENT3
draw forward material
Run Code Online (Sandbox Code Playgroud)
使用这个时,我在firefox中遇到了一个错误:
错误:WebGL:drawBuffers:buffers[i]必须为NONE或COLOR_ATTACHMENTi.
在Chrome浏览器中,我得到了这个:
FrameBufferObject.ts:151的WebGL:INVALID_OPERATION:drawBuffers:COLOR_ATTACHMENTi_EXT或NONE
我的代码出了什么问题?这真让我迷惑...... THX.
目前,使用上传 4096x4096 大纹理texImage2d非常慢,在纹理发送到 GPU 时锁定主线程并最终导致卡顿。
据我所知,WebGL2 能够使用 PBO(像素缓冲区对象)以更有效的方式在 GPU 上创建纹理。但是,我无法在网上找到任何有关如何执行此操作的示例。
我找到了一个关于如何在OpenGL 中实现这一点的很好的描述,但我不确定如何继续使用 WebGL API。
我想使用 aCanvas或 anImageBitmap作为纹理数据的来源。
到目前为止,我正在通过将纹理绘制到画布上进行测试,然后将图像转换为arrayBufferusingcanvas.toBlob()后跟FileReader和readAsArrayBuffer。然后,一旦我真的有一个有效的缓冲区,我就会尝试创建 PBO 并上传它。
我的代码的相关部分如下所示:
var buf = gl.createBuffer();
var view = new Uint8Array(ArrayBuffer);
gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
gl.bufferData(gl.PIXEL_UNPACK_BUFFER, view, gl.STATIC_DRAW);
gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, 0);
Run Code Online (Sandbox Code Playgroud)
但这会返回错误:
GL_INVALID_OPERATION : glTexImage2D: pixel unpack buffer is not large enough
我真的不知道我是否正确地接近它,所以任何帮助将不胜感激。
我正在尝试在 WebGL 2 中进行实例化。我想使用内置变量gl_InstanceID来索引到统一的浮点数组中。
我收到以下错误:
glDrawElementsInstancedANGLE: attempt to draw with all attributes having non-zero divisors
WebGL 2 实例化中唯一允许使用顶点属性的实例化(实例化数组)吗?
另外,规范是了解这些功能的唯一明确的地方吗?
是否有可能在具有多个附件的帧缓冲区上将像素值检索为浮点数?(WebGL 2)
我试过这个:
var framebuffer = _gl.createFramebuffer();
_gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, texture1, 0);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT1, _gl.TEXTURE_2D, texture2, 0);
_gl.drawBuffers([_gl.COLOR_ATTACHMENT0, _gl.COLOR_ATTACHMENT1]);
Run Code Online (Sandbox Code Playgroud)
浮动纹理设置如下:
_gl.texImage2D(_gl.TEXTURE_2D, 0, _gl.RGBA32F, 256, 256, 0, _gl.RGBA, _gl.FLOAT, null);
Run Code Online (Sandbox Code Playgroud)
然后我绑定framebuffer并调用readPixels来获取第一个附件的值:
_gl.readPixels(0, 0, 1, 256, _gl.RGBA, _gl.FLOAT, 0);
Run Code Online (Sandbox Code Playgroud)
没有浮动纹理,这工作但浮动纹理,帧缓冲保持不完整.
WebGL 2规范似乎说这应该有用,但我现在有一些疑问,但似乎_gl.RGBA32F似乎是问题,内部格式为_gl.RGBA,它会产生不兼容的类型错误.
我想知道是否有任何可以利用的 WebGL 异步调用?
我查看了 Spec v1 和 Spec v2,他们没有提及任何内容。在 V2 中,有一个 WebGL 查询机制,我认为这不是我想要的。
在网络上搜索并没有找到任何明确的信息。有这个例子,不清楚同步和异步版本有何不同。http://toji.github.io/shader-perf/
最终,我希望能够异步执行所有这些操作:
有一个 glFinish 操作,它的文档说:“直到所有以前调用的 GL 命令的效果都完成后才返回。”。对我来说,这意味着可以通过调用 Finish() 来等待异步操作?
网络上的一些帖子表明,调用 getError() 也会强制一些同步性,并不是每次调用后都需要做的事情。
我有一个巨大的着色器,需要花费一分钟以上的时间进行编译,从而在整个过程中完全停滞了整个浏览器。据我所知,无法使着色器编译异步,因此可以在等待编译完成时运行其他WebGL命令。
我已经尝试了以下方法:
另一个问题是,有时它会使WebGL(上下文丢失)崩溃,从而使页面(或工作线程)中的所有上下文崩溃。
我有什么办法可以避免浏览器停顿吗?
我可以将着色器拆分为多个部分,然后分别进行编译吗?
这是我的程序初始化的样子,可以以某种方式更改吗?
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
let program = gl.createProgram();
gl.shaderSource(vertexShader, vertexSource);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
let status = gl.getProgramParameter(program, gl.LINK_STATUS);
let programLog = gl.getProgramInfoLog(program);
Run Code Online (Sandbox Code Playgroud)
在调用linkProgram之后等待几分钟,即使在工作者中也无济于事。
最后要注意的一点是:例如,我可以使用不受此影响的OpenGL运行Windows游戏(游戏正在运行,我开始在浏览器中编译此着色器,并且当浏览器停止运行时游戏仍然可以正常运行)
我一直在阅读著名的 webgl 教程https://webgl2fundamentals.org/webgl并学习如何使用bufferData将数据放入缓冲区。本教程bufferData广泛使用这样的形式
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
这里的第二个参数是我们想要发送到 GPU 缓冲区的实际数组或数据。然而,我今天遇到了 API 的这种新用法。
gl.bufferData(gl.ARRAY_BUFFER, 8*maxNumVertices, gl.STATIC_DRAW);
这里第二个参数表示缓冲区的大小。
所以我对此很困惑。我在 MDN https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData上查找了这个 API ,它说
// WebGL1:
void gl.bufferData(target, size, usage);
void gl.bufferData(target, ArrayBuffer? srcData, usage);
void gl.bufferData(target, ArrayBufferView srcData, usage);
// WebGL2:
void gl.bufferData(target, ArrayBufferView srcData, usage, srcOffset, length);
Run Code Online (Sandbox Code Playgroud)
这是否意味着对于 webgl1.0,我们可以将实际的数据数组或缓冲区的大小作为第二个参数传递给 API。但是对于WebGL2.0,我们只能将实际的数据数组传递给API?
对此我还不清楚。请帮忙。
我想检查用户浏览器是否启用和支持 WebGL 2。
有很多关于 WebGL 1 的帖子,但我没有发现与 WebGL 版本 2 相关的内容。
我的片段着色器中有一个制服,当我尝试获取制服位置的值时,它返回 null。
我检查了拼写,没有发现任何拼写错误,并且这个制服也用在着色器代码中。
我的错误是:
getUniformLocation([object WebGLProgram],materialAmbient)中的错误:WebGLProgram(“未命名”)中不存在统一的“materialAmbient”
这是我在 WebGL 中获取统一位置的代码。
let materialAmbientLocation = gl.getUniformLocation(programScene,"materialAmbient");
let materialDiffuseLocation = gl.getUniformLocation(programScene,"materialDiffuse");
let materialSpecularLocation = gl.getUniformLocation(programScene,"materialSpecular");
let shininessLocation = gl.getUniformLocation(programScene, "shininess");
let ambiemtLightLocation = gl.getUniformLocation(programScene, "ambientLight");
let diffuseLightLocation = gl.getUniformLocation(programScene, "diffuseLight");
let specularLightLocation = gl.getUniformLocation(programScene,"specularLight");
Run Code Online (Sandbox Code Playgroud)
我的片段着色器:
我的GLSL
const fsSkybox = `#version 300 es
precision highp float;
in vec3 texPosition;
in vec3 v_normal;
in vec3 f_position;
out vec4 outColor;
// uniform samplerCube u_SkyTexture;
uniform vec3 materialAmbient;
uniform vec3 emission;
uniform vec3 materialDiffuse;
uniform vec3 materialSpecular; …Run Code Online (Sandbox Code Playgroud) 这是一个最小的 WebGL 测试程序,它创建一个具有单个 uint8 值 255 的索引缓冲区。它应该绘制一个大小为 64px 的红色正方形,但事实并非如此(索引值对于绘制来说并不重要)。
不知何故,WebGL 会忽略索引为 255 的元素,尽管它适合无符号字节范围。使用 254 或其他值,红色方块将按预期显示。
这是 WebGL 的错误还是预期的行为?我找不到任何相关信息。
<canvas width="800" height="600"></canvas>
<script>
let canvas = document.querySelector("canvas");
let gl = canvas.getContext("webgl2");
let vert = gl.createShader(gl.VERTEX_SHADER);
let frag = gl.createShader(gl.FRAGMENT_SHADER);
let prog = gl.createProgram();
let index_buf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buf);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([255]), gl.STATIC_DRAW
);
gl.shaderSource(vert, `#version 300 es
void main()
{
gl_Position = vec4(0,0,0,1);
gl_PointSize = 64.0;
}
`);
gl.shaderSource(frag, `#version 300 es
precision highp float;
out vec4 color;
void …Run Code Online (Sandbox Code Playgroud)