2016-07-16 42 views
0

我有一個網格,我使用ShaderMaterial並使用THREE.ShaderLib.phong制服。我已經鏈接了地圖,凹凸&世俗地圖紋理以及它都很好。以下是我的代碼。在ThreeJS中結合THREE.ShaderLib.phong和次表面散射

defines = {}; 
defines[ "USE_MAP" ] = ""; 
defines[ "USE_BUMPMAP" ] = ""; 
defines["USE_SPECULARMAP"] = ""; 

    var uniforms = THREE.UniformsUtils.clone(THREE.ShaderLib.phong.uniforms); 
    uniforms.map.value = THREE.ImageUtils.loadTexture('source/images/texture-pink.jpg'); 
    uniforms.bumpMap.value = THREE.ImageUtils.loadTexture('source/images/texture-pink-bump.jpg'); 
    uniforms.bumpScale.value = 0.02; 
    uniforms.specularMap.value = THREE.ImageUtils.loadTexture('source/images/texture-pink-specular.jpg'); 

    var parameters = { 
     fragmentShader:THREE.ShaderChunk["meshphong_frag"], 
     vertexShader:THREE.ShaderChunk["meshphong_vert"], 
     defines: defines, 
     uniforms: uniforms, 
     lights: true, 
     fog: false, 
     side: THREE.DoubleSide, 
     blending: THREE.NormalBlending, 
     transparent: (uniforms.opacity.value < 1.0), 
     derivatives : true 
    }; 

    material = new THREE.ShaderMaterial(parameters); 

以下是我得到的結果。

enter image description here

我有用於網狀單獨次表面散射的代碼。以下是我的代碼。

<script id="vertexShader" type="x-shader/x-vertex"> 
     varying vec3 v_fragmentPos; 
     varying vec3 v_normal; 

     void main() { 

       vec4 mvPositions = modelViewMatrix * vec4(position, 1.0); 
       v_fragmentPos = (modelMatrix * vec4(position, 1.0)).xyz; 
       v_normal = (modelMatrix * vec4(normal, 0.0)).xyz; 
       gl_Position = projectionMatrix * mvPositions; 
     } 
    </script> 

<script id="fragment_shader" type="x-shader/x-fragment"> 
     varying vec3 v_fragmentPos; 
     varying vec3 v_normal; 
     uniform vec3 u_lightPos; 

     void main() { 

       vec3 _LightColor0 = vec3(1.0,0.5,0.5); 
       float _LightIntensity0 = 2.5; 
       vec3 translucencyColor = vec3(0.8,0.2,0.2); 
       vec3 toLightVector = u_lightPos - v_fragmentPos; 
       float lightDistanceSQ = dot(toLightVector, toLightVector); 
       vec3 lightDir = normalize(toLightVector); 
       float ndotl = max(0.0, dot(v_normal, lightDir)); 
       float inversendotl = step(0.0, dot(v_normal, -lightDir)); 
       vec3 lightColor = _LightColor0.rgb * ndotl/lightDistanceSQ * _LightIntensity0; 
       vec3 subsurfacecolor = translucencyColor.rgb * inversendotl/lightDistanceSQ * _LightIntensity0; 
       vec3 final = subsurfacecolor + lightColor; 
       gl_FragColor=vec4(final,1.0); 
     } 
    </script> 

我在這裏找到的漂亮的基本代碼Shader - Simple SSS lighting issue。和我的材料代碼。

sssUniforms = { 
    u_lightPos: {type: "v3",value: new THREE.Vector3()} 
}; 

var sssMaterial = new THREE.ShaderMaterial({ 
    uniforms: sssUniforms, 
    vertexShader: document.getElementById('vertexShader').textContent, 
    fragmentShader: document.getElementById('fragment_shader').textContent, 
}); 

以下是我用subsurface散射獲得的結果。

enter image description here

現在,我想這兩個結合起來。我嘗試了THREE.UniformsUtils.merge來合併這兩套制服,而且我非常肯定我組合頂點和片段着色器代碼的方式是錯誤的。由於它的字符串我只是複製粘貼在腳本標記中,我不確定這是否是正確的方法。那麼這首先可能嗎?如果是的話,有人可以指導我。我對JavaScript有相當多的知識,並開始獲得三JJ的懸掛,但對於開放GL來說卻沒有什麼知識。

任何幫助表示讚賞。

謝謝。

回答

1

頂點和片段着色器是你跟GPU溝通的方式,並且合併這兩個字符串不會產生任何結果,除非你真的瞭解這個背後的機制。

所以Phong Shading是你在你想要應用的頂點集中讀入specular + diffused + ambient到片段着色器中的方法。

enter image description here [來源:維基]

現在,次表面散射是由你考慮光的相互作用到材料在那裏爲你通常閱讀材料

enter image description here

光的相互作用方式

[出處:Link]

您可以閱讀Chapter-16 Nvidia這解決了您的解決方案的所有數學問題。

我已經爲地下散射創建瞭解決方案,您可以結算表格 Git。這是基於深度圖的SSS。

該代碼靈感來自pixelnerve

總而言之,你試圖合併三個。Phong和Subsurface Scattering相反,你可以爲你的環境擴展相同的示例代碼,寫下你自定義的片段着色器(你可以直接使用這個頂點)。

+0

感謝您的詳細解釋。我已經檢查了pixelnerve erlier中的示例,並且已經使用您的項目來測試片段着色器。我已經達到了可以添加具有次表面散射的正常紋理的程度,但很難設置凹凸和高光貼圖。有什麼可以爲此建議的鏈接? –

+0

@AniketBetkikar啊,我看到你的意思是這樣http://softimage.wiki.softimage.com/xsidocs/mat_sss_shaders_AddingBumpandDisplacementMaps.htm 牛影像與凹凸貼圖相信這是可行的,你可以探索這個或週日嘗試更新相同着色器的git鏈接。 –