Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fog fixed distance to island & override ThreeJS fog shader #151

Merged
merged 10 commits into from
Mar 9, 2025

Conversation

toddeTV
Copy link
Owner

@toddeTV toddeTV commented Mar 5, 2025

Resolves #95
❤️ Pair-Programmed with @Myzios

Not used idea

One giant torus around the scene that has a ray marching depth gradient shader so that the inner has 100% transparency all the way to the outer with 0% transparency. That is very resource hungry and also not really possible in ThreeJS.

Used idea

The ThreeJS fog is a shader applied to every material. Unfortunately, the material.fog is true by default, making every material simulating a fog when one is present in the scene.
Patching ThreeJS and setting the default to false would be an option, but we do not use the declarative approach from TresJS with automatic adding to scenes, but the imperative way with our addToGroup or addShadowAndAddToGroup functions. So we could add functionality to disable the fog shader on a material and do this per default in our add to group functions:

export function removeFogDependence(
object: Object3D,
) {
object.traverse((child) => {
if (child instanceof Mesh) {
child.material.fog = false
}
})
}

export function addToGroup(
group: Scene | Group | Object3D,
object: Object3D,
objectEnableFog = false,
) {
if (objectEnableFog === false) {
removeFogDependence(object)
}
group.add(object)
}

Now we could override the default fog shader in order to stick to a fixed position in the scene and not be dependent on the camera position by modifying each shader that should be effected by a fog:

export function overrideFogShader(
shader: WebGLProgramParametersWithUniforms,
fogCenter = new Vector3(0, 0, 0),
fogDistanceOffset = 0,
) {
shader.vertexShader = shader.vertexShader.replace(
`#include <fog_pars_vertex>`,
`#include <fog_pars_vertex>
#ifdef USE_FOG
// the center of the fog is set here, but bc it is the world center, we do not have do do anything
uniform vec3 fogCenter;
#endif
`,
)
shader.vertexShader = shader.vertexShader.replace(
`#include <project_vertex>`,
`
#ifdef USE_FOG
vec3 vertexWorldPosition = (modelMatrix * vec4(transformed, 1.0)).xyz;
vFogDepth = distance(fogCenter.xz, vertexWorldPosition.xz) + ${fogDistanceOffset.toFixed(1)};
#endif
#include <project_vertex>`,
)
shader.vertexShader = shader.vertexShader.replace(
`#include <fog_vertex>`,
``,
)
const uniforms = ({
fogCenter: { value: fogCenter },
})
shader.uniforms = UniformsUtils.merge([shader.uniforms, uniforms])
}

This new fog shader mechanism was added to the Ocean and the SeaBed (see use of function overrideFogShader).

Known Problems

  • The new fog shader uses the vertices for calculating if they are inside or outside the fog. Therefore, e.g. a big plane with all vertices outside the fog but the face running through the inside of the fog is calculated as outside. So be aware to subdivide large planes (like the sea bed) into small triangles so that the vertices are also inside the fog.
  • Adding meshes with the declarative approach of TresJS will per default set the fog shader on the material. So use the imperative approach with our helper functions addToGroup or addShadowAndAddToGroup, or set the fog on the material manually to false.
  • ⚠️ You must now Opt-In a material to be fog dependent when using our functions addToGroup or addShadowAndAddToGroup, but not when using a normal scene add imperative or TresJS declerative addition.
  • We do not have a solid ocean bc it is only a plane faking to be water. So there is always a spot in the distance where the ocean floor is "shorter" than the ocean above it. This depends on the angle of the camera and the flatter the camera is, the more you can see this. Without the fog this is very clear:
    grafik
    This is also weird with the fog bc the two planes (ocean & ocean floor) are not the same length from the perspective of the camera:
    grafik
    So we apply a shorter fog shader to the ocean than to the ocean floor in order to make it more even. But the camera can be tilted and the current offset is a fixed value. So this effect is sometimes better & sometimes worse depending on the angle of the camera. We tried finding a nice sweet spot but ignore a very strong angle. The more from above the camera looks, the better.
    grafik
    grafik

@toddeTV toddeTV changed the title feat: add fog feat: fog with fixed distance to island Mar 5, 2025
@toddeTV toddeTV changed the title feat: fog with fixed distance to island feat: add fog with fixed distance to island Mar 5, 2025
@toddeTV toddeTV requested review from Myzios and fehnomenal March 5, 2025 22:05
Copy link
Collaborator

@fehnomenal fehnomenal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visually the fog looks very nice, good job!

Am I missing something or are the ocean waves no longer animated?

@toddeTV
Copy link
Owner Author

toddeTV commented Mar 7, 2025

Am I missing something or are the ocean waves no longer animated?

You didn't see anything 🙈 ...

jokes aside, you're absolutely right. Thanks for the catch - that slipped through my fingers while I was too focused on the fog 😅 I fixed it right away.

@toddeTV toddeTV requested a review from fehnomenal March 7, 2025 09:20
Copy link
Collaborator

@fehnomenal fehnomenal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay 😅

@toddeTV toddeTV changed the title feat: add fog with fixed distance to island feat: fog fixed distance to island & override ThreeJS fog shader Mar 9, 2025
@toddeTV toddeTV merged commit 1613211 into main Mar 9, 2025
1 check passed
@toddeTV toddeTV deleted the feat/distance-fog branch March 9, 2025 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: set fog in relation to island (fixed fog distance)
2 participants