mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -04:00
Scale textures and models in LOD terrain to match their true scale.
This also adds some support for rendering larger volumes of voxel models at once. That might allow greeding meshing for voxel models. Fixes #146
This commit is contained in:
parent
9978fd2025
commit
c2a955f86c
@ -7,6 +7,8 @@ flat in int modelIndex;
|
|||||||
flat in int isBackFace;
|
flat in int isBackFace;
|
||||||
flat in int ditherSeed;
|
flat in int ditherSeed;
|
||||||
// For raymarching:
|
// For raymarching:
|
||||||
|
flat in ivec3 minPos;
|
||||||
|
flat in ivec3 maxPos;
|
||||||
in vec3 startPosition;
|
in vec3 startPosition;
|
||||||
in vec3 direction;
|
in vec3 direction;
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ flat out int faceNormal;
|
|||||||
flat out int isBackFace;
|
flat out int isBackFace;
|
||||||
flat out int ditherSeed;
|
flat out int ditherSeed;
|
||||||
// For raymarching:
|
// For raymarching:
|
||||||
|
flat out ivec3 minPos;
|
||||||
|
flat out ivec3 maxPos;
|
||||||
out vec3 startPosition;
|
out vec3 startPosition;
|
||||||
out vec3 direction;
|
out vec3 direction;
|
||||||
|
|
||||||
@ -149,20 +151,24 @@ void main() {
|
|||||||
position *= 16;
|
position *= 16;
|
||||||
position -= ivec3(mirrorVector)*8 - 8;
|
position -= ivec3(mirrorVector)*8 - 8;
|
||||||
position = ivec3(permutationMatrix*(position*mirrorVector));
|
position = ivec3(permutationMatrix*(position*mirrorVector));
|
||||||
|
position *= voxelSize;
|
||||||
ivec3 totalOffset = (ivec3(normals[oldNormal])+1)/2;
|
ivec3 totalOffset = (ivec3(normals[oldNormal])+1)/2;
|
||||||
totalOffset += ivec3(equal(textureX[oldNormal], ivec3(-1))) + (vertexID>>1 & 1)*textureX[oldNormal];
|
totalOffset += ivec3(equal(textureX[oldNormal], ivec3(-1))) + (vertexID>>1 & 1)*textureX[oldNormal];
|
||||||
totalOffset += ivec3(equal(textureY[oldNormal], ivec3(-1))) + (vertexID & 1)*textureY[oldNormal];
|
totalOffset += ivec3(equal(textureY[oldNormal], ivec3(-1))) + (vertexID & 1)*textureY[oldNormal];
|
||||||
totalOffset = ivec3(permutationMatrix*(vec3(equal(mirrorVector, vec3(1)))*totalOffset + vec3(equal(mirrorVector, vec3(-1)))*(1 - totalOffset)));
|
totalOffset = ivec3(permutationMatrix*(vec3(equal(mirrorVector, vec3(1)))*totalOffset + vec3(equal(mirrorVector, vec3(-1)))*(1 - totalOffset)));
|
||||||
ivec3 lowerBound = voxelModels[modelIndex].minimum.xyz;
|
ivec3 lowerBound = voxelModels[modelIndex].minimum.xyz;
|
||||||
ivec3 size = voxelModels[modelIndex].maximum.xyz - voxelModels[modelIndex].minimum.xyz;
|
ivec3 size = voxelModels[modelIndex].maximum.xyz - voxelModels[modelIndex].minimum.xyz;
|
||||||
|
size += (voxelSize - 1)*16;
|
||||||
|
minPos = lowerBound;
|
||||||
|
maxPos = lowerBound + size;
|
||||||
totalOffset = lowerBound + size*totalOffset;
|
totalOffset = lowerBound + size*totalOffset;
|
||||||
position += totalOffset - 16*ivec3(normals[normal]);
|
position += totalOffset - 16*voxelSize*ivec3(normals[normal]);
|
||||||
|
|
||||||
startPosition = (totalOffset)*0.999;
|
startPosition = (totalOffset)*0.999;
|
||||||
|
|
||||||
direction = position.xyz/16.0 + permutationMatrix*(mirrorVector*modelPosition)/voxelSize;
|
direction = position.xyz/16.0 + permutationMatrix*(mirrorVector*modelPosition);
|
||||||
|
|
||||||
vec3 globalPosition = mirrorVector*(transpose(permutationMatrix)*position)*voxelSize/16.0 + modelPosition;
|
vec3 globalPosition = mirrorVector*(transpose(permutationMatrix)*position)/16.0 + modelPosition;
|
||||||
|
|
||||||
vec4 mvPos = viewMatrix*vec4(globalPosition, 1);
|
vec4 mvPos = viewMatrix*vec4(globalPosition, 1);
|
||||||
gl_Position = projectionMatrix*mvPos;
|
gl_Position = projectionMatrix*mvPos;
|
||||||
|
@ -6,6 +6,8 @@ flat in int faceNormal;
|
|||||||
flat in int modelIndex;
|
flat in int modelIndex;
|
||||||
flat in int isBackFace;
|
flat in int isBackFace;
|
||||||
flat in int ditherSeed;
|
flat in int ditherSeed;
|
||||||
|
flat in ivec3 minPos;
|
||||||
|
flat in ivec3 maxPos;
|
||||||
in vec3 startPosition;
|
in vec3 startPosition;
|
||||||
in vec3 direction;
|
in vec3 direction;
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ flat in int modelIndex;
|
|||||||
flat in int isBackFace;
|
flat in int isBackFace;
|
||||||
flat in int ditherSeed;
|
flat in int ditherSeed;
|
||||||
// For raymarching:
|
// For raymarching:
|
||||||
|
flat in ivec3 minPos;
|
||||||
|
flat in ivec3 maxPos;
|
||||||
in vec3 startPosition;
|
in vec3 startPosition;
|
||||||
in vec3 direction;
|
in vec3 direction;
|
||||||
|
|
||||||
@ -59,6 +61,7 @@ const vec3[6] normals = vec3[6](
|
|||||||
);
|
);
|
||||||
|
|
||||||
int getVoxel(ivec3 voxelPos) {
|
int getVoxel(ivec3 voxelPos) {
|
||||||
|
voxelPos &= 15;
|
||||||
int voxelIndex = (voxelPos.x << 8) | (voxelPos.y << 4) | (voxelPos.z);
|
int voxelIndex = (voxelPos.x << 8) | (voxelPos.y << 4) | (voxelPos.z);
|
||||||
int shift = 4*(voxelIndex & 7);
|
int shift = 4*(voxelIndex & 7);
|
||||||
int arrayIndex = voxelIndex >> 3;
|
int arrayIndex = voxelIndex >> 3;
|
||||||
@ -87,9 +90,6 @@ RayMarchResult rayMarching(vec3 startPosition, vec3 direction) { // TODO: Mipmap
|
|||||||
|
|
||||||
ivec3 voxelPos = ivec3(floor(startPosition));
|
ivec3 voxelPos = ivec3(floor(startPosition));
|
||||||
|
|
||||||
ivec3 minPos = voxelModels[modelIndex].minimum.xyz;
|
|
||||||
ivec3 maxPos = voxelModels[modelIndex].maximum.xyz;
|
|
||||||
|
|
||||||
ivec3 compare = mix(-maxPos, minPos, lessThan(direction, vec3(0)));
|
ivec3 compare = mix(-maxPos, minPos, lessThan(direction, vec3(0)));
|
||||||
ivec3 inversionMasks = mix(ivec3(~0), ivec3(0), lessThan(direction, vec3(0)));
|
ivec3 inversionMasks = mix(ivec3(~0), ivec3(0), lessThan(direction, vec3(0)));
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ RayMarchResult rayMarching(vec3 startPosition, vec3 direction) { // TODO: Mipmap
|
|||||||
}
|
}
|
||||||
int textureDir = -block;
|
int textureDir = -block;
|
||||||
if(textureDir == 6) textureDir = lastNormal;
|
if(textureDir == 6) textureDir = lastNormal;
|
||||||
return RayMarchResult(true, lastNormal, textureDir, voxelPos);
|
return RayMarchResult(true, lastNormal, textureDir, voxelPos & 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
ivec2 getTextureCoords(ivec3 voxelPosition, int textureDir) {
|
ivec2 getTextureCoords(ivec3 voxelPosition, int textureDir) {
|
||||||
@ -214,7 +214,7 @@ void main() {
|
|||||||
if(!passDitherTest(interp)) {
|
if(!passDitherTest(interp)) {
|
||||||
result = rayMarching(startPosition, direction);
|
result = rayMarching(startPosition, direction);
|
||||||
} else {
|
} else {
|
||||||
result = RayMarchResult(true, faceNormal, faceNormal, ivec3(startPosition)); // At some point it doesn't make sense to even draw the model.
|
result = RayMarchResult(true, faceNormal, faceNormal, ivec3(startPosition) & 15); // At some point it doesn't make sense to even draw the model.
|
||||||
}
|
}
|
||||||
if(!result.hitAThing) discard;
|
if(!result.hitAThing) discard;
|
||||||
int textureIndex = textureData[blockType].textureIndices[result.textureDir];
|
int textureIndex = textureData[blockType].textureIndices[result.textureDir];
|
||||||
|
@ -18,25 +18,25 @@ const VoxelModel = extern struct {
|
|||||||
max: Vec3i,
|
max: Vec3i,
|
||||||
bitPackedData: [modelSize*modelSize*modelSize/8]u32,
|
bitPackedData: [modelSize*modelSize*modelSize/8]u32,
|
||||||
|
|
||||||
pub fn init(self: *VoxelModel, distributionFunction: *const fn(u16, u16, u16) ?u4) void {
|
pub fn init(self: *VoxelModel, distributionFunction: *const fn(u4, u4, u4) ?u4) void {
|
||||||
if(@sizeOf(VoxelModel) != 16 + 16 + modelSize*modelSize*modelSize*4/8) @compileError("Expected Vec3i to have 16 byte alignment.");
|
if(@sizeOf(VoxelModel) != 16 + 16 + modelSize*modelSize*modelSize*4/8) @compileError("Expected Vec3i to have 16 byte alignment.");
|
||||||
@memset(&self.bitPackedData, 0);
|
@memset(&self.bitPackedData, 0);
|
||||||
self.min = @splat(16);
|
self.min = @splat(16);
|
||||||
self.max = @splat(0);
|
self.max = @splat(0);
|
||||||
var x: u16 = 0;
|
for(0..modelSize) |_x| {
|
||||||
while(x < modelSize): (x += 1) {
|
const x: u4 = @intCast(_x);
|
||||||
var y: u16 = 0;
|
for(0..modelSize) |_y| {
|
||||||
while(y < modelSize): (y += 1) {
|
const y: u4 = @intCast(_y);
|
||||||
var z: u16 = 0;
|
for(0..modelSize) |_z| {
|
||||||
while(z < modelSize): (z += 1) {
|
const z: u4 = @intCast(_z);
|
||||||
var isSolid = distributionFunction(x, y, z);
|
const isSolid = distributionFunction(x, y, z);
|
||||||
var voxelIndex = (x << 2*modelShift) + (y << modelShift) + z;
|
const voxelIndex = (_x << 2*modelShift) + (_y << modelShift) + _z;
|
||||||
var shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
const shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
||||||
var arrayIndex = voxelIndex >> 3;
|
const arrayIndex = voxelIndex >> 3;
|
||||||
if(isSolid) |texture| {
|
if(isSolid) |texture| {
|
||||||
std.debug.assert(texture <= 6);
|
std.debug.assert(texture <= 6);
|
||||||
self.min = @min(self.min, Vec3i{x, y, z});
|
self.min = @min(self.min, Vec3i{x, y, z});
|
||||||
self.max = @max(self.max, Vec3i{x+1, y+1, z+1});
|
self.max = @max(self.max, Vec3i{x, y, z});
|
||||||
self.bitPackedData[arrayIndex] |= @as(u32, 6 - texture) << shift;
|
self.bitPackedData[arrayIndex] |= @as(u32, 6 - texture) << shift;
|
||||||
} else {
|
} else {
|
||||||
self.bitPackedData[arrayIndex] |= @as(u32, 7) << shift;
|
self.bitPackedData[arrayIndex] |= @as(u32, 7) << shift;
|
||||||
@ -44,47 +44,41 @@ const VoxelModel = extern struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.max += @splat(1);
|
||||||
// TODO: Use floodfill for this.
|
// TODO: Use floodfill for this.
|
||||||
var i: u32 = 7;
|
var i: u32 = 7;
|
||||||
while(i < 14) : (i += 1) {
|
while(i < 14) : (i += 1) {
|
||||||
x = 0;
|
for(0..modelSize) |_x| {
|
||||||
while(x < modelSize): (x += 1) {
|
const x: u4 = @intCast(_x);
|
||||||
var y: u16 = 0;
|
for(0..modelSize) |_y| {
|
||||||
while(y < modelSize): (y += 1) {
|
const y: u4 = @intCast(_y);
|
||||||
var z: u16 = 0;
|
|
||||||
outer:
|
outer:
|
||||||
while(z < modelSize): (z += 1) {
|
for(0..modelSize) |_z| {
|
||||||
var voxelIndex = (x << 2*modelShift) + (y << modelShift) + z;
|
const z: u4 = @intCast(_z);
|
||||||
var shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
const voxelIndex = (_x << 2*modelShift) + (_y << modelShift) + _z;
|
||||||
var arrayIndex = voxelIndex >> 3;
|
const shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
||||||
var data = self.bitPackedData[arrayIndex]>>shift & 15;
|
const arrayIndex = voxelIndex >> 3;
|
||||||
|
const data = self.bitPackedData[arrayIndex]>>shift & 15;
|
||||||
if(data <= i) continue;
|
if(data <= i) continue;
|
||||||
var dx: u2 = 0;
|
var dx: u2 = 0;
|
||||||
while(dx < 3) : (dx += 1) {
|
while(dx < 3) : (dx += 1) {
|
||||||
if(dx == 0 and x == 0) continue;
|
|
||||||
if(dx + x - 1 >= 16) continue;
|
|
||||||
var dy: u2 = 0;
|
var dy: u2 = 0;
|
||||||
while(dy < 3) : (dy += 1) {
|
while(dy < 3) : (dy += 1) {
|
||||||
if(dy == 0 and y == 0) continue;
|
|
||||||
if(dy + y - 1 >= 16) continue;
|
|
||||||
var dz: u2 = 0;
|
var dz: u2 = 0;
|
||||||
while(dz < 3) : (dz += 1) {
|
while(dz < 3) : (dz += 1) {
|
||||||
if(dz == 0 and z == 0) continue;
|
const nx = x +% dx -% 1;
|
||||||
if(dz + z - 1 >= 16) continue;
|
const ny = y +% dy -% 1;
|
||||||
var nx = x + dx - 1;
|
const nz = z +% dz -% 1;
|
||||||
var ny = y + dy - 1;
|
const neighborVoxelIndex = (@as(usize, nx) << 2*modelShift) + (@as(usize, ny) << modelShift) + @as(usize, nz);
|
||||||
var nz = z + dz - 1;
|
const neighborShift = 4*@as(u5, @intCast(neighborVoxelIndex & 7));
|
||||||
var neighborVoxelIndex = (nx << 2*modelShift) + (ny << modelShift) + nz;
|
const neighborArrayIndex = neighborVoxelIndex >> 3;
|
||||||
var neighborShift = 4*@as(u5, @intCast(neighborVoxelIndex & 7));
|
const neighborData = self.bitPackedData[neighborArrayIndex]>>neighborShift & 15;
|
||||||
var neighborArrayIndex = neighborVoxelIndex >> 3;
|
|
||||||
var neighborData = self.bitPackedData[neighborArrayIndex]>>neighborShift & 15;
|
|
||||||
if(neighborData < data) continue :outer;
|
if(neighborData < data) continue :outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data += 1;
|
|
||||||
self.bitPackedData[arrayIndex] &= ~(@as(u32, 15) << shift);
|
self.bitPackedData[arrayIndex] &= ~(@as(u32, 15) << shift);
|
||||||
self.bitPackedData[arrayIndex] |= @as(u32, data) << shift;
|
self.bitPackedData[arrayIndex] |= @as(u32, data + 1) << shift;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,12 +86,12 @@ const VoxelModel = extern struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn cube(_: u16, _: u16, _: u16) ?u4 {
|
fn cube(_: u4, _: u4, _: u4) ?u4 {
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Fence = struct {
|
const Fence = struct {
|
||||||
fn fence0(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn fence0(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
||||||
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||||
@ -106,7 +100,7 @@ const Fence = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fence1(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn fence1(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
||||||
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||||
@ -117,7 +111,7 @@ const Fence = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fence2_neighbor(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn fence2_neighbor(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
||||||
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||||
@ -129,7 +123,7 @@ const Fence = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fence2_oppose(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn fence2_oppose(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
||||||
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||||
@ -140,7 +134,7 @@ const Fence = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fence3(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn fence3(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
||||||
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||||
@ -152,7 +146,7 @@ const Fence = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fence4(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn fence4(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
var x = @max(@as(i32, _x)-8, -@as(i32, _x)+7);
|
||||||
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
var y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||||
@ -164,7 +158,7 @@ const Fence = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn log(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn log(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = @as(f32, @floatFromInt(_x)) - 7.5;
|
var x = @as(f32, @floatFromInt(_x)) - 7.5;
|
||||||
var y = @as(f32, @floatFromInt(_y)) - 7.5;
|
var y = @as(f32, @floatFromInt(_y)) - 7.5;
|
||||||
var z = @as(f32, @floatFromInt(_z)) - 7.5;
|
var z = @as(f32, @floatFromInt(_z)) - 7.5;
|
||||||
@ -184,7 +178,7 @@ fn log(_x: u16, _y: u16, _z: u16) ?u4 {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn octahedron(_x: u16, _y: u16, _z: u16) ?u4 {
|
fn octahedron(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||||
var x = _x;
|
var x = _x;
|
||||||
var y = _y;
|
var y = _y;
|
||||||
var z = _z;
|
var z = _z;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user