我想第一次在WebGL場景中實現陰影,據我所知,最直接的方法是使用陰影貼圖,但我找不到解釋這個概念的教程,這不是關於OpenGL,就是包含像three.js這樣的庫。如何在WebGL中實現陰影映射?
但是,我讀過,我必須寫兩對着色器。第一對着色器用於構建陰影貼圖,該貼圖必須存儲在幀緩衝區對象中。然後,我將不得不從幀緩衝區中取出存儲的陰影貼圖,並將其傳遞給第二對着色器,用於繪製場景中的對象。
陰影貼圖必須包含信息,在光線照射到物體之前光源可以從光源傳播的距離,並將該信息傳遞給用於繪製物體的着色器,這將有可能指定哪些部件通過來自光源的光點亮,哪些部件僅通過環境光照亮。
好這麼多的理論,但我不知道該怎樣得到這個工作的想法...
對於實驗,我已經建立了一個非常簡單的場景,呈現由單一的點光源照明兩個領域源,它看起來像這樣:
兩個領域在[0.0, 0.0, 0.0]
和半徑1.0
它們的中心創建的。
較大球體的矩陣由[-2.0, 0.0, -2.0]
翻譯並由[2.0, 2.0, 2.0]
縮放。
較小球體的矩陣由[2.0, 0.0, 2.0]
翻譯並且由[0.5, 0.5, 0.5]
縮放。
點光源的位置是[4.0, 0.0, 4.0]
。
因此,較小的球體現在只是在較大的球體和光源之間,因此在較大的球體表面上應該存在一個不直接點亮的區域。
兩個着色器我用這個場景是這樣的:
頂點着色器
attribute vec4 aPosition;
attribute vec3 aNormal;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
uniform mat3 uNormalMatrix;
varying vec4 vPosition;
varying vec3 vTransformedNormal;
void main () {
vTransformedNormal = uNormalMatrix * aNormal;
vPosition = uModelViewMatrix * aPosition;
gl_Position = uProjectionMatrix * vPosition;
}
片段着色器
precision highp float;
uniform vec3 uLightPosition;
varying vec4 vPosition;
varying vec3 vTransformedNormal;
void main () {
vec3 lightDirection = normalize(uLightPosition - vPosition.xyz);
float diffuseLightWeighting = max(
dot(normalize(vTransformedNormal), lightDirection), 0.0);
vec3 lightWeighting = vec3(0.1, 0.1, 0.1) +
vec3(0.8, 0.8, 0.8) * diffuseLightWeighting;
gl_FragColor = vec4(vec3(1.0, 1.0, 1.0) * lightWeighting, 1.0);
}
所以,第一件事我會現在必須做的是編寫另一對着色器,並且因爲它們不習慣真正的博士在某種程度上,我可以忽略法線的屬性以及法線矩陣的均勻性,也不需要投影矩陣,對嗎?
第二個頂點着色器可以再看看這樣的:
attribute vec4 aPosition;
uniform mat4 uModelViewMatrix;
varying vec4 vPosition;
void main () {
vPosition = uModelViewMatrix * aPosition;
gl_Position = vPosition;
}
有關片段着色器
可是什麼?而且,無論如何,我如何才能找出點光源發出的光線照射到物體的哪個位置?我的意思是,一般需要從全部相關對象一次傳遞頂點位置數據,不是嗎? (雖然在這種特殊情況下,只需要通過較小球體的頂點位置......)
現在,我的問題是,我怎麼從這裏繼續?必須寫入片段着色器,如何保存陰影貼圖,以及如何使用它來計算更大球體上較小球體的陰影?
我擔心我可能需求太多,但如果有人能夠至少讓我指向正確的方向,那將是非常好的。
你好Wacław並非常感謝您的回答!那麼,如果我找到了你的話,我首先要做的第一步就是創建一個'lightMatrix',它應該是一個mat4。因此,在第一遍的頂點着色器中,它看起來像'vPosition = lightMatrix * modelViewMatrix * aPosition',或者我也必須考慮projectionMatrix,比如'vPosition = uProjectionMatrix * lightMatrix * modelViewMatrix * aPosition'?爲了獲得第二遍vec3,我必須通過添加'1'作爲第四個值來使用像glMatrix'vec4.transformMat4'這樣的東西,對吧? – SickBoy
我也很難找到關於深度紋理的東西:MSDN根本沒有描述這個擴展,而MDN只有一個死鏈接。基本語法應該是'depthTexture = gl.getExtension('WEBGL_depth_texture')',對吧?你有什麼鏈接可以看到哪些瀏覽器支持這個功能? _caniuse.com_對WebGL沒有用處,上面提到的網絡也沒有。我記得我已經閱讀過有關將值存儲爲常規紋理的RGBA值的內容,因此可以用作後備?看起來,learnwebgl.com已經離線了...... – SickBoy
......這非常令人傷心,因爲如果我沒有記錯的話,還有關於如何使用frameBuffer對象來製作可用於第二遍。我從來沒有使用過這種技術,因此我對它的工作原理只有一些模糊的想法 - 現在我找不到解釋這一點的文章或教程。但是,對我來說,這是一個很大的問題:如果你想學習純WebGL,很難找到任何文章,文檔和教程!這就像試圖學習JavaScript一樣,你在網上找到的所有東西都只是關於jQuery或Java。 :-( – SickBoy