Skip to content

Commit

Permalink
Updated ambient occlusion map generation to use RenderingDevice
Browse files Browse the repository at this point in the history
  • Loading branch information
RodZill4 committed Jul 18, 2023
1 parent df579f8 commit b73159d
Show file tree
Hide file tree
Showing 14 changed files with 872 additions and 39 deletions.
449 changes: 449 additions & 0 deletions addons/material_maker/bvh_generator.gd

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions addons/material_maker/engine/pipeline/compute_shader.gd
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ func do_render(rd : RenderingDevice, output_tex : RID, size : Vector2i, rids : R
var uniform_set_1 : RID = RID()
if parameter_values.size() > 0:
uniform_set_1 = get_parameter_uniforms(rd, shader, rids)
if ! uniform_set_1.is_valid():
print("Failed to create valid uniform for parameters")
return false

var uniform_set_2 = RID()
if !textures.is_empty():
Expand Down
2 changes: 1 addition & 1 deletion addons/material_maker/engine/pipeline/pipeline.gd
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func set_parameter(name : String, value) -> void:
p.value = value
match p.type:
"float":
if value is float:
if value is float or value is int:
parameter_values.encode_float(p.offset, value)
return
"int":
Expand Down
37 changes: 28 additions & 9 deletions addons/material_maker/engine/pipeline/rendering_pipeline.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extends MMPipeline
class_name MMRenderingPipeline

var shader : RID = RID()

var index_count : int = 0
var clearColors : PackedColorArray = PackedColorArray([Color.TRANSPARENT])
Expand All @@ -11,25 +12,24 @@ func create_framebuffer(rd : RenderingDevice, texture_rid : RID) -> RID:

return framebuffer

func compile_shader(rd : RenderingDevice, vertex_source : String, fragment_source : String, rids : RIDs, replaces : Dictionary = {}) -> RID:
var shader = do_compile_shader(rd, { vertex=vertex_source, fragment=fragment_source }, replaces)
rids.add(shader)
return shader

func bind_buffer_uniforms(rd : RenderingDevice, draw_list : int, shader : RID, buffers : Array[PackedByteArray], set : int, rids : RIDs):
var uniform_set : RID = rd.uniform_set_create(create_buffers_uniform_list(rd, buffers, rids), shader, set)
rids.add(uniform_set)
rd.draw_list_bind_uniform_set(draw_list, uniform_set, set)

func draw_list_extra_setup(rd : RenderingDevice, draw_list : int, shader : RID, rids : RIDs):
pass

func render(vertex_shader : String, fragment_shader : String, size : Vector2i, texture_type : int, target_texture : MMTexture, replaces : Dictionary = {}):

func set_shader(vertex_source : String, fragment_source : String, replaces : Dictionary = {}):
replaces["@DECLARATIONS"] = get_uniform_declarations()+"\n"+get_texture_declarations()
var rd : RenderingDevice = await mm_renderer.request_rendering_device(self)
shader = do_compile_shader(rd, { vertex=vertex_source, fragment=fragment_source }, replaces)
mm_renderer.release_rendering_device(self)

func render(size : Vector2i, texture_type : int, target_texture : MMTexture):
var rd : RenderingDevice = await mm_renderer.request_rendering_device(self)
var rids : RIDs = RIDs.new()

var shader = compile_shader(rd, vertex_shader, fragment_shader, rids)

var target_texture_id : RID = create_output_texture(rd, size, texture_type, true)
var framebuffer : RID = create_framebuffer(rd, target_texture_id)
rids.add(framebuffer)
Expand All @@ -53,6 +53,25 @@ func render(vertex_shader : String, fragment_shader : String, size : Vector2i, t
clearColors)
rd.draw_list_bind_render_pipeline(draw_list, pipeline)

var uniform_set_1 : RID = RID()
if parameter_values.size() > 0:
uniform_set_1 = get_parameter_uniforms(rd, shader, rids)
if ! uniform_set_1.is_valid():
print("Failed to create valid uniform for parameters")
return false

var uniform_set_2 = RID()
if !textures.is_empty():
uniform_set_2 = get_texture_uniforms(rd, shader, rids)
if ! uniform_set_2.is_valid():
print("Failed to create valid uniform for textures")
return false

if uniform_set_1.is_valid():
rd.draw_list_bind_uniform_set(draw_list, uniform_set_1, 1)
if uniform_set_2.is_valid():
rd.draw_list_bind_uniform_set(draw_list, uniform_set_2, 2)

draw_list_extra_setup(rd, draw_list, shader, rids)

rd.draw_list_draw(draw_list, index_count == 0, 1, index_count)
Expand Down
File renamed without changes.
263 changes: 263 additions & 0 deletions addons/material_maker/map_renderer/ao_fragment.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
[gd_resource type="Resource" script_class="TextResource" load_steps=2 format=3 uid="uid://cuveny5onbhr2"]

[ext_resource type="Script" path="res://addons/material_maker/engine/text_resource.gd" id="1_oqegj"]

[resource]
script = ExtResource("1_oqegj")
text = "#version 450
layout(location = 0) out vec4 outColor;
layout(location = 1) in vec3 model_vert;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec2 uv;
@DECLARATIONS
const float PI = 3.1415928;
float intersect_aabb(vec3 ray_origin, vec3 ray_dir, vec3 box_min, vec3 box_max, bool solid) {
vec3 tMin = (box_min - ray_origin) / ray_dir;
vec3 tMax = (box_max - ray_origin) / ray_dir;
vec3 t1 = min(tMin, tMax);
vec3 t2 = max(tMin, tMax);
float tNear = max(max(t1.x, t1.y), t1.z);
float tFar = min(min(t2.x, t2.y), t2.z);
if(tNear > tFar || (tFar < 0.0 && tNear < 0.0)) {
return -1.0;
}
if(tNear < 0.0) {
float temp = tNear;
tNear = tFar;
tFar = temp;
tNear *= float(!solid);
}
return tNear;
}
float intersects_triangle(vec3 ray_start, vec3 ray_dir, vec3 v0, vec3 v1, vec3 v2) {
vec3 e1 = v1 - v0;
vec3 e2 = v2 - v0;
vec3 h = cross(ray_dir, e2);
float a = dot(e1, h);
if (abs(a) < 0.000001) { // Parallel test.
return -1.0;
}
float f = 1.0 / a;
vec3 s = ray_start - v0;
float u = f * dot(s, h);
if (u < 0.0 || u > 1.0) {
return -1.0;
}
vec3 q = cross(s, e1);
float v = f * dot(ray_dir, q);
if (v < 0.0 || u + v > 1.0) {
return -1.0;
}
// At this stage we can compute t to find out where
// the intersection point is on the line.
float t = f * dot(e2, q);
return t > 0.0000001 ? t : -1.0;
}
vec4 get_data(int index) {
ivec2 data_size = textureSize(bvh_data, 0);
return texelFetch(bvh_data, ivec2(
index % data_size.x,
index / data_size.x
), 0);
}
float intersects_bvh(vec3 ray_start, vec3 ray_dir, out vec3 normal_hit) {
int offset_to_nodes = int(get_data(0)[0]);
vec4 root_data_0 = get_data(int(get_data(1)[0]) + offset_to_nodes);
vec4 root_data_1 = get_data(int(get_data(1)[0]) + offset_to_nodes + 1);
float t = intersect_aabb(ray_start, ray_dir, root_data_0.xyz, root_data_1.xyz, false);
if(t == -1.0) {
return 65536.0;
}
float prev_hit = t;
t = 65536.0; // Set to large number
vec3 tri[3];// = vec3[];
int min_node_idx = 0;
int stack_point = 0;
ivec3 node_stack[128];// = ivec3[]; // ivec3
int curr_node_idx = 0;
bool moving_up = false;
for(int i = 0; i < 256; i++) {
if(moving_up && stack_point <= 0) {
break;
}
int node_data_off = int(get_data(1 + curr_node_idx)[0]) + offset_to_nodes;
vec4 node_data_0 = get_data(node_data_off);
vec4 node_data_1 = get_data(node_data_off + 1);
int level = int(node_data_0[3]);
if(!moving_up) { // Moving down node hierarchy
if(node_data_1[3] > 0.0) { // Is a leaf node
for(int j = node_data_off + 2; j < node_data_off + 2 + int(node_data_1[3]) * 3; j+=3) {
vec3 tri_a = get_data(j).xyz;
vec3 tri_b = get_data(j + 1).xyz;
vec3 tri_c = get_data(j + 2).xyz;
float tri_t = intersects_triangle(ray_start, ray_dir,
tri_a, tri_b, tri_c
);
if(tri_t != -1.0) {
if(tri_t < t) {
tri[0] = tri_a;
tri[1] = tri_b;
tri[2] = tri_c;
// print(curr_node_idx)
min_node_idx = curr_node_idx;
}
t = min(t, tri_t);
}
}
stack_point -= 1;
if(stack_point <= 0) {
break;
}
if(node_stack[stack_point][1] == level) { // next node in stack is sibling
if(t < intBitsToFloat(node_stack[stack_point][0])) { // no chance to get better hit from sibling
stack_point -= 1;
moving_up = true;
}
} else {
moving_up = true;
}
prev_hit = intBitsToFloat(node_stack[stack_point][0]);
curr_node_idx = node_stack[stack_point][2];
} else {
// Push self onto stack
node_stack[stack_point] = ivec3(floatBitsToInt(prev_hit), level, curr_node_idx);
stack_point += 1;
ivec2 child_indices = ivec2(get_data(node_data_off + 2).xy);
int left_data_off = int(get_data(1 + child_indices[0])[0]) + offset_to_nodes;
vec4 left_data_0 = get_data(left_data_off);
vec4 left_data_1 = get_data(left_data_off + 1);
int right_data_off = int(get_data(1 + child_indices[1])[0]) + offset_to_nodes;
vec4 right_data_0 = get_data(right_data_off);
vec4 right_data_1 = get_data(right_data_off + 1);
float t_left = intersect_aabb(ray_start, ray_dir, left_data_0.xyz, left_data_1.xyz, true);
float t_right = intersect_aabb(ray_start, ray_dir, right_data_0.xyz, right_data_1.xyz, true);
if(t_right == -1.0 && t_left != -1.0) { // only left node hit
prev_hit = t_left;
curr_node_idx = child_indices[0];
} else if(t_left == -1.0 && t_right != -1.0) { // only right node hit
prev_hit = t_right;
curr_node_idx = child_indices[1];
} else if(t_left < t_right && t_left != -1.0) { // left node hits closer
node_stack[stack_point] = ivec3(floatBitsToInt(t_right), int(right_data_0[3]), child_indices[1]);
stack_point += 1;
prev_hit = t_left;
curr_node_idx = child_indices[0];
} else if(t_right <= t_left && t_right != -1.0) { // right node hits closer
node_stack[stack_point] = ivec3(floatBitsToInt(t_left), int(left_data_0[3]), child_indices[0]);
stack_point += 1;
prev_hit = t_right;
curr_node_idx = child_indices[1];
} else { // no hit
stack_point -= 2;
if(stack_point <= 0) {
break;
}
if(node_stack[stack_point][1] == level) { // next node in stack is sibling
if(t < intBitsToFloat(node_stack[stack_point][0])) { // no chance to get better hit from sibling
stack_point -= 1;
moving_up = true;
}
} else {
moving_up = true;
}
prev_hit = intBitsToFloat(node_stack[max(stack_point, 0)][0]);
curr_node_idx = node_stack[max(stack_point, 0)][2];
}
}
} else { // Moving up hierarchy
stack_point -= 1;
if(stack_point <= 0) {
break;
}
if(node_stack[stack_point][1] == level) { // next node in stack is sibling
if(t < intBitsToFloat(node_stack[stack_point][0])) { // no chance to get better hit from sibling
stack_point -= 1;
} else {
moving_up = false;
}
}
prev_hit = intBitsToFloat(node_stack[max(stack_point, 0)][0]);
curr_node_idx = node_stack[max(stack_point, 0)][2];
}
}
normal_hit = normalize(cross(tri[2] - tri[0], tri[1] - tri[0]));
return t;
}
vec3 random_hemi_point(vec3 rand, vec3 norm) {
float ang1 = (rand.x * 2.0) * PI; // [0..1) -> [0..2*PI)
float u = rand.y * 2.0 - 1.0; // [0..1), cos and acos(2v-1) cancel each other out, so we arrive at [-1..1)
float u2 = u * u;
float sqrt1MinusU2 = sqrt(1.0 - u2);
float x = sqrt1MinusU2 * cos(ang1);
float y = sqrt1MinusU2 * sin(ang1);
float z = u;
vec3 v = vec3(x, y, z);
return v * sign(dot(v, norm));
}
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main() {
vec3 model_norm = normalize(normal) * sign(max_dist);
/*
vec3 ddx_vert = dFdx(model_vert);
vec3 ddy_vert = dFdy(model_vert);
vec3 true_normal = normalize(cross(ddy_vert, ddx_vert)) * sign(max_dist);
*/
vec3 true_normal = model_norm;
vec3 ray_start = model_vert + model_norm * bias_dist;
vec3 ray_dir;
for(int i = 0; i < 5; i++) {
ray_dir = random_hemi_point(vec3(
rand(uv + float(iteration)),
rand(-uv.yx + float(iteration)),
0.0
), model_norm);
if(dot(ray_dir, true_normal) > 0.0) {
break;
}
}
vec3 normal_hit;
float hit = intersects_bvh(ray_start, ray_dir, normal_hit);
if(hit == 65536.0 || hit < 0.0 || hit > max_dist) {
hit = 1.0;
} else{
hit = 1.0 - clamp(dot(model_norm, ray_dir),0.0,1.0);
}
outColor = vec4(mix(texture(prev_iteration_tex, uv).rgb, vec3(hit), 1.0/float(iteration)), 1.0);
}
"
35 changes: 35 additions & 0 deletions addons/material_maker/map_renderer/ao_vertex.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[gd_resource type="Resource" script_class="TextResource" load_steps=2 format=3 uid="uid://cabcobt82hrux"]

[ext_resource type="Script" path="res://addons/material_maker/engine/text_resource.gd" id="1_0bvqj"]

[resource]
script = ExtResource("1_0bvqj")
text = "#version 450
layout(location = 1) out vec3 model_vert;
layout(location = 2) out vec3 normal;
layout(location = 3) out vec2 uv;
layout(binding = 0, std430) buffer restrict readonly Positions {
float positions[];
};
layout(binding = 1, std430) buffer restrict readonly AABB {
float aabb[];
};
layout(binding = 2, std430) buffer restrict readonly Normals {
float normals[];
};
layout(binding = 3, std430) buffer restrict readonly Tangents {
float tangents[];
};
layout(binding = 4, std430) buffer restrict readonly UVs {
vec2 uvs[];
};
void main() {
model_vert = vec3(positions[3*gl_VertexIndex], positions[3*gl_VertexIndex+1], positions[3*gl_VertexIndex+2]);
normal = vec3(normals[3*gl_VertexIndex], normals[3*gl_VertexIndex+1], normals[3*gl_VertexIndex+2]);
uv = uvs[gl_VertexIndex];
gl_Position = vec4(uv*2.0-vec2(1.0), 0.0, 1.0);
}
"
Loading

0 comments on commit b73159d

Please sign in to comment.