簡體   English   中英

使用three.js將PointLight信息傳遞到自定義着色器

[英]Passing PointLight Info to a custom Shader with three.js

我想創建一種類似於Aerotwist教程中所述的起伏球體的效果。 但是,在教程中,Paul在片段着色器中創建了一個偽造的GLSL硬編碼光源-相反,我想將信息從Three.js PointLight實例傳遞給我的着色器,操縱頂點/法線,然后執行Phong着色。

我對在three.js中的場景進行着色時對GPU考慮的各個級別的理解如下(例如,堅持使用Phong):

  1. 無需考慮GPU:使用MeshPhongMaterial ,不必擔心着色器。 這非常簡單,但不會讓您在GPU方面亂七八糟。
  2. 一些GPU注意事項:使用ShaderLib Phong着色器。 這允許您將陰影計算推入GPU,但是由於它們是預先編寫的,因此您無法對頂點位置,法線或照明計算進行任何自定義修改。
  3. 全面的GPU管理:使用ShaderMesh並從頭開始編寫着色器。 這為您提供了完全的自定義功能,但也迫使您顯式傳遞着色器所需的屬性和制服。

問題1:以上理解是否正確?

問題2:是否有辦法在2級和3級之間做某事? 我希望能夠自定義着色器以使頂點位置/法線混亂,但是當three.js包含一個非常好的着色器時,我不想編寫自己的Phong着色器。

問題3:如果在第2級和第3級之間沒有中間立場,而我只需要進入第3級,那么實現這一目標的最佳方法是什么? 我是否要以均勻的形式傳遞燈光的位置,強度等,是否進行頂點/法線修改,然后最后明確編寫Phong陰影計算?

使用three.js來完成您的要求非常簡單

我不確定它在您的Q []中的位置

Q1

  1. 您仍在使用着色器,其他人為您編寫了它們。 您只能訪問該界面。 在幕后,調用諸如MeshBasicMaterial之類的東西實際上可以根據您輸入的內容編譯不同的着色器。 就像,如果沒有調用等圖,它可能不會處理任何UVS並且不將它們包括在着色器中。根據調用的內容,您仍然可以影響GPU。
  2. 如果您指的是着色器塊,則可以在此處修改內容,但這非常麻煩。 我的建議是研究代碼,例如phong陰影,並開始使用塊逐步構建自己的代碼。 看進去什么,出什么。
  3. 無需傳遞屬性。 三.ShaderMaterial並非完全從頭開始構建。 它仍然為您提供了很多東西,並且具有許多可以設置以獲取更多信息的屬性。 一個的基本屬性是為您設置的。 您不聲明“屬性vec3位置”。 如果按West所示勾選照明標志,則可以得到包含場景中所有照明的數組,但是例如,如果您正在構建粒子着色器或某些屏幕效果,則可以忽略此數組。 幾乎每個着色器都設置為讀取一些基本屬性,例如“位置”,“ uv”,“正常”。 您可以輕松地在過程網格上添加您自己的對象,但是在實際模型上並不簡單。 默認情況下,您會獲得一些制服,您將獲得整套MVP矩陣,“ cameraPosition”等。從那里編寫phong着色器很簡單。

現在,您將如何執行此操作。 假設您正在遵循本教程,並且擁有此着色器:

// same name and type as VS
varying vec3 vNormal;

void main() {


//this is hardcoded you want to pass it from your environment
vec3 light = vec3(0.5, 0.2, 1.0);//it needs to be a uniform

// ensure it's normalized
light = normalize(light);//you can normalize it outside of the shader, since it's a directional light

// calculate the dot product of
// the light to the vertex normal
float dProd = max(0.0,
                dot(vNormal, light));

// feed into our frag colour
gl_FragColor = vec4(dProd, // R
                  dProd, // G
                  dProd, // B
                  1.0);  // A

}

這是您需要做的:

GLSL

uniform vec3 myLightPos;//comes in
void main(){
    vec3 light = normalize(myLightPos);//but you better do this in javascript and just pass the normalized vec3
}

Java腳本

new THREE.ShaderMaterial({
   uniforms:{
      myLightPos:{
         type:"v3",
         value: new THREE.Vector3()
      }
   },
   vertexShader: yourVertShader,
   fragmentShader: yourFragmentShader

});

問題1:正確。 雖然,此板上的某些用戶已發布了駭MeshPhongMaterial的變通辦法,但這並不是其初衷。

Q2和Q3:查看ShaderLib.js ,您將看到“法線貼圖着色器”。 這是您的理想模板。 是的,您可以復制/重命名並根據自己的喜好對其進行修改。

它使用基於Phong的照明模型,甚至可以為您訪問場景燈。 您這樣稱呼它:

var shader = THREE.ShaderLib[ "normalmap" ];

var uniforms = THREE.UniformsUtils.clone( shader.uniforms );

. . .

var parameters = {
    fragmentShader: shader.fragmentShader,
    vertexShader: shader.vertexShader,
    uniforms: uniforms,
    lights: true // set this flag and you have access to scene lights
};

var material = new THREE.ShaderMaterial( parameters );

請參閱以下示例: http : //threejs.org/examples/webgl_materials_normalmap.htmlhttp://threejs.org/examples/webgl_materials_normalmap2.html

有關要遵循的編碼模式,請參見ShaderLib.jsShaderChunk.js

three.js r.67

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM