Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ dev
- Add `sleep` callback to `World:setCallbacks`.
- Add `linearDamping` and `angularDamping` settings to `lovr.physics.newWorld`.
- Add `lovr.headset.getHandPosition/Orientation/Pose`.
- Add getters and setters for `Material` properties.
- Add `doubleSided` property to `Material`.
- Add `Model:setMaterial`.

### Change

Expand All @@ -39,6 +42,8 @@ dev
- Change `lovr.graphics.newBuffer` to accept fields without names.
- Change `Font:getLines` wrap parameter to default to no wrap limit.
- Change `lovr.headset.isVisible` to also return whether the main session is visible, for overlays.
- Change `lovr.graphics.newMaterial` to also take a `Texture` or an `Image`.
- Change `uvShift` and `uvScale` material properties to be named `quad`.

### Fix

Expand Down
7 changes: 3 additions & 4 deletions etc/shaders/lovr.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ layout(set = 0, binding = 3) uniform sampler Sampler;
struct MaterialData {
vec4 color;
vec4 glow;
vec2 uvShift;
vec2 uvScale;
vec4 quad;
vec2 sdfRange;
float metalness;
float roughness;
Expand Down Expand Up @@ -558,8 +557,8 @@ void main() {
#endif

if (flag_uvTransform) {
UV *= Material.uvScale;
UV += Material.uvShift;
UV *= Material.quad.zw;
UV += Material.quad.xy;
}
}
#endif
Expand Down
1 change: 1 addition & 0 deletions src/api/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ extern StringEntry lovrHorizontalAlign[];
extern StringEntry lovrJointType[];
extern StringEntry lovrKeyboardKey[];
extern StringEntry lovrLayerType[];
extern StringEntry lovrMaterialTexture[];
extern StringEntry lovrMeshStorage[];
extern StringEntry lovrModelDrawMode[];
extern StringEntry lovrMotorMode[];
Expand Down
23 changes: 19 additions & 4 deletions src/api/l_data_modelData.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,20 +602,33 @@ static int l_lovrModelDataGetMaterial(lua_State* L) {
lua_rawseti(L, -2, 4);
lua_setfield(L, -2, "glow");

// Deprecated
lua_createtable(L, 2, 0);
lua_pushnumber(L, material->uvShift[0]);
lua_pushnumber(L, material->quad[0]);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, material->uvShift[1]);
lua_pushnumber(L, material->quad[1]);
lua_rawseti(L, -2, 2);
lua_setfield(L, -2, "uvShift");

// Deprecated
lua_createtable(L, 2, 0);
lua_pushnumber(L, material->uvScale[0]);
lua_pushnumber(L, material->quad[2]);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, material->uvScale[1]);
lua_pushnumber(L, material->quad[3]);
lua_rawseti(L, -2, 2);
lua_setfield(L, -2, "uvScale");

lua_createtable(L, 4, 0);
lua_pushnumber(L, material->quad[0]);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, material->quad[1]);
lua_rawseti(L, -2, 2);
lua_pushnumber(L, material->quad[2]);
lua_rawseti(L, -2, 3);
lua_pushnumber(L, material->quad[3]);
lua_rawseti(L, -2, 4);
lua_setfield(L, -2, "quad");

lua_pushnumber(L, material->metalness), lua_setfield(L, -2, "metalness");
lua_pushnumber(L, material->roughness), lua_setfield(L, -2, "roughness");
lua_pushnumber(L, material->clearcoat), lua_setfield(L, -2, "clearcoat");
Expand All @@ -633,6 +646,8 @@ static int l_lovrModelDataGetMaterial(lua_State* L) {
PUSH_IMAGE(occlusionTexture);
PUSH_IMAGE(normalTexture);

lua_pushboolean(L, material->doubleSided), lua_setfield(L, -2, "doubleSided");

return 1;
}

Expand Down
133 changes: 79 additions & 54 deletions src/api/l_graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,17 @@ StringEntry lovrHorizontalAlign[] = {
{ 0 }
};

StringEntry lovrMaterialTexture[] = {
[TEXTURE_COLOR] = ENTRY("color"),
[TEXTURE_GLOW] = ENTRY("glow"),
[TEXTURE_METALNESS] = ENTRY("metalness"),
[TEXTURE_ROUGHNESS] = ENTRY("roughness"),
[TEXTURE_CLEARCOAT] = ENTRY("clearcoat"),
[TEXTURE_OCCLUSION] = ENTRY("occlusion"),
[TEXTURE_NORMAL] = ENTRY("normal"),
{ 0 }
};

StringEntry lovrMeshStorage[] = {
[MESH_CPU] = ENTRY("cpu"),
[MESH_GPU] = ENTRY("gpu"),
Expand Down Expand Up @@ -1459,112 +1470,126 @@ static Texture* luax_opttexture(lua_State* L, int index) {
}

static int l_lovrGraphicsNewMaterial(lua_State* L) {
MaterialInfo info;
memset(&info, 0, sizeof(info));
if (lua_isuserdata(L, 1)) {
Material* material = lovrMaterialCreate(luax_opttexture(L, 1));
luax_assert(L, material);
luax_pushtype(L, Material, material);
lovrRelease(material, lovrMaterialDestroy);
return 1;
} else if (!lua_istable(L, 1)) {
return luax_typeerror(L, 1, "Image, Texture, or table");
}

luaL_checktype(L, 1, LUA_TTABLE);
Material* material = lovrMaterialCreate(NULL);
luax_assert(L, material);

lua_getfield(L, 1, "color");
luax_optcolor(L, -1, info.data.color);
if (!lua_isnil(L, -1)) {
float color[4];
luax_optcolor(L, -1, color);
lovrMaterialSetColor(material, color);
}
lua_pop(L, 1);

lua_getfield(L, 1, "glow");
if (lua_isnil(L, -1)) {
memset(info.data.glow, 0, sizeof(info.data.glow));
} else {
luax_optcolor(L, -1, info.data.glow);
if (!lua_isnil(L, -1)) {
float glow[4];
luax_optcolor(L, -1, glow);
lovrMaterialSetGlow(material, glow);
}
lua_pop(L, 1);

float quad[4] = { 0.f, 0.f, 1.f, 1.f };

// Deprecated
lua_getfield(L, 1, "uvShift");
if (lua_type(L, -1) == LUA_TNUMBER) {
float shift = lua_tonumber(L, -1);
info.data.uvShift[0] = shift;
info.data.uvShift[1] = shift;
quad[0] = shift;
quad[1] = shift;
} else if (lua_type(L, -1) == LUA_TTABLE) {
lua_rawgeti(L, -1, 1);
lua_rawgeti(L, -2, 2);
info.data.uvShift[0] = luax_optfloat(L, -2, 0.f);
info.data.uvShift[1] = luax_optfloat(L, -1, 0.f);
quad[0] = luax_optfloat(L, -2, 0.f);
quad[1] = luax_optfloat(L, -1, 0.f);
lua_pop(L, 2);
}
lua_pop(L, 1);

// Deprecated
lua_getfield(L, 1, "uvScale");
if (lua_isnil(L, -1)) {
info.data.uvScale[0] = 1.f;
info.data.uvScale[1] = 1.f;
} else if (lua_isnumber(L, -1)) {
if (lua_isnumber(L, -1)) {
float scale = lua_tonumber(L, -1);
info.data.uvScale[0] = scale;
info.data.uvScale[1] = scale;
quad[2] = scale;
quad[3] = scale;
} else if (lua_type(L, -1) == LUA_TTABLE) {
lua_rawgeti(L, -1, 1);
lua_rawgeti(L, -2, 2);
info.data.uvScale[0] = luax_optfloat(L, -2, 1.f);
info.data.uvScale[1] = luax_optfloat(L, -1, 1.f);
quad[2] = luax_optfloat(L, -2, 1.f);
quad[3] = luax_optfloat(L, -1, 1.f);
lua_pop(L, 2);
}
lua_pop(L, 1);

lua_getfield(L, 1, "quad");
if (lua_istable(L, -1)) {
lua_rawgeti(L, -1, 1);
lua_rawgeti(L, -2, 2);
lua_rawgeti(L, -3, 3);
lua_rawgeti(L, -4, 4);
quad[0] = luax_optfloat(L, -4, 0.f);
quad[1] = luax_optfloat(L, -3, 0.f);
quad[2] = luax_optfloat(L, -2, 1.f);
quad[3] = luax_optfloat(L, -1, 1.f);
lua_pop(L, 4);
}
lua_pop(L, 1);

lovrMaterialSetQuad(material, quad);

lua_getfield(L, 1, "metalness");
info.data.metalness = luax_optfloat(L, -1, 1.f);
if (!lua_isnil(L, -1)) lovrMaterialSetMetalness(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "roughness");
info.data.roughness = luax_optfloat(L, -1, 1.f);
if (!lua_isnil(L, -1)) lovrMaterialSetRoughness(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "clearcoat");
info.data.clearcoat = luax_optfloat(L, -1, 0.f);
if (!lua_isnil(L, -1)) lovrMaterialSetClearcoat(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "clearcoatRoughness");
info.data.clearcoatRoughness = luax_optfloat(L, -1, 0.f);
if (!lua_isnil(L, -1)) lovrMaterialSetClearcoatRoughness(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "occlusionStrength");
info.data.occlusionStrength = luax_optfloat(L, -1, 1.f);
if (!lua_isnil(L, -1)) lovrMaterialSetOcclusionStrength(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "normalScale");
info.data.normalScale = luax_optfloat(L, -1, 1.f);
if (!lua_isnil(L, -1)) lovrMaterialSetNormalScale(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "alphaCutoff");
info.data.alphaCutoff = luax_optfloat(L, -1, 0.f);
lua_pop(L, 1);

lua_getfield(L, 1, "texture");
info.texture = luax_opttexture(L, -1);
lua_pop(L, 1);

lua_getfield(L, 1, "glowTexture");
info.glowTexture = luax_opttexture(L, -1);
lua_pop(L, 1);

lua_getfield(L, 1, "metalnessTexture");
info.metalnessTexture = luax_opttexture(L, -1);
lua_pop(L, 1);

lua_getfield(L, 1, "roughnessTexture");
info.roughnessTexture = luax_opttexture(L, -1);
lua_pop(L, 1);

lua_getfield(L, 1, "clearcoatTexture");
info.clearcoatTexture = luax_opttexture(L, -1);
if (!lua_isnil(L, -1)) lovrMaterialSetAlphaCutoff(material, luax_tofloat(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "occlusionTexture");
info.occlusionTexture = luax_opttexture(L, -1);
lua_getfield(L, 1, "doubleSided");
lovrMaterialSetDoubleSided(material, lua_toboolean(L, -1));
lua_pop(L, 1);

lua_getfield(L, 1, "normalTexture");
info.normalTexture = luax_opttexture(L, -1);
lua_pop(L, 1);
for (uint32_t i = 0; i < MAX_MATERIAL_TEXTURES; i++) {
if (i == 0) {
lua_pushliteral(L, "texture");
} else {
lua_pushfstring(L, "%sTexture", lovrMaterialTexture[i].string);
}
lua_gettable(L, 1);
if (!lua_isnil(L, -1)) lovrMaterialSetTexture(material, i, luax_opttexture(L, -1));
lua_pop(L, 1);
}

Material* material = lovrMaterialCreate(&info);
luax_assert(L, material);
luax_pushtype(L, Material, material);
lovrRelease(material, lovrMaterialDestroy);
return 1;
Expand Down
Loading
Loading