Start implementing a multitexture example

This commit is contained in:
Luke Benstead 2018-08-17 07:09:53 +01:00
parent 37ba9bf3c3
commit d36469faaf
8 changed files with 327 additions and 3 deletions

View File

@ -1,5 +1,4 @@
#ifndef GLKOS_H
#define GLKOS_H
#pragma once
#include "gl.h"
@ -40,4 +39,3 @@ GLAPI void APIENTRY glKosSwapBuffers();
__END_DECLS
#endif // GLKOS_H

View File

@ -19,3 +19,4 @@ all:
$(KOS_MAKE) -C zclip_trianglestrip all
$(KOS_MAKE) -C terrain all
$(KOS_MAKE) -C quadmark all
$(KOS_MAKE) -C multitexture_arrays all

View File

@ -0,0 +1,29 @@
TARGET = multitexture_arrays.elf
OBJS = main.o pvr-texture.o
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

View File

@ -0,0 +1,121 @@
/*
KallistiOS 2.0.0
main.c
(c)2014 Josh Pearson
Open GL Multi-Texture example using Vertex Array Submission.
*/
#include <stdio.h>
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#include "glext.h"
/* Load a PVR texture - located in pvr-texture.c */
extern GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap);
GLfloat VERTEX_ARRAY[4 * 3] = { -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
GLfloat TEXCOORD_ARRAY[4 * 2] = { 0, 0,
1, 0,
1, 1,
0, 1
};
GLuint ARGB_ARRAY[4 * 1] = { 0xFFFF0000, 0xFF0000FF, 0xFF00FF00, 0xFFFFFF00 };
/* Multi-Texture Example using Open GL Vertex Buffer Submission. */
void RenderCallback(GLuint texID0, GLuint texID1) {
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -3.0f);
/* Enable Client States for OpenGL Arrays Submission */
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
/* Bind texture to GL_TEXTURE0_ARB and set texture parameters */
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FILTER, GL_LINEAR);
/* Bind multi-texture to GL_TEXTURE1_ARB and set texture parameters */
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
/* Set Blending Mode */
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
/* Bind texture coordinates to GL_TEXTURE0_ARB */
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORD_ARRAY);
/* Bind texture coordinates to GL_TEXTURE1_ARB */
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
/* Bind the Color Array */
glColorPointer(1, GL_UNSIGNED_INT, 0, ARGB_ARRAY);
/* Bind the Vertex Array */
glVertexPointer(3, GL_FLOAT, 0, VERTEX_ARRAY);
/* Render the Vertices as Indexed Arrays using glDrawArrays */
glDrawArrays(GL_QUADS, 0, 4);
/* Disable GL_TEXTURE1 */
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
/* Make sure to set glActiveTexture back to GL_TEXTURE0_ARB when finished */
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
/* Disable Vertex, Color and Texture Coord Arrays */
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
extern uint8 romdisk[];
KOS_INIT_ROMDISK(romdisk);
int main(int argc, char **argv) {
/* Notice we do not init the PVR here, that is handled by Open GL */
glKosInit();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 640.0f / 480.0f, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* Load two PVR textures to OpenGL */
GLuint texID0 = glTextureLoadPVR("/rd/wp001vq.pvr", 0, 0);
GLuint texID1 = glTextureLoadPVR("/rd/FlareWS_256.pvr", 0, 0);
while(1) {
/* Draw the "scene" */
RenderCallback(texID0, texID1);
/* Finish the frame - Notice there is no glKosBegin/FinshFrame */
glKosSwapBuffers();
}
return 0;
}

View File

@ -0,0 +1,175 @@
/*
KallistiOS 2.0.0
pvr-texture.c
(c)2014 Josh PH3NOM Pearson
Load A PVR Texture to the PVR using Open GL
*/
#include <kos.h>
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#include "glext.h"
#define PVR_HDR_SIZE 0x20
#define MAX(x, y) ((x > y) ? x : y)
static GLuint PVR_TextureHeight(unsigned char *HDR);
static GLuint PVR_TextureWidth(unsigned char *HDR);
static GLuint PVR_TextureFormat(unsigned char *HDR);
static GLuint _glGetMipmapLevelCount(GLuint width, GLuint height) {
return 1 + floor(log2(MAX(width, height)));
}
static GLuint _glGetMipmapDataSize(GLuint width, GLuint height) {
GLuint size = 0;
GLuint i = 0;
for(; i < _glGetMipmapLevelCount(width, height); ++i) {
size += (width * height * 2);
if(width > 1) {
width /= 2;
}
if(height > 1) {
height /= 2;
}
}
return size;
}
/* Load a PVR texture file into memory, and then bind the texture to Open GL.
fname is the name of the PVR texture file to be opened and read.
isMipMapped should be passed as 1 if the texture contains MipMap levels, 0 otherwise.
glMipMap should be passed as 1 if Open GL should calculate the Mipmap levels, 0 otherwise */
GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap) {
FILE *tex = NULL;
uint16 *TEX0 = NULL;
uint8 HDR[PVR_HDR_SIZE];
GLuint texID, texSize, texW, texH, texFormat;
/* Open the PVR texture file, and get its file size */
tex = fopen(fname, "rb");
if(tex == NULL) {
printf("FILE READ ERROR: %s\n", fname);
while(1);
}
fseek(tex, 0, SEEK_END);
texSize = ftell(tex) - PVR_HDR_SIZE;
fseek(tex, 0, SEEK_SET);
/* Read in the PVR texture file header */
fread(HDR, 1, PVR_HDR_SIZE, tex);
/* Extract some information from the PVR texture file header */
texW = PVR_TextureWidth(HDR);
texH = PVR_TextureHeight(HDR);
texFormat = PVR_TextureFormat(HDR);
/* Allocate Some Memory for the texture. If we are using Open GL to build the MipMap,
we need to allocate enough space to hold the MipMap texture levels. */
if(!isMipMapped && glMipMap)
TEX0 = malloc(_glGetMipmapDataSize(texW, texH));
else
TEX0 = malloc(texSize);
fread(TEX0, 1, texSize, tex); /* Read in the PVR texture data */
/* Generate and bind a texture as normal for Open GL */
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
if(texFormat != GL_UNSIGNED_SHORT_5_6_5)
glCompressedTexImage2DARB(GL_TEXTURE_2D,
0,
texFormat,
texW,
texH,
0,
texSize,
TEX0);
else {
fprintf(stderr, "%x\n", texFormat);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
texW, texH,
0,
GL_RGB,
texFormat,
TEX0);
if(!isMipMapped && glMipMap)
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
free(TEX0);
return texID;
}
static GLuint PVR_TextureFormat(unsigned char *HDR) {
GLuint color = (GLuint)HDR[PVR_HDR_SIZE - 8];
GLuint format = (GLuint)HDR[PVR_HDR_SIZE - 7];
GLboolean twiddled = format == 0x01;
GLboolean compressed = (format == 0x10 || format == 0x03);
if(compressed) {
if(twiddled) {
switch(color) {
case 0x0: {
return GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
} break;
case 0x01: {
return GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
} break;
case 0x02: {
return GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
} else {
switch(color) {
case 0: {
return GL_COMPRESSED_ARGB_1555_VQ_KOS;
} break;
case 1: {
return GL_COMPRESSED_RGB_565_VQ_KOS;
} break;
case 2: {
return GL_COMPRESSED_ARGB_4444_VQ_KOS;
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
}
} else {
if(color == 1) {
return GL_UNSIGNED_SHORT_5_6_5;
}
return 0;
}
}
static GLuint PVR_TextureWidth(unsigned char *HDR) {
return (GLuint)HDR[PVR_HDR_SIZE - 4] | HDR[PVR_HDR_SIZE - 3] << 8;
}
static GLuint PVR_TextureHeight(unsigned char *HDR) {
return (GLuint)HDR[PVR_HDR_SIZE - 2] | HDR[PVR_HDR_SIZE - 1] << 8;
}

Binary file not shown.

Binary file not shown.