IsodiModel.vertexShader

Default fragment shader used to render the model.

The data is null-terminated for C compatibility.

struct IsodiModel
static immutable
auto vertexShader = format!" #version 330 #define PI %s "(raylib.PI) ~ q{ in vec3 vertexPosition; in vec2 vertexTexCoord; in vec4 vertexVariantUV; in float vertexBone; uniform mat4 transform; uniform mat4 modelview; uniform mat4 projection; uniform int flatten; uniform sampler2D matrixTexture; out vec2 fragTexCoord; out vec4 fragVariantUV; out vec2 fragAnchor; flat out int angle; /// Rotate a vector by a quaternion. /// See: https://stackoverflow.com/questions/9037174/glsl-rotation-with-a-rotation-vector/9037454#9037454 vec4 rotate(vec4 vector, vec4 quat) { vec3 temp = cross(quat.xyz, vector.xyz) + quat.w * vector.xyz; return vector + vec4(2.0 * cross(quat.xyz, temp), 0.0); } void main() { // Send vertex attributes to fragment shader fragTexCoord = vertexTexCoord; fragVariantUV = vertexVariantUV; // Flatview: Camera transform (modelview) excluding vertex height mat4 flatview = modelview; flatview[0].y = 0; flatview[1].y = 1; flatview[2].y = 0; // Keep [3] to let translations (such as sharpview) through // Also correct Z result, required for proper angle checking flatview[1].z = 0; flatview[2].z /= modelview[1].y; // Note: I achieved this correction by experimenting. It might not be mathematically accurate, but // it looks good enough. // Set transform matrix, angle quaternion and angle index for this bone mat4 boneMatrix = mat4(1.0); vec4 boneQuat = vec4(0, 0, 0, 1); angle = 0; // If we do have bone data if (!isnan(vertexBone)) { // Load the matrix boneMatrix = mat4( texture2D(matrixTexture, vec2(0.0/4, vertexBone)), texture2D(matrixTexture, vec2(1.0/4, vertexBone)), texture2D(matrixTexture, vec2(2.0/4, vertexBone)), texture2D(matrixTexture, vec2(3.0/4, vertexBone)) ); // Get the normal in camera view, only as seen from top in 2D vec2 normal = normalize( (flatview * boneMatrix * vec4(0, 0, 1, 0)).xz ); // Get the bone's orientation in the 2D plane (around Z axis) float orientation = atan(normal.y, normal.x) + PI / 2; // Snap the angle to texture angles // TODO Use the bone's angle property float snapped = round(orientation * 2 / PI); // Revert the rotation for textures angle = (4-int(snapped)) % 4; // Convert angle index to radians orientation = snapped * PI / 2 / 2; // Create a quaternion to counter the orientation boneQuat = vec4(0, sin(orientation), 0, cos(orientation)); } // Transform the vertex according to bone properties vec4 position = boneMatrix * rotate(vec4(vertexPosition, 1), boneQuat); // Set the anchor fragAnchor = position.xz; // Regular shape if (flatten == 0) { // Calculate final vertex position gl_Position = projection * modelview * transform * position; } // Flattened shape else { // Sharp: Camera transform only affecting height mat4 sharpview = mat4( 1, modelview[0].y, 0, 0, 0, modelview[1].y, 0, 0, 0, modelview[2].y, 1, 0, 0, modelview[3].y, 0, 1 ); // Calculate the final position in flat mode gl_Position = projection * flatview * ( // Get the regular position position // Apply transform + sharpview * (transform * vec4(1, 1, 1, 1) - vec4(1, 1, 1, 1)) ); // TODO Fix transform to work properly with rotations. } } } ~ '\0';

Meta