Skip to content

Commit

Permalink
Add normal and sun ray to raymarched value noise field
Browse files Browse the repository at this point in the history
  • Loading branch information
vhiribarren committed Jan 10, 2024
1 parent 346b8d8 commit 479fa20
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
38 changes: 33 additions & 5 deletions src/app/raymarching/value-noise-field/fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma glslify: random = require(../../../glsl-modules/random)

uniform int u_view_type;
uniform bool u_with_gizmos;
uniform uint u_freq_count;
uniform float u_freq_base;
Expand All @@ -17,8 +18,13 @@ uniform float u_yaw;

varying vec2 v_uv;

const vec3 SUN_DIRECTION = normalize(vec3(1.0, 0.0, -1.0));
const float AXIS_LINE_PRECISION = 0.01;

const int VIEW_SUN_RAYS = 0;
const int VIEW_NORMALS = 1;
const int VIEW_DEPTH = 2;


float average_noise_smoothstep(vec2 scaled_uv) {
vec2 percent = smoothstep(vec2(0.), vec2(1.), fract(scaled_uv));
Expand All @@ -45,13 +51,25 @@ float fbm(vec2 uv, float freq_base, uint freq_count, float gain, float lacunarit
return noise_val/total_amplitude;
}

float field_height(vec2 uv) {
float field_height(vec2 uv) {
// TODO: scale field
return fbm(uv, u_freq_base, u_freq_count, u_gain, u_lacunarity);
}

//float field_height(vec2 uv) {
// return random(floor(uv* u_freq_base)) ;
//}
vec3 field_normal(vec2 uv) {
// We compute the gradient of F(x, y, z) = field_heigh(x, y) - z = 0
// It is a level set for which the normal is the gradient
// Derivate is approximated using central difference ((f(x+h) - f(x-h)) / (2h) with h tiny)
// https://stackoverflow.com/questions/49640250/calculate-normals-from-heightmap
// https://en.wikipedia.org/wiki/Level_set#Level_sets_versus_the_gradient
// https://math.stackexchange.com/questions/2459214/is-the-gradient-a-surface-normal-vector-or-does-it-point-in-the-direction-of-max
vec2 e = vec2(0.00001, 0.0);
return normalize(vec3(
field_height(uv + e.xy) - field_height(uv - e.xy),
field_height(uv + e.yx) - field_height(uv - e.yx),
-2.0*e.x
));
}

vec3 raymarch_scene(vec3 ray_origin, vec3 ray_direction) {
float raymarch_dist = 0.0;
Expand All @@ -62,7 +80,16 @@ vec3 raymarch_scene(vec3 ray_origin, vec3 ray_direction) {
vec3 scan_pos = ray_origin + raymarch_dist * ray_direction;
float field_z = field_height(scan_pos.xy);
if (scan_pos.z <= field_z) {
return vec3(1.0 - float(i) / float(u_raymarch_max_steps));
// TODO: need to better interpolate right intersection point when using increasing steps
switch (u_view_type) {
case VIEW_NORMALS:
return abs(field_normal(scan_pos.xy));
case VIEW_SUN_RAYS:
return vec3(dot(field_normal(scan_pos.xy), SUN_DIRECTION));
case VIEW_DEPTH:
default:
return vec3(1.0 - float(i) / float(u_raymarch_max_steps));
}
}
if (u_with_gizmos) {
// Origin
Expand Down Expand Up @@ -129,4 +156,5 @@ void main() {
vec3 color = raymarch_scene(ray_origin, ray_dir);

gl_FragColor = vec4(color, 1.0);

}
16 changes: 15 additions & 1 deletion src/app/raymarching/value-noise-field/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
"use client";

import { NumberInput, Switch } from "@mantine/core";
import { NumberInput, Select, Switch } from "@mantine/core";
import fragmentShader from "./fragment.glsl";
import { FragmentLogic, FragmentView } from "@/components/shaders/FragmentView";
import styles from "../../../styles/shaderControl.module.css";
import { useUniform } from "@/components/shaders/uniforms";


const VIEW_TYPE = ["Sun Rays", "Normal Field", "Depth Field"];


function ValueNoiseRaymarchControl({controlUiTunnel}: FragmentLogic) {

const [viewType, setViewType] = useUniform<number>("u_view_type", 0);

const [gizmos, setGizmos] = useUniform("u_with_gizmos", false);

const [freqCount, setFreqCount] = useUniform("u_freq_count", 8);
Expand All @@ -33,6 +39,14 @@ function ValueNoiseRaymarchControl({controlUiTunnel}: FragmentLogic) {
return (
<ControlUiTunnel>
<div className={styles.shaderControlWrapper}>
<Select
className={styles.shaderControl}
label="View type"
placeholder="Pick value"
data={VIEW_TYPE}
value={VIEW_TYPE[viewType]}
onChange={(e) => setViewType(VIEW_TYPE.indexOf(e!))}
/>
<NumberInput className={styles.shaderControl} label="Number of frequences" onChange={setFreqCount} value={freqCount} min={1} max={10} allowDecimal={false} />
<NumberInput className={styles.shaderControl} label="Base frequence" onChange={setFreqBase} value={freqBase} min={0.0} decimalScale={2} />
<NumberInput className={styles.shaderControl} label="Lacunarity" onChange={setLacunarity} value={lacunarity} min={0.0} step={0.1} decimalScale={2} />
Expand Down

0 comments on commit 479fa20

Please sign in to comment.