const std = @import("std");
const Io = std.Io;
const pow = std.math.pow;
const gl = @cImport({
@cDefine("GLAD_GL_IMPLEMENTATION", "");
@cInclude("glad/gl.h");
@cDefine("GLFW_INCLUDE_NONE", "");
@cInclude("GLFW/glfw3.h");
@cInclude("GL/gl.h");
});
const ftp = @cImport({
@cInclude("freetype2/ft2build.h");
@cInclude("freetype2/freetype/freetype.h");
@cInclude("freetype2/freetype/config/ftconfig.h");
});
const SCREEN_WIDTH = 1000;
const SCREEN_HEIGHT = 800;
const PI = 3.14159265;
fn getShaderFile(init:std.process.Init,filename:[]const u8) []u8 {
const gpa = init.gpa;
const dir = Io.Dir.cwd();
const file = dir.readFileAlloc(init.io, filename, gpa, .unlimited) catch @panic("shader file not found");
return file;
}
fn orthoProjection(w: f32, h: f32) [4]@Vector(4, f32) {
return .{
.{ 2.0 / w, 0.0, 0.0, -1.0 },
.{ 0.0, -2.0 / h, 0.0, 1.0 },
.{ 0.0, 0.0, -1.0, 0.0 },
.{ 0.0, 0.0, 0.0, 1.0 }
};
}
pub fn main(init:std.process.Init) !void {
_ = gl.glfwInit();
defer gl.glfwTerminate();
gl.glfwWindowHint(gl.GLFW_CONTEXT_VERSION_MAJOR, 3);
gl.glfwWindowHint(gl.GLFW_CONTEXT_VERSION_MINOR, 3);
gl.glfwWindowHint(gl.GLFW_OPENGL_PROFILE, gl.GLFW_OPENGL_CORE_PROFILE);
const window: *gl.GLFWwindow = gl.glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "amsasjnd", null, null) orelse unreachable;
defer gl.glfwDestroyWindow(window);
gl.glfwMakeContextCurrent(window);
_ = gl.gladLoadGL(gl.glfwGetProcAddress);
gl.glfwSwapInterval(1);
gl.glEnable(gl.GL_CULL_FACE);
gl.glEnable(gl.GL_BLEND);
gl.glEnable(gl.GL_DEBUG_OUTPUT);
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA);
const vertexSource = getShaderFile(init, "shaders/custom3/text1.vert");
const fragmentSource = getShaderFile(init, "shaders/custom3/text1.frag");
defer init.gpa.free(vertexSource);
defer init.gpa.free(fragmentSource);
const vertexShader = gl.glCreateShader(gl.GL_VERTEX_SHADER);
gl.glShaderSource(vertexShader, 1, &vertexSource.ptr, null);
gl.glCompileShader(vertexShader);
const fragmentShader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER);
gl.glShaderSource(fragmentShader, 1, &fragmentSource.ptr, null);
gl.glCompileShader(fragmentShader);
const shaderProgram = gl.glCreateProgram();
gl.glAttachShader(shaderProgram, vertexShader);
gl.glAttachShader(shaderProgram, fragmentShader);
gl.glLinkProgram(shaderProgram);
gl.glDeleteShader(fragmentShader);
gl.glDeleteShader(vertexShader);
gl.glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
var ft:ftp.FT_Library = undefined;
var face:ftp.FT_Face = undefined;
_ = ftp.FT_Init_FreeType(&ft);
_ = ftp.FT_New_Face(ft, "fonts/MapleMono-Bold.ttf", 0, &face);
_ = ftp.FT_Set_Pixel_Sizes(face, 0, 48);
const character = struct {
texture:c_uint,
size:@Vector(2, i32),
bearing:@Vector(2, i32),
advance:gl.GLuint
};
var mapCharacter:std.ArrayList(character) = .empty ;
defer mapCharacter.deinit(init.gpa);
defer mapCharacter.clearAndFree(init.gpa);
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1);
for (0..128) |c| {
_ = ftp.FT_Load_Char(face, c, ftp.FT_LOAD_RENDER);
// create texture
// note: * = pointer atau ambil dari memory
var texture:c_uint = undefined;
gl.glCreateTextures(gl.GL_TEXTURE_2D, 1, &texture);
gl.glTextureStorage2D(texture, 1, gl.GL_R8, @intCast(face.*.glyph.*.bitmap.width), @intCast(face.*.glyph.*.bitmap.rows));
gl.glTextureSubImage2D(texture, 0, 0, 0, @intCast(face.*.glyph.*.bitmap.width), @intCast(face.*.glyph.*.bitmap.rows), gl.GL_RED, gl.GL_UNSIGNED_BYTE, face.*.glyph.*.bitmap.buffer);
// bind texture
gl.glBindTexture(gl.GL_TEXTURE_2D, texture);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
// unbind
// gl.glBindTexture(gl.GL_TEXTURE_2D, 0);
// append character
mapCharacter.append(init.gpa, .{
.texture = texture,
.size = @Vector(2, i32){@intCast(face.*.glyph.*.bitmap.width), @intCast(face.*.glyph.*.bitmap.rows)},
.bearing = @Vector(2, i32){@intCast(face.*.glyph.*.bitmap_left), @intCast(face.*.glyph.*.bitmap_top)},
.advance = @intCast(face.*.glyph.*.advance.x)
}) catch @panic("character not appenned");
}
_ = ftp.FT_Done_Face(face);
_ = ftp.FT_Done_FreeType(ft);
var vao:c_uint, var vbo:c_uint = .{undefined,undefined};
gl.glCreateVertexArrays(1, &vao);
gl.glCreateBuffers(1, &vbo);
gl.glBindVertexArray(vao);
gl.glNamedBufferData(vbo, @sizeOf(f32) * 24, null, gl.GL_DYNAMIC_DRAW);
gl.glVertexArrayVertexBuffer(vao, 0, vbo, 0, @sizeOf(f32) * 4);
gl.glVertexArrayAttribFormat(vao, 0, 4, gl.GL_FLOAT, gl.GL_FALSE, 0);
gl.glVertexArrayAttribBinding(vao, 0, 0);
gl.glEnableVertexArrayAttrib(vao, 0);
const text:[]const u8 = "hell world";
while (gl.glfwWindowShouldClose(window) == 0) {
gl.glClearColor(0.0, 0.0, 0.0, 1.0);
gl.glClear(gl.GL_COLOR_BUFFER_BIT);
var x:f32 = 1.0;
const y:f32 = 300.0;
const scale:f32 = 1.0;
gl.glUseProgram(shaderProgram);
gl.glBindVertexArray(vao);
const textLoc = gl.glGetUniformLocation(shaderProgram, "text");
if(textLoc != -1) gl.glUniform1i(textLoc, 0);
gl.glActiveTexture(gl.GL_TEXTURE0);
for (text) |v| {
const ch = mapCharacter.items[v];
const xPos:f32 = x + @as(f32,@floatFromInt(ch.bearing[0])) * scale;
const yPos:f32 = y - @as(f32,@floatFromInt(ch.size[1] - ch.bearing[1])) * scale;
const w:f32 = @as(f32,@floatFromInt(ch.size[0])) * scale;
const h:f32 = @as(f32,@floatFromInt(ch.size[1])) * scale;
const vertices = [6][4]f32{
[4]f32{xPos,yPos+h, 0.0, 0.0},
[4]f32{xPos,yPos, 0.0, 1.0},
[4]f32{xPos + w,yPos, 1.0, 1.0},
[4]f32{xPos, yPos + h, 0.0,0.0},
[4]f32{xPos+w, yPos, 1.0, 1.0},
[4]f32{xPos+w, yPos+h, 1.0, 0.0}
};
gl.glNamedBufferSubData(vbo, 0, @sizeOf(f32) * 6 * 4, &vertices);
gl.glBindTexture(gl.GL_TEXTURE_2D, ch.texture);
// gl.glActiveTexture(gl.GL_TEXTURE0);
const projection = orthoProjection(SCREEN_WIDTH, SCREEN_HEIGHT);
const projectionLoc = gl.glGetUniformLocation(shaderProgram, "projection");
const texLoc = gl.glGetUniformLocation(shaderProgram, "textColor");
if(projectionLoc != -1) gl.glUniformMatrix4fv(projectionLoc, 1, gl.GL_FALSE, @ptrCast(&projection));
if(texLoc != -1) gl.glUniform3f(texLoc, 0.88, 0.53, 0.03);
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6);
const px = @as(f32,@floatFromInt(ch.advance >> 6));
x += px * scale;
}
gl.glfwSwapBuffers(window);
gl.glfwPollEvents();
}
}
vertex shader
#version 330 core
layout (location = 0) in vec4 vertex;
uniform mat4 projection;
out vec2 TexCoords;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
}
fragment shader
#version 330 core
in vec2 TexCoords;
out vec4 FragColor;
uniform sampler2D text;
uniform vec3 textColor;
void main() {
float alpha = texture(text, TexCoords).r;
FragColor = vec4(textColor, alpha);
}
i trying making text in opengl with zig and freetype and try follow some example code, this code no error, but the text not show, can anyone tell me whats wrong with my code? , sorry im if my english not very good

