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:
parent
7d31473523
commit
5bb058e35b
134
examples/gg/additive.v
Normal file
134
examples/gg/additive.v
Normal 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()
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user