【发布时间】:2017-08-07 09:20:17
【问题描述】:
任何人都可以帮助我解决以下问题,我很困惑,不胜感激。我会尽量简洁。
我有一个简单的 WebGL 页面,它呈现两个对象。我可以通过单击按钮加载一个或另一个着色器程序,以更改这两个对象的渲染方式。但是,我想用第一个着色器程序渲染一个对象,用第二个着色器程序渲染另一个对象。
这是我的绘图函数(每次用户拖动鼠标时调用):
WebGLViewer.prototype.DrawGLScene = function()
{
this.SetupWebGLContextViewport();
this.SetForProgram();
this.Draw3DObjects();
}
因此,调用了三个函数。他们在这里:
首先设置投影和相机:
WebGLViewer.prototype.SetupWebGLContextViewport = function()
{
this.m_WebGLContext.viewport(0, 0, this.m_WebGLContext.viewportWidth, this.m_WebGLContext.viewportHeight);
this.m_WebGLContext.clear(this.m_WebGLContext.COLOR_BUFFER_BIT | this.m_WebGLContext.DEPTH_BUFFER_BIT);
if(this.m_projection == PROJECTION.ORTHOGRAPHIC)
{
mat4.ortho(this.m_orthoXMin, this.m_orthoXMax, this.m_orthoYMin, this.m_orthoYMax, 0.1, 100, this.m_pMatrix);
}
else
{
mat4.perspective(45, this.m_WebGLContext.viewportWidth / this.m_WebGLContext.viewportHeight, 0.1, 100.0, this.m_pMatrix);
}
mat4.identity(this.m_mvMatrix);
this.m_mvMatrix = mat4.lookAt(this.m_eye, this.m_centre, this.m_up);
}
其次,选择要使用的着色器程序(如果只有一个对象,则使用程序 0,否则使用程序 1 - 我通过单击按钮一次添加一个对象) - (我应该添加 m_arrProgramSettingCallbacks 是一个数组设置顶点和片段着色器统一变量值的两个函数):
WebGLViewer.prototype.SetForProgram = function()
{
if(this.m_numObjects.length == 1)
{
this.UseShaderProgram(0,false);
}
else
{
this.UseShaderProgram(1,false);
}
this.m_WebGLContext.uniformMatrix4fv(this.m_shaderProgram.m_pMatrixUniform, false, this.m_pMatrix);
this.m_WebGLContext.uniformMatrix4fv(this.m_shaderProgram.m_mvMatrixUniform, false, this.m_mvMatrix);
var normalMatrix = mat3.create();
mat4.toInverseMat3(this.m_mvMatrix, normalMatrix);
mat3.transpose(normalMatrix);
this.m_WebGLContext.uniformMatrix3fv(this.m_shaderProgram.m_nMatrixUniform, false, normalMatrix);
this.m_WebGLContext.useProgram(this.m_shaderProgram);
var context = this.m_nShaderProgramID == 0 ? this : this.m_callingObject;
this.m_arrProgramSettingCallbacks[this.m_nShaderProgramID].call(context);
}
您可以看到,上面的函数调用了另一个名为 UseShaderProgram 的函数,它简单地将全局变量 m_nShaderProgramID 和 m_shaderProgram 设置如下(我将 false 作为第二个参数传递,因此不会发生重绘):
WebGLViewer.prototype.UseShaderProgram = function(nShaderProgramID, bRedraw)
{
this.EnableVertexAttribArray(nShaderProgramID);
this.m_nShaderProgramID = nShaderProgramID;
this.m_shaderProgram = this.m_arrShaderPrograms[this.m_nShaderProgramID];
if(bRedraw)
{
this.Draw();
}
}
最后,第三个函数渲染场景:
WebGLViewer.prototype.Draw3DObjects = function()
{
this.m_WebGLContext.activeTexture(this.m_WebGLContext.TEXTURE0);
for(var n3DObject = 0; n3DObject < this.m_arrVertexPositionBuffers.length; n3DObject++)
{
this.m_preRenderObjectCallback.call(this.m_callingObject, n3DObject);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexPositionBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_vertexPositionAttribute, this.m_arrVertexPositionBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexNormalBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_vertexNormalAttribute, this.m_arrVertexNormalBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexColourBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_vertexColourAttribute, this.m_arrVertexColourBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexTextureCoordBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_textureCoordAttribute, this.m_arrVertexTextureCoordBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ELEMENT_ARRAY_BUFFER, this.m_arrVertexIndicesBuffers[n3DObject]);
this.m_WebGLContext.drawElements(this.m_WebGLContext.TRIANGLES, this.m_arrVertexIndicesBuffers[n3DObject].numItems, this.m_WebGLContext.UNSIGNED_SHORT, 0);
}
}
因此,我们可以看到,在任何给定的渲染代码运行中,仅使用一个着色器程序,具体取决于是否有一个或两个对象。
这一切都很完美。
希望每个对象使用一个着色器程序,我基本上将 SetForProgram 调用放在 Draw3DObjects 函数中,如下所示:
WebGLViewer.prototype.Draw3DObjects = function()
{
this.m_WebGLContext.activeTexture(this.m_WebGLContext.TEXTURE0);
for(var n3DObject = 0; n3DObject < this.m_arrVertexPositionBuffers.length; n3DObject++)
{
this.UseShaderProgram(n3DObject,false);
this.m_WebGLContext.uniformMatrix4fv(this.m_shaderProgram.m_pMatrixUniform, false, this.m_pMatrix);
this.m_WebGLContext.uniformMatrix4fv(this.m_shaderProgram.m_mvMatrixUniform, false, this.m_mvMatrix);
var normalMatrix = mat3.create();
mat4.toInverseMat3(this.m_mvMatrix, normalMatrix);
mat3.transpose(normalMatrix);
this.m_WebGLContext.uniformMatrix3fv(this.m_shaderProgram.m_nMatrixUniform, false, normalMatrix);
this.m_WebGLContext.useProgram(this.m_shaderProgram);
var context = this.m_nShaderProgramID == 0 ? this : this.m_callingObject;
this.m_arrProgramSettingCallbacks[this.m_nShaderProgramID].call(context);
this.m_preRenderObjectCallback.call(this.m_callingObject, n3DObject);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexPositionBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_vertexPositionAttribute, this.m_arrVertexPositionBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexNormalBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_vertexNormalAttribute, this.m_arrVertexNormalBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexColourBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_vertexColourAttribute, this.m_arrVertexColourBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ARRAY_BUFFER, this.m_arrVertexTextureCoordBuffers[n3DObject]);
this.m_WebGLContext.vertexAttribPointer(this.m_shaderProgram.m_textureCoordAttribute, this.m_arrVertexTextureCoordBuffers[n3DObject].itemSize, this.m_WebGLContext.FLOAT, false, 0, 0);
this.m_WebGLContext.bindBuffer(this.m_WebGLContext.ELEMENT_ARRAY_BUFFER, this.m_arrVertexIndicesBuffers[n3DObject]);
this.m_WebGLContext.drawElements(this.m_WebGLContext.TRIANGLES, this.m_arrVertexIndicesBuffers[n3DObject].numItems, this.m_WebGLContext.UNSIGNED_SHORT, 0);
}
}
当只有一个对象时工作正常,但是当我添加第二个时程序停止响应。
好吧,对不起所有的代码。感谢任何可以建议我在 OpenGL 渲染循环中为每个对象使用 useProgram 函数的人。
米奇。
【问题讨论】: