# Texture perspective projection

**URL:** <https://discourse.threejs.org/t/texture-perspective-projection/8030>\
**Category:** Questions\
**Tags:** perspective-projection, uv-mapping\
**Created:** [June 11, 2019, 1:45am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030 "2019-06-11T01:45:47Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 11, 2019, 1:45am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/1 "2019-06-11T01:45:47Z")

</div>

As part of a larger problem I’m trying to solve, I need to project a texture from the camera plane to each of the geometry faces of an object.

The way I’m, currently, approaching this is by setting the `uv` of each vertex in the geometry to the `xy` position on clip space. This works as intended when the face normal is aligned with the camera’s focal axis, but the projection breaks as those are no longer aligned.

I’m not entirely sure why this happens, I would greatly appreciate any help.

![perspective_projection](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/2X/9/95fb3fc314d2b538c5b20d3638ab1c986e743c06.png)

[live example](https://jsfiddle.net/yj6qezn8/)

**notes:** I’m aware that the live code provided suffers from a lot of problems. Namely using `Geometry` instead of `BufferGeometry`, and it’s also unnecessarily re-calculating vertices projections. I understand those problems exist, the live example was just meant to illustrate the behavior 🙂

I believe the same effect can be easily achieved making use of the stencil buffer, but I need to actually re-calculate the uvs for use in a later stage. So, I can’t make use of stencil rendering techniques ☹

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [June 11, 2019, 4:16am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/2 "2019-06-11T04:16:49Z")

</div>

Are you trying to do “uv mapping” ? What i see in your sketch seems like a simple (or maybe skewed) perspective projection. There’s not much to do there except to call `render()` with `THREE.PerspectiveCamera`.

---

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 11, 2019, 4:36am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/3 "2019-06-11T04:36:43Z")

</div>

> There’s not much to do there except to call `render()` with `THREE.PerspectiveCamera`

I’m not sure I follow what you mean here.

> Are you trying to do “uv mapping” ?

Yeah, I’m trying to uv map the visible faces of the object according to their pixel positions on the screen. Which means that I’m basically mapping the pixel clip coordinates of each vertex to the uv positions on the texture.

Which, in theory, would show a non distorted ( or skewed as you said ) texture on the surface of the object.

But what I’m getting instead is a skewed projection on the object, whenever the faces normals aren’t aligned with the camera’s direction.

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [June 11, 2019, 4:44am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/4 "2019-06-11T04:44:02Z")

</div>

If you make a cube and put a camera in front of it and render to a texture, you’ve projected 2 triangles according to how i understand your description. What do you expect to happen when you rotate the cube by 45 degrees around some axis?

---

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 11, 2019, 5:05am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/5 "2019-06-11T05:05:37Z")

</div>

Maybe I did a bad job explaining what I wanted in the original post.

There are a few ways of thinking about what I want achieve here. I’m gonna try explaining it two ways:

- Imagine you render a texture to the full viewport, afterwards you render your scene to the screen again, but only color the pixels where your object is not visible.  
What you end up with, is your regular scene, but where you would’ve have your object drawn, you have a silhouette of this object and inside it you can see the texture previously rendered.

- A second way of looking at it is the following, imagine you have two layers on any image editing software. The bottom layer contains your texture, on the top layer you have your scene rendered. Imagine you simply select the pixels of the top layer that contains the object and you delete it. You end up with the same result.

So it doesn’t matter if the object is rotated, if the object is a sphere or a plane. The silhouette of the object will be rendered as a texture. But the key point is that I need to do this by uv mapping, not other approaches.

Hopefully that clarifies.

---

<div class="post-metadata">

**Author:** ![looeee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/looeee/32/59_2.png) [@looeee](https://discourse.threejs.org/u/looeee)\
**Post date:** [June 11, 2019, 5:17am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/6 "2019-06-11T05:17:01Z")

</div>

Have you seen this PR? Is it doing something similar to what you want, using a light’s perspective rather than the cameras? It’s doing the work in the shader, but that’s probably the best approach for implementing new textures mapping functions.

> <https://github.com/mrdoob/three.js/pull/13057>

[Light projectors](https://cdn.rawgit.com/usefulthink/three.js/projector-lights-preview/examples/webgl_lights_projectorlight.html)

 ![pro](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/2X/6/6b9e386abda6354046e730018127c5e5c1337398.jpeg)

BTW, is this for the `LWOLoader`?

---

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 11, 2019, 5:27am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/7 "2019-06-11T05:27:30Z")

</div>

> BTW, is this for the `LWOLoader` ?

No, not really. It’s part of the texture painting project that I’ve been re-thinking. I wanted to move away from raycasting and this idea just popped in my head. It’s all working great, except that I can’t seem to get this projection right ☹

> Have you seen this PR?

No I haven’t, this looks promising 🙂

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [June 11, 2019, 6:49am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/8 "2019-06-11T06:49:08Z")

</div>

Maybe this will be helpful too: [Texture Projection](https://discourse.threejs.org/t/texture-projection/3224)

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [June 11, 2019, 7:21am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/9 "2019-06-11T07:21:08Z")

</div>

I’m not quite sure if i understand what you mean, do you mean like this? [https://jsfiddle.net/j4hbq2ek/](https://jsfiddle.net/j4hbq2ek/)

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [June 11, 2019, 8:10am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/10 "2019-06-11T08:10:40Z")

</div>

This can easily be solved with shader injection. Needs to be provided the perspective matrix along with the view matrix of some perspective camera. Value written to a varying, and then that varying used to read a texture. Be it some built in, or some other. Unfortunately, the ways to do this are very verbose ☹

But yeah, my understanding is that, unlike a projector, the op wants to actually just render a texture in screen space, in whatever geometry is rendered. Imagine if you could look up the AO map, instead of composing it in an additional step.

This could also be achieved with a suuuuper simple shader material, but I’m on my phone right now.

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [June 11, 2019, 8:15am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/11 "2019-06-11T08:15:28Z")

</div>

The problem (I think) is “how to show a texture on an object using its screen coordinates and not the uvs”.

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [June 11, 2019, 8:18am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/12 "2019-06-11T08:18:46Z")

</div>

The fiddle i linked did just that. I’m not sure though if this is exactly what he wants.

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [June 11, 2019, 8:19am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/13 "2019-06-11T08:19:56Z")

</div>

Yeah didn’t load on my phone at first, exactly that.

---

<div class="post-metadata">

**Author:** ![looeee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/looeee/32/59_2.png) [@looeee](https://discourse.threejs.org/u/looeee)\
**Post date:** [June 11, 2019, 10:26am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/14 "2019-06-11T10:26:24Z")

</div>

I’m still not completely sure I understand what you want here.  
Does @Fyrestar’s fiddle solve your problem?

If not, do you mean [Planar UV Mapping](https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-Modeling/files/GUID-B6519472-C0ED-4C07-99C6-12107A3509D9-htm.html)?

![GUID-5D699E6C-4B3F-4136-9C5C-C696DB4D6F98](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/2X/d/de94c620b13fe4585e2bebafd19dbf088291be7b.png)

---

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 11, 2019, 2:52pm UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/15 "2019-06-11T14:52:09Z")

</div>

@prisoner849 Thank you. That looks really similar to what I’m looking for.

@Fyrestar The end result is exactly what I’m looking for, but I wanted to achieve the same result by modifying the vertex UV coordinates attributes we send to the renderer. Not modying the shader mapping itself, theoretically I’m doing the same thing, but in reality I’m not. Which is creating this skewed mapping on my live example.

@looeee Maybe I’m not even sure myself 🤣. The difference is that a planar UV mapping projects orthogonally to the mesh, in my case I want to project perspectively. If that makes sense…

I guess I have enough material to study and try to figure out how to solve my problem. I’ll have to take a look at the resources and see if I can come up with a solution for my problem.  
If I find a solution, I’ll make sure to create a reply.

Thank you all ❤

---

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 11, 2019, 6:16pm UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/16 "2019-06-11T18:16:37Z")

</div>

Ok, thanks to prisoner’s example I understand what’s wrong here.

The problem is that, what I’m looking for appears to be impossible. Even though the UVs map to the correct screen position. The relationship between each frag pixel to the uv vertices is non-linear, so when the UV coord is linearly interpolated to the fragment shader, it breaks the projection 😒

Welp, I guess I’m gonna look for a different approach to my problem.

Thanks again guys.

---

<div class="post-metadata">

**Author:** ![sciecode](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sciecode/32/5623_2.png) [@sciecode](https://discourse.threejs.org/u/sciecode)\
**Post date:** [June 12, 2019, 11:10pm UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/17 "2019-06-12T23:10:28Z")

</div>

I found this relevant [Article](http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/) by Nathan Reed discussing the problem I’ve ran into. I’ve already solved my problem by modifying my approach to the problem, but I feel like this could be useful for future reference.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [March 13, 2022, 11:25pm UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/18 "2022-03-13T23:25:25Z")

</div>

`three-projected-material` 👇 👀

> **[GitHub - marcofugaro/three-projected-material: 📽 Three.js Material which lets...](https://github.com/marcofugaro/three-projected-material)**
>
> 📽 Three.js Material which lets you do Texture Projection on a 3d Model - GitHub - marcofugaro/three-projected-material: 📽 Three.js Material which lets you do Texture Projection on a 3d Model

---

<div class="post-metadata">

**Author:** ![Parisa\_Shahbazi](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/parisa_shahbazi/32/43776_2.png) [@Parisa\_Shahbazi](https://discourse.threejs.org/u/Parisa_Shahbazi)\
**Post date:** [February 27, 2024, 6:33am UTC](https://discourse.threejs.org/t/texture-perspective-projection/8030/19 "2024-02-27T06:33:56Z")

</div>

Hi  
Did you find any good way?
