-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtexture.c
136 lines (128 loc) · 3.77 KB
/
texture.c
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
/**
* Minimal routines for loading an OpenGL texture.
*
* Author: Tim Sjöstrand <[email protected]>
*/
#include <stdio.h>
#include <inttypes.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#include "graphics.h"
#include "color.h"
/**
* Parses pixel data from a compressed image.
*
* @param out Where to store pixel data.
* @param width Where to store image width.
* @param height Where to store image height.
* @param data The compressed image data to parse.
* @param len Length of the compressed data.
*/
int image_load(uint8_t **out, int *width, int *height, const uint8_t *data, size_t len)
{
int components;
uint8_t *tmp = stbi_load_from_memory(data, len, width, height, &components, STBI_rgb_alpha);
if(tmp == NULL) {
graphics_error("image_load(): %s\n", stbi_failure_reason());
return GRAPHICS_IMAGE_LOAD_ERROR;
}
*out = tmp;
return GRAPHICS_OK;
}
/**
* When an image has been loaded via image_load{_file}(), use image_free() to release
* it.
*
* @param data The data to release.
*/
void image_free(uint8_t *data)
{
stbi_image_free(data);
}
/**
* Loads raw RGBA data into an OpenGL texture.
*
* @param tex Where to store the texture id.
* @param data The image data to upload.
* @param width The width of the image.
* @param height The height of the image.
*/
int texture_load_pixels(GLuint *tex, const uint8_t *data,
const int width, const int height)
{
glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_2D, *tex);
/* Upload texture. */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data);
/* Wrapping. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* Filter (mipmap). */
// glGenerateMipmap(GL_TEXTURE_2D);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return GRAPHICS_OK;
}
/**
* Creates an empty texture, a white square. If a sprite does not have a
* texture, the fragment shader can still multiply this texture with a sprite
* color to produce the correct fragment color.
*/
void texture_white(GLuint *tex)
{
glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_2D, *tex);
/* Upload texture. */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
GL_FLOAT, COLOR_WHITE);
/* Wrapping. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
/* Filter. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void texture_free(const GLuint tex)
{
glDeleteTextures(1, &tex);
}
/**
* Parses the image data from a PNG, JPEG, BMP or TGA image and stores in an
* OpenGL texture.
*
* @param tex Store the OpenGL texture id here.
* @param width Store the width of the texture here (or NULL).
* @param height Store the height of the texture here (or NULL).
* @param data The image data to load.
* @param len The length of the image data.
*/
int texture_load(GLuint *tex, int *width, int *height, const uint8_t *data,
size_t len)
{
uint8_t *tmp;
int tmp_width;
int tmp_height;
int ret;
ret = image_load(&tmp, &tmp_width, &tmp_height, data, len);
if(ret != GRAPHICS_OK) {
return ret;
}
ret = texture_load_pixels(tex, tmp, tmp_width, tmp_height);
image_free(tmp);
if(ret != GRAPHICS_OK) {
texture_free(*tex);
return ret;
}
if(width != NULL) {
*(width) = tmp_width;
}
if(height != NULL) {
*(height) = tmp_height;
}
return GRAPHICS_OK;
}