From 3d706a899b124e37d3417e5d6f0db6d4a1f06fe5 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 22 Mar 2025 12:40:54 -0700 Subject: [PATCH 1/3] Add support for second set of UVs; --- etc/shaders.h | 5 ++-- etc/shaders/lovr.glsl | 15 +++++++----- src/api/l_data.c | 1 + src/modules/data/modelData.c | 16 +++++++++++-- src/modules/data/modelData.h | 1 + src/modules/data/modelData_gltf.c | 1 + src/modules/graphics/graphics.c | 38 +++++++++++++++++++------------ 7 files changed, 53 insertions(+), 24 deletions(-) diff --git a/etc/shaders.h b/etc/shaders.h index f93a364c0..2e3066cca 100644 --- a/etc/shaders.h +++ b/etc/shaders.h @@ -17,7 +17,8 @@ #define LOCATION_POSITION 10 #define LOCATION_NORMAL 11 #define LOCATION_UV 12 -#define LOCATION_COLOR 13 -#define LOCATION_TANGENT 14 +#define LOCATION_UV2 13 +#define LOCATION_COLOR 14 +#define LOCATION_TANGENT 15 #define LAST_BUILTIN_BINDING 3 diff --git a/etc/shaders/lovr.glsl b/etc/shaders/lovr.glsl index 75f4d1fed..4d4dabf96 100644 --- a/etc/shaders/lovr.glsl +++ b/etc/shaders/lovr.glsl @@ -74,8 +74,9 @@ layout(push_constant) uniform PushConstants { 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 vec4 VertexTangent; +layout(location = 13) in vec2 VertexUV2; +layout(location = 14) in vec4 VertexColor; +layout(location = 15) in vec4 VertexTangent; #endif // Framebuffer @@ -88,16 +89,18 @@ layout(location = 0) out vec4 PixelColor; layout(location = 10) out vec3 PositionWorld; layout(location = 11) out vec3 Normal; layout(location = 12) out vec2 UV; -layout(location = 13) out vec4 Color; -layout(location = 14) out vec4 Tangent; +layout(location = 13) out vec2 UV2; +layout(location = 14) out vec4 Color; +layout(location = 15) out vec4 Tangent; #endif #ifdef GL_FRAGMENT_SHADER layout(location = 10) in vec3 PositionWorld; layout(location = 11) in vec3 Normal; layout(location = 12) in vec2 UV; -layout(location = 13) in vec4 Color; -layout(location = 14) in vec4 Tangent; +layout(location = 13) in vec2 UV2; +layout(location = 14) in vec4 Color; +layout(location = 15) in vec4 Tangent; #endif // Builtins diff --git a/src/api/l_data.c b/src/api/l_data.c index 5096b20e5..deab49042 100644 --- a/src/api/l_data.c +++ b/src/api/l_data.c @@ -31,6 +31,7 @@ StringEntry lovrDefaultAttribute[] = { [ATTR_POSITION] = ENTRY("position"), [ATTR_NORMAL] = ENTRY("normal"), [ATTR_UV] = ENTRY("uv"), + [ATTR_UV2] = ENTRY("uv2"), [ATTR_COLOR] = ENTRY("color"), [ATTR_TANGENT] = ENTRY("tangent"), [ATTR_JOINTS] = ENTRY("joints"), diff --git a/src/modules/data/modelData.c b/src/modules/data/modelData.c index 5f9f8b84d..62ff9df13 100644 --- a/src/modules/data/modelData.c +++ b/src/modules/data/modelData.c @@ -256,11 +256,23 @@ void lovrModelDataCopyAttribute(ModelData* data, ModelAttribute* attribute, char } else { lovrUnreachable(); } - } else if (type == U16 && components == 1 && !normalized && !attribute->normalized) { - if (attribute->type == U8) { + } else if (type == U16) { + if (attribute->type == U8 && !attribute->normalized && !normalized && components == 1) { for (uint32_t i = 0; i < count; i++, src += attribute->stride, dst += stride) { *((uint16_t*) dst) = *(uint8_t*) src; } + } else if (attribute->type == F32 && normalized) { + for (uint32_t i = 0; i < count; i++, src += attribute->stride, dst += stride) { + for (uint32_t j = 0; j < components; j++) { + ((uint16_t*) dst)[j] = (uint16_t) (((float*) src)[j] * 65535.f + .5f); + } + } + } else if (attribute->type == U8 && attribute->normalized && normalized) { + for (uint32_t i = 0; i < count; i++, src += attribute->stride, dst += stride) { + for (uint32_t j = 0; j < components; j++) { + ((uint16_t*) dst)[j] = (uint16_t) ((((uint8_t*) src)[j] / 255.f) * 65535.f + .5f); + } + } } else { lovrUnreachable(); } diff --git a/src/modules/data/modelData.h b/src/modules/data/modelData.h index f8df0a0e3..7b4935b4b 100644 --- a/src/modules/data/modelData.h +++ b/src/modules/data/modelData.h @@ -25,6 +25,7 @@ typedef enum { ATTR_POSITION, ATTR_NORMAL, ATTR_UV, + ATTR_UV2, ATTR_COLOR, ATTR_TANGENT, ATTR_JOINTS, diff --git a/src/modules/data/modelData_gltf.c b/src/modules/data/modelData_gltf.c index 56dc18ef1..286fa3a0a 100644 --- a/src/modules/data/modelData_gltf.c +++ b/src/modules/data/modelData_gltf.c @@ -858,6 +858,7 @@ bool lovrModelDataInitGltf(ModelData** result, Blob* source, ModelDataIO* io) { if (STR_EQ(name, "POSITION")) { attributeType = ATTR_POSITION; } else if (STR_EQ(name, "NORMAL")) { attributeType = ATTR_NORMAL; } else if (STR_EQ(name, "TEXCOORD_0")) { attributeType = ATTR_UV; } + else if (STR_EQ(name, "TEXCOORD_1")) { attributeType = ATTR_UV2; } else if (STR_EQ(name, "COLOR_0")) { attributeType = ATTR_COLOR; } else if (STR_EQ(name, "TANGENT")) { attributeType = ATTR_TANGENT; } else if (STR_EQ(name, "JOINTS_0")) { attributeType = ATTR_JOINTS; } diff --git a/src/modules/graphics/graphics.c b/src/modules/graphics/graphics.c index fa921a1fd..85b8a49ea 100644 --- a/src/modules/graphics/graphics.c +++ b/src/modules/graphics/graphics.c @@ -361,7 +361,8 @@ typedef struct { typedef struct { struct { float x, y, z; } position; uint32_t normal; - struct { float u, v; } uv; + struct { uint16_t u, v; } uv; + struct { uint16_t u, v; } uv2; struct { uint8_t r, g, b, a; } color; uint32_t tangent; } ModelVertex; @@ -809,8 +810,9 @@ bool lovrGraphicsInit(GraphicsConfig* config) { .attributes[0] = { 0, 10, offsetof(ShapeVertex, position), GPU_TYPE_F32x3 }, .attributes[1] = { 0, 11, offsetof(ShapeVertex, normal), GPU_TYPE_F32x3 }, .attributes[2] = { 0, 12, offsetof(ShapeVertex, uv), GPU_TYPE_F32x2 }, - .attributes[3] = { 1, 13, 16, GPU_TYPE_F32x4 }, - .attributes[4] = { 1, 14, 0, GPU_TYPE_F32x4 } + .attributes[3] = { 1, 13, 0, GPU_TYPE_F32x2 }, + .attributes[4] = { 1, 14, 16, GPU_TYPE_F32x4 }, + .attributes[5] = { 1, 15, 0, GPU_TYPE_F32x4 } }; state.vertexFormats[VERTEX_POINT] = (gpu_vertex_format) { @@ -820,8 +822,9 @@ bool lovrGraphicsInit(GraphicsConfig* config) { .attributes[0] = { 0, 10, 0, GPU_TYPE_F32x3 }, .attributes[1] = { 1, 11, 0, GPU_TYPE_F32x4 }, .attributes[2] = { 1, 12, 0, GPU_TYPE_F32x4 }, - .attributes[3] = { 1, 13, 16, GPU_TYPE_F32x4 }, - .attributes[4] = { 1, 14, 0, GPU_TYPE_F32x4 } + .attributes[3] = { 1, 13, 0, GPU_TYPE_F32x2 }, + .attributes[4] = { 1, 14, 16, GPU_TYPE_F32x4 }, + .attributes[5] = { 1, 15, 0, GPU_TYPE_F32x4 } }; state.vertexFormats[VERTEX_GLYPH] = (gpu_vertex_format) { @@ -831,8 +834,9 @@ bool lovrGraphicsInit(GraphicsConfig* config) { .attributes[0] = { 0, 10, offsetof(GlyphVertex, position), GPU_TYPE_F32x2 }, .attributes[1] = { 1, 11, 0, GPU_TYPE_F32x4 }, .attributes[2] = { 0, 12, offsetof(GlyphVertex, uv), GPU_TYPE_UN16x2 }, - .attributes[3] = { 0, 13, offsetof(GlyphVertex, color), GPU_TYPE_UN8x4 }, - .attributes[4] = { 1, 14, 0, GPU_TYPE_F32x4 } + .attributes[3] = { 1, 13, 0, GPU_TYPE_F32x2 }, + .attributes[4] = { 0, 14, offsetof(GlyphVertex, color), GPU_TYPE_UN8x4 }, + .attributes[5] = { 1, 15, 0, GPU_TYPE_F32x4 } }; state.vertexFormats[VERTEX_MODEL] = (gpu_vertex_format) { @@ -841,9 +845,10 @@ bool lovrGraphicsInit(GraphicsConfig* config) { .bufferStrides[0] = sizeof(ModelVertex), .attributes[0] = { 0, 10, offsetof(ModelVertex, position), GPU_TYPE_F32x3 }, .attributes[1] = { 0, 11, offsetof(ModelVertex, normal), GPU_TYPE_SN10x3 }, - .attributes[2] = { 0, 12, offsetof(ModelVertex, uv), GPU_TYPE_F32x2 }, - .attributes[3] = { 0, 13, offsetof(ModelVertex, color), GPU_TYPE_UN8x4 }, - .attributes[4] = { 0, 14, offsetof(ModelVertex, tangent), GPU_TYPE_SN10x3 } + .attributes[2] = { 0, 12, offsetof(ModelVertex, uv), GPU_TYPE_UN16x2 }, + .attributes[3] = { 0, 13, offsetof(ModelVertex, uv2), GPU_TYPE_UN16x2 }, + .attributes[4] = { 0, 14, offsetof(ModelVertex, color), GPU_TYPE_UN8x4 }, + .attributes[5] = { 0, 15, offsetof(ModelVertex, tangent), GPU_TYPE_SN10x3 } }; state.vertexFormats[VERTEX_EMPTY] = (gpu_vertex_format) { @@ -852,8 +857,9 @@ bool lovrGraphicsInit(GraphicsConfig* config) { .attributes[0] = { 1, 10, 0, GPU_TYPE_F32x3 }, .attributes[1] = { 1, 11, 0, GPU_TYPE_F32x3 }, .attributes[2] = { 1, 12, 0, GPU_TYPE_F32x2 }, - .attributes[3] = { 1, 13, 16, GPU_TYPE_F32x4 }, - .attributes[4] = { 1, 14, 0, GPU_TYPE_F32x4 } + .attributes[3] = { 1, 13, 0, GPU_TYPE_F32x2 }, + .attributes[4] = { 1, 14, 16, GPU_TYPE_F32x4 }, + .attributes[5] = { 1, 15, 0, GPU_TYPE_F32x4 } }; float16Init(); @@ -4958,7 +4964,8 @@ Model* lovrModelCreate(const ModelInfo* info) { { .length = data->vertexCount, .stride = sizeof(ModelVertex), .fieldCount = 5 }, { .name = "VertexPosition", .type = TYPE_F32x3, .offset = offsetof(ModelVertex, position) }, { .name = "VertexNormal", .type = TYPE_SN10x3, .offset = offsetof(ModelVertex, normal) }, - { .name = "VertexUV", .type = TYPE_F32x2, .offset = offsetof(ModelVertex, uv) }, + { .name = "VertexUV", .type = TYPE_UN16x2, .offset = offsetof(ModelVertex, uv) }, + { .name = "VertexUV2", .type = TYPE_UN16x2, .offset = offsetof(ModelVertex, uv2) }, { .name = "VertexColor", .type = TYPE_UN8x4, .offset = offsetof(ModelVertex, color) }, { .name = "VertexTangent", .type = TYPE_SN10x3, .offset = offsetof(ModelVertex, tangent) } } @@ -5105,9 +5112,12 @@ Model* lovrModelCreate(const ModelInfo* info) { uint32_t count = attributes[ATTR_POSITION]->count; size_t stride = sizeof(ModelVertex); + ModelAttribute* uv2 = attributes[ATTR_UV2] ? attributes[ATTR_UV2] : attributes[ATTR_UV]; + lovrModelDataCopyAttribute(data, attributes[ATTR_POSITION], vertexData + 0, F32, 3, false, count, stride, 0); lovrModelDataCopyAttribute(data, attributes[ATTR_NORMAL], vertexData + 12, SN10x3, 1, false, count, stride, 0); - lovrModelDataCopyAttribute(data, attributes[ATTR_UV], vertexData + 16, F32, 2, false, count, stride, 0); + lovrModelDataCopyAttribute(data, attributes[ATTR_UV], vertexData + 16, U16, 2, true, count, stride, 0); + lovrModelDataCopyAttribute(data, uv2, vertexData + 20, U16, 2, true, count, stride, 0); lovrModelDataCopyAttribute(data, attributes[ATTR_COLOR], vertexData + 24, U8, 4, true, count, stride, 255); lovrModelDataCopyAttribute(data, attributes[ATTR_TANGENT], vertexData + 28, SN10x3, 1, false, count, stride, 0); vertexData += count * stride; From b9f79c8c13010fe20c3cfdde82de4c96db7743d3 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 22 Mar 2025 14:06:19 -0700 Subject: [PATCH 2/3] Vertex shader sends UV2 to fragment shader; --- etc/shaders/lovr.glsl | 1 + 1 file changed, 1 insertion(+) diff --git a/etc/shaders/lovr.glsl b/etc/shaders/lovr.glsl index 4d4dabf96..eaf9a0c96 100644 --- a/etc/shaders/lovr.glsl +++ b/etc/shaders/lovr.glsl @@ -529,6 +529,7 @@ void main() { PositionWorld = vec3(WorldFromLocal * VertexPosition); Normal = NormalMatrix * VertexNormal; UV = VertexUV; + UV2 = VertexUV2; Color = vec4(1.0); if (flag_passColor) Color *= PassColor; From 4e6aae3a04a2f62b1f1afe0607c0fcdbdaaeb8bb Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 22 Mar 2025 14:09:40 -0700 Subject: [PATCH 3/3] Fix default vertex formats; --- src/modules/graphics/graphics.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/graphics/graphics.c b/src/modules/graphics/graphics.c index 85b8a49ea..2e9934ff3 100644 --- a/src/modules/graphics/graphics.c +++ b/src/modules/graphics/graphics.c @@ -805,7 +805,7 @@ bool lovrGraphicsInit(GraphicsConfig* config) { state.vertexFormats[VERTEX_SHAPE] = (gpu_vertex_format) { .bufferCount = 2, - .attributeCount = 5, + .attributeCount = 6, .bufferStrides[0] = sizeof(ShapeVertex), .attributes[0] = { 0, 10, offsetof(ShapeVertex, position), GPU_TYPE_F32x3 }, .attributes[1] = { 0, 11, offsetof(ShapeVertex, normal), GPU_TYPE_F32x3 }, @@ -817,7 +817,7 @@ bool lovrGraphicsInit(GraphicsConfig* config) { state.vertexFormats[VERTEX_POINT] = (gpu_vertex_format) { .bufferCount = 2, - .attributeCount = 5, + .attributeCount = 6, .bufferStrides[0] = 12, .attributes[0] = { 0, 10, 0, GPU_TYPE_F32x3 }, .attributes[1] = { 1, 11, 0, GPU_TYPE_F32x4 }, @@ -829,7 +829,7 @@ bool lovrGraphicsInit(GraphicsConfig* config) { state.vertexFormats[VERTEX_GLYPH] = (gpu_vertex_format) { .bufferCount = 2, - .attributeCount = 5, + .attributeCount = 6, .bufferStrides[0] = sizeof(GlyphVertex), .attributes[0] = { 0, 10, offsetof(GlyphVertex, position), GPU_TYPE_F32x2 }, .attributes[1] = { 1, 11, 0, GPU_TYPE_F32x4 }, @@ -841,7 +841,7 @@ bool lovrGraphicsInit(GraphicsConfig* config) { state.vertexFormats[VERTEX_MODEL] = (gpu_vertex_format) { .bufferCount = 2, - .attributeCount = 5, + .attributeCount = 6, .bufferStrides[0] = sizeof(ModelVertex), .attributes[0] = { 0, 10, offsetof(ModelVertex, position), GPU_TYPE_F32x3 }, .attributes[1] = { 0, 11, offsetof(ModelVertex, normal), GPU_TYPE_SN10x3 }, @@ -853,7 +853,7 @@ bool lovrGraphicsInit(GraphicsConfig* config) { state.vertexFormats[VERTEX_EMPTY] = (gpu_vertex_format) { .bufferCount = 2, - .attributeCount = 5, + .attributeCount = 6, .attributes[0] = { 1, 10, 0, GPU_TYPE_F32x3 }, .attributes[1] = { 1, 11, 0, GPU_TYPE_F32x3 }, .attributes[2] = { 1, 12, 0, GPU_TYPE_F32x2 },