我想编写一个使用three.js操纵我的图像的自定义着色器。 为此我想创建一个图像作为纹理的平面。之后我想移动顶点以扭曲图像。
(如果这是绝对错误的方法,请告诉我)。
首先我有我的着色器:
<script type="x-shader/x-vertex" id="vertexshader">
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main() {
// Pass the texcoord to the fragment shader.
v_texCoord = a_texCoord;
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D u_texture;
varying vec2 v_texCoord;
void main() {
vec4 color = texture2D(u_texture, v_texCoord);
gl_FragColor = color;
}
</script>
我真的不明白texture2D在做什么,但我发现在其他代码片段中。 这个样本我想要的是:只用“底层”图像(=纹理)的颜色为顶点(gl_FracColor)着色。
在我的代码中,我使用平面设置了一个普通的三个场景:
// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = window.innerWidth/window.innerHeight,
NEAR = 0.1,
FAR = 1000;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(0, 0, 15);
var vertShader = document.getElementById('vertexshader').innerHTML;
var fragShader = document.getElementById('fragmentshader').innerHTML;
var texloader = new THREE.TextureLoader();
var texture = texloader.load("img/color.jpeg");
var uniforms = {
u_texture: {type: 't', value: 0, texture: texture},
};
var attributes = {
a_texCoord: {type: 'v2', value: new THREE.Vector2()}
};
// create the final material
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertShader,
fragmentShader: fragShader
});
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(renderer.domElement);
var plane = {
width: 5,
height: 5,
widthSegments: 10,
heightSegments: 15
}
var geometry = new THREE.PlaneBufferGeometry(plane.width, plane.height, plane.widthSegments, plane.heightSegments)
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var plane = new THREE.Mesh( geometry, shaderMaterial );
scene.add(plane);
plane.rotation.y += 0.2;
var render = function () {
requestAnimationFrame(render);
// plane.rotation.x += 0.1;
renderer.render(scene, camera);
};
render();
不幸的是,运行该代码后,我只看到一个黑色的窗口。虽然我知道如果我在创建网格时使用material
作为材质,我可以清楚地看到它。
所以它必须是shaderMaterial或着色器。
问题:
u_texture
和属性
我的着色器中的a_texCoord
材质制服和属性?并做
他们必须有完全相同的名字?a_texCoord有什么价值?如果我写的话,什么都没发生:
var attributes = {
a_texCoord: {type: 'v2', value: new THREE.Vector2(1,1)}
};
或者我是否必须使用一些映射(内置三个地图的东西)?但是我怎么会改变顶点位置呢?
有人可以解释一下这个问题吗?
答案 0 :(得分:1)
我通过改变它来实现它:
class StarBarExtension extends \Twig_Extension
{
protected $doctrine;
private $RequestStack;
public function __construct(RegistryInterface $doctrine, RequestStack $RequestStack)
{
$this->doctrine = $doctrine;
$this->requestStack = $RequestStack;
}
public function getFunctions() {
return array(
'starBar' => new \Twig_Function_Method($this, 'myStarBar'),
);
}
public function myStarBar($numStar, $mediaId, $starWidth) {
$cookies = $this->requestStack->getCurrentRequest()->cookies->get('LilmodLemaedNote'.$mediaId);
$nbrPixelsInDiv = $numStar * $starWidth; // Calculate the DIV width in pixel
**$query = $this->get('doctrine_mongodb')->getRepository('PortailBundle:Notes')->findOneBy(array('ARTICLE' =>$mediaId));**
对此:
var uniforms = {
u_texture: {type: 't', value: 0, texture: texture},
};
无论如何,所有其他问题仍然是开放的,答案非常感谢。 (顺便问一下:为什么降级某人?)
答案 1 :(得分:1)
我是否必须定义统一的u_texture和属性a_texCoord 在我的着色器材质制服和属性?他们必须这样做 有完全相同的名字?
是的,是的。制服被定义为着色器材质的一部分,而属性已从版本72中的着色器材质移动到BufferGeometry类(我假设您使用的是最新版本,所以这里是你的方式今天这样做):
var geometry = new THREE.PlaneBufferGeometry(...);
// first, create an array to hold the a_texCoord-values per vertex
var numVertices = (plane.widthSegments + 1) * (plane.heightSegments + 1);
var texCoordBuffer = new Float32Array(2 * numVertices);
// now register it as a new attribute (the 2 here indicates that there are
// two values per element (vec2))
geometry.addAttribute('a_texCoord', new THREE.BufferAttribute(texCoordBuffer, 2));
如您所见,该属性仅在其与着色器代码中指定的名称完全相同时才起作用。
我不确切地知道你打算用它做什么,但听起来很可疑,就像你想拥有紫外线坐标一样。如果是这种情况,如果您查看THREE.PlaneBufferGeometry
课程,可以节省很多工作。它已经提供了一个名为uv
的属性,可能正是您正在寻找的属性。因此,您只需将着色器代码中的属性名称更改为
attribute vec2 uv;
反正有多少个顶点?我会为每个人获得一个顶点吗? 图像中的像素?或者飞机的每个角落只有4个?
根据heightSegments
和widthSegments
参数创建顶点。因此,如果将两者都设置为5,则会有(5 + 1)*(5 + 1)= 36个顶点(+1因为只有1个段的线有两个顶点等)和5 * 5 * 2 = 50个三角形(共有150个指数)。
需要注意的另一件事是PlaneBufferGeometry是一个索引几何体。这意味着每个顶点(以及每个其他属性值)仅存储一次,尽管它由多个三角形使用。有一个特殊的索引属性,它包含用于创建哪些三角形的顶点信息。
a_texCoord有什么价值?如果我写的话,什么都没发生:......
我希望上述内容有助于回答这个问题。
或者我是否必须使用一些映射(内置三个地图的东西)?
我建议你使用上面描述的uv
属性。但你绝对不必。
但我怎么会改变顶点位置呢?
至少有两种方法可以做到这一点:在顶点着色器中或通过javascript。后者可以在这里看到:http://codepen.io/usefulthink/pen/vKzRKr?editors=1010 (更新几何的相关部分从第84行开始)。