Voxel refraction

This commit is contained in:
Lubos Lenco 2017-08-13 20:28:06 +02:00
parent d4d7a265c0
commit a0d14aed21
15 changed files with 83 additions and 28 deletions

View file

@ -136,7 +136,9 @@ void main() {
#ifdef _SSS
envl.rgb *= envmapStrength * fract(g1.a);
#else
#ifndef _VoxelGIRefract
envl.rgb *= envmapStrength * g1.a; // Occlusion
#endif
#endif
#ifdef _DFGI

View file

@ -7,9 +7,9 @@ precision mediump float;
#include "../compiled.glsl"
#include "../std/brdf.glsl"
#include "../std/math.glsl"
// #ifdef _VoxelGI
// #include "../std/conetrace.glsl"
// #endif
#ifdef _VoxelGIDirect
#include "../std/conetrace.glsl"
#endif
#ifdef _PolyLight
#include "../std/ltc.glsl"
#endif
@ -31,9 +31,9 @@ precision mediump float;
#endif
#include "../std/gbuffer.glsl"
// #ifdef _VoxelGI
//-!uniform sampler3D voxels;
// #endif
#ifdef _VoxelGIDirect
//!uniform sampler3D voxels;
#endif
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
@ -138,6 +138,10 @@ void main() {
vec3 lp = lightPos - p;
vec3 l = normalize(lp);
vec3 h = normalize(v + l);
float dotNH = dot(n, h);
float dotVH = dot(v, h);
float dotNL = dot(n, l);
float visibility = 1.0;
#ifndef _NoShadows
@ -150,6 +154,11 @@ void main() {
visibility = shadowTestCube(lp, l);
}
#endif
#ifdef _VoxelGIShadow // #else
if (dotNL > 0.0) visibility = max(0, 1.0 - traceShadow(p / voxelgiDimensions, l, 0.1, length(lp)));
#endif
#ifdef _DFRS
visibility = dfrs(p, l, lightPos);
@ -167,13 +176,6 @@ void main() {
}
}
vec3 h = normalize(v + l);
float dotNH = dot(n, h);
float dotVH = dot(v, h);
float dotNL = dot(n, l);
// float dotLV = dot(l, v);
// float dotLH = dot(l, h);
#ifdef _PolyLight
if (lightType == 3) { // Area
float theta = acos(dotNV);
@ -238,7 +240,7 @@ void main() {
#endif
#ifdef _SSRS
float tvis = traceShadow(-l, p, gbuffer0, invVP, eye);
float tvis = traceShadowSS(-l, p, gbuffer0, invVP, eye);
// vec2 coords = getProjectedCoord(hitCoord);
// vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
// float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
@ -246,9 +248,9 @@ void main() {
visibility *= tvis;
#endif
// #ifdef _VoxelGI
// if (dotNL > 0.0) visibility *= traceShadowCone(p / voxelgiResolution, l, distance(p, lightPos) / voxelgiResolution, n);
// #endif
fragColor.rgb *= visibility;
#ifdef _VoxelGIRefract
fragColor.rgb = mix(traceRefraction(p / voxelgiDimensions, n, -v, metrough.y), fragColor.rgb, g1.a);
#endif
}

View file

@ -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 = 3 * VOXEL_SIZE;
const float offset = 4 * VOXEL_SIZE;
return traceCone(origin, dir, aperture, targetDistance, offset).a;
}
@ -107,7 +107,7 @@ vec3 traceRefraction(const vec3 pos, const vec3 normal, const vec3 viewDir, cons
const float ior = 1.440;
const float transmittance = 1.0;
vec3 refraction = refract(viewDir, normal, 1.0 / ior);
float rough = max(roughness, 0.15);
float rough = max(roughness, 0.03);
float specularAperture = clamp(tan((3.14159265 / 2) * rough), 0.0174533, 3.14159265);
const float offset = 3 * VOXEL_SIZE;
return transmittance * traceCone(pos, refraction, specularAperture, MAX_DISTANCE, offset).xyz;

20
Shaders/std/ies.glsl Normal file
View file

@ -0,0 +1,20 @@
sampler2D texIES;
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
float iesAttenuation(vec3 L, ShadowLightInfo light) {
// Sample direction into light space
vec3 iesSampleDirection = mul(light.worldToLight , -L);
// Cartesian to spherical
// Texture encoded with cos( phi ), scale from -1 - >1 to 0 - >1
float phiCoord = (iesSampleDirection.z * 0.5f) + 0.5f;
float theta = atan2 (iesSampleDirection.y , iesSampleDirection .x);
float thetaCoord = theta * (1.0 / (PI * 2.0));
float iesProfileScale = texture(texIES, vec2(thetaCoord, phiCoord)).r;
return iesProfileScale;
// 1D texture
vec3 pl = normalize(p - lightPos);
float f = asin(dot(pl, l)) / PI + 0.5;
return texture(texIES, vec2(f, 0.0)).r;
}

View file

@ -27,7 +27,7 @@ float getDeltaDepth(vec3 hitCoord, sampler2D gbuffer0, mat4 invVP, vec3 eye) {
return d1 - d2;
}
float traceShadow(vec3 dir, vec3 hitCoord, sampler2D gbuffer0, mat4 invVP, vec3 eye) {
float traceShadowSS(vec3 dir, vec3 hitCoord, sampler2D gbuffer0, mat4 invVP, vec3 eye) {
dir *= ssrsRayStep;
// for (int i = 0; i < maxSteps; i++) {
hitCoord += dir;

View file

@ -123,6 +123,10 @@ def make_deferred(cam):
n.inputs[1].default_value = res
n.inputs[2].default_value = res
links.new(nodes['Image 3D Voxels'].outputs[0], nodes['Deferred Indirect'].inputs[4])
wrd = bpy.data.worlds['Arm']
if wrd.voxelgi_shadows or wrd.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])
if cam.rp_shadowmap != 'None':
n = nodes['Shadow Map']

View file

@ -456,7 +456,11 @@ def make_water_pass(stages, node_group, node):
make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbufferD', 'shadowMap'], shader_context='water_pass/water_pass/water_pass')
def make_deferred_light_pass(stages, node_group, node):
make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'shadowMap'], shader_context='', with_draw_quad=False)
wrd = bpy.data.worlds['Arm']
if wrd.voxelgi_shadows or wrd.voxelgi_refraction:
make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3, 4], bind_target_constants=['gbuffer', 'shadowMap', 'voxels'], shader_context='', with_draw_quad=False)
else:
make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'shadowMap'], shader_context='', with_draw_quad=False)
stage = {}
stage['command'] = 'call_function'
stage['params'] = ['iron.data.RenderPath.lampIsSun']

View file

@ -115,6 +115,12 @@ def build_node_tree(world):
wrd.world_defs += '_VoxelGIMulti'
if wrd.voxelgi_camera:
wrd.world_defs += '_VoxelGICam'
if wrd.voxelgi_shadows:
wrd.world_defs += '_VoxelGIDirect'
wrd.world_defs += '_VoxelGIShadow'
if wrd.voxelgi_refraction:
wrd.world_defs += '_VoxelGIDirect'
wrd.world_defs += '_VoxelGIRefract'
wrd.world_defs += '_VoxelGI'
wrd.world_defs += '_Rad' # Always do radiance for voxels
wrd.world_defs += '_Irr'

View file

@ -206,8 +206,9 @@ def make_deferred(con_mesh):
wrd = bpy.data.worlds['Arm']
discard_transparent = mat_state.material.discard_transparent
parse_opacity = discard_transparent or wrd.voxelgi_refraction
make_base(con_mesh, parse_opacity=discard_transparent)
make_base(con_mesh, parse_opacity=parse_opacity)
frag = con_mesh.frag
vert = con_mesh.vert
@ -260,6 +261,8 @@ def make_deferred(con_mesh):
if '_SSS' in wrd.rp_defs:
frag.add_uniform('int materialID')
frag.write('fragColor[1] = vec4(basecol.rgb, materialID + clamp(occlusion, 0.0, 1.0 - 0.001));')
elif wrd.voxelgi_refraction:
frag.write('fragColor[1] = vec4(basecol.rgb, opacity);')
else:
frag.write('fragColor[1] = vec4(basecol.rgb, occlusion);')

View file

@ -60,13 +60,15 @@ def make(context_id):
frag.write('float roughness;') #
frag.write('float metallic;') #
frag.write('float occlusion;') #
# frag.write('float opacity;') #
parse_opacity = wrd.voxelgi_refraction
if parse_opacity:
frag.write('float opacity;')
frag.write_pre = True
frag.write('mat3 TBN;') # TODO: discard, parse basecolor only
frag.write_pre = False
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=False, parse_displacement=False)
cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False)
if not frag.contains('vec3 n ='):
frag.write_pre = True
@ -152,7 +154,10 @@ def make(context_id):
# frag.write('imageAtomicRGBA8Avg(voxels, ivec3(voxelgiResolution * voxel), vec4(color, 1.0));')
frag.write('ivec3 coords = ivec3(voxelgiResolution * voxel);')
frag.write('vec4 val = vec4(color, 1.0);')
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;')

View file

@ -26,11 +26,14 @@ def get_rpasses(material):
# if material.depthpass:
# ar.append('depth')
wrd = bpy.data.worlds['Arm']
vgirefract = bpy.data.cameras[0].rp_voxelgi and wrd.voxelgi_refraction
if material.decal:
ar.append('decal')
elif material.overlay:
ar.append('overlay')
elif is_transluc(material) and not material.discard_transparent:
elif is_transluc(material) and not material.discard_transparent and not vgirefract:
ar.append('translucent')
else:
ar.append('mesh')
@ -38,7 +41,7 @@ def get_rpasses(material):
ar.append(con)
if bpy.data.cameras[0].rp_voxelgi:
ar.append('voxel')
if bpy.data.worlds['Arm'].voxelgi_multibounce:
if wrd.voxelgi_multibounce:
ar.append('voxelbounce')
if bpy.data.cameras[0].rp_renderer == 'Deferred Plus':
ar.append('rect')

View file

@ -319,6 +319,7 @@ class DeferredLightPassNode(Node, CGPipelineTreeNode):
self.inputs.new('NodeSocketShader', "Target")
self.inputs.new('NodeSocketShader', "GBuffer")
self.inputs.new('NodeSocketShader', "Shadow Map")
self.inputs.new('NodeSocketShader', "Voxels")
self.outputs.new('NodeSocketShader', "Stage")

View file

@ -432,6 +432,8 @@ def init_properties():
bpy.types.World.voxelgi_multibounce = bpy.props.BoolProperty(name="Multi-bounce", description="Accumulate multiple light bounces", default=False, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi_camera = bpy.props.BoolProperty(name="Camera", description="Use camera as voxelization origin", default=False, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi_anisotropic = bpy.props.BoolProperty(name="Anisotropic", description="Use anisotropic voxels", default=False, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi_shadows = bpy.props.BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath)
bpy.types.World.voxelgi_refraction = bpy.props.BoolProperty(name="Refraction", description="Use voxels to render refraction", default=False, update=update_renderpath)
bpy.types.World.voxelgi_diff = bpy.props.FloatProperty(name="Diffuse", description="", default=1.0, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi_spec = bpy.props.FloatProperty(name="Specular", description="", default=1.0, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi_occ = bpy.props.FloatProperty(name="Occlussion", description="", default=1.0, update=assets.invalidate_shader_cache)

View file

@ -342,6 +342,9 @@ class GenRPDataPropsPanel(bpy.types.Panel):
row = layout.row()
row.prop(wrd, 'voxelgi_camera')
row.prop(wrd, 'voxelgi_anisotropic')
row = layout.row()
row.prop(wrd, 'voxelgi_shadows')
row.prop(wrd, 'voxelgi_refraction')
layout.prop(dat, 'rp_voxelgi_hdr')
layout.separator()

Binary file not shown.