mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 12:33:27 +02:00
164 lines
No EOL
6.6 KiB
GLSL
164 lines
No EOL
6.6 KiB
GLSL
#version 120
|
|
|
|
attribute float voxelSizeIn;
|
|
varying float voxelSize;
|
|
|
|
uniform float viewportWidth;
|
|
uniform float viewportHeight;
|
|
uniform vec3 cameraPosition;
|
|
|
|
// Bit codes for faces
|
|
const int NONE = 0;
|
|
const int RIGHT = 1;
|
|
const int LEFT = 2;
|
|
const int BOTTOM = 4;
|
|
const int BOTTOM_RIGHT = BOTTOM + RIGHT;
|
|
const int BOTTOM_LEFT = BOTTOM + LEFT;
|
|
const int TOP = 8;
|
|
const int TOP_RIGHT = TOP + RIGHT;
|
|
const int TOP_LEFT = TOP + LEFT;
|
|
const int NEAR = 16;
|
|
const int NEAR_RIGHT = NEAR + RIGHT;
|
|
const int NEAR_LEFT = NEAR + LEFT;
|
|
const int NEAR_BOTTOM = NEAR + BOTTOM;
|
|
const int NEAR_BOTTOM_RIGHT = NEAR + BOTTOM + RIGHT;
|
|
const int NEAR_BOTTOM_LEFT = NEAR + BOTTOM + LEFT;
|
|
const int NEAR_TOP = NEAR + TOP;
|
|
const int NEAR_TOP_RIGHT = NEAR + TOP + RIGHT;
|
|
const int NEAR_TOP_LEFT = NEAR + TOP + LEFT;
|
|
const int FAR = 32;
|
|
const int FAR_RIGHT = FAR + RIGHT;
|
|
const int FAR_LEFT = FAR + LEFT;
|
|
const int FAR_BOTTOM = FAR + BOTTOM;
|
|
const int FAR_BOTTOM_RIGHT = FAR + BOTTOM + RIGHT;
|
|
const int FAR_BOTTOM_LEFT = FAR + BOTTOM + LEFT;
|
|
const int FAR_TOP = FAR + TOP;
|
|
const int FAR_TOP_RIGHT = FAR + TOP + RIGHT;
|
|
const int FAR_TOP_LEFT = FAR + TOP + LEFT;
|
|
|
|
// If we know the position of the camera relative to the voxel, we can a priori know the vertices that make the visible hull
|
|
// polygon. This also tells us which two vertices are known to make the longest possible distance between any pair of these
|
|
// vertices for the projected polygon. This is a visibleFaces table based on this knowledge.
|
|
|
|
void main(void) {
|
|
// Note: the gl_Vertex in this case are in "world coordinates" meaning they've already been scaled to TREE_SCALE
|
|
// this is also true for voxelSizeIn.
|
|
vec4 bottomNearRight = gl_Vertex;
|
|
vec4 topFarLeft = (gl_Vertex + vec4(voxelSizeIn, voxelSizeIn, voxelSizeIn, 0.0));
|
|
|
|
int visibleFaces = NONE;
|
|
|
|
// In order to use our visibleFaces "table" (implemented as if statements) below, we need to encode the 6-bit code to
|
|
// orient camera relative to the 6 defining faces of the voxel. Based on camera position relative to the bottomNearRight
|
|
// corner and the topFarLeft corner, we can calculate which hull and therefore which two vertices are furthest apart
|
|
// linearly once projected
|
|
if (cameraPosition.x < bottomNearRight.x) {
|
|
visibleFaces += RIGHT;
|
|
}
|
|
if (cameraPosition.x > topFarLeft.x) {
|
|
visibleFaces += LEFT;
|
|
}
|
|
if (cameraPosition.y < bottomNearRight.y) {
|
|
visibleFaces += BOTTOM;
|
|
}
|
|
if (cameraPosition.y > topFarLeft.y) {
|
|
visibleFaces += TOP;
|
|
}
|
|
if (cameraPosition.z < bottomNearRight.z) {
|
|
visibleFaces += NEAR;
|
|
}
|
|
if (cameraPosition.z > topFarLeft.z) {
|
|
visibleFaces += FAR;
|
|
}
|
|
|
|
vec4 cornerAdjustOne;
|
|
vec4 cornerAdjustTwo;
|
|
|
|
if (visibleFaces == RIGHT) {
|
|
cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(0,1,1,0) * voxelSizeIn;
|
|
} else if (visibleFaces == LEFT) {
|
|
cornerAdjustOne = vec4(1,0,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn;
|
|
} else if (visibleFaces == BOTTOM) {
|
|
cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,0,1,0) * voxelSizeIn;
|
|
} else if (visibleFaces == TOP) {
|
|
cornerAdjustOne = vec4(0,1,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn;
|
|
} else if (visibleFaces == NEAR) {
|
|
cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,1,0,0) * voxelSizeIn;
|
|
} else if (visibleFaces == FAR) {
|
|
cornerAdjustOne = vec4(0,0,1,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn;
|
|
} else if (visibleFaces == NEAR_BOTTOM_LEFT ||
|
|
visibleFaces == FAR_TOP ||
|
|
visibleFaces == FAR_TOP_RIGHT) {
|
|
cornerAdjustOne = vec4(0,1,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,0,1,0) * voxelSizeIn;
|
|
} else if (visibleFaces == FAR_TOP_LEFT ||
|
|
visibleFaces == NEAR_RIGHT ||
|
|
visibleFaces == NEAR_BOTTOM ||
|
|
visibleFaces == NEAR_BOTTOM_RIGHT) {
|
|
cornerAdjustOne = vec4(0,0,1,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,1,0,0) * voxelSizeIn;
|
|
} else if (visibleFaces == NEAR_TOP_RIGHT ||
|
|
visibleFaces == FAR_LEFT ||
|
|
visibleFaces == FAR_BOTTOM_LEFT ||
|
|
visibleFaces == BOTTOM_RIGHT ||
|
|
visibleFaces == TOP_LEFT) {
|
|
cornerAdjustOne = vec4(1,0,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(0,1,1,0) * voxelSizeIn;
|
|
|
|
// Everything else...
|
|
//} else if (visibleFaces == BOTTOM_LEFT ||
|
|
// visibleFaces == TOP_RIGHT ||
|
|
// visibleFaces == NEAR_LEFT ||
|
|
// visibleFaces == FAR_RIGHT ||
|
|
// visibleFaces == NEAR_TOP ||
|
|
// visibleFaces == NEAR_TOP_LEFT ||
|
|
// visibleFaces == FAR_BOTTOM ||
|
|
// visibleFaces == FAR_BOTTOM_RIGHT) {
|
|
} else {
|
|
cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn;
|
|
cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn;
|
|
}
|
|
|
|
// Determine our corners
|
|
vec4 cornerOne = gl_Vertex + cornerAdjustOne;
|
|
vec4 cornerTwo = gl_Vertex + cornerAdjustTwo;
|
|
|
|
// Find their model view projections
|
|
vec4 cornerOneMVP = gl_ModelViewProjectionMatrix * cornerOne;
|
|
vec4 cornerTwoMVP = gl_ModelViewProjectionMatrix * cornerTwo;
|
|
|
|
// Map to x, y screen coordinates
|
|
vec2 cornerOneScreen = vec2(cornerOneMVP.x / cornerOneMVP.w, cornerOneMVP.y / cornerOneMVP.w);
|
|
if (cornerOneMVP.w < 0) {
|
|
cornerOneScreen.x = -cornerOneScreen.x;
|
|
cornerOneScreen.y = -cornerOneScreen.y;
|
|
}
|
|
|
|
vec2 cornerTwoScreen = vec2(cornerTwoMVP.x / cornerTwoMVP.w, cornerTwoMVP.y / cornerTwoMVP.w);
|
|
if (cornerTwoMVP.w < 0) {
|
|
cornerTwoScreen.x = -cornerTwoScreen.x;
|
|
cornerTwoScreen.y = -cornerTwoScreen.y;
|
|
}
|
|
|
|
// Find the distance between them in pixels
|
|
float voxelScreenWidth = abs(cornerOneScreen.x - cornerTwoScreen.x) * viewportWidth / 2.0;
|
|
float voxelScreenHeight = abs(cornerOneScreen.y - cornerTwoScreen.y) * viewportHeight / 2.0;
|
|
float voxelScreenLength = sqrt(voxelScreenHeight * voxelScreenHeight + voxelScreenWidth * voxelScreenWidth);
|
|
|
|
// Find the center of the voxel
|
|
vec4 centerVertex = gl_Vertex;
|
|
float halfSizeIn = voxelSizeIn / 2;
|
|
centerVertex += vec4(halfSizeIn, halfSizeIn, halfSizeIn, 0.0);
|
|
vec4 center = gl_ModelViewProjectionMatrix * centerVertex;
|
|
|
|
// Finally place the point at the center of the voxel, with a size equal to the maximum screen length
|
|
gl_Position = center;
|
|
gl_PointSize = voxelScreenLength;
|
|
gl_FrontColor = gl_Color;
|
|
} |