我想要计算一个投影转换来纹理,一个任意的四角体在webgl中(如果可能的话,用three.js和着色器)。

这是我想要的,摘自这的答案。
这篇文章很好地描述了所有的事情,所以我想只要付出一点努力,我就能解决这个问题。下面是解决方案的伪代码:
precompute A matrix (should be trivial since texture coordinates are in [0,1] interval)
compute B matrix according to the vertex positions (not possible in the vertex shader since we need the four coordinates of the points)
use B in the fragment shader to compute the correct texture coordinate at each pixel但是,我想知道在webgl中是否有一种更简单的方法来做到这一点。
-链接到相关主题
有一种类似的方法来解决数学上描述的这里问题,但由于它是一种计算多到多点映射的解决方案,对我来说,这似乎是过火了。
我认为这是OpenGL中的一个解决方案,但意识到它是一种执行简单的透视图正确插值的解决方案,这在默认情况下是幸运的。
我在梯形图上发现了很多东西,这是我想要解决的更一般问题的一个简单版本:1、2和3.。首先,我认为这些会有所帮助,但它们却让我产生了大量的阅读和误解。
最后,这个页面描述了一个解决问题的解决方案,但我对它是否是最简单和最常见的解决方案表示怀疑。现在我认为这可能是正确的!
我一直在寻找这个解决方案,并不是因为它是一个特别复杂的问题,而是因为我正在寻找一个简单和典型的/常见的解决方案。我认为这是一个很容易解决的问题,在许多情况下(每个视频地图应用程序),将有琐碎的答案。
发布于 2013-12-25 15:52:00
好的,我成功地使用了three.js和coffeescript (我必须实现缺少的Matrix3函数):
class Quad
constructor: (width, height, canvasKeyboard, scene) ->
@sceneWidth = scene.width
@sceneHeight = scene.height
# --- QuadGeometry --- #
@geometry = new THREE.Geometry()
normal = new THREE.Vector3( 0, 0, 1 )
@positions = []
@positions.push( x: -width/2, y: height/2 )
@positions.push( x: width/2, y: height/2 )
@positions.push( x: -width/2, y: -height/2 )
@positions.push( x: width/2, y: -height/2 )
for position in @positions
@geometry.vertices.push( new THREE.Vector3( position.x, position.y, 0 ) )
uv0 = new THREE.Vector4(0,1,0,1)
uv1 = new THREE.Vector4(1,1,0,1)
uv2 = new THREE.Vector4(0,0,0,1)
uv3 = new THREE.Vector4(1,0,0,1)
face = new THREE.Face3( 0, 2, 1)
face.normal.copy( normal )
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() )
@geometry.faces.push( face )
@geometry.faceVertexUvs[ 0 ].push( [ uv0.clone(), uv2.clone(), uv1.clone() ] )
face = new THREE.Face3( 1, 2, 3)
face.normal.copy( normal )
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() )
@geometry.faces.push( face )
@geometry.faceVertexUvs[ 0 ].push( [ uv1.clone(), uv2.clone(), uv3.clone() ] )
@geometry.computeCentroids()
# --- Mesh --- #
@texture = new THREE.Texture(canvasKeyboard[0])
@texture.needsUpdate = true
C = new THREE.Matrix4()
@uniforms = { "texture": { type: "t", value: @texture }, "resolution": { type: "v2", value: new THREE.Vector2(@sceneWidth, @sceneHeight) }, "matC": { type: "m4", value: C } }
shaderMaterial = new THREE.ShaderMaterial(
uniforms: @uniforms,
vertexShader: $('#vertexshader').text(),
fragmentShader: $('#fragmentshader').text()
)
@mesh = new THREE.Mesh( @geometry, shaderMaterial )
@mesh.position.set(0,0,1)
scene.add(@mesh)
# --- Sprites --- #
@sprites = []
for i in [0..3]
position = @positions[i]
m = new THREE.SpriteMaterial( {color: new THREE.Color('green') ,useScreenCoordinates: true } )
s = new THREE.Sprite( m )
s.scale.set( 32, 32, 1.0 )
s.position.set(position.x,position.y,1)
scene.add(s)
@sprites.push(s)
# --- Mouse handlers --- #
# those functions enable to drag the four sprites used to control the corners
scene.$container.mousedown(@mouseDown)
scene.$container.mousemove(@mouseMove)
scene.$container.mouseup(@mouseUp)
screenToWorld: (mouseX, mouseY) ->
return new THREE.Vector3(mouseX-@sceneX-@sceneWidth/2, -(mouseY-@sceneY)+@sceneHeight/2, 1)
worldToScreen: (pos) ->
return new THREE.Vector2((pos.x / @sceneWidth)+0.5, (pos.y / @sceneHeight)+0.5)
computeTextureProjection: ()=>
pos1 = @worldToScreen(@sprites[0].position)
pos2 = @worldToScreen(@sprites[1].position)
pos3 = @worldToScreen(@sprites[2].position)
pos4 = @worldToScreen(@sprites[3].position)
srcMat = new THREE.Matrix3(pos1.x, pos2.x, pos3.x, pos1.y, pos2.y, pos3.y, 1, 1, 1)
srcMatInv = @inverseMatrix(srcMat)
srcVars = @multiplyMatrixVector(srcMatInv, new THREE.Vector3(pos4.x, pos4.y, 1))
A = new THREE.Matrix3(pos1.x*srcVars.x, pos2.x*srcVars.y, pos3.x*srcVars.z, pos1.y*srcVars.x, pos2.y*srcVars.y, pos3.y*srcVars.z, srcVars.x, srcVars.y, srcVars.z)
dstMat = new THREE.Matrix3(0, 1, 0, 1, 1, 0, 1, 1, 1)
dstMatInv = @inverseMatrix(dstMat)
dstVars = @multiplyMatrixVector(dstMatInv, new THREE.Vector3(1, 0, 1))
B = new THREE.Matrix3(0, dstVars.y, 0, dstVars.x, dstVars.y, 0, dstVars.x, dstVars.y, dstVars.z)
Ainv = @inverseMatrix(A)
C = @multiplyMatrices(B,Ainv)
ce = C.elements
# I used a Matrix4 since I don't think Matrix3 works in Three.js shaders
@uniforms.matC.value = new THREE.Matrix4(ce[0], ce[3], ce[6], 0, ce[1], ce[4], ce[7], 0, ce[2], ce[5], ce[8], 0, 0, 0, 0, 0)这是碎片着色器:
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D texture;
uniform vec2 resolution;
uniform mat4 matC;
void main() {
vec4 fragCoordH = vec4(gl_FragCoord.xy/resolution, 1, 0);
vec4 uvw_t = matC*fragCoordH;
vec2 uv_t = vec2(uvw_t.x/uvw_t.z, uvw_t.y/uvw_t.z);
gl_FragColor = texture2D(texture, uv_t);
}附加注
Maptastic是Javascript/CSS投影映射实用工具。https://github.com/glowbox/maptasticjs
https://stackoverflow.com/questions/20718663
复制相似问题