# Pixel coordinate to world coordinate (orthographic cam)

**URL:** <https://discourse.threejs.org/t/pixel-coordinate-to-world-coordinate-orthographic-cam/67350>\
**Category:** Questions\
**Created:** [June 27, 2024, 10:23am UTC](https://discourse.threejs.org/t/pixel-coordinate-to-world-coordinate-orthographic-cam/67350 "2024-06-27T10:23:24Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hadock](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hadock/32/49164_2.png) [@Hadock](https://discourse.threejs.org/u/Hadock)\
**Post date:** [June 27, 2024, 10:23am UTC](https://discourse.threejs.org/t/pixel-coordinate-to-world-coordinate-orthographic-cam/67350/1 "2024-06-27T10:23:24Z")

</div>

Hello there, I have built the [following script](https://github.com/bouteillerAlan/personal-website/blob/15a26b3edb02d08a2afe1eec44fc61925e267cb7/easter.js).

The idea is somewhat simple :

1. I loop over each element with a specific class (here `easterEgg`)
2. I map an event listener for `click` on each of this element
3. The user click on it
4. I get an emoji from the attribute of the clicked elem
5. I calculate the real coordinate of the click (`pixelX` and `pixelY`), here I debug this position with `drawHtmlSquare` and the calculated coordinate are good
6. With this coordinate, I place my emoji texture (created with `createEmojiTexture()`) in the same position but in webgl, like so when the user click on a word the emoji appear just below the cursor

My problem is specifically here, I don’t find the way to get the right coordinate.

I have tried many things ([latest attempts are visible here](https://github.com/bouteillerAlan/personal-website/blob/15a26b3edb02d08a2afe1eec44fc61925e267cb7/easter.js#L109-L123)).

The most close result that I have is with :

```js
const calcx = pixelX / (window.innerHeight / 2) - 1;
const calcy = - pixelY / (window.innerWidth / 2) + 1;
const cunproj = new THREE.Vector3(calcx, calcy, -1).unproject(camera);
emojiMesh.position.set(cunproj.x, cunproj.y, -1);

```

But this is not very good, in the following img I map the click (red square) to the result (emoji) :

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/c/d/cd25551cc43c1a3410424247628e58a40fe92663.png)

Another problem that I have is when I want to use the vector directly in the `position.set` like so - with that nothing appear on my screen :

```js
const calcx = pixelX / (window.innerHeight / 2) - 1;
const calcy = - pixelY / (window.innerWidth / 2) + 1;
const cunproj = new THREE.Vector3(calcx, calcy, -1).unproject(camera);
emojiMesh.position.set(cunproj);

```

I’m pretty much a noob in webgl/three.js, so any idea is welcomed !

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [June 28, 2024, 8:39pm UTC](https://discourse.threejs.org/t/pixel-coordinate-to-world-coordinate-orthographic-cam/67350/2 "2024-06-28T20:39:53Z")

</div>

Looks like the projected points are off by .5 of the screenspace…  
Can you try:

const cunproj = new THREE.Vector3(calcx-.5, calcy-.5, -1).unproject(camera);

---

<div class="post-metadata">

**Author:** ![Hadock](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hadock/32/49164_2.png) [@Hadock](https://discourse.threejs.org/u/Hadock)\
**Post date:** [June 29, 2024, 3:45pm UTC](https://discourse.threejs.org/t/pixel-coordinate-to-world-coordinate-orthographic-cam/67350/3 "2024-06-29T15:45:07Z")

</div>

Hello, thanks for your answer, I found the solution 😄

My calculation was not good at all.

Full explanation below

Important note, my 0,0 coordinate on three.js is always at the center of my screen in my case. Also, I use an orto camera, so I don’t need to mind z.

To translate the coordinates of a point from view A (where 0,0 is at the top left, so our screen) to view B (where 0,0 is at the center, the threejs view), we need to perform two transformations:

1. Horizontal translation (x-axis)
2. Vertical translation (y-axis)

#### Horizontal Translation (x-axis)

In view A, the origin (0,0) is at the top left. In view B, the origin (0,0) is at the center. To translate the x-coordinate of a point from view A to view B, we need to move the origin of view A to the center of view B.

- If (Xa, Ya) are the coordinates of a point in view A, the new coordinate Xb in view B is obtained by subtracting half of the width (W/2) from Xa.

Formula: Xb = Xa - (W/2)

#### Vertical Translation (y-axis)

Similarly, for the y-coordinate, we also need to move the origin of view A to the center of view B. However, note that the y-coordinates _increase downwards in view A, but in view B, they increase upwards_ from the center.

- To translate the y-coordinate, we need to subtract Ya from half of the height (H/2).

Formula: Yb = (H/2) - Ya

And I use the coordinate like that without `unproject` or `project`.

```js
const calcx = pixelX - (window.innerWidth / 2) ;
const calcy = (window.innerHeight / 2) - pixelY;
  
for (let i = 0; i < 50; i++) {
    const emojiMesh = new THREE.Mesh(emojiGeometry, emojiMaterial);
    emojiMesh.position.set(calcx, calcy, -1);
    .......
}

```
