Compare commits

...

3 Commits

Author SHA1 Message Date
bjorn 7e5221492d rm pointSize from Material;
It's weird, and about as inconvenient as just putting it in the shader.
2022-08-09 19:54:54 -07:00
bjorn 0a599ccdd6 Rename PixelColors to PixelColor; 2022-08-09 19:51:53 -07:00
bjorn 63a327c0b2 Add getLighting builtin function to shaders; 2022-08-09 19:49:47 -07:00
9 changed files with 140 additions and 33 deletions

View File

@ -1,7 +1,14 @@
// Flags
layout(constant_id = 1000) const bool applyUVTransform = true;
layout(constant_id = 1001) const bool applyAlphaCutoff = false;
layout(constant_id = 1002) const bool applyGlow = false;
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 useColorTexture = false;
layout(constant_id = 1004) const bool useGlowTexture = false;
layout(constant_id = 1005) const bool useMetalnessTexture = false;
layout(constant_id = 1006) const bool useRoughnessTexture = false;
layout(constant_id = 1007) const bool useOcclusionTexture = false;
layout(constant_id = 1008) const bool useClearcoatTexture = false;
layout(constant_id = 1009) const bool useNormalTexture = false;
// Resources
#ifndef GL_COMPUTE_SHADER
@ -23,7 +30,7 @@ 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;
struct MaterialData {
layout(set = 1, binding = 0) uniform MaterialBuffer {
vec4 color;
vec4 glow;
vec2 uvShift;
@ -36,12 +43,7 @@ struct MaterialData {
float occlusionStrength;
float normalScale;
float alphaCutoff;
float pointSize;
};
layout(set = 1, binding = 0) uniform MaterialBuffer {
MaterialData Material;
};
} Material;
layout(set = 1, binding = 1) uniform texture2D ColorTexture;
layout(set = 1, binding = 2) uniform texture2D GlowTexture;
@ -63,20 +65,22 @@ layout(location = 14) in vec3 VertexTangent;
// Framebuffer
#ifdef GL_FRAGMENT_SHADER
layout(location = 0) out vec4 PixelColors[1];
layout(location = 0) out vec4 PixelColor[1];
#endif
// Varyings
#ifdef GL_VERTEX_SHADER
layout(location = 10) out vec3 Normal;
layout(location = 11) out vec4 Color;
layout(location = 12) out vec2 UV;
layout(location = 10) out vec3 PositionWorld;
layout(location = 11) out vec3 Normal;
layout(location = 12) out vec4 Color;
layout(location = 13) out vec2 UV;
#endif
#ifdef GL_FRAGMENT_SHADER
layout(location = 10) in vec3 Normal;
layout(location = 11) in vec4 Color;
layout(location = 12) in vec2 UV;
layout(location = 10) in vec3 PositionWorld;
layout(location = 11) in vec3 Normal;
layout(location = 12) in vec4 Color;
layout(location = 13) in vec2 UV;
#endif
// Macros
@ -141,10 +145,120 @@ layout(location = 12) in vec2 UV;
// Helpers
#ifndef GL_COMPUTE_SHADER
// Helper for sampling textures using the default sampler set using Pass:setSampler
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, vec3 uvw) { return texture(sampler2DArray(t, Sampler), uvw); }
// 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;
};
void initSurface(out Surface surface) {
surface.position = PositionWorld;
if (useNormalTexture) {
//surface.normal = TangentMatrix * vec3(getPixel(NormalTexture, UV)) * Material.normalScale;
} else {
surface.normal = normalize(Normal);
}
surface.geometricNormal = normalize(Normal);
surface.view = CameraPositionWorld - PositionWorld;
surface.reflection = reflect(-surface.view, surface.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;
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), 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 = (D * G) * F;
return (diffuse + specular) * color.rgb * (NoL * color.a * visibility);
}
#endif
// Entrypoints
@ -152,14 +266,15 @@ vec4 getPixel(texture2DArray t, vec3 uvw) { return texture(sampler2DArray(t, Sam
#ifdef GL_VERTEX_SHADER
vec4 lovrmain();
void main() {
PositionWorld = vec3(WorldFromLocal * VertexPosition);
Normal = NormalMatrix * VertexNormal;
Color = VertexColor * Material.color * PassColor;
UV = VertexUV;
PointSize = Material.pointSize;
PointSize = 1.f;
Position = lovrmain();
if (applyUVTransform) {
if (enableUVTransform) {
UV *= Material.uvScale;
UV += Material.uvShift;
}
@ -169,13 +284,13 @@ void main() {
#ifdef GL_FRAGMENT_SHADER
vec4 lovrmain();
void main() {
PixelColors[0] = lovrmain();
PixelColor[0] = lovrmain();
if (applyGlow) {
PixelColors[0].rgb += getPixel(GlowTexture, UV).rgb * Material.glow.rgb * Material.glow.a;
if (enableGlow) {
PixelColor[0].rgb += getPixel(GlowTexture, UV).rgb * Material.glow.rgb * Material.glow.a;
}
if (applyAlphaCutoff && PixelColors[0].a <= Material.alphaCutoff) {
if (enableAlphaCutoff && PixelColor[0].a <= Material.alphaCutoff) {
discard;
}
}

View File

@ -609,7 +609,6 @@ static int l_lovrModelDataGetMaterial(lua_State* L) {
lua_pushnumber(L, material->occlusionStrength), lua_setfield(L, -2, "occlusionStrength");
lua_pushnumber(L, material->normalScale), lua_setfield(L, -2, "normalScale");
lua_pushnumber(L, material->alphaCutoff), lua_setfield(L, -2, "alphaCutoff");
lua_pushnumber(L, material->pointSize), lua_setfield(L, -2, "pointSize");
#define PUSH_IMAGE(t) if (material->t != ~0u) luax_pushtype(L, Image, model->images[material->t]), lua_setfield(L, -2, #t)
PUSH_IMAGE(texture);

View File

@ -1363,10 +1363,6 @@ static int l_lovrGraphicsNewMaterial(lua_State* L) {
info.data.alphaCutoff = luax_optfloat(L, -1, 0.f);
lua_pop(L, 1);
lua_getfield(L, 1, "pointSize");
info.data.pointSize = luax_optfloat(L, -1, 1.f);
lua_pop(L, 1);
lua_getfield(L, 1, "texture");
info.texture = luax_opttexture(L, -1);
lua_pop(L, 1);

View File

@ -52,7 +52,6 @@ static int l_lovrMaterialGetProperties(lua_State* L) {
lua_pushnumber(L, info->data.occlusionStrength), lua_setfield(L, -2, "occlusionStrength");
lua_pushnumber(L, info->data.normalScale), lua_setfield(L, -2, "normalScale");
lua_pushnumber(L, info->data.alphaCutoff), lua_setfield(L, -2, "alphaCutoff");
lua_pushnumber(L, info->data.pointSize), lua_setfield(L, -2, "pointSize");
luax_pushtype(L, Texture, info->texture), lua_setfield(L, -2, "texture");
luax_pushtype(L, Texture, info->glowTexture), lua_setfield(L, -2, "glowTexture");
luax_pushtype(L, Texture, info->occlusionTexture), lua_setfield(L, -2, "occlusionTexture");

View File

@ -86,7 +86,6 @@ typedef struct {
float occlusionStrength;
float normalScale;
float alphaCutoff;
float pointSize;
uint32_t texture;
uint32_t glowTexture;
uint32_t occlusionTexture;

View File

@ -707,7 +707,6 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
material->occlusionStrength = 1.f;
material->normalScale = 1.f;
material->alphaCutoff = 0.f;
material->pointSize = 1.f;
material->texture = ~0u;
material->glowTexture = ~0u;
material->occlusionTexture = ~0u;

View File

@ -58,7 +58,6 @@ static void parseMtl(char* path, char* base, ModelDataIO* io, arr_image_t* image
.occlusionStrength = 1.f,
.normalScale = 1.f,
.alphaCutoff = 0.f,
.pointSize = 1.f,
.texture = ~0u,
.glowTexture = ~0u,
.occlusionTexture = ~0u,

View File

@ -594,6 +594,8 @@ bool lovrGraphicsInit(GraphicsConfig* config) {
state.defaultMaterial = lovrMaterialCreate(&(MaterialInfo) {
.data.color = { 1.f, 1.f, 1.f, 1.f },
.data.uvScale = { 1.f, 1.f },
.data.metalness = 0.f,
.data.roughness = 1.f,
.texture = state.defaultTexture
});

View File

@ -332,7 +332,6 @@ typedef struct {
float occlusionStrength;
float normalScale;
float alphaCutoff;
float pointSize;
} MaterialData;
typedef struct {