Jump to content
Sign in to follow this  
konstantin magnus

Ray marching in COPs

Recommended Posts

Posted (edited)

A basic ray marching / sphere tracing renderer written in VEX inside COPs.

rm_sshot.thumb.jpg.6f5fac4d19c944e02abbbc0100586f41.jpg

Entirely based on a shader toy-tutorial by Martijn Steinrucken / @The_ArtOfCode:
https://odysee.com/@TheArtOfCode:b/ray-marching-for-dummies:f

// SCENE
function float get_dist(vector pos){
    vector pos_sphere = set(sin(TIME), 1.55, 6.0);
    float radius_sphere = 0.75;
    float dist_sphere = length(pos - pos_sphere) - radius_sphere;
    float height_plane = noise(pos * 2.75) * 0.2;
    float dist_plane = pos.y - height_plane;
    float dist_min = min(dist_sphere, dist_plane);
    return dist_min;
}

// TRACING
function float raymarch(vector pos_cam, dir_cam){
    float dist_orig = 0.0;
    float dist_srf = 1e-3;
    float dist_max = 1e1;
    int steps_max = 200;
    for(int i = 0; i < steps_max; i++){
        vector pos = pos_cam + dir_cam * dist_orig;
        float dist_scene = get_dist(pos);
        dist_orig += dist_scene;
        if(dist_scene < dist_srf || dist_scene > dist_max){
            break;
        }
    }
    return dist_orig;
}

// NORMALS
function vector get_normal(vector pos){
    vector offset = {0.01, 0.0, 0.0};
    float dist = get_dist(pos);
    float dx = get_dist(pos - offset.xyy);
    float dy = get_dist(pos - offset.yxy);
    float dz = get_dist(pos - offset.yyx);
    vector nml = normalize(dist - set(dx, dy, dz));
    return nml;
}

// LIGHTING
function float get_light(vector pos){
    vector pos_light = set(1.0, 4.0, 3.0);
    pos_light.x += sin(TIME*8);
    pos_light.z += cos(TIME*8);
    vector dir_light = normalize(pos_light - pos);
    vector nml_srf = get_normal(pos);
    float amount = max(dot(nml_srf, dir_light), 0.0);
    float dist = raymarch(pos + nml_srf * 1e-1, dir_light);
    if(dist < length(pos_light - pos)){
        amount *= 0.2;
    }
    return amount;
}

// CANVAS
float aspect = XRES / float(YRES);
vector uvw = set(X - 0.5, (Y - 0.5) / aspect, 0.0);

// CAMERA
vector pos_cam = {0.0, 1.5, 0.0};
vector dir_cam = normalize(set(uvw.x, uvw.y, 1.0));

// PROCESS
float dist_field = raymarch(pos_cam, dir_cam);
vector pos_world = pos_cam + dir_cam * dist_field;
float diffuse = get_light(pos_world);
float mask_clip = dist_field < 55.0;

// OUTPUT
vector color = diffuse * mask_clip;
assign(R, G, B, color);

ray_marching.hipnc

Edited by konstantin magnus
added ambient occlusion
  • Like 5

Share this post


Link to post
Share on other sites

Thank you @animatrix.
Currently expanding it into a constructive solid geometry (CSG) stack tool.
It can even write to a 3d volume while it creates a really crisp rendering. :D

CSG.thumb.jpg.1f1e55ccb0c875815e80fe13bcd751ab.jpg

  • Like 2

Share this post


Link to post
Share on other sites
Posted (edited)

Basically you reconstruct houdini inside houdini :D !

Edited by flcc
  • Haha 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×