// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module gl // import os import gx import glm // import darwin pub struct Shader { program_id int } const ( TEXT_VERT = '#version 330 core layout (location = 0) in vec4 vertex; // out vec2 TexCoords; uniform mat4 projection; void main() { gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); TexCoords = vertex.zw; } ' TEXT_FRAG = '#version 330 core in vec2 TexCoords; out vec4 color; uniform sampler2D text; uniform vec3 textColor; void main() { vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); color = vec4(textColor, 1.0) * sampled; } ' SIMPLE_VERT = ' #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; uniform mat4 projection; void main() { gl_Position = projection * vec4(aPos, 1.0); // gl_Position = vec4(aPos, 1.0); ourColor = aColor; //TexCoord = vec2(aTexCoord.x, aTexCoord.y); TexCoord = aTexCoord; } ' SIMPLE_FRAG = '#version 330 core out vec4 FragColor; uniform vec3 color; uniform bool has_texture; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D ourTexture; void main() { // FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); // FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f); if (has_texture) { FragColor = texture(ourTexture, TexCoord); } else { FragColor = vec4(color, 1.0f); } } ' ) pub fn new_shader(name string) Shader { // TODO This is not used, remove mut dir := '' // Already have absolute path if name.starts_with('/') { dir = '' } vertex_path := '${dir}${name}.vert' fragment_path := '${dir}${name}.frag' //println('shader path=$vertex_path,\n fpath="$fragment_path"') // vertex_src := os.read_file(vertex_path.trim_space()) mut vertex_src := '' mut fragment_src := '' if name == 'text' { vertex_src = TEXT_VERT fragment_src = TEXT_FRAG } else if name == 'simple' { // println('new shader simple!!!') // println(SIMPLE_VERT) vertex_src = SIMPLE_VERT fragment_src = SIMPLE_FRAG } // //////////////////////////////////////// vertex_shader := gl.create_shader(C.GL_VERTEX_SHADER) gl.shader_source(vertex_shader, 1, vertex_src, 0) gl.compile_shader(vertex_shader) if gl.shader_compile_status(vertex_shader) == 0 { log := gl.shader_info_log(vertex_shader) println('shader $vertex_shader compilation failed') println('shader source = $vertex_src') println('shader failed to compile') exit(1) } // fragment shader // fragment_src := os.read_file(fragment_path.trim_space()) fragment_shader := gl.create_shader(C.GL_FRAGMENT_SHADER) gl.shader_source(fragment_shader, 1, fragment_src, 0) gl.compile_shader(fragment_shader) if gl.shader_compile_status(fragment_shader) == 0 { println('fragment $fragment_shader shader compilation failed') println('shader failed to compile') exit(1) } // link shaders shader_program := gl.create_program() gl.attach_shader(shader_program, vertex_shader) gl.attach_shader(shader_program, fragment_shader) gl.link_program(shader_program) // check for linking errors success := gl.get_program_link_status(shader_program) if success == 0 { println('shader compilation failed') println('vertex source = $vertex_src') println('fragment source = $fragment_src') println('shader failed to compile') exit(1) } shader := Shader { program_id: shader_program, } return shader } pub fn (s Shader) use() { gl.use_program(s.program_id) } pub fn (s Shader) uni_location(key string) int { return C.glGetUniformLocation(s.program_id, key.str) } // fn (s Shader) set_mat4(str string, f *f32) { pub fn (s Shader) set_mat4(str string, m glm.Mat4) { // TODO cache uniform location C.glUniformMatrix4fv(s.uni_location(str), 1, false, m.data) } pub fn (s Shader) set_int(str string, n int) { C.glUniform1i(s.uni_location(str), n) } pub fn (s Shader) set_color(str string, c gx.Color) { C.glUniform3f(s.uni_location(str), f32(c.r) / 255.0, f32(c.g) / 255.0, f32(c.b) / 255.0) }