diff --git a/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index a1e2567a28..91ccb21155 100644 --- a/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -14,17 +14,12 @@ uniform mat4 P; uniform mat3 V3; uniform vec2 cameraProj; -#ifdef _CPostprocess -uniform vec3 PPComp9; -uniform vec3 PPComp10; -#endif - in vec3 viewRay; in vec2 texCoord; out vec4 fragColor; vec3 hitCoord; -float d; +float depth; const int numBinarySearchSteps = 7; const int maxSteps = int(ceil(1.0 / ss_refractionRayStep) * ss_refractionSearchDist); @@ -39,14 +34,12 @@ vec2 getProjectedCoord(const vec3 hit) { return projectedCoord.xy; } - float getDeltaDepth(const vec3 hit) { - d = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0; - vec3 viewPos = normalize(getPosView(viewRay, d, cameraProj)); + depth = textureLod(gbufferD1, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0; + vec3 viewPos = getPosView(viewRay, depth, cameraProj); return viewPos.z - hit.z; } - vec4 binarySearch(vec3 dir) { float ddepth; for (int i = 0; i < numBinarySearchSteps; i++) { @@ -55,28 +48,17 @@ vec4 binarySearch(vec3 dir) { ddepth = getDeltaDepth(hitCoord); if (ddepth < 0.0) hitCoord += dir; } - // Ugly discard of hits too far away - //using a divider of 500 doesn't work here unless the distance is set to at least 500 for a blender unit. - #ifdef _CPostprocess - if (abs(ddepth) > PPComp9.z) return vec4(texCoord.xy, 0.0, 0.0); - #else - if (abs(ddepth) > ss_refractionSearchDist) return vec4(texCoord.xy, 0.0, 0.0); - #endif + if (abs(ddepth) > ss_refractionSearchDist / 500) return vec4(0.0); return vec4(getProjectedCoord(hitCoord), 0.0, 1.0); } - vec4 rayCast(vec3 dir) { float ddepth; - #ifdef _CPostprocess - dir *= PPComp9.x; - #else - dir *= ss_refractionRayStep; - #endif + dir *= ss_refractionRayStep; for (int i = 0; i < maxSteps; i++) { hitCoord += dir; ddepth = getDeltaDepth(hitCoord); - if (ddepth > d) return binarySearch(dir); + if (ddepth > 0.0) return binarySearch(dir); } return vec4(0.0); } @@ -88,7 +70,7 @@ void main() { float ior = gr.x; float opac = gr.y; - d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; if (d == 1.0 || ior == 1.0 || opac == 1.0) { fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; @@ -99,18 +81,13 @@ void main() { vec3 n; n.z = 1.0 - abs(enc.x) - abs(enc.y); n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); - n = normalize(n); vec3 viewNormal = V3 * n; - vec3 viewPos = normalize(getPosView(viewRay, d, cameraProj)); - vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior); + vec3 viewPos = getPosView(viewRay, d, cameraProj); + vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior); hitCoord = viewPos; -#ifdef _CPostprocess - vec3 dir = refracted * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0; -#else vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0; -#endif vec4 coords = rayCast(dir); vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); @@ -118,11 +95,7 @@ void main() { float refractivity = 1.0; -#ifdef _CPostprocess - float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * clamp(-refracted.z, 0.0, 1.0) * clamp((PPComp9.z - length(viewPos - hitCoord)) * (1.0 / PPComp9.z), 0.0, 1.0) * coords.w; -#else float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * clamp((ss_refractionSearchDist - length(viewPos - hitCoord)) * (1.0 / ss_refractionSearchDist), 0.0, 1.0) * coords.w; -#endif intensity = clamp(intensity, 0.0, 1.0); vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb; diff --git a/Shaders/ssrefr_pass/ssrefr_pass.json b/Shaders/ssrefr_pass/ssrefr_pass.json index 4a86991140..716f2180e6 100755 --- a/Shaders/ssrefr_pass/ssrefr_pass.json +++ b/Shaders/ssrefr_pass/ssrefr_pass.json @@ -29,16 +29,6 @@ { "name": "cameraProj", "link": "_cameraPlaneProj" - }, - { - "name": "PPComp9", - "link": "_PPComp9", - "ifdef": ["_CPostprocess"] - }, - { - "name": "PPComp10", - "link": "_PPComp10", - "ifdef": ["_CPostprocess"] } ], "vertex_shader": "../include/pass_viewray2.vert.glsl", diff --git a/Sources/armory/renderpath/RenderPathDeferred.hx b/Sources/armory/renderpath/RenderPathDeferred.hx index afa234427e..e7f14aec20 100644 --- a/Sources/armory/renderpath/RenderPathDeferred.hx +++ b/Sources/armory/renderpath/RenderPathDeferred.hx @@ -344,7 +344,7 @@ class RenderPathDeferred { t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); - //holds colors before refractive meshes are drawn + // holds colors before refractive meshes are drawn var t = new RenderTargetRaw(); t.name = "refr"; t.width = 0; @@ -355,13 +355,13 @@ class RenderPathDeferred { t.depth_buffer = "main"; path.createRenderTarget(t); - //holds background depth + // holds background depth var t = new RenderTargetRaw(); t.name = "gbufferD1"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); - t.format = "DEPTH16"; + t.format = "R32"; t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); } @@ -763,10 +763,6 @@ class RenderPathDeferred { { if (armory.data.Config.raw.rp_ssrefr != false) { - #if (!kha_opengl) - path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it - #end - //save depth path.setTarget("gbufferD1"); path.bindTarget("_main", "tex"); @@ -777,73 +773,9 @@ class RenderPathDeferred { path.bindTarget("tex", "tex"); path.drawShader("shader_datas/copy_pass/copy_pass"); - RenderPathCreator.setTargetMeshes(); + path.setTarget("tex", ["gbuffer0", "gbuffer_refraction"]); path.drawMeshes("refraction"); - path.setTarget("tex"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.bindTarget("gbuffer1", "gbuffer1"); - - #if rp_gbuffer2 - { - path.bindTarget("gbuffer2", "gbuffer2"); - } - #end - - #if rp_gbuffer_emission - { - path.bindTarget("gbuffer_emission", "gbufferEmission"); - } - #end - - #if (rp_ssgi != "Off") - { - if (armory.data.Config.raw.rp_ssgi != false) { - path.bindTarget("singlea", "ssaotex"); - } - else { - path.bindTarget("empty_white", "ssaotex"); - } - } - #end - - var voxelao_pass = false; - #if rp_voxelao - if (armory.data.Config.raw.rp_voxels != false) - { - #if arm_config - voxelao_pass = true; - #end - path.bindTarget(voxels, "voxels"); - #if arm_voxelgi_temporal - { - path.bindTarget(voxelsLast, "voxelsLast"); - } - #end - } - #end - - #if rp_shadowmap - { - #if arm_shadowmap_atlas - Inc.bindShadowMapAtlas(); - #else - Inc.bindShadowMap(); - #end - } - #end - - #if rp_material_solid - path.drawShader("shader_datas/deferred_light_solid/deferred_light"); - #elseif rp_material_mobile - path.drawShader("shader_datas/deferred_light_mobile/deferred_light"); - #else - voxelao_pass ? - path.drawShader("shader_datas/deferred_light/deferred_light_VoxelAOvar") : - path.drawShader("shader_datas/deferred_light/deferred_light"); - #end - path.setTarget("tex"); path.bindTarget("refr", "tex1"); path.bindTarget("tex", "tex"); @@ -852,10 +784,6 @@ class RenderPathDeferred { path.bindTarget("gbuffer0", "gbuffer0"); path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); - - #if (!kha_opengl) - path.setDepthFrom("tex", "gbuffer0"); - #end } } #end diff --git a/Sources/armory/renderpath/RenderPathForward.hx b/Sources/armory/renderpath/RenderPathForward.hx index 13757b9538..0df28f28cd 100644 --- a/Sources/armory/renderpath/RenderPathForward.hx +++ b/Sources/armory/renderpath/RenderPathForward.hx @@ -111,7 +111,7 @@ class RenderPathForward { t.name = "lbuffer1"; t.width = 0; t.height = 0; - t.format = "RGBA64"; + t.format = Inc.getHdrFormat(); t.displayp = Inc.getDisplayp(); t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); @@ -147,7 +147,7 @@ class RenderPathForward { t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); - t.format = "DEPTH16"; + t.format = "R32"; t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); } diff --git a/blender/arm/material/cycles_nodes/nodes_shader.py b/blender/arm/material/cycles_nodes/nodes_shader.py index 449e679497..75c7528979 100644 --- a/blender/arm/material/cycles_nodes/nodes_shader.py +++ b/blender/arm/material/cycles_nodes/nodes_shader.py @@ -158,7 +158,7 @@ def parse_bsdfglass(node: bpy.types.ShaderNodeBsdfGlass, out_socket: NodeSocket, c.write_normal(node.inputs[3]) state.out_roughness = c.parse_value_input(node.inputs[1]) if state.parse_opacity: - state.out_opacity = '0.5' # for refraction mix(refraction, color) + state.out_opacity = '0.0' state.out_ior = c.parse_value_input(node.inputs[2]) diff --git a/blender/arm/material/make_mesh.py b/blender/arm/material/make_mesh.py index ad7d0d0fc7..2933a02cca 100644 --- a/blender/arm/material/make_mesh.py +++ b/blender/arm/material/make_mesh.py @@ -195,7 +195,7 @@ def make_deferred(con_mesh, rpasses): rpdat = arm.utils.get_rp() arm_discard = mat_state.material.arm_discard - parse_opacity = arm_discard or 'translucent' in rpasses or 'refraction' in rpasses + parse_opacity = arm_discard or 'translucent' make_base(con_mesh, parse_opacity=parse_opacity) @@ -203,7 +203,7 @@ def make_deferred(con_mesh, rpasses): vert = con_mesh.vert tese = con_mesh.tese - if parse_opacity and not 'refraction' in rpasses: + if parse_opacity: if arm_discard: opac = mat_state.material.arm_discard_opacity else: @@ -547,9 +547,9 @@ def make_forward(con_mesh): if not blend: mrt = 0 # mrt: multiple render targets if rpdat.rp_ssr: - mrt += 1 + mrt = 1 if rpdat.rp_ss_refraction: - mrt += 1 + mrt = 2 if mrt != 0: # Store light gbuffer for post-processing frag.add_out(f'vec4 fragColor[{mrt}+1]') @@ -590,7 +590,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag = con_mesh.frag tese = con_mesh.tese - if (parse_opacity or arm_discard) and not '_SSRefraction' in wrd.world_defs: + if parse_opacity or arm_discard: if arm_discard or blend: opac = mat_state.material.arm_discard_opacity frag.write('if (opacity < {0}) discard;'.format(opac)) diff --git a/blender/arm/material/make_refract.py b/blender/arm/material/make_refract.py new file mode 100644 index 0000000000..6d13230128 --- /dev/null +++ b/blender/arm/material/make_refract.py @@ -0,0 +1,48 @@ +import bpy + +import arm +import arm.material.cycles as cycles +import arm.material.mat_state as mat_state +import arm.material.make_mesh as make_mesh +import arm.material.make_finalize as make_finalize +import arm.assets as assets + +if arm.is_reload(__name__): + cycles = arm.reload_module(cycles) + mat_state = arm.reload_module(mat_state) + make_mesh = arm.reload_module(make_mesh) + make_finalize = arm.reload_module(make_finalize) + assets = arm.reload_module(assets) +else: + arm.enable_reload(__name__) + + +def make(context_id): + con_refract = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' }) + + make_mesh.make_forward_base(con_refract, parse_opacity=True, transluc_pass=True) + + vert = con_refract.vert + frag = con_refract.frag + tese = con_refract.tese + + frag.add_include('std/gbuffer.glsl') + frag.add_out('vec4 fragColor[3]') + + # Remove fragColor = ...; + frag.main = frag.main[:frag.main.rfind('fragColor')] + frag.write('\n') + + wrd = bpy.data.worlds['Arm'] + + frag.write('n /= (abs(n.x) + abs(n.y) + abs(n.z));') + frag.write('n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);') + frag.write('fragColor[0] = vec4(direct + indirect, packFloat2(occlusion, specular));') + frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') + frag.write('fragColor[2] = vec4(ior, opacity, 0.0, 0.0);') + make_finalize.make(con_refract) + + # assets.vs_equal(con_refract, assets.shader_cons['transluc_vert']) # shader_cons has no transluc yet + # assets.fs_equal(con_refract, assets.shader_cons['transluc_frag']) + + return con_refract diff --git a/blender/arm/material/make_shader.py b/blender/arm/material/make_shader.py index 115b3b0127..4126ff663d 100644 --- a/blender/arm/material/make_shader.py +++ b/blender/arm/material/make_shader.py @@ -16,6 +16,7 @@ import arm.material.make_mesh as make_mesh import arm.material.make_overlay as make_overlay import arm.material.make_transluc as make_transluc +import arm.material.make_refract as make_refract import arm.material.make_voxel as make_voxel import arm.material.mat_state as mat_state import arm.material.mat_utils as mat_utils @@ -96,7 +97,7 @@ def build(material: Material, mat_users: Dict[Material, List[Object]], mat_armus con = make_transluc.make(rp) elif rp == 'refraction': - con = make_mesh.make(rp, rpasses) + con = make_refract.make(rp) elif rp == 'overlay': con = make_overlay.make(rp) diff --git a/blender/arm/material/mat_utils.py b/blender/arm/material/mat_utils.py index f660ce4d8b..2809f6e143 100644 --- a/blender/arm/material/mat_utils.py +++ b/blender/arm/material/mat_utils.py @@ -42,14 +42,14 @@ def get_rpasses(material): ar.append('decal') elif material.arm_overlay: ar.append('overlay') - elif is_transluc(material) and not material.arm_discard and not material.arm_blending and rpdat.rp_ss_refraction: - ar.append('refraction') else: ar.append('mesh') for con in add_mesh_contexts: ar.append(con) - if is_transluc(material) and not material.arm_discard and rpdat.rp_translucency_state != 'Off' and not material.arm_blending: + if is_transluc(material) and not material.arm_discard and rpdat.rp_translucency_state != 'Off' and not material.arm_blending and not rpdat.rp_ss_refraction: ar.append('translucent') + elif is_transluc(material) and not material.arm_discard and not material.arm_blending and rpdat.rp_ss_refraction: + ar.append('refraction') if rpdat.rp_voxelao and has_voxels: ar.append('voxel') if rpdat.rp_renderer == 'Forward' and rpdat.rp_depthprepass and not material.arm_blending and not material.arm_particle_flag: