gl4es updated, added latest changes by ptitSeb
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
gl4es
|
||||
====
|
||||
|
||||
This is a library providing OpenGL 1.x functionality for OpenGL ES accelerated cards.
|
||||
This is a library providing OpenGL 1.x functionality for OpenGL ES accelerated hardware.
|
||||
|
||||
This is a fork a glshim (https://github.com/lunixbochs/glshim). Go check this lib if you need things like RemoteGL or if need support for TinyGLES (for 100% software rendering).
|
||||
|
||||
The focusse is on compatibility with a wide selection of game and software, as well as speed.
|
||||
|
||||
It has been tested successfully of a large selection of games and software, including: Mincraft, OpenMW, SeriousSam, RVGL, TSMC, TORCS, SpeedDreams, GL-117, Blender 2.68 and many more.
|
||||
|
||||
Most function of OpenGL up to 1.5 are supported, with some notable exceptions:
|
||||
* Reading of Depth or Stencil buffer will not work
|
||||
* GL_FEEDBACK mode is not implemented
|
||||
|
||||
Some know limitations:
|
||||
* GL_SELECT as some limitation in its implementation (for exemple, current Depth buffer or binded texture are not taken into account)
|
||||
* NPOT texture are supported, but not with GL_REPEAT / GL_MIRRORED, only GL_CLAMP will work properly
|
||||
* NPOT texture are supported, but not with GL_REPEAT / GL_MIRRORED, only GL_CLAMP will work properly (unless the GLES Hardware support NPOT)
|
||||
* Framebuffer use FRAMEBUFFER_OES extension (that must be present in the GLES 1.1 stack)
|
||||
* Multiple Color attachment on Framebuffer are not supported
|
||||
* OcclusionQuery is implemented, but with a 0 bits precision
|
||||
@@ -214,6 +216,10 @@ Initial Hardware test
|
||||
Version history
|
||||
----
|
||||
|
||||
##### 0.9.2
|
||||
* All matrix are tracked now
|
||||
* Texture Matrix are 100% handled by gl4es. GLES Hardware keep an Identity matrix (TexCoord are transformed if needed). This allows a better handling of NPOT texture on hadware that doesn't support Full NPOT (fixed movies beiing horizontaly shifted in openmw with LIBGL_NPOT=1 for example)
|
||||
|
||||
##### 0.9.1
|
||||
* Added gl4es specifics glHint capabilities. If the extension GL_GL4ES_hint is present, than a few Hint are accessible. Look in include/gl4eshint.h for the list.
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ GLvoid *copy_gl_array(const GLvoid *src,
|
||||
|
||||
GLvoid *copy_gl_array_texcoord(const GLvoid *src,
|
||||
GLenum from, GLsizei width, GLsizei stride,
|
||||
GLenum to, GLsizei to_width, GLsizei skip, GLsizei count, GLvoid* filler) {
|
||||
GLenum to, GLsizei to_width, GLsizei skip, GLsizei count, GLvoid* filler, void* dest) {
|
||||
if (! src || !count)
|
||||
return NULL;
|
||||
|
||||
@@ -74,7 +74,7 @@ GLvoid *copy_gl_array_texcoord(const GLvoid *src,
|
||||
stride = width * gl_sizeof(from);
|
||||
|
||||
const char *unknown_str = "libGL: copy_gl_array -> unknown type: %x\n";
|
||||
GLvoid *dst = malloc((count-skip) * to_width * gl_sizeof(to));
|
||||
GLvoid *dst = (dest)?dest:malloc((count-skip) * to_width * gl_sizeof(to));
|
||||
GLsizei from_size = gl_sizeof(from) * width;
|
||||
GLsizei to_elem = gl_sizeof(to);
|
||||
//texcoord are now 4 dim, so this should never happens
|
||||
@@ -262,7 +262,13 @@ GLvoid *copy_gl_pointer_raw(pointer_state_t *ptr, GLsizei width, GLsizei skip, G
|
||||
GLvoid *copy_gl_pointer_tex(pointer_state_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
|
||||
float filler = 1.0f;
|
||||
return copy_gl_array_texcoord(ptr->pointer, ptr->type, ptr->size, ptr->stride,
|
||||
GL_FLOAT, width, skip, count, &filler);
|
||||
GL_FLOAT, width, skip, count, &filler, 0);
|
||||
}
|
||||
|
||||
void copy_gl_pointer_tex_noalloc(void* dest, pointer_state_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
|
||||
float filler = 1.0f;
|
||||
copy_gl_array_texcoord(ptr->pointer, ptr->type, ptr->size, ptr->stride,
|
||||
GL_FLOAT, width, skip, count, &filler, dest);
|
||||
}
|
||||
|
||||
GLfloat *gl_pointer_index(pointer_state_t *p, GLint index) {
|
||||
|
||||
@@ -18,6 +18,7 @@ GLvoid *copy_gl_pointer_color(pointer_state_t *ptr, GLsizei width, GLsizei skip,
|
||||
GLvoid *copy_gl_pointer_bytecolor(pointer_state_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
|
||||
GLvoid *copy_gl_pointer_raw(pointer_state_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
|
||||
GLvoid *copy_gl_pointer_tex(pointer_state_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
|
||||
void copy_gl_pointer_tex_noalloc(void* dest, pointer_state_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
|
||||
GLfloat *gl_pointer_index(pointer_state_t *ptr, GLint index);
|
||||
GLfloat *copy_eval_double(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder, const GLdouble *points);
|
||||
void normalize_indices(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count);
|
||||
|
||||
@@ -373,11 +373,6 @@ static inline bool should_intercept_render(GLenum mode) {
|
||||
// check bounded tex that will be used if one need some transformations
|
||||
for (int aa=0; aa<hardext.maxtex; aa++) {
|
||||
if (glstate->enable.texture_2d[aa] || glstate->enable.texture_1d[aa] || glstate->enable.texture_3d[aa]) {
|
||||
if(glstate->texture.rect_arb[aa])
|
||||
return true;
|
||||
gltexture_t *bound = glstate->texture.bound[aa];
|
||||
if (bound && (bound->width!=bound->nwidth || bound->height!=bound->nheight))
|
||||
return true;
|
||||
if ((glstate->enable.texgen_s[aa] || glstate->enable.texgen_t[aa] || glstate->enable.texgen_r[aa] || glstate->enable.texgen_q[aa]))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "debug.h"
|
||||
#include "../glx/hardext.h"
|
||||
#include "init.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#define alloc_sublist(n, cap) \
|
||||
(GLfloat *)malloc(n * sizeof(GLfloat) * cap)
|
||||
@@ -682,10 +683,6 @@ void adjust_renderlist(renderlist_t *list) {
|
||||
// in case of Texture bounding inside a list
|
||||
if (list->set_texture && (list->tmu == a))
|
||||
bound = gl4es_getTexture(list->target_texture, list->texture);
|
||||
// adjust the tex_coord now
|
||||
if ((list->tex[a]) && (bound) && ((bound->width != bound->nwidth) || (bound->height != bound->nheight))) {
|
||||
tex_coord_npot(list->tex[a], list->len, bound->width, bound->height, bound->nwidth, bound->nheight);
|
||||
}
|
||||
// GL_ARB_texture_rectangle
|
||||
if ((list->tex[a]) && glstate->texture.rect_arb[a] && (bound)) {
|
||||
tex_coord_rect_arb(list->tex[a], list->len, bound->width, bound->height);
|
||||
@@ -922,28 +919,47 @@ void draw_renderlist(renderlist_t *list) {
|
||||
list->tex[0] = gen_stipple_tex_coords(list->vert, list->len);
|
||||
}
|
||||
}
|
||||
GLfloat *texgened[MAX_TEX];
|
||||
static GLfloat *texgened[MAX_TEX] = {0};
|
||||
static int texgenedsz[MAX_TEX] = {0};
|
||||
int use_texgen[MAX_TEX];
|
||||
#define RS(A, len) if(texgenedsz[A]<len) {free(texgened[A]); texgened[A]=malloc(4*sizeof(GLfloat)*len); texgenedsz[A]=len; } use_texgen[A]=1
|
||||
GLint needclean[MAX_TEX];
|
||||
for (int a=0; a<hardext.maxtex; a++) {
|
||||
texgened[a]=NULL;
|
||||
needclean[a]=0;
|
||||
use_texgen[a]=0;
|
||||
if ((glstate->enable.texgen_s[a] || glstate->enable.texgen_t[a] || glstate->enable.texgen_r[a] || glstate->enable.texgen_q[a])) {
|
||||
RS(a, list->len);
|
||||
gen_tex_coords(list->vert, list->normal, &texgened[a], list->len, &needclean[a], a, (list->ilen<list->len)?indices:NULL, (list->ilen<list->len)?list->ilen:0);
|
||||
} else if (glstate->enable.texture_2d[a] && (list->tex[a]==NULL) && !(list->mode==GL_POINT && glstate->texture.pscoordreplace[a])) {
|
||||
RS(a, list->len);
|
||||
gen_tex_coords(list->vert, list->normal, &texgened[a], list->len, &needclean[a], a, (list->ilen<list->len)?indices:NULL, (list->ilen<list->len)?list->ilen:0);
|
||||
}
|
||||
}
|
||||
// adjust the tex_coord now if needed, even on texgened ones
|
||||
gltexture_t *bound = glstate->texture.bound[a];
|
||||
if((list->tex[a] || use_texgen[a]) && ((!glstate->texture_matrix[a]->identity) || (bound) && ((bound->width != bound->nwidth) || (bound->height != bound->nheight)))) {
|
||||
if(!use_texgen[a]) {
|
||||
RS(a, list->len);
|
||||
memcpy(texgened[a], list->tex[a], 4*sizeof(GLfloat)*list->len);
|
||||
}
|
||||
if (!glstate->texture_matrix[a]->identity)
|
||||
tex_coord_matrix(texgened[a], list->len, getTexMat(a));
|
||||
if ((bound) && ((bound->width != bound->nwidth) || (bound->height != bound->nheight))) {
|
||||
tex_coord_npot(texgened[a], list->len, bound->width, bound->height, bound->nwidth, bound->nheight);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef RS
|
||||
old_tex = glstate->texture.client;
|
||||
GLuint cur_tex = old_tex;
|
||||
#define TEXTURE(A) if (cur_tex!=A) {gl4es_glClientActiveTexture(A+GL_TEXTURE0); cur_tex=A;}
|
||||
for (int a=0; a<hardext.maxtex; a++) {
|
||||
if ((list->tex[a] || texgened[a])/* && glstate->enable.texture_2d[a]*/) {
|
||||
if ((list->tex[a] || use_texgen[a])/* && glstate->enable.texture_2d[a]*/) {
|
||||
TEXTURE(a);
|
||||
if(!glstate->clientstate.tex_coord_array[a]) {
|
||||
gles_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glstate->clientstate.tex_coord_array[a] = 1;
|
||||
}
|
||||
gles_glTexCoordPointer(4, GL_FLOAT, 0, (texgened[a])?texgened[a]:list->tex[a]);
|
||||
gles_glTexCoordPointer(4, GL_FLOAT, 0, (use_texgen[a])?texgened[a]:list->tex[a]);
|
||||
} else {
|
||||
if (glstate->clientstate.tex_coord_array[a]) {
|
||||
TEXTURE(a);
|
||||
@@ -1158,10 +1174,6 @@ void draw_renderlist(renderlist_t *list) {
|
||||
TEXTURE(a);
|
||||
gen_tex_clean(needclean[a], a);
|
||||
}
|
||||
if (texgened[a]) {
|
||||
free(texgened[a]);
|
||||
texgened[a] = NULL;
|
||||
}
|
||||
if (!glstate->enable.texture_2d[a] && (glstate->enable.texture_1d[a] || glstate->enable.texture_3d[a])) {
|
||||
TEXTURE(a);
|
||||
gles_glDisable(GL_TEXTURE_2D);
|
||||
|
||||
@@ -12,14 +12,10 @@
|
||||
void alloc_matrix(matrixstack_t **matrixstack, int depth) {
|
||||
*matrixstack = (matrixstack_t*)malloc(sizeof(matrixstack_t));
|
||||
(*matrixstack)->top = 0;
|
||||
(*matrixstack)->identity = 0;
|
||||
(*matrixstack)->stack = (GLfloat*)malloc(sizeof(GLfloat)*depth*16);
|
||||
}
|
||||
|
||||
void set_identity(GLfloat* mat) {
|
||||
memset(mat, 0, 16*sizeof(GLfloat));
|
||||
mat[0] = mat[1+4] = mat[2+8] = mat[3+12] = 1.0f;
|
||||
}
|
||||
|
||||
#define TOP(A) (glstate->A->stack+(glstate->A->top*16))
|
||||
|
||||
static GLfloat* update_current_mat() {
|
||||
@@ -34,19 +30,45 @@ static GLfloat* update_current_mat() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int update_current_identity(int I) {
|
||||
switch(glstate->matrix_mode) {
|
||||
case GL_MODELVIEW:
|
||||
return glstate->modelview_matrix->identity = (I)?1:is_identity(TOP(modelview_matrix));
|
||||
case GL_PROJECTION:
|
||||
return glstate->projection_matrix->identity = (I)?1:is_identity(TOP(projection_matrix));
|
||||
case GL_TEXTURE:
|
||||
return glstate->texture_matrix[glstate->texture.active]->identity = (I)?1:is_identity(TOP(texture_matrix[glstate->texture.active]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_to_hardware() {
|
||||
switch(glstate->matrix_mode) {
|
||||
case GL_PROJECTION:
|
||||
return 1;
|
||||
case GL_MODELVIEW:
|
||||
return 1;
|
||||
case GL_TEXTURE:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_matrix(glstate_t* glstate) {
|
||||
alloc_matrix(&glstate->projection_matrix, MAX_STACK_PROJECTION);
|
||||
set_identity(TOP(projection_matrix));
|
||||
glstate->projection_matrix->identity = 1;
|
||||
alloc_matrix(&glstate->modelview_matrix, MAX_STACK_MODELVIEW);
|
||||
set_identity(TOP(modelview_matrix));
|
||||
glstate->modelview_matrix->identity = 1;
|
||||
glstate->texture_matrix = (matrixstack_t**)malloc(sizeof(matrixstack_t*)*MAX_TEX);
|
||||
for (int i=0; i<MAX_TEX; i++) {
|
||||
alloc_matrix(&glstate->texture_matrix[i], MAX_STACK_TEXTURE);
|
||||
set_identity(TOP(texture_matrix[i]));
|
||||
glstate->texture_matrix[i]->identity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gl4es_glMatrixMode(GLenum mode) {
|
||||
DBG(printf("glMatrixMode(%s), list=%p\n", PrintEnum(mode), glstate->list.active);)
|
||||
PUSH_IF_COMPILING(glMatrixMode);
|
||||
@@ -81,7 +103,7 @@ DBG(printf("glPushMatrix(), list=%p\n", glstate->list.active);)
|
||||
P(modelview_matrix, MODELVIEW);
|
||||
break;
|
||||
case GL_TEXTURE:
|
||||
P(texture_matrix[glstate->texture.active], PROJECTION);
|
||||
P(texture_matrix[glstate->texture.active], TEXTURE);
|
||||
break;
|
||||
#undef P
|
||||
default:
|
||||
@@ -103,7 +125,8 @@ DBG(printf("glPopMatrix(), list=%p\n", glstate->list.active);)
|
||||
switch(matrix_mode) {
|
||||
#define P(A) if(glstate->A->top) { \
|
||||
--glstate->A->top; \
|
||||
gles_glLoadMatrixf(update_current_mat()); \
|
||||
glstate->A->identity = is_identity(update_current_mat()); \
|
||||
if (send_to_hardware()) gles_glLoadMatrixf(update_current_mat()); \
|
||||
} else errorShim(GL_STACK_UNDERFLOW)
|
||||
case GL_PROJECTION:
|
||||
P(projection_matrix);
|
||||
@@ -127,6 +150,7 @@ DBG(printf("glPopMatrix(), list=%p\n", glstate->list.active);)
|
||||
void gl4es_glLoadMatrixf(const GLfloat * m) {
|
||||
DBG(printf("glLoadMatrix(%f, %f, %f, %f, %f, %f, %f...), list=%p\n", m[0], m[1], m[2], m[3], m[4], m[5], m[6], glstate->list.active);)
|
||||
LOAD_GLES(glLoadMatrixf);
|
||||
LOAD_GLES(glLoadIdentity);
|
||||
|
||||
if ((glstate->list.compiling || glstate->gl_batch) && glstate->list.active) {
|
||||
NewStage(glstate->list.active, STAGE_MATRIX);
|
||||
@@ -135,12 +159,16 @@ DBG(printf("glLoadMatrix(%f, %f, %f, %f, %f, %f, %f...), list=%p\n", m[0], m[1],
|
||||
return;
|
||||
}
|
||||
memcpy(update_current_mat(), m, 16*sizeof(GLfloat));
|
||||
gles_glLoadMatrixf(m);
|
||||
const int id = update_current_identity(0);
|
||||
if(send_to_hardware())
|
||||
if(id) gles_glLoadIdentity(); // in case the driver as some special optimisations
|
||||
else gles_glLoadMatrixf(m);
|
||||
}
|
||||
|
||||
void gl4es_glMultMatrixf(const GLfloat * m) {
|
||||
DBG(printf("glMultMatrix(%f, %f, %f, %f, %f, %f, %f...), list=%p\n", m[0], m[1], m[2], m[3], m[4], m[5], m[6], glstate->list.active);)
|
||||
LOAD_GLES(glLoadMatrixf);
|
||||
LOAD_GLES(glLoadIdentity);
|
||||
if ((glstate->list.compiling || glstate->gl_batch) && glstate->list.active) {
|
||||
if(glstate->list.active->stage == STAGE_MATRIX) {
|
||||
// multiply the matrix mith the current one....
|
||||
@@ -154,7 +182,10 @@ DBG(printf("glMultMatrix(%f, %f, %f, %f, %f, %f, %f...), list=%p\n", m[0], m[1],
|
||||
}
|
||||
GLfloat *current_mat = update_current_mat();
|
||||
matrix_mul(current_mat, m, current_mat);
|
||||
gles_glLoadMatrixf(current_mat);
|
||||
const int id = update_current_identity(0);
|
||||
if(send_to_hardware())
|
||||
if(id) gles_glLoadIdentity(); // in case the driver as some special optimisations
|
||||
else gles_glLoadMatrixf(current_mat);
|
||||
}
|
||||
|
||||
void gl4es_glLoadIdentity() {
|
||||
@@ -168,7 +199,8 @@ DBG(printf("glLoadIdentity(), list=%p\n", glstate->list.active);)
|
||||
}
|
||||
|
||||
set_identity(update_current_mat());
|
||||
gles_glLoadIdentity();
|
||||
update_current_identity(1);
|
||||
if(send_to_hardware()) gles_glLoadIdentity();
|
||||
}
|
||||
|
||||
void gl4es_glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
@@ -237,16 +269,14 @@ DBG(printf("glFrustumf(%f, %f, %f, %f, %f, %f) list=%p\n", left, right, top, bot
|
||||
GLfloat tmp[16];
|
||||
memset(tmp, 0, 16*sizeof(GLfloat));
|
||||
|
||||
tmp[0+0] = 2.0f*nearVal/(right-left); tmp[0+8] = -(right+left)/(right-left);
|
||||
tmp[1+4] = 2.0f*nearVal/(top-bottom); tmp[1+8] = -(top+bottom)/(top-bottom);
|
||||
tmp[2+8] =-(farVal+nearVal)/(farVal-nearVal); tmp[2+12] = -2.0f*farVal*nearVal/(farVal-nearVal);
|
||||
tmp[0+0] = 2.0f*nearVal/(right-left); tmp[0+8] = (right+left)/(right-left);
|
||||
tmp[1+4] = 2.0f*nearVal/(top-bottom); tmp[1+8] = (top+bottom)/(top-bottom);
|
||||
tmp[2+8] =-(farVal+nearVal)/(farVal-nearVal); tmp[2+12] =-2.0f*farVal*nearVal/(farVal-nearVal);
|
||||
tmp[3+8] = -1.0f;
|
||||
|
||||
gl4es_glMultMatrixf(tmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void glMatrixMode(GLenum mode) AliasExport("gl4es_glMatrixMode");
|
||||
void glPushMatrix() AliasExport("gl4es_glPushMatrix");
|
||||
void glPopMatrix() AliasExport("gl4es_glPopMatrix");
|
||||
|
||||
@@ -11,3 +11,7 @@ void gl4es_glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void gl4es_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
void gl4es_glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal);
|
||||
void gl4es_glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal);
|
||||
|
||||
static inline GLfloat* getTexMat(int tmu) {
|
||||
return glstate->texture_matrix[tmu]->stack+glstate->texture_matrix[tmu]->top*16;
|
||||
}
|
||||
|
||||
@@ -67,10 +67,11 @@ void vector_matrix(const float *a, const float *b, float *c) {
|
||||
: "%2", "q0", "q1", "q2", "memory"
|
||||
);
|
||||
#else
|
||||
c[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12];
|
||||
c[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13];
|
||||
c[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14];
|
||||
c[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15];
|
||||
const float a0=a[0], a1=a[1], a2=a[2], a3=a[3];
|
||||
c[0] = a0 * b[0] + a1 * b[4] + a2 * b[8] + a3 * b[12];
|
||||
c[1] = a0 * b[1] + a1 * b[5] + a2 * b[9] + a3 * b[13];
|
||||
c[2] = a0 * b[2] + a1 * b[6] + a2 * b[10] + a3 * b[14];
|
||||
c[3] = a0 * b[3] + a1 * b[7] + a2 * b[11] + a3 * b[15];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -283,3 +284,14 @@ void matrix_mul(const float *a, const float *b, float *c) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_identity(float* mat) {
|
||||
memset(mat, 0, 16*sizeof(GLfloat));
|
||||
mat[0] = mat[1+4] = mat[2+8] = mat[3+12] = 1.0f;
|
||||
}
|
||||
|
||||
int is_identity(const float* mat) {
|
||||
static float i1[16];
|
||||
static int set=0;
|
||||
if(!set) {set_identity(i1); set=1;}
|
||||
return memcmp(mat, i1, 16*sizeof(float))==0?1:0;
|
||||
}
|
||||
@@ -13,6 +13,7 @@ void vector4_normalize(float *a);
|
||||
void matrix_transpose(const float *a, float *b);
|
||||
void matrix_inverse(const float *m, float *r);
|
||||
void matrix_mul(const float *a, const float *b, float *c);
|
||||
|
||||
void set_identity(float* mat);
|
||||
int is_identity(const float* mat);
|
||||
|
||||
#endif
|
||||
@@ -117,6 +117,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int top;
|
||||
int identity;
|
||||
GLfloat *stack;
|
||||
} matrixstack_t;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ void gl4es_glTexGenfv(GLenum coord, GLenum pname, const GLfloat *param) {
|
||||
generation function specified by pname.
|
||||
*/
|
||||
|
||||
//printf("glTexGenfv(%s, %s, [%s, ...]), texture=%i\n", PrintEnum(coord), PrintEnum(pname), PrintEnum(param[0]), glstate->texture.active);
|
||||
//printf("glTexGenf(%s, %s, %s/%f), texture=%i\n", PrintEnum(coord), PrintEnum(pname), PrintEnum(param[0]), param[0], glstate->texture.active);
|
||||
if ((glstate->list.compiling || glstate->gl_batch) && glstate->list.active) {
|
||||
NewStage(glstate->list.active, STAGE_TEXGEN);
|
||||
rlTexGenfv(glstate->list.active, coord, pname, param);
|
||||
@@ -151,9 +151,7 @@ void sphere_loop(const GLfloat *verts, const GLfloat *norm, GLfloat *out, GLint
|
||||
GLfloat ModelviewMatrix[16], InvModelview[16];
|
||||
gl4es_glGetFloatv(GL_MODELVIEW_MATRIX, InvModelview);
|
||||
// column major -> row major
|
||||
for (int i=0; i<4; i++)
|
||||
for (int j=0; j<4; j++)
|
||||
ModelviewMatrix[i*4+j]=InvModelview[i+j*4];
|
||||
matrix_transpose(InvModelview, ModelviewMatrix);
|
||||
// And get the inverse
|
||||
matrix_inverse(ModelviewMatrix, InvModelview);
|
||||
GLfloat eye[4], eye_norm[4], reflect[4];
|
||||
@@ -177,6 +175,36 @@ void sphere_loop(const GLfloat *verts, const GLfloat *norm, GLfloat *out, GLint
|
||||
|
||||
}
|
||||
|
||||
void reflection_loop(const GLfloat *verts, const GLfloat *norm, GLfloat *out, GLint count, GLushort *indices) {
|
||||
// based on https://www.opengl.org/wiki/Mathematics_of_glTexGen
|
||||
/* if (!norm) {
|
||||
printf("LIBGL: GL_REFLECTION_MAP without Normals\n");
|
||||
return;
|
||||
}*/
|
||||
// First get the ModelviewMatrix
|
||||
GLfloat ModelviewMatrix[16], InvModelview[16];
|
||||
gl4es_glGetFloatv(GL_MODELVIEW_MATRIX, InvModelview);
|
||||
// column major -> row major
|
||||
matrix_transpose(InvModelview, ModelviewMatrix);
|
||||
// And get the inverse
|
||||
matrix_inverse(ModelviewMatrix, InvModelview);
|
||||
GLfloat eye[4], eye_norm[4];
|
||||
GLfloat a;
|
||||
for (int i=0; i<count; i++) {
|
||||
GLushort k = indices?indices[i]:i;
|
||||
matrix_vector(ModelviewMatrix, verts+k*4, eye);
|
||||
vector4_normalize(eye);
|
||||
vector3_matrix((norm)?(norm+k*3):glstate->normal, InvModelview, eye_norm);
|
||||
vector4_normalize(eye_norm);
|
||||
a=dot4(eye, eye_norm)*2.0f;
|
||||
out[k*4+0] = eye[0] - eye_norm[0]*a;
|
||||
out[k*4+1] = eye[1] - eye_norm[1]*a;
|
||||
out[k*4+2] = eye[2] - eye_norm[2]*a;
|
||||
out[k*4+3] = 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void eye_loop(const GLfloat *verts, const GLfloat *param, GLfloat *out, GLint count, GLushort *indices) {
|
||||
// based on https://www.opengl.org/wiki/Mathematics_of_glTexGen
|
||||
// First get the ModelviewMatrix
|
||||
@@ -231,10 +259,10 @@ void gen_tex_coords(GLfloat *verts, GLfloat *norm, GLfloat **coords, GLint count
|
||||
// special case: SPHERE_MAP needs both texgen to make sense
|
||||
if ((glstate->enable.texgen_s[texture] && (glstate->texgen[texture].S==GL_SPHERE_MAP)) && (glstate->enable.texgen_t[texture] && (glstate->texgen[texture].T==GL_SPHERE_MAP)))
|
||||
{
|
||||
if (!glstate->enable.texture_2d[texture])
|
||||
return;
|
||||
if ((*coords)==NULL)
|
||||
*coords = (GLfloat *)malloc(count * 4 * sizeof(GLfloat));
|
||||
if (!glstate->enable.texture_2d[texture])
|
||||
return;
|
||||
if ((*coords)==NULL)
|
||||
*coords = (GLfloat *)malloc(count * 4 * sizeof(GLfloat));
|
||||
sphere_loop(verts, norm, *coords, (indices)?ilen:count, indices);
|
||||
return;
|
||||
}
|
||||
@@ -243,22 +271,11 @@ void gen_tex_coords(GLfloat *verts, GLfloat *norm, GLfloat **coords, GLint count
|
||||
&& (glstate->enable.texgen_t[texture] && (glstate->texgen[texture].T==GL_REFLECTION_MAP))
|
||||
&& (glstate->enable.texgen_r[texture] && (glstate->texgen[texture].R==GL_REFLECTION_MAP)))
|
||||
{
|
||||
*needclean=1;
|
||||
// setup reflection map!
|
||||
GLuint old_tex=glstate->texture.active;
|
||||
if (old_tex!=texture) gl4es_glActiveTexture(GL_TEXTURE0 + texture);
|
||||
LOAD_GLES_OES(glTexGeni);
|
||||
LOAD_GLES_OES(glTexGenfv);
|
||||
LOAD_GLES(glEnable);
|
||||
// setup cube map mode
|
||||
gles_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
gles_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
gles_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
||||
// enable texgen
|
||||
gles_glEnable(GL_TEXTURE_GEN_STR); //GLES only support the 3 gen at the same time!
|
||||
|
||||
if (old_tex!=texture) gl4es_glActiveTexture(GL_TEXTURE0 + old_tex);
|
||||
|
||||
if (!glstate->enable.texture_2d[texture])
|
||||
return;
|
||||
if ((*coords)==NULL)
|
||||
*coords = (GLfloat *)malloc(count * 4 * sizeof(GLfloat));
|
||||
reflection_loop(verts, norm, *coords, (indices)?ilen:count, indices);
|
||||
return;
|
||||
}
|
||||
// special case: NORMAL_MAP needs the 3 texgen to make sense
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "../glx/streaming.h"
|
||||
#include "../glx/hardext.h"
|
||||
#include "init.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#ifndef GL_TEXTURE_STREAM_IMG
|
||||
#define GL_TEXTURE_STREAM_IMG 0x8C0D
|
||||
@@ -46,7 +47,6 @@ void tex_coord_npot(GLfloat *tex, GLsizei len,
|
||||
GLsizei nwidth, GLsizei nheight) {
|
||||
if (!tex || !nwidth || !nheight)
|
||||
return;
|
||||
|
||||
GLfloat wratio = (width / (GLfloat)nwidth);
|
||||
GLfloat hratio = (height / (GLfloat)nheight);
|
||||
for (int i = 0; i < len; i++) {
|
||||
@@ -56,42 +56,52 @@ void tex_coord_npot(GLfloat *tex, GLsizei len,
|
||||
}
|
||||
}
|
||||
|
||||
void tex_coord_matrix(GLfloat *tex, GLsizei len, const GLfloat* mat) {
|
||||
if (!tex || !len || !mat)
|
||||
return;
|
||||
for (int i = 0; i < len; i++) {
|
||||
vector_matrix(tex, mat, tex);
|
||||
tex += 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the texture coordinates
|
||||
*
|
||||
* Have to check is ARB_RECTANGLE is used
|
||||
* Apply texture matrix if not identity
|
||||
* Or some NPOT texture used
|
||||
* Or SHRINKED texure used
|
||||
*/
|
||||
void tex_setup_texcoord(GLuint len) {
|
||||
LOAD_GLES(glTexCoordPointer);
|
||||
GLuint texunit = glstate->texture.client;
|
||||
|
||||
static void * tex[8] = {0,0,0,0,0,0,0,0}; // hugly but convenient...
|
||||
static void * tex[MAX_TEX] = {0};
|
||||
static int texlen[MAX_TEX] = {0};
|
||||
|
||||
if (tex[texunit]) {
|
||||
free(tex[texunit]);
|
||||
tex[texunit]=NULL;
|
||||
}
|
||||
|
||||
gltexture_t *bound = glstate->texture.bound[texunit];
|
||||
|
||||
// check if some changes are needed
|
||||
int changes = 0;
|
||||
if ((glstate->texture.rect_arb[texunit]) ||
|
||||
(bound && ((bound->width!=bound->nwidth)||(bound->height!=bound->nheight)||
|
||||
(bound->shrink && (glstate->vao->pointers.tex_coord[texunit].type!=GL_FLOAT) && (glstate->vao->pointers.tex_coord[texunit].type!=GL_DOUBLE)))))
|
||||
if ((glstate->texture.rect_arb[texunit])
|
||||
|| (bound && ((bound->width!=bound->nwidth)||(bound->height!=bound->nheight)
|
||||
)) || !glstate->texture_matrix[texunit]->identity
|
||||
)
|
||||
changes = 1;
|
||||
if (changes) {
|
||||
// first convert to GLfloat, without normalization
|
||||
tex[texunit] = copy_gl_pointer_tex(&glstate->vao->pointers.tex_coord[texunit], 4, 0, len);
|
||||
if (!tex[texunit]) {
|
||||
printf("LIBGL: Error with Texture tranform\n");
|
||||
gles_glTexCoordPointer(glstate->vao->pointers.tex_coord[texunit].size, glstate->vao->pointers.tex_coord[texunit].type, glstate->vao->pointers.tex_coord[texunit].stride, glstate->vao->pointers.tex_coord[texunit].pointer);
|
||||
return;
|
||||
if(texlen[texunit]<len) {
|
||||
if(tex[texunit]) free(tex[texunit]);
|
||||
tex[texunit] = malloc(4*sizeof(GLfloat)*len);
|
||||
texlen[texunit] = len;
|
||||
}
|
||||
copy_gl_pointer_tex_noalloc(tex[texunit], &glstate->vao->pointers.tex_coord[texunit], 4, 0, len);
|
||||
// Normalize if needed
|
||||
if ((glstate->texture.rect_arb[texunit]) || ((glstate->vao->pointers.tex_coord[texunit].type!=GL_FLOAT) && (glstate->vao->pointers.tex_coord[texunit].type!=GL_DOUBLE)))
|
||||
if ((glstate->texture.rect_arb[texunit]))
|
||||
tex_coord_rect_arb(tex[texunit], len, bound->width, bound->height);
|
||||
// Apply transformation matrix if any
|
||||
if (!glstate->texture_matrix[texunit]->identity)
|
||||
tex_coord_matrix(tex[texunit], len, getTexMat(texunit));
|
||||
// NPOT adjust
|
||||
if ((bound->width!=bound->nwidth) || (bound->height!=bound->nheight))
|
||||
tex_coord_npot(tex[texunit], len, bound->width, bound->height, bound->nwidth, bound->nheight);
|
||||
// All done, setup the texcoord array now
|
||||
|
||||
@@ -88,6 +88,9 @@ void tex_coord_rect_arb(GLfloat *tex, GLsizei len,
|
||||
void tex_coord_npot(GLfloat *tex, GLsizei len,
|
||||
GLsizei width, GLsizei height,
|
||||
GLsizei nwidth, GLsizei nheight);
|
||||
|
||||
void tex_coord_matrix(GLfloat *tex, GLsizei len, const GLfloat* mat);
|
||||
|
||||
int npot(int n);
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../../version.h"
|
||||
#include "../gl/init.h"
|
||||
|
||||
#ifdef USE_FBIO
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
#define MAJOR 0
|
||||
#define MINOR 9
|
||||
#define REVISION 1
|
||||
#define REVISION 2
|
||||
|
||||
#endif //_GL4ES_VERSION_H
|
||||
Reference in New Issue
Block a user