• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**************************************************************************
2 *
3 * Copyright 2010 Luca Barbieri
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#define INPUT_PATCH_SIZE 3
28#define OUTPUT_PATCH_SIZE 3
29
30static const float PI = 3.141592653589793238462643f;
31
32cbuffer cb_frame
33{
34	float4x4 model;
35	float4x4 view_proj;
36	float disp_scale;
37	float disp_freq;
38	float tess_factor;
39};
40
41struct IA2VS
42{
43	float3 position : POSITION;
44};
45
46struct VS2HS
47{
48	float3 position : POSITION;
49};
50
51VS2HS vs(IA2VS input)
52{
53	VS2HS result;
54	result.position = input.position;
55	return result;
56}
57
58struct HS2DS_PATCH
59{
60	float tessouter[3] : SV_TessFactor;
61	float tessinner[1] : SV_InsideTessFactor;
62};
63
64struct HS2DS
65{
66	float3 position : POSITION;
67};
68
69HS2DS_PATCH hs_patch(InputPatch<VS2HS, INPUT_PATCH_SIZE> ip)
70{
71	HS2DS_PATCH result;
72
73	result.tessouter[0] = result.tessouter[1] = result.tessouter[2]
74		= result.tessinner[0] = tess_factor;
75	return result;
76}
77
78[domain("tri")]
79[partitioning("fractional_even")]
80[outputtopology("triangle_cw")]
81[outputcontrolpoints(OUTPUT_PATCH_SIZE)]
82[patchconstantfunc("hs_patch")]
83HS2DS hs(InputPatch<VS2HS, INPUT_PATCH_SIZE> p, uint i : SV_OutputControlPointID)
84{
85	HS2DS result;
86	result.position = p[i].position;
87	return result;
88}
89
90struct DS2PS
91{
92	float4 position : SV_POSITION;
93	float3 objpos : OBJPOS;
94	// float3 worldpos : WORLDPOS;
95	float3 objnormal : OBJNORMAL;
96	float3 worldnormal : WORLDNORMAL;
97};
98
99float3 dnormf_dt(float3 f, float3 dfdt)
100{
101	float ff = dot(f, f);
102	return (ff * dfdt - dot(f, dfdt) * f) / (ff * sqrt(ff));
103}
104
105float3 map(float3 p, float3 q, float3 r, float3 k)
106{
107	return normalize(p * k.x + q * k.y + r * k.z);
108}
109
110float3 dmap_du(float3 p, float3 q, float3 r, float3 k)
111{
112	return dnormf_dt(p * k.x + q * k.y + r * k.z, p);
113}
114
115float dispf(float v)
116{
117	return cos(v * disp_freq);
118}
119
120float ddispf(float v)
121{
122	return -sin(v * disp_freq) * disp_freq;
123}
124
125float disp(float3 k)
126{
127	return dispf(k.x) * dispf(k.y) * dispf(k.z);
128}
129
130float ddisp_du(float3 k)
131{
132	return ddispf(k.x) * dispf(k.y) * dispf(k.z);
133}
134
135float3 ddisp(float3 k)
136{
137	float3 f = float3(dispf(k.x), dispf(k.y), dispf(k.z));
138	return float3(ddispf(k.x) * f.y * f.z, ddispf(k.y) * f.z * f.x, ddispf(k.z) * f.x * f.y);
139}
140
141[domain("tri")]
142DS2PS ds(HS2DS_PATCH input,
143                    float3 k : SV_DomainLocation,
144                    const OutputPatch<HS2DS, OUTPUT_PATCH_SIZE> patch)
145{
146	DS2PS result;
147
148	float3 s = map(patch[0].position, patch[1].position, patch[2].position, k);
149	float3 d = 1.0 + disp(s) * disp_scale;
150	result.objpos = s * d;
151	result.objpos /= (1.0 + disp_scale);
152	float3 worldpos = mul(model, float4(result.objpos, 1.0f));
153	result.position = mul(view_proj, float4(worldpos, 1.0f));
154
155	float3 dd = ddisp(s) * disp_scale;
156
157	/*
158	float3 ds_du = dmap_du(patch[0].position, patch[1].position, patch[2].position, k);
159	float3 ds_dv = dmap_du(patch[1].position, patch[2].position, patch[0].position, k.yzx);
160	float3 ds_dw = dmap_du(patch[2].position, patch[0].position, patch[1].position, k.zxy);
161
162	float3 ds_dU = ds_du - ds_dw;
163	float3 ds_dV = ds_dv - ds_dw;
164
165	float3 dc_dU = s * dot(dd, ds_dU) + ds_dU * d;
166	float3 dc_dV = s * dot(dd, ds_dV) + ds_dV * d;
167	*/
168
169	// this should be faster
170	float3 _u = normalize((abs(s.x) > abs(s.y)) ? float3(-s.z, 0, s.x) : float3(0, -s.z, s.y));
171	float3 _v = normalize(cross(s, _u));
172	float3 dc_dU = s * dot(dd, _u) + _u * d;
173	float3 dc_dV = s * dot(dd, _v) + _v * d;
174
175	result.objnormal = normalize(cross(dc_dU, dc_dV));
176	result.worldnormal = mul(model, result.objnormal);
177	return result;
178}
179
180float4 ps(DS2PS input) : SV_TARGET
181{
182	float3 pseudoambient = float3(0.4, 0.4, 0.6);
183	float3 diffuse = float3(0.6, 0.6, 0.4);
184	float3 light = normalize(float3(0, 1, -1));
185
186	float4 r;
187//	r.xyz = normalize(input.objpos + 2 * input.objnormal);
188	r.xyz = pseudoambient * saturate(dot(normalize(input.objnormal), normalize(input.objpos)));
189	r.xyz += saturate(dot(light, normalize(input.worldnormal))) * diffuse;
190
191	r.w = 1;
192	return r;
193}
194