mirror of
https://github.com/aap/librw.git
synced 2024-11-25 13:15:43 +00:00
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]);
|
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
112
src/bmp.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
23
src/gl/shaders/Makefile
Normal 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
|
||||||
|
|
34
src/gl/shaders/matfx_env.frag
Normal file
34
src/gl/shaders/matfx_env.frag
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
58
src/gl/shaders/matfx_env.vert
Normal file
58
src/gl/shaders/matfx_env.vert
Normal 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;
|
||||||
|
}
|
96
src/gl/shaders/matfx_gl3.inc
Normal file
96
src/gl/shaders/matfx_gl3.inc
Normal 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"
|
||||||
|
|
||||||
|
;
|
41
src/gl/shaders/simple.frag
Normal file
41
src/gl/shaders/simple.frag
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
70
src/gl/shaders/simple.vert
Normal file
70
src/gl/shaders/simple.vert
Normal 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);
|
||||||
|
}
|
115
src/gl/shaders/simple_gl3.inc
Normal file
115
src/gl/shaders/simple_gl3.inc
Normal 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
78
src/gl/shaders/skin.vert
Normal 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);
|
||||||
|
}
|
80
src/gl/shaders/skin_gl3.inc
Normal file
80
src/gl/shaders/skin_gl3.inc
Normal 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"
|
||||||
|
;
|
297
src/image.cpp
297
src/image.cpp
@ -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
|
||||||
//
|
//
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
193
src/tga.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user