three.js ShaderMaterial

2023-02-16 17:45 更新

使用自定義shader渲染的材質。 shader是一個用GLSL編寫的小程序 ,在GPU上運行。 您可能需要使用自定義shader,如果你要:

  • 要實現(xiàn)內置 materials 之外的效果。
  • 將許多對象組合成單個BufferGeometry以提高性能。

使用ShaderMaterial時需要注意以下注意事項:

  • ShaderMaterial 只有使用 WebGLRenderer 才可以繪制正常, 因為 vertexShader 和 fragmentShader 屬性中GLSL代碼必須使用WebGL來編譯并運行在GPU中。
  • 從 THREE r72開始,不再支持在ShaderMaterial中直接分配屬性。 必須使用 BufferGeometry實例,使用BufferAttribute實例來定義自定義屬性。
  • 從 THREE r77開始,WebGLRenderTarget 或 WebGLCubeRenderTarget 實例不再被用作uniforms。 必須使用它們的texture 屬性。
  • 內置attributes和uniforms與代碼一起傳遞到shaders。 如果您不希望WebGLProgram向shader代碼添加任何內容,則可以使用RawShaderMaterial而不是此類。
  • 您可以使用指令#pragma unroll_loop_start,#pragma unroll_loop_end 以便通過shader預處理器在GLSL中展開for循環(huán)。 該指令必須放在循環(huán)的正上方。循環(huán)格式必須與定義的標準相對應。
    • 循環(huán)必須標準化normalized。
    • 循環(huán)變量必須是i。
    • 對于給定的迭代,值 UNROLLED_LOOP_INDEX 將替換為 i 的顯式值,并且可以在預處理器語句中使用。
    • #pragma unroll_loop_start
      for ( int i = 0; i < 10; i ++ ) {
      
      	// ...
      
      }
      #pragma unroll_loop_end

代碼示例

const material = new THREE.ShaderMaterial( {

	uniforms: {

		time: { value: 1.0 },
		resolution: { value: new THREE.Vector2() }

	},

	vertexShader: document.getElementById( 'vertexShader' ).textContent,

	fragmentShader: document.getElementById( 'fragmentShader' ).textContent

} );

例子

webgl / buffergeometry / custom / attributes / particles
webgl / buffergeometry / selective / draw
webgl / custom / attributes
webgl / custom / attributes / lines
webgl / custom / attributes / points
webgl / custom / attributes / points2
webgl / custom / attributes / points3
webgl / depth / texture
webgl / gpgpu / birds
webgl / gpgpu / protoplanet
webgl / gpgpu / water
webgl / interactive / points
webgl / video / kinect
webgl / lights / hemisphere
webgl / marchingcubes
webgl / materials / envmaps
webgl / materials / lightmap
webgl / materials / wireframe
webgl / modifier / tessellation
webgl / postprocessing / dof2
webgl / postprocessing / godrays

頂點著色器和片元著色器(Vertex shaders and fragment shaders)

您可以為每種材質指定兩種不同類型的shaders::

  • 頂點著色器首先運行; 它接收attributes, 計算/操縱每個單獨頂點的位置,并將其他數(shù)據(jù)(varyings)傳遞給片元著色器。
  • 片元(或像素)著色器后運行; 它設置渲染到屏幕的每個單獨的“片元”(像素)的顏色。

shader中有三種類型的變量: uniforms, attributes, 和 varyings:

  • Uniforms是所有頂點都具有相同的值的變量。 比如燈光,霧,和陰影貼圖就是被儲存在uniforms中的數(shù)據(jù)。 uniforms可以通過頂點著色器和片元著色器來訪問。
  • Attributes 與每個頂點關聯(lián)的變量。例如,頂點位置,法線和頂點顏色都是存儲在attributes中的數(shù)據(jù)。attributes 只 可以在頂點著色器中訪問。
  • Varyings 是從頂點著色器傳遞到片元著色器的變量。對于每一個片元,每一個varying的值將是相鄰頂點值的平滑插值。

注意:在shader 內部,uniforms和attributes就像常量;你只能使用JavaScript代碼通過緩沖區(qū)來修改它們的值。

內置attributes 和 uniforms(Built-in attributes and uniforms)

WebGLRenderer默認情況下為shader提供了許多attributes和uniforms; 這些變量定義在shader程序編譯時被自動添加到*片元著色器*和*頂點著色器*代碼的前面,你不需要自己聲明它們。 這些變量的描述請參見WebGLProgram。

這些uniforms或attributes(例如,那些和照明,霧等相關的)要求屬性設置在材質上, 以便 WebGLRenderer來拷貝合適的值到GPU中。 如果你想在自己的shader中使用這些功能,請確保設置這些標志。

如果你不希望WebGLProgram 向你的shader代碼中添加任何東西, 你可以使用RawShaderMaterial 而不是這個類。

自定義 attributes 和 uniforms(Custom attributes and uniforms)

自定義attributes和uniforms必須在GLSL著色器代碼中聲明(在 vertexShader 和/或 fragmentShader 中)。 自定義uniforms必須定義為 ShaderMaterial 的 uniforms 屬性, 而任何自定義attributes必須通過BufferAttribute實例來定義。 注意 varyings 只需要在shader代碼中聲明(而不必在材質中)。

要聲明一個自定義屬性,更多細節(jié)請參考BufferGeometry頁面, 以及 BufferAttribute 頁面關于BufferAttribute 接口。

當創(chuàng)建attributes時,您創(chuàng)建的用來保存屬性數(shù)據(jù)的每個類型化數(shù)組(typed array)必須是您的數(shù)據(jù)類型大小的倍數(shù)。 比如,如果你的屬性是一個THREE.Vector3類型,并且在你的緩存幾何模型BufferGeometry中有3000個頂點, 那么你的類型化數(shù)組的長度必須是3000 * 3,或者9000(一個頂點一個值)。每個數(shù)據(jù)類型的尺寸如下表所示:

GLSL 類型 JavaScript 類型 尺寸
float Number 1
vec2 THREE.Vector2 2
vec3 THREE.Vector3 3
vec3 THREE.Color 3
vec4 THREE.Vector4 4

請注意,屬性緩沖區(qū) 不會 在其值更改時自動刷新。要更新自定義屬性, 需要在模型的BufferAttribute中設置needsUpdate為true。 (查看BufferGeometry了解細節(jié))。

要聲明一個自定義的Uniform,使用uniforms屬性:

uniforms: {
		time: { value: 1.0 },
		resolution: { value: new THREE.Vector2() }
	}

在Object3D.onBeforeRender中,建議根據(jù)object和camera來更新自定義Uniform的值。 因為 Material 可以被meshes,Scene的matrixWorld以及Camera共享, 會在WebGLRenderer.render中更新,并會對擁有私有cameras的scene的渲染造成影響。

構造函數(shù)(Constructor)

ShaderMaterial( parameters : Object )

parameters - (可選)用于定義材質外觀的對象,具有一個或多個屬性。 材質的任何屬性都可以從此處傳入(包括從Material繼承的任何屬性)。

屬性(Properties)

共有屬性請參見其基類Material。

.clipping : Boolean

定義此材質是否支持剪裁; 如果渲染器傳遞clippingPlanes uniform,則為true。默認值為false。

.defaultAttributeValues : Object

當渲染的幾何體不包含這些屬性但材質包含這些屬性時,這些默認值將傳遞給shaders。這可以避免在緩沖區(qū)數(shù)據(jù)丟失時出錯。

this.defaultAttributeValues = {
	'color': [ 1, 1, 1 ],
	'uv': [ 0, 0 ],
	'uv2': [ 0, 0 ]
};

.defines : Object

使用 #define 指令在GLSL代碼為頂點著色器和片段著色器定義自定義常量;每個鍵/值對產生一行定義語句:

defines: {
	FOO: 15,
	BAR: true
}

這將在GLSL代碼中產生如下定義語句:

#define FOO 15
#define BAR true

.extensions : Object

一個有如下屬性的對象:

this.extensions = {
	derivatives: false, // set to use derivatives
	fragDepth: false, // set to use fragment depth values
	drawBuffers: false, // set to use draw buffers
	shaderTextureLOD: false // set to use shader texture LOD
};

.fog : Boolean

定義材質顏色是否受全局霧設置的影響; 如果將fog uniforms傳遞給shader,則為true。默認值為false。

.fragmentShader : String

片元著色器的GLSL代碼。這是shader程序的實際代碼。在上面的例子中, vertexShader 和 fragmentShader 代碼是從DOM(HTML文檔)中獲取的; 它也可以作為一個字符串直接傳遞或者通過AJAX加載。

.glslVersion : String

定義自定義著色器代碼的 GLSL 版本。僅與 WebGL 2 相關,以便定義是否指定 GLSL 3.0。有效值為 THREE.GLSL1 或 THREE.GLSL3。默認為空。

.index0AttributeName : String

如果設置,則調用gl.bindAttribLocation 將通用頂點索引綁定到屬性變量。默認值未定義。

.isShaderMaterial : Boolean

只讀標志,用于檢查給定對象是否屬于 ShaderMaterial 類型。

.lights : Boolean

材質是否受到光照的影響。默認值為 false。如果傳遞與光照相關的uniform數(shù)據(jù)到這個材質,則為true。默認是false。

.linewidth : Float

控制線框寬度。默認值為1。

由于OpenGL Core Profile與大多數(shù)平臺上WebGL渲染器的限制,無論如何設置該值,線寬始終為1。

.flatShading : Boolean

定義材質是否使用平面著色進行渲染。默認值為false。

.uniforms : Object

如下形式的對象:

{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }

指定要傳遞給shader代碼的uniforms;鍵為uniform的名稱,值(value)是如下形式:

{ value: 1.0 }

這里 value 是uniform的值。名稱必須匹配 uniform 的name,和GLSL代碼中的定義一樣。 注意,uniforms逐幀被刷新,所以更新uniform值將立即更新GLSL代碼中的相應值。

.uniformsNeedUpdate : Boolean

可用于在 Object3D.onBeforeRender() 中更改制服時強制進行制服更新。默認為假。

.vertexColors : Boolean

定義是否使用頂點著色。默認為假。

.vertexShader : String

頂點著色器的GLSL代碼。這是shader程序的實際代碼。 在上面的例子中,vertexShader 和 fragmentShader 代碼是從DOM(HTML文檔)中獲取的; 它也可以作為一個字符串直接傳遞或者通過AJAX加載。

.wireframe : Boolean

將幾何體渲染為線框(通過GL_LINES而不是GL_TRIANGLES)。默認值為false(即渲染為平面多邊形)。

.wireframeLinewidth : Float

控制線框寬度。默認值為1。

由于OpenGL Core Profile與大多數(shù)平臺上WebGL渲染器的限制,無論如何設置該值,線寬始終為1。

方法(Methods)

共有方法請參見其基類Material。

.clone () : ShaderMaterial this : ShaderMaterial

創(chuàng)建該材質的一個淺拷貝。需要注意的是,vertexShader和fragmentShader使用引用拷貝; attributes的定義也是如此; 這意味著,克隆的材質將共享相同的編譯WebGLProgram; 但是,uniforms 是 值拷貝,這樣對不同的材質我們可以有不同的uniforms變量。

源碼(Source)

src/materials/ShaderMaterial.js


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號