Merge Sdf With Mesh - aiekick/NoodlesPlate GitHub Wiki
With NoodlesPlate you can merge any sdf with any mesh.
You need some things :
- you need to use the same camera matrix for the mesh and for the sdf rendering
- you need to define the depth value of the current pixel according to your sdf
that's all, Opengl wil merge himself perfectly the mesh and the current fbo (where you sdf is rendered)
NoodlesPlate help a lot for this task :
Consider this minimal Sdf Shader :
@UNIFORMS
uniform vec2(buffer) size;
@VERTEX
layout(location = 0) in vec2 a_position; // Current vertex position
out vec2 uv;
void main()
{
uv = a_position * 2.0 - 1.0;
gl_Position = vec4(uv, 0.0, 1.0);
}
@FRAGMENT
layout(location = 0) out vec4 fragColor;
in vec2 uv;
float map(vec3 p)
{
return length(p) - 1.;
}
vec3 getNor(vec3 p, float k)
{
vec3 eps = vec3(k, 0., 0.);
vec3 nor = vec3(
map(p + eps.xyy) - map(p - eps.xyy),
map(p + eps.yxy) - map(p - eps.yxy),
map(p + eps.yyx) - map(p - eps.yyx));
return normalize(nor);
}
void main(void)
{
vec2 v = uv; v.x *= size.x/size.y;
vec3 ro = vec3(0,0,-5);
vec3 rd = normalize(vec3(v,1));
vec3 col = vec3(0.0);
float s = 1., d = 0., md = 50.;
for (int i = 0; i < 100; i++)
{
if (s < 0.001 || d > 50.) break;
s = map(ro + rd * d);
d += s * 0.8;
}
if (d < md)
{
vec3 p = ro + rd * d;
vec3 n = getNor(p, 0.01);
col = n * 0.5 + 0.5;
}
fragColor = vec4(col,1);
}
you get that :
Use the world camera for ray origin and ray direction.
First, Insert << #include "space3d.glsl" >> just after the tag @FRAGMENT
@FRAGMENT
#include "space3d.glsl"
Then, replace the lines
vec3 ro = vec3(0,0,-5);
vec3 rd = normalize(vec3(v,1));
by
vec3 ro = getRayOrigin();
vec3 rd = getRayDirection();
after code save, you get the hability to use camera for :
- rotate around y axis with left mouse
- zoom with the right button
- the camera pane is in the panel Config
Get Backgroud Color and avoid useless calculation
you can "discard" when no hit on the sdf.
just add the case "no hit" in the hit condition :
if (d < md)
{
vec3 p = ro + rd * d;
vec3 n = getNor(p, 0.01);
col = n * 0.5 + 0.5;
}
else
{
discard;
}
after code save, you will get that (you can tune bakcground color in the main menu bar)
show the the grid and axis system to see the merging : fo in Menu Settings -> Show 3D Space
so you get :
compute the depth value of current pixel for have nice merge
just add the function CalcDepth after the distance estimation :
you pass in argument, the ray direction vecotr and your computed distahce to sdf
float s = 1., d = 0., md = 50.;
for (int i = 0; i < 100; i++)
{
if (s < 0.001 || d > 50.) break;
s = map(ro + rd * d);
d += s * 0.8;
}
CalcDepth(rd, d);
after code save you will get that
See the mesh perfeclty merged with your sdf shape
If you want open a mesh to MErge with your SDf :
you can show the Mesh Shader : fo in Menu Settings -> Show Mesh
go in config pane, open Section Config and SubSection 3d Mesh
go in part "Mesh Settings" and open a 3D Model. (for the moment, you can open only obj file with trangle face)
you will get that :
i increased the radius fo the sphere for show the merging with beethoven :)