71c79c0105a422ff0233d601e7c69d143f08f493
[vg.git] / src / vg / vg_tex.h
1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
2 #ifndef VG_TEX_H
3 #define VG_TEX_H
4
5 #define VG_TEXTURE_NO_MIP 0x1
6 #define VG_TEXTURE_REPEAT 0x2
7 #define VG_TEXTURE_CLAMP 0x4
8 #define VG_TEXTURE_NEAREST 0x8
9
10 struct vg_tex2d
11 {
12 const char *path;
13 u32 flags;
14 GLuint name;
15 };
16
17 struct vg_sprite
18 {
19 v4f uv_xywh;
20 };
21
22 static void vg_tex2d_bind( vg_tex2d *tex, u32 id )
23 {
24 glActiveTexture( GL_TEXTURE0 + id );
25 glBindTexture( GL_TEXTURE_2D, tex->name );
26 }
27
28 static inline void vg_tex2d_mipmap(void)
29 {
30 glGenerateMipmap( GL_TEXTURE_2D );
31 }
32
33 static inline void vg_tex2d_linear(void)
34 {
35 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
36 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
37 }
38
39 static inline void vg_tex2d_nearest(void)
40 {
41 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
42 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
43 }
44
45 static inline void vg_tex2d_linear_mipmap(void)
46 {
47 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
48 GL_LINEAR_MIPMAP_LINEAR );
49 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
50 }
51
52 static inline void vg_tex2d_repeat(void)
53 {
54 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
55 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
56 }
57
58 static inline void vg_tex2d_clamp(void)
59 {
60 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
61 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
62 }
63
64 static GLuint vg_tex2d_rgba( const char *path )
65 {
66 i64 length;
67 u8 *src_data = vg_asset_read_s( path, &length );
68
69 GLuint texture_name;
70 glGenTextures( 1, &texture_name );
71 glBindTexture( GL_TEXTURE_2D, texture_name );
72
73 if( src_data )
74 {
75 qoi_desc info;
76 u8 *tex_buffer = qoi_decode( src_data, length, &info, 4 );
77
78 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height,
79 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer );
80
81 free( tex_buffer );
82 free( src_data );
83 }
84 else
85 {
86 u32 tex_err[4] =
87 {
88 0xffff00ff,
89 0xff000000,
90 0xff000000,
91 0xffff00ff
92 };
93
94 vg_error( "Loading texture failed (%s)\n", path );
95 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2,
96 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_err );
97 }
98
99 return texture_name;
100 }
101
102 static void vg_tex2d_init( vg_tex2d *textures[], int num )
103 {
104 for( int i = 0; i < num; i ++ )
105 {
106 vg_tex2d *tex = textures[i];
107 tex->name = vg_tex2d_rgba( tex->path );
108 if( !(tex->flags & VG_TEXTURE_NO_MIP) )
109 vg_tex2d_mipmap();
110
111 if( tex->flags & VG_TEXTURE_NEAREST )
112 {
113 if( tex->flags & VG_TEXTURE_NO_MIP )
114 vg_error( "Invalid texture settings\n" );
115 else
116 vg_tex2d_nearest();
117 }
118 else
119 {
120 if( tex->flags & VG_TEXTURE_NO_MIP )
121 vg_tex2d_linear();
122 else
123 vg_tex2d_linear_mipmap();
124 }
125
126 if( tex->flags & VG_TEXTURE_CLAMP )
127 vg_tex2d_clamp();
128 else
129 vg_tex2d_repeat();
130 }
131 }
132
133 static void vg_tex2d_free( vg_tex2d *textures[], int num )
134 {
135 for( int i = 0; i < num; i ++ )
136 {
137 glDeleteTextures( 1, &textures[i]->name );
138 }
139 }
140
141 #endif /* VG_TEX_H */