---
title: "Asking where the drawn world is along a ray"
description: "Part of the rendering guide (guides { path = \"topics/rendering\" }), which lists every part."
section: "Topics"
slug: "topics-rendering-scene-queries"
canonical: "https://origozero.ai/docs/topics-rendering-scene-queries"
updated: "2026-10-15T11:08:40.265999727+00:00"
tags: ["documentation", "guide", "rendering"]
---

# Asking where the drawn world is along a ray

## Asking where the drawn world is along a ray

`renderer.raycast(origin, direction, maxDistance?, exclude?)` reports the
nearest surface the renderer DRAWS along a ray, and `renderer.raycastAll` every
surface along it, nearest first. Both answer for a mesh whether or not anything
gave it a rigid body, so a terrain, a procedurally generated mesh, or any plain
`Model` reports the surface under a point.

The answer is the nearest triangle of the mesh, so a sloped or terraced surface
reports its height where it was asked rather than the extent of its bounding
box:

```lua
local hit = renderer.raycast({ x, 100, z }, { 0, -1, 0 }, 200)
if hit then
    print(hit.entityId, hit.point.y, hit.normal.y, hit.distance)
end
```

A hit carries `entityId`, the world-space `point`, a unit `normal` turned to
face back along the ray, the `distance` from the origin, the `meshGuid`, and
`exact` — true where the answer came from a triangle, false where a mesh's
vertices live on the GPU alone and the object's bounds are the whole answer.
`distance` is measured in world units — the direction is normalised, at any
length you hand it in — so it is directly comparable to a `physics.raycast`
distance along the same ray. The triangles walked are the mesh's own, placed by
the entity's transform and by the mesh's bind pose, so a surface a skinning or
morph pass deforms on the GPU answers as the geometry the mesh holds.

Everything drawn is in scope — the ground you meant, and equally a character
standing on it, a prop, or a placeholder floor left in the scene. Read
`entityId` before trusting a height, step over what you did not mean with
`exclude`, or take the whole column with `raycastAll` and pick the surface
yourself:

```lua
-- the ground under a camera station, ignoring whoever is standing there
local hit = renderer.raycast({ x, 100, z }, { 0, -1, 0 }, 200, { playerId })

-- or: every surface in the column, choose the one you are after
for _, h in renderer.raycastAll({ x, 100, z }, { 0, -1, 0 }, 200) do
    if h.entityId == groundId then print(h.point.y) end
end
```

`physics.raycast` answers from colliders instead, which is the query for what a
body would collide with; this one is the query for what a camera would see.
