WIP on shaders and textures

Moved functions: LoadShader(), UnloadShader()
Add support for PVR textures compressed/uncompressed
WIP: Detect available extensions for compressed textures
This commit is contained in:
raysan5 2015-04-13 20:15:28 +02:00
parent a632a04a30
commit 7d2318c167
5 changed files with 189 additions and 14 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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):
@ -771,5 +787,110 @@ 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;
}