summaryrefslogtreecommitdiff
path: root/source/dw/app/getshdprg.rs
blob: 2da60957beb9c2cb416cd2396d6b008224adb6a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright 2023 Gabriel Jensen.

use crate::dw::app::App;

extern crate gl;

use gl::{AttachShader, COMPILE_STATUS, CompileShader, COMPUTE_SHADER, CreateProgram, CreateShader, DeleteShader, FALSE, FRAGMENT_SHADER, GEOMETRY_SHADER, GetShaderInfoLog, GetShaderiv, INFO_LOG_LENGTH, LinkProgram, ShaderSource, TESS_CONTROL_SHADER, TESS_EVALUATION_SHADER, VERTEX_SHADER};
use gl::types::{GLchar, GLint, GLsizei, GLuint};
use libc::{STDERR_FILENO, write};
use std::alloc::{alloc, dealloc, Layout};
use std::ffi::c_void;
use std::ptr::{addr_of, null};

impl App {
	pub fn getshdprg(&mut self) -> GLuint {
		eprintln!("compiling shaders");

		let cmpshd = |nam: & str| -> GLuint {
			let extoff = nam.find('.').expect("unable to find file extension seperator")+0x1;
			let filext = &nam[extoff..];
			let typ = match filext {
				"comp" => COMPUTE_SHADER,
				"frag" => FRAGMENT_SHADER,
				"geom" => GEOMETRY_SHADER,
				"tesc" => TESS_CONTROL_SHADER,
				"tese" => TESS_EVALUATION_SHADER,
				"vert" => VERTEX_SHADER,
				_      => panic!("invalid shader file extension \"{}\"", filext),
			};

			let typstr = match typ {
				FRAGMENT_SHADER => "fragment",
				VERTEX_SHADER   => "vertex",
				_               => unreachable!(),
			};

			eprintln!("compiling {} shader \"{}\"", typstr, nam);

			//let src = read(pth).expect("unable to read shader at");
			let src = match nam {
				"main.frag" => include_bytes!("shader/main.frag.glsl").to_vec(),
				"main.vert" => include_bytes!("shader/main.vert.glsl").to_vec(),
				_           => panic!("shader not found"),
			};

			unsafe {
				let shd    = CreateShader(typ);
				let srcptr = src.as_ptr();
				ShaderSource(shd, 0x1, addr_of!(srcptr) as *const *const GLchar, null::<GLint>());

				CompileShader(shd);

				let mut sts: GLint = 0x0;
				GetShaderiv(shd, COMPILE_STATUS, &mut sts);
				if sts == FALSE as GLint {
					let mut len: GLint = 0x0;
					GetShaderiv(shd, INFO_LOG_LENGTH, &mut len);
					
					let lay = Layout::from_size_align(len as usize, 0x1).unwrap();

					let log = alloc(lay);
					GetShaderInfoLog(shd, len, null::<GLsizei>() as *mut GLsizei, log as *mut GLchar);

					eprint!("unable able to compile shader:\n");
					write(STDERR_FILENO, log as *const c_void, len as usize);
					eprintln!();

					dealloc(log, lay);

					panic!("unable to compile shader");
				}

				return shd;
			}
		};

		let frgshd = cmpshd("main.frag");
		let vtxshd = cmpshd("main.vert");
		
		unsafe {
			let prg = CreateProgram();
			AttachShader(prg, frgshd);
			AttachShader(prg, vtxshd);
			LinkProgram(prg);

			DeleteShader(frgshd);
			DeleteShader(vtxshd);

			return prg;
		}
	}
}