fix all
This commit is contained in:
parent
eec406bb36
commit
af2009710a
2 changed files with 186 additions and 115 deletions
|
@ -49,6 +49,7 @@ struct DirectXRenderPipelines {
|
||||||
shadow_pipeline: PipelineState,
|
shadow_pipeline: PipelineState,
|
||||||
quad_pipeline: PipelineState,
|
quad_pipeline: PipelineState,
|
||||||
paths_pipeline: PipelineState,
|
paths_pipeline: PipelineState,
|
||||||
|
paths_indirect_draw_buffer: ID3D11Buffer,
|
||||||
underline_pipeline: PipelineState,
|
underline_pipeline: PipelineState,
|
||||||
mono_sprites: PipelineState,
|
mono_sprites: PipelineState,
|
||||||
poly_sprites: PipelineState,
|
poly_sprites: PipelineState,
|
||||||
|
@ -61,6 +62,14 @@ struct DirectXGlobalElements {
|
||||||
blend_state_for_pr: ID3D11BlendState,
|
blend_state_for_pr: ID3D11BlendState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct DrawInstancedIndirectArgs {
|
||||||
|
vertex_count_per_instance: u32,
|
||||||
|
instance_count: u32,
|
||||||
|
start_vertex_location: u32,
|
||||||
|
start_instance_location: u32,
|
||||||
|
}
|
||||||
|
|
||||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||||
// struct DirectComposition {
|
// struct DirectComposition {
|
||||||
// comp_device: IDCompositionDevice,
|
// comp_device: IDCompositionDevice,
|
||||||
|
@ -122,6 +131,7 @@ impl DirectXRenderer {
|
||||||
[0.0, 0.0, 0.0, 0.0],
|
[0.0, 0.0, 0.0, 0.0],
|
||||||
&self.globals.blend_state,
|
&self.globals.blend_state,
|
||||||
)?;
|
)?;
|
||||||
|
println!("--> Drawing scene");
|
||||||
for batch in scene.batches() {
|
for batch in scene.batches() {
|
||||||
match batch {
|
match batch {
|
||||||
PrimitiveBatch::Shadows(shadows) => self.draw_shadows(shadows),
|
PrimitiveBatch::Shadows(shadows) => self.draw_shadows(shadows),
|
||||||
|
@ -273,41 +283,64 @@ impl DirectXRenderer {
|
||||||
if paths.is_empty() {
|
if paths.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
println!("Drawing {} paths", paths.len());
|
||||||
let mut vertices = Vec::new();
|
let mut vertices = Vec::new();
|
||||||
let mut sprites = Vec::with_capacity(paths.len());
|
let mut sprites = Vec::with_capacity(paths.len());
|
||||||
for path in paths {
|
let mut draw_indirect_commands = Vec::with_capacity(paths.len());
|
||||||
let tile = &path_tiles[&path.id];
|
let mut start_vertex_location = 0;
|
||||||
let texture_view = self.atlas.get_texture_view(tile.texture_id);
|
for (i, path) in paths.iter().enumerate() {
|
||||||
let origin = path.bounds.intersect(&path.content_mask.bounds).origin;
|
draw_indirect_commands.push(DrawInstancedIndirectArgs {
|
||||||
let sprites = [PathSprite {
|
vertex_count_per_instance: path.vertices.len() as u32,
|
||||||
bounds: Bounds {
|
instance_count: 1,
|
||||||
origin: origin.map(|p| p.floor()),
|
start_vertex_location,
|
||||||
size: tile.bounds.size.map(Into::into),
|
start_instance_location: i as u32,
|
||||||
|
});
|
||||||
|
start_vertex_location += path.vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.extend(path.vertices.iter().map(|v| PathVertex {
|
||||||
|
xy_position: v.xy_position,
|
||||||
|
content_mask: ContentMask {
|
||||||
|
bounds: path.content_mask.bounds,
|
||||||
},
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
sprites.push(PathSprite {
|
||||||
|
bounds: path.bounds,
|
||||||
color: path.color,
|
color: path.color,
|
||||||
tile: (*tile).clone(),
|
});
|
||||||
}];
|
}
|
||||||
update_buffer_capacity(
|
|
||||||
&self.pipelines.paths_pipeline,
|
update_buffer_capacity(
|
||||||
std::mem::size_of::<PathSprite>(),
|
&self.pipelines.paths_pipeline,
|
||||||
1,
|
std::mem::size_of::<PathSprite>(),
|
||||||
&self.devices.device,
|
sprites.len(),
|
||||||
)
|
&self.devices.device,
|
||||||
.map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
|
)
|
||||||
update_buffer(
|
.map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
|
||||||
|
update_buffer(
|
||||||
|
&self.devices.device_context,
|
||||||
|
&self.pipelines.paths_pipeline.buffer,
|
||||||
|
&sprites,
|
||||||
|
)?;
|
||||||
|
update_indirect_buffer(
|
||||||
|
&self.devices.device_context,
|
||||||
|
&self.pipelines.paths_indirect_draw_buffer,
|
||||||
|
&draw_indirect_commands,
|
||||||
|
)?;
|
||||||
|
prepare_indirect_draws(
|
||||||
|
&self.devices.device_context,
|
||||||
|
&self.pipelines.paths_pipeline,
|
||||||
|
&self.context.viewport,
|
||||||
|
&self.globals.global_params_buffer,
|
||||||
|
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
for i in 0..paths.len() {
|
||||||
|
draw_indirect(
|
||||||
&self.devices.device_context,
|
&self.devices.device_context,
|
||||||
&self.pipelines.paths_pipeline.buffer,
|
&self.pipelines.paths_indirect_draw_buffer,
|
||||||
&sprites,
|
(i * std::mem::size_of::<DrawInstancedIndirectArgs>()) as u32,
|
||||||
)?;
|
);
|
||||||
draw_with_texture(
|
|
||||||
&self.devices.device_context,
|
|
||||||
&self.pipelines.paths_pipeline,
|
|
||||||
&texture_view,
|
|
||||||
&self.context.viewport,
|
|
||||||
&self.globals.global_params_buffer,
|
|
||||||
&self.globals.sampler,
|
|
||||||
1,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -484,11 +517,13 @@ impl DirectXRenderPipelines {
|
||||||
std::mem::size_of::<PolychromeSprite>(),
|
std::mem::size_of::<PolychromeSprite>(),
|
||||||
32,
|
32,
|
||||||
)?;
|
)?;
|
||||||
|
let paths_indirect_draw_buffer = create_indirect_draw_buffer(device, 32)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
shadow_pipeline,
|
shadow_pipeline,
|
||||||
quad_pipeline,
|
quad_pipeline,
|
||||||
paths_pipeline,
|
paths_pipeline,
|
||||||
|
paths_indirect_draw_buffer,
|
||||||
underline_pipeline,
|
underline_pipeline,
|
||||||
mono_sprites,
|
mono_sprites,
|
||||||
poly_sprites,
|
poly_sprites,
|
||||||
|
@ -884,6 +919,27 @@ fn create_buffer_view(
|
||||||
Ok([view])
|
Ok([view])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_indirect_draw_buffer(device: &ID3D11Device, buffer_size: u32) -> Result<ID3D11Buffer> {
|
||||||
|
// let desc = D3D11_BUFFER_DESC {
|
||||||
|
// ByteWidth: std::mem::size_of::<DrawInstancedIndirectArgs>() as u32 * buffer_size,
|
||||||
|
// Usage: D3D11_USAGE_DYNAMIC,
|
||||||
|
// BindFlags: D3D11_BIND_INDIRECT_DRAW.0 as u32,
|
||||||
|
// MiscFlags: D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS.0 as u32,
|
||||||
|
// ..Default::default()
|
||||||
|
// };
|
||||||
|
let desc = D3D11_BUFFER_DESC {
|
||||||
|
ByteWidth: std::mem::size_of::<DrawInstancedIndirectArgs>() as u32 * buffer_size,
|
||||||
|
Usage: D3D11_USAGE_DYNAMIC,
|
||||||
|
BindFlags: D3D11_BIND_INDEX_BUFFER.0 as u32,
|
||||||
|
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
|
||||||
|
MiscFlags: D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS.0 as u32,
|
||||||
|
StructureByteStride: std::mem::size_of::<DrawInstancedIndirectArgs>() as u32,
|
||||||
|
};
|
||||||
|
let mut buffer = None;
|
||||||
|
unsafe { device.CreateBuffer(&desc, None, Some(&mut buffer)) }?;
|
||||||
|
Ok(buffer.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
fn update_global_params(
|
fn update_global_params(
|
||||||
device_context: &ID3D11DeviceContext,
|
device_context: &ID3D11DeviceContext,
|
||||||
buffer: &[Option<ID3D11Buffer>; 1],
|
buffer: &[Option<ID3D11Buffer>; 1],
|
||||||
|
@ -964,6 +1020,50 @@ fn update_buffer<T>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_indirect_buffer(
|
||||||
|
device_context: &ID3D11DeviceContext,
|
||||||
|
buffer: &ID3D11Buffer,
|
||||||
|
data: &[DrawInstancedIndirectArgs],
|
||||||
|
) -> Result<()> {
|
||||||
|
unsafe {
|
||||||
|
let mut dest = std::mem::zeroed();
|
||||||
|
device_context.Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut dest))?;
|
||||||
|
std::ptr::copy_nonoverlapping(data.as_ptr(), dest.pData as _, data.len());
|
||||||
|
device_context.Unmap(buffer, 0);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_indirect_draws(
|
||||||
|
device_context: &ID3D11DeviceContext,
|
||||||
|
pipeline: &PipelineState,
|
||||||
|
viewport: &[D3D11_VIEWPORT],
|
||||||
|
global_params: &[Option<ID3D11Buffer>],
|
||||||
|
topology: D3D_PRIMITIVE_TOPOLOGY,
|
||||||
|
) -> Result<()> {
|
||||||
|
unsafe {
|
||||||
|
device_context.VSSetShaderResources(1, Some(&pipeline.view));
|
||||||
|
device_context.PSSetShaderResources(1, Some(&pipeline.view));
|
||||||
|
device_context.IASetPrimitiveTopology(topology);
|
||||||
|
device_context.RSSetViewports(Some(viewport));
|
||||||
|
device_context.VSSetShader(&pipeline.vertex, None);
|
||||||
|
device_context.PSSetShader(&pipeline.fragment, None);
|
||||||
|
device_context.VSSetConstantBuffers(0, Some(global_params));
|
||||||
|
device_context.PSSetConstantBuffers(0, Some(global_params));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_indirect(
|
||||||
|
device_context: &ID3D11DeviceContext,
|
||||||
|
indirect_draw_buffer: &ID3D11Buffer,
|
||||||
|
offset: u32,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
device_context.DrawInstancedIndirect(indirect_draw_buffer, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn draw_normal(
|
fn draw_normal(
|
||||||
device_context: &ID3D11DeviceContext,
|
device_context: &ID3D11DeviceContext,
|
||||||
pipeline: &PipelineState,
|
pipeline: &PipelineState,
|
||||||
|
@ -1026,6 +1126,7 @@ mod shader_resources {
|
||||||
use windows_core::{HSTRING, PCSTR};
|
use windows_core::{HSTRING, PCSTR};
|
||||||
|
|
||||||
pub(super) fn build_shader_blob(entry: &str, target: &str) -> Result<ID3DBlob> {
|
pub(super) fn build_shader_blob(entry: &str, target: &str) -> Result<ID3DBlob> {
|
||||||
|
println!("Building shader: {}", entry);
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut entry = entry.to_owned();
|
let mut entry = entry.to_owned();
|
||||||
let mut target = target.to_owned();
|
let mut target = target.to_owned();
|
||||||
|
@ -1039,6 +1140,11 @@ mod shader_resources {
|
||||||
target.push_str("\0");
|
target.push_str("\0");
|
||||||
let entry_point = PCSTR::from_raw(entry.as_ptr());
|
let entry_point = PCSTR::from_raw(entry.as_ptr());
|
||||||
let target_cstr = PCSTR::from_raw(target.as_ptr());
|
let target_cstr = PCSTR::from_raw(target.as_ptr());
|
||||||
|
println!(
|
||||||
|
"Compiling shader: {} with target: {}",
|
||||||
|
entry_point.display(),
|
||||||
|
target_cstr.display()
|
||||||
|
);
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let compile_flag = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
let compile_flag = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
@ -1054,6 +1160,7 @@ mod shader_resources {
|
||||||
&mut compile_blob,
|
&mut compile_blob,
|
||||||
Some(&mut error_blob),
|
Some(&mut error_blob),
|
||||||
);
|
);
|
||||||
|
println!("Shader compile result: {:?}", ret);
|
||||||
if ret.is_err() {
|
if ret.is_err() {
|
||||||
let Some(error_blob) = error_blob else {
|
let Some(error_blob) = error_blob else {
|
||||||
return Err(anyhow::anyhow!("{ret:?}"));
|
return Err(anyhow::anyhow!("{ret:?}"));
|
||||||
|
@ -1064,10 +1171,9 @@ mod shader_resources {
|
||||||
string_len,
|
string_len,
|
||||||
string_len,
|
string_len,
|
||||||
);
|
);
|
||||||
return Err(anyhow::anyhow!(
|
let error_string = String::from_utf8_lossy(&error_string_encode);
|
||||||
"Compile error: {}",
|
println!("Shader compile error: {}", error_string);
|
||||||
String::from_utf8_lossy(&error_string_encode)
|
return Err(anyhow::anyhow!("Compile error: {}", error_string));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Ok(compile_blob.unwrap())
|
Ok(compile_blob.unwrap())
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,28 +81,36 @@ struct TransformationMatrix {
|
||||||
static const float M_PI_F = 3.141592653f;
|
static const float M_PI_F = 3.141592653f;
|
||||||
static const float3 GRAYSCALE_FACTORS = float3(0.2126f, 0.7152f, 0.0722f);
|
static const float3 GRAYSCALE_FACTORS = float3(0.2126f, 0.7152f, 0.0722f);
|
||||||
|
|
||||||
float4 to_device_position(float2 unit_vertex, Bounds bounds) {
|
float4 to_device_position_impl(float2 position) {
|
||||||
float2 position = unit_vertex * bounds.size + bounds.origin;
|
|
||||||
float2 device_position = position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
float2 device_position = position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
||||||
return float4(device_position, 0., 1.);
|
return float4(device_position, 0., 1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 distance_from_clip_rect(float2 unit_vertex, Bounds bounds, Bounds clip_bounds) {
|
float4 to_device_position(float2 unit_vertex, Bounds bounds) {
|
||||||
float2 position = unit_vertex * bounds.size + bounds.origin;
|
float2 position = unit_vertex * bounds.size + bounds.origin;
|
||||||
|
return to_device_position_impl(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 distance_from_clip_rect_impl(float2 position, Bounds clip_bounds) {
|
||||||
return float4(position.x - clip_bounds.origin.x,
|
return float4(position.x - clip_bounds.origin.x,
|
||||||
clip_bounds.origin.x + clip_bounds.size.x - position.x,
|
clip_bounds.origin.x + clip_bounds.size.x - position.x,
|
||||||
position.y - clip_bounds.origin.y,
|
position.y - clip_bounds.origin.y,
|
||||||
clip_bounds.origin.y + clip_bounds.size.y - position.y);
|
clip_bounds.origin.y + clip_bounds.size.y - position.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float4 distance_from_clip_rect(float2 unit_vertex, Bounds bounds, Bounds clip_bounds) {
|
||||||
|
float2 position = unit_vertex * bounds.size + bounds.origin;
|
||||||
|
return distance_from_clip_rect_impl(position, clip_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert linear RGB to sRGB
|
// Convert linear RGB to sRGB
|
||||||
float3 linear_to_srgb(float3 color) {
|
float3 linear_to_srgb(float3 color) {
|
||||||
return pow(color, float3(2.2));
|
return pow(color, float3(2.2, 2.2, 2.2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert sRGB to linear RGB
|
// Convert sRGB to linear RGB
|
||||||
float3 srgb_to_linear(float3 color) {
|
float3 srgb_to_linear(float3 color) {
|
||||||
return pow(color, float3(1.0 / 2.2));
|
return pow(color, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hsla to linear RGBA conversion.
|
/// Hsla to linear RGBA conversion.
|
||||||
|
@ -268,23 +276,23 @@ float quad_sdf(float2 pt, Bounds bounds, Corners corner_radii) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GradientColor prepare_gradient_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1) {
|
GradientColor prepare_gradient_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1) {
|
||||||
GradientColor res;
|
GradientColor output;
|
||||||
if (tag == 0) {
|
if (tag == 0) {
|
||||||
res.solid = hsla_to_rgba(solid);
|
output.solid = hsla_to_rgba(solid);
|
||||||
} else if (tag == 1) {
|
} else if (tag == 1) {
|
||||||
res.color0 = hsla_to_rgba(color0);
|
output.color0 = hsla_to_rgba(color0);
|
||||||
res.color1 = hsla_to_rgba(color1);
|
output.color1 = hsla_to_rgba(color1);
|
||||||
|
|
||||||
// Prepare color space in vertex for avoid conversion
|
// Prepare color space in vertex for avoid conversion
|
||||||
// in fragment shader for performance reasons
|
// in fragment shader for performance reasons
|
||||||
if (color_space == 1) {
|
if (color_space == 1) {
|
||||||
// Oklab
|
// Oklab
|
||||||
res.color0 = srgb_to_oklab(res.color0);
|
output.color0 = srgb_to_oklab(output.color0);
|
||||||
res.color1 = srgb_to_oklab(res.color1);
|
output.color1 = srgb_to_oklab(output.color1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 gradient_color(Background background,
|
float4 gradient_color(Background background,
|
||||||
|
@ -456,22 +464,21 @@ struct Quad {
|
||||||
|
|
||||||
struct QuadVertexOutput {
|
struct QuadVertexOutput {
|
||||||
float4 position: SV_Position;
|
float4 position: SV_Position;
|
||||||
// float4 border_color: COLOR0;
|
nointerpolation float4 border_color: COLOR0;
|
||||||
float4 border_color: FLAT;
|
nointerpolation uint quad_id: TEXCOORD0;
|
||||||
uint quad_id: FLAT;
|
nointerpolation float4 background_solid: COLOR1;
|
||||||
float4 background_solid: FLAT;
|
nointerpolation float4 background_color0: COLOR2;
|
||||||
float4 background_color0: FLAT;
|
nointerpolation float4 background_color1: COLOR3;
|
||||||
float4 background_color1: FLAT;
|
|
||||||
float4 clip_distance: SV_ClipDistance;
|
float4 clip_distance: SV_ClipDistance;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QuadFragmentInput {
|
struct QuadFragmentInput {
|
||||||
uint quad_id: FLAT;
|
nointerpolation uint quad_id: TEXCOORD0;
|
||||||
float4 position: SV_Position;
|
float4 position: SV_Position;
|
||||||
float4 border_color: FLAT;
|
nointerpolation float4 border_color: COLOR0;
|
||||||
float4 background_solid: FLAT;
|
nointerpolation float4 background_solid: COLOR1;
|
||||||
float4 background_color0: FLAT;
|
nointerpolation float4 background_color0: COLOR2;
|
||||||
float4 background_color1: FLAT;
|
nointerpolation float4 background_color1: COLOR3;
|
||||||
};
|
};
|
||||||
|
|
||||||
StructuredBuffer<Quad> quads: register(t1);
|
StructuredBuffer<Quad> quads: register(t1);
|
||||||
|
@ -566,55 +573,11 @@ float4 quad_fragment(QuadFragmentInput input): SV_Target {
|
||||||
return color * float4(1., 1., 1., saturate(0.5 - distance));
|
return color * float4(1., 1., 1., saturate(0.5 - distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
**
|
|
||||||
** Path raster
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct PathVertex {
|
struct PathVertex {
|
||||||
float2 xy_position;
|
float2 xy_position;
|
||||||
float2 st_position;
|
|
||||||
Bounds content_mask;
|
Bounds content_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PathRasterizationOutput {
|
|
||||||
float4 position: SV_Position;
|
|
||||||
float2 st_position: TEXCOORD0;
|
|
||||||
float4 clip_distances: SV_ClipDistance;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathRasterizationInput {
|
|
||||||
float4 position: SV_Position;
|
|
||||||
float2 st_position: TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
StructuredBuffer<PathVertex> path_vertices: register(t1);
|
|
||||||
|
|
||||||
PathRasterizationOutput path_rasterization_vertex(uint vertex_id: SV_VertexID) {
|
|
||||||
PathVertex vertex = path_vertices[vertex_id];
|
|
||||||
PathRasterizationOutput output;
|
|
||||||
float2 device_position = vertex.xy_position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
|
||||||
float2 tl = vertex.xy_position - vertex.content_mask.origin;
|
|
||||||
float2 br = vertex.content_mask.origin + vertex.content_mask.size - vertex.xy_position;
|
|
||||||
|
|
||||||
output.position = float4(device_position, 0.0, 1.0);
|
|
||||||
output.st_position = vertex.st_position;
|
|
||||||
output.clip_distances = float4(tl.x, br.x, tl.y, br.y);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 path_rasterization_fragment(PathRasterizationInput input): SV_Target {
|
|
||||||
float2 dx = ddx(input.st_position);
|
|
||||||
float2 dy = ddy(input.st_position);
|
|
||||||
float2 gradient = float2((2. * input.st_position.x) * dx.x - dx.y,
|
|
||||||
(2. * input.st_position.x) * dy.x - dy.y);
|
|
||||||
float f = (input.st_position.x * input.st_position.x) - input.st_position.y;
|
|
||||||
float distance = f / length(gradient);
|
|
||||||
float alpha = saturate(0.5 - distance);
|
|
||||||
return float4(alpha, 0., 0., 1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**
|
**
|
||||||
** Paths
|
** Paths
|
||||||
|
@ -624,27 +587,27 @@ float4 path_rasterization_fragment(PathRasterizationInput input): SV_Target {
|
||||||
struct PathSprite {
|
struct PathSprite {
|
||||||
Bounds bounds;
|
Bounds bounds;
|
||||||
Background color;
|
Background color;
|
||||||
AtlasTile tile;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PathVertexOutput {
|
struct PathVertexOutput {
|
||||||
float4 position: SV_Position;
|
float4 position: SV_Position;
|
||||||
float2 tile_position: POSITION1;
|
float4 clip_distance: SV_ClipDistance;
|
||||||
uint sprite_id: FLAT;
|
nointerpolation uint sprite_id: TEXCOORD0;
|
||||||
float4 solid_color: FLAT;
|
nointerpolation float4 solid_color: COLOR0;
|
||||||
float4 color0: FLAT;
|
nointerpolation float4 color0: COLOR1;
|
||||||
float4 color1: FLAT;
|
nointerpolation float4 color1: COLOR2;
|
||||||
};
|
};
|
||||||
|
|
||||||
StructuredBuffer<PathSprite> path_sprites: register(t1);
|
StructuredBuffer<PathVertex> path_vertices: register(t1);
|
||||||
|
StructuredBuffer<PathSprite> path_sprites: register(t2);
|
||||||
|
|
||||||
PathVertexOutput paths_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) {
|
PathVertexOutput paths_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) {
|
||||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
PathVertex v = path_vertices[vertex_id];
|
||||||
PathSprite sprite = path_sprites[instance_id];
|
PathSprite sprite = path_sprites[instance_id];
|
||||||
// Don't apply content mask because it was already accounted for when rasterizing the path.
|
|
||||||
PathVertexOutput output;
|
PathVertexOutput output;
|
||||||
output.position = to_device_position(unit_vertex, sprite.bounds);
|
output.position = to_device_position_impl(v.xy_position);
|
||||||
output.tile_position = to_tile_position(unit_vertex, sprite.tile);
|
output.clip_distance = distance_from_clip_rect_impl(v.xy_position, v.content_mask);
|
||||||
output.sprite_id = instance_id;
|
output.sprite_id = instance_id;
|
||||||
|
|
||||||
GradientColor gradient = prepare_gradient_color(
|
GradientColor gradient = prepare_gradient_color(
|
||||||
|
@ -662,13 +625,15 @@ PathVertexOutput paths_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 paths_fragment(PathVertexOutput input): SV_Target {
|
float4 paths_fragment(PathVertexOutput input): SV_Target {
|
||||||
float sample = t_sprite.Sample(s_sprite, input.tile_position).r;
|
float4 zero = 0.0;
|
||||||
float mask = 1.0 - abs(1.0 - sample % 2.0);
|
if (any(input.clip_distance < zero)) {
|
||||||
|
return zero;
|
||||||
|
}
|
||||||
|
|
||||||
PathSprite sprite = path_sprites[input.sprite_id];
|
PathSprite sprite = path_sprites[input.sprite_id];
|
||||||
Background background = sprite.color;
|
Background background = sprite.color;
|
||||||
float4 color = gradient_color(background, input.position.xy, sprite.bounds,
|
float4 color = gradient_color(background, input.position.xy, sprite.bounds,
|
||||||
input.solid_color, input.color0, input.color1);
|
input.solid_color, input.color0, input.color1);
|
||||||
color.a *= mask;
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue