1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

gg: revamp the Context pipeline for more effects, implement an additive effect (#16394)

This commit is contained in:
Junko 2022-11-12 15:39:18 +08:00 committed by GitHub
parent 7d31473523
commit 5bb058e35b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 227 additions and 43 deletions

134
examples/gg/additive.v Normal file
View File

@ -0,0 +1,134 @@
module main
import os
import gg
import gx
import math
[heap]
pub struct Window {
pub mut:
ctx &gg.Context = unsafe { 0 }
image gg.Image
}
pub fn (mut window Window) init(_ voidptr) {
logo_path := os.resource_abs_path(os.join_path('..', 'assets', 'logo.png'))
window.image = window.ctx.create_image(logo_path)
}
pub fn (mut window Window) draw(_ voidptr) {
window.ctx.begin()
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: 400 - window.image.width / 2
y: 300 - window.image.height / 2
width: window.image.width
height: window.image.height
}
// effect: .alpha <-- this can be omitted completely as it is alpha by default.
)
// Red
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: (400 - window.image.width / 2) + f32(math.sin(f32(window.ctx.frame) / 10.0) * 60)
y: (300 - window.image.height / 2) + f32(math.cos(f32(window.ctx.frame) / 10.0) * 60)
width: window.image.width
height: window.image.height
}
color: gx.Color{255, 0, 0, 255}
effect: .add
)
// Green
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: (400 - window.image.width / 2) + f32(math.sin(f32(window.ctx.frame) / 10.0) * 80)
y: (300 - window.image.height / 2) + f32(math.cos(f32(window.ctx.frame) / 10.0) * 80)
width: window.image.width
height: window.image.height
}
color: gx.Color{0, 255, 0, 255}
effect: .add
)
// Blue
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: (400 - window.image.width / 2) + f32(math.sin(f32(window.ctx.frame) / 10.0) * 100)
y: (300 - window.image.height / 2) + f32(math.cos(f32(window.ctx.frame) / 10.0) * 100)
width: window.image.width
height: window.image.height
}
color: gx.Color{0, 0, 255, 255}
effect: .add
)
// More examples
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: 50
y: 0
width: window.image.width
height: window.image.height
}
color: gx.Color{255, 0, 0, 255}
effect: .add
)
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: 50
y: 50
width: window.image.width
height: window.image.height
}
color: gx.Color{0, 255, 0, 255}
effect: .add
)
window.ctx.draw_image_with_config(
img: &window.image
img_id: window.image.id
img_rect: gg.Rect{
x: 50
y: 100
width: window.image.width
height: window.image.height
}
color: gx.Color{0, 0, 255, 255}
effect: .add
)
window.ctx.end()
}
fn main() {
mut window := &Window{}
window.ctx = gg.new_context(
width: 800
height: 600
user_data: window
bg_color: gx.gray
// FNs
init_fn: window.init
frame_fn: window.draw
)
window.ctx.run()
}

View File

@ -16,7 +16,7 @@ pub fn (mut window Window) init() {
pub fn (mut window Window) draw() {
angle := f32(window.ctx.frame) / 64 // since window.ctx.frame is increased by 1 on every frame -> the angle will be increasing too
window.ctx.begin()
sgl.load_pipeline(window.ctx.timage_pip)
sgl.load_pipeline(window.ctx.pipeline.alpha)
sgl.translate(400, 400, 0) // center of the screen
sgl.rotate(angle, 0.0, 0.0, 1.0) // rotate around the Z axis pointing towards the camera

View File

@ -15,7 +15,7 @@ import math
[inline]
pub fn (ctx &Context) draw_pixel(x f32, y f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -37,7 +37,7 @@ pub fn (ctx &Context) draw_pixels(points []f32, c gx.Color) {
len := points.len / 2
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -67,7 +67,7 @@ pub fn (ctx &Context) draw_line(x f32, y f32, x2 f32, y2 f32, c gx.Color) {
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -80,7 +80,7 @@ pub fn (ctx &Context) draw_line(x f32, y f32, x2 f32, y2 f32, c gx.Color) {
// draw_line_with_config draws a line between the points `x,y` and `x2,y2` using `PenConfig`.
pub fn (ctx &Context) draw_line_with_config(x f32, y f32, x2 f32, y2 f32, config PenConfig) {
if config.color.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
if config.thickness <= 0 {
@ -137,7 +137,7 @@ pub fn (ctx &Context) draw_poly_empty(points []f32, c gx.Color) {
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -159,7 +159,7 @@ pub fn (ctx &Context) draw_convex_poly(points []f32, c gx.Color) {
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -182,7 +182,7 @@ pub fn (ctx &Context) draw_convex_poly(points []f32, c gx.Color) {
// `w` is the width, `h` is the height and `c` is the color of the outline.
pub fn (ctx &Context) draw_rect_empty(x f32, y f32, w f32, h f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -207,7 +207,7 @@ pub fn (ctx &Context) draw_rect_filled(x f32, y f32, w f32, h f32, c gx.Color) {
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -230,7 +230,7 @@ pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -329,7 +329,7 @@ pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radiu
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -435,7 +435,7 @@ pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radiu
// `c` is the color of the outline.
pub fn (ctx &Context) draw_triangle_empty(x f32, y f32, x2 f32, y2 f32, x3 f32, y3 f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -454,7 +454,7 @@ pub fn (ctx &Context) draw_triangle_empty(x f32, y f32, x2 f32, y2 f32, x3 f32,
// `c` is the color of the outline.
pub fn (ctx &Context) draw_triangle_filled(x f32, y f32, x2 f32, y2 f32, x3 f32, y3 f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -505,7 +505,7 @@ fn radius_to_segments(r f32) int {
// `c` is the color of the outline.
pub fn (ctx &Context) draw_circle_empty(x f32, y f32, radius f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -554,7 +554,7 @@ pub fn (ctx &Context) draw_polygon_filled(x f32, y f32, size f32, edges int, rot
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -604,7 +604,7 @@ pub fn (ctx &Context) draw_circle_line(x f32, y f32, radius int, segments int, c
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -631,7 +631,7 @@ pub fn (ctx &Context) draw_slice_empty(x f32, y f32, radius f32, start_angle f32
return
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -672,7 +672,7 @@ pub fn (ctx &Context) draw_slice_filled(x f32, y f32, radius f32, start_angle f3
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -721,7 +721,7 @@ pub fn (ctx Context) draw_arc_line(x f32, y f32, radius f32, start_angle f32, en
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -768,7 +768,7 @@ pub fn (ctx &Context) draw_arc_empty(x f32, y f32, inner_radius f32, thickness f
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -835,7 +835,7 @@ pub fn (ctx &Context) draw_arc_filled(x f32, y f32, inner_radius f32, thickness
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -874,7 +874,7 @@ pub fn (ctx &Context) draw_arc_filled(x f32, y f32, inner_radius f32, thickness
// `c` is the color of the outline.
pub fn (ctx &Context) draw_ellipse_empty(x f32, y f32, rw f32, rh f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -894,7 +894,7 @@ pub fn (ctx &Context) draw_ellipse_empty(x f32, y f32, rw f32, rh f32, c gx.Colo
// `c` is the fill color.
pub fn (ctx &Context) draw_ellipse_filled(x f32, y f32, rw f32, rh f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)
@ -926,7 +926,7 @@ pub fn (ctx &Context) draw_cubic_bezier_in_steps(points []f32, steps u32, c gx.C
return
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
sgl.c4b(c.r, c.g, c.b, c.a)

View File

@ -103,6 +103,51 @@ pub:
max_dropped_file_path_length int = 2048 // max length in bytes of a dropped UTF-8 file path (default: 2048)
}
[heap]
pub struct PipelineContainer {
pub mut:
alpha sgl.Pipeline
add sgl.Pipeline
}
fn (mut container PipelineContainer) init_pipeline() {
// FIXME(FireRedz): this looks kinda funny, find a better way to initialize pipeline.
// Alpha
mut alpha_pipdesc := gfx.PipelineDesc{
label: c'alpha-pipeline'
}
unsafe { vmemset(&alpha_pipdesc, 0, int(sizeof(alpha_pipdesc))) }
alpha_pipdesc.colors[0] = gfx.ColorState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha
dst_factor_rgb: .one_minus_src_alpha
}
}
container.alpha = sgl.make_pipeline(&alpha_pipdesc)
// Add
mut add_pipdesc := gfx.PipelineDesc{
label: c'additive-pipeline'
}
unsafe { vmemset(&add_pipdesc, 0, int(sizeof(add_pipdesc))) }
add_pipdesc.colors[0] = gfx.ColorState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha
dst_factor_rgb: .one
}
}
container.add = sgl.make_pipeline(&add_pipdesc)
}
[heap]
pub struct Context {
mut:
@ -120,7 +165,8 @@ pub mut:
height int
clear_pass gfx.PassAction
window sapp.Desc
timage_pip sgl.Pipeline
timage_pip sgl.Pipeline [deprecated: 'Use `Context.pipeline.alpha` instead!']
pipeline &PipelineContainer = unsafe { nil }
config Config
user_data voidptr
ft &FT = unsafe { nil }
@ -205,22 +251,14 @@ fn gg_init_sokol_window(user_data voidptr) {
ctx.font_inited = true
}
}
//
mut pipdesc := gfx.PipelineDesc{
label: c'alpha_image'
}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
color_state := gfx.ColorState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha
dst_factor_rgb: .one_minus_src_alpha
}
}
pipdesc.colors[0] = color_state
// Pipeline
ctx.pipeline = &PipelineContainer{}
ctx.pipeline.init_pipeline()
// Keep the old pipeline for now, cuz v ui used it.
ctx.timage_pip = ctx.pipeline.alpha
ctx.timage_pip = sgl.make_pipeline(&pipdesc)
//
if ctx.config.init_fn != unsafe { nil } {
$if android {

View File

@ -296,7 +296,12 @@ pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) {
mut v0f := if !flip_y { v0 } else { v1 }
mut v1f := if !flip_y { v1 } else { v0 }
sgl.load_pipeline(ctx.timage_pip)
// FIXME: is this okay?
match config.effect {
.alpha { sgl.load_pipeline(ctx.pipeline.alpha) }
.add { sgl.load_pipeline(ctx.pipeline.add) }
}
sgl.enable_texture()
sgl.texture(img.simg)

View File

@ -16,7 +16,14 @@ pub:
part_rect Rect // defines the size and position of part of the image to use when rendering
rotate int // amount to rotate the image in degrees
z f32
color gx.Color = gx.white
color gx.Color = gx.white
effect ImageEffect = .alpha
}
pub enum ImageEffect {
// TODO(FireRedz): Add more effects
alpha
add
}
// Rect represents a rectangular shape in `gg`.

View File

@ -138,7 +138,7 @@ pub fn (ctx &Context) set_text_cfg(cfg gx.TextCfg) {
ctx.ft.fons.set_align(int(cfg.align) | int(cfg.vertical_align))
color := sfons.rgba(cfg.color.r, cfg.color.g, cfg.color.b, cfg.color.a)
if cfg.color.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
}
ctx.ft.fons.set_color(color)
ascender := f32(0.0)

View File

@ -196,7 +196,7 @@ pub fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
]
sgl.mult_matrix(m)
//
sgl.load_pipeline(ctx.timage_pip)
sgl.load_pipeline(ctx.pipeline.alpha)
sgl.enable_texture()
sgl.texture(tf_skl.sg_img)
sgl.begin_quads()