mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -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 ditherSeed;
|
||||
// For raymarching:
|
||||
flat in ivec3 minPos;
|
||||
flat in ivec3 maxPos;
|
||||
in vec3 startPosition;
|
||||
in vec3 direction;
|
||||
|
||||
|
@ -7,6 +7,8 @@ flat out int faceNormal;
|
||||
flat out int isBackFace;
|
||||
flat out int ditherSeed;
|
||||
// For raymarching:
|
||||
flat out ivec3 minPos;
|
||||
flat out ivec3 maxPos;
|
||||
out vec3 startPosition;
|
||||
out vec3 direction;
|
||||
|
||||
@ -149,20 +151,24 @@ void main() {
|
||||
position *= 16;
|
||||
position -= ivec3(mirrorVector)*8 - 8;
|
||||
position = ivec3(permutationMatrix*(position*mirrorVector));
|
||||
position *= voxelSize;
|
||||
ivec3 totalOffset = (ivec3(normals[oldNormal])+1)/2;
|
||||
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(permutationMatrix*(vec3(equal(mirrorVector, vec3(1)))*totalOffset + vec3(equal(mirrorVector, vec3(-1)))*(1 - totalOffset)));
|
||||
ivec3 lowerBound = 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;
|
||||
position += totalOffset - 16*ivec3(normals[normal]);
|
||||
position += totalOffset - 16*voxelSize*ivec3(normals[normal]);
|
||||
|
||||
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);
|
||||
gl_Position = projectionMatrix*mvPos;
|
||||
|
@ -6,6 +6,8 @@ flat in int faceNormal;
|
||||
flat in int modelIndex;
|
||||
flat in int isBackFace;
|
||||
flat in int ditherSeed;
|
||||
flat in ivec3 minPos;
|
||||
flat in ivec3 maxPos;
|
||||
in vec3 startPosition;
|
||||
in vec3 direction;
|
||||
|
||||
|
@ -7,6 +7,8 @@ flat in int modelIndex;
|
||||
flat in int isBackFace;
|
||||
flat in int ditherSeed;
|
||||
// For raymarching:
|
||||
flat in ivec3 minPos;
|
||||
flat in ivec3 maxPos;
|
||||
in vec3 startPosition;
|
||||
in vec3 direction;
|
||||
|
||||
@ -59,6 +61,7 @@ const vec3[6] normals = vec3[6](
|
||||
);
|
||||
|
||||
int getVoxel(ivec3 voxelPos) {
|
||||
voxelPos &= 15;
|
||||
int voxelIndex = (voxelPos.x << 8) | (voxelPos.y << 4) | (voxelPos.z);
|
||||
int shift = 4*(voxelIndex & 7);
|
||||
int arrayIndex = voxelIndex >> 3;
|
||||
@ -87,9 +90,6 @@ RayMarchResult rayMarching(vec3 startPosition, vec3 direction) { // TODO: Mipmap
|
||||
|
||||
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 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;
|
||||
if(textureDir == 6) textureDir = lastNormal;
|
||||
return RayMarchResult(true, lastNormal, textureDir, voxelPos);
|
||||
return RayMarchResult(true, lastNormal, textureDir, voxelPos & 15);
|
||||
}
|
||||
|
||||
ivec2 getTextureCoords(ivec3 voxelPosition, int textureDir) {
|
||||
@ -214,7 +214,7 @@ void main() {
|
||||
if(!passDitherTest(interp)) {
|
||||
result = rayMarching(startPosition, direction);
|
||||
} 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;
|
||||
int textureIndex = textureData[blockType].textureIndices[result.textureDir];
|
||||
|
@ -18,25 +18,25 @@ const VoxelModel = extern struct {
|
||||
max: Vec3i,
|
||||
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.");
|
||||
@memset(&self.bitPackedData, 0);
|
||||
self.min = @splat(16);
|
||||
self.max = @splat(0);
|
||||
var x: u16 = 0;
|
||||
while(x < modelSize): (x += 1) {
|
||||
var y: u16 = 0;
|
||||
while(y < modelSize): (y += 1) {
|
||||
var z: u16 = 0;
|
||||
while(z < modelSize): (z += 1) {
|
||||
var isSolid = distributionFunction(x, y, z);
|
||||
var voxelIndex = (x << 2*modelShift) + (y << modelShift) + z;
|
||||
var shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
||||
var arrayIndex = voxelIndex >> 3;
|
||||
for(0..modelSize) |_x| {
|
||||
const x: u4 = @intCast(_x);
|
||||
for(0..modelSize) |_y| {
|
||||
const y: u4 = @intCast(_y);
|
||||
for(0..modelSize) |_z| {
|
||||
const z: u4 = @intCast(_z);
|
||||
const isSolid = distributionFunction(x, y, z);
|
||||
const voxelIndex = (_x << 2*modelShift) + (_y << modelShift) + _z;
|
||||
const shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
||||
const arrayIndex = voxelIndex >> 3;
|
||||
if(isSolid) |texture| {
|
||||
std.debug.assert(texture <= 6);
|
||||
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;
|
||||
} else {
|
||||
self.bitPackedData[arrayIndex] |= @as(u32, 7) << shift;
|
||||
@ -44,47 +44,41 @@ const VoxelModel = extern struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.max += @splat(1);
|
||||
// TODO: Use floodfill for this.
|
||||
var i: u32 = 7;
|
||||
while(i < 14) : (i += 1) {
|
||||
x = 0;
|
||||
while(x < modelSize): (x += 1) {
|
||||
var y: u16 = 0;
|
||||
while(y < modelSize): (y += 1) {
|
||||
var z: u16 = 0;
|
||||
for(0..modelSize) |_x| {
|
||||
const x: u4 = @intCast(_x);
|
||||
for(0..modelSize) |_y| {
|
||||
const y: u4 = @intCast(_y);
|
||||
outer:
|
||||
while(z < modelSize): (z += 1) {
|
||||
var voxelIndex = (x << 2*modelShift) + (y << modelShift) + z;
|
||||
var shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
||||
var arrayIndex = voxelIndex >> 3;
|
||||
var data = self.bitPackedData[arrayIndex]>>shift & 15;
|
||||
for(0..modelSize) |_z| {
|
||||
const z: u4 = @intCast(_z);
|
||||
const voxelIndex = (_x << 2*modelShift) + (_y << modelShift) + _z;
|
||||
const shift = 4*@as(u5, @intCast(voxelIndex & 7));
|
||||
const arrayIndex = voxelIndex >> 3;
|
||||
const data = self.bitPackedData[arrayIndex]>>shift & 15;
|
||||
if(data <= i) continue;
|
||||
var dx: u2 = 0;
|
||||
while(dx < 3) : (dx += 1) {
|
||||
if(dx == 0 and x == 0) continue;
|
||||
if(dx + x - 1 >= 16) continue;
|
||||
var dy: u2 = 0;
|
||||
while(dy < 3) : (dy += 1) {
|
||||
if(dy == 0 and y == 0) continue;
|
||||
if(dy + y - 1 >= 16) continue;
|
||||
var dz: u2 = 0;
|
||||
while(dz < 3) : (dz += 1) {
|
||||
if(dz == 0 and z == 0) continue;
|
||||
if(dz + z - 1 >= 16) continue;
|
||||
var nx = x + dx - 1;
|
||||
var ny = y + dy - 1;
|
||||
var nz = z + dz - 1;
|
||||
var neighborVoxelIndex = (nx << 2*modelShift) + (ny << modelShift) + nz;
|
||||
var neighborShift = 4*@as(u5, @intCast(neighborVoxelIndex & 7));
|
||||
var neighborArrayIndex = neighborVoxelIndex >> 3;
|
||||
var neighborData = self.bitPackedData[neighborArrayIndex]>>neighborShift & 15;
|
||||
const nx = x +% dx -% 1;
|
||||
const ny = y +% dy -% 1;
|
||||
const nz = z +% dz -% 1;
|
||||
const neighborVoxelIndex = (@as(usize, nx) << 2*modelShift) + (@as(usize, ny) << modelShift) + @as(usize, nz);
|
||||
const neighborShift = 4*@as(u5, @intCast(neighborVoxelIndex & 7));
|
||||
const neighborArrayIndex = neighborVoxelIndex >> 3;
|
||||
const neighborData = self.bitPackedData[neighborArrayIndex]>>neighborShift & 15;
|
||||
if(neighborData < data) continue :outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
data += 1;
|
||||
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;
|
||||
}
|
||||
|
||||
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 y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||
@ -106,7 +100,7 @@ const Fence = struct {
|
||||
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 y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||
@ -117,7 +111,7 @@ const Fence = struct {
|
||||
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 y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||
@ -129,7 +123,7 @@ const Fence = struct {
|
||||
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 y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||
@ -140,7 +134,7 @@ const Fence = struct {
|
||||
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 y = @max(@as(i32, _y)-8, -@as(i32, _y)+7);
|
||||
var z = @max(@as(i32, _z)-8, -@as(i32, _z)+7);
|
||||
@ -152,7 +146,7 @@ const Fence = struct {
|
||||
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 y = @max(@as(i32, _y)-8, -@as(i32, _y)+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 y = @as(f32, @floatFromInt(_y)) - 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;
|
||||
}
|
||||
|
||||
fn octahedron(_x: u16, _y: u16, _z: u16) ?u4 {
|
||||
fn octahedron(_x: u4, _y: u4, _z: u4) ?u4 {
|
||||
var x = _x;
|
||||
var y = _y;
|
||||
var z = _z;
|
||||
|
Loading…
x
Reference in New Issue
Block a user