DFGI test

This commit is contained in:
Lubos Lenco 2017-08-02 11:46:54 +02:00
parent bb7ec8ecf8
commit 9f62011ffc
9 changed files with 209 additions and 107 deletions

View file

@ -45,7 +45,7 @@ uniform float envmapStrength;
uniform vec3 eyeLook;
#endif
#ifdef _DFAO
//!uniform sampler2D sdftex;
//!uniform sampler3D sdftex;
#endif
in vec2 texCoord;
@ -103,7 +103,7 @@ void main() {
// return;
#endif
// Envmap
#ifdef _Irr
vec3 envl = shIrradiance(n, 2.2) / PI;
@ -136,6 +136,10 @@ void main() {
envl.rgb *= envmapStrength * g1.a; // Occlusion
#endif
#ifdef _DFGI
envl.rgb = dfgi(p, n) * albedo;
#endif
#ifdef _SSAO
envl.rgb *= texture(ssaotex, texCoord).r;
#endif

View file

@ -49,7 +49,7 @@ uniform sampler2D gbuffer1;
#endif
#endif
#ifdef _DFRS
//!uniform sampler2D sdftex;
//!uniform sampler3D sdftex;
#endif
uniform mat4 invVP;
@ -152,69 +152,7 @@ void main() {
#endif
#ifdef _DFRS
const float distmax = 40.0;
const float eps = 0.02;
const int maxSteps = 30;
float dist = 0.2;
// float test = mapsdf2(p);
// if (test < 0.1) {
// fragColor = vec4(1.0, 0.0, 0.0, 1.0);
// return;
// }
float lastd = distmax;
for (int i = 0; i < maxSteps; i++) {
vec3 rd = l * dist;
float d = sdBox(p + rd, vec3(1.0));
// Going out of volume box
// if (d > 0.0 && lastd < d) {
// break;
// }
// lastd = d;
if (d <= 0.0) { // In volume
d = mapsdf(p, rd);
if (d < eps) {
visibility = 0.0;
break;
}
}
else { // To volume
// d += mapsdf(p, rd);
vec3 sampleBorder = clamp(p + rd, vec3(-1.0), vec3(1.0));
float phi = mapsdf2(sampleBorder, rd);
float dd = 0.1;
float grad_x = mapsdf2(sampleBorder + vec3(dd, 0, 0), rd) - phi;
float grad_y = mapsdf2(sampleBorder + vec3(0, dd, 0), rd) - phi;
vec3 grad = vec3(grad_x, grad_y, 1.0);
vec3 endpoint = sampleBorder - normalize(grad) * phi;
d = distance(endpoint, p + rd);
// float dd = 0.1;
// vec3 p0 = clamp(p, vec3(-1.0), vec3(1.0));
// vec3 p1 = clamp(p, vec3(-0.99), vec3(0.99));
// float r0 = mapsdf2(p0, rd);
// float r1 = mapsdf2(p1, rd);
// float h0 = 0.5 + (r0 * r0 - r1 * r1) / (2.0 * dd * dd);
// float ri = sqrt(abs(r0 * r0 - h0 * h0 * dd * dd));
// vec3 p2 = p0 + (p1 - p0) * h0;
// vec3 p3 = p2 + vec3(p1.z - p0.z, p1.y - p0.y, p1.x - p0.x) * ri;
// d = length((p + rd) - p3);
}
const float k = 1.0;
visibility = min(visibility, (k * d / dist));
dist += d;
if (dist > distmax) {
break;
}
}
visibility = dfrs(p, l, lightPos);
#endif
// Per-light

View file

@ -1,44 +1,29 @@
const float res = 50.0; // sdftex res
uniform sampler2D sdftex;
uniform sampler3D sdftex;
float mapsdf(vec3 ro, vec3 rd) {
vec3 p = ro + rd;
float mapsdf(vec3 p) {
p = clamp(p, vec3(-1.0), vec3(1.0));
p = p * 0.5 + 0.5;
float s1 = (p.z * res);
float s2 = int(s1);
float s = s2 - s1;
float m = sign(rd.z) > 0.0 ? s : (1.0 - s);
vec2 co = vec2(p.x / res + s2 / res, p.y);
float dist = (texture(sdftex, co).r) * m;
co.x += 1 / res * sign(rd.z);
dist += (texture(sdftex, co).r) * (1.0 - m);
return dist;
return texture(sdftex, p).a;
}
float mapsdf2(vec3 p, vec3 rd) {
// p = p * 0.5 + 0.5;
// float s = int(p.z * res);
// vec2 co = vec2(p.x / res + s / res, p.y);
// return texture(sdftex, co).r;
vec4 mapsdf2(vec3 p) {
p = clamp(p, vec3(-1.0), vec3(1.0));
p = p * 0.5 + 0.5;
float s1 = (p.z * res);
float s2 = int(s1);
float s = s2 - s1;
return texture(sdftex, p);
}
float m = sign(rd.z) > 0.0 ? s : (1.0 - s);
vec2 co = vec2(p.x / res + s2 / res, p.y);
float dist = texture(sdftex, co).r * m;
vec3 calcNormal(const vec3 pos, const float eps) {
const vec3 v1 = vec3( 1.0,-1.0,-1.0);
const vec3 v2 = vec3(-1.0,-1.0, 1.0);
const vec3 v3 = vec3(-1.0, 1.0,-1.0);
const vec3 v4 = vec3( 1.0, 1.0, 1.0);
co.x += 1 / res * sign(rd.z);
dist += (texture(sdftex, co).r) * (1.0 - m);
return dist;
return normalize(v1 * mapsdf(pos + v1 * eps) +
v2 * mapsdf(pos + v2 * eps) +
v3 * mapsdf(pos + v3 * eps) +
v4 * mapsdf(pos + v4 * eps));
}
float sdBox(vec3 p, vec3 b) {
@ -47,6 +32,7 @@ float sdBox(vec3 p, vec3 b) {
}
float dfao(const vec3 p, const vec3 n) {
const float eps = 0.02;
float occ = 0.0;
float sca = 1.0;
for (int i = 0; i < 10; i++) {
@ -55,14 +41,15 @@ float dfao(const vec3 p, const vec3 n) {
vec3 sp = rd + p;
float d;
if (sdBox(sp, vec3(1.0)) <= 0.0) {
d = mapsdf(sp, rd);
d = mapsdf(sp + rd);
// if (d < eps) break;
}
else {
vec3 sampleBorder = clamp(sp, vec3(-1.0), vec3(1.0));
float phi = mapsdf2(sampleBorder, rd);
float phi = mapsdf(sampleBorder);
float dd = 0.1;
float grad_x = mapsdf2(sampleBorder + vec3(dd, 0, 0), rd) - phi;
float grad_y = mapsdf2(sampleBorder + vec3(0, dd, 0), rd) - phi;
float grad_x = mapsdf(sampleBorder + vec3(dd, 0, 0)) - phi;
float grad_y = mapsdf(sampleBorder + vec3(0, dd, 0)) - phi;
vec3 grad = vec3(grad_x, grad_y, 1.0);
vec3 endpoint = sampleBorder - normalize(grad) * phi;
d = distance(endpoint, sp);
@ -70,5 +57,151 @@ float dfao(const vec3 p, const vec3 n) {
occ += (r - d) * sca;
sca *= 0.85;
}
return clamp(1.0 - occ / (3.14), 0.0, 1.0);
return clamp(1.0 - occ / (2.14), 0.0, 1.0);
}
// float dfrs(const vec3 p, const vec3 l) {
float dfrs(const vec3 p, const vec3 l, const vec3 lp) {
float visibility = 1.0;
const float distmax = 10.0;
const float eps = 0.01;
float dist = 0.05;
// float test = mapsdf(p);
// if (test < 0.1) {
// fragColor = vec4(1.0, 0.0, 0.0, 1.0);
// return;
// }
// float lastd = distmax;
for (int i = 0; i < 50; i++) {
vec3 rd = l * dist;
float d = sdBox(p + rd, vec3(1.0));
// Going out of volume box
// if (d > 0.0 && lastd < d) {
// visibility = 1.0;
// break;
// }
// lastd = d;
if (d <= 0.0) { // In volume
d = mapsdf(p + rd);
// if (distance(p + rd, lp) < 0.05) { // Hits light pos
if (dist + d > distance(p, lp) - 0.05) {
// visibility = 1.0;
break;
}
if (d < eps) {
visibility = 0.0;
break;
}
}
else { // To volume
// d += mapsdf(p + rd);
vec3 sampleBorder = clamp(p + rd, vec3(-1.0), vec3(1.0));
float phi = mapsdf(sampleBorder);
float dd = 0.1;
float grad_x = mapsdf(sampleBorder + vec3(dd, 0, 0)) - phi;
float grad_y = mapsdf(sampleBorder + vec3(0, dd, 0)) - phi;
vec3 grad = vec3(grad_x, grad_y, 1.0);
vec3 endpoint = sampleBorder - normalize(grad) * phi;
d = distance(endpoint, p + rd);
// float dd = 0.1;
// vec3 p0 = clamp(p, vec3(-1.0), vec3(1.0));
// vec3 p1 = clamp(p, vec3(-0.99), vec3(0.99));
// float r0 = mapsdf(p0);
// float r1 = mapsdf(p1);
// float h0 = 0.5 + (r0 * r0 - r1 * r1) / (2.0 * dd * dd);
// float ri = sqrt(abs(r0 * r0 - h0 * h0 * dd * dd));
// vec3 p2 = p0 + (p1 - p0) * h0;
// vec3 p3 = p2 + vec3(p1.z - p0.z, p1.y - p0.y, p1.x - p0.x) * ri;
// d = length((p + rd) - p3);
}
const float k = 4.0;
visibility = min(visibility, k * d / dist);
dist += d;
if (dist > distmax) {
break;
}
}
return visibility;
}
vec3 orthogonal(const vec3 u) {
// Pass normalized u
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector
return abs(dot(u, v)) > 0.99999 ? cross(u, vec3(0.0, 1.0, 0.0)) : cross(u, v);
}
vec3 traceCone(const vec3 p, const vec3 n) {
vec3 col = vec3(0.0);
const float eps = 0.02;
float dist = 0.05;
for (int i = 0; i < 10; i++) {
vec3 rd = n * dist;
float d = sdBox(p + rd, vec3(1.0));
if (d <= 0.0) {
vec4 res = mapsdf2(p + rd);
d = res.a;
if (d < eps) {
// float vis = dfrs(p + rd, l, lp);
// vec3 hitn = calcNormal(p + rd, 0.002);
// float diffuse = max(0.0, dot(hitn, l));// / dot(l,l);
col = res.rgb * max(1.0 - dist, 0.0);// * diffuse;// * vis;
break;
}
}
dist += d;
}
return col;
}
vec3 dfgi(const vec3 p, const vec3 n) {
const float ANGLE_MIX = 0.5; // Angle mix (1.0f -> orthogonal direction, 0.0f -> direction of normal)
const float w[3] = { 1.0, 1.0, 1.0 }; // Cone weights
// Find a base for the side cones with the normal as one of its base vectors
const vec3 ortho = normalize(orthogonal(n));
const vec3 ortho2 = normalize(cross(ortho, n));
// Find base vectors for the corner cones
const vec3 corner = 0.5 * (ortho + ortho2);
const vec3 corner2 = 0.5 * (ortho - ortho2);
// Find start position of trace (start with a bit of offset)
const vec3 offset = 0.0 * n;
const vec3 origin = p + offset;
vec3 col = vec3(0.0);
const float CONE_OFFSET = 0.0;//-0.01;
col += w[0] * traceCone(origin + CONE_OFFSET * n, n);
const vec3 s1 = mix(n, ortho, ANGLE_MIX);
const vec3 s2 = mix(n, -ortho, ANGLE_MIX);
const vec3 s3 = mix(n, ortho2, ANGLE_MIX);
const vec3 s4 = mix(n, -ortho2, ANGLE_MIX);
col += w[1] * traceCone(origin + CONE_OFFSET * ortho, s1);
col += w[1] * traceCone(origin - CONE_OFFSET * ortho, s2);
col += w[1] * traceCone(origin + CONE_OFFSET * ortho2, s3);
col += w[1] * traceCone(origin - CONE_OFFSET * ortho2, s4);
const vec3 c1 = mix(n, corner, ANGLE_MIX);
const vec3 c2 = mix(n, -corner, ANGLE_MIX);
const vec3 c3 = mix(n, corner2, ANGLE_MIX);
const vec3 c4 = mix(n, -corner2, ANGLE_MIX);
col += w[2] * traceCone(origin + CONE_OFFSET * corner, c1);
col += w[2] * traceCone(origin - CONE_OFFSET * corner, c2);
col += w[2] * traceCone(origin + CONE_OFFSET * corner2, c3);
col += w[2] * traceCone(origin - CONE_OFFSET * corner2, c4);
return col / 9.0;
}

View file

@ -1931,6 +1931,15 @@ class ArmoryExporter:
sdk_path = arm.utils.get_sdk_path()
sdfgen_path = sdk_path + '/armory/tools/sdfgen'
shutil.copy(fp, sdfgen_path + '/krom/mesh.arm')
# Extract basecolor
# Assume Armpry PBR with linked texture for now
# mat = bobject.material_slots[0].material
# img = None
# for n in mat.node_tree.nodes:
# if n.type == 'GROUP' and n.node_tree.name.startswith('Armory PBR') and n.inputs[0].is_linked:
# img = n.inputs[0].links[0].from_node.image
# fp_img = bpy.path.abspath(img.filepath)
# shutil.copy(fp_img, sdfgen_path + '/krom/mesh.png')
# Run
krom_location, krom_path = arm.utils.krom_paths()
krom_dir = sdfgen_path + '/krom'
@ -1942,6 +1951,8 @@ class ArmoryExporter:
assets.add(sdf_path)
os.remove('out.bin')
os.remove(sdfgen_path + '/krom/mesh.arm')
# if img != None:
# os.remove(sdfgen_path + '/krom/mesh.png')
def export_mesh_quality(self, exportMesh, bobject, fp, o):
# Triangulate mesh and remap vertices to eliminate duplicates

View file

@ -101,6 +101,11 @@ def build_node_tree(world):
if cam.rp_dfao:
wrd.world_defs += '_DFAO'
assets.add_khafile_def('arm_sdf')
if cam.rp_dfgi:
wrd.world_defs += '_DFGI'
assets.add_khafile_def('arm_sdf')
wrd.world_defs += '_Rad' # Always do radiance for gi
wrd.world_defs += '_Irr'
if voxelgi:
assets.add_khafile_def('arm_voxelgi')

View file

@ -371,6 +371,7 @@ def init_properties():
bpy.types.Camera.rp_ssr = bpy.props.BoolProperty(name="SSR", description="Screen space reflections", default=False, update=update_renderpath)
bpy.types.Camera.rp_dfao = bpy.props.BoolProperty(name="DFAO", description="Distance field ambient occlusion", default=False)
bpy.types.Camera.rp_dfrs = bpy.props.BoolProperty(name="DFRS", description="Distance field ray-traced shadows", default=False)
bpy.types.Camera.rp_dfgi = bpy.props.BoolProperty(name="DFGI", description="Distance field global illumination", default=False)
bpy.types.Camera.rp_bloom = bpy.props.BoolProperty(name="Bloom", description="Bloom processing", default=False, update=update_renderpath)
bpy.types.Camera.rp_rendercapture = bpy.props.BoolProperty(name="Render Capture", description="Save output as render result", default=False, update=update_renderpath)
bpy.types.Camera.rp_rendercapture_format = EnumProperty(

View file

@ -42,6 +42,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = False
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -69,6 +70,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = True
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -95,6 +97,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = False
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -121,6 +124,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = True
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -150,6 +154,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = True
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = True
cam.rp_rendercapture_format = '8bit'
@ -179,6 +184,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = True
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -206,6 +212,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = False
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -233,6 +240,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = False
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -259,6 +267,7 @@ def set_preset(self, context, preset):
cam.rp_ssr = False
cam.rp_dfrs = False
cam.rp_dfao = False
cam.rp_dfgi = False
cam.rp_bloom = False
cam.rp_rendercapture = False
cam.rp_motionblur = 'None'
@ -341,8 +350,9 @@ class GenRPDataPropsPanel(bpy.types.Panel):
layout.prop(dat, "rp_volumetriclight")
layout.prop(dat, "rp_ssao")
layout.prop(dat, "rp_ssr")
layout.prop(dat, "rp_dfao")
layout.prop(dat, "rp_dfrs")
# layout.prop(dat, "rp_dfao")
# layout.prop(dat, "rp_dfrs")
# layout.prop(dat, "rp_dfgi")
layout.prop(dat, "rp_bloom")
layout.prop(dat, "rp_motionblur")
layout.prop(dat, "rp_rendercapture")

View file

@ -6,8 +6,8 @@
"render_targets": [
{
"name": "sdf",
"width": 2500,
"height": 50,
"width": 50,
"height": 2500,
"format": "A32"
}
],

File diff suppressed because one or more lines are too long