mirror of https://github.com/raysan5/raylib
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:
parent
a632a04a30
commit
7d2318c167
21
src/models.c
21
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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
52
src/rlgl.c
52
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
121
src/textures.c
121
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):
|
||||
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue