v/examples/sokol/simple_shader_glsl/simple_shader.v

157 lines
4.7 KiB
V

// Copyright(C) 2022 Lars Pontoppidan. All rights reserved.
// Use of this source code is governed by an MIT license file distributed with this software package
module main
// Example shader triangle adapted to V from https://github.com/floooh/sokol-samples/blob/1f2ad36/sapp/triangle-sapp.c
import sokol.sapp
import sokol.gfx
// Use `v shader` or `sokol-shdc` to generate the necessary `.h` file
// Using `v shader -v .` in this directory will show some additional
// info - and what you should include to make things work.
#flag -I @VMODROOT/.
#include "simple_shader.h"
// simple_shader_desc is a C function declaration defined by
// the `@program` entry in the `simple_shader.glsl` shader file.
// When the shader is compiled this function name is generated
// by the shader compiler for easier inclusion of universal shader code
// in C (and V) code.
fn C.simple_shader_desc(gfx.Backend) &gfx.ShaderDesc
// Vertex_t makes it possible to model vertex buffer data
// for use with the shader system
struct Vertex_t {
// Position
x f32
y f32
z f32
// Color
r f32
g f32
b f32
a f32
}
fn main() {
mut app := &App{
width: 800
height: 400
pass_action: gfx.create_clear_pass(0.0, 0.0, 0.0, 1.0) // This will create a black color as a default pass (window background color)
}
app.run()
}
struct App {
pass_action gfx.PassAction
mut:
width int
height int
shader_pipeline gfx.Pipeline
bind gfx.Bindings
}
fn (mut a App) run() {
title := 'V Simple Shader Example'
desc := sapp.Desc{
width: a.width
height: a.height
user_data: a
init_userdata_cb: init
frame_userdata_cb: frame
window_title: title.str
html5_canvas_name: title.str
cleanup_userdata_cb: cleanup
sample_count: 4 // Enables MSAA (Multisample anti-aliasing) x4 on rendered output, this can be omitted.
}
sapp.run(&desc)
}
fn init(user_data voidptr) {
mut app := &App(user_data)
mut desc := sapp.create_desc()
gfx.setup(&desc)
// `vertices` defines a vertex buffer with 3 vertices
// with 3 position fields XYZ and 4 color components RGBA -
// for drawing a multi-colored triangle.
//
// C code:
// float vertices[] = {
// // Positions // Colors
// 0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0,
// 0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0,
// -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0
// };
//
// Array entries in the following V code is the equivalent
// of the C code entry described above:
vertices := [
Vertex_t{0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0},
Vertex_t{0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0},
Vertex_t{-0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0},
]
// Create a vertex buffer with the 3 vertices defined above.
mut vertex_buffer_desc := gfx.BufferDesc{
label: c'triangle-vertices'
}
unsafe { vmemset(&vertex_buffer_desc, 0, int(sizeof(vertex_buffer_desc))) }
vertex_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))
vertex_buffer_desc.data = gfx.Range{
ptr: vertices.data
size: vertex_buffer_desc.size
}
app.bind.vertex_buffers[0] = gfx.make_buffer(&vertex_buffer_desc)
// Create shader from the code-generated sg_shader_desc (gfx.ShaderDesc in V).
// Note the function `C.simple_shader_desc()` (also defined above) - this is
// the function that returns the compiled shader code/desciption we have
// written in `simple_shader.glsl` and compiled with `v shader .` (`sokol-shdc`).
shader := gfx.make_shader(C.simple_shader_desc(gfx.query_backend()))
// Create a pipeline object (default render states are fine for triangle)
mut pipeline_desc := gfx.PipelineDesc{}
// This will zero the memory used to store the pipeline in.
unsafe { vmemset(&pipeline_desc, 0, int(sizeof(pipeline_desc))) }
// Populate the essential struct fields
pipeline_desc.shader = shader
// The vertex shader (`simple_shader.glsl`) takes 2 inputs:
// ```glsl
// in vec4 position;
// in vec4 color0;
// ```
// Also note the naming of the C.ATTR_* used as indicies.
// They are the prefixed versions of the names of the input variables in the shader code.
// If they change in the shader code they will also change here.
pipeline_desc.layout.attrs[C.ATTR_vs_position].format = .float3 // x,y,z as f32
pipeline_desc.layout.attrs[C.ATTR_vs_color0].format = .float4 // r, g, b, a as f32
// The .label is optional but can aid debugging sokol shader related issues
// When things get complex - and you get tired :)
pipeline_desc.label = c'triangle-pipeline'
app.shader_pipeline = gfx.make_pipeline(&pipeline_desc)
}
fn cleanup(user_data voidptr) {
gfx.shutdown()
}
fn frame(user_data voidptr) {
mut app := &App(user_data)
gfx.begin_default_pass(&app.pass_action, sapp.width(), sapp.height())
gfx.apply_pipeline(app.shader_pipeline)
gfx.apply_bindings(&app.bind)
gfx.draw(0, 3, 1)
gfx.end_pass()
gfx.commit()
}