We now actually use the shaders
This commit is contained in:
parent
f2b6ca0092
commit
12dc8b4ee8
1 changed files with 271 additions and 112 deletions
383
shaders.c
383
shaders.c
|
@ -18,85 +18,44 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
PENTA: the whole file is freakin penta...
|
||||
|
||||
"Shader" loading an management
|
||||
"Shader" loading an management.
|
||||
|
||||
All .shader files are parsed on engine startup. We don't load textures for these of course,
|
||||
textures are only loaded per level.
|
||||
*/
|
||||
#include "quakedef.h"
|
||||
|
||||
#define SHADER_MAX_NAME 128
|
||||
#define SHADER_MAX_STAGES 8
|
||||
#define SHADER_MAX_TCMOD 8
|
||||
#define SHADER_MAX_STATUSES 8
|
||||
|
||||
typedef enum {STAGE_SIMPLE, STAGE_COLOR, STAGE_BUMP, STAGE_GLOSS} stagetype_t;
|
||||
typedef enum {TCMOD_ROTATE, TCMOD_SCROLL, TCMOD_SCALE, TCMOD_STRETCH} tcmodtype_t;
|
||||
/**
|
||||
* A single stage in the shader,
|
||||
* a stage is one block { } in a shader definition
|
||||
* this corresponds to a single pass for simple shaders
|
||||
* or a single texture definition for bumpmapping.
|
||||
*/
|
||||
typedef struct tcmod_s {
|
||||
float params[7];
|
||||
tcmodtype_t type;
|
||||
} tcmod_t;
|
||||
|
||||
typedef struct stage_s {
|
||||
stagetype_t type;
|
||||
int numtcmods;
|
||||
tcmod_t tcmods[SHADER_MAX_TCMOD];
|
||||
int numtextures;
|
||||
gltexture_t *texture[8]; //animations
|
||||
int src_blend, dst_blend; //have special values for bumpmap passes
|
||||
int alphatresh;
|
||||
} stage_t;
|
||||
|
||||
#define SURF_NOSHADOW 0x40000 //don't cast stencil shadows
|
||||
#define SURF_BUMP 0x80000 //do diffuse bumpmapping and gloss if gloss is enabled too
|
||||
#define SURF_GLOSS 0x100000//do gloss
|
||||
#define SURF_PPLIGHT 0x200000//do per pixel lighting...
|
||||
//if bump is unset it uses a flat bumpmap and no gloss
|
||||
//if bump is set and gloss unet it does only diffuse bumps
|
||||
|
||||
/**
|
||||
* A shader, holds the stages and the general info for that shader.
|
||||
*/
|
||||
typedef struct shader_s {
|
||||
char name[SHADER_MAX_NAME];
|
||||
int flags;
|
||||
int numstages;
|
||||
stage_t stages[SHADER_MAX_STAGES];
|
||||
stage_t colorStage;
|
||||
stage_t bumpStage;
|
||||
stage_t glossStage;
|
||||
vec3_t fog_color;
|
||||
float fog_dist;
|
||||
int numstatus;
|
||||
struct shader_s *status[SHADER_MAX_STATUSES]; //if the object the shader is on it's status is > 0 this shader will be used insead of the base shader...
|
||||
struct shader_s *next; //in the shader linked list
|
||||
} shader_t;
|
||||
|
||||
static shader_t *shaderList;
|
||||
|
||||
/*=====================================================
|
||||
|
||||
Generic shader routines
|
||||
|
||||
======================================================*/
|
||||
|
||||
void GL_ShaderLoadTextures(shader_t *shader);
|
||||
|
||||
/**
|
||||
* Generates a clean stage before one is parsed over it
|
||||
*/
|
||||
void clearStage(stage_t *stage) {
|
||||
memset(stage,0,sizeof(stage_t));
|
||||
stage->texture[0] = NULL;
|
||||
stage->type = STAGE_SIMPLE;
|
||||
stage->src_blend = -1;
|
||||
stage->dst_blend = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a default shader from the given name.
|
||||
*/
|
||||
void initDefaultStage(char *texname, stage_t *stage, stagetype_t type) {
|
||||
memset(stage,0,sizeof(stage_t));
|
||||
//memset(stage,0,sizeof(stage_t));
|
||||
clearStage(stage);
|
||||
stage->numtextures = 1;
|
||||
if (type == STAGE_BUMP) {
|
||||
stage->texture[0] = GL_CacheTexture(texname,true,TEXTURE_NORMAL);
|
||||
} else
|
||||
stage->texture[0] = GL_CacheTexture(texname,true,TEXTURE_RGB);
|
||||
stage->numtcmods = 0;
|
||||
stage->type = type;
|
||||
strncpy(stage->filename,texname,2*MAX_QPATH+1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,14 +64,22 @@ void initDefaultStage(char *texname, stage_t *stage, stagetype_t type) {
|
|||
void initDefaultShader(char *name, shader_t *shader) {
|
||||
char namebuff[256];
|
||||
|
||||
memset(shader,0,sizeof(shader));
|
||||
strncpy(shader->name,name,sizeof(shader->name));
|
||||
shader->flags = 0;
|
||||
shader->numstages = 3;
|
||||
initDefaultStage(name, &shader->stages[0], STAGE_COLOR);
|
||||
sprintf(namebuff,"%s%s",name,"_normal");
|
||||
initDefaultStage(namebuff, &shader->stages[1], STAGE_BUMP);
|
||||
sprintf(namebuff,"%s%s",name,"_gloss");
|
||||
initDefaultStage(namebuff, &shader->stages[2], STAGE_GLOSS);
|
||||
shader->numstages = 0;
|
||||
shader->mipmap = true;
|
||||
shader->cull = true;
|
||||
sprintf(namebuff,"%s.tga",name);
|
||||
initDefaultStage(namebuff, &shader->colorstages[0], STAGE_COLOR);
|
||||
sprintf(namebuff,"%s_norm.tga|%s_gloss.tga",name,name);
|
||||
initDefaultStage(namebuff, &shader->bumpstages[0], STAGE_BUMP);
|
||||
initDefaultStage(namebuff, &shader->glossstages[0], STAGE_GRAYGLOSS);
|
||||
|
||||
shader->numbumpstages = 1;
|
||||
shader->numglossstages = 1;
|
||||
shader->numcolorstages = 1;
|
||||
shader->flags |= (SURF_GLOSS | SURF_PPLIGHT | SURF_BUMP);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -128,8 +95,10 @@ shader_t *GL_ShaderForName(char *name) {
|
|||
shader_t *s;
|
||||
s = shaderList;
|
||||
|
||||
//Con_Printf("ShaderForName %s\n",name);
|
||||
while(s) {
|
||||
if (!strcmp(name,s->name)) {
|
||||
GL_ShaderLoadTextures(s);
|
||||
return s;
|
||||
}
|
||||
s = s->next;
|
||||
|
@ -144,10 +113,84 @@ shader_t *GL_ShaderForName(char *name) {
|
|||
initDefaultShader(name,s);
|
||||
s->next = shaderList;
|
||||
shaderList = s;
|
||||
|
||||
GL_ShaderLoadTextures(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
StageLoadTextures
|
||||
|
||||
load all the textures for the given stage
|
||||
================
|
||||
*/
|
||||
void StageLoadTextures(stage_t *stage, shader_t *shader) {
|
||||
|
||||
stage->numtextures = 1;
|
||||
|
||||
switch (stage->type) {
|
||||
case STAGE_COLOR:
|
||||
case STAGE_GLOSS:
|
||||
case STAGE_SIMPLE:
|
||||
stage->texture[0] = GL_CacheTexture(stage->filename, shader->mipmap, TEXTURE_RGB);
|
||||
break;
|
||||
case STAGE_BUMP:
|
||||
stage->texture[0] = GL_CacheTexture(stage->filename, shader->mipmap, TEXTURE_NORMAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_ShaderLoadTextures
|
||||
|
||||
load all the textures for the given shader
|
||||
================
|
||||
*/
|
||||
void GL_ShaderLoadTextures(shader_t *shader) {
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<shader->numstages; i++) {
|
||||
StageLoadTextures(&shader->stages[i],shader);
|
||||
}
|
||||
|
||||
for (i=0; i<shader->numbumpstages; i++) {
|
||||
StageLoadTextures(&shader->bumpstages[i],shader);
|
||||
}
|
||||
|
||||
for (i=0; i<shader->numglossstages; i++) {
|
||||
StageLoadTextures(&shader->glossstages[i],shader);
|
||||
}
|
||||
|
||||
for (i=0; i<shader->numcolorstages; i++) {
|
||||
StageLoadTextures(&shader->colorstages[i],shader);
|
||||
}
|
||||
|
||||
for (i=0; i<shader->numglossstages; i++) {
|
||||
if (shader->glossstages[i].type == STAGE_GRAYGLOSS) {
|
||||
for (j=0; j< shader->glossstages[i].numtextures; j++)
|
||||
shader->glossstages[i].texture[j] = shader->bumpstages[i].texture[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qboolean IsShaderBlended(shader_t *s) {
|
||||
|
||||
if (s->numstages)
|
||||
return (s->stages[0].src_blend >= 0);
|
||||
|
||||
if (s->numcolorstages)
|
||||
return (s->colorstages[0].src_blend >= 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*=====================================================
|
||||
|
||||
Shader script parsing
|
||||
|
||||
======================================================*/
|
||||
|
||||
// parse some stuff but make sure you give some errors
|
||||
#define GET_SAFE_TOKEN data = COM_Parse (data);\
|
||||
if (!data)\
|
||||
|
@ -170,48 +213,48 @@ char *ParceTcMod(char *data, stage_t *stage) {
|
|||
|
||||
stage->tcmods[stage->numtcmods].type = TCMOD_ROTATE;
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[0] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[0] = atof(com_token);
|
||||
|
||||
} else if (!strcmp(com_token, "scroll")) {
|
||||
|
||||
stage->tcmods[stage->numtcmods].type = TCMOD_SCROLL;
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[0] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[0] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[1] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[1] = atof(com_token);
|
||||
|
||||
} else if (!strcmp(com_token, "scale")) {
|
||||
|
||||
stage->tcmods[stage->numtcmods].type = TCMOD_SCALE;
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[0] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[0] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[1] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[1] = atof(com_token);
|
||||
|
||||
} else if (!strcmp(com_token, "stretch")) {
|
||||
|
||||
stage->tcmods[stage->numtcmods].type = TCMOD_STRETCH;
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[0] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[0] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[1] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[1] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[2] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[2] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[3] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[3] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[4] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[4] = atof(com_token);
|
||||
|
||||
} else if (!strcmp(com_token, "turb")) {
|
||||
|
||||
//parse it and give a warning that it's not supported
|
||||
stage->tcmods[stage->numtcmods].type = TCMOD_SCALE;
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[0] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[0] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[1] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[1] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[2] = atoi(com_token);
|
||||
stage->tcmods[stage->numtcmods].params[2] = atof(com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
stage->tcmods[stage->numtcmods].params[3] = atoi(com_token);
|
||||
Con_Printf("Warning: turb not supported by Tenebrae.\n");
|
||||
|
@ -234,9 +277,10 @@ char *ParseStage (char *data, shader_t *shader)
|
|||
char command[256];
|
||||
char texture[256];
|
||||
stage_t stage;
|
||||
|
||||
qboolean isgraygloss;
|
||||
//Con_Printf("Parsing shader stage...\n");
|
||||
clearStage(&stage);
|
||||
isgraygloss = false;
|
||||
|
||||
// go through all the dictionary pairs
|
||||
while (1)
|
||||
|
@ -245,18 +289,46 @@ char *ParseStage (char *data, shader_t *shader)
|
|||
|
||||
//end of stage
|
||||
if (com_token[0] == '}') {
|
||||
//end of stage cleanup...
|
||||
//end of stage is parsed now set everything up correctly
|
||||
strncpy(stage.filename,texture,MAX_QPATH);
|
||||
stage.numtextures = 1;
|
||||
|
||||
//stage->texture = GL_CacheTexture(com_token);
|
||||
if (stage.type == STAGE_GLOSS) {
|
||||
shader->glossStage = stage;
|
||||
|
||||
//if it has a gray gloss map we change the bumpmaps filename so it loads the gray
|
||||
//glossmap too, we won't bother with the glossmap in the graygloss shaders anymore
|
||||
//as we just bind the bumpmap.
|
||||
if (isgraygloss) {
|
||||
stage_t *bumpstage;
|
||||
|
||||
//setup the filenames correctly
|
||||
stage.type = STAGE_GRAYGLOSS;
|
||||
if (shader->numbumpstages < 1) {
|
||||
Con_Printf("Gray gloss defined before bumpmap\n");
|
||||
return NULL;
|
||||
}
|
||||
bumpstage = &shader->bumpstages[shader->numbumpstages-1];
|
||||
sprintf(stage.filename,"%s|%s",texture,bumpstage->filename);
|
||||
strcpy(bumpstage->filename, stage.filename);
|
||||
}
|
||||
shader->flags = shader->flags | SURF_GLOSS;
|
||||
if (shader->numglossstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return NULL;
|
||||
shader->glossstages[shader->numglossstages] = stage;
|
||||
shader->numglossstages++;
|
||||
} else if (stage.type == STAGE_COLOR) {
|
||||
shader->colorStage = stage;
|
||||
shader->flags = shader->flags | SURF_PPLIGHT;
|
||||
shader->flags = shader->flags | SURF_PPLIGHT;
|
||||
if (shader->numcolorstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return NULL;
|
||||
shader->colorstages[shader->numcolorstages] = stage;
|
||||
shader->numcolorstages++;
|
||||
} else if (stage.type == STAGE_BUMP) {
|
||||
shader->bumpStage = stage;
|
||||
shader->flags = shader->flags | SURF_BUMP;
|
||||
if (shader->numbumpstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return NULL;
|
||||
shader->bumpstages[shader->numbumpstages] = stage;
|
||||
shader->numbumpstages++;
|
||||
|
||||
} else {
|
||||
if (shader->numstages >= SHADER_MAX_STAGES)
|
||||
return NULL;
|
||||
|
@ -280,7 +352,7 @@ char *ParseStage (char *data, shader_t *shader)
|
|||
} else if (!strcmp(com_token, "bumpmap")) {
|
||||
stage.type = STAGE_BUMP;
|
||||
} else if (!strcmp(com_token, "specularmap")) {
|
||||
stage.type = STAGE_GLOSS;
|
||||
stage.type = STAGE_GLOSS;
|
||||
} else {
|
||||
Con_Printf("Unknown stage type %s\n",com_token);
|
||||
}
|
||||
|
@ -288,10 +360,14 @@ char *ParseStage (char *data, shader_t *shader)
|
|||
} else if (!strcmp(command, "map")) {
|
||||
|
||||
GET_SAFE_TOKEN;
|
||||
//add the textures to the known texture list
|
||||
//stage.texture = GL_CacheTexture(com_token);
|
||||
//Con_Printf("Cache texture %s\n",com_token);
|
||||
strncpy(texture,com_token,sizeof(texture));
|
||||
|
||||
//If it has a gray modifier it means the glossmap has to be stored in the bumpmap alpha
|
||||
if (!strcmp(com_token, "gray")) {
|
||||
GET_SAFE_TOKEN;
|
||||
strncpy(texture,com_token,MAX_QPATH);
|
||||
isgraygloss = true;
|
||||
} else
|
||||
strncpy(texture,com_token,MAX_QPATH);
|
||||
|
||||
} else if (!strcmp(command, "tcMod")) {
|
||||
|
||||
|
@ -308,20 +384,19 @@ char *ParseStage (char *data, shader_t *shader)
|
|||
} else if (!strcmp(com_token,"add")) {
|
||||
stage.src_blend = GL_ONE;
|
||||
stage.dst_blend = GL_ONE;
|
||||
} else {
|
||||
stage.src_blend = -1;
|
||||
stage.dst_blend = -1;
|
||||
}
|
||||
} else {
|
||||
GET_SAFE_TOKEN;
|
||||
stage.dst_blend = SC_BlendModeForName(com_token);
|
||||
}
|
||||
|
||||
if (stage.type != STAGE_SIMPLE) {
|
||||
Con_Printf("Warning: Blendfunc with nonsimpel stage type will be ignored.\n");
|
||||
}
|
||||
|
||||
} else if (!strcmp(command, "alphafunc")) {
|
||||
|
||||
GET_SAFE_TOKEN;
|
||||
if (!strcmp(com_token,"GE128")) {
|
||||
Con_Printf("alpha test\n");
|
||||
stage.alphatresh = 128;
|
||||
}
|
||||
|
||||
|
@ -344,9 +419,15 @@ char *ParseStage (char *data, shader_t *shader)
|
|||
* Automatically generate a bump stage with the bumpmap keyword
|
||||
*/
|
||||
void normalStage(shader_t *shader, char *name) {
|
||||
clearStage(&shader->bumpStage);
|
||||
shader->bumpStage.type = STAGE_BUMP;
|
||||
//shader->bumpstage->texture = GL_CacheTexture(com_token);
|
||||
stage_t *stage;
|
||||
if (shader->numbumpstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return;
|
||||
stage = &shader->bumpstages[shader->numbumpstages];
|
||||
shader->numbumpstages++;
|
||||
|
||||
clearStage(stage);
|
||||
stage->type = STAGE_BUMP;
|
||||
strncpy(stage->filename,name,MAX_QPATH);
|
||||
shader->flags = shader->flags | SURF_BUMP;
|
||||
}
|
||||
|
||||
|
@ -354,20 +435,67 @@ void normalStage(shader_t *shader, char *name) {
|
|||
* Automatically generate a specular stage with the specularmap keyword
|
||||
*/
|
||||
void specularStage(shader_t *shader, char *name) {
|
||||
clearStage(&shader->glossStage);
|
||||
shader->glossStage.type = STAGE_GLOSS;
|
||||
//shader->glossStage->texture = GL_CacheTexture(com_token);
|
||||
shader->flags = shader->flags | SURF_GLOSS;
|
||||
stage_t *stage;
|
||||
if (shader->numglossstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return;
|
||||
stage = &shader->glossstages[shader->numglossstages];
|
||||
shader->numglossstages++;
|
||||
|
||||
clearStage(stage);
|
||||
stage->type = STAGE_GLOSS;
|
||||
strncpy(stage->filename,name,MAX_QPATH);
|
||||
shader->flags = shader->flags | SURF_GLOSS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically generate a specular stage with the normalspecular keyword
|
||||
* This is a shader with a grayscale gloss map .
|
||||
*/
|
||||
void normalSpecularStage(shader_t *shader, char *name, char *name2) {
|
||||
stage_t *stage, *stage2;
|
||||
char buff[MAX_QPATH*2+1];
|
||||
|
||||
if (shader->numglossstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return;
|
||||
|
||||
if (shader->numbumpstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return;
|
||||
|
||||
stage = &shader->bumpstages[shader->numbumpstages];
|
||||
shader->numbumpstages++;
|
||||
|
||||
clearStage(stage);
|
||||
stage->type = STAGE_BUMP;
|
||||
strncpy(stage->filename,name,MAX_QPATH);
|
||||
shader->flags = shader->flags | SURF_BUMP;
|
||||
|
||||
stage2 = &shader->glossstages[shader->numglossstages];
|
||||
shader->numglossstages++;
|
||||
|
||||
clearStage(stage2);
|
||||
stage2->type = STAGE_GRAYGLOSS;
|
||||
strncpy(stage2->filename,name2,MAX_QPATH);
|
||||
shader->flags = shader->flags | SURF_GLOSS;
|
||||
|
||||
sprintf(buff,"%s|%s",stage->filename, stage2->filename);
|
||||
strcpy(stage->filename, buff);
|
||||
strcpy(stage2->filename, buff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically generate a bump stage with the colormap keyword
|
||||
*/
|
||||
void diffuseStage(shader_t *shader, char *name) {
|
||||
clearStage(&shader->colorStage);
|
||||
shader->colorStage.type = STAGE_COLOR;
|
||||
//shader->colorStage->texture = GL_CacheTexture(com_token);
|
||||
shader->flags = shader->flags | SURF_PPLIGHT;
|
||||
stage_t *stage;
|
||||
if (shader->numcolorstages >= SHADER_MAX_BUMP_STAGES)
|
||||
return;
|
||||
stage = &shader->colorstages[shader->numcolorstages];
|
||||
shader->numcolorstages++;
|
||||
|
||||
clearStage(stage);
|
||||
stage->type = STAGE_COLOR;
|
||||
strncpy(stage->filename,name,MAX_QPATH);
|
||||
shader->flags = shader->flags | SURF_PPLIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -402,8 +530,21 @@ char *ParseShader (char *data, shader_t *shader)
|
|||
} else if (!strcmp(command,"specularmap")) {
|
||||
GET_SAFE_TOKEN;
|
||||
specularStage(shader,com_token);
|
||||
} else if (!strcmp(command,"normalspecular")) {
|
||||
GET_SAFE_TOKEN;
|
||||
strcpy(command,com_token);
|
||||
GET_SAFE_TOKEN;
|
||||
normalSpecularStage(shader,command, com_token);
|
||||
} else if (!strcmp(command,"surfaceparm")) {
|
||||
data = COM_SkipLine(data);
|
||||
} else if (!strcmp(command,"nomipmaps")) {
|
||||
shader->mipmap = false;
|
||||
} else if (!strcmp(command,"cull")) {
|
||||
GET_SAFE_TOKEN;
|
||||
if (!strcmp(com_token,"disable")) {
|
||||
shader->cull = false;
|
||||
} else
|
||||
shader->cull = true;
|
||||
} else {
|
||||
|
||||
//ignore q3map and radiant commands
|
||||
|
@ -418,25 +559,43 @@ char *ParseShader (char *data, shader_t *shader)
|
|||
|
||||
void LoadShadersFromString (char *data)
|
||||
{
|
||||
shader_t shader;
|
||||
shader_t shader, *s;
|
||||
// parse shaders
|
||||
memset(&shader,0,sizeof(shader));
|
||||
while (1)
|
||||
{
|
||||
data = COM_Parse (data);
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
strncpy(shader.name,com_token,sizeof(shader.name));
|
||||
//check if shader already exists
|
||||
s = shaderList;
|
||||
while(s) {
|
||||
if (!strcmp(com_token,s->name)) {
|
||||
Con_Printf("Error: Shader redefined %s\n",com_token);
|
||||
return;
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
//make a new one
|
||||
s = malloc(sizeof(shader_t));
|
||||
if (!s) Sys_Error("Not enough mem");
|
||||
memset(s,0,sizeof(shader_t));
|
||||
s->next = shaderList;
|
||||
shaderList = s;
|
||||
strncpy(s->name,com_token,sizeof(s->name));
|
||||
s->mipmap = true;
|
||||
s->cull = true;
|
||||
|
||||
//parse it from the file
|
||||
data = COM_Parse (data);
|
||||
if (!data)
|
||||
break;
|
||||
if (com_token[0] != '{')
|
||||
Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
|
||||
|
||||
//Con_Printf("Parsing shader %s\n",shader.name);
|
||||
data = ParseShader (data, &shader);
|
||||
Con_Printf("Parsing %s...\n",s->name);
|
||||
data = ParseShader (data, s);
|
||||
}
|
||||
|
||||
if ((!fog_start.value) && (!fog_end.value)) {
|
||||
|
|
Loading…
Reference in a new issue