aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorraysan5 <raysan5@gmail.com>2015-04-13 20:15:28 +0200
committerraysan5 <raysan5@gmail.com>2015-04-13 20:15:28 +0200
commit7d2318c1677fd6e81b8cc63b040289148ca8adfc (patch)
treea8782a2ecfa48440e8bad02ed3be112dbacac441 /src
parenta632a04a300a60232f6b9a941e73af08d74c6e6a (diff)
downloadraylib-7d2318c1677fd6e81b8cc63b040289148ca8adfc.tar.gz
raylib-7d2318c1677fd6e81b8cc63b040289148ca8adfc.zip
WIP on shaders and textures
Moved functions: LoadShader(), UnloadShader() Add support for PVR textures compressed/uncompressed WIP: Detect available extensions for compressed textures
Diffstat (limited to 'src')
-rw-r--r--src/models.c21
-rw-r--r--src/raylib.h3
-rw-r--r--src/rlgl.c52
-rw-r--r--src/rlgl.h6
-rw-r--r--src/textures.c121
5 files changed, 189 insertions, 14 deletions
diff --git a/src/models.c b/src/models.c
index f4f83fd8..ffb077d4 100644
--- a/src/models.c
+++ b/src/models.c
@@ -1101,12 +1101,33 @@ void UnloadModel(Model model)
rlDeleteShader(model.shader.id);
}
+// Link a texture to a model
void SetModelTexture(Model *model, Texture2D texture)
{
if (texture.id <= 0) model->texture.id = whiteTexture; // Default white texture (use mesh color)
else model->texture = texture;
}
+// Load a custom shader (vertex shader + fragment shader)
+Shader LoadShader(char *vsFileName, char *fsFileName)
+{
+ Shader shader = rlglLoadShader(vsFileName, fsFileName);
+
+ return shader;
+}
+
+// Unload a custom shader from memory
+void UnloadShader(Shader shader)
+{
+ rlDeleteShader(shader.id);
+}
+
+// Set shader for a model
+void SetModelShader(Model *model, Shader shader)
+{
+ rlglSetModelShader(model, shader);
+}
+
// Draw a model (with texture if set)
void DrawModel(Model model, Vector3 position, float scale, Color tint)
{
diff --git a/src/raylib.h b/src/raylib.h
index 0e532ebe..603cc47d 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -338,6 +338,8 @@ typedef enum {
COMPRESSED_ETC1_RGB, // 4 bpp
COMPRESSED_ETC2_RGB, // 4 bpp
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
+ COMPRESSED_PVRT_RGB, // 4 bpp
+ COMPRESSED_PVRT_RGBA, // 4 bpp
/*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp
} TextureFormat;
@@ -543,6 +545,7 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size,
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader (vertex shader + fragment shader)
+void UnloadShader(Shader shader); // Unload a custom shader from memory
bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);
bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2);
diff --git a/src/rlgl.c b/src/rlgl.c
index c4deda8f..cedad6a7 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -793,7 +793,7 @@ void rlglInit(void)
const GLubyte *extensionName = glGetStringi(GL_EXTENSIONS, i);
if (strcmp(extensionName, (const GLubyte *)"GL_ARB_vertex_array_object") == 0)
{
- // The extension is supported by our hardware and driver, try to get related functions popinters
+ // The extension is supported by our hardware and driver, try to get related functions pointers
glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)wglGetProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)wglGetProcAddress("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)wglGetProcAddress("glDeleteVertexArrays");
@@ -851,14 +851,40 @@ void rlglInit(void)
// Show supported extensions
// NOTE: We don't need that much data on screen... right now...
-/*
+
#if defined(GRAPHICS_API_OPENGL_33)
GLint numExt;
glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
for (int i = 0; i < numExt; i++)
{
- TraceLog(INFO, "Supported extension: %s", glGetStringi(GL_EXTENSIONS, i));
+ //TraceLog(INFO, "Supported extension: %s", glGetStringi(GL_EXTENSIONS, i));
+ /*
+ if (strcmp(glGetStringi(GL_EXTENSIONS, i),"GL_EXT_texture_compression_s3tc") == 0)
+ {
+ // DDS texture compression support
+
+ // TODO: Check required tokens
+ }
+ else if (strcmp(glGetStringi(GL_EXTENSIONS, i),"GL_OES_compressed_ETC1_RGB8_texture") == 0)
+ {
+ // ETC1 texture compression support
+ }
+ else if (strcmp(glGetStringi(GL_EXTENSIONS, i),"GL_ARB_ES3_compatibility") == 0)
+ {
+ //OES_compressed_ETC2_RGB8_texture,
+ //OES_compressed_ETC2_RGBA8_texture,
+ // ETC2/EAC texture compression support
+ }
+ else if (strcmp(glGetStringi(GL_EXTENSIONS, i),"GL_IMG_texture_compression_pvrtc") == 0)
+ {
+ // PVR texture compression support
+ }
+ else if (strcmp(glGetStringi(GL_EXTENSIONS, i),"GL_KHR_texture_compression_astc_hdr") == 0)
+ {
+ // ASTC texture compression support
+ }
+ */
}
#elif defined(GRAPHICS_API_OPENGL_ES2)
char *extensions = (char *)glGetString(GL_EXTENSIONS); // One big string
@@ -866,7 +892,7 @@ void rlglInit(void)
// NOTE: String could be splitted using strtok() function (string.h)
TraceLog(INFO, "Supported extension: %s", extensions);
#endif
-*/
+
/*
GLint numComp = 0;
glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numComp);
@@ -894,7 +920,7 @@ void rlglInit(void)
// Init default Shader (GLSL 110) -> Common for GL 3.3+ and ES2
defaultShader = LoadDefaultShader();
simpleShader = LoadSimpleShader();
- //customShader = LoadShader("custom.vs", "custom.fs"); // Works ok
+ //customShader = rlglLoadShader("custom.vs", "custom.fs"); // Works ok
InitializeBuffers(); // Init vertex arrays
InitializeBuffersGPU(); // Init VBO and VAO
@@ -1795,7 +1821,7 @@ Model rlglLoadModel(VertexData mesh)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Load a shader (vertex shader + fragment shader) from text data
-unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr)
+unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr)
{
unsigned int program;
GLuint vertexShader;
@@ -1915,17 +1941,17 @@ unsigned char *rlglReadScreenPixels(int width, int height)
return imgData; // NOTE: image data should be freed
}
-// Load a shader (vertex shader + fragment shader) from text data
-Shader LoadShader(char *vsFileName, char *fsFileName)
+// Load a shader (vertex shader + fragment shader) from files
+Shader rlglLoadShader(char *vsFileName, char *fsFileName)
{
Shader shader;
-
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Shaders loading from external text file
char *vShaderStr = TextFileRead(vsFileName);
char *fShaderStr = TextFileRead(fsFileName);
- shader.id = rlglLoadShader(vShaderStr, fShaderStr);
+ shader.id = rlglLoadShaderFromText(vShaderStr, fShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shader.id);
@@ -1955,7 +1981,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
}
// Link shader to model
-void SetModelShader(Model *model, Shader shader)
+void rlglSetModelShader(Model *model, Shader shader)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
model->shader = shader;
@@ -2079,7 +2105,7 @@ static Shader LoadDefaultShader(void)
" gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor; \n"
"} \n";
- shader.id = rlglLoadShader(vShaderStr, fShaderStr);
+ shader.id = rlglLoadShaderFromText(vShaderStr, fShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id);
else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id);
@@ -2145,7 +2171,7 @@ static Shader LoadSimpleShader(void)
" gl_FragColor = texture2D(texture0, fragTexCoord) * tintColor; \n"
"} \n";
- shader.id = rlglLoadShader(vShaderStr, fShaderStr);
+ shader.id = rlglLoadShaderFromText(vShaderStr, fShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Simple shader loaded successfully", shader.id);
else TraceLog(WARNING, "[SHDR ID %i] Simple shader could not be loaded", shader.id);
diff --git a/src/rlgl.h b/src/rlgl.h
index c1d71cc9..3335fe16 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -104,6 +104,8 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
COMPRESSED_ETC1_RGB, // 4 bpp
COMPRESSED_ETC2_RGB, // 4 bpp
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
+ COMPRESSED_PVRT_RGB, // 4 bpp
+ COMPRESSED_PVRT_RGBA, // 4 bpp
/*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp
} TextureFormat;
@@ -208,10 +210,12 @@ void rlglDraw(void); // Draw VAO/VBO
void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff)
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load in GPU OpenGL texture
-unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr); // Load a shader from text data
+Shader rlglLoadShader(char *vsFileName, char *fsFileName); // Load a shader (vertex shader + fragment shader) from files
+unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr); // Load a shader from text data
void rlglInitPostpro(void); // Initialize postprocessing system
void rlglDrawPostpro(void); // Draw with postprocessing shader
void rlglSetPostproShader(Shader shader); // Set postprocessing shader
+void rlglSetModelShader(Model *model, Shader shader); // Set shader for a model
Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids
void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires);
diff --git a/src/textures.c b/src/textures.c
index e45739ac..1d22e509 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -70,6 +70,7 @@ typedef struct {
//----------------------------------------------------------------------------------
static ImageEx LoadDDS(const char *fileName); // Load DDS file
static ImageEx LoadPKM(const char *fileName); // Load PKM file
+static ImageEx LoadPVR(const char *fileName); // Load PVR file
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -326,6 +327,20 @@ Texture2D LoadTexture(const char *fileName)
free(image.data);
}
+ else if (strcmp(GetExtension(fileName),"pvr") == 0)
+ {
+ ImageEx image = LoadPVR(fileName);
+
+ texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps, false);
+
+ texture.width = image.width;
+ texture.height = image.height;
+
+ if (texture.id == 0) TraceLog(WARNING, "[%s] PVR texture could not be loaded", fileName);
+ else TraceLog(INFO, "[%s] PVR texture loaded successfully", fileName);
+
+ free(image.data);
+ }
else
{
Image image = LoadImage(fileName);
@@ -694,6 +709,7 @@ static ImageEx LoadDDS(const char *fileName)
// Loading PKM image data (ETC1/ETC2 compression)
// NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps)
// PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps)
+// ETC1 compression support requires extension GL_OES_compressed_ETC1_RGB8_texture
static ImageEx LoadPKM(const char *fileName)
{
// If OpenGL ES 2.0. the following format could be supported (ETC1):
@@ -772,4 +788,109 @@ static ImageEx LoadPKM(const char *fileName)
}
return image;
+}
+
+// Loading PVR image data (uncompressed or PVRT compression)
+// NOTE: PVR compression requires extension GL_IMG_texture_compression_pvrtc (PowerVR GPUs)
+static ImageEx LoadPVR(const char *fileName)
+{
+ // If supported in OpenGL ES 2.0. the following formats could be defined:
+ // GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG (RGB)
+ // GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG (RGBA)
+
+ // PVR file v2 Header (52 bytes)
+ typedef struct {
+ unsigned int headerLength;
+ unsigned int height;
+ unsigned int width;
+ unsigned int numMipmaps;
+ unsigned int flags;
+ unsigned int dataLength;
+ unsigned int bpp;
+ unsigned int bitmaskRed;
+ unsigned int bitmaskGreen;
+ unsigned int bitmaskBlue;
+ unsigned int bitmaskAlpha;
+ unsigned int pvrTag;
+ unsigned int numSurfs;
+ } pvrHeaderV2;
+
+ // PVR file v3 Header (52 bytes)
+ // NOTE: After it could be metadata (15 bytes?)
+ typedef struct {
+ unsigned int version;
+ unsigned int flags;
+ unsigned long long pixelFormat;
+ unsigned int colourSpace;
+ unsigned int channelType;
+ unsigned int height;
+ unsigned int width;
+ unsigned int depth;
+ unsigned int numSurfaces;
+ unsigned int numFaces;
+ unsigned int numMipmaps;
+ unsigned int metaDataSize;
+ } pvrHeaderV3;
+
+ // Bytes Swap (little-endian <-> big-endian)
+ //unsigned short data;
+ //unsigned short swap = ((data & 0x00FF) << 8) | ((data & 0xFF00) >> 8);
+
+ ImageEx image;
+
+ image.data = NULL;
+ image.width = 0;
+ image.height = 0;
+ image.mipmaps = 0;
+ image.format = 0;
+
+ FILE *pvrFile = fopen(fileName, "rb");
+
+ if (pvrFile == NULL)
+ {
+ TraceLog(WARNING, "[%s] PVR image file could not be opened", fileName);
+ }
+ else
+ {
+ // Check PVR image version
+ unsigned int pvrVersion = 0;
+ fread(&pvrVersion, sizeof(unsigned int), 1, pvrFile);
+ fsetpos(pvrFile, 0);
+
+ if (pvrVersion == 52)
+ {
+ pvrHeaderV2 header;
+
+ fread(&header, sizeof(pvrHeaderV2), 1, pvrFile);
+
+ image.width = header.width;
+ image.height = header.height;
+ image.mipmaps = header.numMipmaps;
+ image.format = COMPRESSED_PVRT_RGB; //COMPRESSED_PVRT_RGBA
+ }
+ else if (pvrVersion == 3)
+ {
+ pvrHeaderV3 header;
+
+ fread(&header, sizeof(pvrHeaderV3), 1, pvrFile);
+
+ image.width = header.width;
+ image.height = header.height;
+ image.mipmaps = header.numMipmaps;
+
+ // TODO: Skip metaDataSize
+
+ image.format = COMPRESSED_PVRT_RGB; //COMPRESSED_PVRT_RGBA
+ }
+
+ int size = (image.width/4)*(image.height/4)*8; // Total data size in bytes
+
+ image.data = (unsigned char*)malloc(size * sizeof(unsigned char));
+
+ fread(image.data, 1, size, pvrFile);
+
+ fclose(pvrFile); // Close file pointer
+ }
+
+ return image;
} \ No newline at end of file