Skip to content

Commit

Permalink
-Render to texture from viewpoint. Quest displays this upside down at…
Browse files Browse the repository at this point in the history
… the moment.
  • Loading branch information
maluoi committed Apr 12, 2021
1 parent 46443bd commit 1b251ac
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 6 deletions.
34 changes: 34 additions & 0 deletions Examples/StereoKitTest/Demos/DemoRenderTexture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using StereoKit;
using System;

class DemoRenderTexture : ITest
{
Tex renderSurface;
Material renderView;
public void Initialize()
{
renderSurface = new Tex(TexType.Rendertarget, TexFormat.Rgba32);
renderSurface.SetSize(512, 512);
renderSurface.AddZBuffer(TexFormat.Depth32);
renderView = Default.MaterialUnlit.Copy();
renderView[MatParamName.DiffuseTex] = renderSurface;
renderView.FaceCull = Cull.None;
}

Pose from = new Pose(V.XYZ(0,0,-0.2f), Quat.Identity);
Pose at = new Pose(V.XYZ(0,0,-0.3f), Quat.Identity);
public void Update()
{
UI.Handle("from", ref from, new Bounds(Vec3.One*0.02f), true);
UI.Handle("to", ref at, new Bounds(Vec3.One*0.02f), true);
Lines.Add(from.position, at.position, Color.White, 0.005f);
from.orientation = at.orientation = Quat.LookDir(at.position-from.position);
Default.MeshQuad.Draw(renderView, Matrix.TRS(at.position + at.orientation*Vec3.Up*0.06f, Quat.LookDir(from.position-at.position), 0.1f));

Renderer.RenderTo(renderSurface,
Matrix.TR(at.position+at.Forward*0.01f, at.orientation),
Matrix.Perspective(10 + Math.Max(0,Math.Min(1,(Vec3.Distance(from.position, at.position)-0.05f)/0.2f))*110, 1, 0.01f, 100));
}

public void Shutdown() { }
}
19 changes: 19 additions & 0 deletions StereoKit/Assets/Tex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,25 @@ public void SetColors(int width, int height, in float[] data)
}
NativeAPI.tex_set_colors(_inst, width, height, data);
}

/// <summary>Set the texture's size without providing any color data.
/// In most cases, you should probably just call SetColors instead,
/// but this can be useful if you're adding color data some other
/// way, such as when blitting or rendering to it.</summary>
/// <param name="width">Width in pixels of the texture. Powers of two
/// are generally best!</param>
/// <param name="height">Height in pixels of the texture. Powers of
/// two are generally best!</param>
public void SetSize(int width, int height)
=> NativeAPI.tex_set_colors(_inst, width, height, IntPtr.Zero);

/// <summary>Only applicable if this texture is a rendertarget!
/// This creates and attaches a zbuffer surface to the texture for
/// use when rendering to it.</summary>
/// <param name="depthFormat">The format of the depth texture, must
/// be a depth format type!</param>
public void AddZBuffer(TexFormat depthFormat)
=> NativeAPI.tex_add_zbuffer(_inst, depthFormat);
#endregion

#region Static Methods
Expand Down
38 changes: 38 additions & 0 deletions StereoKit/Math/Matrix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,5 +313,43 @@ public static Matrix TRS(Vec3 translation, Vec3 pitchYawRollDeg, float scale)
/// information into a single Matrix!</returns>
public static Matrix TRS(Vec3 translation, Vec3 pitchYawRollDeg, Vec3 scale)
=> NativeAPI.matrix_trs(translation, Quat.FromAngles(pitchYawRollDeg), scale);

/// <summary>This creates a matrix used for projecting 3D geometry
/// onto a 2D surface for rasterization. Perspective projection
/// matrices will cause parallel lines to converge at the horizon.
/// This is great for normal looking content.</summary>
/// <param name="fovDegrees">This is the vertical field of view of
/// the perspective matrix, units are in degrees.</param>
/// <param name="aspectRatio">The projection surface's width/height.
/// </param>
/// <param name="nearClip">Anything closer than this distance (in
/// meters) will be discarded. Must not be zero, and if you make this
/// too small, you may experience glitching in your depth buffer.</param>
/// <param name="farClip">Anything further than this distance (in
/// meters) will be discarded. For low resolution depth buffers, this
/// should not be too far away, or you'll see bad z-fighting
/// artifacts.</param>
/// <returns>The final perspective matrix.</returns>
public static Matrix Perspective(float fovDegrees, float aspectRatio, float nearClip, float farClip)
=> Matrix4x4.CreatePerspectiveFieldOfView(fovDegrees*Units.deg2rad, aspectRatio, nearClip, farClip);

/// <summary>This creates a matrix used for projecting 3D geometry
/// onto a 2D surface for rasterization. Orthographic projection
/// matrices will preserve parallel lines. This is great for 2D
/// scenes or content.</summary>
/// <param name="width">The width, in meters, of the area that will
/// be projected.</param>
/// <param name="height">The height, in meters, of the area that will
/// be projected.</param>
/// <param name="nearClip">Anything closer than this distance (in
/// meters) will be discarded. Must not be zero, and if you make this
/// too small, you may experience glitching in your depth buffer.</param>
/// <param name="farClip">Anything further than this distance (in
/// meters) will be discarded. For low resolution depth buffers, this
/// should not be too far away, or you'll see bad z-fighting
/// artifacts.</param>
/// <returns>The final orhtographic matrix.</returns>
public static Matrix Orthographic(float width, float height, float nearClip, float farClip)
=> Matrix4x4.CreateOrthographic(width, height, nearClip, farClip);
}
}
1 change: 1 addition & 0 deletions StereoKit/Native/NativeAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ internal static class NativeAPI
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern void render_add_model (IntPtr model, in Matrix transform, Color color);
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern void render_blit (IntPtr to_rendertarget, IntPtr material);
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern void render_screenshot (Vec3 from_viewpt, Vec3 at, int width, int height, string file);
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern void render_from_viewpoint(IntPtr to_rendertarget, in Matrix camera, in Matrix projection);
//[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern void render_get_device (void **device, void **context);

///////////////////////////////////////////
Expand Down
16 changes: 16 additions & 0 deletions StereoKit/Systems/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,21 @@ public static void Blit(Tex toRendertarget, Material material)
public static void Screenshot(Vec3 from, Vec3 at, int width, int height, string filename)
=> NativeAPI.render_screenshot(from, at, width, height, filename);

/// <summary>This renders the current scene to the indicated
/// rendertarget texture, from the specified viewpoint. This call
/// enqueues a render that occurs immediately before the screen
/// itself is rendered.</summary>
/// <param name="toRendertarget">The texture to which the scene will
/// be rendered to. This must be a Rendertarget type texture.</param>
/// <param name="camera">A TRS matrix representing the location and
/// orientation of the camera. This matrix gets inverted later on, so
/// no need to do it yourself.</param>
/// <param name="projection">The projection matrix describes how the
/// geometry is flattened onto the draw surface. Normally, you'd use
/// Matrix.Perspective, and occasionally Matrix.Orthographic might be
/// helpful as well.</param>
public static void RenderTo(Tex toRendertarget, Matrix camera, Matrix projection)
=> NativeAPI.render_from_viewpoint(toRendertarget._inst, camera, projection);

}
}
20 changes: 20 additions & 0 deletions StereoKitC/sk_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,26 @@ void matrix_trs_out(matrix &out_result, const vec3 &position, const quat &orient

///////////////////////////////////////////

matrix matrix_perspective(float fov_degrees, float aspect_ratio, float near_clip, float far_clip) {
matrix result;
math_fast_to_matrix(XMMatrixPerspectiveFovRH(
fov_degrees * deg2rad, aspect_ratio,
near_clip, far_clip), &result);
return result;
}

///////////////////////////////////////////

matrix matrix_orthographic(float width, float height, float near_clip, float far_clip) {
matrix result;
math_fast_to_matrix(XMMatrixOrthographicRH(
width, height,
near_clip, far_clip), &result);
return result;
}

///////////////////////////////////////////

bool32_t matrix_decompose(const matrix &transform, vec3 &out_position, vec3 &out_scale, quat &out_orientation) {
XMVECTOR pos, scale, rot;
XMMATRIX mat;
Expand Down
3 changes: 3 additions & 0 deletions StereoKitC/stereokit.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ SK_API pose_t matrix_mul_pose (const sk_ref(matrix) transform, const sk_re
SK_API vec3 matrix_to_angles (const sk_ref(matrix) transform);
SK_API matrix matrix_trs (const sk_ref(vec3) position, const sk_ref(quat) orientation sk_default({0,0,0,1}), const sk_ref(vec3) scale sk_default({1,1,1}));
SK_API void matrix_trs_out (sk_ref(matrix) out_result, const sk_ref(vec3) position, const sk_ref(quat) orientation sk_default({0,0,0,1}), const sk_ref(vec3) scale sk_default({1,1,1}));
SK_API matrix matrix_perspective (float fov_degrees, float aspect_ratio, float near_clip, float far_clip);
SK_API matrix matrix_orthographic (float width, float height, float near_clip, float far_clip);
SK_API bool32_t matrix_decompose (const sk_ref(matrix) transform, sk_ref(vec3) out_position, sk_ref(vec3) out_scale, sk_ref(quat) out_orientation);
SK_API vec3 matrix_extract_translation(const sk_ref(matrix) transform);
SK_API vec3 matrix_extract_scale (const sk_ref(matrix) transform);
Expand Down Expand Up @@ -666,6 +668,7 @@ SK_API void render_add_mesh (mesh_t mesh, material_t mate
SK_API void render_add_model (model_t model, const sk_ref(matrix) transform, color128 color_linear sk_default({1,1,1,1}));
SK_API void render_blit (tex_t to_rendertarget, material_t material);
SK_API void render_screenshot (vec3 from_viewpt, vec3 at, int width, int height, const char *file);
SK_API void render_render_to (tex_t to_rendertarget, const sk_ref(matrix) camera, const sk_ref(matrix) projection);
SK_API void render_get_device (void **device, void **context);

///////////////////////////////////////////
Expand Down
59 changes: 53 additions & 6 deletions StereoKitC/systems/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ struct render_screenshot_t {
int width;
int height;
};
struct render_viewpoint_t {
tex_t rendertarget;
matrix camera;
matrix projection;
};

///////////////////////////////////////////

Expand All @@ -80,6 +85,7 @@ color128 render_clear_color = {0,0,0,1};
render_list_t render_list_primary = -1;

array_t<render_screenshot_t> render_screenshot_list = {};
array_t<render_viewpoint_t> render_viewpoint_list = {};

mesh_t render_sky_mesh = nullptr;
material_t render_sky_mat = nullptr;
Expand All @@ -103,6 +109,7 @@ skg_bind_t render_list_sky_bind = { 11, skg_stage_pixel };
void render_set_material (material_t material);
skg_buffer_t *render_fill_inst_buffer (array_t<render_transform_buffer_t> &list, int32_t &offset, int32_t &out_count);
void render_check_screenshots();
void render_check_viewpoints ();

///////////////////////////////////////////

Expand Down Expand Up @@ -363,13 +370,16 @@ void render_draw_queue(const matrix *views, const matrix *projections, int32_t v
///////////////////////////////////////////

void render_draw_matrix(const matrix* views, const matrix* projections, int32_t count) {
render_check_viewpoints();
render_draw_queue(views, projections, count);
render_check_screenshots();
}

///////////////////////////////////////////

void render_check_screenshots() {
if (render_screenshot_list.count == 0) return;

skg_tex_t *old_target = skg_tex_target_get();
for (size_t i = 0; i < render_screenshot_list.count; i++) {
int32_t w = render_screenshot_list[i].width;
Expand All @@ -380,12 +390,7 @@ void render_check_screenshots() {
quat_lookat(render_screenshot_list[i].from, render_screenshot_list[i].at));
matrix_inverse(view, view);

matrix proj;
math_fast_to_matrix(XMMatrixPerspectiveFovRH(
render_fov * deg2rad,
(float)w/h,
render_clip_planes.x,
render_clip_planes.y), &proj);
matrix proj = matrix_perspective(render_fov, (float)w/h, render_clip_planes.x, render_clip_planes.y);

// Create the screenshot surface

Expand Down Expand Up @@ -419,6 +424,33 @@ void render_check_screenshots() {

///////////////////////////////////////////

void render_check_viewpoints() {
if (render_viewpoint_list.count == 0) return;

skg_tex_t *old_target = skg_tex_target_get();
for (size_t i = 0; i < render_viewpoint_list.count; i++) {

// Setup to render the screenshot
float color[4] = {
render_clear_color.r / 255.f,
render_clear_color.g / 255.f,
render_clear_color.b / 255.f,
render_clear_color.a / 255.f };
skg_tex_target_bind(&render_viewpoint_list[i].rendertarget->tex, true, color);

// Render!
render_draw_queue(&render_viewpoint_list[i].camera, &render_viewpoint_list[i].projection, 1);
skg_tex_target_bind(nullptr, false, nullptr);

// Release the reference we added, the user should have their own ref
assets_releaseref(render_viewpoint_list[i].rendertarget->header);
}
render_viewpoint_list.clear();
skg_tex_target_bind(old_target, false, nullptr);
}

///////////////////////////////////////////

void render_clear() {
//log_infof("draws: %d, instances: %d, material: %d, shader: %d, texture %d, mesh %d", render_stats.draw_calls, render_stats.draw_instances, render_stats.swaps_material, render_stats.swaps_shader, render_stats.swaps_texture, render_stats.swaps_mesh);
render_list_clear(render_list_active);
Expand Down Expand Up @@ -487,6 +519,7 @@ void render_shutdown() {
render_lists.free();
render_list_stack.free();
render_screenshot_list.free();
render_viewpoint_list.free();
render_instance_list.free();

material_release(render_sky_mat);
Expand Down Expand Up @@ -542,6 +575,20 @@ void render_screenshot(vec3 from_viewpt, vec3 at, int width, int height, const c

///////////////////////////////////////////

void render_render_to(tex_t to_rendertarget, const matrix &camera, const matrix &projection) {
if ((to_rendertarget->type & tex_type_rendertarget) == 0) {
log_err("render_render_to texture must be a render target texture type!");
return;
}
assets_addref(to_rendertarget->header);

matrix inv_cam;
matrix_inverse(camera, inv_cam);
render_viewpoint_list.add({ to_rendertarget, inv_cam, projection });
}

///////////////////////////////////////////

void render_set_material(material_t material) {
if (material == render_last_material)
return;
Expand Down

0 comments on commit 1b251ac

Please sign in to comment.