mirror of https://github.com/bjornbytes/lovr.git
Compare commits
6 Commits
7e5221492d
...
5324ae9a84
Author | SHA1 | Date |
---|---|---|
bjorn | 5324ae9a84 | |
bjorn | 143b0ba664 | |
bjorn | 8233c202ba | |
bjorn | b51d4e7de7 | |
bjorn | 0be94e0f1a | |
bjorn | 3b33f4917e |
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue