hardcoded gl3 shaders; extended Image; bmp writer

This commit is contained in:
aap 2016-07-19 18:40:10 +02:00
parent 14547ef830
commit 69356264d7
23 changed files with 1132 additions and 187 deletions

View File

@ -533,6 +533,61 @@ matrixPrint(float32 *mat)
mat[3], mat[7], mat[11], mat[15]); 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 int32
Stream::writeI8(int8 val) Stream::writeI8(int8 val)
{ {

112
src/bmp.cpp Normal file
View File

@ -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();
}
}

View File

@ -460,9 +460,9 @@ rasterFromImage(Raster *raster, Image *image)
in = image->palette; in = image->palette;
out = (uint8*)natras->palette; out = (uint8*)natras->palette;
for(int32 i = 0; i < pallength; i++){ for(int32 i = 0; i < pallength; i++){
out[0] = in[2]; out[0] = in[0];
out[1] = in[1]; out[1] = in[1];
out[2] = in[0]; out[2] = in[2];
out[3] = in[3]; out[3] = in[3];
in += 4; in += 4;
out += 4; out += 4;
@ -537,7 +537,7 @@ rasterToImage(Raster *raster)
if((raster->format & Raster::PAL4) == Raster::PAL4){ if((raster->format & Raster::PAL4) == Raster::PAL4){
depth = 4; depth = 4;
pallength = 16; pallength = 16;
}else if((raster->format & Raster::PAL4) == Raster::PAL8){ }else if((raster->format & Raster::PAL8) == Raster::PAL8){
depth = 8; depth = 8;
pallength = 256; pallength = 256;
} }
@ -550,9 +550,9 @@ rasterToImage(Raster *raster)
out = image->palette; out = image->palette;
in = (uint8*)natras->palette; in = (uint8*)natras->palette;
for(int32 i = 0; i < pallength; i++){ for(int32 i = 0; i < pallength; i++){
out[0] = in[2]; out[0] = in[0];
out[1] = in[1]; out[1] = in[1];
out[2] = in[0]; out[2] = in[2];
out[3] = in[3]; out[3] = in[3];
in += 4; in += 4;
out += 4; out += 4;

View File

@ -7,6 +7,7 @@
#include "../rwplg.h" #include "../rwplg.h"
#include "../rwpipeline.h" #include "../rwpipeline.h"
#include "../rwobjects.h" #include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h" #include "rwd3d.h"
namespace rw { namespace rw {
@ -224,7 +225,7 @@ beginUpdate(Camera *cam)
proj[9] = cam->viewOffset.y*invwy; proj[9] = cam->viewOffset.y*invwy;
proj[12] = -proj[8]; proj[12] = -proj[8];
proj[13] = -proj[9]; proj[13] = -proj[9];
if(cam->projection == PERSPECTIVE){ if(cam->projection == Camera::PERSPECTIVE){
proj[10] = cam->farPlane*invz; proj[10] = cam->farPlane*invz;
proj[11] = 1.0f; proj[11] = 1.0f;
@ -242,8 +243,7 @@ beginUpdate(Camera *cam)
void void
initializeRender(void) initializeRender(void)
{ {
driver[PLATFORM_D3D8]->beginUpdate = beginUpdate; engine->beginUpdate = beginUpdate;
driver[PLATFORM_D3D9]->beginUpdate = beginUpdate;
} }
#endif #endif

View File

@ -349,7 +349,7 @@ FrameList_::streamRead(Stream *stream)
f->matrix.posw = 1.0f; f->matrix.posw = 1.0f;
//f->matflag = buf.matflag; //f->matflag = buf.matflag;
if(buf.parent >= 0) 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++) for(int32 i = 0; i < this->numFrames; i++)
Frame::s_plglist.streamRead(stream, this->frames[i]); Frame::s_plglist.streamRead(stream, this->frames[i]);

View File

@ -420,7 +420,8 @@ initializeRender(void)
engine->zNear = -1.0f; engine->zNear = -1.0f;
engine->zFar = 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); glClearColor(0.25, 0.25, 0.25, 1.0);

View File

@ -32,8 +32,9 @@ Shader *envShader;
static void* static void*
matfxOpen(void *o, int32, int32) matfxOpen(void *o, int32, int32)
{ {
#include "shaders/matfx_gl3.inc"
matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline(); 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; return o;
} }
@ -235,8 +236,10 @@ Shader *skinShader;
static void* static void*
skinOpen(void *o, int32, int32) skinOpen(void *o, int32, int32)
{ {
#include "shaders/simple_gl3.inc"
#include "shaders/skin_gl3.inc"
skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline(); skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline();
skinShader = Shader::fromFiles("skin.vert", "simple.frag"); skinShader = Shader::fromStrings(skin_vert_src, simple_frag_src);
return o; return o;
} }

View File

@ -134,22 +134,18 @@ linkprogram(GLint vs, GLint fs, GLuint *program)
} }
Shader* Shader*
Shader::fromFiles(const char *vspath, const char *fspath) Shader::fromStrings(const char *vsrc, const char *fsrc)
{ {
GLuint vs, fs, program; GLuint vs, fs, program;
int i; int i;
char *src; char *src;
int fail; int fail;
src = loadfile(vspath); fail = compileshader(GL_VERTEX_SHADER, vsrc, &vs);
fail = compileshader(GL_VERTEX_SHADER, src, &vs);
free(src);
if(fail) if(fail)
return nil; return nil;
src = loadfile(fspath); fail = compileshader(GL_FRAGMENT_SHADER, fsrc, &fs);
fail = compileshader(GL_FRAGMENT_SHADER, src, &fs);
free(src);
if(fail) if(fail)
return nil; return nil;
@ -179,6 +175,18 @@ Shader::fromFiles(const char *vspath, const char *fspath)
return sh; 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 void
Shader::use(void) Shader::use(void)
{ {

View File

@ -33,6 +33,7 @@ public:
GLint *uniformLocations; GLint *uniformLocations;
static Shader *fromFiles(const char *vs, const char *fs); static Shader *fromFiles(const char *vs, const char *fs);
static Shader *fromStrings(const char *vsrc, const char *fsrc);
void use(void); void use(void);
}; };

23
src/gl/shaders/Makefile Normal file
View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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"
;

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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"
;

78
src/gl/shaders/skin.vert Normal file
View File

@ -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);
}

View File

@ -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"
;

View File

@ -357,6 +357,7 @@ Texture::streamGetSizeNative(void)
// //
// Image // Image
// //
// TODO: full 16 bit support
Image* Image*
Image::create(int32 width, int32 height, int32 depth) Image::create(int32 width, int32 height, int32 depth)
@ -401,10 +402,14 @@ Image::allocate(void)
void void
Image::free(void) Image::free(void)
{ {
if(this->flags&1) if(this->flags&1){
delete[] this->pixels; delete[] this->pixels;
if(this->flags&2) this->pixels = nil;
}
if(this->flags&2){
delete[] this->palette; delete[] this->palette;
this->palette = nil;
}
} }
void void
@ -428,7 +433,6 @@ Image::hasAlpha(void)
uint8 *pixels = this->pixels; uint8 *pixels = this->pixels;
if(this->depth == 24) if(this->depth == 24)
return 0; return 0;
// TODO: palettized textures
if(this->depth == 32){ if(this->depth == 32){
for(int y = 0; y < this->height; y++){ for(int y = 0; y < this->height; y++){
uint8 *line = pixels; uint8 *line = pixels;
@ -438,10 +442,136 @@ Image::hasAlpha(void)
} }
pixels += this->stride; 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; 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; static char *searchPaths = nil;
int numSearchPaths = 0; int numSearchPaths = 0;
@ -511,167 +641,6 @@ Image::getFilename(const char *name)
return nil; 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 // Raster
// //

View File

@ -335,7 +335,7 @@ rasterCreate(Raster *raster)
while(n--){ while(n--){
mipw = w < minW ? minW : w; mipw = w < minW ? minW : w;
miph = h < minH ? minH : h; miph = h < minH ? minH : h;
ras->texelSize += ALIGN16(mipw*miph*raster->depth/8) ras->texelSize += ALIGN16(mipw*miph*raster->depth/8);
w /= 2; w /= 2;
h /= 2; h /= 2;
} }

View File

@ -206,6 +206,8 @@ struct Sphere
* Streams * Streams
*/ */
void makePath(char *filename);
class Stream class Stream
{ {
public: public:
@ -357,9 +359,10 @@ enum Errors
#undef ECODE #undef ECODE
extern int version; extern int32 version;
extern int build; extern int32 build;
extern int platform; extern int32 platform;
extern bool32 streamAppendFrames;
extern char *debugFile; extern char *debugFile;
int strncmp_ci(const char *s1, const char *s2, int n); int strncmp_ci(const char *s1, const char *s2, int n);

View File

@ -183,13 +183,18 @@ struct Image
void setPixels(uint8 *pixels); void setPixels(uint8 *pixels);
void setPalette(uint8 *palette); void setPalette(uint8 *palette);
bool32 hasAlpha(void); bool32 hasAlpha(void);
void unindex(void);
void removeMask(void);
Image *extractMask(void);
static void setSearchPath(const char*); static void setSearchPath(const char*);
static void printSearchPath(void); static void printSearchPath(void);
static char *getFilename(const char*); static char *getFilename(const char*);
}; };
Image *readTGA(const char *filename); Image *readTGA(const char *filename);
void writeTGA(Image *image, const char *filename); void writeTGA(Image *image, const char *filename);
void writeBMP(Image *image, const char *filename);
// used to emulate d3d and xbox textures // used to emulate d3d and xbox textures
struct RasterLevels struct RasterLevels

193
src/tga.cpp Normal file
View File

@ -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();
}
}