Skip to content

Instantly share code, notes, and snippets.

@josemorval
Last active January 26, 2024 01:11
Show Gist options
  • Save josemorval/0051c5e912b60e57786a5467c0873954 to your computer and use it in GitHub Desktop.
Save josemorval/0051c5e912b60e57786a5467c0873954 to your computer and use it in GitHub Desktop.
voxelizer in lazyengine
require("lualibs.vec")
function init()
-- get usual variables
global_t = get_time()
delta_t = get_delta_time()
screenx,screeny = get_window_size()
mouseposx,mouseposy = imgui_getmousepos()
deltamouseposx = 0
deltamouseposy = 0
-- first person camera controller
main_camera = {
eye = vec.new(-5.0,2.0,5.0),
dir = vec.mul(-1.0,vec.normalize(vec.new(-5.0,2.0,5.0))),
lighteye = vec.new(0.001,1.0,0.001),
lightdir = vec.new(0.0,0.0,0.0),
update = function(self)
if imgui_ismousepressed(1) then
local right = transform_view_to_world(1,0,0,0)
local up = transform_view_to_world(0,1,0,0)
local forward = transform_view_to_world(0,0,1,0)
-- w key
if imgui_iskeypressed(568) then
self.eye = vec.add(self.eye,vec.mul(0.1,forward))
end
-- a key
if imgui_iskeypressed(546) then
self.eye = vec.add(self.eye,vec.mul(-0.1,right))
end
-- s key
if imgui_iskeypressed(564) then
self.eye = vec.add(self.eye,vec.mul(-0.1,forward))
end
-- d key
if imgui_iskeypressed(549) then
self.eye = vec.add(self.eye,vec.mul(0.1,right))
end
if math.abs(deltamouseposx)>1350.0 then deltamouseposx = 0 end
if math.abs(deltamouseposy)>650.0 then deltamouseposy = 0 end
self.dir = vec.add(self.dir, vec.mul(deltamouseposx*0.001,right))
self.dir = vec.add(self.dir, vec.mul(-deltamouseposy*0.001,up))
self.dir = vec.normalize(self.dir)
set_camera(self.eye.x,self.eye.y,self.eye.z,self.dir.x,self.dir.y,self.dir.z)
end
end,
use = function(self)
self.lighteye = vec.new(3.0,5.0,2.0)
self.lightdir = vec.mul(-1.0,vec.normalize(self.lighteye))
set_camera(self.eye.x,self.eye.y,self.eye.z,self.dir.x,self.dir.y,self.dir.z)
set_perspective(1.0,screenx/screeny,0.1,50.0)
set_light_camera(self.lighteye.x,self.lighteye.y,self.lighteye.z,self.lightdir.x,self.lightdir.y,self.lightdir.z)
set_light_orthographic(10.0*screenx/screeny,10.0,0.1,50.0)
update_globalconstantbuffer()
end
}
-- create depth texture
maindepth_texture = create_renderdepth2D(screenx,screeny)
-- create shadow map
shadowmap_texture = create_renderdepth2D(screenx,screeny)
-- create voxel render target
number_voxels = 100
voxel_texture = create_rendertarget3D(number_voxels,number_voxels,number_voxels)
-- camera for voxelization
voxel_camera = {
eye = vec.new(0.0,0.0,20.0),
dir = vec.new(0.0,0.0,-1.0),
use = function(self)
set_camera(self.eye.x,self.eye.y,self.eye.z,self.dir.x,self.dir.y,self.dir.z)
set_orthographic(20,20,0.1,100.0)
update_globalconstantbuffer()
end
}
-- standard (+ shadowmap) material
standard_material = create_fx("./shaders/gi/standard.hlsl", false)
standard_shadow_material = create_fx("./shaders/gi/standard_shadow.hlsl", false)
-- voxelizer + voxel viewer material
voxelize_material = create_fx("./shaders/gi/voxelize.hlsl", true)
voxelviewer_material = create_fx("./shaders/gi/voxelviewer.hlsl", false)
-- voxel constant buffer
voxel_constant_buffer = create_constantbuffer( 16*2 )
update_constantbuffer(
voxel_constant_buffer,
3, 10.0, 4, number_voxels
)
attach_constantbuffer(voxel_constant_buffer,3)
-- create two cube entities. defined below
cube = create_cube()
ground = create_cube()
end
function imgui()
end
-- main logic loop
function render()
global_t = get_time()
delta_t = get_delta_time()
update_mousepos()
-----------------------
-- shadowmap render
-----------------------
main_camera:update()
main_camera:use()
use_viewport(0,0,screenx,screeny)
use_rasterizer()
use_write_depthstencil()
clear_depth_renderdepth2D(shadowmap_texture)
set_depth_renderdepth2D(shadowmap_texture)
use_fx(standard_shadow_material)
render_scene()
-----------------------
-- voxelization
-----------------------
voxel_camera:use()
use_viewport(0,0,number_voxels,number_voxels)
use_nocull_rasterizer()
clear_depthstencil()
--voxelize scene
clear_rendertarget_rendertarget3D(voxel_texture,0.0,0.0,0.0,0.0)
set_rendertarget_depth_and_uavs(false,{},{},{voxel_texture},-1,1)
use_fx(voxelize_material)
attach_srv_renderdepth2D(shadowmap_texture,0)
render_scene()
clean_srv(0)
-----------------------
-- voxelization viewer
-----------------------
main_camera:use()
use_viewport(0,0,screenx,screeny)
use_write_depthstencil()
-- ping-pong between normal/wireframe viz
e,f = math.modf(0.2*global_t,1.0)
if f > 0.5 then
use_rasterizer()
else
use_wireframe_rasterizer()
end
-- sky color
clear_rendertarget_backbuffer(0.4,0.7,1.0,1.0)
clear_depth_renderdepth2D(maindepth_texture)
set_rendertarget_and_depth_backbuffer(maindepth_texture)
use_fx(voxelviewer_material)
attach_srv_rendertarget3D(voxel_texture,1)
use_cube()
draw_instances_cube(number_voxels * number_voxels * number_voxels)
clean_srv(1)
end
-- as simple scene
function render_scene()
cube.rotation = vec.new(math.sin(global_t),math.cos(global_t),math.sin(global_t),0.5)
cube.scale = vec.new(2.0,2.0,2.0)
cube.position = vec.new(-2.0,0.0,0.0)
cube:draw()
cube.rotation = vec.new(math.sin(global_t+1.0),math.cos(global_t+1.0),math.sin(global_t+1.0),0.5)
cube.scale = vec.new(1.0,1.0,1.0)
cube.position = vec.new(1.0,0.0,2.0)
cube:draw()
cube.rotation = vec.new(math.sin(global_t+1.0),math.cos(global_t+1.0),math.sin(global_t+1.0),0.5)
cube.scale = vec.new(-1.0,1.0,1.0)
cube.position = vec.new(1.0,0.0,2.0)
cube:draw()
cube.rotation = vec.new(math.sin(global_t+1.0),math.cos(global_t+1.0),math.sin(global_t+1.0),0.5)
cube.scale = vec.new(-1.0,1.0,1.0)
cube.position = vec.new(1.0,0.3,-1.0)
cube:draw()
ground.position = vec.new(0.0,-1.0,0.0)
ground.scale = vec.new(5.0,0.2,5.0)
ground:draw()
end
function cleanup()
end
---------------------
-- Helpers ----------
---------------------
function create_cube()
return {
position = vec.new(0,0,0),
rotation = vec.new(0,1,0,0),
scale = vec.new(1,1,1),
draw = function(self)
use_cube()
set_translation_transform(0,self.position.x,self.position.y,self.position.z)
set_rotation_transform(0,self.rotation.x,self.rotation.y,self.rotation.z,self.rotation.w)
set_scale_transform(0,self.scale.x,self.scale.y,self.scale.z)
update_transformbuffer()
draw_instances_cube(1)
end
}
end
function transform_view_to_world(x,y,z,w)
local vx,vy,vz,vw = inv_transform_point_camera(x,y,z,w)
v = vec.new(vx,vy,vz)
return v
end
function update_mousepos()
newmouseposx, newmouseposy = imgui_getmousepos()
deltamouseposx = newmouseposx - mouseposx
deltamouseposy = newmouseposy - mouseposy
mouseposx = newmouseposx
mouseposy = newmouseposy
end
SamplerState linear_wrap_sampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
SamplerState point_wrap_sampler
{
Filter = MIN_MAG_MIP_POINT;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
SamplerState linear_clamp_sampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
SamplerState point_clamp_sampler
{
Filter = MIN_MAG_MIP_POINT;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
cbuffer constants : register(b0)
{
float4x4 g_view_matrix;
float4x4 g_inv_view_matrix;
float4x4 g_projection_matrix;
float4x4 g_light_view_matrix;
float4x4 g_light_inv_view_matrix;
float4x4 g_light_projection_matrix;
float g_global_time;
float g_delta_time;
};
cbuffer transform_constants : register(b1)
{
float4x4 translation_matrix[64];
float4x4 rotation_matrix[64];
float4x4 scale_matrix[64];
};
cbuffer custom_data_constants : register(b2)
{
float4 custom_data0;
float4 custom_data1;
float4 custom_data2;
}
cbuffer voxel_constants : register(b3)
{
float4 g_voxel_center_size;
float4 g_voxel_dim;
};
RWTexture3D<float4> voxelize_scene_render : register(u1);
Texture2D<float4> light_shadowmap_texture : register(t0);
Texture3D<float4> voxelize_scene_texture : register(t1);
float compute_direct_lighting(float3 world_position, float3 world_normal, Texture2D t_texture, SamplerState s_texture)
{
float4 position_light_space = mul(g_light_view_matrix, float4(world_position, 1.0));
position_light_space = mul(g_light_projection_matrix, position_light_space);
float depth = t_texture.Sample(s_texture, 0.5 - 0.5 * float2(-1.0, 1.0) * position_light_space.xy).r;
float current_depth = position_light_space.z;
float3 light_forward = -(mul(g_light_inv_view_matrix, float4(0.0, 0.0, 1.0, 0.0))).xyz;
float sha = smoothstep(0.001, 0.0, current_depth-depth);
float3 nor = normalize(world_normal);
float dif = clamp(dot(nor, normalize(light_forward)), 0.0, 1.0);
return sha * dif;
}
#include "./shaders/common.hlsl"
#include "./shaders/gi/gi_common.hlsl"
struct VS_INPUT {
float3 position : POSITION;
float2 texcoord : TEXCOORD;
float3 normal : NORMAL;
uint instanceid : SV_InstanceID;
};
struct VS_OUTPUT {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
float3 world_position: TEXCOORD1;
float3 world_normal : TEXCOORD2;
float3 local_position : TEXCOORD3;
};
VS_OUTPUT vs_main(VS_INPUT i)
{
VS_OUTPUT o;
float4 local_pos = float4(i.position,1.0);
o.world_position = mul(translation_matrix[i.instanceid],mul(rotation_matrix[i.instanceid],mul(scale_matrix[i.instanceid],float4(local_pos.xyz,1.0))));
o.position = mul(g_projection_matrix,mul(g_view_matrix,float4(o.world_position,1.0)));
o.world_normal = normalize(mul(rotation_matrix[i.instanceid],float4(i.normal,0.0)).xyz);
o.texcoord = i.texcoord;
o.local_position = mul(scale_matrix[i.instanceid],float4(i.position,1.0)).xyz;
return o;
}
float4 ps_main(VS_OUTPUT i) : SV_TARGET
{
float dili = compute_direct_lighting(i.world_position, i.world_normal, light_shadowmap_texture, linear_wrap_sampler);
float3 color = float3(1.0,0.9,0.8);
color *= dili;
return float4(color,1.0);
}
#include "./shaders/common.hlsl"
struct VS_INPUT {
float3 position : POSITION;
float2 texcoord : TEXCOORD;
float3 normal : NORMAL;
uint instanceid : SV_InstanceID;
};
struct VS_OUTPUT {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
float3 world_position: TEXCOORD1;
float3 world_normal : TEXCOORD2;
float3 local_position : TEXCOORD3;
};
VS_OUTPUT vs_main(VS_INPUT i)
{
VS_OUTPUT o;
float4 local_pos = float4(i.position,1.0);
o.world_position = mul(translation_matrix[i.instanceid],mul(rotation_matrix[i.instanceid],mul(scale_matrix[i.instanceid],float4(local_pos.xyz,1.0))));
o.position = mul(g_light_projection_matrix,mul(g_light_view_matrix,float4(o.world_position,1.0)));
o.world_normal = normalize(mul(rotation_matrix[i.instanceid],float4(i.normal,0.0)).xyz);
o.texcoord = i.texcoord;
o.local_position = mul(scale_matrix[i.instanceid],float4(i.position,1.0)).xyz;
return o;
}
float4 ps_main(VS_OUTPUT i) : SV_TARGET
{
return float4(0.0,0.0,0.0,0.0);
}
#include "./shaders/common.hlsl"
#include "./shaders/gi/gi_common.hlsl"
struct VS_INPUT {
float3 position : POSITION;
float2 texcoord : TEXCOORD;
float3 normal : NORMAL;
uint instanceid : SV_InstanceID;
};
struct VS_OUTPUT {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct PS_INPUT {
float4 position : SV_POSITION;
float3 world_position : TEXCOORD0;
float3 world_normal : TEXCOORD1;
float2 texcoord : TEXCOORD2;
};
VS_OUTPUT vs_main(VS_INPUT i)
{
VS_OUTPUT o;
float4 local_pos = float4(i.position,1.0);
o.position = mul(translation_matrix[i.instanceid],mul(rotation_matrix[i.instanceid],mul(scale_matrix[i.instanceid],float4(local_pos.xyz,1.0))));
o.texcoord = i.texcoord;
o.normal = normalize(mul(rotation_matrix[i.instanceid],float4(i.normal,0.0)).xyz);
return o;
}
[maxvertexcount(3)]
void gs_main(triangle VS_OUTPUT input[3], inout TriangleStream<PS_INPUT> triStream)
{
for (int i = 0; i < 3; i++)
{
PS_INPUT output;
float angle = 2. * 3.1419 * float(i)/3.0;
float2 posxy = 0.7*float2(cos(angle), sin(angle));
output.position = float4(posxy,1.0,1.0);
output.world_position = input[i].position;
output.world_normal = input[i].normal;
output.texcoord = input[i].texcoord;
triStream.Append(output);
}
triStream.RestartStrip();
}
float4 ps_main(PS_INPUT i) : SV_TARGET
{
float li = compute_direct_lighting(i.world_position, i.world_normal, light_shadowmap_texture, point_wrap_sampler);
float3 world_position_centered = i.world_position - g_voxel_center_size.xyz;
world_position_centered = floor((world_position_centered/g_voxel_center_size.w + 0.5) * g_voxel_dim.x);
if (
world_position_centered.x < g_voxel_dim.x &&
world_position_centered.y < g_voxel_dim.x &&
world_position_centered.z < g_voxel_dim.x
)
{
voxelize_scene_render[uint3(world_position_centered.x, world_position_centered.y, world_position_centered.z)] = float4(li*float3(1.0,1.0,1.0), 1.0);
}
return float4(0.0,0.0,0.0,0.0);
}
#include "./shaders/common.hlsl"
#include "./shaders/gi/gi_common.hlsl"
struct VS_INPUT {
float3 position : POSITION;
float2 texcoord : TEXCOORD;
float3 normal : NORMAL;
uint instanceid : SV_InstanceID;
};
struct VS_OUTPUT {
float4 position : SV_POSITION;
float3 color : TEXCOORD;
};
VS_OUTPUT vs_main(VS_INPUT i)
{
VS_OUTPUT o;
float4 local_pos = float4(i.position,1.0);
uint3 voxel_index = uint3(0,0,0);
{
int i_voxel_dim = floor(g_voxel_dim.x);
int x = i.instanceid % i_voxel_dim;
int y = ((i.instanceid - x)/i_voxel_dim) % i_voxel_dim;
int z = (i.instanceid - x - g_voxel_dim * y) / (i_voxel_dim * i_voxel_dim);
voxel_index = uint3(x,y,z);
}
float3 world_position_offset = (voxel_index / g_voxel_dim.x - 0.5) * g_voxel_center_size.w + g_voxel_center_size.xyz;
if( voxelize_scene_texture[ voxel_index ].a < 0.5 ) local_pos.xyz *= 0;
float3 world_position = world_position_offset + local_pos.xyz * g_voxel_center_size.w / g_voxel_dim.x;
o.position = mul(g_projection_matrix,mul(g_view_matrix,float4(world_position,1.0)));
o.color = voxelize_scene_texture[ voxel_index ].rgb;
return o;
}
float4 ps_main(VS_OUTPUT i) : SV_TARGET
{
float3 color = i.color;
return float4(color,1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment