2022-07-31 19:49:18 +00:00
|
|
|
// Flags
|
2023-04-06 04:52:00 +00:00
|
|
|
#ifndef GL_COMPUTE_SHADER
|
2022-08-26 17:28:23 +00:00
|
|
|
layout(constant_id = 1000) const float flag_pointSize = 1.f;
|
|
|
|
layout(constant_id = 1002) const bool flag_passColor = true;
|
|
|
|
layout(constant_id = 1003) const bool flag_materialColor = true;
|
|
|
|
layout(constant_id = 1004) const bool flag_vertexColors = true;
|
|
|
|
layout(constant_id = 1005) const bool flag_uvTransform = true;
|
|
|
|
layout(constant_id = 1006) const bool flag_alphaCutoff = false;
|
|
|
|
layout(constant_id = 1007) const bool flag_glow = false;
|
|
|
|
layout(constant_id = 1008) const bool flag_normalMap = false;
|
|
|
|
layout(constant_id = 1009) const bool flag_vertexTangents = true;
|
|
|
|
layout(constant_id = 1010) const bool flag_colorTexture = true;
|
2022-09-02 22:33:18 +00:00
|
|
|
layout(constant_id = 1011) const bool flag_glowTexture = true;
|
2022-08-26 17:28:23 +00:00
|
|
|
layout(constant_id = 1012) const bool flag_metalnessTexture = true;
|
|
|
|
layout(constant_id = 1013) const bool flag_roughnessTexture = true;
|
2022-09-02 22:33:18 +00:00
|
|
|
layout(constant_id = 1014) const bool flag_ambientOcclusion = true;
|
2022-08-26 17:28:23 +00:00
|
|
|
layout(constant_id = 1015) const bool flag_clearcoatTexture = false;
|
2022-08-26 17:34:32 +00:00
|
|
|
layout(constant_id = 1016) const bool flag_tonemap = false;
|
2023-04-06 04:52:00 +00:00
|
|
|
#endif
|
2022-07-31 19:49:18 +00:00
|
|
|
|
2022-06-16 03:46:43 +00:00
|
|
|
// Resources
|
|
|
|
#ifndef GL_COMPUTE_SHADER
|
|
|
|
struct Camera {
|
|
|
|
mat4 view;
|
|
|
|
mat4 projection;
|
|
|
|
mat4 viewProjection;
|
|
|
|
mat4 inverseProjection;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Draw {
|
2023-08-02 01:45:37 +00:00
|
|
|
mat4x3 transform;
|
2022-06-16 03:46:43 +00:00
|
|
|
vec4 color;
|
|
|
|
};
|
|
|
|
|
2022-08-26 04:57:15 +00:00
|
|
|
layout(set = 0, binding = 0) uniform Globals { vec2 Resolution; float Time; };
|
2022-08-06 20:37:27 +00:00
|
|
|
layout(set = 0, binding = 1) uniform CameraBuffer { Camera Cameras[6]; };
|
2023-08-02 01:45:37 +00:00
|
|
|
layout(set = 0, binding = 2) uniform DrawBuffer { layout(row_major) Draw Draws[256]; };
|
2022-08-06 20:37:27 +00:00
|
|
|
layout(set = 0, binding = 3) uniform sampler Sampler;
|
2022-06-17 06:49:09 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
struct MaterialData {
|
2022-07-31 19:49:18 +00:00
|
|
|
vec4 color;
|
|
|
|
vec4 glow;
|
|
|
|
vec2 uvShift;
|
|
|
|
vec2 uvScale;
|
|
|
|
vec2 sdfRange;
|
|
|
|
float metalness;
|
|
|
|
float roughness;
|
|
|
|
float clearcoat;
|
|
|
|
float clearcoatRoughness;
|
|
|
|
float occlusionStrength;
|
|
|
|
float normalScale;
|
|
|
|
float alphaCutoff;
|
2023-08-03 01:11:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
layout(set = 1, binding = 0) uniform MaterialBuffer {
|
|
|
|
MaterialData Material;
|
|
|
|
};
|
2022-06-17 06:49:09 +00:00
|
|
|
|
2022-07-07 05:54:56 +00:00
|
|
|
layout(set = 1, binding = 1) uniform texture2D ColorTexture;
|
2022-06-17 06:49:09 +00:00
|
|
|
layout(set = 1, binding = 2) uniform texture2D GlowTexture;
|
2022-09-24 06:44:31 +00:00
|
|
|
layout(set = 1, binding = 3) uniform texture2D MetalnessTexture;
|
|
|
|
layout(set = 1, binding = 4) uniform texture2D RoughnessTexture;
|
|
|
|
layout(set = 1, binding = 5) uniform texture2D ClearcoatTexture;
|
|
|
|
layout(set = 1, binding = 6) uniform texture2D OcclusionTexture;
|
2022-06-17 06:49:09 +00:00
|
|
|
layout(set = 1, binding = 7) uniform texture2D NormalTexture;
|
2024-02-20 23:14:39 +00:00
|
|
|
|
|
|
|
layout(push_constant) uniform PushConstants {
|
|
|
|
uint DrawID;
|
|
|
|
};
|
2022-06-16 03:46:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Attributes
|
|
|
|
#ifdef GL_VERTEX_SHADER
|
|
|
|
layout(location = 10) in vec4 VertexPosition;
|
|
|
|
layout(location = 11) in vec3 VertexNormal;
|
|
|
|
layout(location = 12) in vec2 VertexUV;
|
|
|
|
layout(location = 13) in vec4 VertexColor;
|
2023-11-10 00:50:52 +00:00
|
|
|
layout(location = 14) in vec4 VertexTangent;
|
2022-06-16 03:46:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Framebuffer
|
|
|
|
#ifdef GL_FRAGMENT_SHADER
|
2023-02-06 00:04:17 +00:00
|
|
|
layout(location = 0) out vec4 PixelColor;
|
2022-06-16 03:46:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Varyings
|
|
|
|
#ifdef GL_VERTEX_SHADER
|
2022-08-10 02:49:47 +00:00
|
|
|
layout(location = 10) out vec3 PositionWorld;
|
|
|
|
layout(location = 11) out vec3 Normal;
|
2023-06-24 18:26:09 +00:00
|
|
|
layout(location = 12) out vec2 UV;
|
|
|
|
layout(location = 13) out vec4 Color;
|
2023-11-10 00:50:52 +00:00
|
|
|
layout(location = 14) out vec4 Tangent;
|
2022-07-10 06:39:20 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GL_FRAGMENT_SHADER
|
2022-08-10 02:49:47 +00:00
|
|
|
layout(location = 10) in vec3 PositionWorld;
|
|
|
|
layout(location = 11) in vec3 Normal;
|
2023-06-24 18:26:09 +00:00
|
|
|
layout(location = 12) in vec2 UV;
|
|
|
|
layout(location = 13) in vec4 Color;
|
2023-11-10 00:50:52 +00:00
|
|
|
layout(location = 14) in vec4 Tangent;
|
2022-06-16 03:46:43 +00:00
|
|
|
#endif
|
|
|
|
|
2023-03-03 03:03:15 +00:00
|
|
|
// Builtins
|
2022-06-16 03:46:43 +00:00
|
|
|
#ifdef GL_COMPUTE_SHADER
|
2022-08-06 20:06:42 +00:00
|
|
|
#define SubgroupCount gl_NumSubgroups
|
|
|
|
#define WorkgroupCount gl_NumWorkGroups
|
|
|
|
#define WorkgroupSize gl_WorkGroupSize
|
|
|
|
#define WorkgroupID gl_WorkGroupID
|
|
|
|
#define GlobalThreadID gl_GlobalInvocationID
|
|
|
|
#define LocalThreadID gl_LocalInvocationID
|
|
|
|
#define LocalThreadIndex gl_LocalInvocationIndex
|
2022-06-16 03:46:43 +00:00
|
|
|
#else
|
|
|
|
#define ClipDistance gl_ClipDistance
|
|
|
|
#define CullDistance gl_CullDistance
|
2023-03-03 03:03:15 +00:00
|
|
|
#define PrimitiveID gl_PrimitiveID
|
|
|
|
#define ViewIndex gl_ViewIndex
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GL_VERTEX_SHADER
|
|
|
|
#define BaseInstance gl_BaseInstance
|
|
|
|
#define BaseVertex gl_BaseVertex
|
2022-06-16 03:46:43 +00:00
|
|
|
#define DrawIndex gl_DrawIndex
|
2024-02-20 23:14:39 +00:00
|
|
|
#define InstanceIndex gl_InstanceIndex
|
2023-03-03 03:03:15 +00:00
|
|
|
#define PointSize gl_PointSize
|
|
|
|
#define Position gl_Position
|
|
|
|
#define VertexIndex gl_VertexIndex
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GL_FRAGMENT_SHADER
|
2022-06-16 03:46:43 +00:00
|
|
|
#define FragCoord gl_FragCoord
|
|
|
|
#define FragDepth gl_FragDepth
|
|
|
|
#define FrontFacing gl_FrontFacing
|
|
|
|
#define PointCoord gl_PointCoord
|
2022-08-06 20:06:42 +00:00
|
|
|
#define SampleID gl_SampleID
|
2022-06-16 03:46:43 +00:00
|
|
|
#define SampleMaskIn gl_SampleMaskIn
|
|
|
|
#define SampleMask gl_SampleMask
|
|
|
|
#define SamplePosition gl_SamplePosition
|
2023-03-03 03:03:15 +00:00
|
|
|
#endif
|
2022-06-16 03:46:43 +00:00
|
|
|
|
2023-03-03 03:03:15 +00:00
|
|
|
// Constants
|
|
|
|
#define PI 3.141592653589793238462643383279502f
|
|
|
|
#define TAU (2.f * PI)
|
|
|
|
#define PI_2 (.5f * PI)
|
|
|
|
|
|
|
|
// Helpers
|
|
|
|
|
2024-02-20 23:07:30 +00:00
|
|
|
#define Constants uniform DefaultUniformBlock
|
2023-03-03 03:03:15 +00:00
|
|
|
|
|
|
|
#ifndef GL_COMPUTE_SHADER
|
2022-07-07 05:54:56 +00:00
|
|
|
#define Projection Cameras[ViewIndex].projection
|
|
|
|
#define View Cameras[ViewIndex].view
|
|
|
|
#define ViewProjection Cameras[ViewIndex].viewProjection
|
|
|
|
#define InverseProjection Cameras[ViewIndex].inverseProjection
|
2023-03-03 03:03:15 +00:00
|
|
|
#define CameraPositionWorld (-View[3].xyz * mat3(View))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GL_VERTEX_SHADER
|
2023-08-02 01:45:37 +00:00
|
|
|
#define Transform mat4(Draws[DrawID].transform)
|
|
|
|
#define NormalMatrix (cofactor3(Draws[DrawID].transform))
|
2022-08-06 20:06:42 +00:00
|
|
|
#define PassColor Draws[DrawID].color
|
2022-06-16 03:46:43 +00:00
|
|
|
#define ClipFromLocal (ViewProjection * Transform)
|
|
|
|
#define ClipFromWorld (ViewProjection)
|
|
|
|
#define ClipFromView (Projection)
|
|
|
|
#define ViewFromLocal (View * Transform)
|
|
|
|
#define ViewFromWorld (View)
|
2022-08-06 20:06:42 +00:00
|
|
|
#define ViewFromClip (InverseProjection)
|
2022-06-16 03:46:43 +00:00
|
|
|
#define WorldFromLocal (Transform)
|
2022-08-06 20:06:42 +00:00
|
|
|
#define WorldFromView (inverse(View))
|
|
|
|
#define WorldFromClip (inverse(ViewProjection))
|
2022-06-16 03:46:43 +00:00
|
|
|
#define DefaultPosition (ClipFromLocal * VertexPosition)
|
2023-08-02 01:45:37 +00:00
|
|
|
|
|
|
|
mat3 cofactor3(mat4x3 m) {
|
|
|
|
return mat3(vec3(
|
|
|
|
(m[1][1] * m[2][2] - m[2][1] * m[1][2]),
|
|
|
|
-(m[1][0] * m[2][2] - m[2][0] * m[1][2]),
|
|
|
|
(m[1][0] * m[2][1] - m[2][0] * m[1][1])), vec3(
|
|
|
|
-(m[0][1] * m[2][2] - m[2][1] * m[0][2]),
|
|
|
|
(m[0][0] * m[2][2] - m[2][0] * m[0][2]),
|
|
|
|
-(m[0][0] * m[2][1] - m[2][0] * m[0][1])), vec3(
|
|
|
|
(m[0][1] * m[1][2] - m[1][1] * m[0][2]),
|
|
|
|
-(m[0][0] * m[1][2] - m[1][0] * m[0][2]),
|
|
|
|
(m[0][0] * m[1][1] - m[1][0] * m[0][1])
|
|
|
|
));
|
|
|
|
}
|
2022-07-07 05:54:56 +00:00
|
|
|
#endif
|
|
|
|
|
2023-03-03 03:03:15 +00:00
|
|
|
#ifdef GL_FRAGMENT_SHADER
|
|
|
|
#define DefaultColor (flag_colorTexture ? (Color * getPixel(ColorTexture, UV)) : Color)
|
2022-09-23 03:44:06 +00:00
|
|
|
#endif
|
2022-08-13 05:44:18 +00:00
|
|
|
|
2022-08-10 02:49:47 +00:00
|
|
|
// Helper for sampling textures using the default sampler set using Pass:setSampler
|
2022-08-13 00:59:06 +00:00
|
|
|
#ifndef GL_COMPUTE_SHADER
|
2022-07-07 05:54:56 +00:00
|
|
|
vec4 getPixel(texture2D t, vec2 uv) { return texture(sampler2D(t, Sampler), uv); }
|
|
|
|
vec4 getPixel(texture3D t, vec3 uvw) { return texture(sampler3D(t, Sampler), uvw); }
|
|
|
|
vec4 getPixel(textureCube t, vec3 dir) { return texture(samplerCube(t, Sampler), dir); }
|
2022-08-13 07:00:00 +00:00
|
|
|
vec4 getPixel(texture2DArray t, vec2 uv, float layer) { return texture(sampler2DArray(t, Sampler), vec3(uv, layer)); }
|
2023-11-10 19:15:16 +00:00
|
|
|
vec4 getPixel(textureCubeArray t, vec4 coord) { return texture(samplerCubeArray(t, Sampler), coord); }
|
2022-08-13 00:59:06 +00:00
|
|
|
#endif
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2022-08-13 00:59:06 +00:00
|
|
|
#ifdef GL_FRAGMENT_SHADER
|
2022-08-10 02:49:47 +00:00
|
|
|
// Surface contains all light-independent data needed for shading. It can be calculated once per
|
|
|
|
// pixel and reused for multiple lights. It stores information from the vertex shader and material
|
|
|
|
// inputs. The Surface can be initialized using initSurface, and is passed into the other lighting
|
|
|
|
// functions. Everything is in world space.
|
|
|
|
struct Surface {
|
|
|
|
vec3 position; // Position of fragment
|
|
|
|
vec3 normal; // Includes normal mapping
|
|
|
|
vec3 geometricNormal; // Raw normal from vertex shader
|
|
|
|
vec3 view; // The direction from the fragment to the camera
|
|
|
|
vec3 reflection; // The view vector reflected about the normal
|
|
|
|
|
|
|
|
vec3 f0;
|
|
|
|
vec3 diffuse;
|
|
|
|
vec3 emissive;
|
2023-08-03 01:11:36 +00:00
|
|
|
vec4 baseColor;
|
2022-09-24 06:44:31 +00:00
|
|
|
float metalness;
|
2022-09-24 06:58:47 +00:00
|
|
|
float roughness;
|
2022-08-10 02:49:47 +00:00
|
|
|
float roughness2;
|
|
|
|
float occlusion;
|
|
|
|
float clearcoat;
|
|
|
|
float clearcoatRoughness;
|
|
|
|
};
|
|
|
|
|
2022-08-13 00:59:06 +00:00
|
|
|
#define TangentMatrix getTangentMatrix()
|
|
|
|
|
|
|
|
mat3 getTangentMatrix() {
|
2022-08-26 17:28:23 +00:00
|
|
|
if (flag_vertexTangents) {
|
2022-08-13 00:59:06 +00:00
|
|
|
vec3 N = normalize(Normal);
|
2023-11-10 00:50:52 +00:00
|
|
|
vec3 T = normalize(Tangent.xyz);
|
|
|
|
vec3 B = cross(N, T) * Tangent.w;
|
2022-08-13 00:59:06 +00:00
|
|
|
return mat3(T, B, N);
|
|
|
|
} else {
|
|
|
|
// http://www.thetenthplanet.de/archives/1180
|
|
|
|
vec3 N = normalize(Normal);
|
|
|
|
vec3 dp1 = dFdx(PositionWorld);
|
|
|
|
vec3 dp2 = dFdy(PositionWorld);
|
|
|
|
vec2 duv1 = dFdx(UV);
|
|
|
|
vec2 duv2 = dFdy(UV);
|
|
|
|
vec3 dp2perp = cross(dp2, N);
|
|
|
|
vec3 dp1perp = cross(N, dp1);
|
|
|
|
vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
|
|
|
|
vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
|
|
|
|
float invmax = inversesqrt(max(dot(T, T), dot(B, B)));
|
|
|
|
return mat3(T * invmax, B * invmax, N);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
Surface newSurface() {
|
|
|
|
Surface surface;
|
2022-08-10 02:49:47 +00:00
|
|
|
surface.position = PositionWorld;
|
2023-08-03 01:11:36 +00:00
|
|
|
surface.geometricNormal = normalize(Normal);
|
|
|
|
surface.normal = surface.geometricNormal;
|
|
|
|
surface.view = normalize(CameraPositionWorld - PositionWorld);
|
|
|
|
surface.emissive = vec3(0.);
|
|
|
|
surface.baseColor = Color;
|
|
|
|
surface.metalness = 1.;
|
|
|
|
surface.roughness = 1.;
|
|
|
|
surface.occlusion = 1.;
|
|
|
|
surface.clearcoat = 0.;
|
|
|
|
surface.clearcoatRoughness = 0.;
|
|
|
|
return surface;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
vec4 getMaterialBaseColor() {
|
|
|
|
vec4 color = Color;
|
|
|
|
if (flag_colorTexture) color *= getPixel(ColorTexture, UV);
|
|
|
|
return color;
|
|
|
|
}
|
2022-08-13 06:30:39 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
vec3 getMaterialEmissive() {
|
|
|
|
vec3 emissive = Material.glow.rgb * Material.glow.a;
|
|
|
|
if (flag_glow && flag_glowTexture) emissive *= getPixel(GlowTexture, UV).rgb;
|
|
|
|
return emissive;
|
|
|
|
}
|
2022-08-13 06:30:39 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
float getMaterialMetalness() {
|
|
|
|
float metalness = Material.metalness;
|
|
|
|
if (flag_metalnessTexture) metalness *= getPixel(MetalnessTexture, UV).b;
|
|
|
|
return metalness;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
float getMaterialRoughness() {
|
|
|
|
float roughness = Material.roughness;
|
|
|
|
if (flag_roughnessTexture) roughness *= getPixel(RoughnessTexture, UV).g;
|
|
|
|
return roughness;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
float getMaterialOcclusion() {
|
|
|
|
float occlusion = 1.;
|
|
|
|
if (flag_ambientOcclusion) occlusion *= getPixel(OcclusionTexture, UV).r * Material.occlusionStrength;
|
|
|
|
return occlusion;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
float getMaterialClearcoat() {
|
|
|
|
float clearcoat = Material.clearcoat;
|
|
|
|
if (flag_clearcoatTexture) clearcoat *= getPixel(ClearcoatTexture, UV).r;
|
|
|
|
return clearcoat;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
float getMaterialClearcoatRoughness() {
|
|
|
|
return Material.clearcoatRoughness;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
Surface applyMaterial(inout Surface surface) {
|
|
|
|
surface.baseColor = getMaterialBaseColor();
|
|
|
|
surface.emissive = getMaterialEmissive();
|
|
|
|
surface.metalness = getMaterialMetalness();
|
|
|
|
surface.roughness = getMaterialRoughness();
|
|
|
|
surface.occlusion = getMaterialOcclusion();
|
|
|
|
surface.clearcoat = getMaterialClearcoat();
|
|
|
|
surface.clearcoatRoughness = getMaterialClearcoatRoughness();
|
|
|
|
if (flag_normalMap) {
|
|
|
|
vec3 normalScale = vec3(Material.normalScale, Material.normalScale, 1.);
|
|
|
|
surface.normal = TangentMatrix * normalize((getPixel(NormalTexture, UV).rgb * 2. - 1.) * normalScale);
|
|
|
|
}
|
|
|
|
return surface;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
void finalizeSurface(inout Surface surface) {
|
|
|
|
if (!FrontFacing) {
|
|
|
|
surface.normal = -surface.normal;
|
|
|
|
surface.geometricNormal = -surface.geometricNormal;
|
|
|
|
}
|
|
|
|
surface.reflection = reflect(-surface.view, surface.normal);
|
|
|
|
surface.f0 = mix(vec3(.04), surface.baseColor.rgb, surface.metalness);
|
|
|
|
surface.diffuse = mix(surface.baseColor.rgb, vec3(0.), surface.metalness);
|
2022-09-24 06:58:47 +00:00
|
|
|
surface.roughness = max(surface.roughness, .05);
|
|
|
|
surface.roughness2 = surface.roughness * surface.roughness;
|
2023-08-03 01:11:36 +00:00
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
Surface getDefaultSurface() {
|
|
|
|
Surface surface = newSurface();
|
|
|
|
applyMaterial(surface);
|
|
|
|
finalizeSurface(surface);
|
|
|
|
return surface;
|
|
|
|
}
|
2022-08-10 02:49:47 +00:00
|
|
|
|
2023-08-03 01:11:36 +00:00
|
|
|
// Deprecated
|
|
|
|
void initSurface(out Surface surface) {
|
|
|
|
surface = getDefaultSurface();
|
2022-08-10 02:49:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float D_GGX(const Surface surface, float NoH) {
|
2022-09-24 06:58:47 +00:00
|
|
|
float alpha2 = surface.roughness * surface.roughness2;
|
2022-08-10 02:49:47 +00:00
|
|
|
float denom = (NoH * NoH) * (alpha2 - 1.) + 1.;
|
|
|
|
return alpha2 / (PI * denom * denom);
|
|
|
|
}
|
|
|
|
|
|
|
|
float G_SmithGGXCorrelated(const Surface surface, float NoV, float NoL) {
|
|
|
|
float alpha2 = surface.roughness2 * surface.roughness2;
|
|
|
|
float GGXV = NoL * sqrt(alpha2 + (1. - alpha2) * (NoV * NoV));
|
|
|
|
float GGXL = NoV * sqrt(alpha2 + (1. - alpha2) * (NoL * NoL));
|
|
|
|
return .5 / (GGXV + GGXL);
|
|
|
|
}
|
|
|
|
|
|
|
|
vec3 F_Schlick(const Surface surface, float VoH) {
|
|
|
|
return surface.f0 + (vec3(1.) - surface.f0) * pow(1. - VoH, 5.);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Evaluates a direct light for a given surface
|
|
|
|
vec3 getLighting(const Surface surface, vec3 direction, vec4 color, float visibility) {
|
|
|
|
if (visibility <= 0.) {
|
|
|
|
return vec3(0.);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parameters
|
|
|
|
vec3 N = surface.normal;
|
|
|
|
vec3 V = surface.view;
|
|
|
|
vec3 L = normalize(-direction);
|
|
|
|
vec3 H = normalize(V + L);
|
2022-08-26 17:28:23 +00:00
|
|
|
vec3 R = surface.reflection;
|
2022-08-10 02:49:47 +00:00
|
|
|
float NoV = abs(dot(N, V)) + 1e-8;
|
2022-09-24 06:44:31 +00:00
|
|
|
float NoL = clamp(dot(N, L), 0., 1.);
|
2022-08-10 02:49:47 +00:00
|
|
|
float NoH = clamp(dot(N, H), 0., 1.);
|
|
|
|
float VoH = clamp(dot(V, H), 0., 1.);
|
|
|
|
|
|
|
|
// Diffuse
|
|
|
|
float Fd_Lambert = 1. / PI;
|
|
|
|
vec3 diffuse = surface.diffuse * Fd_Lambert;
|
|
|
|
|
|
|
|
// Specular
|
|
|
|
float D = D_GGX(surface, NoH);
|
|
|
|
float G = G_SmithGGXCorrelated(surface, NoV, NoL);
|
|
|
|
vec3 F = F_Schlick(surface, VoH);
|
2022-08-13 00:59:06 +00:00
|
|
|
vec3 specular = vec3(D * G) * F;
|
2022-08-10 02:49:47 +00:00
|
|
|
|
|
|
|
return (diffuse + specular) * color.rgb * (NoL * color.a * visibility);
|
|
|
|
}
|
2022-08-26 17:28:43 +00:00
|
|
|
|
2022-09-24 06:44:31 +00:00
|
|
|
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
|
|
|
|
vec2 prefilteredBRDF(float NoV, float roughness) {
|
|
|
|
vec4 c0 = vec4(-1., -.0275, -.572, .022);
|
|
|
|
vec4 c1 = vec4(1., .0425, 1.04, -.04);
|
|
|
|
vec4 r = roughness * c0 + c1;
|
|
|
|
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
|
|
|
|
return vec2(-1.04, 1.04) * a004 + r.zw;
|
|
|
|
}
|
|
|
|
|
2022-08-26 17:28:43 +00:00
|
|
|
vec3 evaluateSphericalHarmonics(vec3 sh[9], vec3 n) {
|
|
|
|
return max(
|
|
|
|
sh[0] +
|
|
|
|
sh[1] * n.y +
|
|
|
|
sh[2] * n.z +
|
|
|
|
sh[3] * n.x +
|
|
|
|
sh[4] * n.y * n.x +
|
|
|
|
sh[5] * n.y * n.z +
|
|
|
|
sh[6] * (3. * n.z * n.z - 1.) +
|
|
|
|
sh[7] * n.z * n.x +
|
|
|
|
sh[8] * (n.x * n.x - n.y * n.y)
|
|
|
|
, 0.);
|
|
|
|
}
|
2022-08-26 17:34:32 +00:00
|
|
|
|
2022-09-24 06:44:31 +00:00
|
|
|
vec3 getIndirectLighting(const Surface surface, textureCube environment, vec3 sphericalHarmonics[9]) {
|
|
|
|
float NoV = dot(surface.normal, surface.view);
|
2022-09-24 06:58:47 +00:00
|
|
|
vec2 lookup = prefilteredBRDF(NoV, surface.roughness);
|
2022-09-24 06:44:31 +00:00
|
|
|
|
|
|
|
int mipmapCount = textureQueryLevels(samplerCube(environment, Sampler));
|
2022-09-24 06:58:47 +00:00
|
|
|
vec3 ibl = textureLod(samplerCube(environment, Sampler), surface.reflection, surface.roughness * mipmapCount).rgb;
|
|
|
|
vec3 specular = (surface.f0 * lookup.r + lookup.g) * ibl;
|
|
|
|
|
2022-09-24 06:44:31 +00:00
|
|
|
vec3 sh = evaluateSphericalHarmonics(sphericalHarmonics, surface.normal);
|
|
|
|
vec3 diffuse = surface.diffuse * surface.occlusion * sh;
|
|
|
|
|
|
|
|
return diffuse + specular;
|
|
|
|
}
|
|
|
|
|
2022-08-26 17:34:32 +00:00
|
|
|
vec3 tonemap(vec3 x) {
|
|
|
|
float a = 2.51;
|
|
|
|
float b = 0.03;
|
|
|
|
float c = 2.43;
|
|
|
|
float d = 0.59;
|
|
|
|
float e = 0.14;
|
|
|
|
return (x * (a * x + b)) / (x * (c * x + d) + e);
|
|
|
|
}
|
2022-06-16 03:46:43 +00:00
|
|
|
#endif
|
2022-07-31 18:18:15 +00:00
|
|
|
|
2023-09-28 12:10:26 +00:00
|
|
|
vec3 gammaToLinear(vec3 color) {
|
|
|
|
return mix(pow((color + .055) / 1.055, vec3(2.4)), color / 12.92, lessThanEqual(color, vec3(.04045)));
|
|
|
|
}
|
|
|
|
|
|
|
|
vec3 linearToGamma(vec3 color) {
|
|
|
|
return mix(1.055 * pow(color, vec3(1. / 2.4)) - .055, color * 12.92, lessThanEqual(color, vec3(.0031308)));
|
|
|
|
}
|
|
|
|
|
2024-01-21 01:37:00 +00:00
|
|
|
uint packSnorm10x3(vec4 v) {
|
|
|
|
return
|
|
|
|
((int(v.x * 511.) & 0x3ff) << 0) |
|
|
|
|
((int(v.y * 511.) & 0x3ff) << 10) |
|
|
|
|
((int(v.z * 511.) & 0x3ff) << 20) |
|
|
|
|
((int(v.w * 2.) & 0x3) << 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The weird 22 bit shift basically does sign-extension of a 10-bit value stored in a 32-bit int
|
|
|
|
vec4 unpackSnorm10x3(uint n) {
|
|
|
|
return vec4(
|
|
|
|
max((int((n >> 0) & 0x3ff) << 22 >> 22) / 511., -1.),
|
|
|
|
max((int((n >> 10) & 0x3ff) << 22 >> 22) / 511., -1.),
|
|
|
|
max((int((n >> 20) & 0x3ff) << 22 >> 22) / 511., -1.),
|
|
|
|
max(float((n >> 30) & 0x3), -1.)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-31 18:18:15 +00:00
|
|
|
// Entrypoints
|
|
|
|
#ifndef NO_DEFAULT_MAIN
|
|
|
|
#ifdef GL_VERTEX_SHADER
|
|
|
|
vec4 lovrmain();
|
|
|
|
void main() {
|
2022-08-10 02:49:47 +00:00
|
|
|
PositionWorld = vec3(WorldFromLocal * VertexPosition);
|
2022-07-31 18:18:15 +00:00
|
|
|
Normal = NormalMatrix * VertexNormal;
|
|
|
|
UV = VertexUV;
|
2022-07-31 19:49:18 +00:00
|
|
|
|
2022-08-26 17:28:23 +00:00
|
|
|
Color = vec4(1.0);
|
|
|
|
if (flag_passColor) Color *= PassColor;
|
|
|
|
if (flag_materialColor) Color *= Material.color;
|
|
|
|
if (flag_vertexColors) Color *= VertexColor;
|
|
|
|
|
2023-04-01 02:23:20 +00:00
|
|
|
if (flag_vertexTangents) {
|
2023-11-10 00:50:52 +00:00
|
|
|
Tangent = vec4(NormalMatrix * VertexTangent.xyz, VertexTangent.w);
|
2022-08-13 00:59:06 +00:00
|
|
|
}
|
|
|
|
|
2022-08-26 17:28:23 +00:00
|
|
|
PointSize = flag_pointSize;
|
2022-07-31 18:18:15 +00:00
|
|
|
Position = lovrmain();
|
2022-07-31 19:49:18 +00:00
|
|
|
|
2022-08-26 17:28:23 +00:00
|
|
|
if (flag_uvTransform) {
|
2022-07-31 19:49:18 +00:00
|
|
|
UV *= Material.uvScale;
|
|
|
|
UV += Material.uvShift;
|
|
|
|
}
|
2022-07-31 18:18:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GL_FRAGMENT_SHADER
|
|
|
|
vec4 lovrmain();
|
|
|
|
void main() {
|
2023-02-06 00:04:17 +00:00
|
|
|
PixelColor = lovrmain();
|
2022-07-31 19:49:18 +00:00
|
|
|
|
2022-08-26 17:28:23 +00:00
|
|
|
if (flag_glow) {
|
|
|
|
if (flag_glowTexture) {
|
2023-02-06 00:04:17 +00:00
|
|
|
PixelColor.rgb += getPixel(GlowTexture, UV).rgb * Material.glow.rgb * Material.glow.a;
|
2022-08-26 17:28:23 +00:00
|
|
|
} else {
|
2023-02-06 00:04:17 +00:00
|
|
|
PixelColor.rgb += Material.glow.rgb * Material.glow.a;
|
2022-08-26 17:28:23 +00:00
|
|
|
}
|
2022-07-31 19:49:18 +00:00
|
|
|
}
|
|
|
|
|
2022-08-26 17:34:32 +00:00
|
|
|
if (flag_tonemap) {
|
2023-02-06 00:04:17 +00:00
|
|
|
PixelColor.rgb = tonemap(PixelColor.rgb);
|
2022-08-26 17:34:32 +00:00
|
|
|
}
|
|
|
|
|
2023-02-06 00:04:17 +00:00
|
|
|
if (flag_alphaCutoff && PixelColor.a <= Material.alphaCutoff) {
|
2022-07-31 19:49:18 +00:00
|
|
|
discard;
|
|
|
|
}
|
2022-07-31 18:18:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GL_COMPUTE_SHADER
|
2022-08-06 20:06:42 +00:00
|
|
|
void lovrmain();
|
2022-07-31 18:18:15 +00:00
|
|
|
void main() {
|
|
|
|
lovrmain();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|