I'm having issue sending a texture to a shader. Here is the code i'm using.
uniforms = {
"rightTexture": { type: "t", value: THREE.ImageUtils.loadTexture( "images/doors_right_512.png" ) },
"tDiffuse": { type: "t", value: null },
"aspect": { type: "v2", value: new THREE.Vector2( 512, 512 ) },
};
uniform sampler2D rightTexture;
vec3 sample;
sample = texture2D(rightTexture, vUv).rgb;
gl_FragColor = vec4(vec3(sample), 1.0);
When I'm sampling tDiffuse everything looks fine but if I use rightTexture I just get a black screen. Why is this?
Related
I want to do a sort of "inner glow", where a partially transparent color is more intense towards the outside of a sphere, as the user looks at it.
In plain ol' CSS it would be pretty simple:
.gradient{
height: 500px;
width: 500px;
border-radius: 50%;
box-shadow:0 0 50px 1px inset rgba(0,225,255,0.8);
background: rgba(0,225,255,0.1);
}
<div class="gradient"></div>
This tutorial has this effect, and I have a separate question here about an issue I ran into implementing if anyone else has trouble.
Some custom GL shaders: this is GL code that lives in a string to get compiled later:
const vertexShader = `
uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main()
{
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( c - dot(vNormal, vNormel), p );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
const fragmentShader = `
uniform vec3 glowColor;
varying float intensity;
void main()
{
vec3 glow = glowColor * intensity;
gl_FragColor = vec4( glow, 1.0 );
}`;
This is the material to create the effect. Play with c and p values for intensity/depth of the "gradient".
const customMaterial = new THREE.ShaderMaterial({
uniforms: {
"c": { type: "f", value: 1.5 },
"p": { type: "f", value: 2 },
glowColor: { type: "c", value: new THREE.Color(0x00e1ff) },
viewVector: { type: "v3", value: camera.position }
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.FrontSide,
blending: THREE.AdditiveBlending,
transparent: true
});
You'll want to apply it to your geometry, and scalar your geometry up to the size of "shell" you desire.
const moonGlow = new THREE.Mesh( Orb, customMaterial);
moonGlow.position = moon.position;
moonGlow.scale.multiplyScalar(1.2);
scene.add( moonGlow );
Finally, facing is important. In you're changing up positions, like in an animation loop with motion controls, add this:
customMaterial.uniforms.viewVector.value = camera.position;
We are trying to achieve a glow around a sphere/globe using this code :
var sphereGeom = new THREE.SphereGeometry(3, 40, 40);
var moonTexture = new THREE.TextureLoader().load(
"../../assets/moon-map.png"
);
var moonMaterial = new THREE.MeshPhongMaterial({ map: moonTexture });
var moon = new THREE.Mesh(sphereGeom, moonMaterial);
moon.position.set(0, 0, 0);
this.add(moon);
var customMaterial = new THREE.ShaderMaterial({
uniforms: {
c: { type: "f", value: 0.4 },
p: { type: "f", value: 2.3 },
glowColor: { type: "c", value: new THREE.Color(0xffffff) },
viewVector: { type: "v3", value: new THREE.Vector3(10, 10, 10) }
},
vertexShader: `uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main()
{
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( c - dot(vNormal, vNormel), p );
// intensity = 0;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
fragmentShader: `uniform vec3 glowColor;
varying float intensity;
void main()
{
vec3 glow = glowColor * intensity;
gl_FragColor = vec4( glow, 1.0 );
}`,
side: THREE.BackSide,
blending: THREE.AdditiveBlending,
transparent: true
});
moonGlow = new THREE.Mesh(sphereGeom.clone(), customMaterial.clone());
moonGlow.position.set(moon.position.x, moon.position.y, moon.position.z);
moonGlow.scale.multiplyScalar(1.1);
this.add(moonGlow);
This all looks good and we are getting the desired result. BUT when we are setting the WebGLRenderer’s alpha to true (for getting a gradient in the background body element) then the whole glow is being surrounded by a black border.
Is there some way for getting a gradient color in the background and in the front showing this sphere with glow?
You can apply a texture to scene.background to achieve the desired effect. In this case, it's not necessary to apply alpha = true to WebGLRenderer.
var loader = new THREE.TextureLoader();
var texture = loader.load( 'textures/gradient.jpg' );
scene.background = texture;
Demo: https://jsfiddle.net/f2Lommf5/4946/
I have one problem here)
I decided to use my shader for (scene.overrideMaterial) and I need to somehow get the map texture.
MaterialsShader = {
uniforms: {
time: { type: 'f', value: 0.0 },
},
vertexShader:
"varying vec2 vUv; \n\
void main(){\n\
vUv = uv;\n\
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );\n\
gl_Position = projectionMatrix * mvPosition;\n\
}",
fragmentShader: [
'varying vec2 vUv;',
'uniform float opacity;',
'#ifdef USE_MAP',
'uniform sampler2D map;',
'#endif',
'void main(){',
'vec3 color = vec3(1.0,0.0,0.0) * opacity;',
'#ifdef USE_MAP',
'vec4 mapTexel = texture2D( map, vUv.xy );',
'gl_FragColor = mapTexel;',
'#endif',
//'gl_FragColor.rgb = color;',
'}'].join("\n")
}
But for some reason the texture itself does not exist, I get black material.
var uniforms = THREE.UniformsUtils.clone( MaterialsShader.uniforms );
uniforms = THREE.UniformsUtils.merge( [uniforms, THREE.UniformsLib['common'],THREE.UniformsLib['lights']] );
var material = new THREE.ShaderMaterial({
uniforms : uniforms,
vertexShader : MaterialsShader.vertexShader,
fragmentShader : MaterialsShader.fragmentShader,
});
How can I get a (map) texture?
1) You need to actually define your map uniform...
MaterialsShader = {
uniforms: {
time: { type: 'f', value: 0.0 },
map: { type: 't', value: yourLoadedTexture },
},
2) You need to define USE_MAP in order to enter that code segment of your shader. Either add this to the top of your shader code:
#define USE_MAP true
Or you can set a defines property for your shader:
var material = new THREE.ShaderMaterial({
uniforms : uniforms,
vertexShader : MaterialsShader.vertexShader,
fragmentShader : MaterialsShader.fragmentShader,
map : yourLoadedTexture,
defines : {
USE_MAP: true
}
});
These have the same effect.
I am trying to write a THREE.ShaderMaterial to render a model loaded using THREE.OBJMTLLoader, but I do not understand how to access the vertex colors in the vertex/fragment shader. The result when using my shader (see code below) is a pure white model (due to the default color value I guess).
The result when not using my shader is ok, i.e. model is rendered with correct colors.
I have set shaderMaterial.vertexColors = THREE.VertexColors; and child.material = shaderMaterial; for all childs in the object.
Vertex shader:
varying vec3 vecColor;
void main()
{
vecColor = color;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Fragment shader:
varying vec3 vecColor;
void main()
{
gl_FragColor = vec4(vecColor, 1.0);
}
I finally realized that I was actually replacing materiels generated by OBJMTLLoader with my own material. The solution I found was to extract info from the original child.material and insert it into instances of my shader, organized in in a map:
var materialMap = {};
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
if (child.material.id in materialMap) {
console.log("Using predefined material");
child.material = materialMap[child.material.id];
}
else {
console.log("Creating new material");
materialMap[child.material.id] = new THREE.ShaderMaterial({
uniforms: {
bumpMap: { type: "t", value: texture },
color: { type: "v3", value: new THREE.Vector3( child.material.color.r, child.material.color.g, child.material.color.b ) }
},
vertexShader: vShader,
fragmentShader: fShader
});
child.material = materialMap[child.material.id];
}
}
});
I'm having troubles enabling scene Fog in THREE.ShaderMaterial. Currently the fog only affects other geometries, but the Skydome that is created using THREE.ShaderMaterial, is unaffected by the fog.
There appears to be a boolean fog parameter in ShaderMaterial, which apparently should be set to true to use scene fog. Using it results in uniforms.fogColor is undefined errors however. The error happens at WebGLRenderer function refreshUniformsFog.
Is it a bug or am I using the parameter wrong?
Test case based on webgl_materials_lightmap.html example here: http://jsfiddle.net/HXhb4/
If you set fog to true in line 62 and run the test, you get the errors. What I would like to happen is the skydome to be affected by the fog like a model or skydome created with normal MeshPhongMaterial.
If you want to use fog with your custom ShaderMaterial, you need to be sure to specify the required fog uniforms. For example,
var uniforms = {
topColor: { type: "c", value: new THREE.Color( 0x0077ff ) },
bottomColor: { type: "c", value: new THREE.Color( 0xffffff ) },
offset: { type: "f", value: 33 },
exponent: { type: "f", value: 0.6 },
fogColor: { type: "c", value: scene.fog.color },
fogNear: { type: "f", value: scene.fog.near },
fogFar: { type: "f", value: scene.fog.far }
}
var skyMat = new THREE.ShaderMaterial( {
vertexShader: vertexShader,
fragmentShader: fragmentShader,
uniforms: uniforms,
side: THREE.BackSide,
fog: true
} );
Also specify fogDensity if you decide to use it. You will also have to incorporate the fog logic into your shader.
three.js r.59
In the accepted answer WestLangley mentioned:
You will also have to incorporate the fog logic into your shader.
I figured out how to do that by reading the example NormalDisplacementShader.js. Here are the steps:
Write your shader in an external .js file
Add the UniformsLib
Add the ShaderChunks
In the fragment shader, declare vec3 outgoingLight
Use outgoingLight in your output gl_FragColor
Example below:
THREE.YourCustomShader = {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
{
"someCustomUniform" : { type: 'f', value: 1.0 }
}
] ),
fragmentShader: [
"varying float someCustomVarying;",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
"void main() {",
"vec3 outgoingLight = vec3( 0.0 );",
THREE.ShaderChunk[ "fog_fragment" ],
"gl_FragColor = vec4(outgoingLight, 1.0);",
"}"
].join("\n"),
vertexShader: [
"uniform float someCustomUniform;",
"varying float someCustomVarying;",
"void main() {",
"someCustomVarying = 1.0 * someCustomUniform;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0 );",
"}"
].join("\n")
};