admin管理员组文章数量:1293159
I noticed that THREE.js uses shaders internally to create core material "e.g. MeshLambertMaterial", So I decided to copy the lambert shader from Three.js code into a new shader and build on it.
This is the code I got (Copied faithfully from Three.js r66)
THREE.MyShader = {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "mon" ],
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
THREE.UniformsLib[ "shadowmap" ],
{
"ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
"emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
}
]),
vertexShader: [
"#define LAMBERT",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
"varying vec3 vLightBack;",
"#endif",
THREE.ShaderChunk[ "map_pars_vertex" ],
THREE.ShaderChunk[ "lightmap_pars_vertex" ],
THREE.ShaderChunk[ "envmap_pars_vertex" ],
THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
THREE.ShaderChunk[ "color_pars_vertex" ],
THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
THREE.ShaderChunk[ "skinning_pars_vertex" ],
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
"void main() {",
THREE.ShaderChunk[ "map_vertex" ],
THREE.ShaderChunk[ "lightmap_vertex" ],
THREE.ShaderChunk[ "color_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
THREE.ShaderChunk[ "skinbase_vertex" ],
THREE.ShaderChunk[ "skinnormal_vertex" ],
THREE.ShaderChunk[ "defaultnormal_vertex" ],
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
THREE.ShaderChunk[ "default_vertex" ],
THREE.ShaderChunk[ "worldpos_vertex" ],
THREE.ShaderChunk[ "envmap_vertex" ],
THREE.ShaderChunk[ "lights_lambert_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ],
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
"varying vec3 vLightBack;",
"#endif",
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "map_pars_fragment" ],
THREE.ShaderChunk[ "lightmap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "specularmap_pars_fragment" ],
"void main() {",
"gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
THREE.ShaderChunk[ "map_fragment" ],
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
"#ifdef DOUBLE_SIDED",
//"float isFront = float( gl_FrontFacing );",
//"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
"if ( gl_FrontFacing )",
"gl_FragColor.xyz *= vLightFront;",
"else",
"gl_FragColor.xyz *= vLightBack;",
"#else",
"gl_FragColor.xyz *= vLightFront;",
"#endif",
THREE.ShaderChunk[ "lightmap_fragment" ],
THREE.ShaderChunk[ "color_fragment" ],
THREE.ShaderChunk[ "envmap_fragment" ],
THREE.ShaderChunk[ "shadowmap_fragment" ],
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
}
and this is the code that I use to setup my uniforms and create the material.
var textureUsed = 'rock_1';
var texture = THREE.ImageUtils.loadTexture( texturePath + textureUsed + "/diffuse.png");
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.x = 128;
texture.repeat.y = 128;
var shaderUniforms = THREE.UniformsUtils.clone( THREE.MyShader.uniforms );
shaderUniforms[ "map" ].value = texture;
var material = new THREE.ShaderMaterial({
name: "TerrainShader",
uniforms : shaderUniforms,
vertexShader: THREE.MyShader.vertexShader,
fragmentShader: THREE.MyShader.fragmentShader,
fog:false,
lights:true
});
The problem is that when I use these parameters to create a MeshLambertMaterial I get the correct lighting and texture repetitions, when I use it to create ShaderMaterial the lights and shadows seem to be working but the texture map isn't loaded, to fix this I dug through the code and managed to get the map to load by adding this ugly "hack" to my code, right after the material definition
material.map = true;
Now the texture is loaded and displayed but it looks like the texture coordinates are messed up, instead of repeating, the Shader seems to be ignoring the repeat values I supplied.
Why did I need that hack to get my texture processed and what can I do to get the correct texture repetitions?
I noticed that THREE.js uses shaders internally to create core material "e.g. MeshLambertMaterial", So I decided to copy the lambert shader from Three.js code into a new shader and build on it.
This is the code I got (Copied faithfully from Three.js r66)
THREE.MyShader = {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "mon" ],
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
THREE.UniformsLib[ "shadowmap" ],
{
"ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
"emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
}
]),
vertexShader: [
"#define LAMBERT",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
"varying vec3 vLightBack;",
"#endif",
THREE.ShaderChunk[ "map_pars_vertex" ],
THREE.ShaderChunk[ "lightmap_pars_vertex" ],
THREE.ShaderChunk[ "envmap_pars_vertex" ],
THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
THREE.ShaderChunk[ "color_pars_vertex" ],
THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
THREE.ShaderChunk[ "skinning_pars_vertex" ],
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
"void main() {",
THREE.ShaderChunk[ "map_vertex" ],
THREE.ShaderChunk[ "lightmap_vertex" ],
THREE.ShaderChunk[ "color_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
THREE.ShaderChunk[ "skinbase_vertex" ],
THREE.ShaderChunk[ "skinnormal_vertex" ],
THREE.ShaderChunk[ "defaultnormal_vertex" ],
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
THREE.ShaderChunk[ "default_vertex" ],
THREE.ShaderChunk[ "worldpos_vertex" ],
THREE.ShaderChunk[ "envmap_vertex" ],
THREE.ShaderChunk[ "lights_lambert_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ],
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
"varying vec3 vLightBack;",
"#endif",
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "map_pars_fragment" ],
THREE.ShaderChunk[ "lightmap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "specularmap_pars_fragment" ],
"void main() {",
"gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
THREE.ShaderChunk[ "map_fragment" ],
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
"#ifdef DOUBLE_SIDED",
//"float isFront = float( gl_FrontFacing );",
//"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
"if ( gl_FrontFacing )",
"gl_FragColor.xyz *= vLightFront;",
"else",
"gl_FragColor.xyz *= vLightBack;",
"#else",
"gl_FragColor.xyz *= vLightFront;",
"#endif",
THREE.ShaderChunk[ "lightmap_fragment" ],
THREE.ShaderChunk[ "color_fragment" ],
THREE.ShaderChunk[ "envmap_fragment" ],
THREE.ShaderChunk[ "shadowmap_fragment" ],
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
}
and this is the code that I use to setup my uniforms and create the material.
var textureUsed = 'rock_1';
var texture = THREE.ImageUtils.loadTexture( texturePath + textureUsed + "/diffuse.png");
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.x = 128;
texture.repeat.y = 128;
var shaderUniforms = THREE.UniformsUtils.clone( THREE.MyShader.uniforms );
shaderUniforms[ "map" ].value = texture;
var material = new THREE.ShaderMaterial({
name: "TerrainShader",
uniforms : shaderUniforms,
vertexShader: THREE.MyShader.vertexShader,
fragmentShader: THREE.MyShader.fragmentShader,
fog:false,
lights:true
});
The problem is that when I use these parameters to create a MeshLambertMaterial I get the correct lighting and texture repetitions, when I use it to create ShaderMaterial the lights and shadows seem to be working but the texture map isn't loaded, to fix this I dug through the code and managed to get the map to load by adding this ugly "hack" to my code, right after the material definition
material.map = true;
Now the texture is loaded and displayed but it looks like the texture coordinates are messed up, instead of repeating, the Shader seems to be ignoring the repeat values I supplied.
Why did I need that hack to get my texture processed and what can I do to get the correct texture repetitions?
Share edited Feb 21, 2014 at 15:11 genpfault 52.2k12 gold badges91 silver badges148 bronze badges asked Feb 21, 2014 at 7:37 Mostafa AbdelraoufMostafa Abdelraouf 6281 gold badge6 silver badges14 bronze badges 6-
3
three.js was designed to be easy to use, not easy to modify. This may change in the future... As a start, try adding
material.defines
like so:var defines = {}; defines[ "USE_MAP" ] = "";
. Specifydefines: defines
in the material constructor, and see if that helps. – WestLangley Commented Feb 21, 2014 at 9:31 - Thanks, Your modification had the same effect as the "materials.map" hack I used. The texture map is loaded but the repetitions weren't – Mostafa Abdelraouf Commented Feb 21, 2014 at 10:01
-
1
shaderUniforms[ "offsetRepeat" ].value.set( 0, 0, 2, 2 );
– WestLangley Commented Feb 21, 2014 at 12:21 - That solved the issue, but I cannot seem to mark it as solved – Mostafa Abdelraouf Commented Feb 21, 2014 at 15:28
- I created an answer for you. – WestLangley Commented Feb 21, 2014 at 16:08
1 Answer
Reset to default 10three.js was designed to be easy to use, not easy to modify. This may change in the future...
You need to set the material.defines
like so:
var defines = {};
defines[ "USE_MAP" ] = "";.
Then specify defines
in the material constructor.
var material = new THREE.ShaderMaterial({
name: "TerrainShader",
defines : defines,
uniforms : shaderUniforms,
vertexShader: THREE.MyShader.vertexShader,
fragmentShader: THREE.MyShader.fragmentShader,
fog:false,
lights:true
});
Regarding the texture repetitions, you need to add the repeat to your uniforms:
shaderUniforms[ "offsetRepeat" ].value.set( 0, 0, 2, 2 );
three.js r.66
本文标签: javascriptReplicating MeshLambertMaterial Using ShaderMaterial ignores texturesStack Overflow
版权声明:本文标题:javascript - Replicating MeshLambertMaterial Using ShaderMaterial ignores textures - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741571084a2386012.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论