2016-07-16 506 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链接。 –