Compare commits

...

6 Commits

Author SHA1 Message Date
bjorn 5324ae9a84 Fix error screen; 2022-08-12 19:28:25 -07:00
bjorn 143b0ba664 Fix DefaultShader initialization; 2022-08-12 18:26:47 -07:00
bjorn 8233c202ba Fix Pass:points / Pass:lines with vectors; 2022-08-12 18:11:45 -07:00
bjorn b51d4e7de7 Normal mapping; 2022-08-12 17:59:06 -07:00
bjorn 0be94e0f1a Set default material normalScale to 1; 2022-08-12 17:44:29 -07:00
bjorn 3b33f4917e Fix vertex format binding; 2022-08-12 17:43:41 -07:00
5 changed files with 103 additions and 65 deletions

View File

@ -191,13 +191,12 @@ function lovr.errhand(message, traceback)
elseif name == 'restart' then return 'restart', lovr.restart and lovr.restart()
elseif name == 'keypressed' and a == 'f5' then lovr.event.restart() end
end
local passes = {}
if lovr.headset then
if lovr.headset and lovr.headset.getDriver() ~= 'desktop' then
lovr.headset.update()
local pass = lovr.headset.getPass()
if pass then
render(pass)
passes[#passes + 1] = pass
lovr.graphics.submit(pass)
end
end
if lovr.system.isWindowOpen() then
@ -207,9 +206,9 @@ function lovr.errhand(message, traceback)
local projection = lovr.math.mat4():perspective(1.0, width / height, .1, 100)
pass:setProjection(1, projection)
render(pass)
passes[#passes + 1] = pass
lovr.graphics.submit(pass)
lovr.graphics.present()
end
lovr.graphics.submit(passes)
if lovr.headset then lovr.headset.submit() end
if lovr.math then lovr.math.drain() end
end

View File

@ -2,13 +2,14 @@
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;
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;
// Resources
#ifndef GL_COMPUTE_SHADER
@ -74,6 +75,7 @@ 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
@ -81,6 +83,7 @@ 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
@ -144,14 +147,16 @@ layout(location = 13) in vec2 UV;
#define PI_2 (.5f * PI)
// Helpers
#ifndef GL_COMPUTE_SHADER
// 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, vec3 uvw) { return texture(sampler2DArray(t, Sampler), uvw); }
#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
@ -173,17 +178,42 @@ struct Surface {
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;
if (useNormalTexture) {
//surface.normal = TangentMatrix * vec3(getPixel(NormalTexture, UV)) * Material.normalScale;
if (enableNormalMap) {
vec3 normalScale = vec3(Material.normalScale, Material.normalScale, 1.);
surface.normal = TangentMatrix * (normalize(getPixel(NormalTexture, UV).rgb * 2. - 1.) * normalScale);
} else {
surface.normal = normalize(Normal);
}
surface.geometricNormal = normalize(Normal);
surface.view = CameraPositionWorld - PositionWorld;
surface.view = normalize(CameraPositionWorld - PositionWorld);
surface.reflection = reflect(-surface.view, surface.normal);
vec4 color = Color;
@ -241,9 +271,9 @@ vec3 getLighting(const Surface surface, vec3 direction, vec4 color, float visibi
vec3 V = surface.view;
vec3 L = normalize(-direction);
vec3 H = normalize(V + L);
vec3 R = surface.reflection;
//vec3 R = surface.reflection;
float NoV = abs(dot(N, V)) + 1e-8;
float NoL = clamp(dot(N, L), 0., 1.);
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.);
@ -255,7 +285,7 @@ vec3 getLighting(const Surface surface, vec3 direction, vec4 color, float visibi
float D = D_GGX(surface, NoH);
float G = G_SmithGGXCorrelated(surface, NoV, NoL);
vec3 F = F_Schlick(surface, VoH);
vec3 specular = (D * G) * F;
vec3 specular = vec3(D * G) * F;
return (diffuse + specular) * color.rgb * (NoL * color.a * visibility);
}
@ -271,6 +301,10 @@ void main() {
Color = VertexColor * Material.color * PassColor;
UV = VertexUV;
if (enableNormalMap && useVertexTangents) {
Tangent = NormalMatrix * VertexTangent;
}
PointSize = 1.f;
Position = lovrmain();

View File

@ -1108,6 +1108,7 @@ static ShaderSource luax_checkshadersource(lua_State* L, int index, ShaderStage
} else {
for (int i = 0; lovrDefaultShader[i].length; i++) {
if (lovrDefaultShader[i].length == length && !memcmp(lovrDefaultShader[i].string, string, length)) {
*allocated = false;
return lovrGraphicsGetDefaultShaderSource(i, stage);
}
}
@ -1179,6 +1180,8 @@ static int l_lovrGraphicsNewShader(lua_State* L) {
info.source[0] = lovrGraphicsGetDefaultShaderSource(i, STAGE_VERTEX);
info.source[1] = lovrGraphicsGetDefaultShaderSource(i, STAGE_FRAGMENT);
info.type = SHADER_GRAPHICS;
allocated[0] = false;
allocated[1] = false;
break;
}
}

View File

@ -592,6 +592,7 @@ static uint32_t luax_getvertexcount(lua_State* L, int index) {
lua_pop(L, 1);
return luax_len(L, index) / (innerType == LUA_TNUMBER ? 3 : 1);
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
return lua_gettop(L) - index + 1;
default:
return luax_typeerror(L, index, "number, table, or vector");
@ -629,8 +630,10 @@ static void luax_readvertices(lua_State* L, int index, float* vertices, uint32_t
}
break;
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
for (uint32_t i = 0; i < count; i++) {
vec3_init(vertices, luax_checkvector(L, index + i, V_VEC3, NULL));
float *v = luax_checkvector(L, index + i, V_VEC3, NULL);
memcpy(vertices, v, 3 * sizeof(float));
vertices += 3;
}
break;

View File

@ -596,6 +596,7 @@ bool lovrGraphicsInit(GraphicsConfig* config) {
.data.uvScale = { 1.f, 1.f },
.data.metalness = 0.f,
.data.roughness = 1.f,
.data.normalScale = 1.f,
.texture = state.defaultTexture
});
@ -4011,57 +4012,55 @@ static void bindPipeline(Pass* pass, Draw* draw, Shader* shader) {
}
// Vertex formats
if (pipeline->formatHash != 1 + draw->vertex.format) {
if (!draw->vertex.buffer) {
pipeline->formatHash = 1 + draw->vertex.format;
pipeline->info.vertex = state.vertexFormats[draw->vertex.format];
pipeline->dirty = true;
if (draw->vertex.buffer && pipeline->formatHash != draw->vertex.buffer->hash) {
pipeline->formatHash = draw->vertex.buffer->hash;
pipeline->info.vertex.bufferCount = 2;
pipeline->info.vertex.attributeCount = shader->attributeCount;
pipeline->info.vertex.bufferStrides[0] = draw->vertex.buffer->info.stride;
pipeline->info.vertex.bufferStrides[1] = 0;
pipeline->dirty = true;
if (shader->hasCustomAttributes) {
for (uint32_t i = 0; i < shader->attributeCount; i++) {
if (shader->attributes[i].location < 10) {
pipeline->info.vertex.attributes[pipeline->info.vertex.attributeCount++] = (gpu_attribute) {
.buffer = 1,
.location = shader->attributes[i].location,
.type = GPU_TYPE_F32x4,
.offset = shader->attributes[i].location == LOCATION_COLOR ? 16 : 0
};
}
for (uint32_t i = 0; i < shader->attributeCount; i++) {
ShaderAttribute* attribute = &shader->attributes[i];
bool found = false;
for (uint32_t j = 0; j < draw->vertex.buffer->info.fieldCount; j++) {
BufferField field = draw->vertex.buffer->info.fields[j];
lovrCheck(field.type < FIELD_MAT2, "Currently, matrix and index types can not be used in vertex buffers");
if (field.hash ? (field.hash == attribute->hash) : (field.location == attribute->location)) {
pipeline->info.vertex.attributes[i] = (gpu_attribute) {
.buffer = 0,
.location = attribute->location,
.offset = field.offset,
.type = field.type
};
found = true;
break;
}
}
} else {
pipeline->formatHash = draw->vertex.buffer->hash;
pipeline->info.vertex.bufferCount = 2;
pipeline->info.vertex.attributeCount = shader->attributeCount;
pipeline->info.vertex.bufferStrides[0] = draw->vertex.buffer->info.stride;
pipeline->info.vertex.bufferStrides[1] = 0;
pipeline->dirty = true;
if (!found) {
pipeline->info.vertex.attributes[i] = (gpu_attribute) {
.buffer = 1,
.location = attribute->location,
.offset = attribute->location == LOCATION_COLOR ? 16 : 0,
.type = GPU_TYPE_F32x4
};
}
}
} else if (!draw->vertex.buffer && pipeline->formatHash != 1 + draw->vertex.format) {
pipeline->formatHash = 1 + draw->vertex.format;
pipeline->info.vertex = state.vertexFormats[draw->vertex.format];
pipeline->dirty = true;
if (shader->hasCustomAttributes) {
for (uint32_t i = 0; i < shader->attributeCount; i++) {
ShaderAttribute* attribute = &shader->attributes[i];
bool found = false;
for (uint32_t j = 0; j < draw->vertex.buffer->info.fieldCount; j++) {
BufferField field = draw->vertex.buffer->info.fields[j];
lovrCheck(field.type < FIELD_MAT2, "Currently, matrix and index types can not be used in vertex buffers");
if (field.hash ? (field.hash == attribute->hash) : (field.location == attribute->location)) {
pipeline->info.vertex.attributes[i] = (gpu_attribute) {
.buffer = 0,
.location = attribute->location,
.offset = field.offset,
.type = field.type
};
found = true;
break;
}
}
if (!found) {
pipeline->info.vertex.attributes[i] = (gpu_attribute) {
if (shader->attributes[i].location < 10) {
pipeline->info.vertex.attributes[pipeline->info.vertex.attributeCount++] = (gpu_attribute) {
.buffer = 1,
.location = attribute->location,
.offset = attribute->location == LOCATION_COLOR ? 16 : 0,
.type = GPU_TYPE_F32x4
.location = shader->attributes[i].location,
.type = GPU_TYPE_F32x4,
.offset = shader->attributes[i].location == LOCATION_COLOR ? 16 : 0
};
}
}