Implementing 3D Shaders
I've been experimenting with the three.js library and shaders in the past weeks and I'm stuck with the shader implementation on my model. I found this interesting example at pixhaders.com that I want to implement on a 3D model.
http://pixelshaders.com/examples/noise.html
This is the last example at the bottom of the page and Im trying to implement.
I am trying to add it to a 3D model which can be found at the link below:
http://martinr.nl/lab/Speeltuin/webgl_shader2.html
Hardly when I add the example code the 3D model disappears. This makes debugging and error detection difficult.
This is the shader code that works, but not with the correct shader:
<script id="fragmentShader" type="x-shader/x-fragment">
varying vec2 vUv;
uniform float time;
uniform vec2 resolution;
precision mediump float;
void main( void ) {
vec2 position = 2.0 + 2.0 * vUv;
float red = abs( sin( position.x / position.y + time / 5.0 ) );
float green = abs( sin( position.x / position.y + time / 4.0 ) );
float blue = abs( sin( position.x / position.y + time / 3.0 ) );
gl_FragColor = vec4( red, green, blue, 1.0 );
}
</script>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main()
{
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
</script>
When I try to implement the shader of the above example, the 3D model disappears.
Does anyone know how to implement the pixelshader.com example shader on the model in my example?
Or does anyone have any hints that I could try to get it to work?
source to share
I replaced your fragment shader with code from pixhaders.com. The console reported the following error:
> THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false
> gl.getPRogramInfoLog Varyings with the same name but different type,
> or statically used varyings in fragment shader are not declared in
> vertex shader: position
Variable is essentially the interface between the vertex shader and the fragment shader. This error tells us what is position
declared in the fragment shader, but not in the vertex shader.
You did have the required variable in your vertex shader ... other than the fact that it was named vUv
. All I had to do was make the variable names consistent.
Full source (I did scaling with help time
in function render()
):
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - materials - shaders [custom]</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #ffffff;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #050505;
margin: 0px;
overflow: hidden;
}
a {
color: #ffffff;
}
#oldie a { color:#da0 }
</style>
</head>
<body>
<div id="container"></div>
<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - shader material demo. featuring <a href="http://www.pouet.net/prod.php?which=52761" target="_blank">Monjori by Mic</a></div>
<link rel="stylesheet" href="css/skeleton.css">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/codemirror.css">
<script src="js/lib/three.min.js"></script>
<script src="js/lib/Detector.js"></script>
<script src="js/geo.js"></script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vUv;
uniform float time;
float random(float p) {
return fract(sin(p)*10000.);
}
float noise(vec2 p) {
return random(p.x + p.y*10000.);
}
vec2 sw(vec2 p) {return vec2( floor(p.x) , floor(p.y) );}
vec2 se(vec2 p) {return vec2( ceil(p.x) , floor(p.y) );}
vec2 nw(vec2 p) {return vec2( floor(p.x) , ceil(p.y) );}
vec2 ne(vec2 p) {return vec2( ceil(p.x) , ceil(p.y) );}
float smoothNoise(vec2 p) {
vec2 inter = smoothstep(0., 1., fract(p));
float s = mix(noise(sw(p)), noise(se(p)), inter.x);
float n = mix(noise(nw(p)), noise(ne(p)), inter.x);
return mix(s, n, inter.y);
return noise(nw(p));
}
float movingNoise(vec2 p) {
float total = 0.0;
total += smoothNoise(p - time);
total += smoothNoise(p*2. + time) / 2.;
total += smoothNoise(p*4. - time) / 4.;
total += smoothNoise(p*8. + time) / 8.;
total += smoothNoise(p*16. - time) / 16.;
total /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
return total;
}
float nestedNoise(vec2 p) {
float x = movingNoise(p);
float y = movingNoise(p + 100.);
return movingNoise(p + vec2(x, y));
}
void main() {
vec2 p = vUv * 6.;
float brightness = nestedNoise(p);
gl_FragColor.rgb = vec3(brightness);
gl_FragColor.a = 1.;
}
</script>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main()
{
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var camera, controls, scene, renderer;
var uniforms;
var clock = new THREE.Clock();
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.z = 2;
scene = new THREE.Scene();
var geometry = new THREE.BoxGeometry( 0.5, 0.5, 0.5 );
uniforms = {
time: { type: "f", value: 1.0 },
resolution: { type: "v2", value: new THREE.Vector3() }
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader').textContent
});
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
uniforms.resolution.value.x = window.innerWidth;
uniforms.resolution.value.y = window.innerHeight;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var delta = clock.getDelta();
uniforms.time.value += delta;
// for ( var i = 0; i < scene.children.length; i ++ ) {
//
// var object = scene.children[ i ];
//
// object.rotation.y += delta * 0.5 * ( i % 2 ? 1 : -1 );
// object.rotation.x += delta * 0.5 * ( i % 2 ? -1 : 1 );
//
// }
renderer.render( scene, camera );
}
</script>
</body>
</html>
source to share