thorvg/src/renderer/wg_engine/tvgWgShaderSrc.cpp
2023-12-28 10:43:25 +09:00

336 lines
9.5 KiB
C++

/*
* Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* 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 THE
* AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#include "tvgWgShaderSrc.h"
#include <string>
//************************************************************************
// shader pipeline fill
//************************************************************************
const char* cShaderSource_PipelineFill = R"(
// vertex input
struct VertexInput {
@location(0) position: vec2f
};
// vertex output
struct VertexOutput {
@builtin(position) position: vec4f
};
// uniforms
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
// fill output
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> void {
// nothing to draw, just stencil value
}
)";
//************************************************************************
// shader pipeline solid
//************************************************************************
const char* cShaderSource_PipelineSolid = R"(
// vertex input
struct VertexInput {
@location(0) position: vec2f
};
// BlendSettigs
struct BlendSettigs {
format : u32, // ColorSpace
dummy0 : f32,
dummy1 : f32,
opacity : f32
};
// vertex output
struct VertexOutput {
@builtin(position) position: vec4f
};
// uniforms
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
// fill output
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// resulting color
var color = vec4(1.0);
// get color
color = uSolidColor;
return vec4f(color.rgb, color.a * uBlendSettigs.opacity);
}
)";
//************************************************************************
// shader pipeline linear
//************************************************************************
const char* cShaderSource_PipelineLinear = R"(
// vertex input
struct VertexInput {
@location(0) position: vec2f
};
// BlendSettigs
struct BlendSettigs {
format : u32, // ColorSpace
dummy0 : f32,
dummy1 : f32,
opacity : f32
};
// LinearGradient
const MAX_LINEAR_GRADIENT_STOPS = 4;
struct LinearGradient {
nStops : vec4f,
gradStartPos : vec2f,
gradEndPos : vec2f,
stopPoints : vec4f,
stopColors : array<vec4f, MAX_LINEAR_GRADIENT_STOPS>
};
// vertex output
struct VertexOutput {
@builtin(position) position : vec4f,
@location(0) vScreenCoord : vec2f
};
// uniforms
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
@group(2) @binding(0) var<uniform> uLinearGradient : LinearGradient;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
// fill output
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
out.vScreenCoord = in.position.xy;
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// resulting color
var color = vec4(1.0);
let pos: vec2f = in.vScreenCoord;
let st: vec2f = uLinearGradient.gradStartPos;
let ed: vec2f = uLinearGradient.gradEndPos;
let ba: vec2f = ed - st;
// get interpolation factor
let t: f32 = clamp(dot(pos - st, ba) / dot(ba, ba), 0.0, 1.0);
// get stops count
let last: i32 = i32(uLinearGradient.nStops[0]) - 1;
// closer than first stop
if (t <= uLinearGradient.stopPoints[0]) {
color = uLinearGradient.stopColors[0];
}
// further than last stop
if (t >= uLinearGradient.stopPoints[last]) {
color = uLinearGradient.stopColors[last];
}
// look in the middle
for (var i = 0i; i < last; i++) {
let strt = uLinearGradient.stopPoints[i];
let stop = uLinearGradient.stopPoints[i+1];
if ((t > strt) && (t < stop)) {
let step: f32 = (t - strt) / (stop - strt);
color = mix(uLinearGradient.stopColors[i], uLinearGradient.stopColors[i+1], step);
}
}
return vec4f(color.rgb, color.a * uBlendSettigs.opacity);
}
)";
//************************************************************************
// shader pipeline radial
//************************************************************************
const char* cShaderSource_PipelineRadial = R"(
// vertex input
struct VertexInput {
@location(0) position: vec2f
};
// BlendSettigs
struct BlendSettigs {
format : u32, // ColorSpace
dummy0 : f32,
dummy1 : f32,
opacity : f32
};
// RadialGradient
const MAX_RADIAL_GRADIENT_STOPS = 4;
struct RadialGradient {
nStops : vec4f,
centerPos : vec2f,
radius : vec2f,
stopPoints : vec4f,
stopColors : array<vec4f, MAX_RADIAL_GRADIENT_STOPS>
};
// vertex output
struct VertexOutput {
@builtin(position) position : vec4f,
@location(0) vScreenCoord : vec2f
};
// uniforms
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
@group(2) @binding(0) var<uniform> uRadialGradient : RadialGradient;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
// fill output
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
out.vScreenCoord = in.position.xy;
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// resulting color
var color = vec4(1.0);
// get interpolation factor
let t: f32 = clamp(distance(uRadialGradient.centerPos, in.vScreenCoord) / uRadialGradient.radius.x, 0.0, 1.0);
// get stops count
let last: i32 = i32(uRadialGradient.nStops[0]) - 1;
// closer than first stop
if (t <= uRadialGradient.stopPoints[0]) {
color = uRadialGradient.stopColors[0];
}
// further than last stop
if (t >= uRadialGradient.stopPoints[last]) {
color = uRadialGradient.stopColors[last];
}
// look in the middle
for (var i = 0i; i < last; i++) {
let strt = uRadialGradient.stopPoints[i];
let stop = uRadialGradient.stopPoints[i+1];
if ((t > strt) && (t < stop)) {
let step: f32 = (t - strt) / (stop - strt);
color = mix(uRadialGradient.stopColors[i], uRadialGradient.stopColors[i+1], step);
}
}
return vec4f(color.rgb, color.a * uBlendSettigs.opacity);
}
)";
//************************************************************************
// cShaderSource_PipelineImage
//************************************************************************
const char* cShaderSource_PipelineImage = R"(
// vertex input
struct VertexInput {
@location(0) position: vec2f,
@location(1) texCoord: vec2f
};
// BlendSettigs
struct BlendSettigs {
format : u32, // ColorSpace
dummy0 : f32,
dummy1 : f32,
opacity : f32
};
// vertex output
struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) texCoord: vec2f
};
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
@group(1) @binding(1) var<uniform> uBlendSettigs : BlendSettigs;
@group(2) @binding(0) var uSampler : sampler;
@group(2) @binding(1) var uTextureView : texture_2d<f32>;
@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
// fill output
var out: VertexOutput;
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
out.texCoord = in.texCoord;
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
var color: vec4f = textureSample(uTextureView, uSampler, in.texCoord.xy);
var result: vec4f = color;
var format: u32 = uBlendSettigs.format;
if (format == 1u) { /* FMT_ARGB8888 */
result = color.bgra;
} else if (format == 2u) { /* FMT_ABGR8888S */
result = vec4(color.rgb * color.a, color.a);
} else if (format == 3u) { /* FMT_ARGB8888S */
result = vec4(color.bgr * color.a, color.a);
}
return vec4f(result.rgb, result.a * uBlendSettigs.opacity);
};
)";