Skip to content

Merge Sdf With Mesh

Aiekick edited this page Jul 14, 2019 · 1 revision

With NoodlesPlate you can merge any sdf with any mesh.

You need some things :

  1. you need to use the same camera matrix for the mesh and for the sdf rendering
  2. 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 :

NoodlesPlate_MSVC_Debug_2019-07-13_22-10-27

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

NoodlesPlate_MSVC_Debug_2019-07-13_22-21-02

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 :

NoodlesPlate_MSVC_x64_Release_2019-07-13_22-54-23

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

NoodlesPlate_MSVC_x64_Release_2019-07-13_22-55-56

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 :

2019-07-13_23-07-39

i increased the radius fo the sphere for show the merging with beethoven :)

Clone this wiki locally