在 threejs 可视化中从 webgl 上下文填充着色器属性
filling shader attributes from webgl context in threejs visualization
我正在使用一些现有的 webgl 教程学习着色器,我希望有一种方法可以将已编译的着色器程序附加到 threejs 着色器material,但我被卡住了.如果可能的话,最好使用 gl 方法设置属性和制服,然后在 material 上设置着色器程序。这是我试过的。
<!doctype html>
<html>
<head>
<script src="http://threejs.org/build/three.min.js"></script>
<meta charset="utf-8" />
<title>Sample Three.js</title>
<style>
#container {
background: #000;
width: 400px;
height: 300px;
}
</style>
</head>
<body>
</body>
<script type="x-shader/x-vertex" id="vertexshader">
// switch on high precision floats
#ifdef GL_ES
precision highp float;
#endif
uniform mat4 projectionmyMatrix;
attribute vec3 vertexPos;
attribute float displacement;
uniform float amplitude;
void main()
{
vec3 newPos = vertexPos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos,1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
#ifdef GL_ES
precision highp float;
#endif
void main( void ) {
gl_FragColor = vec4( 1.0,1.0,1.0,1.0);
}
</script>
<!-- End Shaders -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript">
// set the scene size
var WIDTH = 800,
HEIGHT = 600;
// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 1,
FAR = 1000;
// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('body');
// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR );
var scene = new THREE.Scene();
// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;
// start the renderer
renderer.setSize(WIDTH, HEIGHT);
// attach the render-supplied DOM element
$container.append(renderer.domElement);
// set up the sphere vars
var radius = 50, segments = 16, rings = 16;
// create the sphere's material
var shaderMaterial = new THREE.ShaderMaterial({
vertexShader: $('#vertexshader').text(),
fragmentShader: $('#fragmentshader').text()
});
// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, rings),
shaderMaterial);
//filling the attribute vertex array
// add the sphere and camera to the scene
scene.add(sphere);
scene.add(camera);
renderer.compile(scene,camera)
var gl = renderer.getContext()
var sq = createSquare(gl)
var prg = shaderMaterial.program.program
var posAttr = gl.getAttribLocation(prg,'vertexPos')
// set the vertex buffer to be drawn
gl.bindBuffer(gl.ARRAY_BUFFER, sq.buffer);
// set the shader to use
gl.useProgram(prg);
// connect up the shader parameters: vertex position and projection/model matrices
gl.vertexAttribPointer(posAttr, sq.vertSize, gl.FLOAT, false, 0, 0);
renderer.compile(scene,camera)
// create a rendering loop
var frame = 0;
function update() {
frame += .01
renderer.render(scene, camera);
requestAnimationFrame(update)
}
requestAnimationFrame(update)
</script>
</html>
我宁愿不必将教程翻译成制服,three.js 使用的属性语法如下所示
```
var attributes = {
displacement: {
type: 'f', // a float
value: [] // an empty array
}
};
var uniforms = {
amplitude: {
type: 'f', // a float
value: 1
}
};
var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');
// create the final material
var shaderMaterial =
new THREE.MeshShaderMaterial({
uniforms: uniforms,
attributes: attributes,
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});
...
不,既不推荐也不支持这种方法。除了使用原始 WebGL 上下文,您有两个选择:
- 您可以使用
THREE.ShaderMaterial
自定义着色器定义。 three.js
自动提供一些 built-in 属性和制服(例如 modelViewMatrix
或 projectionMatrix
),它们经常被顶点和片段着色器使用。官方doc page提供了很多资料
THREE.RawShaderMaterial
是一个更轻量级的选项,因为 three.js
不提供提到的 built-in 制服和属性。
以下两个基本示例显示了两种材料在最新版本 three.js
(R91
) 中的用法:
https://threejs.org/examples/#webgl_shader
https://threejs.org/examples/#webgl_buffergeometry_rawshader
我建议使用这些示例,而不是可能已过时的教程。例如,属性不再是 ShaderMaterial
的参数。相反,属性数据是几何的一部分。
我正在使用一些现有的 webgl 教程学习着色器,我希望有一种方法可以将已编译的着色器程序附加到 threejs 着色器material,但我被卡住了.如果可能的话,最好使用 gl 方法设置属性和制服,然后在 material 上设置着色器程序。这是我试过的。
<!doctype html>
<html>
<head>
<script src="http://threejs.org/build/three.min.js"></script>
<meta charset="utf-8" />
<title>Sample Three.js</title>
<style>
#container {
background: #000;
width: 400px;
height: 300px;
}
</style>
</head>
<body>
</body>
<script type="x-shader/x-vertex" id="vertexshader">
// switch on high precision floats
#ifdef GL_ES
precision highp float;
#endif
uniform mat4 projectionmyMatrix;
attribute vec3 vertexPos;
attribute float displacement;
uniform float amplitude;
void main()
{
vec3 newPos = vertexPos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos,1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
#ifdef GL_ES
precision highp float;
#endif
void main( void ) {
gl_FragColor = vec4( 1.0,1.0,1.0,1.0);
}
</script>
<!-- End Shaders -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript">
// set the scene size
var WIDTH = 800,
HEIGHT = 600;
// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 1,
FAR = 1000;
// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('body');
// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR );
var scene = new THREE.Scene();
// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;
// start the renderer
renderer.setSize(WIDTH, HEIGHT);
// attach the render-supplied DOM element
$container.append(renderer.domElement);
// set up the sphere vars
var radius = 50, segments = 16, rings = 16;
// create the sphere's material
var shaderMaterial = new THREE.ShaderMaterial({
vertexShader: $('#vertexshader').text(),
fragmentShader: $('#fragmentshader').text()
});
// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, rings),
shaderMaterial);
//filling the attribute vertex array
// add the sphere and camera to the scene
scene.add(sphere);
scene.add(camera);
renderer.compile(scene,camera)
var gl = renderer.getContext()
var sq = createSquare(gl)
var prg = shaderMaterial.program.program
var posAttr = gl.getAttribLocation(prg,'vertexPos')
// set the vertex buffer to be drawn
gl.bindBuffer(gl.ARRAY_BUFFER, sq.buffer);
// set the shader to use
gl.useProgram(prg);
// connect up the shader parameters: vertex position and projection/model matrices
gl.vertexAttribPointer(posAttr, sq.vertSize, gl.FLOAT, false, 0, 0);
renderer.compile(scene,camera)
// create a rendering loop
var frame = 0;
function update() {
frame += .01
renderer.render(scene, camera);
requestAnimationFrame(update)
}
requestAnimationFrame(update)
</script>
</html>
我宁愿不必将教程翻译成制服,three.js 使用的属性语法如下所示
```
var attributes = {
displacement: {
type: 'f', // a float
value: [] // an empty array
}
};
var uniforms = {
amplitude: {
type: 'f', // a float
value: 1
}
};
var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');
// create the final material
var shaderMaterial =
new THREE.MeshShaderMaterial({
uniforms: uniforms,
attributes: attributes,
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});
...
不,既不推荐也不支持这种方法。除了使用原始 WebGL 上下文,您有两个选择:
- 您可以使用
THREE.ShaderMaterial
自定义着色器定义。three.js
自动提供一些 built-in 属性和制服(例如modelViewMatrix
或projectionMatrix
),它们经常被顶点和片段着色器使用。官方doc page提供了很多资料 THREE.RawShaderMaterial
是一个更轻量级的选项,因为three.js
不提供提到的 built-in 制服和属性。
以下两个基本示例显示了两种材料在最新版本 three.js
(R91
) 中的用法:
https://threejs.org/examples/#webgl_shader https://threejs.org/examples/#webgl_buffergeometry_rawshader
我建议使用这些示例,而不是可能已过时的教程。例如,属性不再是 ShaderMaterial
的参数。相反,属性数据是几何的一部分。