Three.js Shader改寫

上一篇我們分析了Three.js的材質(zhì)Shader的源碼結(jié)構(gòu),本篇在討論一下官方提供的api onBeforeCompile如何使用。

首先官方描述如下:

.onBeforeCompile ( shader : Shader, renderer : WebGLRenderer ) : undefined

An optional callback that is executed immediately before the shader program is compiled. This function is called with the shader source code as a parameter. Useful for the modification of built-in materials.

Unlike properties, the callback is not supported by .clone(), .copy() and .toJSON().
編譯著色器程序之前立即執(zhí)行的可選回調(diào)。將著色器源代碼作為參數(shù)調(diào)用此函數(shù)。用于修改內(nèi)置材料。
與屬性不同,不支持回調(diào)??寺?、復(fù)制、和toJSON。

其實(shí)就是說,我們shader本來就是以字符串的形式傳進(jìn)去執(zhí)行的,你用這個(gè)onBeforeCompile可以在執(zhí)行之前,修改這個(gè)字符串,以達(dá)到自寫shader的目的。

以下是一個(gè)使用案例:

            depthMaterial = new THREE.MeshDepthMaterial();
            depthMaterial.userData.darkness = { value: state.shadow.darkness };
            depthMaterial.onBeforeCompile = function (shader) {
                shader.uniforms.darkness = depthMaterial.userData.darkness;
                shader.fragmentShader = /* glsl */`
                        uniform float darkness;
                        ${shader.fragmentShader.replace(
                    'gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );',
                    'gl_FragColor = vec4( vec3( 0.0 ), ( 1.0 - fragCoordZ ) * darkness );'
                )}
                `;
            };

首先需要選擇一個(gè)Material,直接修改模型的Material的話需要先log清楚當(dāng)前到底用的是哪個(gè)shader。然后按照上述格式使用.replace("","")和普通的string.replace用法一樣。

下面分步講解一下:

1.首先定義需要傳入的參數(shù)uniform float darkness;
2.定義需要replace的代碼段'gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );',這里很重要,必須要從官方的源碼里復(fù)制出來,空格也不能少
3.編寫需要替換后的代碼段'gl_FragColor = vec4( vec3( 0.0 ), ( 1.0 - fragCoordZ ) * darkness );'
4.從材質(zhì)將數(shù)據(jù)傳到shader中shader.uniforms.darkness = depthMaterial.userData.darkness;
5.從js將數(shù)據(jù)傳輸?shù)組aterial中depthMaterial.userData.darkness = { value: state.shadow.darkness };

用法不是很復(fù)雜,最重要的一點(diǎn)就是如果replace找不到第一個(gè)參數(shù),就會(huì)替換失敗,替換失敗也不會(huì)報(bào)錯(cuò),當(dāng)然了也不會(huì)有效果,可以先寫一段錯(cuò)誤代碼比如缺分號(hào)的,去看看是否replace成功,再修改shader代碼。


另外,能替換的僅僅是fragment$6之類的里面的如下圖藍(lán)色選中部分,而橙色部分output_fragment內(nèi)部的代碼是無法替換的。


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容