157 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			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()
 | |
| }
 |