( name: "GridShader", resources: [ ( name: "properties", kind: PropertyGroup([ ( name: "diffuseColor", kind: Color(r: 40, g: 40, b: 40, a: 255), ), ( name: "xAxisColor", kind: Color(r: 255, g: 0, b: 0, a: 255), ), ( name: "yAxisColor", kind: Color(r: 0, g: 255, b: 0, a: 255), ), ( name: "zAxisColor", kind: Color(r: 0, g: 0, b: 255, a: 255), ), ( name: "orientation", kind: Int(value: 0), ), ( name: "isPerspective", kind: Bool(value: false) ), ( name: "scale", kind: Vector2(value: (1.0, 1.0)) ) ]), binding: 0 ), ( name: "fyrox_cameraData", kind: PropertyGroup([ // Autogenerated ]), binding: 1 ), ], disabled_passes: ["GBuffer", "DirectionalShadow", "PointShadow", "SpotShadow"], passes: [ ( name: "Forward", draw_parameters: DrawParameters( cull_face: None, color_write: ColorMask( red: true, green: true, blue: true, alpha: true, ), depth_write: true, stencil_test: None, depth_test: Some(Less), blend: Some(BlendParameters( func: BlendFunc( sfactor: SrcAlpha, dfactor: OneMinusSrcAlpha, alpha_sfactor: SrcAlpha, alpha_dfactor: OneMinusSrcAlpha, ), equation: BlendEquation( rgb: Add, alpha: Add ) )), stencil_op: StencilOp( fail: Keep, zfail: Keep, zpass: Keep, write_mask: 0xFFFF_FFFF, ), scissor_box: None ), vertex_shader: r#" layout(location = 0) in vec3 vertexPosition; out vec3 nearPoint; out vec3 farPoint; vec3 Unproject(float x, float y, float z, mat4 matrix) { vec4 position = matrix * vec4(x, y, z, 1.0); return position.xyz / position.w; } void main() { mat4 invViewProj = inverse(fyrox_cameraData.viewProjectionMatrix); nearPoint = Unproject(vertexPosition.x, vertexPosition.y, 0.0, invViewProj); farPoint = Unproject(vertexPosition.x, vertexPosition.y, 1.0, invViewProj); gl_Position = vec4(vertexPosition, 1.0); } "#, fragment_shader: r#" // Original code: https://asliceofrendering.com/scene%20helper/2020/01/05/InfiniteGrid/ // Fixed and adapted for Fyrox. out vec4 FragColor; in vec3 nearPoint; in vec3 farPoint; vec4 grid(vec3 fragPos3D) { vec2 projection; vec3 planeNormal; vec4 xColor; vec4 yColor; if (properties.orientation == 0) { projection = fragPos3D.xz; planeNormal = vec3(0.0, 1.0, 0.0); xColor = properties.xAxisColor; yColor = properties.zAxisColor; } else if (properties.orientation == 1) { projection = fragPos3D.xy; planeNormal = vec3(0.0, 0.0, 1.0); xColor = properties.yAxisColor; yColor = properties.xAxisColor; } else if (properties.orientation == 2) { projection = fragPos3D.zy; planeNormal = vec3(1.0, 0.0, 0.0); xColor = properties.zAxisColor; yColor = properties.yAxisColor; } vec2 coord = projection * properties.scale; vec2 derivative = fwidth(coord); vec2 grid = abs(fract(coord - 0.5) - 0.5) / derivative; float line = min(grid.x, grid.y); float minX = 0.5 * min(derivative.x, 1.0); float minY = 0.5 * min(derivative.y, 1.0); vec4 color = properties.diffuseColor; float alpha = 1.0 - min(line, 1.0); // Sharpen lines a bit. color.a = alpha >= 0.5 ? 1.0 : 0.0; if (projection.x > -minX && projection.x < minX) { color.xyz = xColor.xyz; } else if (projection.y > -minY && projection.y < minY) { color.xyz = yColor.xyz; } else { vec3 viewDir = fragPos3D - fyrox_cameraData.position; // This helps to negate moire pattern at large distances. float cosAngle = abs(dot(planeNormal, normalize(viewDir))); color.a *= cosAngle; } return color; } float computeDepth(vec3 pos) { vec4 clip_space_pos = fyrox_cameraData.viewProjectionMatrix * vec4(pos.xyz, 1.0); return (clip_space_pos.z / clip_space_pos.w); } void main() { float nearCoord; float farCoord; if (properties.orientation == 0) { nearCoord = nearPoint.y; farCoord = farPoint.y; } else if (properties.orientation == 1) { nearCoord = nearPoint.z; farCoord = farPoint.z; } else if (properties.orientation == 2) { nearCoord = nearPoint.x; farCoord = farPoint.x; } float denominator = farCoord - nearCoord; float t = denominator != 0.0 ? -nearCoord / denominator : 0.0; vec3 fragPos3D = nearPoint + t * (farPoint - nearPoint); float depth = computeDepth(fragPos3D); gl_FragDepth = ((gl_DepthRange.diff * depth) + gl_DepthRange.near + gl_DepthRange.far) / 2.0; FragColor = grid(fragPos3D); if (properties.isPerspective) { FragColor.a *= float(t > 0.0); } // Alpha test to prevent blending issues. if (FragColor.a < 0.01) { discard; } } "#, ), ], )