Backlog/tools/trenchbroom/shader/EntityModel.vertsh

160 lines
4.3 KiB
Plaintext

#version 120
/*
Copyright (C) 2020 MaxED
This file is part of TrenchBroom.
TrenchBroom is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TrenchBroom is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
*/
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform vec3 CameraPosition;
uniform vec3 CameraDirection;
uniform vec3 CameraRight;
uniform vec3 CameraUp;
// see Orientation enum in EntityModel.h
uniform int Orientation;
varying vec4 worldCoordinates;
mat4 getScaleMatrix() {
float sx = length(vec3(ModelMatrix[0]));
float sy = length(vec3(ModelMatrix[1]));
float sz = length(vec3(ModelMatrix[2]));
return mat4(
vec4(sx, 0.0, 0.0, 0.0),
vec4(0.0, sy, 0.0, 0.0),
vec4(0.0, 0.0, sz, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
}
mat4 getViewPlaneParallelUprightModelMatrix() {
// Faces view plane, up is towards the heavens.
vec3 right = CameraRight;
vec3 up = vec3(0.0, 0.0, 1.0);
vec3 normal = normalize(cross(right, up));
return mat4(
vec4(right, 0.0),
vec4(up, 0.0),
vec4(normal, 0.0),
ModelMatrix[3]
) * getScaleMatrix();
}
mat4 getFacingUprightModelMatrix() {
// Faces camera origin, up is towards the heavens.
vec3 toCam = CameraPosition - vec3(ModelMatrix[3]);
vec3 up = vec3(0.0, 0.0, 1.0);
vec3 right = normalize(cross(up, toCam));
vec3 normal = normalize(cross(right, up));
return mat4(
vec4(right, 0.0),
vec4(up, 0.0),
vec4(normal, 0.0),
ModelMatrix[3]
) * getScaleMatrix();
}
mat4 getViewPlaneParallelModelMatrix() {
// Faces view plane, up is towards the top of the screen.
vec3 normal = -CameraDirection;
vec3 right = CameraRight;
vec3 up = CameraUp;
return mat4(
vec4(right, 0.0),
vec4(up, 0.0),
vec4(normal, 0.0),
ModelMatrix[3]
) * getScaleMatrix();
}
float extractRollAngle(mat4 rotation) {
if (abs(rotation[0][2]) != 1.0) {
float theta = -asin(rotation[0][1]);
float cosTheta = cos(theta);
return atan(rotation[1][2] / cosTheta, rotation[2][2] / cosTheta);
} else if (rotation[0][2] == -1.0) {
return atan(rotation[1][0], rotation[2][0]);
} else {
return atan(-rotation[1][0], -rotation[2][0]);
}
}
mat4 getViewPlaneParallelOrientedModelMatrix() {
// Faces view plane, but obeys roll value.
mat4 transform = mat4(
ModelMatrix[0],
ModelMatrix[1],
ModelMatrix[2],
vec4(0.0, 0.0, 0.0, 1.0)
);
// the rotated unit vectors
vec3 x = normalize((transform * vec4(1.0, 0.0, 0.0, 1.0)).xyz);
vec3 y = normalize(cross((transform * vec4(0.0, 0.0, 1.0, 1.0)).xyz, x));
vec3 z = normalize(cross(x, y));
mat4 rotation = mat4(
vec4(x, 0.0),
vec4(y, 0.0),
vec4(z, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
float roll = extractRollAngle(rotation);
float s = sin(roll);
float c = cos(roll);
vec3 normal = -CameraDirection;
vec3 right = CameraRight * c + CameraUp * s;
vec3 up = CameraRight * -s + CameraUp * c;
return mat4(
vec4(right, 0.0),
vec4(up, 0.0),
vec4(normal, 0.0),
ModelMatrix[3]
) * getScaleMatrix();
}
mat4 getModelMatrix() {
if (Orientation == 0) {
return getViewPlaneParallelUprightModelMatrix();
} else if (Orientation == 1) {
return getFacingUprightModelMatrix();
} else if (Orientation == 2) {
return getViewPlaneParallelModelMatrix();
} else if (Orientation == 4) {
return getViewPlaneParallelOrientedModelMatrix();
}
// Pitch yaw roll are independent of camera.
return ModelMatrix;
}
void main(void) {
gl_Position = gl_ProjectionMatrix * ViewMatrix * getModelMatrix() * gl_Vertex;
worldCoordinates = ModelMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}