Skip to content

Commit

Permalink
Add possibility to give each model its own shader through a new optio…
Browse files Browse the repository at this point in the history
…nal SHADERS directive in the PIE file.
  • Loading branch information
perim committed Sep 2, 2013
1 parent daff1e6 commit 465894d
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 21 deletions.
2 changes: 2 additions & 0 deletions lib/ivis_opengl/imd.cpp
Expand Up @@ -39,6 +39,7 @@ iIMDShape::iIMDShape()
normalpage = iV_TEX_INVALID;
specularpage = iV_TEX_INVALID;
numFrames = 0;
shaderProgram = 0;
}

//*************************************************************************
Expand Down Expand Up @@ -81,6 +82,7 @@ void iV_IMDRelease(iIMDShape *s)
s->shadowEdgeList = NULL;
}
glDeleteBuffers(VBO_COUNT, s->buffers);
// shader deleted later, if any
d = s->next;
delete s;
iV_IMDRelease(d);
Expand Down
31 changes: 29 additions & 2 deletions lib/ivis_opengl/imdload.cpp
Expand Up @@ -29,6 +29,7 @@
#include "lib/framework/frameresource.h"
#include "lib/framework/fixedpoint.h"
#include "lib/ivis_opengl/piematrix.h"
#include "lib/ivis_opengl/piestate.h"

#include "ivisdef.h" // for imd structures
#include "imd.h" // for imd structures
Expand Down Expand Up @@ -670,6 +671,7 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
int32_t imd_version;
uint32_t imd_flags;
bool bTextured = false;
GLuint shader = 0;

memset(normalfile, 0, sizeof(normalfile));
memset(specfile, 0, sizeof(specfile));
Expand Down Expand Up @@ -804,8 +806,7 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
char ch, texType[PATH_MAX];
int i;

/* the first parameter for textures is always ignored; which is why we ignore
* nlevels read in above */
/* the first parameter for textures is always ignored; which is why we ignore nlevels read in above */
ch = *pFileData++;

// Run up to the dot or till the buffer is filled. Leave room for the extension.
Expand Down Expand Up @@ -838,6 +839,30 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
pFileData += cnt;
}

if (strncmp(buffer, "SHADERS", 7) == 0)
{
char vertex[PATH_MAX], fragment[PATH_MAX];

/* the first parameter for "textures" is always ignored; which is why we ignore nlevels read in above */
pFileData++;

if (sscanf(pFileData, "%255s %255s%n", vertex, fragment, &cnt) != 2)
{
debug(LOG_ERROR, "%s shader corrupt: %s", pFileName, buffer);
return NULL;
}
pFileData += cnt;
shader = pie_LoadShader("", vertex, fragment);

/* Try -yet again- to read in LEVELS directive */
if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2)
{
debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer);
return NULL;
}
pFileData += cnt;
}

if (strncmp(buffer, "LEVELS", 6) != 0)
{
debug(LOG_ERROR, "iV_ProcessIMD: expecting 'LEVELS' directive (%s)", buffer);
Expand Down Expand Up @@ -865,6 +890,8 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
return NULL;
}

shape->shaderProgram = shader;

// load texture page if specified
if (bTextured)
{
Expand Down
1 change: 1 addition & 0 deletions lib/ivis_opengl/ivisdef.h
Expand Up @@ -120,6 +120,7 @@ struct iIMDShape

// The new rendering data
GLuint buffers[VBO_COUNT];
GLuint shaderProgram; // if using specialized shader for this model

iIMDShape *next; // next pie in multilevel pies (NULL for non multilevel !)
};
Expand Down
9 changes: 8 additions & 1 deletion lib/ivis_opengl/piedraw.cpp
Expand Up @@ -217,7 +217,14 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, PIELI

if (light)
{
pie_ActivateShader(SHADER_COMPONENT, shape, teamcolour, colour);
if (shape->shaderProgram)
{
pie_ActivateShader(shape->shaderProgram, shape, teamcolour, colour);
}
else
{
pie_ActivateShader(SHADER_COMPONENT, shape, teamcolour, colour);
}
}
else
{
Expand Down
46 changes: 29 additions & 17 deletions lib/ivis_opengl/piestate.cpp
Expand Up @@ -214,16 +214,28 @@ static void getLocs(SHADER_PROGRAM *program)
glUniform1i(locTex3, 3);
}

void pie_FreeShaders()
{
while (shaderProgram.size() > SHADER_MAX)
{
SHADER_PROGRAM program = shaderProgram.takeLast();
glDeleteShader(program.program);
}
}

// Read/compile/link shaders
bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char *vertexPath, const char *fragmentPath)
GLuint pie_LoadShader(const char *definitions, const char *vertexPath, const char *fragmentPath)
{
SHADER_PROGRAM program;
GLint status;
bool success = true; // Assume overall success
char *buffer[2];

program->program = glCreateProgram();
memset(&program, 0, sizeof(program));

program.program = glCreateProgram();
ASSERT_OR_RETURN(false, definitions != NULL, "Null in preprocessor definitions!");
ASSERT_OR_RETURN(false, program->program, "Could not create shader program!");
ASSERT_OR_RETURN(false, program.program, "Could not create shader program!");

*buffer = (char *)definitions;

Expand All @@ -248,7 +260,7 @@ bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char
else
{
printShaderInfoLog(LOG_3D, shader);
glAttachShader(program->program, shader);
glAttachShader(program.program, shader);
success = true;
}

Expand Down Expand Up @@ -277,7 +289,7 @@ bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char
else
{
printShaderInfoLog(LOG_3D, shader);
glAttachShader(program->program, shader);
glAttachShader(program.program, shader);
success = true;
}

Expand All @@ -287,49 +299,49 @@ bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char

if (success)
{
glLinkProgram(program->program);
glLinkProgram(program.program);

// Check for linkage errors
glGetProgramiv(program->program, GL_LINK_STATUS, &status);
glGetProgramiv(program.program, GL_LINK_STATUS, &status);
if (!status)
{
debug(LOG_ERROR, "Shader program linkage has failed [%s, %s]", vertexPath, fragmentPath);
printProgramInfoLog(LOG_ERROR, program->program);
printProgramInfoLog(LOG_ERROR, program.program);
success = false;
}
else
{
printProgramInfoLog(LOG_3D, program->program);
printProgramInfoLog(LOG_3D, program.program);
}
}

getLocs(program);
getLocs(&program);
glUseProgram(0);

return success;
shaderProgram.append(program);

return shaderProgram.size() - 1;
}

// Run from screen.c on init. Do not change the order of loading here! First ones are enumerated.
bool pie_LoadShaders()
{
bool result;
SHADER_PROGRAM program;
int result;

// Load some basic shaders
memset(&program, 0, sizeof(program));
shaderProgram.append(program);

// TCMask shader for map-placed models with advanced lighting
debug(LOG_3D, "Loading shader: SHADER_COMPONENT");
result = pie_LoadShader(&program, "", "shaders/tcmask.vert", "shaders/tcmask.frag");
result = pie_LoadShader("", "shaders/tcmask.vert", "shaders/tcmask.frag");
ASSERT_OR_RETURN(false, result, "Failed to load component shader");
shaderProgram.append(program);

// TCMask shader for buttons with flat lighting
debug(LOG_3D, "Loading shader: SHADER_BUTTON");
result = pie_LoadShader(&program, "", "shaders/button.vert", "shaders/button.frag");
result = pie_LoadShader("", "shaders/button.vert", "shaders/button.frag");
ASSERT_OR_RETURN(false, result, "Failed to load button shader");
shaderProgram.append(program);

currentShaderMode = SHADER_NONE;
return true;
Expand Down Expand Up @@ -377,7 +389,7 @@ void pie_ActivateShader(int shaderMode, iIMDShape* shape, PIELIGHT teamcolour, P
glUniform1i(program.locFog, rendStates.fog);
glUniform1f(program.locTime, timeState);

currentShaderMode = shaderMode;
currentShaderMode = shaderMode;
}

glColor4ubv(colour.vector);
Expand Down
3 changes: 2 additions & 1 deletion lib/ivis_opengl/piestate.h
Expand Up @@ -85,7 +85,8 @@ extern void pie_SetAlphaTest(bool keyingOn);
extern void pie_SetRendMode(REND_MODE rendMode);

bool pie_LoadShaders();
bool pie_LoadShader(SHADER_PROGRAM *program, const char *definitions, const char *vertexPath, const char *fragmentPath);
void pie_FreeShaders();
GLuint pie_LoadShader(const char *definitions, const char *vertexPath, const char *fragmentPath);

// Actual shaders (we do not want to export these calls)
void pie_ActivateShader(int shaderMode, iIMDShape* shape, PIELIGHT teamcolour, PIELIGHT colour);
Expand Down
2 changes: 2 additions & 0 deletions src/init.cpp
Expand Up @@ -934,6 +934,8 @@ bool stageOneShutDown(void)
{
debug(LOG_WZ, "== stageOneShutDown ==");

pie_FreeShaders();

if ( audio_Disabled() == false )
{
sound_CheckAllUnloaded();
Expand Down

0 comments on commit 465894d

Please sign in to comment.