diff --git a/resources/core/shader/dof_coc_fs.sc b/resources/core/shader/dof_coc_fs.sc new file mode 100644 index 0000000..e78ada9 --- /dev/null +++ b/resources/core/shader/dof_coc_fs.sc @@ -0,0 +1,53 @@ +// spiral sampling from https://blog.voxagon.se/2018/05/04/bokeh-depth-of-field-in-single-pass.html + +#include + +SAMPLER2D(u_color, 0); +SAMPLER2D(u_attr0, 1); + +uniform vec4 u_params; // x: focus point, y: focus_length + +#define GOLDEN_ANGLE 2.39996323 +#define MAX_BLUR_SIZE 20.0 +#define RAD_SCALE 0.75 // Smaller = nicer blur, larger = faster + +float ComputeCoC(float depth) { + return clamp(abs(depth - u_params.x) / u_params.y, 0.0, 1.0) * MAX_BLUR_SIZE; +} + +void main() { + // reference pixel + vec2 uv = gl_FragCoord.xy / uResolution.xy; + vec4 ref_color = texture2D(u_color, uv); + float ref_depth = texture2D(u_attr0, uv).w; + + float ref_coc = ComputeCoC(ref_depth); + + // sample CoC + float smp_count = 1.0; + vec4 dof_out = ref_color; + + float radius = RAD_SCALE; + + for (float a = 0.0; radius < MAX_BLUR_SIZE; a += GOLDEN_ANGLE) { + vec2 smp_uv = (gl_FragCoord.xy + vec2(cos(a) * radius, sin(a) * radius)) / uResolution.xy; + + float smp_depth = texture2D(u_attr0, smp_uv).w; + vec4 smp_color = texture2D(u_color, smp_uv); + + float coc = ref_coc; + + if (smp_depth <= ref_depth) { + float smp_coc = ComputeCoC(smp_depth); + coc = min(ref_coc, smp_coc); + } + + float k = smoothstep(radius - 0.5, radius + 0.5, coc); + dof_out += mix(dof_out / smp_count, smp_color, k); + + smp_count += 1.0; + radius += RAD_SCALE / radius; + } + + gl_FragColor = dof_out / smp_count; +} diff --git a/resources/core/shader/dof_coc_varying.def b/resources/core/shader/dof_coc_varying.def new file mode 100644 index 0000000..8fdde79 --- /dev/null +++ b/resources/core/shader/dof_coc_varying.def @@ -0,0 +1,4 @@ +vec2 v_texcoord0 : TEXCOORD0; + +vec3 a_position : POSITION; +vec2 a_texcoord0 : TEXCOORD0; diff --git a/resources/core/shader/dof_coc_vs.sc b/resources/core/shader/dof_coc_vs.sc new file mode 100644 index 0000000..968f4f2 --- /dev/null +++ b/resources/core/shader/dof_coc_vs.sc @@ -0,0 +1,8 @@ +$input a_position, a_texcoord0 + +// HARFANG(R) Copyright (C) 2022 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details. +#include + +void main() { + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +} diff --git a/scene_dof.py b/scene_dof.py new file mode 100644 index 0000000..90d127e --- /dev/null +++ b/scene_dof.py @@ -0,0 +1,56 @@ +# Toyota 2JZ-GTE Engine model by Serhii Denysenko (CGTrader: serhiidenysenko8256) +# URL : https://www.cgtrader.com/3d-models/vehicle/part/toyota-2jz-gte-engine-2932b715-2f42-4ecd-93ce-df9507c67ce8 + +import harfang as hg +from random import uniform + +hg.InputInit() +hg.WindowSystemInit() + +res_x, res_y = 1280, 720 +win = hg.RenderInit('AAA Scene', res_x, res_y, hg.RF_VSync | hg.RF_MSAA4X) + +# +pipeline = hg.CreateForwardPipeline() +res = hg.PipelineResources() + +hg.AddAssetsFolder("resources_compiled") + +# load scene +scene = hg.Scene() +hg.LoadSceneFromAssets("car_engine/engine.scn", scene, res, hg.GetForwardPipelineInfo()) + +# AAA pipeline +pipeline_aaa_config = hg.ForwardPipelineAAAConfig() +pipeline_aaa = hg.CreateForwardPipelineAAAFromAssets("core", pipeline_aaa_config, hg.BR_Equal, hg.BR_Equal) +pipeline_aaa_config.sample_count = 1 +target_dof_focus_point = 3.5 +target_dof_focus_length = 2.0 +pipeline_aaa_config.dof_focus_point = target_dof_focus_point # Distance to the focus point (in meters) +pipeline_aaa_config.dof_focus_length = target_dof_focus_length # Depth of field (in meters); smaller values result in a narrower focused area. + +# main loop +frame = 0 + +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): + dt = hg.TickClock() + + trs = scene.GetNode('engine_master').GetTransform() + trs.SetRot(trs.GetRot() + hg.Vec3(0, hg.Deg(15) * hg.time_to_sec_f(dt), 0)) + + # change DOF randomly + if frame%250 == 0: + target_dof_focus_point = uniform(2.5, 3.5) + target_dof_focus_length = uniform(0.5, 2.0) + + pipeline_aaa_config.dof_focus_point = hg.Lerp(pipeline_aaa_config.dof_focus_point, target_dof_focus_point, 0.1) + pipeline_aaa_config.dof_focus_length = hg.Lerp(pipeline_aaa_config.dof_focus_length, target_dof_focus_length, 0.1) + + scene.Update(dt) + hg.SubmitSceneToPipeline(0, scene, hg.IntRect(0, 0, res_x, res_y), True, pipeline, res, pipeline_aaa, pipeline_aaa_config, frame) + + frame = hg.Frame() + hg.UpdateWindow(win) + +hg.RenderShutdown() +hg.DestroyWindow(win)