任何人都可能幫助我以下,我很困難,並會感謝任何建議。我會盡量保持簡潔。如何在WebGL渲染函數中加載多個着色器程序
我有一個簡單的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 - I添加對象的一個在一個按鈕點擊時間) - (I要補充的是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);
}
可以看到的是,上述的函數調用另一個稱爲UseS的函數haderProgram這只是設置全局變量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函數的人。
米奇。
非常感謝你。你徹底的回答讓我想起了我的一些電話的順序,過了一段時間,我看到了錯誤,現在一切正常。感謝您抽出時間,非常感謝。米奇, – user3738290