got the uniforms in e.g
uniforms: {
"time": { type: "f", value: 0.0 }
},
where does e.g.
attribute float customFrequency;
attribute vec3 customColor; go? tia (just added code I am trying to convert)
<script type="x-shader/x-vertex" id="vertexshader">
uniform float time;
attribute float customFrequency;
attribute vec3 customColor;
varying vec3 vColor;
void main()
{
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size;
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
varying vec3 vColor;
void main()
{
gl_FragColor = vec4( vColor, 1.0 );
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
}
</script>
apologies for not formulating the question very well - want to create threejs shader from above script in the form of
THREE.BasicShader = {
uniforms: {},
vertexShader: [
"void main() {",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"void main() {",
"gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );",
"}"
].join("\n")
};
and cannot find an example using vertex attributes. tia
The question is not very clear, but I believe you are a little bit confused on the basic concepts.
Shaders are not supposed to be converted to javascript. They are written in GLSL language which the browser also understands and passes over to the display driver.
Uniforms are the way you pass variables between Javascript code and GLSL shaders. So you only need to care about uniforms on the Javascript side. The other code in the shader scripts are part of the shader GLSL code, can't be shared with or converted to javascript, and if you want to make changes to them, you need to modify the shader itself.
Lee Stemkoski kindly supplied the answer to this:
THREE.BasicShader = {
uniforms: {},
vertexShader: [
"uniform float time;",
"attribute float customFrequency;",
"attribute vec3 customColor;",
"varying vec3 vColor;",
"void main()",
"{",
"vColor = customColor;",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"gl_PointSize = (1.0 + sin( customFrequency * time )) * 8.0 * ( 300.0 / length( mvPosition.xyz ) );",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join("\n"),
fragmentShader:
[
((similar to above))
].join("\n")
};
Related
We were using Three 0.115 version and everything was working. Since we got vulnerability issues for < 0.125, we decided to upgrade to latest version. Then we are getting issues with shader material.
We have an application that uses Point cloud rendered with buffer geometry(positions, sizes and colors bufferattributes) and shadermaterial.
function vertexShader() {
return `attribute float size;
attribute vec3 customColor;
varying vec3 vColor;
attribute float visibility;
varying float vVisible;
void main() {
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;
vVisible = visibility;
}`
}
function fragmentShader() {
return `uniform vec3 color;
uniform sampler2D pointTexture;
varying vec3 vColor;
varying float vVisible;
void main() {
gl_FragColor = vec4( color * vColor, 1.0 );
gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
if ( gl_FragColor.a < ALPHATEST ) discard;
if (vVisible < 0.5) discard;
}`
}
and in our javascript init code.
const material = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xffffff) },
texture: { value: new THREE.TextureLoader().load(circle) },
resolution: { value: new THREE.Vector2() },
},
vertexShader: vertexShader(),
fragmentShader: fragmentShader(),
alphaTest: 0.9,
blending: THREE.AdditiveBlending
});
there is no error in console. But points are not rendered.
we use raycast for detecting points and that works without any issue.
Any idea why after upgrading to latest version of three, rendering of points fails?
is this something to do with shadermaterial?
Thanks for the help :)
I'm very new to shaders. I'm trying to achieve this color and transparent effect:
Example #1 Example#2
This is my result:
my result
This what I have so far:
this.material = new THREE.ShaderMaterial({
extensions: {
derivatives: "#extension GL_OES_standard_derivatives : enable"
},
side: THREE.DoubleSide,
uniforms: {
time: { value: 0 },
resolution: { value: new THREE.Vector4() }
},
transparent: true,
vertexShader: vertex,
fragmentShader: fragment
});
fragmentShader
varying vec2 vUv;
varying float vNoise;
uniform vec2 u_resolution;
void main() {
vec3 color1 = vec3(0.,0.,0.);
vec3 color2 = vec3(1.,1.,1.);
vec3 finalcolor = mix(color1,color2,0.9*(vNoise+1.));
gl_FragColor = vec4( vec3(finalcolor),0.2);
}
How would you go about this?
Thanks!
I guess that it is a bit late for answer, but maybe someone will have same problem. I think you are looking for Fresnel Shader:
Three.js example can be found here:
https://jsfiddle.net/8n36c47p/4/
Here is main shader part:
vertexShader: [
"varying vec3 vPositionW;",
"varying vec3 vNormalW;",
"void main() {",
" vPositionW = vec3( vec4( position, 1.0 ) * modelMatrix);",
" vNormalW = normalize( vec3( vec4( normal, 0.0 ) * modelMatrix ) );",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"varying vec3 vPositionW;",
"varying vec3 vNormalW;",
"void main() {",
" vec3 color = vec3(1., 1., 1.);",
" vec3 viewDirectionW = normalize(cameraPosition - vPositionW);",
" float fresnelTerm = dot(viewDirectionW, vNormalW);",
" fresnelTerm = clamp(1.0 - fresnelTerm, 0., 1.);",
" gl_FragColor = vec4( color * fresnelTerm, 1.);",
"}"
].join( "\n" )
The original post is here https://discourse.threejs.org/t/please-help-me-find-the-error-in-my-shader/2924/7
Seems it is a non trivial work, because the lack of documentation and example in three.js website about this topic.
So far, I can make it render the right picture, and with the kindly help from #Mugen87 , it can cast shadow too, but it still can not receive shadow.
This is the lastest code from above link, I write here so people can see it directly,
var mat = new THREE.ShaderMaterial({
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib.fog,
THREE.UniformsLib.lights,
THREE.UniformsLib.shadowmap,
{
mapMain: {value: null},
mapGlow: {value: null}
}
]),
vertexShader: [
"uniform vec4 offsetRepeat;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vViewPosition;",
"varying vec3 fPosition;",
"varying vec2 vUvM;",
THREE.ShaderChunk.common,
THREE.ShaderChunk.lights_pars_begin,
THREE.ShaderChunk.shadowmap_pars_vertex,
THREE.ShaderChunk.fog_pars_vertex,
// "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"void main(){",
// THREE.ShaderChunk.beginnormal_vertex,
// THREE.ShaderChunk.defaultnormal_vertex,
"vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);",
"vec4 worldPosition = modelMatrix * vec4(position, 1.0);",
"vViewPosition = - mvPosition.xyz;",
"vNormal = normalize( normalMatrix *normal );",
// "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
// "vUvM = uv * offsetRepeat.zw + offsetRepeat.xy;",
"vUv = uv ;",
"vUvM = uv;",
"gl_Position = projectionMatrix * mvPosition;",
// THREE.ShaderChunk.begin_vertex,
// THREE.ShaderChunk.project_vertex,
// THREE.ShaderChunk.worldpos_vertex,
// //THREE.ShaderChunk.logdepthbuf_vertex,
// "fPosition = position;",
THREE.ShaderChunk.shadowmap_vertex,
THREE.ShaderChunk.fog_vertex,
"}"
].join("\n"),
fragmentShader: [
"uniform sampler2D mapMain;",
"uniform sampler2D mapGlow;",
THREE.ShaderChunk.common,
THREE.ShaderChunk.bsdfs,
THREE.ShaderChunk.packing,
THREE.ShaderChunk.shadowmap_pars_fragment,
THREE.ShaderChunk.fog_pars_fragment,
// THREE.ShaderChunk.dithering_pars_fragment,
// THREE.ShaderChunk.emissivemap_pars_fragment,
// // THREE.ShaderChunk.lights_pars,
THREE.ShaderChunk.lights_pars_begin,
THREE.ShaderChunk.lights_pars_maps,
// THREE.ShaderChunk.lights_phong_pars_fragment,
// THREE.ShaderChunk.specularmap_pars_fragment,
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec2 vUvM;",
"varying vec3 vViewPosition;",
"void main(){",
// "vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does
// "vec4 diffuseColor = vec4( diffuse, opacity );",
"vec4 mainColor = texture2D(mapMain, vUv);",
"vec3 glowColor = texture2D(mapGlow, vUvM).rgb;",
"vec3 glow = (1.0 - mainColor.a) * glowColor;",
// THREE.ShaderChunk.specularmap_fragment,
"vec3 normal = normalize( vNormal );",
// "vec3 viewerDirection = normalize( vViewPosition );",
"vec3 viewPosition = normalize( vViewPosition );",
"vec3 totalDiffuseLight = vec3( 0.0 );",
"vec3 totalSpecularLight = vec3( 0.0 );",
// directional lights
"#if NUM_DIR_LIGHTS > 0",
"vec3 dirDiffuse = vec3( 0.0 );",
"vec3 dirSpecular = vec3( 0.0 );",
"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
"vec3 dirVector = directionalLights[ i ].direction;",
"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
// "float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
// "totalSpecularLight += directionalLights[ i ].color * specular * dirSpecularWeight * dirDiffuseWeight;",
"}",
"#endif",
// THREE.ShaderChunk.lights_phong_fragment,
//THREE.ShaderChunk.lights_template,
THREE.ShaderChunk.lights_fragment_begin,
THREE.ShaderChunk.lights_fragment_maps,
THREE.ShaderChunk.lights_fragment_end,
"gl_FragColor = vec4((mainColor.rgb + glow) * totalDiffuseLight, 1.0);",
// THREE.ShaderChunk.shadowmap_fragment,
// THREE.ShaderChunk.tonemapping_fragment,
// THREE.ShaderChunk.encodings_fragment,
// THREE.ShaderChunk.premultiplied_alpha_fragment,
// THREE.ShaderChunk.dithering_fragment,
THREE.ShaderChunk.fog_fragment,
"}"
].join("\n")
});
And the error:
three.js:15911 Uncaught TypeError: Cannot read property 'direction' of
undefined
at StructuredUniform.setValue (three.js:15911)
at StructuredUniform.setValue (three.js:15911)
at Function.WebGLUniforms.upload (three.js:16039)
at setProgram (three.js:23023)
at WebGLRenderer.renderBufferDirect (three.js:21797)
at renderObject (three.js:22556)
at renderObjects (three.js:22526)
at WebGLRenderer.render (three.js:22288)
at GameModel.update (main.js:1632)
at render (main.js:2555)
need to add lighting flags
var mat = new THREE.ShaderMaterial({
uniforms:...,
vertexShader:...,
fragmentShader:...,
lights: true // add this,
fog: true,
transparent: true
});
I'm trying to get a ShaderMaterial with lights working in three.js r77. It works correctly when applied to a mesh with a simple BoxGeometry but it behaves incorrectly when applied to a mesh imported from Blender.
A simple jsfiddle illustrating the problem is here. The mesh on the left is created from a Blender export. The mesh on the right is created from a simple BoxGeometry. Both are using the same ShaderMaterial. The position of the light is indicated by the DirectionalLightHelper.
The mesh on the right is being lit correctly, while the mesh on the left is not. Clearly the problem is in my shader code. I initially assumed that the problem is in the UV map on the imported mesh, but that does not appear to be true. In the jsfiddle example the UV map is copied directly to the BoxGeometry mesh from the imported geometry---they're rotated relative to each other because of the coordinate differences between Blender and three.js, but the lighting is still working correctly on the mesh on the right with the imported UVs.
The shader code is:
THREE.TestShader = {
uniforms: {
"uDirLightPos": {
type: "v3",
value: new THREE.Vector3(20, 20, 20)
},
"uDirLightColor": {
type: "c",
value: new THREE.Color(0xffffff)
},
"uTexture": {
type: "t",
value: null
},
},
vertexShader: [
"varying vec3 vNormal;",
"varying vec3 vViewPosition;",
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"vNormal = normalize(normalMatrix * normal);",
"vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);",
"vViewPosition = -mvPosition.xyz;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"}"
].join("\n"),
fragmentShader: [
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"varying vec2 vUv;",
"varying vec3 vNormal;",
"varying vec3 vViewPosition;",
"varying vec4 mvPosition;",
"uniform sampler2D uTexture;",
"void main() {",
"vec4 lDirection = viewMatrix * vec4(uDirLightPos, 0.0);",
"vec3 lVector = normalize(lDirection.xyz);",
"vec3 normal = normalize(vNormal);",
"float diffuse = dot(normal, lVector);",
"vec4 texel = texture2D( uTexture, vUv );",
"gl_FragColor = vec4(uDirLightColor * diffuse, 1.0) * texel;",
"}"
].join("\n")
};
In addition to a solution to this particular problem, a pointer to better documentation on the three.js shader stuff would be appreciated. The official documentation for ShaderChunk, ShaderLib, and UniformsLib is not what you'd call exhaustive.
Your Blender-exported model has incorrect normals.
vnh1 = new THREE.VertexNormalsHelper( mesh1, 1, 0xff0000, 1 );
scene.add( vnh1 );
fiddle: https://jsfiddle.net/5j0axcgz/1/
three.js r.77
I am currently working on creating a shader in THREE.JS which will act like the normal shader, but using a color as the input to define how it is shaded.
Below is the Code that is causing the problem, and after that is a longer explanation of why I am doing it, and what I think is causing the problem:
fragmentShader: [
"uniform float opacity;",
"varying vec3 vNormal;",
"uniform vec3 color;",
"void main() {",
//THIS IS WHAT I THINK IS SCREWING UP EVERYTHING
//Can I not call normalize with that complex
//of equations within a normalize function?
"gl_FragColor = vec4( normalize(color.r + (vNormal.x*color.r)*.5, color.g + (vNormal.y*color.g)*.5, color.b + (vNormal.z*color.b)*.5), opacity );",
"}"
].join("\n")
A longer description:
I am basically using the same code as the normal shader in the THREE.shaderLib, which is as follows:
'normal': {
uniforms: {
"opacity" : { type: "f", value: 1.0 }
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalize( normalMatrix * normal );",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"varying vec3 vNormal;",
"void main() {",
"gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",
"}"
].join("\n")
},
What I am using is basically this, but with a color aspect added, and it is called within a function that defines a new shader, like so:
function assignNewShader(color){
var colorAssign = new THREE.Color(color)
THREE.ShaderLib[color] = {
uniforms: {
"opacity" : { type: "f", value: 1.0 },
"color" : { type: "c", value: colorAssign },
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalMatrix * normal;",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"varying vec3 vNormal;",
"uniform vec3 color;",
"void main() {",
"gl_FragColor = vec4(color.r + (vNormal.x*color.r)*.5, color.g + (vNormal.y*color.g)*.5, color.b + (vNormal.z*color.b)*.5, opacity );",
"}"
].join("\n")
}
}
You can see that the biggest difference lies within the 'fragmentShader' section, where the vNormal is used to make the gl_FragColor similar (but not exactly the same) as the color that is given in the function.
My problem is this: As a object is 'scaled' this color difference gets more and more drastic, to the point where all of the colors are only as bright as possible. Because of that, I tried to do the following to the 'fragementShader' section of the code:
fragmentShader: [
"uniform float opacity;",
"varying vec3 vNormal;",
"uniform vec3 color;",
"void main() {",
"gl_FragColor = vec4( normalize(color.r + (vNormal.x*color.r)*.5, color.g + (vNormal.y*color.g)*.5, color.b + (vNormal.z*color.b)*.5), opacity );",
"}"
].join("\n")
When I do this, I am greeted with a PLETHORA of errors including:
ERROR: 0:37: 'normalize' : no matching overloaded function found
ERROR: 0:37: 'constructor' : not enough data provided for construction
WebGL: INVALID_VALUE: attachShader: no object or object deleted
Could not initialise shader
VALIDATE_STATUS: false, gl error [1281]
WebGL: INVALID_OPERATION: getUniformLocation: program not linked
I am definitly in over my head getting into the webGL part of THREE, but it seems to me that this mode of altering the fragment shader should work. Does anybody have any ideas as to why it might not?
Normalize takes a vec3 not a vec4.