How to make diamond looks real?

image
I try many times, but the effect looks bad. I wonder should I need to write the shader to achieve the real effect?
I follow the examples, but It looks fake.
fake effect
And I found some other perfect effect like below, but I have no idea.
real effect
image

It’s not trivial so I will not give you a full example or explanation, only some pointers.

By the look of it the diamonds in the second link you shared are geometries with an identical UV map for each individual diamond, and a ShaderMaterial using two textures like this as uniforms :


One of the texture could be exactly this one, the other should be a panoramic baking of faces normal from the inside of a diamond.

Firstly the vertex shader would hand uv and normal information to the fragment shader.
Then the fragment shader would start by sampling the panoramic normal texture based on uv and normal (with a bit of offsetting to fake a first refraction effet), to get new normal and compute the coords of the diffuse texture sampling (again with offset to fake a second refraction effect like the light bounced twice). The chromatic aberrations look like a third texture sampling like the diffuse texture sampling but with a different offset, with some smart colour blending.

Again it’s absolutely not trivial so I’m only giving pointers.

3 Likes

Thank you for reply, recently I learning webgl and shader because I find some examples about what I want at shaderToy. But I can’nt port it to three.js.
shaderToy examples

I have also ported some examples from Shadertoy in the collection. Maybe they help you with the porting.

See Little Shader Book (a bit more complicated … )

2 Likes

Hope this helps (1) Live Coding:Bending Light - YouTube

1 Like

It’s not trivial so I will not give you a full example or explanation, only some pointers.

why is everything in threejs always so secretive and mysterious @felixmariotto :smile: i will never be able to deal with the math, just want to have a nice diamond on my web page. i will figure the damn thing out and open source it. :blush:

1 Like

@vcxiaohan - not exactly diamond shaped, but this WebGL guide also has a few nice gifs and explanations on math and handling of diamond-like surfaces (with internal reflections without transparency.)

This topic and answers to it may also be quite helpful.


@drcmda it’s not about secrecy - all the math is already there. The main (and kinda only) challenge lies in transparency right now - since diamonds require 2 overlaying transparent surfaces to simulate total internal reflections (and overlaying transparency is easy neither in WebGLRenderer, nor in postprocessing.)

Writing and open-sourcing a “fake” diamond shader (1, 2, 3) isn’t that hard, but will likely lead to an example like Water / Water2 - where the amount of limitations and “assumptions” makes them not really universal / maintainable. And in case where code isn’t reusable outside one project - we’re happy to give answers and help, but expect the other side to do the keyboard tapping :see_no_evil:

2 Likes

i did try to abstract it once: Floating diamonds (forked) - CodeSandbox

but the bits and pieces that are available online weren’t enough to figure it out for me. i have nothing against tapping a keyboard, but i can’t understand math. what i have so far somewhat refracts, i guess, but looks nothing like what i see in the demos and videos that are closed source.

1 Like

says the guy who has a diamond shader repo at github :smiling_face_with_tear:

3 Likes

diamond refraction hack with three.js (felixmariotto.github.io)

3 Likes

try throwing the above texture at it, let’s see what it looks like :sweat_smile:

2 Likes

The example in the repo I shared works differently than OP’s links, that’s why I didn’t mention it. Don’t use this code guys, it was just an experiment :sweat_smile: As @mjurczyk explained there are lots of assumptions that make the technic unsuable in real life use cases.

1 Like

i will totally use this :smile:

getting close: prod-rgb-zqrreo - CodeSandbox this is from a post on twitter i’ve stumbled over https://twitter.com/garrettkjohnson/status/1569756547508469762 and trying to untangle diamonds/main.js at 2dfb1ba5c938f213b8ecd0e2d7289cba1f299a72 · N8python/diamonds · GitHub into something more readily re-usable.

it’s missing the rgb color shift, does anyone have an idea how to implement that?

3 Likes

do three rays for r, g and b with slightly different ior

physically incorrect, but more performant: count the length the ray traveled, shift proportionally.

2 Likes

Something like this, I guess… I found this code in an old repo online

image

image

1 Like

updated the sandbox with the solution from n8programms: https://twitter.com/N8Programs/status/1569865007042646018

could you guys check if that’s good or is your version faster? here’s the sandboxbox again

it looks pretty damn good :smile:

6 Likes

Yeah, the effect looks very good. I must spend a lot of time learning these. Thank you very much! :smile:

if anyone needs it, i published the raw shader: UNPKG - @react-three/drei (npm: import { MeshRefractionMaterial } from '@react-three/drei/materials/MeshRefractionMaterial'). it will not pull anything from react, it’s just the namespace.

to use it you need to give it a couple of defines without which it can’t work, and a bvh index, you can see how to add both here: drei/MeshRefractionMaterial.tsx at 66750d85d3c3ed5d1289d779acf9377eee159bb1 · pmndrs/drei · GitHub

1 Like