mirror of https://github.com/aap/librw.git
hardcoded gl3 shaders; extended Image; bmp writer
This commit is contained in:
parent
14547ef830
commit
69356264d7
55
src/base.cpp
55
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 <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
||||
;
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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"
|
||||
|
||||
;
|
|
@ -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);
|
||||
}
|
|
@ -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"
|
||||
;
|
297
src/image.cpp
297
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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue