1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-05 22:03:36 +00:00
lovr/etc/shaders/lovr.glsl
bjorn ede1036694 Temporary Passes;
Sigh, back to getPass.  I don't even know at this point.  Basically now
that we came up with a half-solution for temp buffers, it makes sense to
apply this to passes as well, since we aren't going with the workstream
idea and temp passes are more convenient than retained passes.
2022-08-25 21:57:15 -07:00

352 lines
11 KiB
GLSL

// Flags
layout(constant_id = 1000) const bool enableUVTransform = true;
layout(constant_id = 1001) const bool enableAlphaCutoff = false;
layout(constant_id = 1002) const bool enableGlow = false;
layout(constant_id = 1003) const bool enableNormalMap = false;
layout(constant_id = 1004) const bool useVertexTangents = true;
layout(constant_id = 1005) const bool useColorTexture = true;
layout(constant_id = 1006) const bool useGlowTexture = false;
layout(constant_id = 1007) const bool useMetalnessTexture = true;
layout(constant_id = 1008) const bool useRoughnessTexture = true;
layout(constant_id = 1009) const bool useOcclusionTexture = false;
layout(constant_id = 1010) const bool useClearcoatTexture = false;
layout(constant_id = 1011) const uint attachmentCount = 1;
layout(constant_id = 1012) const float defaultPointSize = 1.f;
// Resources
#ifndef GL_COMPUTE_SHADER
struct Camera {
mat4 view;
mat4 projection;
mat4 viewProjection;
mat4 inverseProjection;
};
struct Draw {
mat4 transform;
mat4 normalMatrix;
vec4 color;
};
layout(set = 0, binding = 0) uniform Globals { vec2 Resolution; float Time; };
layout(set = 0, binding = 1) uniform CameraBuffer { Camera Cameras[6]; };
layout(set = 0, binding = 2) uniform DrawBuffer { Draw Draws[256]; };
layout(set = 0, binding = 3) uniform sampler Sampler;
layout(set = 1, binding = 0) uniform MaterialBuffer {
vec4 color;
vec4 glow;
vec2 uvShift;
vec2 uvScale;
vec2 sdfRange;
float metalness;
float roughness;
float clearcoat;
float clearcoatRoughness;
float occlusionStrength;
float normalScale;
float alphaCutoff;
} Material;
layout(set = 1, binding = 1) uniform texture2D ColorTexture;
layout(set = 1, binding = 2) uniform texture2D GlowTexture;
layout(set = 1, binding = 3) uniform texture2D OcclusionTexture;
layout(set = 1, binding = 4) uniform texture2D MetalnessTexture;
layout(set = 1, binding = 5) uniform texture2D RoughnessTexture;
layout(set = 1, binding = 6) uniform texture2D ClearcoatTexture;
layout(set = 1, binding = 7) uniform texture2D NormalTexture;
#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;
layout(location = 14) in vec3 VertexTangent;
#endif
// Framebuffer
#ifdef GL_FRAGMENT_SHADER
layout(location = 0) out vec4 PixelColor[attachmentCount];
#endif
// Varyings
#ifdef GL_VERTEX_SHADER
layout(location = 10) out vec3 PositionWorld;
layout(location = 11) out vec3 Normal;
layout(location = 12) out vec4 Color;
layout(location = 13) out vec2 UV;
layout(location = 14) out vec3 Tangent;
#endif
#ifdef GL_FRAGMENT_SHADER
layout(location = 10) in vec3 PositionWorld;
layout(location = 11) in vec3 Normal;
layout(location = 12) in vec4 Color;
layout(location = 13) in vec2 UV;
layout(location = 14) in vec3 Tangent;
#endif
// Macros
#ifdef GL_COMPUTE_SHADER
#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
#else
#define BaseInstance gl_BaseInstance
#define BaseVertex gl_BaseVertex
#define ClipDistance gl_ClipDistance
#define CullDistance gl_CullDistance
#define DrawIndex gl_DrawIndex
#define InstanceIndex (gl_InstanceIndex - gl_BaseInstance)
#define FragCoord gl_FragCoord
#define FragDepth gl_FragDepth
#define FrontFacing gl_FrontFacing
#define PointCoord gl_PointCoord
#define PointSize gl_PointSize
#define Position gl_Position
#define PrimitiveID gl_PrimitiveID
#define SampleID gl_SampleID
#define SampleMaskIn gl_SampleMaskIn
#define SampleMask gl_SampleMask
#define SamplePosition gl_SamplePosition
#define VertexIndex gl_VertexIndex
#define ViewIndex gl_ViewIndex
#define DrawID gl_BaseInstance
#define Projection Cameras[ViewIndex].projection
#define View Cameras[ViewIndex].view
#define ViewProjection Cameras[ViewIndex].viewProjection
#define InverseProjection Cameras[ViewIndex].inverseProjection
#define Transform Draws[DrawID].transform
#define NormalMatrix mat3(Draws[DrawID].normalMatrix)
#define PassColor Draws[DrawID].color
#define ClipFromLocal (ViewProjection * Transform)
#define ClipFromWorld (ViewProjection)
#define ClipFromView (Projection)
#define ViewFromLocal (View * Transform)
#define ViewFromWorld (View)
#define ViewFromClip (InverseProjection)
#define WorldFromLocal (Transform)
#define WorldFromView (inverse(View))
#define WorldFromClip (inverse(ViewProjection))
#define CameraPositionWorld (-View[3].xyz * mat3(View))
#define DefaultPosition (ClipFromLocal * VertexPosition)
#define DefaultColor (Color * getPixel(ColorTexture, UV))
#endif
// Constants
#define PI 3.141592653589793238462643383279502f
#define TAU (2.f * PI)
#define PI_2 (.5f * PI)
// Helpers
#define Constants layout(push_constant) uniform PushConstants
// Helper for sampling textures using the default sampler set using Pass:setSampler
#ifndef GL_COMPUTE_SHADER
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); }
vec4 getPixel(texture2DArray t, vec2 uv, uint layer) { return texture(sampler2DArray(t, Sampler), vec3(uv, layer)); }
vec4 getPixel(texture2DArray t, vec2 uv, float layer) { return texture(sampler2DArray(t, Sampler), vec3(uv, layer)); }
#endif
#ifdef GL_FRAGMENT_SHADER
// 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;
float roughness2;
float occlusion;
float clearcoat;
float clearcoatRoughness;
float alpha;
};
#define TangentMatrix getTangentMatrix()
mat3 getTangentMatrix() {
if (useVertexTangents) {
vec3 N = normalize(Normal);
vec3 T = normalize(Tangent);
vec3 B = cross(N, T);
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);
}
}
void initSurface(out Surface surface) {
surface.position = PositionWorld;
vec3 normal = normalize(Normal);
if (!FrontFacing) {
normal = -normal;
}
if (enableNormalMap) {
vec3 normalScale = vec3(Material.normalScale, Material.normalScale, 1.);
surface.normal = TangentMatrix * (normalize(getPixel(NormalTexture, UV).rgb * 2. - 1.) * normalScale);
} else {
surface.normal = normal;
}
surface.geometricNormal = normal;
surface.view = normalize(CameraPositionWorld - PositionWorld);
surface.reflection = reflect(-surface.view, normal);
vec4 color = Color;
if (useColorTexture) color *= getPixel(ColorTexture, UV);
float metallic = Material.metalness;
if (useMetalnessTexture) metallic *= getPixel(MetalnessTexture, UV).b;
surface.f0 = mix(vec3(.04), color.rgb, metallic);
surface.diffuse = mix(color.rgb, vec3(0.), metallic);
surface.emissive = Material.glow.rgb * Material.glow.a;
if (useGlowTexture) surface.emissive *= getPixel(GlowTexture, UV).rgb;
float roughness = Material.roughness;
if (useRoughnessTexture) roughness *= getPixel(RoughnessTexture, UV).g;
roughness = max(roughness, .05);
surface.roughness2 = roughness * roughness;
surface.occlusion = 1.;
if (useOcclusionTexture) surface.occlusion *= getPixel(OcclusionTexture, UV).r * Material.occlusionStrength;
surface.clearcoat = Material.clearcoat;
if (useClearcoatTexture) surface.clearcoat *= getPixel(ClearcoatTexture, UV).r;
surface.clearcoatRoughness = Material.clearcoatRoughness;
surface.alpha = color.a;
}
float D_GGX(const Surface surface, float NoH) {
float alpha2 = surface.roughness2 * surface.roughness2;
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);
//vec3 R = surface.reflection;
float NoV = abs(dot(N, V)) + 1e-8;
float NoL = clamp(dot(N, L) * .5 + .5, 0., 1.);
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);
vec3 specular = vec3(D * G) * F;
return (diffuse + specular) * color.rgb * (NoL * color.a * visibility);
}
#endif
// Entrypoints
#ifndef NO_DEFAULT_MAIN
#ifdef GL_VERTEX_SHADER
vec4 lovrmain();
void main() {
PositionWorld = vec3(WorldFromLocal * VertexPosition);
Normal = NormalMatrix * VertexNormal;
Color = VertexColor * Material.color * PassColor;
UV = VertexUV;
if (enableNormalMap && useVertexTangents) {
Tangent = NormalMatrix * VertexTangent;
}
PointSize = defaultPointSize;
Position = lovrmain();
if (enableUVTransform) {
UV *= Material.uvScale;
UV += Material.uvShift;
}
}
#endif
#ifdef GL_FRAGMENT_SHADER
vec4 lovrmain();
void main() {
PixelColor[0] = lovrmain();
if (enableGlow) {
PixelColor[0].rgb += getPixel(GlowTexture, UV).rgb * Material.glow.rgb * Material.glow.a;
}
if (enableAlphaCutoff && PixelColor[0].a <= Material.alphaCutoff) {
discard;
}
}
#endif
#ifdef GL_COMPUTE_SHADER
void lovrmain();
void main() {
lovrmain();
}
#endif
#endif