/* * 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 //************************************************************************ // 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 uViewMat : mat4x4f; @group(1) @binding(0) var 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 uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @group(1) @binding(1) var uBlendSettigs : BlendSettigs; @group(2) @binding(0) var 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 }; // vertex output struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec2f }; // uniforms @group(0) @binding(0) var uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @group(1) @binding(1) var uBlendSettigs : BlendSettigs; @group(2) @binding(0) var 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 }; // vertex output struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec2f }; // uniforms @group(0) @binding(0) var uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @group(1) @binding(1) var uBlendSettigs : BlendSettigs; @group(2) @binding(0) var 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 uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @group(1) @binding(1) var uBlendSettigs : BlendSettigs; @group(2) @binding(0) var uSampler : sampler; @group(2) @binding(1) var uTextureView : texture_2d; @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); }; )";