demos/teapot: Add a tessellation demo.

This commit is contained in:
Henri Verbeet
2025-06-16 18:49:08 +02:00
parent d572f4ac1f
commit 5911e410a8
Notes: Henri Verbeet 2025-06-18 16:00:25 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1575
8 changed files with 932 additions and 24 deletions

View File

@@ -325,6 +325,7 @@ vkd3d_test_headers = \
vkd3d_demos = \
demos/vkd3d-gears \
demos/vkd3d-teapot \
demos/vkd3d-triangle
vkd3d_demos_headers = \
@@ -549,6 +550,14 @@ demos_vkd3d_gears_CFLAGS = $(DEMOS_CFLAGS)
demos_vkd3d_gears_LDADD = $(DEMOS_LDADD) -lm
demos/vkd3d_gears-gears.$(OBJEXT): demos/gears.hlsl
demos_vkd3d_teapot_SOURCES = \
demos/teapot.c \
demos/teapot.h \
demos/teapot.hlsl
demos_vkd3d_teapot_CFLAGS = $(DEMOS_CFLAGS)
demos_vkd3d_teapot_LDADD = $(DEMOS_LDADD) -lm
demos/vkd3d_teapot-teapot.$(OBJEXT): demos/teapot.hlsl
demos_vkd3d_triangle_SOURCES = demos/triangle.c demos/triangle.hlsl
demos_vkd3d_triangle_CFLAGS = $(DEMOS_CFLAGS)
demos_vkd3d_triangle_LDADD = $(DEMOS_LDADD)
@@ -657,6 +666,7 @@ endif
if BUILD_DEMOS
CROSS32_EXEFILES += $(vkd3d_demos:demos/vkd3d-%=demos/%.cross32.exe)
demos/gears.cross32.exe: demos/gears.hlsl
demos/teapot.cross32.exe: demos/teapot.hlsl
demos/triangle.cross32.exe: demos/triangle.hlsl
endif
@@ -706,6 +716,7 @@ endif
if BUILD_DEMOS
CROSS64_EXEFILES += $(vkd3d_demos:demos/vkd3d-%=demos/%.cross64.exe)
demos/gears.cross64.exe: demos/gears.hlsl
demos/teapot.cross64.exe: demos/teapot.hlsl
demos/triangle.cross64.exe: demos/triangle.hlsl
endif

View File

@@ -38,6 +38,7 @@
#define COBJMACROS
#include <vkd3d_d3d12.h>
#include <inttypes.h>
#include <math.h>
#ifdef __WIN32__
#define DEMO_ASM_PUSHSECTION ".section rdata\n\t"
@@ -81,12 +82,14 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
#define DEMO_KEY_UNKNOWN 0x0000
#define DEMO_KEY_ESCAPE 0xff1b
#define DEMO_KEY_LEFT 0xff51
#define DEMO_KEY_UP 0xff52
#define DEMO_KEY_RIGHT 0xff53
#define DEMO_KEY_DOWN 0xff54
#define DEMO_KEY_UNKNOWN 0x0000
#define DEMO_KEY_ESCAPE 0xff1b
#define DEMO_KEY_LEFT 0xff51
#define DEMO_KEY_UP 0xff52
#define DEMO_KEY_RIGHT 0xff53
#define DEMO_KEY_DOWN 0xff54
#define DEMO_KEY_KP_ADD 0xffab
#define DEMO_KEY_KP_SUBTRACT 0xffad
struct demo_vec3
{
@@ -103,6 +106,11 @@ struct demo_matrix
float m[4][4];
};
struct demo_patch
{
uint16_t p[4][4];
};
struct demo_swapchain_desc
{
unsigned int width;
@@ -120,6 +128,36 @@ static inline void demo_vec3_set(struct demo_vec3 *v, float x, float y, float z)
v->z = z;
}
static inline void demo_vec3_subtract(struct demo_vec3 *v, const struct demo_vec3 *a, const struct demo_vec3 *b)
{
demo_vec3_set(v, a->x - b->x, a->y - b->y, a->z - b->z);
}
static inline float demo_vec3_dot(const struct demo_vec3 *a, const struct demo_vec3 *b)
{
return a->x * b->x + a->y * b->y + a->z * b->z;
}
static inline float demo_vec3_length(const struct demo_vec3 *v)
{
return sqrtf(demo_vec3_dot(v, v));
}
static inline void demo_vec3_scale(struct demo_vec3 *v, const struct demo_vec3 *a, float s)
{
demo_vec3_set(v, a->x * s, a->y * s, a->z *s);
}
static inline void demo_vec3_normalise(struct demo_vec3 *v, const struct demo_vec3 *a)
{
demo_vec3_scale(v, a, 1.0f / demo_vec3_length(a));
}
static inline void demo_vec3_cross(struct demo_vec3 *v, const struct demo_vec3 *a, const struct demo_vec3 *b)
{
demo_vec3_set(v, a->y * b->z - a->z * b->y, a->z * b->x - a->x * b->z, a->x * b->y - a->y * b->x);
}
static inline void demo_vec4_set(struct demo_vec4 *v, float x, float y, float z, float w)
{
v->x = x;
@@ -128,6 +166,27 @@ static inline void demo_vec4_set(struct demo_vec4 *v, float x, float y, float z,
v->w = w;
}
static inline void demo_matrix_look_at_rh(struct demo_matrix *m, const struct demo_vec3 *eye,
const struct demo_vec3 *ref, const struct demo_vec3 *up)
{
struct demo_vec3 f, s, t, u;
demo_vec3_subtract(&f, eye, ref);
demo_vec3_normalise(&f, &f);
demo_vec3_cross(&s, up, &f);
demo_vec3_normalise(&s, &s);
demo_vec3_cross(&u, &f, &s);
demo_vec3_set(&t, demo_vec3_dot(&s, eye), demo_vec3_dot(&u, eye), demo_vec3_dot(&f, eye));
*m = (struct demo_matrix)
{{
{ s.x, u.x, f.x, 0.0f},
{ s.y, u.y, f.y, 0.0f},
{ s.z, u.z, f.z, 0.0f},
{-t.x, -t.y, -t.z, 1.0f},
}};
}
static inline void demo_matrix_multiply(struct demo_matrix *out,
const struct demo_matrix *a, const struct demo_matrix *b)
{

View File

@@ -176,12 +176,16 @@ static demo_key demo_key_from_nsevent(id event)
{
enum vkey
{
kVK_ANSI_A = 0x00,
kVK_Escape = 0x35,
kVK_LeftArrow = 0x7b,
kVK_RightArrow = 0x7c,
kVK_DownArrow = 0x7d,
kVK_UpArrow = 0x7e,
kVK_ANSI_A = 0x00,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_Minus = 0x1b,
kVK_Escape = 0x35,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadMinus = 0x4e,
kVK_LeftArrow = 0x7b,
kVK_RightArrow = 0x7c,
kVK_DownArrow = 0x7d,
kVK_UpArrow = 0x7e,
} vkey;
size_t i;
@@ -192,12 +196,16 @@ static demo_key demo_key_from_nsevent(id event)
}
lookup[] =
{
{kVK_ANSI_A, 'a'},
{kVK_Escape, DEMO_KEY_ESCAPE},
{kVK_LeftArrow, DEMO_KEY_LEFT},
{kVK_RightArrow, DEMO_KEY_RIGHT},
{kVK_UpArrow, DEMO_KEY_UP},
{kVK_DownArrow, DEMO_KEY_DOWN},
{kVK_ANSI_A, 'a'},
{kVK_ANSI_Equal, '='},
{kVK_ANSI_Minus, '-'},
{kVK_Escape, DEMO_KEY_ESCAPE},
{kVK_ANSI_KeypadPlus, DEMO_KEY_KP_ADD},
{kVK_ANSI_KeypadMinus, DEMO_KEY_KP_SUBTRACT},
{kVK_LeftArrow, DEMO_KEY_LEFT},
{kVK_RightArrow, DEMO_KEY_RIGHT},
{kVK_DownArrow, DEMO_KEY_DOWN},
{kVK_UpArrow, DEMO_KEY_UP},
};
vkey = NSEvent_keyCode(event);

View File

@@ -127,11 +127,15 @@ static demo_key demo_key_from_win32_vkey(DWORD vkey)
}
lookup[] =
{
{VK_ESCAPE, DEMO_KEY_ESCAPE},
{VK_LEFT, DEMO_KEY_LEFT},
{VK_RIGHT, DEMO_KEY_RIGHT},
{VK_UP, DEMO_KEY_UP},
{VK_DOWN, DEMO_KEY_DOWN},
{VK_OEM_MINUS, '-'},
{VK_OEM_PLUS, '='},
{VK_ESCAPE, DEMO_KEY_ESCAPE},
{VK_LEFT, DEMO_KEY_LEFT},
{VK_UP, DEMO_KEY_UP},
{VK_RIGHT, DEMO_KEY_RIGHT},
{VK_DOWN, DEMO_KEY_DOWN},
{VK_ADD, DEMO_KEY_KP_ADD},
{VK_SUBTRACT, DEMO_KEY_KP_SUBTRACT},
};
unsigned int i;

View File

@@ -45,7 +45,6 @@
#include <sys/time.h>
#include <assert.h>
#include <stdio.h>
#include <math.h>
#include "demo.h"
DEMO_EMBED(gears_hlsl, "gears.hlsl");

577
demos/teapot.c Normal file

File diff suppressed because it is too large Load Diff

129
demos/teapot.h Normal file
View File

@@ -0,0 +1,129 @@
/*
* Copyright 2025 Henri Verbeet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Teapot data adapted from freeglut's fg_teapot_data.h with the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The data is of course ultimately derived from Martin Newell's famous
* teapot, also known as the Utah teapot.
*/
/* Rim, body, lid, and bottom data must be rotated along all four quadrants;
* handle and spout data is flipped (negate y values) only. */
static const struct demo_patch teapot_rotate_patches[] =
{
{{{ 0, 1, 2, 3}, { 4, 5, 6, 7}, { 8, 9, 10, 11}, { 12, 13, 14, 15}}}, /* rim */
{{{ 12, 13, 14, 15}, { 16, 17, 18, 19}, { 20, 21, 22, 23}, { 24, 25, 26, 27}}}, /* body */
{{{ 24, 25, 26, 27}, { 28, 29, 30, 31}, { 32, 33, 34, 35}, { 36, 37, 38, 39}}},
{{{ 40, 40, 40, 40}, { 43, 44, 45, 46}, { 47, 47, 47, 47}, { 48, 49, 50, 51}}}, /* lid */
{{{ 48, 49, 50, 51}, { 52, 53, 54, 55}, { 56, 57, 58, 59}, { 60, 61, 62, 63}}},
{{{ 64, 64, 64, 64}, { 65, 66, 67, 68}, { 69, 70, 71, 72}, { 39, 38, 37, 36}}}, /* bottom */
},
teapot_flip_patches[] =
{
{{{ 73, 74, 75, 76}, { 77, 78, 79, 80}, { 81, 82, 83, 84}, { 85, 86, 87, 88}}}, /* handle */
{{{ 85, 86, 87, 88}, { 89, 90, 91, 92}, { 93, 94, 95, 96}, { 97, 98, 99, 100}}},
{{{101, 102, 103, 104}, {105, 106, 107, 108}, {109, 110, 111, 112}, {113, 114, 115, 116}}}, /* spout */
{{{113, 114, 115, 116}, {117, 118, 119, 120}, {121, 122, 123, 124}, {125, 126, 127, 128}}},
};
static const struct demo_vec3 teapot_control_points[] =
{
{ 1.40000f, 0.00000f, 2.40000f}, { 1.40000f, -0.78400f, 2.40000f},
{ 0.78400f, -1.40000f, 2.40000f}, { 0.00000f, -1.40000f, 2.40000f},
{ 1.33750f, 0.00000f, 2.53125f}, { 1.33750f, -0.74900f, 2.53125f},
{ 0.74900f, -1.33750f, 2.53125f}, { 0.00000f, -1.33750f, 2.53125f},
{ 1.43750f, 0.00000f, 2.53125f}, { 1.43750f, -0.80500f, 2.53125f},
{ 0.80500f, -1.43750f, 2.53125f}, { 0.00000f, -1.43750f, 2.53125f},
{ 1.50000f, 0.00000f, 2.40000f}, { 1.50000f, -0.84000f, 2.40000f},
{ 0.84000f, -1.50000f, 2.40000f}, { 0.00000f, -1.50000f, 2.40000f},
{ 1.75000f, 0.00000f, 1.87500f}, { 1.75000f, -0.98000f, 1.87500f},
{ 0.98000f, -1.75000f, 1.87500f}, { 0.00000f, -1.75000f, 1.87500f},
{ 2.00000f, 0.00000f, 1.35000f}, { 2.00000f, -1.12000f, 1.35000f},
{ 1.12000f, -2.00000f, 1.35000f}, { 0.00000f, -2.00000f, 1.35000f},
{ 2.00000f, 0.00000f, 0.90000f}, { 2.00000f, -1.12000f, 0.90000f},
{ 1.12000f, -2.00000f, 0.90000f}, { 0.00000f, -2.00000f, 0.90000f},
{ 2.00000f, 0.00000f, 0.45000f}, { 2.00000f, -1.12000f, 0.45000f},
{ 1.12000f, -2.00000f, 0.45000f}, { 0.00000f, -2.00000f, 0.45000f},
{ 1.50000f, 0.00000f, 0.22500f}, { 1.50000f, -0.84000f, 0.22500f},
{ 0.84000f, -1.50000f, 0.22500f}, { 0.00000f, -1.50000f, 0.22500f},
{ 1.50000f, 0.00000f, 0.15000f}, { 1.50000f, -0.84000f, 0.15000f},
{ 0.84000f, -1.50000f, 0.15000f}, { 0.00000f, -1.50000f, 0.15000f},
{ 0.00000f, 0.00000f, 3.15000f}, { 0.00000f, -0.00200f, 3.15000f},
{ 0.00200f, 0.00000f, 3.15000f}, { 0.80000f, 0.00000f, 3.15000f},
{ 0.80000f, -0.45000f, 3.15000f}, { 0.45000f, -0.80000f, 3.15000f},
{ 0.00000f, -0.80000f, 3.15000f}, { 0.00000f, 0.00000f, 2.85000f},
{ 0.20000f, 0.00000f, 2.70000f}, { 0.20000f, -0.11200f, 2.70000f},
{ 0.11200f, -0.20000f, 2.70000f}, { 0.00000f, -0.20000f, 2.70000f},
{ 0.40000f, 0.00000f, 2.55000f}, { 0.40000f, -0.22400f, 2.55000f},
{ 0.22400f, -0.40000f, 2.55000f}, { 0.00000f, -0.40000f, 2.55000f},
{ 1.30000f, 0.00000f, 2.55000f}, { 1.30000f, -0.72800f, 2.55000f},
{ 0.72800f, -1.30000f, 2.55000f}, { 0.00000f, -1.30000f, 2.55000f},
{ 1.30000f, 0.00000f, 2.40000f}, { 1.30000f, -0.72800f, 2.40000f},
{ 0.72800f, -1.30000f, 2.40000f}, { 0.00000f, -1.30000f, 2.40000f},
{ 0.00000f, 0.00000f, 0.00000f}, { 0.00000f, -1.42500f, 0.00000f},
{ 0.79800f, -1.42500f, 0.00000f}, { 1.42500f, -0.79800f, 0.00000f},
{ 1.42500f, 0.00000f, 0.00000f}, { 0.00000f, -1.50000f, 0.07500f},
{ 0.84000f, -1.50000f, 0.07500f}, { 1.50000f, -0.84000f, 0.07500f},
{ 1.50000f, 0.00000f, 0.07500f}, {-1.60000f, 0.00000f, 2.02500f},
{-1.60000f, -0.30000f, 2.02500f}, {-1.50000f, -0.30000f, 2.25000f},
{-1.50000f, 0.00000f, 2.25000f}, {-2.30000f, 0.00000f, 2.02500f},
{-2.30000f, -0.30000f, 2.02500f}, {-2.50000f, -0.30000f, 2.25000f},
{-2.50000f, 0.00000f, 2.25000f}, {-2.70000f, 0.00000f, 2.02500f},
{-2.70000f, -0.30000f, 2.02500f}, {-3.00000f, -0.30000f, 2.25000f},
{-3.00000f, 0.00000f, 2.25000f}, {-2.70000f, 0.00000f, 1.80000f},
{-2.70000f, -0.30000f, 1.80000f}, {-3.00000f, -0.30000f, 1.80000f},
{-3.00000f, 0.00000f, 1.80000f}, {-2.70000f, 0.00000f, 1.57500f},
{-2.70000f, -0.30000f, 1.57500f}, {-3.00000f, -0.30000f, 1.35000f},
{-3.00000f, 0.00000f, 1.35000f}, {-2.50000f, 0.00000f, 1.12500f},
{-2.50000f, -0.30000f, 1.12500f}, {-2.65000f, -0.30000f, 0.93750f},
{-2.65000f, 0.00000f, 0.93750f}, {-2.00000f, 0.00000f, 0.90000f},
{-2.00000f, -0.30000f, 0.90000f}, {-1.90000f, -0.30000f, 0.60000f},
{-1.90000f, 0.00000f, 0.60000f}, { 1.70000f, 0.00000f, 1.42500f},
{ 1.70000f, -0.66000f, 1.42500f}, { 1.70000f, -0.66000f, 0.60000f},
{ 1.70000f, 0.00000f, 0.60000f}, { 2.60000f, 0.00000f, 1.42500f},
{ 2.60000f, -0.66000f, 1.42500f}, { 3.10000f, -0.66000f, 0.82500f},
{ 3.10000f, 0.00000f, 0.82500f}, { 2.30000f, 0.00000f, 2.10000f},
{ 2.30000f, -0.25000f, 2.10000f}, { 2.40000f, -0.25000f, 2.02500f},
{ 2.40000f, 0.00000f, 2.02500f}, { 2.70000f, 0.00000f, 2.40000f},
{ 2.70000f, -0.25000f, 2.40000f}, { 3.30000f, -0.25000f, 2.40000f},
{ 3.30000f, 0.00000f, 2.40000f}, { 2.80000f, 0.00000f, 2.47500f},
{ 2.80000f, -0.25000f, 2.47500f}, { 3.52500f, -0.25000f, 2.49375f},
{ 3.52500f, 0.00000f, 2.49375f}, { 2.90000f, 0.00000f, 2.47500f},
{ 2.90000f, -0.15000f, 2.47500f}, { 3.45000f, -0.15000f, 2.51250f},
{ 3.45000f, 0.00000f, 2.51250f}, { 2.80000f, 0.00000f, 2.40000f},
{ 2.80000f, -0.15000f, 2.40000f}, { 3.20000f, -0.15000f, 2.40000f},
{ 3.20000f, 0.00000f, 2.40000f}
};

121
demos/teapot.hlsl Normal file
View File

@@ -0,0 +1,121 @@
/*
* Copyright 2025 Henri Verbeet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
cbuffer teapot_cb : register(b0)
{
float4x4 mvp_matrix;
float level;
};
struct control_point
{
float4 position : SV_POSITION;
};
struct patch_constant_data
{
float edges[4] : SV_TessFactor;
float inside[2] : SV_InsideTessFactor;
};
struct ps_in
{
float4 position : SV_POSITION;
};
float4 vs_main(float4 position : POSITION, uint id : SV_InstanceID) : SV_POSITION
{
/* Mirror/flip patches based on the instance ID. */
position.w = -1.0;
if (id & 1)
position.yw = -position.yw;
if (id & 2)
position.xw = -position.xw;
return position;
}
struct patch_constant_data patch_constant(InputPatch<control_point, 16> input)
{
struct patch_constant_data output;
output.edges[0] = level;
output.edges[1] = level;
output.edges[2] = level;
output.edges[3] = level;
output.inside[0] = level;
output.inside[1] = level;
return output;
}
[domain("quad")]
[outputcontrolpoints(16)]
[outputtopology("triangle_ccw")]
[partitioning("integer")]
[patchconstantfunc("patch_constant")]
struct control_point hs_main(InputPatch<control_point, 16> input, uint i : SV_OutputControlPointID)
{
/* Reorder mirrored/flipped control points. */
if (input[0].position.w < 0.0)
{
uint u = i % 4, v = i / 4;
return input[v * 4 + (3 - u)];
}
return input[i];
}
float3 eval_quadratic(float3 p0, float3 p1, float3 p2, float t)
{
return lerp(lerp(p0, p1, t), lerp(p1, p2, t), t);
}
float3 eval_cubic(float3 p0, float3 p1, float3 p2, float3 p3, float t)
{
return lerp(eval_quadratic(p0, p1, p2, t),
eval_quadratic(p1, p2, p3, t), t);
}
struct ps_in eval_patch(float2 t, float4 p[16])
{
float3 position, q[4];
struct ps_in o;
q[0] = eval_cubic(p[0].xyz, p[4].xyz, p[8].xyz, p[12].xyz, t.y);
q[1] = eval_cubic(p[1].xyz, p[5].xyz, p[9].xyz, p[13].xyz, t.y);
q[2] = eval_cubic(p[2].xyz, p[6].xyz, p[10].xyz, p[14].xyz, t.y);
q[3] = eval_cubic(p[3].xyz, p[7].xyz, p[11].xyz, p[15].xyz, t.y);
position = eval_cubic(q[0], q[1], q[2], q[3], t.x);
o.position = mul(mvp_matrix, float4(position, 1.0));
return o;
}
[domain("quad")]
struct ps_in ds_main(struct patch_constant_data input,
float2 tess_coord : SV_DomainLocation, const OutputPatch<control_point, 16> patch)
{
return eval_patch(tess_coord, patch);
}
float4 ps_main(struct ps_in i) : SV_TARGET
{
return float4(1.0, 0.69, 0.0, 1.0);
}