mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.89k stars 35.32k forks source link

PixelPerfect Sprite (feature request) #19003

Closed Josema closed 4 years ago

Josema commented 4 years ago

I love three.js but it amaze me that we are not able to render images in a scene without changing it's properties.

image

On the left side the best result I could get with this config:

SpriteMaterial.sizeAttenuation = false
texture.minFilter = THREE.NearestFilter
sprite.scale = 0.008

On the right side the actual PNG pasted in Photoshop. I can achieve the result I want by overlapping a div and using CSS/HTML but I see this as a dirty solution.

Mugen87 commented 4 years ago

Can you please demonstrate the issue with a live example? https://jsfiddle.net/hyok6tvj/

Josema commented 4 years ago

I have the same size in both images because I adjusted the scale to my screen. Maybe you should adjust the sprite scale according to your screen. https://jsfiddle.net/hunmr8e4/

Ideally we should not have to change the scale of the sprite when sizeAttenuation is false. Don't know why is this behavior.

Mugen87 commented 4 years ago

You can only achieve the intended result (meaning a 1:1 match of your original image) if you render the sprite like HUD elements (similar to the red sprites in this example).

https://jsfiddle.net/swkvgyoL/

To do so, you have to render the sprites with a separate scene and orthographic camera. It's then not necessary to manually define a scale value since it can be computed from the image dimensions. I don't think it's possible to achieve an equivalent exact output with a perspective camera on all possible devices.

Josema commented 4 years ago

Still blurry on my screen. image

Also the two cameras makes my code more complex. Will a 256x256 image and then scaling it with an PerspectiveCamera solve this issue?

Mugen87 commented 4 years ago

Still blurry in my screen.

I don't see a noticeable difference on my system (Chrome 80.0.3987.149, macOS 10.15.3).

Will a 256x256 image and then scaling it with an PerspectiveCamera solve this issue?

It's not a matter of resolution.

Josema commented 4 years ago

Can you please show a screenshot?

Mugen87 commented 4 years ago

screenshot

Left is HTML element, right is the sprite.

Josema commented 4 years ago

image

Looks the same in my macbook too. The other one was Chrome and Windows. Weird.

By the way, do you know how to combine the ortographic camera with the OrbitControls? If this task is not posible I can't use this solution.

Mugen87 commented 4 years ago

By the way, do you know how to combine the ortographic camera with the OrbitControls?

Um, what do you mean by that? OrbitControls definitely supports orthographic cameras.

Josema commented 4 years ago

Something like this: controls = new OrbitControls( [camera, cameraOrtho], renderer.domElement );

I'm using a PerspectiveCamera with OrbitControls. The idea of using this technique is having two cameras that both moves at the same time when using the orbitcontrols. And of course that sprite must be represented in the correct position of the PerspectiveCamera.

Mugen87 commented 4 years ago

Sorry, you can't use OrbitControls like that. Besides, I don't think what you are looking for is possible. What I have showed you assumes the sprites are used as HUD elements (in screen space).

Josema commented 4 years ago

Just wondering how games solve this task with their engines. Look at this example from League Of Legends. image

I just want to achieve more or less the same. They represent the life the same way, like a Sprite that does not change the size when zooming.

Wouldn't be a good feature to add in Three.js?

Mugen87 commented 4 years ago

I'm sorry but this is not a real feature request since you can implement annotations or status bars with existing library features like sprites or the CSS renderers. I suggest you search in the forum for more information about this topic. Especially the following post explains how to implement health bars like in your screenshot in a web-based game:

https://discourse.threejs.org/t/sphere-health-bar/11890/5?u=mugen87

Classes like CSS2DRenderer might be helpful in this context.

BTW: Using HTML/CSS is not a dirty solution like you mentioned in your initial post. Many games used Flash in the past for implementing UIs. Using HTML/CSS with JS is definitely the better choice.

Josema commented 4 years ago

Imagine that Three.js is ported in the future to a smart-tv device that support WebGL but does not have CSS+HTML. I don't think Unity or any other 3D engine use CSS+HTML to solve this issue.