Compare commits
No commits in common. "4a80ef547b2990a8d37d112c66b6646ae669a4f1" and "cbf309aaa410a9c55891522acf7c4f37ccfde31b" have entirely different histories.
4a80ef547b
...
cbf309aaa4
|
@ -149,44 +149,56 @@ public class WorldRep : IChunk
|
|||
}
|
||||
}
|
||||
|
||||
public readonly byte[] AsBytesRgba(int layer)
|
||||
public readonly byte[] AsBytesRgba()
|
||||
{
|
||||
if (layer >= Layers)
|
||||
var length = Width * Height * 4;
|
||||
var bytes = new byte[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(layer));
|
||||
bytes[i] = 0;
|
||||
}
|
||||
|
||||
var length = Width * Height * 4;
|
||||
var layerOffset = layer * Bpp * Width * Height;
|
||||
var bytes = new byte[length];
|
||||
for (var y = 0; y < Height; y++)
|
||||
// TODO: might be faster to do these fors in the switch?
|
||||
for (var z = 0; z < Layers; z++)
|
||||
{
|
||||
for (var x = 0; x < Width; x++)
|
||||
for (var y = 0; y < Height; y++)
|
||||
{
|
||||
var bIdx = x * 4 + y * 4 * Width;
|
||||
var pIdx = x * Bpp + y * Bpp * Width + layerOffset;
|
||||
switch (Bpp)
|
||||
for (var x = 0; x < Width; x++)
|
||||
{
|
||||
case 1:
|
||||
var raw1 = Pixels[pIdx];
|
||||
bytes[bIdx] = raw1;
|
||||
bytes[bIdx + 1] = raw1;
|
||||
bytes[bIdx + 2] = raw1;
|
||||
bytes[bIdx + 3] = 255;
|
||||
break;
|
||||
case 2:
|
||||
var raw2 = Pixels[pIdx] + (Pixels[pIdx + 1] << 8);
|
||||
bytes[bIdx] = (byte)(255 * (raw2 & 31) / 31.0f);
|
||||
bytes[bIdx + 1] = (byte)(255 * ((raw2 >> 5) & 31) / 31.0f);
|
||||
bytes[bIdx + 2] = (byte)(255 * ((raw2 >> 10) & 31) / 31.0f);
|
||||
bytes[bIdx + 3] = 255;
|
||||
break;
|
||||
case 4:
|
||||
bytes[bIdx] = Pixels[pIdx + 2];
|
||||
bytes[bIdx + 1] = Pixels[pIdx + 1];
|
||||
bytes[bIdx + 2] = Pixels[pIdx];
|
||||
bytes[bIdx + 3] = Pixels[pIdx + 3];
|
||||
break;
|
||||
var pIdx = 0 + x * Bpp + y * Bpp * Width + z * Bpp * Width * Height;
|
||||
var r = 0;
|
||||
var g = 0;
|
||||
var b = 0;
|
||||
var a = 0;
|
||||
switch (Bpp)
|
||||
{
|
||||
case 1:
|
||||
var raw1 = Pixels[pIdx];
|
||||
r = raw1;
|
||||
g = raw1;
|
||||
b = raw1;
|
||||
a = 255;
|
||||
break;
|
||||
case 2:
|
||||
var raw2 = Pixels[pIdx] + (Pixels[pIdx + 1] << 8);
|
||||
r = (int)(255 * (raw2 & 31) / 31.0f);
|
||||
g = (int)(255 * ((raw2 >> 5) & 31) / 31.0f);
|
||||
b = (int)(255 * ((raw2 >> 10) & 31) / 31.0f);
|
||||
a = 255;
|
||||
break;
|
||||
case 4:
|
||||
r = Pixels[pIdx + 2];
|
||||
g = Pixels[pIdx + 1];
|
||||
b = Pixels[pIdx];
|
||||
a = Pixels[pIdx + 3];
|
||||
break;
|
||||
}
|
||||
|
||||
var bIdx = x * 4 + y * 4 * Width;
|
||||
bytes[bIdx] = (byte)Math.Min(255, bytes[bIdx] + r);
|
||||
bytes[bIdx + 1] = (byte)Math.Min(255, bytes[bIdx + 1] + g);
|
||||
bytes[bIdx + 2] = (byte)Math.Min(255, bytes[bIdx + 2] + b);
|
||||
bytes[bIdx + 3] = (byte)Math.Min(255, bytes[bIdx + 3] + a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,16 +45,12 @@ public partial class Mission : Node3D
|
|||
DbFile _file;
|
||||
TextureLoader _textureLoader;
|
||||
ModelLoader _modelLoader;
|
||||
List<ShaderMaterial> _materials;
|
||||
Vector2I _lmLayerMask;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
var extractPath = ProjectSettings.GlobalizePath($"user://extracted/tmp");
|
||||
_installPaths = new ResourcePathManager(extractPath);
|
||||
_modelLoader = new ModelLoader(_installPaths);
|
||||
_materials = new List<ShaderMaterial>();
|
||||
_lmLayerMask = new Vector2I(~0, ~0);
|
||||
var missionSelector = GetNode<Control>("%MissionSelector") as MissionSelector;
|
||||
missionSelector.pathManager = _installPaths;
|
||||
missionSelector.MissionSelected += (string campaign, string mission) =>
|
||||
|
@ -88,10 +84,6 @@ public partial class Mission : Node3D
|
|||
{
|
||||
Build = true;
|
||||
}
|
||||
if (keyEvent.Keycode == Key.O)
|
||||
{
|
||||
ToggleLightmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,8 +93,6 @@ public partial class Mission : Node3D
|
|||
{
|
||||
node.QueueFree();
|
||||
}
|
||||
|
||||
_materials.Clear();
|
||||
}
|
||||
|
||||
public void RebuildMap()
|
||||
|
@ -121,60 +111,6 @@ public partial class Mission : Node3D
|
|||
}
|
||||
}
|
||||
|
||||
public void ToggleLightmap()
|
||||
{
|
||||
if (_lmLayerMask == Vector2I.Zero)
|
||||
{
|
||||
_lmLayerMask = new Vector2I(~0, ~0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lmLayerMask = Vector2I.Zero;
|
||||
}
|
||||
|
||||
foreach (var mat in _materials)
|
||||
{
|
||||
mat.SetShaderParameter("lightmap_bitmask", _lmLayerMask);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleLmLayer(uint layer)
|
||||
{
|
||||
if (layer >= 64)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(layer));
|
||||
}
|
||||
|
||||
static int ToggleBit(int bitIdx, int val)
|
||||
{
|
||||
var mask = 1 << bitIdx;
|
||||
var isEnabled = (val & mask) != 0;
|
||||
if (isEnabled)
|
||||
{
|
||||
val &= ~mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
val |= mask;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
if (layer < 32)
|
||||
{
|
||||
_lmLayerMask.X = ToggleBit((int)layer, _lmLayerMask.X);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lmLayerMask.Y = ToggleBit((int)layer - 32, _lmLayerMask.Y);
|
||||
}
|
||||
|
||||
foreach (var mat in _materials)
|
||||
{
|
||||
mat.SetShaderParameter("lightmap_bitmask", _lmLayerMask);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make this less of a mess
|
||||
private ObjectHierarchy BuildHierarchy()
|
||||
{
|
||||
|
@ -303,12 +239,10 @@ public partial class Mission : Node3D
|
|||
}
|
||||
|
||||
var albedoTexture = _textureLoader.Get(textureId);
|
||||
var mat = BuildMaterial(albedoTexture, lightmapTexture, lmHdr, _lmLayerMask);
|
||||
_materials.Add(mat);
|
||||
|
||||
var mesh = new ArrayMesh();
|
||||
mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, surface.BuildSurfaceArray());
|
||||
mesh.SurfaceSetMaterial(0, mat);
|
||||
mesh.SurfaceSetMaterial(0, BuildMaterial(albedoTexture, lightmapTexture, lmHdr));
|
||||
|
||||
var meshInstance = new MeshInstance3D { Mesh = mesh };
|
||||
AddChild(meshInstance);
|
||||
|
@ -348,11 +282,7 @@ public partial class Mission : Node3D
|
|||
return new LightmapRectData(cellIdx, polyIdx, textureId, start, end);
|
||||
}
|
||||
|
||||
private static Texture2DArray BuildLightmapTexture(
|
||||
WorldRep.Cell[] cells,
|
||||
PackingRectangle[] packingRects,
|
||||
Dictionary<int, LightmapRectData> rectDataMap,
|
||||
Dictionary<int, MeshSurfaceData> surfaceDataMap)
|
||||
private static Texture BuildLightmapTexture(WorldRep.Cell[] cells, PackingRectangle[] packingRects, Dictionary<int, LightmapRectData> rectDataMap, Dictionary<int, MeshSurfaceData> surfaceDataMap)
|
||||
{
|
||||
var bounds = Timing.TimeStage("RectPack", () =>
|
||||
{
|
||||
|
@ -360,16 +290,7 @@ public partial class Mission : Node3D
|
|||
return bounds;
|
||||
});
|
||||
GD.Print($"Creating lightmap with bounds: ({bounds.Width}, {bounds.Height})");
|
||||
|
||||
var lightmapFormat = Image.Format.Rgba8;
|
||||
var lmLayerCount = 33;
|
||||
var lmImages = new Godot.Collections.Array<Image>();
|
||||
lmImages.Resize(lmLayerCount);
|
||||
for (var i = 0; i < lmLayerCount; i++)
|
||||
{
|
||||
lmImages[i] = Image.CreateEmpty((int)bounds.Width, (int)bounds.Height, false, lightmapFormat);
|
||||
}
|
||||
|
||||
var image = Image.CreateEmpty((int)bounds.Width, (int)bounds.Height, false, Image.Format.Rgba8);
|
||||
foreach (var rect in packingRects)
|
||||
{
|
||||
if (!rectDataMap.ContainsKey(rect.Id)) GD.Print("Invalid rectDataMap key");
|
||||
|
@ -377,18 +298,9 @@ public partial class Mission : Node3D
|
|||
|
||||
if (info.cellIndex >= cells.Length) GD.Print($"CellIndex too big: {info.cellIndex}/{cells.Length}");
|
||||
if (info.lightmapIndex >= cells[info.cellIndex].Lightmaps.Length) GD.Print($"LightmapIndex too big: {info.lightmapIndex}/{cells[info.cellIndex].Lightmaps.Length}");
|
||||
|
||||
var lightmap = cells[info.cellIndex].Lightmaps[info.lightmapIndex];
|
||||
var width = lightmap.Width;
|
||||
var height = lightmap.Height;
|
||||
var layerCount = lightmap.Layers;
|
||||
var srcRect = new Rect2I(0, 0, width, height);
|
||||
var dst = new Vector2I((int)rect.X, (int)rect.Y);
|
||||
for (var i = 0; i < layerCount; i++)
|
||||
{
|
||||
var cellLm = Image.CreateFromData(width, height, false, lightmapFormat, lightmap.AsBytesRgba(i));
|
||||
lmImages[i].BlitRect(cellLm, srcRect, dst);
|
||||
}
|
||||
var cellLm = Image.CreateFromData(lightmap.Width, lightmap.Height, false, Image.Format.Rgba8, lightmap.AsBytesRgba());
|
||||
image.BlitRect(cellLm, new Rect2I(0, 0, lightmap.Width, lightmap.Height), new Vector2I((int)rect.X, (int)rect.Y));
|
||||
|
||||
if (!surfaceDataMap.ContainsKey(info.textureId)) GD.Print("Invalid SurfaceDataMap key");
|
||||
surfaceDataMap[info.textureId].TransformUv2s(info.uvStart, info.uvEnd, (uv) =>
|
||||
|
@ -409,9 +321,7 @@ public partial class Mission : Node3D
|
|||
});
|
||||
}
|
||||
|
||||
var lightmapTexture = new Texture2DArray();
|
||||
lightmapTexture.CreateFromImages(lmImages);
|
||||
return lightmapTexture;
|
||||
return ImageTexture.CreateFromImage(image);
|
||||
}
|
||||
|
||||
private int CalcBaseUV(
|
||||
|
@ -538,17 +448,12 @@ public partial class Mission : Node3D
|
|||
}
|
||||
|
||||
const string MATERIAL_PATH = "res://project/materials/base.tres";
|
||||
private static ShaderMaterial BuildMaterial(
|
||||
Texture2D albedoTexture,
|
||||
Texture2DArray lightmapTexture,
|
||||
bool lmHdr,
|
||||
Vector2I layerMask)
|
||||
private static Material BuildMaterial(Texture albedoTexture, Texture lightmapTexture, bool lmHdr)
|
||||
{
|
||||
var material = ResourceLoader.Load<ShaderMaterial>(MATERIAL_PATH).Duplicate() as ShaderMaterial;
|
||||
material.SetShaderParameter("texture_albedo", albedoTexture);
|
||||
material.SetShaderParameter("lightmap_albedo", lightmapTexture);
|
||||
material.SetShaderParameter("lightmap_2x", lmHdr);
|
||||
material.SetShaderParameter("lightmap_bitmask", layerMask);
|
||||
return material;
|
||||
}
|
||||
}
|
|
@ -4,9 +4,8 @@
|
|||
code = "shader_type spatial;
|
||||
render_mode blend_mix,depth_draw_opaque,cull_back,unshaded;
|
||||
uniform sampler2D texture_albedo : filter_linear_mipmap_anisotropic,repeat_enable;
|
||||
uniform sampler2DArray lightmap_albedo : filter_linear_mipmap_anisotropic,repeat_enable;
|
||||
uniform sampler2D lightmap_albedo : filter_linear_mipmap_anisotropic,repeat_enable;
|
||||
uniform bool lightmap_2x;
|
||||
uniform ivec2 lightmap_bitmask;
|
||||
|
||||
float srgb_to_linear_e(float input) {
|
||||
float output;
|
||||
|
@ -29,27 +28,11 @@ vec3 srgb_to_linear(vec3 input) {
|
|||
|
||||
void fragment() {
|
||||
vec4 albedo_tex = texture(texture_albedo,UV);
|
||||
if (lightmap_bitmask.x == 0 && lightmap_bitmask.y == 0) {
|
||||
ALBEDO = srgb_to_linear(albedo_tex.rgb);
|
||||
} else {
|
||||
vec4 lightmap_tex = vec4(0.0);
|
||||
int mask = lightmap_bitmask.x;
|
||||
for (int i = 0; i < 33; i++) {
|
||||
if (i == 32) {
|
||||
mask = lightmap_bitmask.y;
|
||||
}
|
||||
bool layer_enabled = (mask & (1 << (i % 32))) != 0;
|
||||
if (layer_enabled) {
|
||||
lightmap_tex += texture(lightmap_albedo, vec3(UV2, float(i)));
|
||||
}
|
||||
}
|
||||
lightmap_tex = min(vec4(1.0), lightmap_tex);
|
||||
|
||||
if (lightmap_2x) {
|
||||
lightmap_tex *= 2.0f;
|
||||
}
|
||||
ALBEDO = srgb_to_linear((albedo_tex * lightmap_tex).rgb);
|
||||
vec4 lightmap_tex = texture(lightmap_albedo,UV2);
|
||||
if (lightmap_2x) {
|
||||
lightmap_tex *= 2.0f;
|
||||
}
|
||||
ALBEDO = srgb_to_linear((albedo_tex * lightmap_tex).rgb);
|
||||
}
|
||||
"
|
||||
|
||||
|
@ -57,4 +40,3 @@ void fragment() {
|
|||
render_priority = 0
|
||||
shader = SubResource("Shader_eumy4")
|
||||
shader_parameter/lightmap_2x = null
|
||||
shader_parameter/lightmap_bitmask = null
|
||||
|
|
Loading…
Reference in New Issue