Dynamic camera for voxels

This commit is contained in:
Lubos Lenco 2017-10-12 12:12:48 +02:00
parent 68b7380785
commit 2985ea60d0
11 changed files with 173 additions and 129 deletions

View file

@ -27,9 +27,11 @@ uniform sampler2D gbuffer1;
#ifdef _VoxelGI
//!uniform sampler3D voxels;
uniform vec3 eyeSnap;
#endif
#ifdef _VoxelAO
//!uniform sampler3D voxels;
uniform vec3 eyeSnap;
#endif
uniform float envmapStrength;
@ -90,24 +92,27 @@ void main() {
#ifdef _VoxelGI
#ifdef _VoxelGICam
const float step = voxelgiDimensions / voxelgiResolution;
vec3 eyeSnap = ivec3(eye / step) * step;
vec3 wpos = (p - eyeSnap) / voxelgiDimensions;
vec3 voxpos = (p - eyeSnap) / voxelgiHalfExtents;
#else
vec3 wpos = p / voxelgiDimensions;
vec3 voxpos = p / voxelgiHalfExtents;
#endif
vec4 indirectDiffuse = traceDiffuse(wpos, n);
vec3 indirectSpecular = traceSpecular(wpos, n, v, metrough.y);
vec4 indirectDiffuse = traceDiffuse(voxpos, n);
vec3 indirectSpecular = traceSpecular(voxpos, n, v, metrough.y);
indirectSpecular *= f0 * envBRDF.x + envBRDF.y;
indirectSpecular = vec3(0.0);
fragColor.rgb = indirectDiffuse.rgb * voxelgiDiff * g1.rgb + indirectSpecular * voxelgiSpec;
// if (!isInsideCube(voxpos)) fragColor = vec4(1.0); // Show bounds
#ifdef _SSAO
fragColor.rgb *= texture(ssaotex, texCoord).r * 0.5 + 0.5;
#endif
// float opacity = g1.a;
// if (opacity < 1.0) fragColor.rgb = mix(indirectRefractiveLight(-v, n, vec3(1.0), opacity, wpos), fragColor.rgb, opacity);
// if (opacity < 1.0) fragColor.rgb = mix(indirectRefractiveLight(-v, n, vec3(1.0), opacity, voxpos), fragColor.rgb, opacity);
// return;
#endif
@ -162,8 +167,14 @@ void main() {
#endif
#ifdef _VoxelAO
vec3 wpos = p / voxelgiDimensions;
envl.rgb *= 1.0 - traceAO(wpos, n);
#ifdef _VoxelGICam
vec3 voxpos = (p - eyeSnap) / voxelgiHalfExtents;
#else
vec3 voxpos = p / voxelgiHalfExtents;
#endif
envl.rgb *= 1.0 - traceAO(voxpos, n);
#endif
#ifdef _VoxelGI
@ -171,4 +182,14 @@ void main() {
#else
fragColor.rgb = envl;
#endif
// Show voxels
// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
// vec3 direction = vec3(0.0, 0.0, -1.0);
// vec4 color = vec4(0.0f);
// for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
// vec3 point = origin + 0.005 * step * direction;
// color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
// }
// fragColor.rgb += color.rgb;
}

View file

@ -7,11 +7,15 @@
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "eye",
"link": "_cameraPosition"
},
{
"name": "eyeSnap",
"link": "_cameraPositionSnap",
"ifdef": ["_VoxelGI"]
},
{
"name": "eyeLook",
"link": "_cameraLook",

View file

@ -8,7 +8,7 @@
// https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
const float MAX_DISTANCE = 1.73205080757;
const float VOXEL_SIZE = 1.0 / voxelgiResolution;
const float VOXEL_SIZE = 2.0 / voxelgiResolution;
uniform sampler3D voxels;
@ -73,7 +73,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal) {
const vec3 o2 = normalize(cross(o1, normal));
const vec3 c1 = 0.5f * (o1 + o2);
const vec3 c2 = 0.5f * (o1 - o2);
const float offset = 3 * VOXEL_SIZE;
const float offset = 1.5 * VOXEL_SIZE;
// Normal direction
vec4 col = traceCone(origin, normal, aperture, MAX_DISTANCE, offset);
// 4 side cones
@ -90,7 +90,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal) {
}
float traceShadow(const vec3 origin, const vec3 dir, const float aperture, const float targetDistance) {
const float offset = 4 * VOXEL_SIZE;
const float offset = 2 * VOXEL_SIZE;
return traceCone(origin, dir, aperture, targetDistance, offset).a;
}
@ -99,7 +99,7 @@ vec3 traceSpecular(const vec3 pos, const vec3 normal, const vec3 viewDir, const
float specularAperture = clamp(tan((3.14159265 / 2) * rough * 0.75), 0.0174533, 3.14159265);
vec3 specularDir = normalize(reflect(-viewDir, normal));
// Clamp to 1 grad and pi, exponent is angle of cone in radians
const float offset = 6 * VOXEL_SIZE;
const float offset = 3 * VOXEL_SIZE;
return traceCone(pos, specularDir, specularAperture, MAX_DISTANCE, offset).xyz;
}
@ -109,7 +109,7 @@ vec3 traceRefraction(const vec3 pos, const vec3 normal, const vec3 viewDir, cons
vec3 refraction = refract(viewDir, normal, 1.0 / ior);
float rough = max(roughness, 0.03);
float specularAperture = clamp(tan((3.14159265 / 2) * rough), 0.0174533, 3.14159265);
const float offset = 3 * VOXEL_SIZE;
const float offset = 1.5 * VOXEL_SIZE;
return transmittance * traceCone(pos, refraction, specularAperture, MAX_DISTANCE, offset).xyz;
}
@ -138,7 +138,7 @@ float traceAO(const vec3 origin, const vec3 normal) {
const vec3 o2 = normalize(cross(o1, normal));
const vec3 c1 = 0.5f * (o1 + o2);
const vec3 c2 = 0.5f * (o1 - o2);
const float offset = 3 * VOXEL_SIZE;
const float offset = 1.5 * VOXEL_SIZE;
// Normal direction
float col = traceConeAO(origin, normal, aperture, MAX_DISTANCE, offset);
// 4 side cones

View file

@ -39,7 +39,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'World'
rpdat.rp_stereo = False
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = False
rpdat.rp_gi = 'Off'
rpdat.rp_render_to_texture = False
rpdat.rp_supersampling = '1'
rpdat.rp_antialiasing = 'None'
@ -70,7 +70,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'World'
rpdat.rp_stereo = False
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = False
rpdat.rp_gi = 'Off'
rpdat.rp_render_to_texture = True
rpdat.rp_supersampling = '1'
rpdat.rp_antialiasing = 'SMAA'
@ -101,7 +101,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'World'
rpdat.rp_stereo = False
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = False
rpdat.rp_gi = 'Off'
rpdat.rp_render_to_texture = True
rpdat.rp_supersampling = '1'
rpdat.rp_antialiasing = 'FXAA'
@ -131,7 +131,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'World'
rpdat.rp_stereo = False
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = True
rpdat.rp_gi = 'Voxel GI'
rpdat.rp_voxelgi_resolution = '256'
rpdat.rp_render_to_texture = True
rpdat.rp_supersampling = '2'
@ -165,7 +165,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'World'
rpdat.rp_stereo = False
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = False
rpdat.rp_gi = 'Off'
rpdat.rp_render_to_texture = True
rpdat.rp_supersampling = '1'
rpdat.rp_antialiasing = 'TAA'
@ -196,7 +196,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'World'
rpdat.rp_stereo = True
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = False
rpdat.rp_gi = 'Off'
rpdat.rp_render_to_texture = False
rpdat.rp_supersampling = '1'
rpdat.rp_antialiasing = 'None'
@ -227,7 +227,7 @@ def set_preset(self, context, preset):
rpdat.rp_background = 'Clear'
rpdat.rp_stereo = False
rpdat.rp_greasepencil = False
rpdat.rp_voxelgi = False
rpdat.rp_gi = 'Off'
rpdat.rp_render_to_texture = False
rpdat.rp_supersampling = '1'
rpdat.rp_antialiasing = 'None'
@ -393,11 +393,17 @@ def make_deferred(rpdat):
nodes['Begin'].inputs[1].default_value = rpdat.rp_hdr
nodes['Screen'].inputs[0].default_value = int(rpdat.rp_supersampling)
if rpdat.rp_voxelgi:
if rpdat.rp_gi == 'Voxel GI':
n = nodes['Image 3D Voxels']
# if rpdat.rp_voxelgi_hdr:
# n.inputs[4].default_value = 'RGBA64'
links.new(nodes['Begin'].outputs[0], nodes['Branch Function Voxelize'].inputs[0])
# One lamp only for now - draw shadow map in advance
links.new(nodes['Begin'].outputs[0], nodes['Set Target SM'].inputs[0])
links.new(nodes['Draw Meshes SM'].outputs[0], nodes['Branch Function Voxelize'].inputs[0])
l = nodes['Loop Lamps'].outputs[1].links[0]
links.remove(l)
links.new(nodes['Loop Lamps'].outputs[1], nodes['Deferred Light'].inputs[0])
links.new(nodes['Merge Stages Voxelize'].outputs[0], nodes['Set Target Mesh'].inputs[0])
res = int(rpdat.rp_voxelgi_resolution)
n.inputs[1].default_value = res
@ -410,7 +416,7 @@ def make_deferred(rpdat):
if rpdat.arm_voxelgi_shadows or rpdat.arm_voxelgi_refraction:
links.new(nodes['Image 3D Voxels'].outputs[0], nodes['Deferred Light'].inputs[4])
links.new(nodes['Image 3D Voxels'].outputs[0], nodes['Deferred Light.001'].inputs[4])
elif rpdat.rp_voxelao:
elif rpdat.rp_gi == 'Voxel AO':
n = nodes['Image 3D Voxels']
# n.inputs[4].default_value = 'R8'
links.new(nodes['Begin'].outputs[0], nodes['Branch Function Voxelize'].inputs[0])

View file

@ -107,9 +107,12 @@ def build_node_tree(world):
if rpdat.rp_shadowmap == 'None':
wrd.world_defs += '_NoShadows'
assets.add_khafile_def('arm_no_shadows')
if rpdat.rp_voxelgi:
if rpdat.rp_shadowmap_cascades != '1':
wrd.world_defs += '_CSM'
assets.add_khafile_def('arm_csm')
if rpdat.rp_gi == 'Voxel GI':
voxelgi = True
elif rpdat.rp_voxelao:
elif rpdat.rp_gi == 'Voxel AO':
voxelao = True
if rpdat.rp_dfrs:
wrd.world_defs += '_DFRS'

View file

@ -411,10 +411,7 @@ def make_forward_mobile(con_mesh):
frag.add_uniform('vec3 lightPos', '_lampPosition')
frag.add_uniform('float envmapStrength', link='_envmapStrength')
if '_NoShadows' in wrd.world_defs:
is_shadows = False
else:
is_shadows = True
is_shadows = not '_NoShadows' in wrd.world_defs
frag.write('float visibility = 1.0;')
frag.write('float dotNL = max(dot(n, lightDir), 0.0);')
@ -553,14 +550,8 @@ def make_forward_base(con_mesh, parse_opacity=False):
frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf')
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
if '_NoShadows' in wrd.world_defs:
is_shadows = False
else:
is_shadows = True
if '_PCSS' in wrd.world_defs:
is_pcss = True
else:
is_pcss = False
is_shadows = not '_NoShadows' in wrd.world_defs
is_pcss = '_PCSS' in wrd.world_defs
frag.write('float visibility = 1.0;')
frag.write('vec3 lp = lightPos - wposition;')

View file

@ -6,7 +6,7 @@ import arm.material.mat_utils as mat_utils
def make(context_id):
rpdat = arm.utils.get_rp()
if rpdat.rp_voxelgi:
if rpdat.rp_gi == 'Voxel GI':
return make_gi(context_id)
else:
return make_ao(context_id)
@ -15,10 +15,7 @@ def make_gi(context_id):
con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True })
wrd = bpy.data.worlds['Arm']
if '_NoShadows' in wrd.world_defs:
is_shadows = False
else:
is_shadows = True
is_shadows = not '_NoShadows' in wrd.world_defs
vert = con_voxel.make_vert()
frag = con_voxel.make_frag()
@ -46,13 +43,17 @@ def make_gi(context_id):
frag.add_uniform('int lightType', '_lampType')
frag.add_uniform('vec3 lightDir', '_lampDirection')
frag.write('if (!isInsideCube(wposition)) return;')
frag.write('if (!isInsideCube(voxposition)) return;')
frag.write('vec3 wposition = voxposition * voxelgiHalfExtents;')
frag.write('float visibility = 1.0;')
frag.write('vec3 lp = lightPos - wposition * voxelgiDimensions;')
frag.write('vec3 lp = lightPos - wposition;')
frag.write('vec3 l;')
frag.write('if (lightType == 0) l = lightDir;')
frag.write('else { l = normalize(lp); visibility *= attenuate(distance(wposition * voxelgiDimensions, lightPos)); }')
frag.write('else { l = normalize(lp); visibility *= attenuate(distance(wposition, lightPos)); }')
frag.write('float dotNL = max(dot(wnormal, l), 0.0);')
frag.write('if (dotNL == 0.0) return;')
if is_shadows:
frag.add_include('../../Shaders/std/shadows.glsl')
@ -63,11 +64,12 @@ def make_gi(context_id):
frag.add_uniform('float shadowsBias', '_lampShadowsBias')
frag.write('if (lightShadow == 1 && lampPos.w > 0.0) {')
frag.write(' vec3 lpos = lampPos.xyz / lampPos.w;')
# frag.write(' if (lpos.x < 0.0 || lpos.y < 0.0 || lpos.x > 1.0 || lpos.y > 1.0) return;')
# Note: shadowmap bound for sun lamp is tight behind the camera - can cause darkening no close surfaces
frag.write(' if (texture(shadowMap, lpos.xy).r < lpos.z - shadowsBias) visibility = 0.0;')
# frag.write(' visibility = PCF(lpos.xy, lpos.z - shadowsBias);')
frag.write('}')
frag.write('else if (lightShadow == 2) visibility *= float(texture(shadowMapCube, -l).r + shadowsBias > lpToDepth(lp, lightPlane));')
else:
frag.write('int lightShadow = 0;')
# frag.write('if (lightType == 2) {')
# frag.write(' float spotEffect = dot(lightDir, l);')
@ -106,7 +108,6 @@ def make_gi(context_id):
if parse_opacity:
frag.write('float opacity;')
frag.write('float dotNV = 0.0;')
frag.write('float dotNL = max(dot(wnormal, l), 0.0);')
cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True)
if not frag.contains('vec3 n ='):
@ -121,12 +122,10 @@ def make_gi(context_id):
vert.write('mpositionGeom = pos;')
vert.write_pre = False
if rpdat.arm_voxelgi_camera:
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat3 N', '_normalMatrix')
vert.add_out('vec3 wpositionGeom')
vert.add_out('vec3 voxpositionGeom')
vert.add_out('vec3 wnormalGeom')
vert.add_include('../../Shaders/compiled.glsl')
@ -140,20 +139,19 @@ def make_gi(context_id):
vert.write('texCoordGeom = tex;')
if rpdat.arm_voxelgi_camera:
vert.write('const float step = voxelgiDimensions / voxelgiResolution;') # TODO: Pass as uniform
vert.write('vec3 eyeSnap = ivec3(eye / step) * step;') # TODO: Pass as uniform
vert.write('wpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiDimensions;')
vert.add_uniform('vec3 eyeSnap', '_cameraPositionSnap')
vert.write('voxpositionGeom = (vec3(W * vec4(pos, 1.0)) - eyeSnap) / voxelgiHalfExtents;')
else:
vert.write('wpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiDimensions;')
vert.write('voxpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiHalfExtents;')
vert.write('wnormalGeom = normalize(N * nor);')
vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);')
# vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);')
if is_shadows:
vert.add_out('vec4 lampPosGeom')
vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix')
vert.write('lampPosGeom = LWVP * vec4(pos, 1.0);')
geom.add_out('vec3 wposition')
geom.add_out('vec3 voxposition')
geom.add_out('vec3 wnormal')
if is_shadows:
geom.add_out('vec4 lampPos')
@ -164,11 +162,11 @@ def make_gi(context_id):
if export_mpos:
geom.add_out('vec3 mposition')
geom.write('const vec3 p1 = wpositionGeom[1] - wpositionGeom[0];')
geom.write('const vec3 p2 = wpositionGeom[2] - wpositionGeom[0];')
geom.write('const vec3 p1 = voxpositionGeom[1] - voxpositionGeom[0];')
geom.write('const vec3 p2 = voxpositionGeom[2] - voxpositionGeom[0];')
geom.write('const vec3 p = abs(cross(p1, p2));')
geom.write('for (uint i = 0; i < 3; ++i) {')
geom.write(' wposition = wpositionGeom[i];')
geom.write(' voxposition = voxpositionGeom[i];')
geom.write(' wnormal = wnormalGeom[i];')
if is_shadows:
geom.write(' lampPos = lampPosGeom[i];')
@ -179,13 +177,13 @@ def make_gi(context_id):
if export_mpos:
geom.write(' mposition = mpositionGeom[i];')
geom.write(' if (p.z > p.x && p.z > p.y) {')
geom.write(' gl_Position = vec4(wposition.x, wposition.y, 0.0, 1.0);')
geom.write(' gl_Position = vec4(voxposition.x, voxposition.y, 0.0, 1.0);')
geom.write(' }')
geom.write(' else if (p.x > p.y && p.x > p.z) {')
geom.write(' gl_Position = vec4(wposition.y, wposition.z, 0.0, 1.0);')
geom.write(' gl_Position = vec4(voxposition.y, voxposition.z, 0.0, 1.0);')
geom.write(' }')
geom.write(' else {')
geom.write(' gl_Position = vec4(wposition.x, wposition.z, 0.0, 1.0);')
geom.write(' gl_Position = vec4(voxposition.x, voxposition.z, 0.0, 1.0);')
geom.write(' }')
geom.write(' EmitVertex();')
geom.write('}')
@ -195,7 +193,7 @@ def make_gi(context_id):
frag.write('vec3 color = basecol;')
else:
frag.write('vec3 color = basecol * visibility * lightColor * dotNL;')
frag.write('vec3 voxel = wposition * 0.5 + vec3(0.5);')
frag.write('vec3 voxel = voxposition * 0.5 + 0.5;')
# if rpdat.arm_material_model == 'Cycles':
# frag.write('color = min(color * 0.9, vec3(0.9)) + min(color / 200.0, 0.1);') # Higher range to allow emission
@ -205,33 +203,33 @@ def make_gi(context_id):
# else:
frag.write('color = clamp(color, vec3(0.0), vec3(1.0));')
# frag.write('uint val = convVec4ToRGBA8(vec4(color, 1.0) * 255);')
# frag.write('imageAtomicMax(voxels, ivec3(voxelgiResolution * voxel), val);')
frag.write('uint val = convVec4ToRGBA8(vec4(color, 1.0) * 255);')
frag.write('imageAtomicMax(voxels, ivec3(voxelgiResolution * voxel), val);')
# frag.write('imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));')
# frag.write('imageAtomicRGBA8Avg(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));')
frag.write('ivec3 coords = ivec3(voxelgiResolution * voxel);')
if parse_opacity:
frag.write('vec4 val = vec4(color, opacity);')
else:
frag.write('vec4 val = vec4(color, 1.0);')
frag.write('val *= 255.0;')
frag.write('uint newVal = encUnsignedNibble(convVec4ToRGBA8(val), 1);')
frag.write('uint prevStoredVal = 0;')
frag.write('uint currStoredVal;')
# frag.write('int counter = 0;')
# frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal && counter < 16) {')
frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {')
frag.write(' vec4 rval = convRGBA8ToVec4(currStoredVal & 0xFEFEFEFE);')
frag.write(' uint n = decUnsignedNibble(currStoredVal);')
frag.write(' rval = rval * n + val;')
frag.write(' rval /= ++n;')
frag.write(' rval = round(rval / 2) * 2;')
frag.write(' newVal = encUnsignedNibble(convVec4ToRGBA8(rval), n);')
frag.write(' prevStoredVal = currStoredVal;')
# frag.write(' counter++;')
frag.write('}')
# frag.write('ivec3 coords = ivec3(voxelgiResolution * voxel);')
# if parse_opacity:
# frag.write('vec4 val = vec4(color, opacity);')
# else:
# frag.write('vec4 val = vec4(color, 1.0);')
# frag.write('val *= 255.0;')
# frag.write('uint newVal = encUnsignedNibble(convVec4ToRGBA8(val), 1);')
# frag.write('uint prevStoredVal = 0;')
# frag.write('uint currStoredVal;')
# # frag.write('int counter = 0;')
# # frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal && counter < 16) {')
# frag.write('while ((currStoredVal = imageAtomicCompSwap(voxels, coords, prevStoredVal, newVal)) != prevStoredVal) {')
# frag.write(' vec4 rval = convRGBA8ToVec4(currStoredVal & 0xFEFEFEFE);')
# frag.write(' uint n = decUnsignedNibble(currStoredVal);')
# frag.write(' rval = rval * n + val;')
# frag.write(' rval /= ++n;')
# frag.write(' rval = round(rval / 2) * 2;')
# frag.write(' newVal = encUnsignedNibble(convVec4ToRGBA8(rval), n);')
# frag.write(' prevStoredVal = currStoredVal;')
# # frag.write(' counter++;')
# frag.write('}')
# frag.write('val.rgb *= 255.0f;')
# frag.write('uint newVal = convVec4ToRGBA8(val);')
@ -269,38 +267,39 @@ def make_ao(context_id):
frag.add_uniform('layout(RGBA8) image3D voxels')
# frag.add_uniform('layout(R8) image3D voxels')
frag.write('if (!isInsideCube(wposition)) return;')
frag.write('if (!isInsideCube(voxposition)) return;')
frag.write('vec3 wposition = voxposition * voxelgiHalfExtents;')
if rpdat.arm_voxelgi_camera:
vert.add_uniform('vec3 eye', '_cameraPosition')
# if rpdat.arm_voxelgi_camera:
# vert.add_uniform('vec3 eye', '_cameraPosition')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_out('vec3 wpositionGeom')
vert.add_out('vec3 voxpositionGeom')
vert.add_include('../../Shaders/compiled.glsl')
vert.write('wpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiDimensions;')
vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);')
vert.write('voxpositionGeom = vec3(W * vec4(pos, 1.0)) / voxelgiHalfExtents;')
# vert.write('gl_Position = vec4(0.0, 0.0, 0.0, 1.0);')
geom.add_out('vec3 wposition')
geom.write('const vec3 p1 = wpositionGeom[1] - wpositionGeom[0];')
geom.write('const vec3 p2 = wpositionGeom[2] - wpositionGeom[0];')
geom.add_out('vec3 voxposition')
geom.write('const vec3 p1 = voxpositionGeom[1] - voxpositionGeom[0];')
geom.write('const vec3 p2 = voxpositionGeom[2] - voxpositionGeom[0];')
geom.write('const vec3 p = abs(cross(p1, p2));')
geom.write('for (uint i = 0; i < 3; ++i) {')
geom.write(' wposition = wpositionGeom[i];')
geom.write(' voxposition = voxpositionGeom[i];')
geom.write(' if (p.z > p.x && p.z > p.y) {')
geom.write(' gl_Position = vec4(wposition.x, wposition.y, 0.0, 1.0);')
geom.write(' gl_Position = vec4(voxposition.x, voxposition.y, 0.0, 1.0);')
geom.write(' }')
geom.write(' else if (p.x > p.y && p.x > p.z) {')
geom.write(' gl_Position = vec4(wposition.y, wposition.z, 0.0, 1.0);')
geom.write(' gl_Position = vec4(voxposition.y, voxposition.z, 0.0, 1.0);')
geom.write(' }')
geom.write(' else {')
geom.write(' gl_Position = vec4(wposition.x, wposition.z, 0.0, 1.0);')
geom.write(' gl_Position = vec4(voxposition.x, voxposition.z, 0.0, 1.0);')
geom.write(' }')
geom.write(' EmitVertex();')
geom.write('}')
geom.write('EndPrimitive();')
frag.write('vec3 voxel = wposition * 0.5 + vec3(0.5);')
frag.write('vec3 voxel = voxposition * 0.5 + vec3(0.5);')
frag.write('imageStore(voxels, ivec3(voxelgiResolution * voxel), vec4(1.0));')
return con_voxel

View file

@ -27,7 +27,7 @@ def get_rpasses(material):
# ar.append('depth')
rpdat = arm.utils.get_rp()
vgirefract = rpdat.rp_voxelgi and rpdat.arm_voxelgi_refraction
vgirefract = rpdat.rp_gi == 'Voxel GI' and rpdat.arm_voxelgi_refraction
if material.arm_decal:
ar.append('decal')
@ -39,7 +39,7 @@ def get_rpasses(material):
ar.append('mesh')
for con in add_mesh_contexts:
ar.append(con)
if rpdat.rp_voxelgi or rpdat.rp_voxelao:
if rpdat.rp_gi == 'Voxel GI' or rpdat.rp_gi == 'Voxel AO':
ar.append('voxel')
if rpdat.rp_renderer == 'Deferred Plus':
ar.append('rect')

View file

@ -80,8 +80,15 @@ class ArmRPListItem(bpy.types.PropertyGroup):
('1024', '1024', '1024'),
('2048', '2048', '2048'),
('4096', '4096', '4096'),
('8192', '8192', '8192')],
('8192', '8192', '8192'),
('16384', '16384', '16384'),],
name="Shadow Map", description="Shadow map resolution", default='2048', update=update_renderpath)
rp_shadowmap_cascades = EnumProperty(
items=[('1', '1', '1'),
('2', '2', '2'),
('3', '3', '3'),
('4', '4', '4')],
name="Cascades", description="Shadow map cascades", default='3', update=update_renderpath)
rp_supersampling = EnumProperty(
items=[('1', '1X', '1X'),
('2', '2X', '2X'),
@ -138,8 +145,13 @@ class ArmRPListItem(bpy.types.PropertyGroup):
rp_stereo = bpy.props.BoolProperty(name="Stereo", description="Stereo rendering", default=False, update=update_renderpath)
rp_greasepencil = bpy.props.BoolProperty(name="Grease Pencil", description="Render Grease Pencil data", default=False, update=update_renderpath)
rp_ocean = bpy.props.BoolProperty(name="Ocean", description="Ocean pass", default=False, update=update_renderpath)
rp_voxelgi = bpy.props.BoolProperty(name="Voxel GI", description="Voxel-based Global Illumination", default=False, update=update_renderpath)
rp_voxelao = bpy.props.BoolProperty(name="Voxel AO", description="Voxel-based Ambient Occlussion", default=False, update=update_renderpath)
rp_gi = bpy.props.EnumProperty(
items=[('Off', 'Off', 'Off'),
('Voxel GI', 'Voxel GI', 'Voxel GI'),
('Voxel AO', 'Voxel AO', 'Voxel AO')
],
name="Global Illumination", description="Dynamic global illumination", default='Off', update=update_renderpath)
rp_voxelgi_resolution = bpy.props.EnumProperty(
items=[('32', '32', '32'),
('64', '64', '64'),
@ -186,10 +198,10 @@ class ArmRPListItem(bpy.types.PropertyGroup):
arm_voxelgi_dimensions = bpy.props.FloatProperty(name="Dimensions", description="Voxelization bounds",default=16, update=assets.invalidate_shader_cache)
arm_voxelgi_revoxelize = bpy.props.BoolProperty(name="Revoxelize", description="Revoxelize scene each frame", default=False, update=assets.invalidate_shader_cache)
# arm_voxelgi_multibounce = bpy.props.BoolProperty(name="Multi-bounce", description="Accumulate multiple light bounces", default=False, update=assets.invalidate_shader_cache)
arm_voxelgi_camera = bpy.props.BoolProperty(name="Camera", description="Use camera as voxelization origin", default=False, update=assets.invalidate_shader_cache)
arm_voxelgi_camera = bpy.props.BoolProperty(name="Dynamic Camera", description="Use camera as voxelization origin", default=False, update=assets.invalidate_shader_cache)
# arm_voxelgi_anisotropic = bpy.props.BoolProperty(name="Anisotropic", description="Use anisotropic voxels", default=False, update=update_renderpath)
arm_voxelgi_shadows = bpy.props.BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath)
arm_voxelgi_refraction = bpy.props.BoolProperty(name="Refraction", description="Use voxels to render refraction", default=False, update=update_renderpath)
arm_voxelgi_shadows = bpy.props.BoolProperty(name="Trace Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath)
arm_voxelgi_refraction = bpy.props.BoolProperty(name="Trace Refraction", description="Use voxels to render refraction", default=False, update=update_renderpath)
arm_samples_per_pixel = EnumProperty(
items=[('1', '1X', '1X'),
('2', '2X', '2X'),

View file

@ -918,6 +918,8 @@ class ArmRenderPathPanel(bpy.types.Panel):
layout.prop(rpdat, "rp_renderer")
layout.prop(rpdat, "arm_material_model")
layout.prop(rpdat, "rp_shadowmap")
if rpdat.rp_shadowmap != 'None':
layout.prop(rpdat, "rp_shadowmap_cascades")
layout.prop(rpdat, "rp_translucency_state")
layout.prop(rpdat, "rp_overlays_state")
layout.prop(rpdat, "rp_decals_state")
@ -927,19 +929,18 @@ class ArmRenderPathPanel(bpy.types.Panel):
layout.prop(rpdat, "rp_hdr")
layout.prop(rpdat, "rp_stereo")
layout.prop(rpdat, "rp_greasepencil")
layout.prop(rpdat, 'rp_voxelgi')
if not rpdat.rp_voxelgi:
layout.prop(rpdat, 'rp_voxelao')
else:
layout.prop(rpdat, 'rp_voxelgi_resolution')
layout.prop(rpdat, 'arm_voxelgi_dimensions')
layout.prop(rpdat, 'arm_voxelgi_revoxelize')
# layout.prop(rpdat, 'arm_voxelgi_camera')
# layout.prop(rpdat, 'arm_voxelgi_multibounce')
# layout.prop(rpdat, 'arm_voxelgi_anisotropic')
layout.prop(rpdat, 'arm_voxelgi_shadows')
layout.prop(rpdat, 'arm_voxelgi_refraction')
# layout.prop(rpdat, 'rp_voxelgi_hdr')
layout.prop(rpdat, 'rp_gi')
if rpdat.rp_gi != 'Off':
layout.prop(rpdat, 'rp_voxelgi_resolution')
layout.prop(rpdat, 'arm_voxelgi_dimensions')
layout.prop(rpdat, 'arm_voxelgi_revoxelize')
if rpdat.arm_voxelgi_revoxelize:
layout.prop(rpdat, 'arm_voxelgi_camera')
# layout.prop(rpdat, 'arm_voxelgi_multibounce')
# layout.prop(rpdat, 'arm_voxelgi_anisotropic')
layout.prop(rpdat, 'arm_voxelgi_shadows')
layout.prop(rpdat, 'arm_voxelgi_refraction')
# layout.prop(rpdat, 'rp_voxelgi_hdr')
layout.separator()
layout.prop(rpdat, "rp_render_to_texture")
@ -951,7 +952,7 @@ class ArmRenderPathPanel(bpy.types.Panel):
layout.prop(rpdat, "rp_ssao")
layout.prop(rpdat, "rp_ssr")
if rpdat.rp_ssr:
layout.prop(rpdat, 'arm_ssr_half_res')
layout.prop(rpdat, 'arm_ssr_half_res')
# layout.prop(wrd, 'arm_ssao_half_res')
# layout.prop(rpdat, "rp_dfao")
# layout.prop(rpdat, "rp_dfrs")

View file

@ -246,6 +246,12 @@ class Main {
}
#end""")
if rpdat.rp_gi == 'Voxel GI' or rpdat.rp_gi == 'Voxel AO':
f.write("""
public static inline var voxelgiVoxelSize = """ + str(rpdat.arm_voxelgi_dimensions) + " / " + str(rpdat.rp_voxelgi_resolution) + """;
public static inline var voxelgiHalfExtents = """ + str(round(rpdat.arm_voxelgi_dimensions / 2.0)) + """;
""")
f.write("""
public static function main() {
iron.object.BoneAnimation.skinMaxBones = """ + str(wrd.arm_skin_max_bones) + """;
@ -332,6 +338,7 @@ const float PI2 = PI * 2.0;
const vec2 cameraPlane = vec2(""" + str(round(clip_start * 100) / 100) + """, """ + str(round(clip_end * 100) / 100) + """);
const vec2 shadowmapSize = vec2(""" + str(shadowmap_size) + """, """ + str(shadowmap_size) + """);
const float shadowmapCubePcfSize = """ + str(round(wrd.arm_pcfsize * 10000) / 10000) + """;
const int shadowmapCascades = """ + str(rpdat.rp_shadowmap_cascades) + """;
""")
if rpdat.arm_clouds:
f.write(
@ -423,10 +430,10 @@ const float compoDOFFstop = """ + str(round(bpy.data.cameras[0].gpu_dof.fstop *
const float compoDOFLength = 160.0;
""") # str(round(bpy.data.cameras[0].lens * 100) / 100)
if rpdat.rp_voxelgi or rpdat.rp_voxelao:
if rpdat.rp_gi == 'Voxel GI' or rpdat.rp_gi == 'Voxel AO':
f.write(
"""const float voxelgiResolution = """ + str(rpdat.rp_voxelgi_resolution) + """;
const float voxelgiDimensions = """ + str(round(rpdat.arm_voxelgi_dimensions)) + """;
"""const int voxelgiResolution = """ + str(rpdat.rp_voxelgi_resolution) + """;
const float voxelgiHalfExtents = """ + str(round(rpdat.arm_voxelgi_dimensions / 2.0)) + """;
const float voxelgiDiff = """ + str(round(wrd.arm_voxelgi_diff * 100) / 100) + """;
const float voxelgiSpec = """ + str(round(wrd.arm_voxelgi_spec * 100) / 100) + """;
const float voxelgiOcc = """ + str(round(wrd.arm_voxelgi_occ * 100) / 100) + """;