Skip to content

Conversation

@BlagoGunev
Copy link

@BlagoGunev BlagoGunev commented Mar 29, 2025

Brushed Material Simulation:

Implements some features of a raytracer such that a scene containing a sphere and a light source can be drawn.
The ray bounces off of the sphere and gets a color sample from an environment map created using the existing implementation of gradient generation. Multiple samples are taken to simulate a look of brushed material.

brushed

Implementation:

The sample is retrieved from the gradient with an offset depending on the ray direction. I used sine to make the effect more appealing:

def sampleEnvironment(rayDir: Vec3[Float32])(using animationInstant: AnimationInstant): Vec3[Float32] =
      val f = smooth(from = 0f, to = 5f, duration = 5.seconds) + sin(3f  * rayDir.x) + rayDir.y * 2f
      val brightness = vec3(0.3f, 0.4f, 1f)
      val contrast = vec3(0.25f, 0.5f, 0f)
      val freq = vec3(1f)
      val offsets = vec3(0.5f, 0f, 0f)
      igPallette(brightness, contrast, freq, offsets, f)

In here a basis orthogonal to the reflected ray direction is created so that an offset for the reflection can be taken. Then, the offset is sampled uniformly from a disk. This simulates the imperfections in reflections in real life by making the reflection direction be more random. Multiple samples are taken to make the result closer to how a real world object would look like.

GSeq.gen(
          first = RayState(nextRayPos, reflectDir, sampleEnvironment(reflectDir) * (1f / REFLECTION_SAMPLES), random),
          next = {
            case state@RayState(rayPos, rayDir, color, random) =>
              val (rand1, angle) = random.next[Float32]
              val (rand2, scale) = rand1.next[Float32]
              val sqrScale = sqrt(scale) / 2f
              val firstBasis = getOrthogonal(rayDir, hitInfo.normal)
              val secondBasis = getOrthogonal(firstBasis, rayDir)
              val wiggle = (firstBasis * sin(angle) + secondBasis * cos(angle)) * sqrScale
              val newSample = sampleEnvironment(normalize(rayDir + wiggle))
              RayState(
                rayPos = rayPos,
                rayDir = rayDir,
                color = color + newSample * (1f / REFLECTION_SAMPLES),
                random = rand2
              )
          }
        ).limit(REFLECTION_SAMPLES).lastOr(
          RayState(vec3(0f), vec3(0f), vec3(0f), random)
        )

Raytraced Solar System:

The visualization showcases something similar to Earth's orbit around the Sun and how the Moon can cause solar eclipses. It is all done using the existing raytracing implementation.

solar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant