diff --git a/packs/Angryfly.pack b/packs/Angryfly.pack index dc4b501080..366645068f 100644 Binary files a/packs/Angryfly.pack and b/packs/Angryfly.pack differ diff --git a/packs/License.txt b/packs/License.txt index eb92c692d8..0175af7d70 100644 --- a/packs/License.txt +++ b/packs/License.txt @@ -3,6 +3,6 @@ The AngryFly pack is only to be distributed as a whole, without modifications wi As the files build up to the pack are licensed under the "Royalty-Free-License" from TurboSquid. So no other redistrubution, or reverse engineering of the pack files is allowed. See: http://support.turbosquid.com/entries/31030006-Royalty-Free-License -The msgamedev pack is only to be distributed as a whole, without modifications with copies of EmptyEpsilon. +The msgamedev packs, msgamedev-1.pack and msgamedev-2.pack, are only to be distributed together as a whole, without modifications with copies of EmptyEpsilon. As the files build up to the pack are licensed under the licence from cgtrader. So no other redistrubution, or reverse engineering of the pack files is allowed. diff --git a/packs/msgamedev-1.pack b/packs/msgamedev-1.pack new file mode 100644 index 0000000000..cab8a871b1 Binary files /dev/null and b/packs/msgamedev-1.pack differ diff --git a/packs/msgamedev.pack b/packs/msgamedev-2.pack similarity index 59% rename from packs/msgamedev.pack rename to packs/msgamedev-2.pack index fe1ea1296d..e435228474 100644 Binary files a/packs/msgamedev.pack and b/packs/msgamedev-2.pack differ diff --git a/packs/pack_gen.py b/packs/pack_gen.py deleted file mode 100644 index aff5f168fb..0000000000 --- a/packs/pack_gen.py +++ /dev/null @@ -1,82 +0,0 @@ -import os -import glob -import struct - -FORMAT_VERSION = 0 - -def convertObj(filename): - f = open(filename, 'r') - vertices = [] - normals = [] - uvs = [] - faces = [] - for line in f: - line = line.strip().split() - if len(line) < 1: - continue - if line[0] == 'v': - vertices.append(map(lambda n: float(n), line[1:])) - elif line[0] == 'vn': - normals.append(map(lambda n: float(n), line[1:])) - elif line[0] == 'vt': - uvs.append(map(lambda n: float(n), line[1:])) - elif line[0] == 'f': - faces.append(map(lambda n: map(lambda m: int(m), n.split('/')), line[1:])) - f.close() - data = '' - cnt = 0 - for face in faces: - for i in xrange(2, len(face)): - for n in [0, i-1, i]: - v = vertices[face[n][0] - 1] - vt = uvs[face[n][1] - 1] - vn = normals[face[n][2] - 1] - cnt += 1 - data += struct.pack('@ffffffff', v[0], v[2], v[1], vn[0], vn[2], vn[1], vt[0], 1.0 - vt[1]) - data = struct.pack('>i', cnt) + data - return data, os.path.splitext(filename)[0] + '.model' - -def buildPack(name): - os.chdir(name) - filenames = glob.glob('*') + glob.glob('*/*') + glob.glob('*/*/*') - files = {} - for filename in filenames: - filename = filename.encode('ascii') - filename = filename.replace('\\', '/') - if os.path.isfile(filename): - ext = os.path.splitext(filename)[1] - if ext == '.obj': - data, filename = convertObj(filename) - elif ext == '.rar' or ext == '.zip': - continue - else: - f = open(filename, "rb") - data = f.read() - f.close() - files[filename] = data - os.chdir('..') - f = open(name + '.pack', 'wb') - flog = open(name + '.packlist', 'wb') - f.write(struct.pack('>i', FORMAT_VERSION)) - f.write(struct.pack('>i', len(files))) - offset = 8 - for filename, data in files.items(): - offset += 1 + len(filename) + 8 - for filename, data in files.items(): - f.write(struct.pack('>B', len(filename))) - f.write(filename) - flog.write(filename + '\n') - f.write(struct.pack('>ii', offset, len(data))) - print offset, filename - offset += len(data) - for filename, data in files.items(): - f.write(data) - f.close() - flog.close() - -def main(): - for dir in os.listdir("."): - if os.path.isdir(dir): - buildPack(dir) - -main() diff --git a/resources/shaders/objectShader.shader b/resources/shaders/objectShader.shader index 0269340c93..331fae6a39 100644 --- a/resources/shaders/objectShader.shader +++ b/resources/shaders/objectShader.shader @@ -10,19 +10,20 @@ uniform mat4 u_projection; attribute vec3 a_position; attribute vec3 a_normal; attribute vec2 a_texcoords; -attribute vec3 a_tangent; +// xyz: tangent. w: bitangent handedness. +attribute vec4 a_tangent; // Per-vertex outputs varying vec3 v_normal; varying vec2 v_texcoords; -varying vec3 v_tangent; +varying vec4 v_tangent; void main() { v_normal = normalize((u_model * vec4(a_normal, 0.)).xyz); - v_tangent = normalize((u_model * vec4(a_tangent, 0.)).xyz); + v_tangent = vec4(normalize((u_model * vec4(a_tangent.xyz, 0.)).xyz), a_tangent.w); vec4 modelview_position = u_view * u_model * vec4(a_position, 1.); - + v_texcoords = a_texcoords; gl_Position = u_projection * modelview_position; } @@ -48,18 +49,18 @@ uniform sampler2D u_normalMap; // Per-fragment inputs varying vec3 v_normal; varying vec2 v_texcoords; -varying vec3 v_tangent; +varying vec4 v_tangent; void main() { vec3 n = v_normal; #ifdef NORMAL - vec3 bitangent = cross(v_tangent, n); - mat3 TBN = mat3(normalize(v_tangent), normalize(bitangent), normalize(n)); - n = normalize(TBN * (texture2D(u_normalMap, v_texcoords.st).rgb * 2.0 - 1.0)); + vec3 bitangent = cross(n, v_tangent.xyz) * v_tangent.w; + mat3 TBN = mat3(normalize(v_tangent.xyz), normalize(bitangent), normalize(n)); + n = normalize(TBN * (texture2D(u_normalMap, v_texcoords.st).rgb * 2.0 - 1.0)); #endif float intensity = max(0.1, dot(u_ambientLightDirection, n)); - + vec4 base = texture2D(u_baseMap, v_texcoords.st); #ifdef ILLUMINATION vec4 illumination = texture2D(u_illuminationMap, v_texcoords.st); diff --git a/scripts/api/modelData.lua b/scripts/api/modelData.lua index dcfcbda627..404750207f 100644 --- a/scripts/api/modelData.lua +++ b/scripts/api/modelData.lua @@ -81,8 +81,8 @@ end --- Optional; if omitted, no normal map is applied. --- Valid values include PNG- or JPG-format images relative to the resources/ directory, or paths defined within a resource pack loaded from the packs/ directory. --- Example: ---- model:setNormalMap("space_station_1/space_station_1_normal.jpg") -- loads this texture from a resource pack ---- model:setNormalMap("mesh/ship/Ender Battlecruiser_normal.png") -- loads this texture from the resources/ directory +--- model:setNormalMap("space_station_1/space_station_1_normal.png") -- loads this texture from a resource pack +--- model:setNormalMap("mesh/ship/my_ship_normal.png") -- loads this texture from the resources/ directory function ModelData:setNormalMap(texture) if self.mesh_render == nil then self.mesh_render = {} end self.mesh_render.normal_texture=texture diff --git a/scripts/model_data.lua b/scripts/model_data.lua index 4cbc79f878..6b400e4a37 100644 --- a/scripts/model_data.lua +++ b/scripts/model_data.lua @@ -7,6 +7,7 @@ model:setMesh("space_station_4/space_station_4.model") model:setTexture("space_station_4/space_station_4_color.jpg") model:setSpecular("space_station_4/space_station_4_specular.jpg") model:setIllumination("space_station_4/space_station_4_illumination.jpg") +model:setNormalMap("space_station_4/space_station_4_normal.png") model:setRenderOffset(0, 0, 5) model:setScale(10) model:setRadius(300) @@ -18,6 +19,7 @@ model:setMesh("space_station_3/space_station_3.model") model:setTexture("space_station_3/space_station_3_color.jpg") model:setSpecular("space_station_3/space_station_3_specular.jpg") model:setIllumination("space_station_3/space_station_3_illumination.jpg") +model:setNormalMap("space_station_3/space_station_3_normal.png") model:setRenderOffset(10, 0, 5) model:setScale(20) model:setRadius(1000) @@ -29,6 +31,7 @@ model:setMesh("space_station_2/space_station_2.model") model:setTexture("space_station_2/space_station_2_color.jpg") model:setSpecular("space_station_2/space_station_2_specular.jpg") model:setIllumination("space_station_2/space_station_2_illumination.jpg") +model:setNormalMap("space_station_2/space_station_2_normal.png") model:setRenderOffset(10, 0, 5) model:setScale(20) model:setRadius(1300) @@ -40,6 +43,7 @@ model:setMesh("space_station_1/space_station_1.model") model:setTexture("space_station_1/space_station_1_color.jpg") model:setSpecular("space_station_1/space_station_1_specular.jpg") model:setIllumination("space_station_1/space_station_1_illumination.jpg") +model:setNormalMap("space_station_1/space_station_1_normal.png") model:setRenderOffset(0, 0, 5) model:setScale(20) model:setRadius(1500) @@ -51,6 +55,7 @@ model:setMesh("small_fighter_1.model") model:setTexture("small_fighter_1_color.jpg") model:setSpecular("small_fighter_1_specular.jpg") model:setIllumination("small_fighter_1_illumination.jpg") +model:setNormalMap("small_fighter_1_normal.png") model:setScale(3) model:setRadius(40) @@ -79,6 +84,7 @@ model:setMesh("space_frigate_6.model") model:setTexture("space_frigate_6_color.png") model:setSpecular("space_frigate_6_specular.png") model:setIllumination("space_frigate_6_illumination.png") +model:setNormalMap("space_frigate_6_normal.png") model:setScale(6) model:setRadius(100) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -109,6 +115,7 @@ model:setMesh("dark_fighter_6.model") model:setTexture("dark_fighter_6_color.png") model:setSpecular("dark_fighter_6_specular.png") model:setIllumination("dark_fighter_6_illumination.png") +model:setNormalMap("dark_fighter_6_normal.png") model:setScale(3) model:setRadius(140) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -124,6 +131,7 @@ model:setMesh("battleship_destroyer_1_upgraded/battleship_destroyer_1_upgraded.m model:setTexture("battleship_destroyer_1_upgraded/battleship_destroyer_1_upgraded_color.jpg") model:setSpecular("battleship_destroyer_1_upgraded/battleship_destroyer_1_upgraded_specular.jpg") model:setIllumination("battleship_destroyer_1_upgraded/battleship_destroyer_1_upgraded_illumination.jpg") +model:setNormalMap("battleship_destroyer_1_upgraded/battleship_destroyer_1_upgraded_normal.png") model:setScale(4) model:setRadius(200) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -145,6 +153,7 @@ model:setMesh("battleship_destroyer_2_upgraded/battleship_destroyer_2_upgraded.m model:setTexture("battleship_destroyer_2_upgraded/battleship_destroyer_2_upgraded_color.jpg") model:setSpecular("battleship_destroyer_2_upgraded/battleship_destroyer_2_upgraded_specular.jpg") model:setIllumination("battleship_destroyer_2_upgraded/battleship_destroyer_2_upgraded_illumination.jpg") +model:setNormalMap("battleship_destroyer_2_upgraded/battleship_destroyer_2_upgraded_normal.png") model:setScale(4) model:setRadius(200) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -164,6 +173,7 @@ model:setMesh("battleship_destroyer_3_upgraded/battleship_destroyer_3_upgraded.m model:setTexture("battleship_destroyer_3_upgraded/battleship_destroyer_3_upgraded_color.jpg") model:setSpecular("battleship_destroyer_3_upgraded/battleship_destroyer_3_upgraded_specular.jpg") model:setIllumination("battleship_destroyer_3_upgraded/battleship_destroyer_3_upgraded_illumination.jpg") +model:setNormalMap("battleship_destroyer_3_upgraded/battleship_destroyer_3_upgraded_normal.png") model:setScale(4) model:setRadius(200) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -182,6 +192,7 @@ model:setMesh("battleship_destroyer_4_upgraded/battleship_destroyer_4_upgraded.m model:setTexture("battleship_destroyer_4_upgraded/battleship_destroyer_4_upgraded_color.jpg") model:setSpecular("battleship_destroyer_4_upgraded/battleship_destroyer_4_upgraded_specular.jpg") model:setIllumination("battleship_destroyer_4_upgraded/battleship_destroyer_4_upgraded_illumination.jpg") +model:setNormalMap("battleship_destroyer_4_upgraded/battleship_destroyer_4_upgraded_normal.png") model:setScale(4) model:setRadius(200) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -201,6 +212,7 @@ model:setMesh("battleship_destroyer_5_upgraded/battleship_destroyer_5_upgraded.m model:setTexture("battleship_destroyer_5_upgraded/battleship_destroyer_5_upgraded_color.jpg") model:setSpecular("battleship_destroyer_5_upgraded/battleship_destroyer_5_upgraded_specular.jpg") model:setIllumination("battleship_destroyer_5_upgraded/battleship_destroyer_5_upgraded_illumination.jpg") +model:setNormalMap("battleship_destroyer_5_upgraded/battleship_destroyer_5_upgraded_normal.png") model:setScale(4) model:setRadius(200) @@ -248,6 +260,7 @@ model:setMesh("sci_fi_alien_ship_1/sci_fi_alien_ship_1.model") model:setTexture("sci_fi_alien_ship_1/sci_fi_alien_ship_1_color.jpg") model:setSpecular("sci_fi_alien_ship_1/sci_fi_alien_ship_1_specular.jpg") model:setIllumination("sci_fi_alien_ship_1/sci_fi_alien_ship_1_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_1/sci_fi_alien_ship_1_normal.png") model:setScale(3) model:setRadius(180) @@ -257,6 +270,7 @@ model:setMesh("sci_fi_alien_ship_2/sci_fi_alien_ship_2.model") model:setTexture("sci_fi_alien_ship_2/sci_fi_alien_ship_2_color.jpg") model:setSpecular("sci_fi_alien_ship_2/sci_fi_alien_ship_2_specular.jpg") model:setIllumination("sci_fi_alien_ship_2/sci_fi_alien_ship_2_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_2/sci_fi_alien_ship_2_normal.png") model:setScale(3) model:setRadius(180) @@ -266,6 +280,7 @@ model:setMesh("sci_fi_alien_ship_3/sci_fi_alien_ship_3.model") model:setTexture("sci_fi_alien_ship_3/sci_fi_alien_ship_3_color.jpg") model:setSpecular("sci_fi_alien_ship_3/sci_fi_alien_ship_3_specular.jpg") model:setIllumination("sci_fi_alien_ship_3/sci_fi_alien_ship_3_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_3/sci_fi_alien_ship_3_normal.png") model:setScale(3) model:setRadius(150) @@ -275,6 +290,7 @@ model:setMesh("sci_fi_alien_ship_4/sci_fi_alien_ship_4.model") model:setTexture("sci_fi_alien_ship_4/sci_fi_alien_ship_4_color.jpg") model:setSpecular("sci_fi_alien_ship_4/sci_fi_alien_ship_4_specular.jpg") model:setIllumination("sci_fi_alien_ship_4/sci_fi_alien_ship_4_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_4/sci_fi_alien_ship_4_normal.png") model:setScale(3) model:setRadius(150) @@ -284,6 +300,7 @@ model:setMesh("sci_fi_alien_ship_5/sci_fi_alien_ship_5.model") model:setTexture("sci_fi_alien_ship_5/sci_fi_alien_ship_5_color.jpg") model:setSpecular("sci_fi_alien_ship_5/sci_fi_alien_ship_5_specular.jpg") model:setIllumination("sci_fi_alien_ship_5/sci_fi_alien_ship_5_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_5/sci_fi_alien_ship_5_normal.png") model:setScale(3) model:setRadius(150) @@ -293,6 +310,7 @@ model:setMesh("sci_fi_alien_ship_6/sci_fi_alien_ship_6.model") model:setTexture("sci_fi_alien_ship_6/sci_fi_alien_ship_6_color.jpg") model:setSpecular("sci_fi_alien_ship_6/sci_fi_alien_ship_6_specular.jpg") model:setIllumination("sci_fi_alien_ship_6/sci_fi_alien_ship_6_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_6/sci_fi_alien_ship_6_normal.png") model:setScale(3) model:setRadius(150) @@ -302,6 +320,7 @@ model:setMesh("sci_fi_alien_ship_7/sci_fi_alien_ship_7.model") model:setTexture("sci_fi_alien_ship_7/sci_fi_alien_ship_7_color.jpg") model:setSpecular("sci_fi_alien_ship_7/sci_fi_alien_ship_7_specular.jpg") model:setIllumination("sci_fi_alien_ship_7/sci_fi_alien_ship_7_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_7/sci_fi_alien_ship_7_normal.png") model:setScale(6) model:setRadius(330) @@ -311,6 +330,7 @@ model:setMesh("sci_fi_alien_ship_8/sci_fi_alien_ship_8.model") model:setTexture("sci_fi_alien_ship_8/sci_fi_alien_ship_8_color.jpg") model:setSpecular("sci_fi_alien_ship_8/sci_fi_alien_ship_8_specular.jpg") model:setIllumination("sci_fi_alien_ship_8/sci_fi_alien_ship_8_illumination.jpg") +model:setNormalMap("sci_fi_alien_ship_8/sci_fi_alien_ship_8_normal.png") model:setScale(6) model:setRadius(350) @@ -336,6 +356,7 @@ model:setMesh("small_frigate_1/small_frigate_1.model") model:setTexture("small_frigate_1/small_frigate_1_color.png") model:setSpecular("small_frigate_1/small_frigate_1_specular.png") model:setIllumination("small_frigate_1/small_frigate_1_illumination.png") +model:setNormalMap("small_frigate_1/small_frigate_1_normal.png") model:setScale(1) model:setRadius(100) @@ -350,6 +371,7 @@ model:setMesh("small_frigate_2/small_frigate_2.model") model:setTexture("small_frigate_2/small_frigate_2_color.png") model:setSpecular("small_frigate_2/small_frigate_2_specular.png") model:setIllumination("small_frigate_2/small_frigate_2_illumination.png") +model:setNormalMap("small_frigate_2/small_frigate_2_normal.png") model:setScale(1) model:setRadius(80) @@ -362,6 +384,7 @@ model:setMesh("small_frigate_3/small_frigate_3.model") model:setTexture("small_frigate_3/small_frigate_3_color.png") model:setSpecular("small_frigate_3/small_frigate_3_specular.png") model:setIllumination("small_frigate_3/small_frigate_3_illumination.png") +model:setNormalMap("small_frigate_3/small_frigate_3_normal.png") model:setScale(0.8) model:setRadius(80) @@ -376,6 +399,7 @@ model:setMesh("small_frigate_4/small_frigate_4.model") model:setTexture("small_frigate_4/small_frigate_4_color.png") model:setSpecular("small_frigate_4/small_frigate_4_specular.png") model:setIllumination("small_frigate_4/small_frigate_4_illumination.png") +model:setNormalMap("small_frigate_4/small_frigate_4_normal.png") model:setScale(1) model:setRadius(100) @@ -389,6 +413,7 @@ model:setMesh("small_frigate_5/small_frigate_5.model") model:setTexture("small_frigate_5/small_frigate_5_color.png") model:setSpecular("small_frigate_5/small_frigate_5_specular.png") model:setIllumination("small_frigate_5/small_frigate_5_illumination.png") +model:setNormalMap("small_frigate_5/small_frigate_5_normal.png") model:setScale(1) model:setRadius(80) @@ -406,6 +431,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("AdlerLongRangeScout/AlbedoAO/AdlerLongRangeScout"..color.."AlbedoAO.png") model:setSpecular("AdlerLongRangeScout/AdlerLongRangeScoutPBRSpecular.png") model:setIllumination("AdlerLongRangeScout/AdlerLongRangeScoutIllumination.png") + model:setNormalMap("AdlerLongRangeScout/AdlerLongRangeScoutNormal.png") model:setScale(20) model:setRadius(30) -- Visual positions of the beams/missiletubes (blender: -X, Y, Z) @@ -424,6 +450,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("AtlasHeavyFighter/AlbedoAO/AtlasHeavyFighter"..color.."AlbedoAO.png") model:setSpecular("AtlasHeavyFighter/AtlasHeavyFighterPBRSpecular.png") model:setIllumination("AtlasHeavyFighter/AtlasHeavyFighterIllumination.png") + model:setNormalMap("AtlasHeavyFighter/AtlasHeavyFighterNormal.png") model:setScale(50) model:setRadius(80) @@ -444,6 +471,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("LindwurmFighter/AlbedoAO/LindwurmFighter"..color.."AlbedoAO.png") model:setSpecular("LindwurmFighter/LindwurmFighterPBRSpecular.png") model:setIllumination("LindwurmFighter/LindwurmFighterIllumination.png") + model:setNormalMap("LindwurmFighter/LindwurmFighterNormal.png") model:setScale(20) model:setRadius(30) model:addTubePosition(1.4, 0, 0.06) @@ -458,6 +486,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("WespeScout/AlbedoAO/WespeScout"..color.."AlbedoAO.png") model:setSpecular("WespeScout/WespeScoutPBRSpecular.png") model:setIllumination("WespeScout/WespeScoutIllumination.png") + model:setNormalMap("WespeScout/WespeScoutNormal.png") model:setScale(20) model:setRadius(30) model:addBeamPosition(1.15, 0.13, -0.03) @@ -471,6 +500,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("HeavyCorvette/AlbedoAO/HeavyCorvette"..color.."AlbedoAO.png") model:setSpecular("HeavyCorvette/HeavyCorvettePBRSpecular.png") model:setIllumination("HeavyCorvette/HeavyCorvetteIllumination.png") + model:setNormalMap("HeavyCorvette/HeavyCorvetteNormal.png") model:setScale(50) model:setRadius(80) @@ -484,6 +514,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("LaserCorvette/AlbedoAO/LaserCorvette"..color.."AlbedoAO.png") model:setSpecular("LaserCorvette/LaserCorvettePBRSpecular.png") model:setIllumination("LaserCorvette/LaserCorvetteIllumination.png") + model:setNormalMap("LaserCorvette/LaserCorvetteNormal.png") model:setScale(50) model:setRadius(80) @@ -496,6 +527,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("LightCorvette/AlbedoAO/LightCorvette"..color.."AlbedoAO.png") model:setSpecular("LightCorvette/LightCorvettePBRSpecular.png") model:setIllumination("LightCorvette/LightCorvetteIllumination.png") + model:setNormalMap("LightCorvette/LightCorvetteNormal.png") model:setScale(50) model:setRadius(80) @@ -509,6 +541,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("MineLayerCorvette/AlbedoAO/MineLayerCorvette"..color.."AlbedoAO.png") model:setSpecular("MineLayerCorvette/MineLayerCorvettePBRSpecular.png") model:setIllumination("MineLayerCorvette/MineLayerCorvetteIllumination.png") + model:setNormalMap("MineLayerCorvette/MineLayerCorvetteNormal.png") model:setScale(50) model:setRadius(80) @@ -521,6 +554,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("MissileCorvette/AlbedoAO/MissileCorvette"..color.."AlbedoAO.png") model:setSpecular("MissileCorvette/MissileCorvettePBRSpecular.png") model:setIllumination("MissileCorvette/MissileCorvetteIllumination.png") + model:setNormalMap("MissileCorvette/MissileCorvetteNormal.png") model:setScale(50) model:setRadius(80) @@ -534,6 +568,7 @@ for idx, color in ipairs({"Blue", "Green", "Grey", "Red", "White", "Yellow"}) do model:setTexture("MultiGunCorvette/AlbedoAO/MultiGunCorvette"..color.."AlbedoAO.png") model:setSpecular("MultiGunCorvette/MultiGunCorvettePBRSpecular.png") model:setIllumination("MultiGunCorvette/MultiGunCorvetteIllumination.png") + model:setNormalMap("MultiGunCorvette/MultiGunCorvetteNormal.png") model:setScale(50) model:setRadius(80) @@ -547,6 +582,7 @@ model:setName("SensorBuoyMKI") model:setMesh("SensorBuoy/SensorBuoyMKI.model") model:setTexture("SensorBuoy/SensorBuoyAlbedoAO.png") model:setSpecular("SensorBuoy/SensorBuoyPBRSpecular.png") +model:setNormalMap("SensorBuoy/SensorBuoyNormal.png") model:setScale(300) model:setRadius(15) @@ -555,6 +591,7 @@ model:setName("SensorBuoyMKII") model:setMesh("SensorBuoy/SensorBuoyMKII.model") model:setTexture("SensorBuoy/SensorBuoyAlbedoAO.png") model:setSpecular("SensorBuoy/SensorBuoyPBRSpecular.png") +model:setNormalMap("SensorBuoy/SensorBuoyNormal.png") model:setScale(300) model:setRadius(15) @@ -563,6 +600,7 @@ model:setName("SensorBuoyMKIII") model:setMesh("SensorBuoy/SensorBuoyMKIII.model") model:setTexture("SensorBuoy/SensorBuoyAlbedoAO.png") model:setSpecular("SensorBuoy/SensorBuoyPBRSpecular.png") +model:setNormalMap("SensorBuoy/SensorBuoyNormal.png") model:setScale(300) model:setRadius(15) @@ -585,6 +623,7 @@ for type=1,5 do model:setTexture("transport_space_ship_" .. type .. "/transport_space_ship_" .. type .. "_color.png") model:setSpecular("transport_space_ship_" .. type .. "/transport_space_ship_" .. type .. "_specular.png") model:setIllumination("transport_space_ship_" .. type .. "/transport_space_ship_" .. type .. "_illumination.png") + model:setNormalMap("transport_space_ship_" .. type .. "/transport_space_ship_" .. type .. "_normal.png") end end diff --git a/src/mesh.cpp b/src/mesh.cpp index 67f84a7b6d..cd6b8a42b5 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -94,7 +95,7 @@ void Mesh::render(int32_t position_attrib, int32_t texcoords_attrib, int32_t nor glVertexAttribPointer(texcoords_attrib, 2, GL_FLOAT, GL_FALSE, sizeof(MeshVertex), (void*)offsetof(MeshVertex, uv)); if (tangent_attrib != -1) - glVertexAttribPointer(tangent_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(MeshVertex), (void*)offsetof(MeshVertex, tangent)); + glVertexAttribPointer(tangent_attrib, 4, GL_FLOAT, GL_FALSE, sizeof(MeshVertex), (void*)offsetof(MeshVertex, tangent)); if (!indices.empty()) { @@ -341,17 +342,24 @@ Mesh* Mesh::getMesh(const string& filename) glm::vec2 deltaUV1 = uv1 - uv0; glm::vec2 deltaUV2 = uv2 - uv0; - float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); + auto normal = glm::vec3(mesh_vertices[idx].normal[0], mesh_vertices[idx].normal[1], mesh_vertices[idx].normal[2]); - auto tangent = glm::vec3( - f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x), - f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y), - f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z)); + // No 1/determinant: the shader normalizes the basis, so only the sign survives. + float determinant_sign = (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y) < 0.0f ? -1.0f : 1.0f; + auto tangent = determinant_sign * (deltaUV2.y * edge1 - deltaUV1.y * edge2); + auto bitangent = determinant_sign * (deltaUV1.x * edge2 - deltaUV2.x * edge1); + + // Mirrored UV islands are left-handed. + float handedness = glm::dot(glm::cross(normal, tangent), bitangent) < 0.0f ? -1.0f : 1.0f; + + if (glm::length2(tangent) <= 0.0f) + tangent = glm::cross(normal, std::abs(normal.z) < 0.9f ? glm::vec3(0.0f, 0.0f, 1.0f) : glm::vec3(1.0f, 0.0f, 0.0f)); for(int n=0; n<3; n++) { mesh_vertices[idx+n].tangent[0] = tangent.x; mesh_vertices[idx+n].tangent[1] = tangent.y; mesh_vertices[idx+n].tangent[2] = tangent.z; + mesh_vertices[idx+n].tangent[3] = handedness; } } diff --git a/src/mesh.h b/src/mesh.h index ac754d55cd..f5ef0fa7b9 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -12,7 +12,8 @@ struct MeshVertex float position[3]; float normal[3]; float uv[2]; - float tangent[3]; + // xyz: tangent. w: bitangent handedness, +1 or -1. + float tangent[4]; }; class Mesh : sp::NonCopyable diff --git a/src/multiplayer/rendering.cpp b/src/multiplayer/rendering.cpp index eb223e6878..af6f444660 100644 --- a/src/multiplayer/rendering.cpp +++ b/src/multiplayer/rendering.cpp @@ -13,6 +13,7 @@ BASIC_REPLICATION_IMPL(MeshRenderComponentReplication, MeshRenderComponent) BASIC_REPLICATION_FIELD(texture.name); BASIC_REPLICATION_FIELD(specular_texture.name); BASIC_REPLICATION_FIELD(illumination_texture.name); + BASIC_REPLICATION_FIELD(normal_texture.name); BASIC_REPLICATION_FIELD(mesh_offset); BASIC_REPLICATION_FIELD(scale); } diff --git a/src/screenComponents/rotatingModelView.cpp b/src/screenComponents/rotatingModelView.cpp index 4e3ed6163e..aba067d54e 100644 --- a/src/screenComponents/rotatingModelView.cpp +++ b/src/screenComponents/rotatingModelView.cpp @@ -21,6 +21,7 @@ #include "gui/gui2_panel.h" #include "gui/gui2_slider.h" #include "gui/gui2_label.h" +#include "gui/gui2_togglebutton.h" #endif GuiRotatingModelView::GuiRotatingModelView(GuiContainer* owner, string id, sp::ecs::Entity& entity) @@ -353,8 +354,14 @@ GuiRotatingModelDebugView::GuiRotatingModelDebugView(GuiContainer* owner, string ->setPosition(0.f, 0.f, sp::Alignment::BottomLeft) ->setSize(GuiElement::GuiSizeMax, panel_h); - // First column is left empty for the normal map toggle, which stays out of - // the UI until the resource packs ship normal maps. + // Toggles the normal map off so its contribution can be judged against the + // flat-shaded model. State is shown by the toggle style, not the text. + (new GuiToggleButton(panel, id + "_NM_BTN", "Normal map", + [this](bool active) { setDebugShowNormalMap(active); })) + ->setValue(true) + ->setPosition(8.f, label_h + 4.f, sp::Alignment::TopLeft) + ->setSize(ctrl_w, ctrl_h); + constexpr float az_x = ctrl_w + 24.f; (new GuiLabel(panel, id + "_AZ_LABEL", "Light azimuth", label_h)) ->setPosition(az_x, 4.f, sp::Alignment::TopLeft) diff --git a/src/systems/rendering.cpp b/src/systems/rendering.cpp index 499afd1192..0517532979 100644 --- a/src/systems/rendering.cpp +++ b/src/systems/rendering.cpp @@ -113,8 +113,8 @@ void drawMesh(MeshRenderComponent& mrc, ShaderRegistry::ScopedShader& shader) mrc.getMesh()->render(positions.get(), texcoords.get(), normals.get(), tangent.get()); - // wut iz? - if (mrc.getSpecularTexture() || mrc.getIlluminationTexture()) + // Restore the active unit so the next mesh binds its base texture to unit 0. + if (mrc.getSpecularTexture() || mrc.getIlluminationTexture() || mrc.getNormalTexture()) glActiveTexture(GL_TEXTURE0); }