Skip to content

Instantly share code, notes, and snippets.

@w0wca7a
Created September 3, 2025 22:24
Show Gist options
  • Select an option

  • Save w0wca7a/6187196a0e4c7f86b5b17bb33a3fb0ca to your computer and use it in GitHub Desktop.

Select an option

Save w0wca7a/6187196a0e4c7f86b5b17bb33a3fb0ca to your computer and use it in GitHub Desktop.
TargetRender for Stride game engine
// add this component to Entity, which must be marked as target
using Stride.Core;
using Stride.Engine;
[DataContract]
public class TargetComponent : EntityComponent {}
// Based on Stride Community Toolkit Example #9
// https://github.com/stride3d/stride-community-toolkit/blob/08218340fb99b6d994e160d2d0af05bcce43fab1/examples/code-only/Example09_Renderer/MyCustomSceneRenderer.cs
using Stride.Core.Mathematics;
using Stride.Engine;
using Stride.Graphics;
using Stride.Rendering;
using Stride.Rendering.Compositing;
namespace BlurUI.CustomRenderer
{
public class TargetRenderer : SceneRendererBase, ISharedRenderer
{
public Texture TargetTexture;
private SpriteBatch _spriteBatch;
private Scene _scene;
private CameraComponent _camera;
protected override void InitializeCore()
{
base.InitializeCore();
_spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void DrawCore(RenderContext context, RenderDrawContext drawContext)
{
var graphicsCompositor = context.Tags.Get(GraphicsCompositor.Current);
if (graphicsCompositor is null) return;
_camera ??= context.GetCurrentCamera();
_scene ??= SceneInstance.GetCurrent(context).RootScene;
if (_spriteBatch is null || _camera is null || _scene is null) return;
var viewProjection = _camera.ViewProjectionMatrix;
_spriteBatch.Begin(
drawContext.GraphicsContext);
foreach (var entity in _scene.Entities)
{
/* using Stride.Core;
* using Stride.Engine;
* [DataContract]
* public class TargetComponent : EntityComponent {}
*
* can be add from code
*/
// Find object with TargetComponent
if (entity.Components.Get<TargetComponent>() is null) continue;
// original
// var screenPosition = _camera.WorldToScreenPoint(ref entity.Transform.Position, GraphicsDevice);
var worldPos = entity.Transform.Position;
// Transform to clip space
var clipPosition = Vector4.Transform(new Vector4(worldPos, 1f), viewProjection);
if (clipPosition.W <= 0f)
continue; // behind the camera
// Perspective divide -> Normalized Device Coordinates (NDC)
var inverseW = 1f / clipPosition.W;
var normalizedDeviceCoordinatesX = clipPosition.X * inverseW;
var normalizedDeviceCoordinatesY = clipPosition.Y * inverseW;
var normalizedDeviceCoordinatesZ = clipPosition.Z * inverseW;
// Clip test in NDC: x and y in [-1,1], z in [0,1]
var outsideNdc = normalizedDeviceCoordinatesZ < 0f || normalizedDeviceCoordinatesZ > 1f || normalizedDeviceCoordinatesX < -1f || normalizedDeviceCoordinatesX > 1f || normalizedDeviceCoordinatesY < -1f || normalizedDeviceCoordinatesY > 1f;
// culled
if (outsideNdc) continue;
// implementation
// start
Vector3.TransformCoordinate(ref worldPos, ref _camera.ViewProjectionMatrix, out Vector3 viewProject);
Vector3.TransformCoordinate(ref worldPos, ref _camera.ViewMatrix, out Vector3 viewSpace);
Vector3 result = new()
{
X = (viewProject.X + 1f) / 2f,
Y = 1f - (viewProject.Y + 1f) / 2f,
Z = viewSpace.Z + _camera.NearClipPlane,
};
var windowSize = new Int2(
drawContext.GraphicsDevice.Presenter.BackBuffer.Width,
drawContext.GraphicsDevice.Presenter.BackBuffer.Height);
Vector2 screenPosition = new()
{
X = result.X * windowSize.X,
Y = result.Y * windowSize.Y
};
// end
// Draw a texture
_spriteBatch.Draw(
TargetTexture,
new Rectangle(
(int)screenPosition.X - TargetTexture.Width/2, // horizontal center of texture in center of object
(int)screenPosition.Y - TargetTexture.Height/2, // vertical center of texture in center of object
TargetTexture.Width, // rectangle width same as texture
TargetTexture.Height), // rectangle height same as texture
new(1.0f, 1.0f, 1.0f, 1.0f)); // Color
}
// End the SpriteBatch
_spriteBatch.End();
}
}
}
@w0wca7a
Copy link
Author

w0wca7a commented Sep 3, 2025

1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment