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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/* date = January 26th 2026 11:00 am */
#ifndef EDITOR_GL_H
#define EDITOR_GL_H
//~ Types
typedef GLuint gl_uint;
typedef GLint gl_int;
typedef GLenum gl_enum;
typedef struct gl_render_state gl_render_state;
struct gl_render_state
{
gl_uint VAOs[1];
gl_uint VBOs[1];
gl_uint Textures[2];
gl_uint RectShader;
b32 ShadersCompiled;
};
//~ Globals
global_variable arena *GL_FrameArena = 0;
//~ Functions
internal void
GL_ErrorStatus(gl_uint Handle, b32 IsShader)
{
b32 Valid = true;
char InfoLog[KB(2)] = {0};
if(IsShader)
{
glGetShaderiv(Handle, GL_COMPILE_STATUS, &Valid);
glGetShaderInfoLog(Handle, sizeof(InfoLog), NULL, InfoLog);
}
else
{
glGetProgramiv(Handle, GL_LINK_STATUS, &Valid);
glGetProgramInfoLog(Handle, sizeof(InfoLog), NULL, InfoLog);
}
if(!Valid)
{
ErrorLog("%s", InfoLog);
}
}
internal gl_uint
GL_CompileShaderFromSource(str8 FileNameAfterExe, u32 Type)
{
gl_uint Shader = (gl_uint)glCreateShader(Type);
char *FileName = PathFromExe(GL_FrameArena, FileNameAfterExe);
str8 Source = OS_ReadEntireFileIntoMemory(FileName);
if(Source.Size)
{
glShaderSource(Shader, 1, (const char **)&Source.Data, NULL);
glCompileShader(Shader);
GL_ErrorStatus(Shader, true);
}
OS_FreeFileMemory(Source);
return Shader;
}
internal gl_uint
GL_ProgramFromShaders(str8 VertPath, str8 FragPath)
{
gl_uint Program = 0;
gl_uint VertexShader, FragmentShader;
VertexShader = GL_CompileShaderFromSource(VertPath, GL_VERTEX_SHADER);
FragmentShader = GL_CompileShaderFromSource(FragPath, GL_FRAGMENT_SHADER);
Program = glCreateProgram();
glAttachShader(Program, VertexShader);
glAttachShader(Program, FragmentShader);
glLinkProgram(Program);
GL_ErrorStatus(Program, false);
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
return Program;
}
internal void
GL_LoadFloatsIntoBuffer(gl_uint BufferHandle, gl_uint ShaderHandle, char *AttributeName, s32 Count, s32 VecSize, void *Buffer)
{
gl_int AttribHandle;
s32 SizeOfVec = (smm)(sizeof(f32))*VecSize;
glBindBuffer(GL_ARRAY_BUFFER, BufferHandle);
AttribHandle = glGetAttribLocation(ShaderHandle, AttributeName);
Assert(AttribHandle != -1);
glEnableVertexAttribArray((gl_uint)AttribHandle);
glVertexAttribPointer((gl_uint)AttribHandle, VecSize, GL_FLOAT, GL_FALSE, SizeOfVec, 0);
glBufferData(GL_ARRAY_BUFFER, (SizeOfVec*Count), Buffer, GL_STATIC_DRAW);
}
internal void
GL_LoadTextureFromImage(gl_uint Texture, s32 Width, s32 Height, u8 *Image, gl_enum Format, gl_uint ShaderProgram, char *TextureHandle)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
s32 InternalFormat = GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Image);
// NOTE(luca): Border might show up sometimes, so we use it to debug, but it isn't really desired.
#if 0
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
#endif
// TODO(luca): Use mipmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#if 1
f32 Color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, Color);
#endif
gl_int UTexture = glGetUniformLocation(ShaderProgram, TextureHandle);
glUniform1i(UTexture, 0);
}
#endif //EDITOR_GL_H
|