diff --git a/Shaders/deferred_light_mobile/deferred_light.frag.glsl b/Shaders/deferred_light_mobile/deferred_light.frag.glsl new file mode 100644 index 00000000..d21db2b3 --- /dev/null +++ b/Shaders/deferred_light_mobile/deferred_light.frag.glsl @@ -0,0 +1,255 @@ +#version 450 + +#include "compiled.inc" +#include "std/gbuffer.glsl" +#include "std/math.glsl" +#include "std/brdf.glsl" +#ifdef _Clusters +#include "std/clusters.glsl" +#endif +#ifdef _ShadowMap +#include "std/shadows.glsl" +#endif +#ifdef _Irr +#include "std/shirr.glsl" +#endif + +uniform sampler2D gbufferD; +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; + +uniform float envmapStrength; +#ifdef _Irr +//!uniform vec4 shirr[7]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + +uniform vec2 cameraProj; +uniform vec3 eye; +uniform vec3 eyeLook; + +#ifdef _Clusters +uniform vec4 lightsArray[maxLights * 2]; + #ifdef _Spot + uniform vec4 lightsArraySpot[maxLights]; + #endif +uniform sampler2D clustersData; +uniform vec2 cameraPlane; +#ifdef _ShadowMap + #ifdef _ShadowMapCube + uniform vec2 lightProj; + // uniform samplerCubeShadow shadowMap0; //arm_dev + uniform samplerCube shadowMap0; + // uniform samplerCube shadowMap1; + // uniform samplerCube shadowMap2; + // uniform samplerCube shadowMap3; + #else + uniform sampler2D shadowMap0; + // uniform sampler2D shadowMap1; + // uniform sampler2D shadowMap2; + // uniform sampler2D shadowMap3; + uniform mat4 LWVP0; + // uniform mat4 LWVP1; + // uniform mat4 LWVP2; + // uniform mat4 LWVP3; + #endif + #ifdef _Spot + uniform sampler2D shadowMapSpot0; + // uniform sampler2D shadowMapSpot1; + // uniform sampler2D shadowMapSpot2; + // uniform sampler2D shadowMapSpot3; + uniform mat4 LWVPSpot0; + // uniform mat4 LWVPSpot1; + // uniform mat4 LWVPSpot2; + // uniform mat4 LWVPSpot3; + #endif +#endif // _ShadowMap +#endif // _Clusters + +#ifdef _Sun +uniform vec3 sunDir; +uniform vec3 sunCol; + #ifdef _ShadowMap + // uniform sampler2DShadow shadowMap; // arm_dev + uniform sampler2D shadowMap; + uniform float shadowsBias; + #ifdef _CSM + //!uniform vec4 casData[shadowmapCascades * 4 + 4]; + #else + uniform mat4 LWVP; + #endif + // #ifdef _SoftShadows + // uniform sampler2D svisibility; + // #else + #endif // _ShadowMap +#endif + +in vec2 texCoord; +in vec3 viewRay; +out vec4 fragColor; + +void main() { + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, metallic/roughness, depth + + vec3 n; + n.z = 1.0 - abs(g0.x) - abs(g0.y); + n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); + n = normalize(n); + + vec2 metrough = unpackFloat(g0.b); + vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ + vec2 occspec = unpackFloat2(g1.a); + vec3 albedo = surfaceAlbedo(g1.rgb, metrough.x); // g1.rgb - basecolor + vec3 f0 = surfaceF0(g1.rgb, metrough.x); + + float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec3 v = normalize(eye - p); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _Brdf + vec2 envBRDF = textureLod(senvmapBrdf, vec2(metrough.y, 1.0 - dotNV), 0.0).xy; +#endif + + // Envmap +#ifdef _Irr + vec3 envl = shIrradiance(n); + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(1.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(metrough.y, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y; +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * surfaceF0(g1.rgb, metrough.x); // f0 + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + fragColor.rgb = envl; + +#ifdef _Sun + vec3 sh = normalize(v + sunDir); + float sdotNH = dot(n, sh); + float sdotVH = dot(v, sh); + float sdotNL = dot(n, sunDir); + float svisibility = 1.0; + vec3 sdirect = albedo * max(sdotNL, 0.0) + + specularBRDF(f0, metrough.y, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y; + + #ifdef _ShadowMap + // if (lightShadow == 1) { + #ifdef _CSM + svisibility = shadowTestCascade(shadowMap, eye, p + n * shadowsBias * 10, shadowsBias, shadowmapSize * vec2(shadowmapCascades, 1.0)); + #else + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); + if (lPos.w > 0.0) svisibility = shadowTest(shadowMap, lPos.xyz / lPos.w, shadowsBias, shadowmapSize); + #endif + // } + #endif + + fragColor.rgb += sdirect * svisibility * sunCol; +#endif + +#ifdef _Clusters + float viewz = linearize(depth * 0.5 + 0.5, cameraProj); + int clusterI = getClusterI(texCoord, viewz, cameraPlane); + int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); + + #ifdef HLSL + viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler + #endif + + #ifdef _Spot + int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); + int numPoints = numLights - numSpots; + #endif + + for (int i = 0; i < min(numLights, maxLightsCluster); i++) { + int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); + + // lightsArray[li * 2 ] - pos + // lightsArray[li * 2 + 1] - color + // lightsArraySpot[li] - (spot)dir + + vec3 lp = lightsArray[li * 2].xyz; + vec3 ld = lp - p; + vec3 l = normalize(ld); + vec3 h = normalize(v + l); + float dotNH = dot(n, h); + float dotVH = dot(v, h); + float dotNL = dot(n, l); + + vec3 direct = albedo * max(dotNL, 0.0) + + specularBRDF(f0, metrough.y, dotNL, dotNH, dotNV, dotVH) * occspec.y; + + direct *= lightsArray[li * 2 + 1].xyz; + + float visibility = attenuate(distance(p, lp)); + + #ifdef _Spot + if (i > numPoints - 1) { + float spotEffect = dot(lightsArraySpot[li].xyz, l); // lightDir + // x - cutoff, y - cutoff - exponent + if (spotEffect < lightsArray[li * 2 + 1].w) { + visibility *= smoothstep(lightsArraySpot[li].w, lightsArray[li * 2 + 1].w, spotEffect); + } + } + #endif + + #ifdef _LightIES + visibility *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + // if (lightShadow == 1) { + float bias = lightsArray[li * 2].w; + #ifdef _ShadowMapCube + visibility *= PCFCube(shadowMap0, ld, -l, bias, lightProj, n); + #else + vec4 lPos = LWVP0 * vec4(p + n * bias * 10, 1.0); + if (lPos.w > 0.0) { + #ifdef _SMSizeUniform + visibility *= shadowTest(shadowMap0, lPos.xyz / lPos.w, bias, smSizeUniform); + #else + visibility *= shadowTest(shadowMap0, lPos.xyz / lPos.w, bias, shadowmapSizeCube); + #endif + } + #endif + // } + #endif // _ShadowMap + + fragColor.rgb += direct * visibility; + } + +#endif +} diff --git a/Shaders/deferred_light_mobile/deferred_light_mobile.json b/Shaders/deferred_light_mobile/deferred_light_mobile.json new file mode 100644 index 00000000..b799b541 --- /dev/null +++ b/Shaders/deferred_light_mobile/deferred_light_mobile.json @@ -0,0 +1,110 @@ +{ + "contexts": [ + { + "name": "deferred_light", + "depth_write": false, + "compare_mode": "always", + "cull_mode": "none", + "links": [ + { + "name": "eye", + "link": "_cameraPosition" + }, + { + "name": "eyeLook", + "link": "_cameraLook" + }, + { + "name": "invVP", + "link": "_inverseViewProjectionMatrix" + }, + { + "name": "shirr", + "link": "_envmapIrradiance", + "ifdef": ["_Irr"] + }, + { + "name": "senvmapRadiance", + "link": "_envmapRadiance", + "ifdef": ["_Rad"] + }, + { + "name": "envmapNumMipmaps", + "link": "_envmapNumMipmaps", + "ifdef": ["_Rad"] + }, + { + "name": "senvmapBrdf", + "link": "_envmapBrdf", + "ifdef": ["_Brdf"] + }, + { + "name": "cameraProj", + "link": "_cameraPlaneProj" + }, + { + "name": "envmapStrength", + "link": "_envmapStrength" + }, + { + "name": "backgroundCol", + "link": "_backgroundCol", + "ifdef": ["_EnvCol"] + }, + { + "name": "lightsArray", + "link": "_lightsArray", + "ifdef": ["_Clusters"] + }, + { + "name": "lightsArraySpot", + "link": "_lightsArraySpot", + "ifdef": ["_Spot"] + }, + { + "name": "clustersData", + "link": "_clustersData", + "ifdef": ["_Clusters"] + }, + { + "name": "cameraPlane", + "link": "_cameraPlane", + "ifdef": ["_Clusters"] + }, + { + "name": "sunDir", + "link": "_sunDirection", + "ifdef": ["_Sun"] + }, + { + "name": "sunCol", + "link": "_sunColor", + "ifdef": ["_Sun"] + }, + { + "name": "shadowsBias", + "link": "_sunShadowsBias", + "ifdef": ["_Sun", "_ShadowMap"] + }, + { + "name": "LWVP", + "link": "_biasLightWorldViewProjectionMatrix", + "ifndef": ["_CSM"], + "ifdef": ["_Sun", "_ShadowMap"] + }, + { + "name": "casData", + "link": "_cascadeData", + "ifdef": ["_Sun", "_ShadowMap", "_CSM"] + }, + { + "name": "lightProj", + "link": "_lightPlaneProj", + "ifdef": ["_Clusters", "_ShadowMapCube"] + } + ], + "vertex_shader": "../include/pass_viewray.vert.glsl", + "fragment_shader": "deferred_light.frag.glsl" + } + ] +} diff --git a/Shaders/deferred_light_solid/deferred_light.frag.glsl b/Shaders/deferred_light_solid/deferred_light.frag.glsl new file mode 100644 index 00000000..ccc79ea9 --- /dev/null +++ b/Shaders/deferred_light_solid/deferred_light.frag.glsl @@ -0,0 +1,15 @@ +#version 450 + +#include "compiled.inc" +#include "std/gbuffer.glsl" + +uniform sampler2D gbufferD; +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; + +in vec2 texCoord; +out vec4 fragColor; + +void main() { + fragColor.rgb = textureLod(gbuffer1, texCoord, 0.0).rgb; // Basecolor.rgb +} diff --git a/Shaders/deferred_light_solid/deferred_light_solid.json b/Shaders/deferred_light_solid/deferred_light_solid.json new file mode 100644 index 00000000..822c2de7 --- /dev/null +++ b/Shaders/deferred_light_solid/deferred_light_solid.json @@ -0,0 +1,13 @@ +{ + "contexts": [ + { + "name": "deferred_light", + "depth_write": false, + "compare_mode": "always", + "cull_mode": "none", + "links": [], + "vertex_shader": "../include/pass.vert.glsl", + "fragment_shader": "deferred_light.frag.glsl" + } + ] +} diff --git a/Shaders/ssr_pass/ssr_pass.frag.glsl b/Shaders/ssr_pass/ssr_pass.frag.glsl index 72234691..c5d06198 100755 --- a/Shaders/ssr_pass/ssr_pass.frag.glsl +++ b/Shaders/ssr_pass/ssr_pass.frag.glsl @@ -48,7 +48,7 @@ vec4 binarySearch(vec3 dir) { if (ddepth < 0.0) hitCoord += dir; } // Ugly discard of hits too far away - if (abs(ddepth) > ssrSearchDist / 50) return vec4(0.0); + if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0); return vec4(getProjectedCoord(hitCoord), 0.0, 1.0); } diff --git a/Shaders/std/clusters.glsl b/Shaders/std/clusters.glsl index 762e36ef..9c9786b4 100644 --- a/Shaders/std/clusters.glsl +++ b/Shaders/std/clusters.glsl @@ -6,8 +6,9 @@ const vec3 clusterSlices = vec3(16, 16, 16); int getClusterI(vec2 tc, float viewz, vec2 cameraPlane) { int sliceZ = 0; - if (viewz >= clusterNear) { - float z = log(viewz - clusterNear + 1.0) / log(cameraPlane.y - clusterNear + 1.0); + float cnear = clusterNear + cameraPlane.x; + if (viewz >= cnear) { + float z = log(viewz - cnear + 1.0) / log(cameraPlane.y - cnear + 1.0); sliceZ = int(z * (clusterSlices.z - 1)) + 1; } return int(tc.x * clusterSlices.x) + diff --git a/Sources/armory/renderpath/RenderPathDeferred.hx b/Sources/armory/renderpath/RenderPathDeferred.hx index 7a9c0fc7..d2e3e20e 100644 --- a/Sources/armory/renderpath/RenderPathDeferred.hx +++ b/Sources/armory/renderpath/RenderPathDeferred.hx @@ -143,7 +143,13 @@ class RenderPathDeferred { } #end + #if rp_material_solid + path.loadShader("shader_datas/deferred_light_solid/deferred_light"); + #elseif rp_material_mobile + path.loadShader("shader_datas/deferred_light_mobile/deferred_light"); + #else path.loadShader("shader_datas/deferred_light/deferred_light"); + #end #if rp_probes path.loadShader("shader_datas/probe_planar/probe_planar"); @@ -664,9 +670,15 @@ class RenderPathDeferred { } #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.setDepthFrom("tex", "gbuffer0"); // Re-bind depth #if rp_probes diff --git a/blender/arm/make_renderpath.py b/blender/arm/make_renderpath.py index 14e418a5..4131b6b3 100755 --- a/blender/arm/make_renderpath.py +++ b/blender/arm/make_renderpath.py @@ -38,7 +38,7 @@ def add_world_defs(): voxelgi = False voxelao = False has_voxels = arm.utils.voxel_support() - if has_voxels: + if has_voxels and rpdat.arm_material_model == 'Full': if rpdat.rp_gi == 'Voxel GI': voxelgi = True elif rpdat.rp_gi == 'Voxel AO': @@ -236,12 +236,12 @@ def build(): rp_gi = rpdat.rp_gi has_voxels = arm.utils.voxel_support() - if not has_voxels: + if not has_voxels or rpdat.arm_material_model != 'Full': rp_gi = 'Off' assets.add_khafile_def('rp_gi={0}'.format(rp_gi)) - if rpdat.rp_gi != 'Off': + if rp_gi != 'Off': if has_voxels: - assets.add_khafile_def('rp_gi={0}'.format(rpdat.rp_gi)) + assets.add_khafile_def('rp_gi={0}'.format(rp_gi)) assets.add_khafile_def('rp_voxelgi_resolution={0}'.format(rpdat.rp_voxelgi_resolution)) assets.add_khafile_def('rp_voxelgi_resolution_z={0}'.format(rpdat.rp_voxelgi_resolution_z)) if rpdat.arm_voxelgi_shadows: @@ -265,7 +265,11 @@ def build(): assets.add_khafile_def('rp_ssgi_half') if rpdat.rp_renderer == 'Deferred': - assets.add_shader_pass('deferred_light') + if rpdat.arm_material_model == 'Full': + assets.add_shader_pass('deferred_light') + else: # mobile, solid + assets.add_shader_pass('deferred_light_' + rpdat.arm_material_model.lower()) + assets.add_khafile_def('rp_material_' + rpdat.arm_material_model.lower()) if bpy.app.version >= (2, 80, 1) and len(bpy.data.lightprobes) > 0: wrd.world_defs += '_Probes' diff --git a/blender/arm/props_ui.py b/blender/arm/props_ui.py index d42e4b30..24d06109 100644 --- a/blender/arm/props_ui.py +++ b/blender/arm/props_ui.py @@ -739,13 +739,13 @@ class ArmRenderPathPanel(bpy.types.Panel): layout.prop(wrd, 'rp_search', icon='VIEWZOOM') - self.label(layout, text='Renderer') + layout.separator() box = self.box(layout) row = self.row(box) self.prop(row, rpdat, 'rp_renderer') - col = self.column(box, enabled=(rpdat.rp_renderer == 'Forward')) - self.prop(col, rpdat, 'rp_depthprepass') - self.prop(col, rpdat, 'arm_material_model') + if rpdat.rp_renderer == 'Forward': + self.prop(box, rpdat, 'rp_depthprepass') + self.prop(box, rpdat, 'arm_material_model') self.prop(box, rpdat, 'rp_translucency_state') self.prop(box, rpdat, 'rp_overlays_state') self.prop(box, rpdat, 'rp_decals_state')