diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index 125802c..eac149c 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -98,6 +98,10 @@ struct UniformObject }; const char *shaderDecl330 = "#version 330\n"; +const char *shaderDecl100es = +"#version 100\n"\ +"precision highp float;\n"\ +"precision highp int;\n"; const char *shaderDecl310es = "#version 310 es\n"\ "precision highp float;\n"\ @@ -105,17 +109,40 @@ const char *shaderDecl310es = #ifdef RW_GLES3 const char *shaderDecl = shaderDecl310es; +#elif defined RW_GLES2 +const char *shaderDecl = shaderDecl100es; #else const char *shaderDecl = shaderDecl330; #endif +#ifndef RW_GLES2 static GLuint vao; static GLuint ubo_state, ubo_scene, ubo_object; +#endif static GLuint whitetex; static UniformState uniformState; static UniformScene uniformScene; static UniformObject uniformObject; +#ifdef RW_GLES2 +// State +int32 u_alphaRef; +int32 u_fogStart; +int32 u_fogEnd; +int32 u_fogRange; +int32 u_fogDisable; +int32 u_fogColor; + +// Scene +int32 u_proj; +int32 u_view; + +// Object +int32 u_world; +int32 u_ambLight; +// TODO: lights! +#endif + int32 u_matColor; int32 u_surfProps; @@ -727,9 +754,62 @@ setViewMatrix(float32 *mat) sceneDirty = 1; } +Shader *lastShaderUploaded; + void flushCache(void) { +#ifdef RW_GLES2 +#define U(i) currentShader->uniformLocations[i] + + // TODO: this is probably a stupid way to do it with gl2 + if(lastShaderUploaded != currentShader){ + lastShaderUploaded = currentShader; + objectDirty = 1; + sceneDirty = 1; + stateDirty = 1; + } + + if(objectDirty){ + glUniformMatrix4fv(U(u_world), 1, 0, (float*)&uniformObject.world); + glUniform4fv(U(u_ambLight), 1, (float*)&uniformObject.ambLight); + // TODO: lights somehow + objectDirty = 0; + } + + if(sceneDirty){ + glUniformMatrix4fv(U(u_proj), 1, 0, uniformScene.proj); + glUniformMatrix4fv(U(u_view), 1, 0, uniformScene.view); + sceneDirty = 0; + } + + if(stateDirty){ + uniformState.fogDisable = rwStateCache.fogEnable ? 0.0f : 1.0f; + uniformState.fogStart = rwStateCache.fogStart; + uniformState.fogEnd = rwStateCache.fogEnd; + uniformState.fogRange = 1.0f/(rwStateCache.fogStart - rwStateCache.fogEnd); + + switch(uniformState.alphaFunc){ + case ALPHAALWAYS: + default: + glUniform2f(U(u_alphaRef), -1000.0f, 1000.0f); + break; + case ALPHAGREATEREQUAL: + glUniform2f(U(u_alphaRef), uniformState.alphaRef, 1000.0f); + break; + case ALPHALESS: + glUniform2f(U(u_alphaRef), -1000.0f, uniformState.alphaRef); + break; + } + + glUniform1f(U(u_fogStart), uniformState.fogStart); + glUniform1f(U(u_fogEnd), uniformState.fogEnd); + glUniform1f(U(u_fogRange), uniformState.fogRange); + glUniform1f(U(u_fogDisable), uniformState.fogDisable); + glUniform4fv(U(u_fogColor), 1, (float*)&uniformState.fogColor); + stateDirty = 0; + } +#else if(objectDirty){ glBindBuffer(GL_UNIFORM_BUFFER, ubo_object); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformObject), @@ -752,6 +832,7 @@ flushCache(void) &uniformState); stateDirty = 0; } +#endif } static void @@ -1035,6 +1116,10 @@ openGLFW(EngineOpenParams *openparams) glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); +#elif defined RW_GLES2 + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); #else glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -1087,6 +1172,7 @@ startGLFW(void) return 0; } glfwMakeContextCurrent(win); +printf("version %s\n", glGetString(GL_VERSION)); /* Init GLEW */ glewExperimental = GL_TRUE; @@ -1119,9 +1205,23 @@ stopGLFW(void) static int initOpenGL(void) { +#ifdef RW_GLES2 + u_alphaRef = registerUniform("u_alphaRef"); + u_fogStart = registerUniform("u_fogStart"); + u_fogEnd = registerUniform("u_fogEnd"); + u_fogRange = registerUniform("u_fogRange"); + u_fogDisable = registerUniform("u_fogDisable"); + u_fogColor = registerUniform("u_fogColor"); + u_proj = registerUniform("u_proj"); + u_view = registerUniform("u_view"); + u_world = registerUniform("u_world"); + u_ambLight = registerUniform("u_ambLight"); + lastShaderUploaded = nil; +#else registerBlock("Scene"); registerBlock("Object"); registerBlock("State"); +#endif u_matColor = registerUniform("u_matColor"); u_surfProps = registerUniform("u_surfProps"); @@ -1137,6 +1237,7 @@ initOpenGL(void) resetRenderState(); +#ifndef RW_GLES2 glGenVertexArrays(1, &vao); glBindVertexArray(vao); @@ -1160,9 +1261,15 @@ initOpenGL(void) glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformObject), &uniformObject, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); +#endif +#ifdef RW_GLES2 +#include "gl2_shaders/default_vs_gl2.inc" +#include "gl2_shaders/simple_fs_gl2.inc" +#else #include "shaders/default_vs_gl3.inc" #include "shaders/simple_fs_gl3.inc" +#endif const char *vs[] = { shaderDecl, header_vert_src, default_vert_src, nil }; const char *fs[] = { shaderDecl, simple_frag_src, nil }; defaultShader = Shader::create(vs, fs); diff --git a/src/gl/gl3immed.cpp b/src/gl/gl3immed.cpp index 387a837..68d0c65 100644 --- a/src/gl/gl3immed.cpp +++ b/src/gl/gl3immed.cpp @@ -50,8 +50,13 @@ openIm2D(void) { u_xform = registerUniform("u_xform"); +#ifdef RW_GLES2 +#include "gl2_shaders/im2d_gl2.inc" +#include "gl2_shaders/simple_fs_gl2.inc" +#else #include "shaders/im2d_gl3.inc" #include "shaders/simple_fs_gl3.inc" +#endif const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *fs[] = { shaderDecl, simple_frag_src, nil }; im2dShader = Shader::create(vs, fs); @@ -179,8 +184,13 @@ static int32 num3DVertices; // not actually needed here void openIm3D(void) { +#ifdef RW_GLES2 +#include "gl2_shaders/im3d_gl2.inc" +#include "gl2_shaders/simple_fs_gl2.inc" +#else #include "shaders/im3d_gl3.inc" #include "shaders/simple_fs_gl3.inc" +#endif const char *vs[] = { shaderDecl, header_vert_src, im3d_vert_src, nil }; const char *fs[] = { shaderDecl, simple_frag_src, nil }; im3dShader = Shader::create(vs, fs); diff --git a/src/gl/gl3matfx.cpp b/src/gl/gl3matfx.cpp index 6679eab..5502b71 100644 --- a/src/gl/gl3matfx.cpp +++ b/src/gl/gl3matfx.cpp @@ -41,7 +41,11 @@ matfxOpen(void *o, int32, int32) u_colorClamp = registerUniform("u_colorClamp"); matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline(); +#ifdef RW_GLES2 +#include "gl2_shaders/matfx_gl2.inc" +#else #include "shaders/matfx_gl3.inc" +#endif const char *vs[] = { shaderDecl, header_vert_src, matfx_env_vert_src, nil }; const char *fs[] = { shaderDecl, matfx_env_frag_src, nil }; envShader = Shader::create(vs, fs); diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index f331438..1d1b62e 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -33,7 +33,7 @@ rasterCreateTexture(Raster *raster) natras->format = GL_RGBA; natras->type = GL_UNSIGNED_BYTE; natras->hasAlpha = 1; - natras->bbp = 4; + natras->bpp = 4; raster->depth = 32; break; case Raster::C888: @@ -41,7 +41,7 @@ rasterCreateTexture(Raster *raster) natras->format = GL_RGB; natras->type = GL_UNSIGNED_BYTE; natras->hasAlpha = 0; - natras->bbp = 3; + natras->bpp = 3; raster->depth = 24; break; case Raster::C1555: @@ -49,7 +49,7 @@ rasterCreateTexture(Raster *raster) natras->format = GL_RGBA; natras->type = GL_UNSIGNED_SHORT_5_5_5_1; natras->hasAlpha = 1; - natras->bbp = 2; + natras->bpp = 2; raster->depth = 16; break; default: @@ -57,7 +57,15 @@ rasterCreateTexture(Raster *raster) return nil; } - raster->stride = raster->width*natras->bbp; +#ifdef RW_GLES + // glReadPixels only supports GL_RGBA + natras->internalFormat = GL_RGBA8; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_BYTE; + natras->bpp = 4; +#endif + + raster->stride = raster->width*natras->bpp; glGenTextures(1, &natras->texid); glBindTexture(GL_TEXTURE_2D, natras->texid); @@ -91,6 +99,7 @@ rasterCreateCameraTexture(Raster *raster) natras->format = GL_RGBA; natras->type = GL_UNSIGNED_BYTE; natras->hasAlpha = 1; + natras->bpp = 4; break; case Raster::C888: default: @@ -98,15 +107,27 @@ rasterCreateCameraTexture(Raster *raster) natras->format = GL_RGB; natras->type = GL_UNSIGNED_BYTE; natras->hasAlpha = 0; + natras->bpp = 3; break; case Raster::C1555: natras->internalFormat = GL_RGB5_A1; natras->format = GL_RGBA; natras->type = GL_UNSIGNED_SHORT_5_5_5_1; natras->hasAlpha = 1; + natras->bpp = 2; break; } +#ifdef RW_GLES + // glReadPixels only supports GL_RGBA +// natras->internalFormat = GL_RGBA8; +// natras->format = GL_RGBA; +// natras->type = GL_UNSIGNED_BYTE; +// natras->bpp = 4; +#endif + + raster->stride = raster->width*natras->bpp; + glGenTextures(1, &natras->texid); glBindTexture(GL_TEXTURE_2D, natras->texid); glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, @@ -218,13 +239,28 @@ rasterLock(Raster *raster, int32 level, int32 lockMode) case Raster::TEXTURE: case Raster::CAMERATEXTURE: px = (uint8*)rwMalloc(raster->stride*raster->height, MEMDUR_EVENT | ID_DRIVER); +memset(px, 0, raster->stride*raster->height); assert(raster->pixels == nil); raster->pixels = px; if(lockMode & Raster::LOCKREAD || !(lockMode & Raster::LOCKNOFETCH)){ +#ifdef RW_GLES + GLuint fbo; +GLenum e; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0); + e = glCheckFramebufferStatus(GL_FRAMEBUFFER); +assert(natras->format == GL_RGBA); + glReadPixels(0, 0, raster->width, raster->height, natras->format, natras->type, px); +//e = glGetError(); printf("GL err4 %x (%x)\n", e, natras->format); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo); +#else uint32 prev = bindTexture(natras->texid); glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px); bindTexture(prev); +#endif } raster->privateFlags = lockMode; @@ -342,26 +378,38 @@ rasterFromImage(Raster *raster, Image *image) Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); switch(image->depth){ case 32: +#ifdef RW_GLES + conv = conv_RGBA8888_to_RGBA8888; +#else if(raster->format == Raster::C8888) conv = conv_RGBA8888_to_RGBA8888; else if(raster->format == Raster::C888) conv = conv_RGB888_to_RGB888; else goto err; +#endif break; case 24: +#ifdef RW_GLES + conv = conv_RGB888_to_RGBA8888; +#else if(raster->format == Raster::C8888) conv = conv_RGB888_to_RGBA8888; else if(raster->format == Raster::C888) conv = conv_RGB888_to_RGB888; else goto err; +#endif break; case 16: +#ifdef RW_GLES + conv = conv_RGBA1555_to_RGBA8888; +#else if(raster->format == Raster::C1555) conv = conv_RGBA1555_to_RGBA5551; else goto err; +#endif break; case 8: @@ -387,7 +435,7 @@ rasterFromImage(Raster *raster, Image *image) for(x = 0; x < image->width; x++){ conv(rasrow, imgrow); imgrow += image->bpp; - rasrow += natras->bbp; + rasrow += natras->bpp; } imgpixels -= image->stride; pixels += raster->stride; diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index 665b572..7057cc4 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -16,7 +16,11 @@ namespace rw { namespace gl3 { +#ifdef RW_GLES2 +#include "gl2_shaders/header_vs.inc" +#else #include "shaders/header_vs.inc" +#endif UniformRegistry uniformRegistry; @@ -68,6 +72,27 @@ findBlock(const char *name) Shader *currentShader; +static void +printShaderSource(const char **src) +{ + int f, l; + const char *file; + bool printline; + int line = 1; + for(f = 0; src[f]; f++){ + char c; + file = src[f]; + printline = true; + while(c = *file++, c != '\0'){ + if(printline) + printf("%.4d: ", line++); + putchar(c); + printline = c == '\n'; + } + putchar('\n'); + } +} + static int compileshader(GLenum type, const char **src, GLuint *shader) { @@ -83,6 +108,7 @@ compileshader(GLenum type, const char **src, GLuint *shader) glCompileShader(shdr); glGetShaderiv(shdr, GL_COMPILE_STATUS, &success); if(!success){ + printShaderSource(src); fprintf(stderr, "Error in %s shader\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment"); glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &len); @@ -105,6 +131,16 @@ linkprogram(GLint vs, GLint fs, GLuint *program) prog = glCreateProgram(); +#ifdef RW_GLES2 + // TODO: perhaps just do this always and get rid of the layout stuff? + glBindAttribLocation(prog, ATTRIB_POS, "in_pos"); + glBindAttribLocation(prog, ATTRIB_NORMAL, "in_normal"); + glBindAttribLocation(prog, ATTRIB_COLOR, "in_color"); + glBindAttribLocation(prog, ATTRIB_TEXCOORDS0, "in_tex0"); + glBindAttribLocation(prog, ATTRIB_WEIGHTS, "in_weights"); + glBindAttribLocation(prog, ATTRIB_INDICES, "in_indices"); +#endif + glAttachShader(prog, vs); glAttachShader(prog, fs); glLinkProgram(prog); @@ -150,6 +186,33 @@ Shader::create(const char **vsrc, const char **fsrc) Shader *sh = rwNewT(Shader, 1, MEMDUR_EVENT | ID_DRIVER); // or global? +#ifdef xxxRW_GLES2 + int numUniforms; + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms); + for(i = 0; i < numUniforms; i++){ + GLint size; + GLenum type; + char name[100]; + glGetActiveUniform(program, i, 100, nil, &size, &type, name); + printf("%d %d %s\n", size, type, name); + } + printf("\n"); +#endif + +#ifdef xxxRW_GLES2 + int numAttribs; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttribs); + for(i = 0; i < numAttribs; i++){ + GLint size; + GLenum type; + char name[100]; + glGetActiveAttrib(program, i, 100, nil, &size, &type, name); + GLint bind = glGetAttribLocation(program, name); + printf("%d %d %s. %d\n", size, type, name, bind); + } + printf("\n"); +#endif + // set uniform block binding for(i = 0; i < uniformRegistry.numBlocks; i++){ int idx = glGetUniformBlockIndex(program, diff --git a/src/gl/gl3skin.cpp b/src/gl/gl3skin.cpp index 4a37a82..acc0241 100644 --- a/src/gl/gl3skin.cpp +++ b/src/gl/gl3skin.cpp @@ -37,8 +37,13 @@ skinOpen(void *o, int32, int32) u_boneMatrices = registerUniform("u_boneMatrices"); skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline(); +#ifdef RW_GLES2 +#include "gl2_shaders/simple_fs_gl2.inc" +#include "gl2_shaders/skin_gl2.inc" +#else #include "shaders/simple_fs_gl3.inc" #include "shaders/skin_gl3.inc" +#endif const char *vs[] = { shaderDecl, header_vert_src, skin_vert_src, nil }; const char *fs[] = { shaderDecl, simple_frag_src, nil }; skinShader = Shader::create(vs, fs); @@ -60,12 +65,6 @@ initSkin(void) skinOpen, skinClose); } -enum -{ - ATTRIB_WEIGHTS = ATTRIB_TEXCOORDS7+1, - ATTRIB_INDICES -}; - void skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) { diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 031495b..c397b8f 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -47,12 +47,16 @@ enum AttribIndices ATTRIB_COLOR, ATTRIB_TEXCOORDS0, ATTRIB_TEXCOORDS1, +#ifndef RW_GLES2 ATTRIB_TEXCOORDS2, ATTRIB_TEXCOORDS3, ATTRIB_TEXCOORDS4, ATTRIB_TEXCOORDS5, ATTRIB_TEXCOORDS6, - ATTRIB_TEXCOORDS7 + ATTRIB_TEXCOORDS7, +#endif + ATTRIB_WEIGHTS, + ATTRIB_INDICES }; // default uniform indices @@ -217,7 +221,7 @@ struct Gl3Raster int32 internalFormat; int32 type; int32 format; - int32 bbp; // bytes per pixel + int32 bpp; // bytes per pixel // texture object uint32 texid; diff --git a/src/gl/shaders/header.vert b/src/gl/shaders/header.vert index 60127a4..1adc854 100644 --- a/src/gl/shaders/header.vert +++ b/src/gl/shaders/header.vert @@ -82,5 +82,5 @@ float DoFog(float w) } #define DIRECTIONALS -#define POINTLIGHTS -#define SPOTLIGHTS +//#define POINTLIGHTS +//#define SPOTLIGHTS diff --git a/src/gl/shaders/header_vs.inc b/src/gl/shaders/header_vs.inc index 569638b..695c7b5 100644 --- a/src/gl/shaders/header_vs.inc +++ b/src/gl/shaders/header_vs.inc @@ -83,6 +83,6 @@ const char *header_vert_src = "}\n" "#define DIRECTIONALS\n" -"#define POINTLIGHTS\n" -"#define SPOTLIGHTS\n" +"//#define POINTLIGHTS\n" +"//#define SPOTLIGHTS\n" ; diff --git a/src/gl/shaders/im2d.vert b/src/gl/shaders/im2d.vert index cff0870..241593b 100644 --- a/src/gl/shaders/im2d.vert +++ b/src/gl/shaders/im2d.vert @@ -12,6 +12,7 @@ void main(void) { gl_Position = in_pos; + gl_Position.w = 1.0; gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw; v_fog = DoFog(gl_Position.z); gl_Position.xyz *= gl_Position.w; diff --git a/src/gl/shaders/im2d_gl3.inc b/src/gl/shaders/im2d_gl3.inc index 3212919..68341b3 100644 --- a/src/gl/shaders/im2d_gl3.inc +++ b/src/gl/shaders/im2d_gl3.inc @@ -13,6 +13,7 @@ const char *im2d_vert_src = "main(void)\n" "{\n" " gl_Position = in_pos;\n" +" gl_Position.w = 1.0;\n" " gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n" " v_fog = DoFog(gl_Position.z);\n" " gl_Position.xyz *= gl_Position.w;\n" diff --git a/src/raster.cpp b/src/raster.cpp index d9bc806..866014f 100644 --- a/src/raster.cpp +++ b/src/raster.cpp @@ -259,4 +259,18 @@ conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in) out[1] = g>>2 | r<<3; } +void +conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in) +{ + uint32 r, g, b, a; + a = (in[1]>>7) & 1; + r = (in[1]>>2) & 0x1F; + g = (in[1]&3)<<3 | (in[0]>>5)&7; + b = in[0] & 0x1F; + out[0] = r*0xFF/0x1f; + out[1] = g*0xFF/0x1f; + out[2] = b*0xFF/0x1f; + out[3] = a*0xFF; +} + } diff --git a/src/rwbase.h b/src/rwbase.h index c956d08..63183d0 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -6,11 +6,20 @@ #define M_PI 3.14159265358979323846 #endif +// TODO: clean up the opengl defines +// and figure out what we even want here... #ifdef RW_GL3 #define RW_OPENGL #define RWDEVICE gl3 #endif +#ifdef RW_GLES2 +#define RW_GLES +#endif +#ifdef RW_GLES3 +#define RW_GLES +#endif + #ifdef RW_D3D9 #define RWDEVICE d3d #define RWHALFPIXEL diff --git a/src/rwobjects.h b/src/rwobjects.h index a7532ed..1ffcd1f 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -269,6 +269,7 @@ void conv_RGBA8888_to_RGBA8888(uint8 *out, uint8 *in); void conv_RGB888_to_RGBA8888(uint8 *out, uint8 *in); void conv_RGB888_to_RGB888(uint8 *out, uint8 *in); void conv_RGBA1555_to_RGBA5551(uint8 *out, uint8 *in); +void conv_RGBA1555_to_RGBA8888(uint8 *out, uint8 *in); #define IGNORERASTERIMP 0