diff --git a/src/base.cpp b/src/base.cpp index 5144d88..26481df 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -533,6 +533,61 @@ matrixPrint(float32 *mat) mat[3], mat[7], mat[11], mat[15]); } +#define PSEP_C '/' +#define PSEP_S "/" +#ifndef _WIN32 +#include +#include +#endif + +void +correctPathCase(char *filename) +{ +#ifndef _WIN32 + DIR *direct; + struct dirent *dirent; + + char *dir, *arg; + char copy[1024], sofar[1024] = "."; + strncpy(copy, filename, 1024); + arg = copy; + // hack for absolute paths + if(filename[0] == '/'){ + sofar[0] = '/'; + sofar[1] = '/'; + sofar[2] = '\0'; + arg++; + } + while(dir = strtok(arg, PSEP_S)){ + arg = nil; + if(direct = opendir(sofar), dir == nil) + return; + while(dirent = readdir(direct), dirent != nil) + if(strncmp_ci(dirent->d_name, dir, 1024) == 0){ + strncat(sofar, PSEP_S, 1024); + strncat(sofar, dirent->d_name, 1024); + break; + } + closedir(direct); + if(dirent == nil) + return; + } + strcpy(filename, sofar+2); +#endif +} + +void +makePath(char *filename) +{ + size_t len = strlen(filename); + for(size_t i = 0; i < len; i++) + if(filename[i] == '/' || filename[i] == '\\') + filename[i] = PSEP_C; +#ifndef _WIN32 + correctPathCase(filename); +#endif +} + int32 Stream::writeI8(int8 val) { diff --git a/src/bmp.cpp b/src/bmp.cpp new file mode 100644 index 0000000..683d5ea --- /dev/null +++ b/src/bmp.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include + +#include "rwbase.h" +#include "rwerror.h" +#include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwengine.h" + +#ifdef _WIN32 +/* srsly? */ +#define strdup _strdup +#endif + +#define PLUGIN_ID 0 + +namespace rw { + +/* can't write alpha */ +void +writeBMP(Image *image, const char *filename) +{ + uint8 buf[54]; + uint8 *p; + StreamFile file; + if(!file.open(filename, "wb")){ + RWERROR((ERR_FILE, filename)); + return; + } + + int32 pallen = image->depth > 8 ? 0 : + image->depth == 4 ? 16 : 256; + int32 stride = image->width*image->depth/8; + int32 depth = image->depth == 32 ? 24 : image->depth; + stride = stride+3 & ~3; + + // File header + p = buf; + *p++ = 'B'; + *p++ = 'M'; + *(uint32*)p = 0x36 + 4*pallen + image->height*stride; p += 4; + *(uint16*)p = 0; p += 2; // reserved + *(uint16*)p = 0; p += 2; + *(uint32*)p = 0x36 + 4*pallen; p += 4; // data offset + + // DIB header + *(uint32*)p = 0x28; p += 4; // header size + *(int32*)p = image->width; p += 4; + *(int32*)p = image->height; p += 4; + *(int16*)p = 1; p += 2; // number of planes + *(int16*)p = depth; p += 2; + *(uint32*)p = 0; p += 4; // compression: none + *(int32*)p = 0; p += 4; // size, not needed in our case + *(int32*)p = 2835; p += 4; // x resolution, 72dpi + *(int32*)p = 2835; p += 4; // y resolution + *(int32*)p = 0; p += 4; // number of used palette colors: max + *(int32*)p = 0; p += 4; // important pixels + + file.write(buf, 54); + + for(int i = 0; i < pallen; i++){ + file.writeU8(image->palette[i*4+2]); + file.writeU8(image->palette[i*4+1]); + file.writeU8(image->palette[i*4+0]); + file.writeU8(0); + } + + uint8 *line = image->pixels + (image->height-1)*image->stride; + int32 n; + for(int y = 0; y < image->height; y++){ + p = line; + for(int x = 0; x < image->width; x++){ + switch(image->depth){ + case 4: + file.writeU8((p[0]&0xF)<<4 | p[1]&0xF); + p += 2; + x++; + break; + case 8: + file.writeU8(*p++); + break; + case 16: + file.writeU8(p[0]); + file.writeU8(p[1]); + p += 2; + break; + case 24: + file.writeU8(p[2]); + file.writeU8(p[1]); + file.writeU8(p[0]); + p += 3; + break; + case 32: + file.writeU8(p[2]); + file.writeU8(p[1]); + file.writeU8(p[0]); + p += 4; + } + } + n = (p-line) % 4; + while(n--) + file.writeU8(0); + line -= image->stride; + } + + file.close(); +} + +} diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index db0f6d6..161af8e 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -460,9 +460,9 @@ rasterFromImage(Raster *raster, Image *image) in = image->palette; out = (uint8*)natras->palette; for(int32 i = 0; i < pallength; i++){ - out[0] = in[2]; + out[0] = in[0]; out[1] = in[1]; - out[2] = in[0]; + out[2] = in[2]; out[3] = in[3]; in += 4; out += 4; @@ -537,7 +537,7 @@ rasterToImage(Raster *raster) if((raster->format & Raster::PAL4) == Raster::PAL4){ depth = 4; pallength = 16; - }else if((raster->format & Raster::PAL4) == Raster::PAL8){ + }else if((raster->format & Raster::PAL8) == Raster::PAL8){ depth = 8; pallength = 256; } @@ -550,9 +550,9 @@ rasterToImage(Raster *raster) out = image->palette; in = (uint8*)natras->palette; for(int32 i = 0; i < pallength; i++){ - out[0] = in[2]; + out[0] = in[0]; out[1] = in[1]; - out[2] = in[0]; + out[2] = in[2]; out[3] = in[3]; in += 4; out += 4; diff --git a/src/d3d/d3ddriver.cpp b/src/d3d/d3ddriver.cpp index 51938fd..12cf481 100644 --- a/src/d3d/d3ddriver.cpp +++ b/src/d3d/d3ddriver.cpp @@ -7,6 +7,7 @@ #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" +#include "../rwengine.h" #include "rwd3d.h" namespace rw { @@ -224,7 +225,7 @@ beginUpdate(Camera *cam) proj[9] = cam->viewOffset.y*invwy; proj[12] = -proj[8]; proj[13] = -proj[9]; - if(cam->projection == PERSPECTIVE){ + if(cam->projection == Camera::PERSPECTIVE){ proj[10] = cam->farPlane*invz; proj[11] = 1.0f; @@ -242,8 +243,7 @@ beginUpdate(Camera *cam) void initializeRender(void) { - driver[PLATFORM_D3D8]->beginUpdate = beginUpdate; - driver[PLATFORM_D3D9]->beginUpdate = beginUpdate; + engine->beginUpdate = beginUpdate; } #endif diff --git a/src/frame.cpp b/src/frame.cpp index 5e2e05f..761c366 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -349,7 +349,7 @@ FrameList_::streamRead(Stream *stream) f->matrix.posw = 1.0f; //f->matflag = buf.matflag; if(buf.parent >= 0) - this->frames[buf.parent]->addChild(f); + this->frames[buf.parent]->addChild(f, rw::streamAppendFrames); } for(int32 i = 0; i < this->numFrames; i++) Frame::s_plglist.streamRead(stream, this->frames[i]); diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3driver.cpp index 4748a4a..50c62e3 100644 --- a/src/gl/gl3driver.cpp +++ b/src/gl/gl3driver.cpp @@ -420,7 +420,8 @@ initializeRender(void) engine->zNear = -1.0f; engine->zFar = 1.0f; - simpleShader = Shader::fromFiles("simple.vert", "simple.frag"); +#include "shaders/simple_gl3.inc" + simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); glClearColor(0.25, 0.25, 0.25, 1.0); diff --git a/src/gl/gl3plugins.cpp b/src/gl/gl3plugins.cpp index 0024dc7..f549741 100644 --- a/src/gl/gl3plugins.cpp +++ b/src/gl/gl3plugins.cpp @@ -32,8 +32,9 @@ Shader *envShader; static void* matfxOpen(void *o, int32, int32) { +#include "shaders/matfx_gl3.inc" matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline(); - envShader = Shader::fromFiles("matfx_env.vert", "matfx_env.frag"); + envShader = Shader::fromStrings(matfx_env_vert_src, matfx_env_frag_src); return o; } @@ -235,8 +236,10 @@ Shader *skinShader; static void* skinOpen(void *o, int32, int32) { +#include "shaders/simple_gl3.inc" +#include "shaders/skin_gl3.inc" skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline(); - skinShader = Shader::fromFiles("skin.vert", "simple.frag"); + skinShader = Shader::fromStrings(skin_vert_src, simple_frag_src); return o; } diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index b210e4e..af4a9f5 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -134,22 +134,18 @@ linkprogram(GLint vs, GLint fs, GLuint *program) } Shader* -Shader::fromFiles(const char *vspath, const char *fspath) +Shader::fromStrings(const char *vsrc, const char *fsrc) { GLuint vs, fs, program; int i; char *src; int fail; - src = loadfile(vspath); - fail = compileshader(GL_VERTEX_SHADER, src, &vs); - free(src); + fail = compileshader(GL_VERTEX_SHADER, vsrc, &vs); if(fail) return nil; - src = loadfile(fspath); - fail = compileshader(GL_FRAGMENT_SHADER, src, &fs); - free(src); + fail = compileshader(GL_FRAGMENT_SHADER, fsrc, &fs); if(fail) return nil; @@ -179,6 +175,18 @@ Shader::fromFiles(const char *vspath, const char *fspath) return sh; } +Shader* +Shader::fromFiles(const char *vspath, const char *fspath) +{ + char *vsrc, *fsrc; + vsrc = loadfile(vspath); + fsrc = loadfile(fspath); + Shader *s = fromStrings(vsrc, fsrc); + free(vsrc); + free(fsrc); + return s; +} + void Shader::use(void) { diff --git a/src/gl/rwgl3shader.h b/src/gl/rwgl3shader.h index 40f96b2..70134ff 100644 --- a/src/gl/rwgl3shader.h +++ b/src/gl/rwgl3shader.h @@ -33,6 +33,7 @@ public: GLint *uniformLocations; static Shader *fromFiles(const char *vs, const char *fs); + static Shader *fromStrings(const char *vsrc, const char *fsrc); void use(void); }; diff --git a/src/gl/shaders/Makefile b/src/gl/shaders/Makefile new file mode 100644 index 0000000..5d6fe06 --- /dev/null +++ b/src/gl/shaders/Makefile @@ -0,0 +1,23 @@ +all: simple_gl3.inc matfx_gl3.inc skin_gl3.inc + +simple_gl3.inc: simple.frag simple.vert + (echo 'const char *simple_vert_src =';\ + sed 's/..*/"&\\n"/' simple.vert;\ + echo ';';\ + echo 'const char *simple_frag_src =';\ + sed 's/..*/"&\\n"/' simple.frag;\ + echo ';') >simple_gl3.inc + +matfx_gl3.inc: matfx_env.frag matfx_env.vert + (echo 'const char *matfx_env_vert_src =';\ + sed 's/..*/"&\\n"/' matfx_env.vert;\ + echo ';';\ + echo 'const char *matfx_env_frag_src =';\ + sed 's/..*/"&\\n"/' matfx_env.frag;\ + echo ';') >matfx_gl3.inc + +skin_gl3.inc: skin.vert + (echo 'const char *skin_vert_src =';\ + sed 's/..*/"&\\n"/' skin.vert;\ + echo ';') >skin_gl3.inc + diff --git a/src/gl/shaders/matfx_env.frag b/src/gl/shaders/matfx_env.frag new file mode 100644 index 0000000..5c9522d --- /dev/null +++ b/src/gl/shaders/matfx_env.frag @@ -0,0 +1,34 @@ +#version 330 + +layout(std140) uniform State +{ + int u_alphaTest; + float u_alphaRef; + // fog etc. +}; + +uniform sampler2D tex; + +in vec4 v_color; +in vec2 v_tex0; + +out vec4 color; + +void +main(void) +{ + color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + switch(u_alphaTest){ + default: + case 0: break; + case 1: + if(color.a < u_alphaRef) + discard; + break; + case 2: + if(color.a >= u_alphaRef) + discard; + break; + } +} + diff --git a/src/gl/shaders/matfx_env.vert b/src/gl/shaders/matfx_env.vert new file mode 100644 index 0000000..d63ada2 --- /dev/null +++ b/src/gl/shaders/matfx_env.vert @@ -0,0 +1,58 @@ +#version 330 + +layout(std140) uniform Scene +{ + mat4 u_proj; + mat4 u_view; +}; + +#define MAX_LIGHTS 8 +struct Light { + vec4 position; + vec4 direction; + vec4 color; + float radius; + float minusCosAngle; +}; + +layout(std140) uniform Object +{ + mat4 u_world; + vec4 u_ambLight; + int u_numLights; + Light u_lights[MAX_LIGHTS]; +}; + +uniform vec4 u_matColor; +uniform vec4 u_surfaceProps; // amb, spec, diff, extra + +uniform mat4 u_texMatrix; +uniform float u_coefficient; + +layout(location = 0) in vec3 in_pos; +layout(location = 1) in vec3 in_normal; +layout(location = 2) in vec4 in_color; +layout(location = 3) in vec2 in_tex0; + +out vec4 v_color; +out vec2 v_tex0; + +void +main(void) +{ + vec4 V = u_world * vec4(in_pos, 1.0); + gl_Position = u_proj * u_view * V; + vec3 N = mat3(u_world) * in_normal; + + v_color = in_color; + for(int i = 0; i < u_numLights; i++){ + float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz))); + v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z; + } + v_color.rgb += u_ambLight.rgb*u_surfaceProps.x; + v_color *= u_matColor; + + v_color *= u_coefficient; + vec3 cN = mat3(u_view) * in_normal; + v_tex0 = (u_texMatrix * vec4(cN, 1.0)).xy; +} diff --git a/src/gl/shaders/matfx_gl3.inc b/src/gl/shaders/matfx_gl3.inc new file mode 100644 index 0000000..3a8f5f5 --- /dev/null +++ b/src/gl/shaders/matfx_gl3.inc @@ -0,0 +1,96 @@ +const char *matfx_env_vert_src = +"#version 330\n" + +"layout(std140) uniform Scene\n" +"{\n" +" mat4 u_proj;\n" +" mat4 u_view;\n" +"};\n" + +"#define MAX_LIGHTS 8\n" +"struct Light {\n" +" vec4 position;\n" +" vec4 direction;\n" +" vec4 color;\n" +" float radius;\n" +" float minusCosAngle;\n" +"};\n" + +"layout(std140) uniform Object\n" +"{\n" +" mat4 u_world;\n" +" vec4 u_ambLight;\n" +" int u_numLights;\n" +" Light u_lights[MAX_LIGHTS];\n" +"};\n" + +"uniform vec4 u_matColor;\n" +"uniform vec4 u_surfaceProps; // amb, spec, diff, extra\n" + +"uniform mat4 u_texMatrix;\n" +"uniform float u_coefficient;\n" + +"layout(location = 0) in vec3 in_pos;\n" +"layout(location = 1) in vec3 in_normal;\n" +"layout(location = 2) in vec4 in_color;\n" +"layout(location = 3) in vec2 in_tex0;\n" + +"out vec4 v_color;\n" +"out vec2 v_tex0;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 V = u_world * vec4(in_pos, 1.0);\n" +" gl_Position = u_proj * u_view * V;\n" +" vec3 N = mat3(u_world) * in_normal;\n" + +" v_color = in_color;\n" +" for(int i = 0; i < u_numLights; i++){\n" +" float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz)));\n" +" v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z;\n" +" }\n" +" v_color.rgb += u_ambLight.rgb*u_surfaceProps.x;\n" +" v_color *= u_matColor;\n" + +" v_color *= u_coefficient;\n" +" vec3 cN = mat3(u_view) * in_normal;\n" +" v_tex0 = (u_texMatrix * vec4(cN, 1.0)).xy;\n" +"}\n" +; +const char *matfx_env_frag_src = +"#version 330\n" + +"layout(std140) uniform State\n" +"{\n" +" int u_alphaTest;\n" +" float u_alphaRef;\n" +" // fog etc.\n" +"};\n" + +"uniform sampler2D tex;\n" + +"in vec4 v_color;\n" +"in vec2 v_tex0;\n" + +"out vec4 color;\n" + +"void\n" +"main(void)\n" +"{\n" +" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" switch(u_alphaTest){\n" +" default:\n" +" case 0: break;\n" +" case 1:\n" +" if(color.a < u_alphaRef)\n" +" discard;\n" +" break;\n" +" case 2:\n" +" if(color.a >= u_alphaRef)\n" +" discard;\n" +" break;\n" +" }\n" +"}\n" + +; diff --git a/src/gl/shaders/simple.frag b/src/gl/shaders/simple.frag new file mode 100644 index 0000000..11b2939 --- /dev/null +++ b/src/gl/shaders/simple.frag @@ -0,0 +1,41 @@ +#version 330 + +layout(std140) uniform State +{ + int u_alphaTest; + float u_alphaRef; + + int u_fogEnable; + float u_fogStart; + float u_fogEnd; + vec4 u_fogColor; +}; + +uniform sampler2D tex; + +in vec4 v_color; +in vec2 v_tex0; +in float v_fog; + +out vec4 color; + +void +main(void) +{ + color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + if(u_fogEnable != 0) + color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); + switch(u_alphaTest){ + default: + case 0: break; + case 1: + if(color.a < u_alphaRef) + discard; + break; + case 2: + if(color.a >= u_alphaRef) + discard; + break; + } +} + diff --git a/src/gl/shaders/simple.vert b/src/gl/shaders/simple.vert new file mode 100644 index 0000000..67e53bb --- /dev/null +++ b/src/gl/shaders/simple.vert @@ -0,0 +1,70 @@ +#version 330 + +layout(std140) uniform State +{ + int u_alphaTest; + float u_alphaRef; + + int u_fogEnable; + float u_fogStart; + float u_fogEnd; + vec4 u_fogColor; +}; + +layout(std140) uniform Scene +{ + mat4 u_proj; + mat4 u_view; +}; + +#define MAX_LIGHTS 8 +struct Light { + vec4 position; + vec4 direction; + vec4 color; + float radius; + float minusCosAngle; +}; + +layout(std140) uniform Object +{ + mat4 u_world; + vec4 u_ambLight; + int u_numLights; + Light u_lights[MAX_LIGHTS]; +}; + +uniform vec4 u_matColor; +uniform vec4 u_surfaceProps; // amb, spec, diff, extra + +layout(location = 0) in vec3 in_pos; +layout(location = 1) in vec3 in_normal; +layout(location = 2) in vec4 in_color; +layout(location = 3) in vec2 in_tex0; + +out vec4 v_color; +out vec2 v_tex0; +out float v_fog; + +void +main(void) +{ + vec3 lightdir = vec3(1.0, 1.0, -1.0); + + vec4 V = u_world * vec4(in_pos, 1.0); + vec4 cV = u_view * V; + gl_Position = u_proj * cV; + vec3 N = mat3(u_world) * in_normal; + + v_color = in_color; + for(int i = 0; i < u_numLights; i++){ + float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz))); + v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z; + } + v_color.rgb += u_ambLight.rgb*u_surfaceProps.x; + v_color *= u_matColor; + + v_tex0 = in_tex0; + + v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0); +} diff --git a/src/gl/shaders/simple_gl3.inc b/src/gl/shaders/simple_gl3.inc new file mode 100644 index 0000000..6d0e614 --- /dev/null +++ b/src/gl/shaders/simple_gl3.inc @@ -0,0 +1,115 @@ +const char *simple_vert_src = +"#version 330\n" + +"layout(std140) uniform State\n" +"{\n" +" int u_alphaTest;\n" +" float u_alphaRef;\n" + +" int u_fogEnable;\n" +" float u_fogStart;\n" +" float u_fogEnd;\n" +" vec4 u_fogColor;\n" +"};\n" + +"layout(std140) uniform Scene\n" +"{\n" +" mat4 u_proj;\n" +" mat4 u_view;\n" +"};\n" + +"#define MAX_LIGHTS 8\n" +"struct Light {\n" +" vec4 position;\n" +" vec4 direction;\n" +" vec4 color;\n" +" float radius;\n" +" float minusCosAngle;\n" +"};\n" + +"layout(std140) uniform Object\n" +"{\n" +" mat4 u_world;\n" +" vec4 u_ambLight;\n" +" int u_numLights;\n" +" Light u_lights[MAX_LIGHTS];\n" +"};\n" + +"uniform vec4 u_matColor;\n" +"uniform vec4 u_surfaceProps; // amb, spec, diff, extra\n" + +"layout(location = 0) in vec3 in_pos;\n" +"layout(location = 1) in vec3 in_normal;\n" +"layout(location = 2) in vec4 in_color;\n" +"layout(location = 3) in vec2 in_tex0;\n" + +"out vec4 v_color;\n" +"out vec2 v_tex0;\n" +"out float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec3 lightdir = vec3(1.0, 1.0, -1.0);\n" + +" vec4 V = u_world * vec4(in_pos, 1.0);\n" +" vec4 cV = u_view * V; \n" +" gl_Position = u_proj * cV;\n" +" vec3 N = mat3(u_world) * in_normal;\n" + +" v_color = in_color;\n" +" for(int i = 0; i < u_numLights; i++){\n" +" float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz)));\n" +" v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z;\n" +" }\n" +" v_color.rgb += u_ambLight.rgb*u_surfaceProps.x;\n" +" v_color *= u_matColor;\n" + +" v_tex0 = in_tex0;\n" + +" v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0);\n" +"}\n" +; +const char *simple_frag_src = +"#version 330\n" + +"layout(std140) uniform State\n" +"{\n" +" int u_alphaTest;\n" +" float u_alphaRef;\n" + +" int u_fogEnable;\n" +" float u_fogStart;\n" +" float u_fogEnd;\n" +" vec4 u_fogColor;\n" +"};\n" + +"uniform sampler2D tex;\n" + +"in vec4 v_color;\n" +"in vec2 v_tex0;\n" +"in float v_fog;\n" + +"out vec4 color;\n" + +"void\n" +"main(void)\n" +"{\n" +" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" if(u_fogEnable != 0)\n" +" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" +" switch(u_alphaTest){\n" +" default:\n" +" case 0: break;\n" +" case 1:\n" +" if(color.a < u_alphaRef)\n" +" discard;\n" +" break;\n" +" case 2:\n" +" if(color.a >= u_alphaRef)\n" +" discard;\n" +" break;\n" +" }\n" +"}\n" + +; diff --git a/src/gl/shaders/skin.vert b/src/gl/shaders/skin.vert new file mode 100644 index 0000000..2c66494 --- /dev/null +++ b/src/gl/shaders/skin.vert @@ -0,0 +1,78 @@ +#version 330 + +layout(std140) uniform State +{ + int u_alphaTest; + float u_alphaRef; + + int u_fogEnable; + float u_fogStart; + float u_fogEnd; + vec4 u_fogColor; +}; + +layout(std140) uniform Scene +{ + mat4 u_proj; + mat4 u_view; +}; + +#define MAX_LIGHTS 8 +struct Light { + vec4 position; + vec4 direction; + vec4 color; + float radius; + float minusCosAngle; +}; + +layout(std140) uniform Object +{ + mat4 u_world; + vec4 u_ambLight; + int u_numLights; + Light u_lights[MAX_LIGHTS]; +}; + +uniform vec4 u_matColor; +uniform vec4 u_surfaceProps; // amb, spec, diff, extra + +layout(location = 0) in vec3 in_pos; +layout(location = 1) in vec3 in_normal; +layout(location = 2) in vec4 in_color; +layout(location = 3) in vec2 in_tex0; +layout(location = 11) in vec4 in_weights; +layout(location = 12) in vec4 in_indices; + +uniform mat4 u_boneMatrices[64]; + +out vec4 v_color; +out vec2 v_tex0; +out float v_fog; + +void +main(void) +{ + mat4 m = u_boneMatrices[int(in_indices[0])] * in_weights[0]; + m += u_boneMatrices[int(in_indices[1])] * in_weights[1]; + m += u_boneMatrices[int(in_indices[2])] * in_weights[2]; + m += u_boneMatrices[int(in_indices[3])] * in_weights[3]; + mat4 world = u_world * m; + + vec4 V = world * vec4(in_pos, 1.0); + vec4 cV = u_view * V; + gl_Position = u_proj * cV; + vec3 N = mat3(world) * in_normal; + + v_color = in_color; + for(int i = 0; i < u_numLights; i++){ + float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz))); + v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z; + } + v_color.rgb += u_ambLight.rgb*u_surfaceProps.x; + v_color *= u_matColor; + + v_tex0 = in_tex0; + + v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0); +} diff --git a/src/gl/shaders/skin_gl3.inc b/src/gl/shaders/skin_gl3.inc new file mode 100644 index 0000000..4730087 --- /dev/null +++ b/src/gl/shaders/skin_gl3.inc @@ -0,0 +1,80 @@ +const char *skin_vert_src = +"#version 330\n" + +"layout(std140) uniform State\n" +"{\n" +" int u_alphaTest;\n" +" float u_alphaRef;\n" + +" int u_fogEnable;\n" +" float u_fogStart;\n" +" float u_fogEnd;\n" +" vec4 u_fogColor;\n" +"};\n" + +"layout(std140) uniform Scene\n" +"{\n" +" mat4 u_proj;\n" +" mat4 u_view;\n" +"};\n" + +"#define MAX_LIGHTS 8\n" +"struct Light {\n" +" vec4 position;\n" +" vec4 direction;\n" +" vec4 color;\n" +" float radius;\n" +" float minusCosAngle;\n" +"};\n" + +"layout(std140) uniform Object\n" +"{\n" +" mat4 u_world;\n" +" vec4 u_ambLight;\n" +" int u_numLights;\n" +" Light u_lights[MAX_LIGHTS];\n" +"};\n" + +"uniform vec4 u_matColor;\n" +"uniform vec4 u_surfaceProps; // amb, spec, diff, extra\n" + +"layout(location = 0) in vec3 in_pos;\n" +"layout(location = 1) in vec3 in_normal;\n" +"layout(location = 2) in vec4 in_color;\n" +"layout(location = 3) in vec2 in_tex0;\n" +"layout(location = 11) in vec4 in_weights;\n" +"layout(location = 12) in vec4 in_indices;\n" + +"uniform mat4 u_boneMatrices[64];\n" + +"out vec4 v_color;\n" +"out vec2 v_tex0;\n" +"out float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" mat4 m = u_boneMatrices[int(in_indices[0])] * in_weights[0];\n" +" m += u_boneMatrices[int(in_indices[1])] * in_weights[1];\n" +" m += u_boneMatrices[int(in_indices[2])] * in_weights[2];\n" +" m += u_boneMatrices[int(in_indices[3])] * in_weights[3];\n" +" mat4 world = u_world * m;\n" + +" vec4 V = world * vec4(in_pos, 1.0);\n" +" vec4 cV = u_view * V; \n" +" gl_Position = u_proj * cV;\n" +" vec3 N = mat3(world) * in_normal;\n" + +" v_color = in_color;\n" +" for(int i = 0; i < u_numLights; i++){\n" +" float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz)));\n" +" v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z;\n" +" }\n" +" v_color.rgb += u_ambLight.rgb*u_surfaceProps.x;\n" +" v_color *= u_matColor;\n" + +" v_tex0 = in_tex0;\n" + +" v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0);\n" +"}\n" +; diff --git a/src/image.cpp b/src/image.cpp index 28a9e20..1e87991 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -357,6 +357,7 @@ Texture::streamGetSizeNative(void) // // Image // +// TODO: full 16 bit support Image* Image::create(int32 width, int32 height, int32 depth) @@ -401,10 +402,14 @@ Image::allocate(void) void Image::free(void) { - if(this->flags&1) + if(this->flags&1){ delete[] this->pixels; - if(this->flags&2) + this->pixels = nil; + } + if(this->flags&2){ delete[] this->palette; + this->palette = nil; + } } void @@ -428,7 +433,6 @@ Image::hasAlpha(void) uint8 *pixels = this->pixels; if(this->depth == 24) return 0; - // TODO: palettized textures if(this->depth == 32){ for(int y = 0; y < this->height; y++){ uint8 *line = pixels; @@ -438,10 +442,136 @@ Image::hasAlpha(void) } pixels += this->stride; } + }else if(this->depth <= 8){ + for(int y = 0; y < this->height; y++){ + uint8 *line = pixels; + for(int x = 0; x < this->width; x++){ + ret &= this->palette[*line*4+3]; + line++; + } + pixels += this->stride; + } } return ret != 0xFF; } +void +Image::unindex(void) +{ + if(this->depth > 8) + return; + assert(this->pixels); + assert(this->palette); + + int32 ndepth = this->hasAlpha() ? 32 : 24; + int32 nstride = this->width*ndepth/8; + uint8 *npixels = new uint8[nstride*this->height]; + + uint8 *line = this->pixels; + uint8 *nline = npixels; + uint8 *p, *np; + for(int32 y = 0; y < this->height; y++){ + p = line; + np = nline; + for(int32 x = 0; x < this->width; x++){ + np[0] = this->palette[*p*4+0]; + np[1] = this->palette[*p*4+1]; + np[2] = this->palette[*p*4+2]; + np += 3; + if(ndepth == 32) + *np++ = this->palette[*p*4+3]; + p++; + } + line += this->stride; + nline += nstride; + } + this->free(); + this->depth = ndepth; + this->stride = nstride; + this->setPixels(npixels); +} + +void +Image::removeMask(void) +{ + if(this->depth <= 8){ + assert(this->palette); + int32 pallen = 4*(this->depth == 4 ? 16 : 256); + for(int32 i = 0; i < pallen; i += 4) + this->palette[i] = 0xFF; + return; + } + if(this->depth == 24) + return; + assert(this->pixels); + uint8 *line = this->pixels; + uint8 *p; + for(int32 y = 0; y < this->height; y++){ + p = line; + for(int32 x = 0; x < this->width; x++){ + switch(this->depth){ + case 16: + p[1] |= 0x80; + p += 2; + break; + case 32: + p[3] = 0xFF; + p += 4; + break; + } + } + line += this->stride; + } +} + +Image* +Image::extractMask(void) +{ + Image *img = Image::create(this->width, this->height, 8); + img->allocate(); + + // use an 8bit palette to store all shades of grey + for(int32 i = 0; i < 256; i++){ + img->palette[i*4+0] = i; + img->palette[i*4+1] = i; + img->palette[i*4+2] = i; + img->palette[i*4+3] = 0xFF; + } + + // Then use the alpha value as palette index + uint8 *line = this->pixels; + uint8 *nline = img->pixels; + uint8 *p, *np; + for(int32 y = 0; y < this->height; y++){ + p = line; + np = nline; + for(int32 x = 0; x < this->width; x++){ + switch(this->depth){ + case 4: + case 8: + *np++ = this->palette[*p*4+3]; + p++; + break; + case 16: + *np++ = 0xFF*!!(p[1]&0x80); + p += 2; + break; + case 24: + *np++ = 0xFF; + p += 3; + break; + case 32: + *np++ = p[3]; + p += 4; + break; + } + } + line += this->stride; + nline += img->stride; + } + return img; +} + static char *searchPaths = nil; int numSearchPaths = 0; @@ -511,167 +641,6 @@ Image::getFilename(const char *name) return nil; } -// -// TGA I/O -// - -// TODO: fuck pakced structs -#ifndef RW_PS2 -#pragma pack(push) -#pragma pack(1) -#define PACKED_STRUCT -#else -#define PACKED_STRUCT __attribute__((__packed__)) -#endif -struct PACKED_STRUCT TGAHeader -{ - int8 IDlen; - int8 colorMapType; - int8 imageType; - int16 colorMapOrigin; - int16 colorMapLength; - int8 colorMapDepth; - int16 xOrigin, yOrigin; - int16 width, height; - uint8 depth; - uint8 descriptor; -}; -#ifndef RW_PS2 -#pragma pack(push) -#endif - -Image* -readTGA(const char *afilename) -{ - TGAHeader header; - Image *image; - char *filename; - int depth = 0, palDepth = 0; - filename = Image::getFilename(afilename); - if(filename == nil) - return nil; - uint32 length; - uint8 *data = getFileContents(filename, &length); - assert(data != nil); - free(filename); - StreamMemory file; - file.open(data, length); - file.read(&header, sizeof(header)); - - assert(header.imageType == 1 || header.imageType == 2); - file.seek(header.IDlen); - if(header.colorMapType){ - assert(header.colorMapOrigin == 0); - depth = (header.colorMapLength <= 16) ? 4 : 8; - palDepth = header.colorMapDepth; - assert(palDepth == 24 || palDepth == 32); - }else{ - depth = header.depth; - assert(depth == 24 || depth == 32); - } - - image = Image::create(header.width, header.height, depth); - image->allocate(); - uint8 *palette = header.colorMapType ? image->palette : nil; - uint8 (*color)[4] = nil; - if(palette){ - int maxlen = depth == 4 ? 16 : 256; - color = (uint8(*)[4])palette; - int i; - for(i = 0; i < header.colorMapLength; i++){ - color[i][2] = file.readU8(); - color[i][1] = file.readU8(); - color[i][0] = file.readU8(); - color[i][3] = 0xFF; - if(palDepth == 32) - color[i][3] = file.readU8(); - } - for(; i < maxlen; i++){ - color[i][0] = color[i][1] = color[i][2] = 0; - color[i][3] = 0xFF; - } - } - - uint8 *pixels = image->pixels; - if(!(header.descriptor & 0x20)) - pixels += (image->height-1)*image->stride; - for(int y = 0; y < image->height; y++){ - uint8 *line = pixels; - for(int x = 0; x < image->width; x++){ - if(palette) - *line++ = file.readU8(); - else{ - line[2] = file.readU8(); - line[1] = file.readU8(); - line[0] = file.readU8(); - line += 3; - if(depth == 32) - *line++ = file.readU8(); - } - } - pixels += (header.descriptor&0x20) ? - image->stride : -image->stride; - } - - file.close(); - delete[] data; - return image; -} - -void -writeTGA(Image *image, const char *filename) -{ - TGAHeader header; - StreamFile file; - if(!file.open(filename, "wb")){ - RWERROR((ERR_FILE, filename)); - return; - } - header.IDlen = 0; - header.imageType = image->palette != nil ? 1 : 2; - header.colorMapType = image->palette != nil; - header.colorMapOrigin = 0; - header.colorMapLength = image->depth == 4 ? 16 : - image->depth == 8 ? 256 : 0; - header.colorMapDepth = image->palette ? 32 : 0; - header.xOrigin = 0; - header.yOrigin = 0; - header.width = image->width; - header.height = image->height; - header.depth = image->depth == 4 ? 8 : image->depth; - header.descriptor = 0x20 | (image->depth == 32 ? 8 : 0); - file.write(&header, sizeof(header)); - - uint8 *pixels = image->pixels; - uint8 *palette = header.colorMapType ? image->palette : nil; - uint8 (*color)[4] = (uint8(*)[4])palette;; - if(palette) - for(int i = 0; i < header.colorMapLength; i++){ - file.writeU8(color[i][2]); - file.writeU8(color[i][1]); - file.writeU8(color[i][0]); - file.writeU8(color[i][3]); - } - - for(int y = 0; y < image->height; y++){ - uint8 *line = pixels; - for(int x = 0; x < image->width; x++){ - if(palette) - file.writeU8(*line++); - else{ - file.writeU8(line[2]); - file.writeU8(line[1]); - file.writeU8(line[0]); - line += 3; - if(image->depth == 32) - file.writeU8(*line++); - } - } - pixels += image->stride; - } - file.close(); -} - // // Raster // diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 39ec4c9..d2723a6 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -335,7 +335,7 @@ rasterCreate(Raster *raster) while(n--){ mipw = w < minW ? minW : w; miph = h < minH ? minH : h; - ras->texelSize += ALIGN16(mipw*miph*raster->depth/8) + ras->texelSize += ALIGN16(mipw*miph*raster->depth/8); w /= 2; h /= 2; } diff --git a/src/rwbase.h b/src/rwbase.h index 6432282..555d775 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -206,6 +206,8 @@ struct Sphere * Streams */ +void makePath(char *filename); + class Stream { public: @@ -357,9 +359,10 @@ enum Errors #undef ECODE -extern int version; -extern int build; -extern int platform; +extern int32 version; +extern int32 build; +extern int32 platform; +extern bool32 streamAppendFrames; extern char *debugFile; int strncmp_ci(const char *s1, const char *s2, int n); diff --git a/src/rwobjects.h b/src/rwobjects.h index 8944eb3..89dfc0e 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -183,13 +183,18 @@ struct Image void setPixels(uint8 *pixels); void setPalette(uint8 *palette); bool32 hasAlpha(void); + void unindex(void); + void removeMask(void); + Image *extractMask(void); static void setSearchPath(const char*); static void printSearchPath(void); static char *getFilename(const char*); }; + Image *readTGA(const char *filename); void writeTGA(Image *image, const char *filename); +void writeBMP(Image *image, const char *filename); // used to emulate d3d and xbox textures struct RasterLevels diff --git a/src/tga.cpp b/src/tga.cpp new file mode 100644 index 0000000..5b79ad6 --- /dev/null +++ b/src/tga.cpp @@ -0,0 +1,193 @@ +#include +#include +#include +#include + +#include "rwbase.h" +#include "rwerror.h" +#include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwengine.h" + +#ifdef _WIN32 +/* srsly? */ +#define strdup _strdup +#endif + +#define PLUGIN_ID 0 + +namespace rw { + +// TODO: fuck packed structs +#ifndef RW_PS2 +#pragma pack(push) +#pragma pack(1) +#define PACKED_STRUCT +#else +#define PACKED_STRUCT __attribute__((__packed__)) +#endif +struct PACKED_STRUCT TGAHeader +{ + int8 IDlen; + int8 colorMapType; + int8 imageType; + int16 colorMapOrigin; + int16 colorMapLength; + int8 colorMapDepth; + int16 xOrigin, yOrigin; + int16 width, height; + uint8 depth; + uint8 descriptor; +}; +#ifndef RW_PS2 +#pragma pack(push) +#endif + +Image* +readTGA(const char *afilename) +{ + TGAHeader header; + Image *image; + char *filename; + int depth = 0, palDepth = 0; + filename = Image::getFilename(afilename); + if(filename == nil) + return nil; + uint32 length; + uint8 *data = getFileContents(filename, &length); + assert(data != nil); + free(filename); + StreamMemory file; + file.open(data, length); + file.read(&header, sizeof(header)); + + assert(header.imageType == 1 || header.imageType == 2); + file.seek(header.IDlen); + if(header.colorMapType){ + assert(header.colorMapOrigin == 0); + depth = (header.colorMapLength <= 16) ? 4 : 8; + palDepth = header.colorMapDepth; + assert(palDepth == 24 || palDepth == 32); + }else{ + depth = header.depth; + assert(depth == 24 || depth == 32); + } + + image = Image::create(header.width, header.height, depth); + image->allocate(); + uint8 *palette = header.colorMapType ? image->palette : nil; + uint8 (*color)[4] = nil; + if(palette){ + int maxlen = depth == 4 ? 16 : 256; + color = (uint8(*)[4])palette; + int i; + for(i = 0; i < header.colorMapLength; i++){ + color[i][2] = file.readU8(); + color[i][1] = file.readU8(); + color[i][0] = file.readU8(); + color[i][3] = 0xFF; + if(palDepth == 32) + color[i][3] = file.readU8(); + } + for(; i < maxlen; i++){ + color[i][0] = color[i][1] = color[i][2] = 0; + color[i][3] = 0xFF; + } + } + + uint8 *pixels = image->pixels; + if(!(header.descriptor & 0x20)) + pixels += (image->height-1)*image->stride; + for(int y = 0; y < image->height; y++){ + uint8 *line = pixels; + for(int x = 0; x < image->width; x++){ + if(palette) + *line++ = file.readU8(); + else{ + line[2] = file.readU8(); + line[1] = file.readU8(); + line[0] = file.readU8(); + line += 3; + if(depth == 32) + *line++ = file.readU8(); + } + } + pixels += (header.descriptor&0x20) ? + image->stride : -image->stride; + } + + file.close(); + delete[] data; + return image; +} + +void +writeTGA(Image *image, const char *filename) +{ + TGAHeader header; + StreamFile file; + if(!file.open(filename, "wb")){ + RWERROR((ERR_FILE, filename)); + return; + } + header.IDlen = 0; + header.imageType = image->palette != nil ? 1 : 2; + header.colorMapType = image->palette != nil; + header.colorMapOrigin = 0; + header.colorMapLength = image->depth == 4 ? 16 : + image->depth == 8 ? 256 : 0; + header.colorMapDepth = image->palette ? 32 : 0; + header.xOrigin = 0; + header.yOrigin = 0; + header.width = image->width; + header.height = image->height; + header.depth = image->depth == 4 ? 8 : image->depth; + header.descriptor = 0x20 | (image->depth == 32 ? 8 : 0); + file.write(&header, sizeof(header)); + + uint8 *palette = header.colorMapType ? image->palette : nil; + uint8 (*color)[4] = (uint8(*)[4])palette;; + if(palette) + for(int i = 0; i < header.colorMapLength; i++){ + file.writeU8(color[i][2]); + file.writeU8(color[i][1]); + file.writeU8(color[i][0]); + file.writeU8(color[i][3]); + } + + uint8 *line = image->pixels; + uint8 *p; + for(int y = 0; y < image->height; y++){ + p = line; + for(int x = 0; x < image->width; x++){ + switch(image->depth){ + case 4: + case 8: + file.writeU8(*p++); + break; + case 16: + file.writeU8(p[0]); + file.writeU8(p[1]); + p += 2; + break; + case 24: + file.writeU8(p[2]); + file.writeU8(p[1]); + file.writeU8(p[0]); + p += 3; + break; + case 32: + file.writeU8(p[2]); + file.writeU8(p[1]); + file.writeU8(p[0]); + file.writeU8(p[3]); + p += 4; + } + } + line += image->stride; + } + file.close(); +} + +}