Fix voxelize pass

This commit is contained in:
luboslenco 2017-02-18 20:18:38 +01:00
parent 27a423fd23
commit 4c10c37396
10 changed files with 148 additions and 11 deletions

View file

@ -10,7 +10,9 @@ precision mediump float;
// #ifdef _PolyLight
#include "../std/ltc.glsl"
// #endif
// ...
#ifdef _VoxelGI
#include "../std/conetrace.glsl"
#endif
#ifndef _NoShadows
#ifdef _PCSS
#include "../std/shadows_pcss.glsl"

View file

@ -1,6 +1,6 @@
uniform sampler3D voxels;
const float voxelGridWorldSize = 150.0;
const int voxelDimensions = 512;
const int voxelDimensions = 128;
const float maxDist = 30.0;
const float alphaThreshold = 0.95;
const int numCones = 6;
@ -45,12 +45,12 @@ vec4 coneTrace(vec3 posWorld, vec3 direction, vec3 norWorld, float tanHalfAngle,
}
vec4 coneTraceIndirect(vec3 posWorld, mat3 tanToWorld, vec3 norWorld, out float occlusion) {
vec4 color = vec4(0);
vec4 color = vec4(0.0);
occlusion = 0.0;
for (int i = 0; i < numCones; i++) {
float coneOcclusion;
const float tanangle = tan(30):
const float tanangle = tan(30.0);
color += coneWeights[i] * coneTrace(posWorld, tanToWorld * coneDirections[i], norWorld, tanangle, coneOcclusion);
occlusion += coneWeights[i] * coneOcclusion;
}

View file

@ -424,9 +424,9 @@ 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=['tex', 'gbufferD'], 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='deferred_light/deferred_light/deferred_light')
# Draw lamp volume - TODO: properly generate stage
make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'shadowMap'], shader_context='deferred_light/deferred_light/deferred_light')
# make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'shadowMap'], shader_context='deferred_light/deferred_light/deferred_light')
make_quad_pass(stages, node_group, node, target_index=1, bind_target_indices=[2, 3, 4], bind_target_constants=['gbuffer', 'shadowMap', 'voxels'], shader_context='deferred_light/deferred_light/deferred_light')
stages[-1]['command'] = 'draw_lamp_volume'
def make_volumetric_light_pass(stages, node_group, node):

View file

@ -12,6 +12,7 @@ import material.make_transluc as make_transluc
import material.make_overlay as make_overlay
import material.make_depth as make_depth
import material.make_decal as make_decal
import material.make_voxel as make_voxel
rpass_hook = None
mesh_make = make_mesh.make
@ -83,6 +84,9 @@ def parse(material, mat_data, mat_users, mat_armusers, rid):
elif rp == 'depth':
con = make_depth.make(rp)
elif rp == 'voxel':
con = make_voxel.make(rp)
elif rpass_hook != None:
con = rpass_hook(rp)

View file

@ -0,0 +1,110 @@
# http://simonstechblog.blogspot.sk/2013/01/implementing-voxel-cone-tracing.html
# http://leifnode.com/2015/05/voxel-cone-traced-global-illumination/
# http://www.seas.upenn.edu/%7Epcozzi/OpenGLInsights/OpenGLInsights-SparseVoxelization.pdf
# https://github.com/Cigg/Voxel-Cone-Tracing
# https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
import material.cycles as cycles
import material.mat_state as mat_state
import material.mat_utils as mat_utils
def make(context_id):
con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none' })
vert = con_voxel.make_vert()
frag = con_voxel.make_frag()
geom = con_voxel.make_geom()
tesc = None
tese = None
geom.ins = vert.outs
frag.ins = geom.outs
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_out('vec4 lampPos')
# vert.add_out('vec2 texuv')
# vert.write('texuv = tex;')
vert.write('lampPos = LWVP * vec4(pos, 1.0);')
vert.write('gl_Position = W * vec4(pos, 1.0);')
geom.add_uniform('mat4 PX', '_projectionXMatrix')
geom.add_uniform('mat4 PY', '_projectionYMatrix')
geom.add_uniform('mat4 PZ', '_projectionZMatrix')
#geom.add_out('vec2 geom_texuv')
geom.add_out('flat int geom_axis')
geom.add_out('vec4 geom_lampPos')
geom.write('vec3 p1 = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz;')
geom.write('vec3 p2 = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz;')
geom.write('vec3 absnor = abs(normalize(cross(p1, p2)));')
geom.write('mat4 P; // Dominant axis')
geom.write('if (absnor.x >= absnor.y && absnor.x >= absnor.z) {')
geom.write(' geom_axis = 1;')
geom.write(' P = PX;')
geom.write('}')
geom.write('else if (absnor.y >= absnor.x && absnor.y >= absnor.z) {')
geom.write(' geom_axis = 2;')
geom.write(' P = PY;')
geom.write('}')
geom.write('else {')
geom.write(' geom_axis = 3;')
geom.write(' P = PZ;')
geom.write('}')
geom.write('for (int i = 0; i < gl_in.length(); i++) {')
geom.write(' vec3 middlePos = gl_in[0].gl_Position.xyz / 3.0 + gl_in[1].gl_Position.xyz / 3.0 + gl_in[2].gl_Position.xyz / 3.0;')
#geom.write(' geom_texuv = texuv[i];')
geom.write(' geom_lampPos = lampPos[i];')
geom.write(' gl_Position = P * gl_in[i].gl_Position;')
geom.write(' EmitVertex();')
geom.write('}')
geom.write('EndPrimitive();')
frag.write_header('#extension GL_ARB_shader_image_load_store : enable')
frag.add_uniform('layout(RGBA8) image3D voxels')
#frag.add_uniform('sampler2D sbase')
#frag.add_uniform('vec4 baseCol')
#frag.add_uniform('sampler2D shadowMap')
frag.write('const int voxelDimensions = 128;')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False)
frag.write('vec4 matCol = vec4(basecol, 1.0);')
# vec3 lampPos = geom_lampPos.xyz / geom_lampPos.w;
# lampPos.xy = lampPos.xy * 0.5 + 0.5;
# float distanceFromLight = texture(shadowMap, lampPos.xy).r * 2.0 - 1.0;
# const float shadowsBias = 0.0001;
# float visibility = float(distanceFromLight > lampPos.z - shadowsBias);
frag.write('float visibility = 1.0;')
frag.write('ivec3 camPos = ivec3(gl_FragCoord.x, gl_FragCoord.y, voxelDimensions * gl_FragCoord.z);')
frag.write('ivec3 texPos;')
frag.write('if (geom_axis == 1) {')
frag.write(' texPos.x = voxelDimensions - camPos.z;')
frag.write(' texPos.z = camPos.x;')
frag.write(' texPos.y = camPos.y;')
frag.write('}')
frag.write('else if (geom_axis == 2) {')
frag.write(' texPos.z = camPos.y;')
frag.write(' texPos.y = voxelDimensions - camPos.z;')
frag.write(' texPos.x = camPos.x;')
frag.write('}')
frag.write('else {')
frag.write(' texPos = camPos;')
frag.write('}')
frag.write('texPos.z = voxelDimensions - texPos.z - 1;')
frag.write('imageStore(voxels, texPos, vec4(matCol.rgb * visibility, 1.0));')
return con_voxel

View file

@ -36,6 +36,8 @@ def get_rpasses(material):
ar.append('mesh')
for con in add_mesh_contexts:
ar.append(con)
if bpy.data.worlds['Arm'].voxelgi:
ar.append('voxel')
shadows_enabled = False
for cam in bpy.data.cameras:

View file

@ -13,6 +13,7 @@ class Shader:
self.functions = {}
self.main = ''
self.main_pre = ''
self.header = ''
self.write_pre = False
self.tab = 1
@ -27,8 +28,12 @@ class Shader:
def add_uniform(self, s, link=None, included=False):
ar = s.split(' ')
if ar[0] == 'sampler2D':
self.context.add_texture_unit(ar[0], ar[1], link=link)
# layout(RGBA8) image3D voxels
utype = ar[-2]
uname = ar[-1]
if utype.startswith('sampler') or utype.startswith('image'):
is_image = True if utype.startswith('image') else None
self.context.add_texture_unit(utype, uname, link=link, is_image=is_image)
else:
# Prefer vec4[] for d3d to avoid padding
if ar[0] == 'float' and '[' in ar[1]:
@ -56,9 +61,14 @@ class Shader:
else:
self.main += '\t' * self.tab + s + '\n'
def write_header(self, s):
self.header += s + '\n'
def get(self):
s = '#version 450\n'
s += self.header
defs = make_utils.def_strings_to_array(bpy.data.worlds['Arm'].world_defs)
for a in defs:
s += '#define {0}\n'.format(a)
@ -77,7 +87,7 @@ class Shader:
s += 'layout(vertices = 3) out;\n'
# Gen outs
for sin in self.ins:
ar = sin.split(' ') # vec3 wnormal
ar = sin.rsplit(' ', 1) # vec3 wnormal
tc_s = 'tc_' + ar[1]
self.add_out(ar[0] + ' ' + tc_s)
# Pass data
@ -87,6 +97,11 @@ class Shader:
in_ext = '[]'
s += 'layout(triangles, equal_spacing, ccw) in;\n'
elif self.shader_type == 'geom':
in_ext = '[]'
s += 'layout(triangles) in;\n'
s += 'layout(triangle_strip, max_vertices = 3) out;\n'
for a in self.includes:
s += '#include "' + a + '"\n'
for a in self.ins:

View file

@ -104,7 +104,7 @@ class ShaderContext:
c['link'] = link
self.constants.append(c)
def add_texture_unit(self, ctype, name, link=None):
def add_texture_unit(self, ctype, name, link=None, is_image=None):
for c in self.tunits:
if c['name'] == name:
return
@ -112,6 +112,8 @@ class ShaderContext:
c = { 'name': name }
if link != None:
c['link'] = link
if is_image != None:
c['is_image'] = is_image
self.tunits.append(c)
def make_vert(self):

View file

@ -295,6 +295,8 @@ class DeferredLightPassNode(Node, CGPipelineTreeNode):
self.inputs.new('NodeSocketShader', "Target")
self.inputs.new('NodeSocketShader', "GBuffer")
self.inputs.new('NodeSocketShader', "Shadow Map")
# Testing voxels
self.inputs.new('NodeSocketShader', "Voxels")
self.outputs.new('NodeSocketShader', "Stage")

View file

@ -432,7 +432,7 @@ def init_properties():
items=[('Lambert', 'Lambert', 'Lambert'),
('Oren Nayar', 'Oren Nayar', 'Oren Nayar')],
name="Diffuse", description="Diffuse model", default='Lambert', update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi = bpy.props.BoolProperty(name="VGI", description="Voxel-based Global Illumination", default=False, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi = bpy.props.BoolProperty(name="Voxel GI", description="Voxel-based Global Illumination", default=False, update=assets.invalidate_shader_cache)
bpy.types.World.voxelgi_dimensions = bpy.props.FloatVectorProperty(name="Dimensions", description="3D texture size", size=3, default=[128, 128, 128], update=assets.invalidate_shader_cache)
# For material
bpy.types.Material.is_cached = bpy.props.BoolProperty(name="Material Cached", description="No need to reexport material data", default=False, update=update_mat_cache)