Skip to content

Commit

Permalink
Merge pull request #2960 from e2002e/ss_refraction
Browse files Browse the repository at this point in the history
Ss refraction
  • Loading branch information
luboslenco committed Jan 25, 2024
2 parents d804eba + 7114d78 commit 3c1c628
Show file tree
Hide file tree
Showing 30 changed files with 643 additions and 175 deletions.
6 changes: 6 additions & 0 deletions Shaders/custom_mat_presets/custom_mat_deferred.frag.glsl
Expand Up @@ -40,6 +40,8 @@ void main() {
float specular = 1.0;
uint materialId = 0;
vec3 emissionCol = vec3(0.0);
float ior = 1.450;
float opacity = 1.0;

// Store in gbuffer (see layout table above)
fragColor[GBUF_IDX_0] = vec4(n.xy, roughness, packFloatInt16(metallic, materialId));
Expand All @@ -48,4 +50,8 @@ void main() {
#ifdef _EmissionShaded
fragColor[GBUF_IDX_EMISSION] = vec4(emissionCol, 0.0);
#endif

#ifdef _SSRefraction
fragColor[GBUF_IDX_REFRACTION] = vec4(ior, opacity, 0.0, 0.0);
#endif
}
3 changes: 1 addition & 2 deletions Shaders/ssr_pass/ssr_pass.frag.glsl
Expand Up @@ -45,7 +45,6 @@ float getDeltaDepth(const vec3 hit) {

vec4 binarySearch(vec3 dir) {
float ddepth;
vec3 start = hitCoord;
for (int i = 0; i < numBinarySearchSteps; i++) {
dir *= 0.5;
hitCoord -= dir;
Expand Down Expand Up @@ -93,7 +92,7 @@ void main() {

vec3 viewNormal = V3 * n;
vec3 viewPos = getPosView(viewRay, d, cameraProj);
vec3 reflected = normalize(reflect(viewPos, viewNormal));
vec3 reflected = reflect(normalize(viewPos), viewNormal);
hitCoord = viewPos;

#ifdef _CPostprocess
Expand Down
132 changes: 132 additions & 0 deletions Shaders/ssrefr_pass/ssrefr_pass.frag.glsl
@@ -0,0 +1,132 @@
#version 450

#include "compiled.inc"
#include "std/math.glsl"
#include "std/gbuffer.glsl"

uniform sampler2D tex;
uniform sampler2D tex1;
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbufferD1;
uniform sampler2D gbuffer_refraction; // ior\opacity
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;

const int numBinarySearchSteps = 7;
const int maxSteps = int(ceil(1.0 / ss_refractionRayStep) * ss_refractionSearchDist);

vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
#ifdef _InvY
projectedCoord.y = 1.0 - projectedCoord.y;
#endif
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));
return viewPos.z - hit.z;
}


vec4 binarySearch(vec3 dir) {
float ddepth;
for (int i = 0; i < numBinarySearchSteps; i++) {
dir *= 0.5;
hitCoord -= 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
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
}


vec4 rayCast(vec3 dir) {
float ddepth;
#ifdef _CPostprocess
dir *= PPComp9.x;
#else
dir *= ss_refractionRayStep;
#endif
for (int i = 0; i < maxSteps; i++) {
hitCoord += dir;
ddepth = getDeltaDepth(hitCoord);
if (ddepth > d) return binarySearch(dir);
}
return vec4(0.0);
}

void main() {
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
float roughness = g0.z;
vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0);
float ior = gr.x;
float opac = gr.y;

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;
return;
}

vec2 enc = g0.rg;
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);
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);
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);

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;
refractionCol = clamp(refractionCol, 0.0, 1.0);
vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb;
fragColor.rgb = mix(refractionCol * intensity, color, opac);
}
48 changes: 48 additions & 0 deletions Shaders/ssrefr_pass/ssrefr_pass.json
@@ -0,0 +1,48 @@
{
"contexts": [
{
"name": "ssrefr_pass",
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "P",
"link": "_projectionMatrix"
},
{
"name": "V3",
"link": "_viewMatrix3"
},
{
"name": "eye",
"link": "_cameraPosition"
},
{
"name": "eyeLook",
"link": "_cameraLook"
},
{
"name": "invP",
"link": "_inverseProjectionMatrix"
},
{
"name": "cameraProj",
"link": "_cameraPlaneProj"
},
{
"name": "PPComp9",
"link": "_PPComp9",
"ifdef": ["_CPostprocess"]
},
{
"name": "PPComp10",
"link": "_PPComp10",
"ifdef": ["_CPostprocess"]
}
],
"vertex_shader": "../include/pass_viewray2.vert.glsl",
"fragment_shader": "ssrefr_pass.frag.glsl"
}
]
}
6 changes: 3 additions & 3 deletions Shaders/std/conetrace.glsl
Expand Up @@ -50,7 +50,7 @@ float traceConeAO(sampler3D voxels, const vec3 origin, vec3 dir, const float ape
float traceConeAOShadow(sampler3D voxels, const vec3 origin, vec3 dir, const float aperture, const float maxDist, const float offset) {
dir = normalize(dir);
float sampleCol = 0.0;
float dist = 1.5 * VOXEL_SIZE * voxelgiOffset * 2.5; //
float dist = 1.5 * VOXEL_SIZE * voxelgiOffset * 2.5;
float diam = dist * aperture;
vec3 samplePos;
while (sampleCol < 1.0 && dist < maxDist) {
Expand Down Expand Up @@ -81,7 +81,7 @@ float traceAO(const vec3 origin, const vec3 normal, sampler3D voxels) {
#else
const float factor = voxelgiOcc * 0.90;
#endif

#ifdef _VoxelCones1
return traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE) * factor;
#endif
Expand All @@ -101,7 +101,7 @@ float traceAO(const vec3 origin, const vec3 normal, sampler3D voxels) {
col += traceConeAO(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE);
return (col / 5.0) * factor;
#endif

#ifdef _VoxelCones9
float col = traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE);
col += traceConeAO(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE);
Expand Down
2 changes: 1 addition & 1 deletion Shaders/std/gbuffer.glsl
Expand Up @@ -15,7 +15,7 @@ vec3 getNor(const vec2 enc) {

vec3 getPosView(const vec3 viewRay, const float depth, const vec2 cameraProj) {
float linearDepth = cameraProj.y / (cameraProj.x - depth);
// float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
//float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
return viewRay * linearDepth;
}

Expand Down
2 changes: 1 addition & 1 deletion Shaders/translucent_resolve/translucent_resolve.frag.glsl
Expand Up @@ -19,7 +19,7 @@ void main() {
if (revealage == 0.0) {
discard;
}

float f = texelFetch(gbuffer1, ivec2(texCoord * texSize), 0).r;
fragColor = vec4(accum.rgb / clamp(f, 0.0001, 5000), revealage);
}
29 changes: 13 additions & 16 deletions Shaders/water_pass/water_pass.frag.glsl
Expand Up @@ -38,8 +38,8 @@ out vec4 fragColor;
vec3 hitCoord;
float depth;

const int numBinarySearchSteps = 16;
const int maxSteps = 16;
const int numBinarySearchSteps = 7;
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);

vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0);
Expand All @@ -59,37 +59,34 @@ float getDeltaDepth(const vec3 hit) {

vec4 binarySearch(vec3 dir) {
float ddepth;
vec3 start = hitCoord;
for (int i = 0; i < numBinarySearchSteps; i++)
{
for (int i = 0; i < numBinarySearchSteps; i++) {
dir *= 0.5;
start -= dir;
ddepth = getDeltaDepth(start);
hitCoord -= dir;
ddepth = getDeltaDepth(hitCoord);
if (ddepth < 0.0) hitCoord += dir;
}
// Ugly discard of hits too far away
#ifdef _CPostprocess
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
#else
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
#endif
return vec4(getProjectedCoord(start), 0.0, 1.0);
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
}

vec4 rayCast(vec3 dir) {
#ifdef _CPostprocess
dir *= PPComp9.x;
dir *= PPComp9.x;
#else
dir *= ssrRayStep;
dir *= ssrRayStep;
#endif
for (int i = 0; i < maxSteps; i++)
{
for (int i = 0; i < maxSteps; i++) {
hitCoord += dir;
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
}
return vec4(0.0);
}
#endif
#endif //SSR

void main() {
float gdepth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
Expand Down Expand Up @@ -152,7 +149,7 @@ void main() {

vec3 viewNormal = n2;
vec3 viewPos = getPosView(viewRay, gdepth, cameraProj);
vec3 reflected = normalize(reflect(viewPos, viewNormal));
vec3 reflected = reflect(normalize(viewPos), viewNormal);
hitCoord = viewPos;

#ifdef _CPostprocess
Expand Down
1 change: 1 addition & 0 deletions Sources/armory/data/Config.hx
Expand Up @@ -45,6 +45,7 @@ typedef TConfig = {
@:optional var rp_shadowmap_cascade: Null<Int>; // size for single cascade
@:optional var rp_ssgi: Null<Bool>;
@:optional var rp_ssr: Null<Bool>;
@:optional var rp_ssrefr: Null<Bool>;
@:optional var rp_bloom: Null<Bool>;
@:optional var rp_motionblur: Null<Bool>;
@:optional var rp_gi: Null<Bool>; // voxelao
Expand Down
2 changes: 2 additions & 0 deletions Sources/armory/logicnode/RpConfigNode.hx
Expand Up @@ -16,6 +16,8 @@ class RpConfigNode extends LogicNode {
on ? armory.data.Config.raw.rp_ssgi = true : armory.data.Config.raw.rp_ssgi = false;
case "SSR":
on ? armory.data.Config.raw.rp_ssr = true : armory.data.Config.raw.rp_ssr = false;
case "SSREFR":
on ? armory.data.Config.raw.rp_ssrefr = true : armory.data.Config.raw.rp_ssrefr = false;
case "Bloom":
on ? armory.data.Config.raw.rp_bloom = true : armory.data.Config.raw.rp_bloom = false;
case "GI":
Expand Down
1 change: 1 addition & 0 deletions Sources/armory/object/Uniforms.hx
Expand Up @@ -166,6 +166,7 @@ class Uniforms {
}
}
#end

#if rp_voxels
case "_cameraPositionSnap": {
v = iron.object.Uniforms.helpVec;
Expand Down
3 changes: 3 additions & 0 deletions Sources/armory/renderpath/Inc.hx
Expand Up @@ -453,6 +453,7 @@ class Inc {
var t = new RenderTargetRaw();
t.name = tname;
t.format = "R8";

var res = getVoxelRes();
var resZ = getVoxelResZ();
t.width = res;
Expand Down Expand Up @@ -537,6 +538,8 @@ class Inc {
return 0.5;
#elseif (rp_voxelgi_resolution_z == 0.25)
return 0.25;
#elseif (rp_voxelgi_resolution_z == 0.125)
return 0.125;
#else
return 0.0;
#end
Expand Down

0 comments on commit 3c1c628

Please sign in to comment.