Thu, 24 Apr 2025 19:53:40 +0200
in preparation of more scenes, bring back AscScene struct
50 | 1 | /* |
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
3 | * Copyright 2024 Mike Becker. All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are met: | |
7 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
25 | * POSSIBILITY OF SUCH DAMAGE. | |
26 | */ | |
27 | ||
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
28 | #include "ascension/context.h" |
50 | 29 | #include "ascension/texture.h" |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
30 | #include "ascension/filesystem.h" |
50 | 31 | |
32 | #include <assert.h> | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
33 | #include <cx/utils.h> |
50 | 34 | #include <GL/glew.h> |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
35 | #include <SDL2/SDL_image.h> |
50 | 36 | |
37 | void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) { | |
38 | glActiveTexture(GL_TEXTURE0 + unit); | |
39 | GLenum error = glGetError(); | |
40 | if (error == GL_INVALID_ENUM) { | |
92 | 41 | GLint max_units; |
42 | glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_units); | |
43 | asc_error("Tried to use more texture units than available (%u/%u).", unit, max_units); | |
50 | 44 | } |
45 | glBindTexture(tex->target, tex->tex_id); | |
46 | glUniform1i(uniform_location, unit); | |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
47 | asc_error_catch_all_gl(); |
50 | 48 | } |
49 | ||
50 | void asc_texture_from_surface(AscTexture *tex, SDL_Surface const *surface) { | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
51 | if (tex->tex_id == 0) { |
92 | 52 | asc_error("Tried to use uninitialized texture (%"PRIxPTR ").", (uintptr_t) tex); |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
53 | return; |
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
54 | } |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
55 | tex->width = surface->w; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
56 | tex->height = surface->h; |
50 | 57 | glBindTexture(tex->target,tex->tex_id); |
58 | glPixelStorei(GL_UNPACK_ROW_LENGTH, | |
59 | surface->pitch / surface->format->BytesPerPixel); | |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
60 | |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
61 | // Determine the format and internal format based on the SDL surface format |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
62 | GLint internal_format; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
63 | GLenum format; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
64 | switch (surface->format->format) { |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
65 | case SDL_PIXELFORMAT_RGB24: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
66 | internal_format = GL_RGB8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
67 | format = GL_RGB; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
68 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
69 | case SDL_PIXELFORMAT_BGR24: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
70 | internal_format = GL_RGB8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
71 | format = GL_BGR; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
72 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
73 | case SDL_PIXELFORMAT_RGBA32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
74 | case SDL_PIXELFORMAT_ABGR32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
75 | internal_format = GL_RGBA8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
76 | format = GL_RGBA; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
77 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
78 | case SDL_PIXELFORMAT_ARGB32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
79 | case SDL_PIXELFORMAT_BGRA32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
80 | internal_format = GL_RGBA8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
81 | format = GL_BGRA; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
82 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
83 | default: |
92 | 84 | asc_error("Unsupported pixel format: %x", surface->format->format); |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
85 | return; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
86 | } |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
87 | glTexImage2D(tex->target, 0, internal_format, |
50 | 88 | surface->w, surface->h, |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
89 | 0, format, |
50 | 90 | GL_UNSIGNED_BYTE, surface->pixels); |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
91 | // TODO: replace catch all with proper error handling for this single call |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
92 | asc_error_catch_all_gl(); |
50 | 93 | } |
94 | ||
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
95 | void asc_texture_from_file(AscTexture *tex, const char *name) { |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
96 | cxmutstr filepath = asc_filesystem_combine_paths(cx_strcast(asc_context.texture_path), cx_str(name)); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
97 | asc_dprintf("Load texture from %" CX_PRIstr, CX_SFMT(filepath)); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
98 | SDL_Surface *image = IMG_Load(filepath.ptr); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
99 | cx_strfree(&filepath); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
100 | if (image == NULL) { |
91
8433c87c0f51
improve error.c functions
Mike Becker <universe@uap-core.de>
parents:
89
diff
changeset
|
101 | asc_error("Failed to load texture: %s", IMG_GetError()); |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
102 | return; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
103 | } |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
104 | asc_texture_from_surface(tex, image); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
105 | asc_dprintf("Free temporary surface %"PRIxPTR, (uintptr_t) image); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
106 | SDL_FreeSurface(image); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
107 | } |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
108 | |
50 | 109 | void asc_texture_init( |
110 | AscTexture *tex, | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
111 | unsigned count, |
50 | 112 | enum asc_texture_target target, |
113 | enum asc_texture_min_filter min_filter, | |
114 | enum asc_texture_mag_filter mag_filter | |
115 | ) { | |
116 | static const GLenum texture_targets[] = { | |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
117 | GL_TEXTURE_RECTANGLE, |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
118 | GL_TEXTURE_2D, |
50 | 119 | }; |
120 | static const GLint texture_filters[] = { | |
121 | GL_NEAREST, | |
122 | GL_LINEAR, | |
123 | GL_NEAREST_MIPMAP_NEAREST, | |
124 | GL_LINEAR_MIPMAP_NEAREST, | |
125 | GL_NEAREST_MIPMAP_LINEAR, | |
126 | GL_LINEAR_MIPMAP_LINEAR | |
127 | }; | |
128 | assert(target < sizeof(texture_targets) / sizeof(GLenum)); | |
129 | assert(min_filter < sizeof(texture_filters) / sizeof(GLint)); | |
130 | assert(mag_filter < 2); // mag filter only supports nearest/linear | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
131 | |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
132 | GLuint textures[count]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
133 | glGenTextures(count, textures); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
134 | |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
135 | for (unsigned i = 0; i < count; ++i) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
136 | memset(&tex[i], 0, sizeof(AscTexture)); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
137 | tex[i].tex_id = textures[i]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
138 | tex[i].target = texture_targets[target]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
139 | glBindTexture(tex[i].target, tex[i].tex_id); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
140 | glTexParameteri(tex[i].target, GL_TEXTURE_MIN_FILTER, |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
141 | texture_filters[min_filter]); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
142 | glTexParameteri(tex[i].target, GL_TEXTURE_MAG_FILTER, |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
143 | texture_filters[mag_filter]); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
144 | asc_dprintf("Initialized texture: %u", tex[i].tex_id); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
145 | } |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
146 | |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
147 | // TODO: proper error handling for each gl call |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
148 | asc_error_catch_all_gl(); |
50 | 149 | } |
150 | ||
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
151 | void asc_texture_destroy(AscTexture *tex, unsigned count) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
152 | GLuint textures[count]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
153 | for (unsigned i = 0; i < count; ++i) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
154 | if (tex[i].refcount > 0) { |
92 | 155 | asc_wprintf("Texture %u still in use by %u objects.", |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
156 | tex[i].tex_id, tex[i].refcount); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
157 | } |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
158 | asc_dprintf("Destroy texture: %u", tex[i].tex_id); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
159 | textures[i] = tex[i].tex_id; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
160 | memset(&tex[i], 0, sizeof(AscTexture)); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
161 | } |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
162 | glDeleteTextures(count, textures); |
50 | 163 | } |