Threejs着色器实现
Threejs shader implementation
过去几周我一直在试验 three.js 库和着色器,但我一直坚持在我的模型上实现着色器。我在 pixelshaders.com 上发现了这个有趣的例子,我想在 threejs 模型上实现它。
http://pixelshaders.com/examples/noise.html
这是页面底部的最后一个示例,我正在尝试实现。
我正在尝试将它添加到 3D 模型中,可以在下面的 link 中找到:
http://martinr.nl/lab/Speeltuin/webgl_shader2.html
困难的是当我添加示例代码时 3D 模型消失了。这使得调试和查找错误变得非常困难。
这是有效的着色器代码,但不适用于正确的着色器:
<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>
当我尝试实现上述示例的着色器时,3D 模型消失了。
有谁知道如何将 pixelshader.com 示例的着色器应用到我示例中的模型上?
或者有没有人有任何提示我可以尝试使其工作?
我用 pixelshaders.com 中的代码替换了您的片段着色器。控制台报告以下错误:
> 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
可变变量本质上是顶点着色器和片段着色器之间的接口。这个错误告诉我们 position
是在片段着色器中声明的,但不是在顶点着色器中声明的。
您实际上在顶点着色器中有所需的变量...除了它被命名为 vUv
。我所要做的就是使变量名称保持一致。
完整源代码(我也在 render()
函数中取消了 time
的缩放):
<!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>
过去几周我一直在试验 three.js 库和着色器,但我一直坚持在我的模型上实现着色器。我在 pixelshaders.com 上发现了这个有趣的例子,我想在 threejs 模型上实现它。
http://pixelshaders.com/examples/noise.html
这是页面底部的最后一个示例,我正在尝试实现。
我正在尝试将它添加到 3D 模型中,可以在下面的 link 中找到:
http://martinr.nl/lab/Speeltuin/webgl_shader2.html
困难的是当我添加示例代码时 3D 模型消失了。这使得调试和查找错误变得非常困难。
这是有效的着色器代码,但不适用于正确的着色器:
<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>
当我尝试实现上述示例的着色器时,3D 模型消失了。
有谁知道如何将 pixelshader.com 示例的着色器应用到我示例中的模型上?
或者有没有人有任何提示我可以尝试使其工作?
我用 pixelshaders.com 中的代码替换了您的片段着色器。控制台报告以下错误:
> 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
可变变量本质上是顶点着色器和片段着色器之间的接口。这个错误告诉我们 position
是在片段着色器中声明的,但不是在顶点着色器中声明的。
您实际上在顶点着色器中有所需的变量...除了它被命名为 vUv
。我所要做的就是使变量名称保持一致。
完整源代码(我也在 render()
函数中取消了 time
的缩放):
<!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>