I'm making an isometric voxel game. I'd like to make it so that if a character is obscured by a roof that is exactly 3 blocks above the player, then the roof is moved over 2 blocks so that you can see the player and still and interact with whatever is on the roof.

I've got this shader code which kind of does what I want except that it deforms the roof:

void vertex() {
	vec3 _pixel_world_pos = (WORLD_MATRIX * vec4(VERTEX, 1.0)).xyz;
	
	if (_looking_up) {
	// If the pixel is part of a roof aka exactly 2 blocks above the player
		if ( _pixel_world_pos.y > _player_position.y + 2.0) {
			
			// Move the vertex over 2 blocks in world space
			_pixel_world_pos.z += 2.0;

                   // Convert back object space
			VERTEX = (inverse(WORLD_MATRIX) * vec4(_pixel_world_pos, 1.0)).xyz;
		}
	}
}

Before (The white thing is the character): After:

I'd like the blocks to still be blocks and not be stretched out. Any idea why that could be happening? Thanks!

The top vertex positions of a blocks at ( player_position.y + 1.0 ) are exactly at ( player_position.y + 2.0 ). That's why the top vertices of the block below your threshold value are affected.

Maybe the height of each block could simply be 0.9999 instead of 1.0. That way the top vertices should no longer be affected.

@mangis Thanks for the response. The shader is effecting the blocks that I want it to effect. The problem ( i think) is that the shader automatically stretches the mesh so that it stays connected. I want it to actually break apart instead of stretch.

@Megalomaniak Thanks. I could do that, but its a multiplayer game. If i were to actually move the blocks and enemies on top of the blocks it might make networking very hard since those objects exist in different locations for different players. Maybe thats not as hard as I think? However, even if I do use a shader I'm going to need to come up with some clever mouse coordinate transformations to ensure that I can still click on things on the moved roof...

a year later