Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refraction #316

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions packages/shaderlab/src/shaders/Common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,57 @@ float remapDepthBufferLinear01(float z){
#define INVERSE_MAT(mat) inverseMat(mat)
#endif

vec4 sampleTexture(sampler2D tex, vec2 uv){
vec4 color = texture2D(tex, uv);

#ifndef ENGINE_IS_COLORSPACE_GAMMA
color = gammaToLinear(color);
#endif

return color;
}

vec2 bSpline3MiddleLeft(vec2 x){
return 0.16666667 + x * (0.5 + x * (0.5 - x * 0.5));
}

vec2 bSpline3MiddleRight(vec2 x){
return 0.66666667 + x * (-1.0 + 0.5 * x) * x;
}

vec2 bSpline3Rightmost(vec2 x){
return 0.16666667 + x * (-0.5 + x * (0.5 - x * 0.16666667));
}

// Compute weights & offsets for 4x bilinear taps for the bicubic B-Spline filter.
// The fractional coordinate should be in the [0, 1] range (centered on 0.5).
// Inspired by: http://vec3.ca/bicubic-filtering-in-fewer-taps/
void bicubicFilter(vec2 fracCoord, out vec2 weights[2], out vec2 offsets[2]){
vec2 r = bSpline3Rightmost(fracCoord);
vec2 mr = bSpline3MiddleRight(fracCoord);
vec2 ml = bSpline3MiddleLeft(fracCoord);
vec2 l = 1.0 - mr - ml - r;

weights[0] = r + mr;
weights[1] = ml + l;
offsets[0] = -1.0 + mr / weights[0];
offsets[1] = 1.0 + l / weights[1];
}


// texSize: (1/width, 1/height, width, height)
vec4 sampleTexture2DBicubic(sampler2D tex, vec2 coord, vec4 texSize){
vec2 xy = coord * texSize.zw + 0.5;
vec2 ic = floor(xy);
vec2 fc = fract(xy);

vec2 weights[2];
vec2 offsets[2];
bicubicFilter(fc, weights, offsets);

return weights[0].y * (weights[0].x * sampleTexture(tex, (ic + vec2(offsets[0].x, offsets[0].y) - 0.5) * texSize.xy) +
weights[1].x * sampleTexture(tex, (ic + vec2(offsets[1].x, offsets[0].y) - 0.5) * texSize.xy)) +
weights[1].y * (weights[0].x * sampleTexture(tex, (ic + vec2(offsets[0].x, offsets[1].y) - 0.5) * texSize.xy) +
weights[1].x * sampleTexture(tex, (ic + vec2(offsets[1].x, offsets[1].y) - 0.5) * texSize.xy));
}
#endif
9 changes: 8 additions & 1 deletion packages/shaderlab/src/shaders/PBR.gs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,14 @@ Shader "PBR.gs" {
material_SheenTexture("ColorTexture", Texture2D);
material_SheenRoughnessTexture("RoughnessTexture", Texture2D);
}

Header("Refraction"){
material_attenuationColor("AttenuationColor", Color ) = (0, 0, 0, 1);
material_attenuationDistance("AttenuationDistance", Range(0, 1, 0.01)) = 0;
material_transmission("Transmission", Range(0, 1, 0.01)) = 0;
material_Thickness("Thickness", Float) = 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add range constraints to material_Thickness.

The material_Thickness property should have range constraints to prevent invalid values that could affect rendering calculations.

-        material_Thickness("Thickness", Float) = 0;
+        material_Thickness("Thickness", Range(0, 100, 0.1)) = 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
material_Thickness("Thickness", Float) = 0;
material_Thickness("Thickness", Range(0, 100, 0.1)) = 0;

material_TransmissionTexture("TransmissionTexture", Texture2D);
material_ThicknessTexture("ThicknessTexture", Texture2D);
}
Header("Common") {
material_AlphaCutoff( "AlphaCutoff", Range(0, 1, 0.01) ) = 0;
material_TilingOffset("TilingOffset", Vector4) = (1, 1, 0, 0);
Expand Down
14 changes: 14 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/BRDF.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct SurfaceData{
float specularAO;
float f0;
float opacity;
float IOR;

// geometry
vec3 position;
Expand Down Expand Up @@ -64,6 +65,19 @@ struct SurfaceData{
vec3 sheenColor;
#endif

#ifdef MATERIAL_ENABLE_SS_REFRACTION
vec3 attenuationColor;
float attenuationDistance;

// #ifdef MATERIAL_HAS_TRANSMISSION
float transmission;
// #endif

// #ifdef MATERIAL_ENABLE_THICKNESS
float thickness;
// #endif
#endif

};


Expand Down
53 changes: 53 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/BTDF.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#ifndef BTDF_INCLUDED
#define BTDF_INCLUDED

#include "Refraction.glsl"

vec4 renderer_texelSize; // x: 1/width, y: 1/height, z: width, w: height
sampler2D camera_OpaqueTexture;

#ifdef MATERIAL_ENABLE_SS_REFRACTION
vec3 evaluateRefraction(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, vec3 speculaColor) {
RefractionModel ray;
#if REFRACTION_SPHERE
RefractionModelSphere(surfaceData.viewDir, varyings.positionWS, varyings.normalWS, surfaceData.IOR, surfaceData.thickness, ray);
#elif REFRACTION_PLANE
RefractionModelBox(surfaceData.viewDir, varyings.positionWS, varyings.normalWS, surfaceData.IOR, surfaceData.thickness, ray);
#elif REFRACTION_THIN
RefractionModelBox(surfaceData.viewDir, varyings.positionWS, varyings.normalWS, surfaceData.IOR, surfaceData.thickness, ray);
#endif

vec3 refractedRayExit = ray.position; //ray.position + ray.direction;

// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
vec4 ndcPos = camera_ProjMat * camera_ViewMat * vec4( refractedRayExit, 1.0 );
vec2 refractionCoords = ndcPos.xy / ndcPos.w;
refractionCoords *= 0.5;
refractionCoords += 0.5;

// compute transmission
vec3 absorptionCoefficient = max(vec3(0), -log(surfaceData.attenuationColor)/surfaceData.attenuationDistance);
#ifdef MATERIAL_HAS_ABSORPTION
vec3 transmittance = min(vec3(1.0), exp(-absorptionCoefficient * ray.dist));
#else
vec3 transmittance = 1.0 - absorptionCoefficient;
#endif

// vec4 transmittedLight = texture2D(camera_OpaqueTexture, varyings.uv);
vec4 transmittedLight = sampleTexture2DBicubic(camera_OpaqueTexture, refractionCoords, renderer_texelSize);
// vec3 transmittanceColor = brdfData.diffuseColor * transmittance;
vec3 E = envBRDFApprox(speculaColor, brdfData.roughness, surfaceData.dotNV);

vec3 ft = transmittedLight.rgb;
ft *= brdfData.diffuseColor;
ft *= 1.0 - E;

#ifdef MATERIAL_HAS_ABSORPTION
ft *= transmittance;
#endif

return ft;
}
#endif

#endif
58 changes: 57 additions & 1 deletion packages/shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

#include "Normal.glsl"

// #if MATERIAL_ENABLE_SS_REFRACTION
// #define REFRACTION_SPHERE
// #define REFRACTION_PLANE
// #define REFRACTION_THIN
// #endif

float material_AlphaCutoff;
vec4 material_BaseColor;
float material_Metal;
Expand Down Expand Up @@ -62,6 +68,28 @@ float material_OcclusionTextureCoord;
#endif
#endif

#ifdef MATERIAL_ENABLE_SS_REFRACTION
#define REFRACTION_SPHERE
#define REFRACTION_PLANE
#define REFRACTION_THIN

vec3 material_attenuationColor;
float material_attenuationDistance;

// #ifdef MATERIAL_ENABLE_SS_REFRACTION
float material_transmission;
// #ifdef MATERIAL_HAS_TRANSMISSION_TEXTURE
// sampler2D material_TransmissionTexture;
// #endif
// #endif

// #ifdef MATERIAL_ENABLE_THICKNESS
float material_thickness;
// #ifdef MATERIAL_HAS_THICKNESS_TEXTURE
// sampler2D material_ThicknessTexture;
// #endif
// #endif
#endif
// Texture
#ifdef MATERIAL_HAS_BASETEXTURE
sampler2D material_BaseTexture;
Expand Down Expand Up @@ -166,7 +194,7 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
surfaceData.emissiveColor = emissiveRadiance;
surfaceData.metallic = metallic;
surfaceData.roughness = roughness;
surfaceData.f0 = f0;
surfaceData.IOR = material_IOR;

#ifdef MATERIAL_IS_TRANSPARENT
surfaceData.opacity = baseColor.a;
Expand Down Expand Up @@ -292,6 +320,34 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
#endif
#endif


#ifdef MATERIAL_ENABLE_SS_REFRACTION
surfaceData.attenuationColor = material_attenuationColor;

// #if REFRACTION_THIN
// #define REFRACTION_THIN_DISTANCE 0.005
// surfaceData.attenuationDistance = REFRACTION_THIN_DISTANCE;
// #else
surfaceData.attenuationDistance = material_attenuationDistance;
// #endif

// #ifdef MATERIAL_HAS_TRANSMISSION
surfaceData.transmission = material_transmission;
// #ifdef MATERIAL_HAS_TRANSMISSION_TEXTURE
// surfaceData.transmission *= texture2D( material_TransmissionTexture, uv).r;
// #endif
// #else
// surfaceData.transmission = 1.0;
// #endif

// #ifdef MATERIAL_ENABLE_THICKNESS
surfaceData.thickness = max(0.0, material_thickness);
// #ifdef MATERIAL_HAS_THICKNESS_TEXTURE
// surfaceData.thickness *= texture2D( material_ThicknessTexture, uv).g;
// #endif
// #endif

#endif
// AO
float diffuseAO = 1.0;
float specularAO = 1.0;
Expand Down
5 changes: 5 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/LightDirectPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ void surfaceShading(Varyings varyings, SurfaceData surfaceData, BRDFData brdfDat
FUNCTION_DIFFUSE_LOBE(varyings, surfaceData, brdfData, attenuationIrradiance, diffuseColor);
// Specular Lobe
FUNCTION_SPECULAR_LOBE(varyings, surfaceData, brdfData, incidentDirection, attenuationIrradiance, specularColor);

// #ifdef MATERIAL_ENABLE_SS_REFRACTION
// diffuseColor *= (1.0 - surfaceData.transmission);
// #endif

// Sheen Lobe
FUNCTION_SHEEN_LOBE(varyings, surfaceData, brdfData, incidentDirection, attenuationIrradiance, diffuseColor, specularColor);

Expand Down
13 changes: 12 additions & 1 deletion packages/shaderlab/src/shaders/shadingPBR/LightIndirectPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define FUNCTION_SHEEN_IBL evaluateSheenIBL
#endif
#include "BRDF.glsl"
#include "BTDF.glsl"
#include "Light.glsl"
#include "LightIndirectFunctions.glsl"

Expand Down Expand Up @@ -92,7 +93,7 @@ void evaluateSheenIBL(Varyings varyings, SurfaceData surfaceData, BRDFData brdfD
void evaluateIBL(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, inout vec3 color){
vec3 diffuseColor = vec3(0);
vec3 specularColor = vec3(0);

vec3 transmissioncolor = vec3(0);
// IBL diffuse
FUNCTION_DIFFUSE_IBL(varyings, surfaceData, brdfData, diffuseColor);

Expand All @@ -105,8 +106,18 @@ void evaluateIBL(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData,
// IBL sheen
FUNCTION_SHEEN_IBL(varyings, surfaceData, brdfData, radianceAttenuation, diffuseColor, specularColor);


// #ifdef MATERIAL_ENABLE_SS_REFRACTION
// vec3 Ft = evaluateRefraction(varyings, surfaceData, brdfData, specularColor);
// Ft *= surfaceData.transmission;
// diffuseColor *= (1.0 - surfaceData.transmission);
// #endif

color += diffuseColor + specularColor;

// #ifdef MATERIAL_ENABLE_SS_REFRACTION
// color.rgb += Ft;
// #endif
}


Expand Down
56 changes: 56 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/Refraction.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef REFRACTION_INCLUDED
#define REFRACTION_INCLUDED

#ifdef MATERIAL_ENABLE_SS_REFRACTION

struct RefractionModel{
float dist; // length of the transmission during refraction through the shape
vec3 position; // out ray position
vec3 direction; // out ray direction
};

void RefractionModelSphere(vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModel ray){
// Sphere shape model:
// We approximate locally the shape of the object as sphere, that is tangent to the shape.
// The sphere has a diameter of {thickness}
// The center of the sphere is at {positionWS} - {normalWS} * {thickness} * 0.5
// So the light is refracted twice: in and out of the tangent sphere

// First refraction (tangent sphere in)
// Refracted ray
vec3 R1 = refract(V, normalWS, 1.0 / ior);
// Center of the tangent sphere
vec3 C = positionWS - normalWS * thickness * 0.5;

// Second refraction (tangent sphere out)
float NoR1 = dot(normalWS, R1);
// Optical depth within the sphere
float dist = -NoR1 * thickness;
// Out hit point in the tangent sphere
vec3 P1 = positionWS + R1 * dist;
// Out normal
vec3 N1 = normalize(C - P1);
// Out refracted ray
vec3 R2 = refract(R1, N1, ior);

ray.dist = dist;
ray.position = P1;
ray.direction = R2;
}

void RefractionModelBox(vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModel ray){
// Plane shape model:
// We approximate locally the shape of the object as a plane with normal {normalWS} at {positionWS}
// with a thickness {thickness}
// Refracted ray
vec3 R = refract(V, normalWS, 1.0 / ior);

// Optical depth within the thin plane
float dist = thickness / max(dot(R, -normalWS), 0.001);

ray.dist = dist;
ray.position = positionWS + R * dist;
ray.direction = V;
}
#endif
#endif
6 changes: 5 additions & 1 deletion packages/shaderlab/src/shaders/shadingPBR/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import LightIndirectPBR from "./LightIndirectPBR.glsl";
import ReflectionLobe from "./ReflectionLobe.glsl";
import VaryingsPBR from "./VaryingsPBR.glsl";
import VertexPBR from "./VertexPBR.glsl";
import Refraction from "./Refraction.glsl";
import BTDF from "./BTDF.glsl";

export default [
{ source: ForwardPassPBR, includeKey: "ForwardPassPBR.glsl" },
Expand All @@ -19,5 +21,7 @@ export default [
{ source: VertexPBR, includeKey: "VertexPBR.glsl" },
{ source: BRDF, includeKey: "BRDF.glsl" },
{ source: LightIndirectFunctions, includeKey: "LightIndirectFunctions.glsl" },
{ source: ReflectionLobe, includeKey: "ReflectionLobe.glsl" }
{ source: ReflectionLobe, includeKey: "ReflectionLobe.glsl" },
{ source: Refraction, includeKey: "Refraction.glsl" },
{ source: BTDF, includeKey: "BTDF.glsl" }
];
Loading