我正在使用 webgl 开发一个小游戏。在这个游戏中,我有某种森林,由许多(100 多个)树木对象组成。因为我只有几个不同的树模型,所以在显示它们之前我会以不同的方式旋转和缩放这些模型。
目前我遍历所有树来显示它们:
for (var tree in trees) {
tree.display();
}
Run Code Online (Sandbox Code Playgroud)
而display()树的方法如下所示:
display : function() { // tree
this.treeModel.setRotation(this.rotation);
this.treeModel.setScale(this.scale);
this.treeModel.setPosition(this.position);
this.treeModel.display();
}
Run Code Online (Sandbox Code Playgroud)
许多树对象共享同一个treeModel对象,因此每次显示模型之前我都必须设置模型的旋转/缩放/位置。每棵树的旋转/缩放/位置值都不同。
显示方法treeModel完成所有 gl 的工作:
display : function() { // treeModel
// bind texture
// set uniforms for projection/modelview matrix based on rotation/scale/position
// bind buffers
// drawArrays
}
Run Code Online (Sandbox Code Playgroud)
所有树模型都使用相同的着色器,但可以使用不同的纹理。
因为单个树模型仅由几个三角形组成,所以我想将所有树组合到一个 VBO 中,并通过一次drawArrays()调用显示整个森林。
一些使谈论数字更容易的假设:
我有的问题:
目前我有 5 个字节50 * 3 …
我想用 GLKit 绘制半透明图元。我已经通过禁用深度测试glDisable(GL_DEPTH_TEST)并通过启用混合
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Run Code Online (Sandbox Code Playgroud)
现在,对于较大的 alpha 值(例如 0.9),我需要首先绘制最远的三角形,这样它们就不会出现在较近的三角形上方。glBlendFunc 的文档中也说明了这一点:
透明度最好使用混合函数(GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA)来实现,其中图元从最远到最近排序。请注意,此透明度计算不需要帧缓冲区中存在 alpha 位平面
在应用程序中使用深度缓冲时,您需要注意渲染图元的顺序。需要首先渲染完全不透明的图元,然后按从后到前的顺序渲染部分不透明的图元。如果不按此顺序渲染图元,则通过部分不透明图元可见的图元可能会完全失去深度测试。
但由于视角可以改变(当我改变渲染效果时modelViewMatrix),从远到近的顺序取决于当前的视角。
有没有办法让 OpenGL 以正确的顺序自动渲染我的图元,如果没有,最好的方法是什么?我认为计算 z 位置(取决于当前视角)并为每帧订购几千个三角形(或者更准确地说,每次视角变化时,可以是每帧)的成本太高,特别是当我需要为每一帧将此订单推送到 GPU 时。
请注意,我不关心使用纹理(只是彩色顶点)。
我开始接触 WebGL,我想知道是否有一个学习错误输出的好地方。
我不断收到以下错误
WebGL: INVALID_VALUE: attachShader: no object or object deleted localhost:1
WebGL: INVALID_OPERATION: getAttribLocation: program not linked localhost:1
WebGL: INVALID_OPERATION: getUniformLocation: program not linked localhost:1
WebGL: INVALID_OPERATION: useProgram: program not valid localhost:1
WebGL: INVALID_OPERATION: drawElements: attribs not setup correctly
Run Code Online (Sandbox Code Playgroud)
所以,我从这些错误中可以看出我的着色器无法工作
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
Run Code Online (Sandbox Code Playgroud)
随后的错误与没有程序有关。
所以我的问题是:我如何找出代码中出了什么问题?
该程序没有以某种方式定义,而我确实有var program = gl.createProgram();。那么,为什么会发生这种情况呢?我该往哪里看?我猜测这是因为我的着色器无法编译,但据我所知,我的着色器中出现了 0 个错误或警告。它被前面提到的代码/警告混淆了......此外,chrome 提到了这些警告,而 firefox 没有。但两者都无法初始化着色器
您好,我在使用 VBO 绘图时遇到问题。所以我在这里问了一个问题。我找不到问题的答案。但通过讨论那里给出的一个答案,我现在有了另一个关于 VBO 中的进步的问题。我对它是什么和做什么感到困惑。
在这里 我发现有人回答
如果你将所有顶点数据放在一个数组中(数组:读取为 malloc''ed 指针),将所有法线放在另一个数组中,等等。那么你的步幅为 0。例如,如果顶点、法线等存储如下:
[顶点0][顶点1][顶点2]...
[正常0][正常1][正常2]...
[texcoord0][texcoord1][texcoord2]...
如果你的顶点、法线等是这样包装的:
[顶点0][法线0][纹理坐标0][顶点1][法线1][纹理坐标1][顶点2][法线2][纹理坐标2]...
然后,您应该设置一个非空的步长,它对应于从一个元素切换到下一个元素所需的偏移量。(顺便说一下,这个步幅被计算为字节)
根据该解释,我认为步幅实际上意味着缓冲区中一个顶点的末端与另一个顶点的开始之间的距离。在第一种情况下它是 0,因为所有顶点都是连续存储的。纹理也是如此。但后来我在同一线程中读到了关于步幅定义的另一个答案。
关于 VBO 步幅往往会有些混乱,主要是因为它对 0 的特殊含义。
本文中的“步幅”是指内存中一个值的开头与内存中下一个值的开头之间的距离。它不是一个结尾与下一个开头之间的距离。因此,在作为结构数组的 VBO 中,该结构的每个元素的步长将是整个结构的大小。请记住,结构填充会影响这一点。
这只是与其他答案所说的相反。或者我对第一个答案的意思有误?任何人都可以帮我解决这个问题吗?如果有人能举例给出答案,我将非常感激。我在这个问题的开头给出了我的 VBO 实现的链接,但尚未解决。谢谢。
据我所知,我第一次尝试在三角形上绘制纹理设置正确,但它显示为全黑。
我将图像发送到 OpenGL,如下所示:
GLuint gridTexture;
glGenTextures(1, &gridTexture);
glBindTexture(GL_TEXTURE_2D, gridTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x,
size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
Run Code Online (Sandbox Code Playgroud)
虽然我不确定如何测试“像素”是否符合我的预期,但我确实知道 和size.x变量size.y对于我正在使用的 PNG 正确记录,所以我假设像素也工作良好,因为它们都是在我的资源加载器中一起提取
我的着色器很简单:
attribute vec4 Position;
attribute vec4 SourceColor;
attribute vec2 TextureCoordinate;
varying vec4 DestinationColor;
varying vec2 TextureCoordOut;
uniform mat4 Projection;
uniform mat4 Modelview;
void main(void)
{
DestinationColor = SourceColor;
gl_Position=Projection*Modelview*Position;
TextureCoordOut = TextureCoordinate;
}
Run Code Online (Sandbox Code Playgroud)
分段:
varying lowp vec4 DestinationColor;
varying mediump vec2 TextureCoordOut;
uniform sampler2D Sampler;
void main(void)
{ …Run Code Online (Sandbox Code Playgroud) 我已经阅读了一些 OpenGL-ES 2.0 的教程,我注意到他们为每个 60Hz 帧设置了视口 (glViewport)。
这样做是个好主意还是只是为了简化示例?
如果这样做的话,会有性能损失吗?
目前适用于 iOS,但旨在移植到其他平台。
我一直在浏览OpenGLSL ES 3.0 Spec,但我找不到有关内置函数如何texture(sampler, p)定义 P 的任何内容。我知道它是一个vec2.
它是一个介于 0.0 和 1.0 之间的标准化浮点,定义从左上角到按钮右侧的缩放器吗?
或者是像函数一样从 0 到维度大小减 1 查找纹素texelFetch()?
或者它是否更复杂并且以某种方式在纹理属性中定义?这里它指出“纹理坐标可以标准化或在纹素空间中”。但我对此表示怀疑,因为我没有看到任何地方可以将纹理设置为标准化。
当我将不同的顶点属性配置绑定到 VAO 时,我可以轻松更改 VAO 并渲染不同的内容。但那些不同的东西可能也需要不同的纹理。将纹理绑定到 VAO 是否有意义,这样当您更改 VAO 时,相同的纹理索引会填充不同的数据?
如果我理解正确的话,渲染缓冲区只能用作帧缓冲区的附件,并且不能以任何方式读取或重用。如果是这样,多重采样渲染缓冲区的用例是什么?如果它们没有影响,哪些数据会写入其他 FBO 附件?或者是否可以以某种方式使用它们在主后缓冲区之外获取硬件 MSAA(WebGL2 尚不支持多重采样纹理)?
这里找到一篇文章OpenGL ES vs Vulkan,谁是性能之王?提到:
“OpenGL ES 3.1 的问题在于,虽然图形看起来比 OpenGL ES 2.0 好得多,但性能受到的影响非常大,以至于游戏基本上无法玩,查看上面在我的 Nexus 6P 上比较 OpenGL ES 2.0 和 3.1 的图像可以看出,与 OpenGL ES 2.0 相比,完全相同的场景以每秒三分之一的帧速度运行。这就是 Vulkan 的用武之地,它提供至少相同的图形质量,但性能有所提高。那么 Vulkan 表现如何呢?
我无法想象相同场景下 3.1 会比 2.0 慢。作者是不是把图搞错了?看来右图有 GI。