deadzones adjustable & other fixes
[vg.git] / 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_GAME
6 #include "vg/vg.h"
7 #include "vg/vg_log.h"
8
9 #define VG_TEXTURE_NO_MIP 0x1
10 #define VG_TEXTURE_REPEAT 0x2
11 #define VG_TEXTURE_CLAMP 0x4
12 #define VG_TEXTURE_NEAREST 0x8
13 #define VG_TEXTURE_ALLOCATED_INTERNAL 0x10
14
15 VG_STATIC void *vg_qoi_malloc( size_t size )
16 {
17 return vg_linear_alloc( vg_mem.scratch, size );
18 }
19
20 VG_STATIC void vg_qoi_free( void *ptr )
21 {
22
23 }
24
25 #define QOI_IMPLEMENTATION
26 #define QOI_NO_STDIO
27 #define QOI_MALLOC(sz) vg_qoi_malloc( sz )
28 #define QOI_FREE(p) vg_qoi_free( p )
29
30 #include "submodules/qoi/qoi.h"
31
32 struct vg_tex2d
33 {
34 const char *path;
35 u32 flags;
36 GLuint name;
37 };
38
39 struct vg_sprite
40 {
41 v4f uv_xywh;
42 };
43
44 VG_STATIC void vg_tex2d_bind( vg_tex2d *tex, u32 id )
45 {
46 if( !(tex->flags & VG_TEXTURE_ALLOCATED_INTERNAL) )
47 {
48 vg_error( "Tried to use '%s' while unloaded!\n", tex->path );
49 return;
50 }
51
52 glActiveTexture( GL_TEXTURE0 + id );
53 glBindTexture( GL_TEXTURE_2D, tex->name );
54 }
55
56 static inline void vg_tex2d_mipmap(void)
57 {
58 glGenerateMipmap( GL_TEXTURE_2D );
59 }
60
61 static inline void vg_tex2d_linear(void)
62 {
63 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
64 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
65 }
66
67 static inline void vg_tex2d_nearest(void)
68 {
69 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
70 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
71 }
72
73 static inline void vg_tex2d_linear_mipmap(void)
74 {
75 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
76 GL_LINEAR_MIPMAP_LINEAR );
77 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
78 }
79
80 static inline void vg_tex2d_repeat(void)
81 {
82 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
83 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
84 }
85
86 static inline void vg_tex2d_clamp(void)
87 {
88 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
89 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
90 }
91
92 VG_STATIC GLuint vg_tex2d_new(void)
93 {
94 GLuint texture_name;
95 glGenTextures( 1, &texture_name );
96 glBindTexture( GL_TEXTURE_2D, texture_name );
97
98 return texture_name;
99 }
100
101 VG_STATIC void vg_tex2d_set_error(void)
102 {
103 u32 tex_err[4] =
104 {
105 0xffff00ff,
106 0xff000000,
107 0xff000000,
108 0xffff00ff
109 };
110
111 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2,
112 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_err );
113 }
114
115 VG_STATIC void vg_tex2d_qoi( void *mem, u32 size, const char *name )
116 {
117 qoi_desc info;
118 u8 *tex_buffer = qoi_decode( mem, size, &info, 4 );
119
120 if( tex_buffer )
121 {
122 vg_info( "Texture decoded: [%u %u] %s\n",
123 info.width, info.height, name );
124
125 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height,
126 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer );
127
128 QOI_FREE(tex_buffer);
129 }
130 else
131 {
132 vg_error( "File size: %u\n", size );
133 vg_tex2d_set_error();
134 }
135 }
136
137 VG_STATIC GLuint vg_tex2d_rgba( const char *path )
138 {
139 GLuint texture_name = vg_tex2d_new();
140
141 vg_linear_clear( vg_mem.scratch );
142 u32 size;
143 void *file = vg_file_read( vg_mem.scratch, path, &size );
144
145 if( file )
146 {
147 vg_tex2d_qoi( file, size, path );
148 }
149 else
150 {
151 vg_error( "Loading texture failed (%s)\n", path );
152 vg_tex2d_set_error();
153 }
154
155 return texture_name;
156 }
157
158 VG_STATIC void vg_tex2d_init( vg_tex2d *textures[], int num )
159 {
160 for( int i=0; i<num; i ++ )
161 {
162 vg_tex2d *tex = textures[i];
163 tex->name = vg_tex2d_rgba( tex->path );
164 if( !(tex->flags & VG_TEXTURE_NO_MIP) )
165 vg_tex2d_mipmap();
166
167 if( tex->flags & VG_TEXTURE_NEAREST )
168 {
169 if( tex->flags & VG_TEXTURE_NO_MIP )
170 vg_error( "Invalid texture settings\n" );
171 else
172 vg_tex2d_nearest();
173 }
174 else
175 {
176 if( tex->flags & VG_TEXTURE_NO_MIP )
177 vg_tex2d_linear();
178 else
179 vg_tex2d_linear_mipmap();
180 }
181
182 if( tex->flags & VG_TEXTURE_CLAMP )
183 vg_tex2d_clamp();
184 else
185 vg_tex2d_repeat();
186
187 tex->flags |= VG_TEXTURE_ALLOCATED_INTERNAL;
188 }
189 }
190
191 VG_STATIC void vg_tex2d_free( vg_tex2d *textures[], int num )
192 {
193 for( int i = 0; i < num; i ++ )
194 {
195 glDeleteTextures( 1, &textures[i]->name );
196 }
197 }
198
199 #endif /* VG_TEX_H */